public override void AttackToPosition(Vector2 destination) { _destination = destination; MacroState = LogicStates.AttackingToPosition; _lastState = LogicStates.MovingToPosition; CurrentTarget = null; }
/// <summary> /// Move to destination, ignoring targets along the way. /// </summary> /// <returns></returns> protected IEnumerable MoveToPosition(Vector2 destination) { var randomness = _rand.Next(0, 10) / 10f; yield return(new TurnTowards(this, randomness, () => _destination)); while (true) { var result = AIHelper.TurnTowardPosition( Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, _destination, _lastGameTime.ElapsedMilliseconds, .2f ); Ship.Rotation = result.Rotation; if (!result.Rotated) { Ship.Thrust(ThrustTypes.Forward); Ship.Thrusting = true; } yield return(new Wait()); } // Ship is at destination, go back to whatever it was doing MacroState = _lastState == LogicStates.Roaming ? _lastState : LogicStates.HoldingPosition; Ship.Thrusting = false; }
public override void HoldPosition() { if (Ship.IsLocalSim) { MacroState = LogicStates.HoldingPosition; } }
/// <summary> /// Allows the pilot to logically choose a new target /// </summary> /// <param name="firingObject"></param> public override void HitByTargetable(ITargetable firingObject) { // Randomly selects a target for now, 1/5 probability of choosing the firingObject if (CurrentTarget == null && firingObject.IsBodyValid) { CurrentTarget = firingObject; return; } if (_rand.Next(5) == 1) { CurrentTarget = firingObject; if (MacroState == LogicStates.Roaming || MacroState == LogicStates.MovingToPosition) { MacroState = LogicStates.AttackingAll; } } }
/// <summary> /// Changes the logic state of the game /// </summary> public void SetState(LogicStates newState) { switch (newState) { case LogicStates.Playing: break; case LogicStates.GameOver: break; case LogicStates.Scores: break; default: break; //TODO: more states! } //save the new state this.currentState = newState; }
public override void Simulate(IGameTimeService gameTime) { if (!IsBodyValid) { return; } Weapon.Update(gameTime); DelayTime += gameTime.ElapsedMilliseconds; // Used for Loading. #region Logic if (logicState != LogicStates.Resting && (CurrentTarget == null || !CurrentTarget.IsBodyValid)) { CurrentTarget = null; logicState = LogicStates.SearchingForTarget; } switch (logicState) { case LogicStates.Resting: if (PotentialTargets.Count > 0) { logicState = LogicStates.SearchingForTarget; } break; case LogicStates.SearchingForTarget: FindTarget(); if (CurrentTarget != null) { logicState = LogicStates.TurningTowardTarget; } break; case LogicStates.TurningTowardTarget: if (!CurrentTarget.IsBodyValid) { PotentialTargets.Remove(CurrentTarget.Id); CurrentTarget = null; logicState = LogicStates.Resting; break; } if (gameTime.TotalMilliseconds - _lastTargetCheckTime > 200) //Retargets closest item 5 times per second //Retargeting is expensive, if turrets lag this needs to be rethought { _lastTargetCheckTime = (float)gameTime.TotalMilliseconds; CurrentTarget = null; logicState = LogicStates.Resting; break; } if (Vector2.Distance(CurrentTarget.Position, Position) > turretRange) { CurrentTarget = null; logicState = LogicStates.Resting; break; } var result = AIHelper.TurnTowardPosition(Rotation, rotationSpeed, Position, CurrentTarget.Position, gameTime.ElapsedMilliseconds, AimTolerance); Rotation = result.Rotation; if (!result.Rotated) { if (Weapon.CanFire()) { Weapon.TimeOfWaitStart = gameTime.TotalMilliseconds; Weapon.Fire_LocalOrigin(Rotation, 0, true); Weapon.WaitingForFireResponse = true; } } break; } #endregion OldTime += gameTime.ElapsedMilliseconds; // Updates Time since Last Action }
public override void Update(IGameTimeService gameTime) { if (IsLocalSim) { Simulate(gameTime); return; } if (IsDead) { return; } Weapon.Update(gameTime); DelayTime += gameTime.ElapsedMilliseconds; // Used for Loading. #region Logic //0 = No target(s) in range, laser at rest //1 = Target(s) on planet, find one //2 = Turn head to aim or Fire if within aim tolerance //3 = Fire switch (logicState) //Just FYI in case you're confused, a locally simulated turret doesn't run this code, it runs .Simulate() instead. { case LogicStates.Resting: if (PotentialTargets.Count > 0) { logicState = LogicStates.SearchingForTarget; } break; case LogicStates.SearchingForTarget: FindTarget(); if (CurrentTarget != null) { logicState = LogicStates.TurningTowardTarget; } break; case LogicStates.TurningTowardTarget: if (CurrentTarget == null) { logicState = LogicStates.Resting; break; } else if (CurrentTarget != null && !CurrentTarget.IsBodyValid) { PotentialTargets.Remove(CurrentTarget.Id); CurrentTarget = null; logicState = LogicStates.Resting; break; } else if (gameTime.TotalMilliseconds - _lastTargetCheckTime > 200) //Retargets closest item 5 times per second //Retargeting is expensive, if turrets lag this needs to be rethought { _lastTargetCheckTime = (float)gameTime.TotalMilliseconds; CurrentTarget = null; logicState = LogicStates.Resting; break; } else if (Vector2.Distance(CurrentTarget.Position, Position) > turretRange) { CurrentTarget = null; logicState = LogicStates.Resting; break; } Rotation = AIHelper.TurnTowardPosition( Rotation, rotationSpeed, Position, CurrentTarget.Position, gameTime.ElapsedMilliseconds, AimTolerance ).Rotation; break; } #endregion OldTime += gameTime.ElapsedMilliseconds; // Updates Time since Last Action }
public override void Simulate(IGameTimeService gameTime) { if (!Ship.IsBodyValid || !Ship.IsAlive) { return; } Ship.Thrusting = false; if (MacroState == LogicStates.AttackingAll) { //Find nearest target in system, attack, repeat, do nothing if no targets are available #region AttackingAll var vecToTarget = new Vector2(); if (CurrentTarget != null) { if (CurrentTarget.IsBodyValid) { vecToTarget = getVectorToPosition(CurrentTarget.Position); } else { CurrentTarget = null; MicroState = 0; } } else { MicroState = 0; } #region Logic if (Ship.CurrentHealth <= 0) { return; } switch (MicroState) { case 0: //Do nothing _findTarget(10000); //"Infinite" range if (CurrentTarget != null) { MicroState = 1; } break; case 1: //Turn to face target { var result = AIHelper.TurnTowardPosition(Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, CurrentTarget.Position, gameTime.ElapsedMilliseconds, .175f); Ship.Rotation = result.Rotation; if (!result.Rotated) { MicroState = 2; } break; } case 2: //Fly toward target { var result = AIHelper.TurnTowardPosition(Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, CurrentTarget.Position, gameTime.ElapsedMilliseconds, .1f); Ship.Rotation = result.Rotation; if (Math.Abs((Ship.Position - CurrentTarget.Position).Length()) >= 3) { Ship.Thrust(ThrustTypes.Forward); Ship.Thrusting = true; //Need a better way to do this } if (vecToTarget.Length() <= 3) { MicroState = 3; //Start strafing } break; } case 3: //Strafe target { var result = AIHelper.TurnTowardPosition(Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, CurrentTarget.Position, gameTime.ElapsedMilliseconds, .1f); Ship.Rotation = result.Rotation; if (CurrentTarget.TargetType == TargetTypes.Moving) { Ship.Thrust(ThrustTypes.Forward); Ship.Thrusting = true; } Ship.TryFireWeapon(gameTime, 1); if (vecToTarget.Length() >= 5) { MicroState = 1; //Stop strafing, turn to face player again Ship.Thrusting = false; } break; } case 4: break; } #endregion #endregion } else if (MacroState == LogicStates.HoldingPosition) { //Hold the ship's position StopShip(gameTime); } else if (MacroState == LogicStates.MovingToPosition) { //Move to _destination, ignoring targets along the way #region MovingToPosition //Tolerance is randomized so all ships don't move to the same location //Should probably move tolerance outside of this loop so that it isn't set on every iteration if ((Ship.Position - _destination).Length() < 3f && Ship.LinearVelocity.Length() > .1f) { StopShip(gameTime);//Ship is within range of the destination, start slowing down } else if ((Ship.Position - _destination).Length() < (float)_rand.Next(0, 10) / 10f && Ship.LinearVelocity.Length() <= .1) { //Ship is at destination, go back to whatever it was doing if (_lastState == LogicStates.Roaming) { MacroState = _lastState; } else { MacroState = LogicStates.HoldingPosition; } Ship.Thrusting = false; } else { var result = AIHelper.TurnTowardPosition(Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, _destination, (float)gameTime.ElapsedMilliseconds, .2f); Ship.Rotation = result.Rotation; if (!result.Rotated) { Ship.Thrust(ThrustTypes.Forward); Ship.Thrusting = true; } } #endregion } else if (MacroState == LogicStates.AttackingTarget) { //Pursue and attack target until it is killed or warps #region AttackingTarget if (CurrentTarget == null || !CurrentTarget.IsBodyValid) { CurrentTarget = null; //Set to null if target is no longer valid if (_lastState != MacroState) //To avoid getting stuck in this state { MacroState = _lastState; } else { MacroState = LogicStates.Roaming; } return; } switch (MicroState) { case 1: //Turn to face target { var result = AIHelper.TurnTowardPosition(Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, CurrentTarget.Position, gameTime.ElapsedMilliseconds, .2f); Ship.Rotation = result.Rotation; if (!result.Rotated) { MicroState = 2; } break; } case 2: //Fly toward target { var result = AIHelper.TurnTowardPosition(Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, CurrentTarget.Position, gameTime.ElapsedMilliseconds, .2f); Ship.Rotation = result.Rotation; if ((Ship.Position - CurrentTarget.Position).Length() >= 3) { Ship.Thrust(ThrustTypes.Forward); Ship.Thrusting = true; } if ((Ship.Position - CurrentTarget.Position).Length() <= 3) { MicroState = 3; //Start strafing } break; } case 3: //Strafe target { var result = AIHelper.TurnTowardPosition(Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, CurrentTarget.Position, gameTime.ElapsedMilliseconds, .2f); Ship.Rotation = result.Rotation; if (CurrentTarget.TargetType == TargetTypes.Moving) { Ship.Thrust(ThrustTypes.Forward); Ship.Thrusting = true; } Ship.TryFireWeapon(gameTime, 1); if ((Ship.Position - CurrentTarget.Position).Length() >= 5) { MicroState = 1; //Stop strafing, turn to face target again Ship.Thrusting = false; } break; } } #endregion } else if (MacroState == LogicStates.Roaming) { #region Roaming //Really hacky stupid way to temporarily generate random positions _destination = new Vector2((_rand.Next(-15, 15)), _rand.Next(-15, 15)); if (_rand.Next(0, 2) == 0)//Avoids destinations in the sun { _destination.X *= -1; } if (_rand.Next(0, 2) == 0) { _destination.Y *= -1; } //Console.WriteLine("Setting Course for " + _destination); _lastState = LogicStates.Roaming; MacroState = LogicStates.MovingToPosition; #endregion } else if (MacroState == LogicStates.AttackingToPosition) { if (CurrentTarget == null) { _findTarget(_engagementRange); } if (CurrentTarget == null)//No targets available within range { if ((Ship.Position - _destination).Length() < 2f && Ship.LinearVelocity.Length() > .01) { StopShip(gameTime);//Ship is within range of the destination, start slowing down } if ((Ship.Position - _destination).Length() < (float)_rand.Next(0, 10) / 10f && Ship.LinearVelocity.Length() <= .01) { //Ship is at destination, hold position aggressively MacroState = LogicStates.HoldPosAggressively; Ship.Thrusting = false; } else { var result = AIHelper.TurnTowardPosition(Ship.Rotation, Ship.ShipStats.TurnRate, Ship.Position, _destination, gameTime.ElapsedMilliseconds, .2f); Ship.Rotation = result.Rotation; if (!result.Rotated) { Ship.Thrust(ThrustTypes.Forward); Ship.Thrusting = true; } } } else { MacroState = LogicStates.AttackingTarget; MicroState = 1; _lastState = LogicStates.AttackingToPosition; } } else if (MacroState == LogicStates.HoldPosAggressively) { if (CurrentTarget == null) { _findTarget(_engagementRange); } if (CurrentTarget == null) { StopShip(gameTime);//Hold the ship's position } else { MacroState = LogicStates.AttackingTarget; _lastState = LogicStates.HoldPosAggressively; } } }
public override void AttackTarget(ITargetable target) { MacroState = LogicStates.AttackingTarget; MicroState = 1; CurrentTarget = target; }
public override void Stop() { MacroState = LogicStates.Stopped; }
public override void GoToPosition(Vector2 destination) { _destination = destination; MacroState = LogicStates.MovingToPosition; }