Skip to content

Instantly share code, notes, and snippets.

@diginc
Last active August 29, 2015 14:01
Show Gist options
  • Save diginc/ad29b017b2246d3d30c7 to your computer and use it in GitHub Desktop.
Save diginc/ad29b017b2246d3d30c7 to your computer and use it in GitHub Desktop.
[SAI] Nav System
// Custom functions list:
// Also see var Robot for variables that tie into some of these custom functions:
/*
Robot.prototype.gridSetup = function(ev) // Ran once
Robot.prototype.updateCurrentCoords = function(ev) // Ran every idle
Robot.prototype.navigation = function(ev) {
Robot.prototype.navigateCorner = function(ev) {
Robot.prototype.navigateWall = function(ev) {
Robot.prototype.navigateOpenArea = function(ev) {
Robot.prototype.postScanned = function(ev) {
Robot.prototype.postHit = function(ev) {
Robot.prototype.postBotCollision = function(ev) {
Robot.prototype.postWallCollision = function(ev) {
// Helpers
Robot.prototype.isInCorner = function( x, y ) {
Robot.prototype.isAlongWall = function( x, y ) {
Robot.prototype.getWallName = function( x, y ) {
Robot.prototype.getClosestRightAngle = function( bearing ) {
Robot.prototype.idleLogging = function(ev) {
*/
var Robot = function(robot) {
this.runOnce = false;
this.x = 0;
this.y = 0;
// slow down there idleLogging()
this.logCounter = 0;
this.logIdleEveryXLoops = 6;
this.logNavigation = false;
this.moveDirection = 1;
this.cannonDirection = -1;
// Core function flags to trigger behavior change until you say to stop
// rather than when the listen event function is done running
this.hit = 0;
this.scannedEnemy = 0;
this.botCollision = 0;
this.wallCollision = 0;
// function variables
this.wallName = null;
};
Robot.prototype.gridSetup = function(ev) {
var r = ev.robot;
r.log("Setting up the grid...");
this.yGridSize = r.arenaHeight/this.yGridSections;
this.y_grid = new Array();
for (var y=0 ; y <= this.yGridSections; y++) {
this.y_grid[y] = this.yGridSize * (y+1);
r.log("Y" + y +": "+ this.y_grid[y]);
}
this.xGridSize = r.arenaWidth/this.xGridSections;
this.x_grid = new Array();
for (var x=0 ; x <= this.xGridSections; x++) {
this.x_grid[x] = this.xGridSize * (x+1);
r.log("X" + x +": "+ this.x_grid[x]);
}
this.avgSectionSize = (this.xGridSize + this.yGridSize) / 2;
};
Robot.prototype.updateCurrentCoords = function(ev) {
var r = ev.robot;
for ( var x = 0; x < this.x_grid.length ; x++) {
if (r.position.x <= this.x_grid[x]) {
this.x = x;
break;
}
}
for ( var y = 0; y < this.y_grid.length ; y++) {
if (r.position.y <= this.y_grid[y]) {
this.y = y;
break;
}
}
};
Robot.prototype.onIdle = function(ev) {
var r = ev.robot;
if (this.runOnce == false) {
this.xGridSections = 8;
this.yGridSections = Math.round( (this.xGridSections * r.arenaHeight) / r.arenaWidth) ;
this.gridSetup(ev);
r.log("Start Position")
r.rotateCannon(-90);
this.runOnce = true;
}
// Keep the cannon pointed inward by reversing direction once parallel to wall
// does not always work, sometimes turrent gets stuck reversing direction repeatedly
if(r.cannonRelativeAngle < 270) {
this.reverseCannon();
//r.rotateCannon( (270 - r.cannonRelativeAngle) * this.cannonDirection );
}
if( r.cannonRelativeAngle > 90) {
this.reverseCannon();
//r.rotateCannon( (r.cannonRelativeAngle - 90) * this.cannonDirection );
}
//r.ignore(Robot.prototype.onScannedRobot);
this.idleLogging(ev);
this.updateCurrentCoords(ev);
if (this.hit == 1) { this.postHit(ev); }
else
if (this.scannedEnemy == 1) { this.postScanned(ev); }
else
if (this.botCollision == 1) { this.postBotCollision(ev); }
else
if (this.wallCollision == 1) { this.postWallCollision(ev); }
else {
this.navigation(ev);
}
};
Robot.prototype.navigation = function(ev) {
var r = ev.robot;
var logNavigation = this.logNavigation;
this.wallName = this.getWallName(this.x, this.y);
//uncomment to slow bot down!
//r.rotateCannon(15); r.rotateCannon(-15);
if( this.isInCorner(this.x, this.y) ) {
if(logNavigation != false) { r.log("navigateCorner!"); }
this.navigateCorner(ev);
}
else if ( this.isAlongWall(this.x, this.y) ) {
if(logNavigation != false) { r.log("navigateWall!"); }
this.navigateWall(ev);
}
else {
if(logNavigation != false) { r.log("navigateOpenArea!"); }
this.navigateOpenArea(ev);
}
};
// Core Nav functions
Robot.prototype.navigateCorner = function(ev) {
var r = ev.robot;
for( var i=1; i <= 10 ; i++) {
r.turn(9 * (-1 * this.moveDirection));
r.move(this.avgSectionSize/16, this.moveDirection);
}
r.move(50, this.moveDirection);
};
Robot.prototype.navigateWall = function(ev) {
var r = ev.robot;
this.turnParallelToWall(ev);
r.move(this.avgSectionSize/5, this.moveDirection);
r.rotateCannon(10 * this.cannonDirection);
};
Robot.prototype.navigateOpenArea = function(ev) {
var r = ev.robot;
r.move(3, this.direction);
r.turn(-1 * this.moveDirection);
r.rotateCannon(1 * this.cannonDirection);
};
Robot.prototype.turnParallelToWall = function(ev) {
var r = ev.robot;
var parallelAngle;
var parallelAngleCorrection;
switch ( this.getWallName( this.x, this.y ) ) {
case "S": parallelAngle = 90; break;
case "E": parallelAngle = 0; break;
case "N": parallelAngle = 270; break;
case "W": parallelAngle = 180; break;
}
if ( ! this.isRightAngle(r.angle) ) {
r.log("Correcting to a parallelAngle angle "+parallelAngle+" from "+ r.angle);
if (r.angle > parallelAngle) {
parallelAngleCorrection = r.angle - parallelAngle;
r.log("Correction = "+ r.angle +" - "+ parallelAngle + " = " + parallelAngleCorrection)
} else {
parallelAngleCorrection = parallelAngle - r.angle;
r.log("Correction = "+ r.angle +" - "+ parallelAngle + " = " + parallelAngleCorrection)
}
//r.turn( parallelAngleCorrection );
this.absoluteTurn( ev, parallelAngleCorrection )
}
};
// Default available events + post event custom functions
Robot.prototype.onScannedRobot = function(ev) {
var r = ev.robot;
var scanned = ev.scannedRobot;
this.enemyAngle = ev.cannonRelativeAngle;
if(scanned.id !== r.parentId && scanned.parentId !== r.id) {
this.scannedEnemy = 1;
//r.fire();
}
};
Robot.prototype.postScanned = function(ev) {
var r = ev.robot;
this.cannonDirectionReversed = (this.cannonDirection * -1);
r.rotateCannon(7 * this.cannonDirectionReversed);
this.scannedEnemy = 0;
this.reverseCannon();
};
Robot.prototype.onHitByBullet = function(ev) {
var r = ev.robot;
this.hit++;
r.log("Hit: " + this.hit);
};
Robot.prototype.postHit = function(ev) {
var r = ev.robot;
this.hit = 0;
};
Robot.prototype.onRobotCollision = function(ev) {
var r = ev.robot;
this.botCollision++;
r.disappear();
//r.back(2);
//r.turn(9 * this.moveDirection);
this.moveDirection = this.moveDirection * -1;
};
Robot.prototype.postBotCollision = function(ev) {
var r = ev.robot;
this.botCollision = 0;
};
Robot.prototype.onWallCollision = function(ev) {
var r = ev.robot;
this.wallCollision++;
// Calculate the exact amount to turn parallel to the wall
r.back(2);
r.turn(-9 * this.moveDirection);
};
Robot.prototype.postWallCollision = function(ev) {
var r = ev.robot;
this.wallCollision = 0;
};
// Other helper functions
Robot.prototype.isInCorner = function( x, y ) {
if ( x == 0 && y == 0
|| x == 0 && y == (this.yGridSections - 1)
|| x == (this.xGridSections - 1) && y == 0
|| x == (this.xGridSections - 1) && y == (this.yGridSections - 1)
) {
return true;
}
return false;
};
Robot.prototype.isAlongWall = function( x, y ) {
if ( x == 0
|| y == 0
|| x == (this.xGridSections - 1)
|| y == (this.yGridSections - 1)
) {
return true;
}
return false;
};
Robot.prototype.getWallName = function( x, y ) {
if ( x == 0 && y == 0 )
{ return "NW"; }
if ( x == 0 && y == (this.yGridSections - 1) )
{ return "SW"; }
if ( x == (this.xGridSections - 1) && y == 0 )
{ return "NE"; }
if ( x == (this.xGridSections - 1) && y == (this.yGridSections - 1) )
{ return "SE"; }
if ( x == 0 )
{ return "W"; }
if ( y == 0 )
{ return "N"; }
if ( x == (this.xGridSections - 1) )
{ return "E"; }
if ( y == (this.yGridSections - 1) )
{ return "S"; }
return "Mid";
};
Robot.prototype.getClosestRightAngle = function( angle ) {
// Front of tank = 0
if (angle < 45 || angle > 315) { return 0; }
if (angle > 45 && angle < 135) { return 90; }
if (angle > 135 && angle < 225) { return 180; }
if (angle > 225 && angle < 315) { return 270; }
return 0;
};
Robot.prototype.isRightAngle = function( angle ) {
// Front of tank = 0
switch (angle) {
case 0: return true;
case 90: return true;
case 180: return true;
case 270: return true;
}
return false;
};
Robot.prototype.radian = function( angle ) {
if (angle < 0) {
return Math.absolute(angle)
}
if (angle > 360) {
var multiplier = angle % 360
return angle - 360 * multiplier;
}
};
Robot.prototype.absoluteTurn = function( ev, angle ) {
var r = ev.robot;
var angleDiff = (r.bearing > angle ? r.bearing - angle : angle - r.bearing);
var turnDegrees = 0;
if (r.bearing > angle) {
if(angleDiff > 180) {
r.log('aTurn case1');
turnDegrees = -1 * (angle - 180);
} else {
r.log('aTurn case2');
turnDegrees = angle;
}
} else {
if(angleDiff > 180) {
r.log('aTurn case3');
turnDegrees = (angle - 180);
} else {
r.log('aTurn case4');
turnDegrees = -1 * angle; // works for S but not N?
}
}
r.log("turnDegrees: "+turnDegrees);
r.turn(turnDegrees);
// Examples of bad turns go below
/*
NORTH WALL:
ROBOT player: Correction = 40 - 270 = 23
ROBOT player: aTurn case4
ROBOT player: turnDegrees: -230
*/
};
Robot.prototype.idleLogging = function(ev) {
var r = ev.robot;
this.logCounter++;
// Idle repeats/ticks very fast, slow down!
if ( this.logCounter == this.logIdleEveryXLoops ) {
r.log( "ID="+ r.id
+ " X=" + this.x + "/" + this.xGridSections
+ " Y=" + this.y + "/" + this.yGridSections
+ " ("+ this.wallName + ")"
+ " angle=" + r.angle
+ " rightAngle=" + this.getClosestRightAngle(r.angle)
+ " CannonAbs=" + r.cannonAbsoluteAngle
+ " cannonRel=" + r.cannonRelativeAngle
);
this.logCounter = 0;
}
};
Robot.prototype.reverseCannon = function() {
this.cannonDirection = this.cannonDirection * -1;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment