Skip to content

Instantly share code, notes, and snippets.

@xphere
Created December 21, 2012 17:57
Show Gist options
  • Select an option

  • Save xphere/4354508 to your computer and use it in GitHub Desktop.

Select an option

Save xphere/4354508 to your computer and use it in GitHub Desktop.
js[CODE].is('Fun');
// SimpleRand as part of C implementation
// Usage:
// s = new SimpleRand(seed);
// v = s.rand(5, 10);
function SimpleRand(randState) {
var u;
function next() {
if (randState === u) {
randState = 54819;
}
randState = ((randState * 214013) + 2531011) & 0xFFFFFFFF;
return (randState >> 16) & 0x7FFF;
}
this.seed = function(seed) {
randState = seed;
};
this.rand = function(min, max) {
var n = next();
if (max === u) {
if (min === u) {
return n;
}
max = min;
min = 0;
}
return min + (n * (max - min) / 32768);
};
}
// Extending Vector2 class
// All "position" elements are of this type and will inherit this methods
// Angle between two vectors in (-180..180)
// Usage: angle = robot.position.angle(scannedRobot.position);
Vector2.prototype.angle = function(v) {
return (270 + RAD2DEG * Math.atan2(v.y - this.y, v.x - this.x)) % 360 - 180;
};
// Convert current vector into destination as percent becomes 1.0
// Usage: position = robot.position.interpolate(destination, percent);
Vector2.prototype.interpolate = function(v, percent) {
return new Vector2(this.x + (this.x - v.x) * percent, this.y + (this.y - v.y) * percent);
};
// Calculates distance between two vectors
// Usage: value = robot.position.distance(scannedRobot.position);
Vector2.prototype.distance = function(v) {
return Math.sqrt((this.x - v.x) * (this.x - v.x) + (this.y - v.y) * (this.y - v.y));
};
// Other existing methods already in Vector2 objects are:
// - module(): Returns distance to position (0, 0)
// - dot(v): Returns the dot product between this and v
// - projectTo(v): Returns the projection vector of this one into v
// - rotate(angle, origin): Rotates vector "angle" degrees around "origin"
// Global methods of Vector2 class
// Vector2.add, Vector2.subtract, Vector2.multiply, Vector2.divide
// Usage: vr = Vector2.add(v1, v2);
// Angles are a bit tricky in FightCode
// When robot.angle is 0, it's looking north (up)
// As it says, robot.cannonRelativeAngle is relative to the current robot.angle and starts at 90 degrees
// When it's 0, it points to the *left side* of the robot, 90 points ahead, 180 right and 270, back
// Same happens with robot.cannonAbsoluteAngle, 0 degrees when pointing left, and so on...
// Also, all angles are in 0..360 range, which seems to me pretty useless compared to -180..180
// Hence the necessity of this two functions
// Use this with cannon angles to get normalized -180..180 angle with 0 pointing north
// Usage: angle = getCannonAngle(robot.cannonRelativeAngle);
function getCannonAngle(angle) {
return (angle + 90) % 360 - 180;
}
// Use this with robot angles or others in 0..360 range to get a -180..180 value
// Usage: angle = getAngle(robot.angle);
// Ex: angle = getAngle(getCannonAngle(robot.cannonAbsoluteAngle) - robot.angle);
function getAngle(angle) {
return (angle + 540) % 360 - 180;
}
// Inconsistencies exist also with ahead and back methods in robot
// This is a easy tool for simplify movement
function move(robot, amount) {
amount && robot[amount > 0 ? 'ahead' : 'back'](amount);
}
// How to detect enemies?
function isEnemy(robot, other) {
return robot.parentId !== other.id && other.parentId !== robot.id;
}
// Allows control over multiple robot instances
// Usage: See Robot below
function MultipleRobot() {
this._instances = {};
}
MultipleRobot.prototype = {
getInstances: function() {
return this._instances;
},
getInstance: function(robot) {
if (!this._instances[robot.id]) {
this._instances[robot.id] = this.createInstance(robot);
}
return this._instances[robot.id];
},
createInstance: function(/*robot*/) {
return {};
}
};
// MultipleRobot usage
Robot.prototype = Object.create(MultipleRobot.prototype);
function Robot(r) {
MultipleRobot.call(this);
this.global = {};
}
// Example
Robot.prototype.createInstance = function(robot) {
if (robot.availableClones) {
robot.clone();
}
return {
direction: robot.parentId ? -1 : 1,
speed: robot.parentId ? 2 : 1,
turnSpeed: robot.parentId ? -1 : 1,
isEnemy: isEnemy.bind(null, robot),
global: this.global
};
};
Robot.prototype.onScannedRobot = function(e) {
var r = e.robot, i = this.getInstance(r), o = e.scannedRobot;
if (i.isEnemy(o)) {
i.global.enemy = o;
r.fire();
}
};
Robot.prototype.onIdle = function(e) {
var r = e.robot, i = this.getInstance(r), o = i.global.enemy;
if (!o) {
r.turn(i.turnSpeed);
move(r, i.speed * i.direction);
} else {
var angle = getAngle(r.position.angle(o.position) - e.robot.angle);
if (Math.abs(angle) > 1) {
r.turn(angle);
}
}
};
Robot.prototype.onWallCollision =
Robot.prototype.onRobotCollision = function(e) {
var r = e.robot, i = this.getInstance(r), o = e.collidedRobot;
r.ignore('onWallCollision');
r.ignore('onRobotCollision');
i.direction = -i.direction;
move(r, 20 * i.direction);
if (o && i.isEnemy(o)) {
i.global.enemy = o;
r.turn(e.bearing);
}
r.listen('onRobotCollision');
r.listen('onWallCollision');
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment