function BotController(game) { this.decisionDelay = 10; this.lastDecision = 0; this.shipState = "idle"; this.shootDelay = 0; this.targetedEnemy = null; this.init = function() { }; this.reset = function(ship) { this.shipState = "idle"; }; this.makeDecisions = function(ship) { this.shootDelay--; this.avoidPlanets(ship); this.avoidStars(ship); switch(this.shipState) { case "idle": ship.idle(); if(this.decisionDelay <= 0) { this.decideNextAction(ship); this.decisionDelay = 10; } this.decisionDelay--; break; case "takeoff": this.takeOff(ship); break; case "hunt": this.targetEnemy(ship); break; case "captureplanet": this.capturePlanet(ship); break; case "heal": this.heal(ship); break; case "combat": this.targetEnemy(ship); break; } }; this.decideNextAction = function(ship) { this.lastDecision = parseInt(4 * Math.random()); if(ship.touching != null) { this.lastDecision = 3; } if(ship.health < parseInt(ship.maxHealth / 2)) { this.lastDecision = 4; } switch(this.lastDecision) { case 0: this.shipState = "idle"; break; case 1: this.shipState = "captureplanet"; break; case 2: this.shipState = "hunt"; break; case 3: this.shipState = "takeoff"; break; case 4: this.shipState = "heal"; break; case 5: this.shipState = "fight"; break; } } this.takeOff = function(ship) { var nearestSystem = game.getNearestSystem(game, ship); var nearestPlanet = game.getNearestPlanet(nearestSystem, ship); var nearestPlanetDistance = game.calculateDistanceTo(ship, nearestPlanet); if(nearestPlanetDistance > 300) { this.shipState = "idle"; return; } var oppositeFromPlanetAngle = system.game.calculateAngleTo(nearestPlanet, ship) + Math.PI; ship.targetAngle = oppositeFromPlanetAngle; ship.accelerate(); }; this.avoidStars = function(ship) { //if star is directly in front //calculate time to slow down //if } this.avoidPlanets = function(ship) { //if star is directly in front //calculate time to slow down //if } this.targetEnemy = function(ship) { this.targetedEnemy = null; if(ship.touching != null) { this.shipState = "idle"; return; } var nearestShip = game.getNearestShip(game, ship); if(nearestShip == null || nearestShip.isDead) { this.shipState = "idle"; this.decisionDelay = 0; return; } this.targetedEnemy = nearestShip; var nearestShipDistance = game.calculateDistanceTo(ship, nearestShip); if(nearestShipDistance > 500) { var nearestShipAngle = game.calculateAngleTo(ship, nearestShip); ship.targetAngle = nearestShipAngle + Math.PI; ship.accelerate(); }/* else if(nearestShipDistance > 250 && !this.matchesVelocity(ship, nearestShip)) { this.adjustVelocity(ship, nearestShip, nearestShipAngle); }*/ else if(nearestShipDistance < 250) { var nearestShipAngle = game.calculateAngleTo(ship, nearestShip); var predictedAngle = Math.atan2(ship.position.y - (nearestShip.position.y + nearestShip.velocity.y * 20) , ship.position.x - (nearestShip.position.x + nearestShip.velocity.x * 20)); ship.targetAngle = predictedAngle + Math.PI; if(this.shootDelay <= 0) { ship.shoot(); this.shootDelay = parseInt(20 * Math.random()); } } //get nearest enemy ship //if within x distance, chase //if velocity > enemy velocity, slow down //if within x distance, shoot } this.matchesVelocity = function(ship, other) { return false; } this.adjustVelocity = function(ship, other, angle) { ship.idle(); var otherVector = {x: other.velocity.x, y: other.velocity.y}; var shipVector = {x: ship.velocity.x, y: ship.velocity.y}; var shipMagnitude = Math.abs(Math.sqrt(Math.pow(ship.velocity.x, 2) + Math.pow(ship.velocity.y, 2))); var otherMagnitude = Math.abs(Math.sqrt(Math.pow(other.velocity.x, 2) + Math.pow(other.velocity.y, 2))); var dotProduct = shipVector.x * otherVector.x + shipVector.y + otherVector.y; var newangle = Math.acos(dotProduct / (shipMagnitude * otherMagnitude)); ship.targetAngle = newangle; ship.accelerate(); //get heading of other ship //get heading of current ship //find vector difference in velocities //change angle of current ship to apply thrust in appropriate direction //ship accelerate } this.capturePlanet = function(ship) { this.shipState = "idle"; //get nearest unclaimed planet //travel to //if within x distance, go towards //if within x distance, slow down //interact with //if within x distance, land } this.heal = function(ship) { if(ship.health == ship.maxHealth) { this.shipState = "takeoff"; } //if health is low //get nearest claimed planet //travel to //if within x distance, go towards //if within x distance, slow down //interact with //if within x distance, land //if health is max, launch } this.getColor = function() { var random = parseInt(4* Math.random()); switch(random) { case 0: return "#DDDD33"; case 1: return "#DD33DD"; case 2: return "#33DD33"; case 3: return "#3333DD"; } }; this.debugDraw = function(ship, context) { return false; //combat markers if(this.shipState == "hunt" && this.targetedEnemy != null) { context.lineWidth = 1; context.strokeStyle = "crimson"; context.beginPath(); context.moveTo(ship.position.x,ship.position.y); context.lineTo(this.targetedEnemy.position.x, this.targetedEnemy.position.y); context.stroke(); context.beginPath(); context.arc(this.targetedEnemy.position.x, this.targetedEnemy.position.y, 20, 0, 2 * Math.PI); context.stroke(); } context.save(); context.translate(ship.position.x, ship.position.y); context.lineWidth = 1; context.strokeStyle = "limegreen"; context.beginPath(); context.moveTo(0,0); context.lineTo(400 * ship.acceleration.x, 400 * ship.acceleration.y); context.stroke(); context.strokeStyle = "cornflowerblue"; var last = {x:0, y: 0}; for(var i = 0; i < 400; i++) { context.beginPath(); context.moveTo(last.x + ship.width, last.y + ship.height); last.x += (i * ship.acceleration.x + ship.velocity.x); last.y += (i * ship.acceleration.y + ship.velocity.y); context.lineTo(last.x + ship.width, last.y + ship.height); context.stroke(); } var last = {x:0, y: 0}; for(var i = 0; i < 400; i++) { context.beginPath(); context.moveTo(last.x - ship.width, last.y - ship.height); last.x += (i * ship.acceleration.x + ship.velocity.x); last.y += (i * ship.acceleration.y + ship.velocity.y); context.lineTo(last.x - ship.width, last.y - ship.height); context.stroke(); } context.restore(); }; };