/// <summary> /// Controls moving the enemy ships towards the player, and controls their firing mechanics, as well as moving cannon balls after they have been fired /// </summary> /// <param name="gameTime">used to restrict the Enemy's rate of fire</param> /// <param name="player">Provides player data so that Enemies can respond to events accordingly</param> public override void UpdateAndMove(TimeSpan gameTime, Ship player) { float distanceFromPlayer = Vector2.Distance(position, player.Position); //if the enemy is chasing the player, then move the enemy in a heading along that angle //otherwise, it is in firing mode, so the enemy should not move and instead orient itself to be parallel with the player if (distanceFromPlayer <= range) { state = EnemyState.Firing; } if (state == EnemyState.Chasing) { //calculate the angle towards the player and set the enemy's angle to that angle this.angle = TurnToFace(position, player.Position, this.angle, turnSpeed); Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); this.position += heading * this.speed; } //now that the position has been set, check to see if it needs to fire if (state == EnemyState.Firing) { //assume the firing position. this.angle = TurnToFire(position, player.Position, this.angle, turnSpeed); Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); if (gameTime.TotalMilliseconds - lastFire.TotalMilliseconds > rateOfFire) { this.Fire(); lastFire = gameTime; } base.Update(gameTime); }//end if firing }
/// <summary> /// Update the rotation of the FriendlyShip towards an Enemy and fire at that Enemy /// </summary> /// <param name="gameTime">Snapshot of timing values</param> /// <param name="enemy">Enemy data so that the FriendlyShip can aim and fire at it</param> public override void UpdateAndMove(TimeSpan gameTime, Ship enemy) { //assume the firing position. this.angle = base.TurnToFire(position, enemy.Position, this.angle, turnSpeed); Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); base.Fire(gameTime); base.Update(gameTime); }
/// <summary> /// Update the rotation of the FriendlyShip towards an Enemy and fire at that Enemy /// </summary> /// <param name="gameTime">Snapshot of timing values</param> /// <param name="enemy">Enemy data so that the FriendlyShip can aim and fire at it</param> public override void UpdateAndMove(TimeSpan gameTime, Ship enemy) { //assume the firing position. this.angle = base.TurnToFire(position, enemy.Position, this.angle, turnSpeed); Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); if (gameTime.TotalMilliseconds - lastFire.TotalMilliseconds > rateOfFire) { base.Fire(); lastFire = gameTime; } base.Update(gameTime); }
/// <summary> /// Handles changing position, c_direction and angle when applicable /// </summary> /// <param name="player">Player data so that the object can respond to player events accordingly</param> public virtual void Update(Ship player) { float distanceFromPlayer = Vector2.Distance(this.position, player.Position); if (distanceFromPlayer <= player.Texture.Width/2 + this.Texture.Width/2 + 15) { this.angle = TurnToFace(position, player.Position, angle, 10); WrapAngle(this.angle); this.speed *= 2; } Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); this.position += heading * this.speed; }
/// <summary> /// Update the enemy's state and move the enemy towards the player /// </summary> /// <param name="gameTime">Timing snapshot used to regulate rate of fire</param> /// <param name="player">The player's game information so that the AI can react accordingly</param> public virtual void UpdateAndMove(TimeSpan gameTime, Ship player) { float distanceFromPlayer = Vector2.Distance(position, player.Position); //if the enemy is chasing the player, then move the enemy in a heading along that angle //otherwise, it is in firing mode, so the enemy should not move and instead orient itself to be parallel with the player if (state == EnemyState.Chasing) { //calculate the angle towards the player and set the enemy's angle to that angle this.angle = TurnToFace(position, player.Position, this.angle, turnSpeed); Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); this.position += heading * this.speed; } }
private void CollisionDetection(Ship s, Ship e, int index) { //check cannon balls for (int j = s.getCBA().Count - 1; j >= 0; j--) { CannonBall cB = s.getCBA().ElementAt(j); if (cB.BoundingBox.Intersects(e.BoundingBox)) { Console.WriteLine("\nCOLLISION CB "+ j + ": \n" + cB.BoundingBox.Print() + "\nAGAINST: \n" + e.BoundingBox.Print()+"\n"); //deal damage to enemy e.takeDamage(cB.getDamage()); //remove cannon ball //if the ship is not a player frigate, remove the cannon ball upon contact if (s.GetType() != typeof(Player_Frigate)) s.getCBA().Remove(cB); //if it is a player frigate, check to see if it's ability is activated, if not, then remove the cannon ball upon contact. Else, leave the cannon balls alone else { if (((Player)(s)).getShipState() != Ship.ShipState.AbilityActivated) s.getCBA().Remove(cB); } }//end if collision //check if the ship should be sunk }//end for j //if s is the player, then check if it is a brig and has its ability activated if (s == player) { if (player.GetType() == typeof(Player_Brig) && player.getShipState() == Ship.ShipState.AbilityActivated) if (s.BoundingBox.Intersects(e.BoundingBox)) { e.takeDamage(s.getDamage()); } } //check if the ship should be sunk if (e.getHealth() <= 0) { if (e.GetType() == typeof(Player_Brig) || e.GetType() == typeof(Player_Frigate) || e.GetType() == typeof(Player_ManOfWar)) { UnloadContent(); EndRun(); } } }
/// <summary> /// Activate the multiplier's ability. Since it does nothing to a ship, calling this method does nothing. /// </summary> /// <param name="s">The ship to act against</param> public override void ActivateAbility(Ship s) { //do nothing. No ability to call }
/// <summary> /// Update all projectiles and move the boss /// </summary> /// <param name="gameTime">Snapshot of time values</param> /// <param name="player">Player data so that the boss can respond to events accordingly</param> public override void UpdateAndMove(TimeSpan gameTime, Ship player) { float distance = Vector2.Distance(position, startingPos); if (distance <= 50) bossState = BossState.Firing; //if the boss is moving to position, just move towards it if (bossState == BossState.MovingToPosition) { //calculate the angle towards the player and set the enemy's angle to that angle this.angle = TurnToFace(position, startingPos, this.angle, turnSpeed); Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); this.position += heading * this.speed; } //if the boss is set to fire, start firing projectiles else if (bossState == BossState.Firing) { //assume the firing position. this.angle = TurnToFire(position, player.Position, this.angle, turnSpeed); Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); //the boss fires a burst of 10 projectiles with a break between each projectile in the burst, and a break in between each full burst if (gameTime.TotalMilliseconds - lastFire.TotalMilliseconds > rateOfFire && gameTime.TotalMilliseconds - lastBurst.TotalMilliseconds > TIME_BETWEEN_BURSTS) { //update time of last burst lastBurst = gameTime; //fire another salvo of projectiles this.Fire(gameTime); if (++burstCount > TOTAL_PER_BURST) { //Burst is complete, so this round of firing is complete too, reset burst count to 0, and set lastFire to current time burstCount = 0; lastFire = gameTime; } } //Move cannon balls this.Update(gameTime); } }
/// <summary> /// Collision detection between two ships. Checks the cannon ball array of the first ship against the second ship to see if the first ship has hit the second. If it has, damage is dealt, and this function checks to see if the second ship has lost all its health and if it has removes the ship. Works for both player vs enemy and enemy vs player and handles all special cases /// </summary> /// <param name="s">The ship dealing damage</param> /// <param name="e">The ship having damage dealt against it</param> /// <param name="index">Only needs to be used if the function is being called from a loop iterating through a list. it allows the use of RemoveAt() which is O(1) over Remove() which is O(n)</param> private void CollisionDetection(Ship s, Ship e, int index) { //check cannon balls for (int j = s.CannonBalls.Count - 1; j >= 0; j--) { CannonBall cB = s.CannonBalls.ElementAt(j); if (cB.BoundingBox.Intersects(e.BoundingBox)) { //deal damage to enemy e.takeDamage(cB.Damage); //remove cannon ball s.CannonBalls.Remove(cB); }//end if collision //check if the ship should be sunk }//end for j //if s is the player, then check if it is a brig and has its ability activated if (s == player) { if (player.GetType() == typeof(Player_Brig) && player.getShipState() == Player.ShipState.AbilityActivated) if (s.BoundingBox.Intersects(e.BoundingBox)) { e.takeDamage(s.Damage); } } //if the ship is a fireboat, check if it has collided with the other ship. If it has, then do damage and remove it from the list and return if (s.GetType() == typeof(FireBoat)) { if (s.BoundingBox.Intersects(e.BoundingBox)) { EnemyList.RemoveAt(index); return; } } //check if the ship should be sunk if (e.Health <= 0) { if (e.GetType() == typeof(Player_Brig) || e.GetType() == typeof(Player_Frigate) || e.GetType() == typeof(Player_ManOfWar)) { gameState = GameState.GameOver; } else { //add score score += (((Enemy)(e)).getScore() * scoreMultiplier); //drop multipliers int numberOfMultis = ((Enemy)(e)).getScore() / 5; for (int m = 0; m < numberOfMultis; m++) { Multiplier mp = new Multiplier(MULTIPLIER_DATA, e.Position, e.Position, (float)(randomGenerator.Next(360)) * (float)(Math.PI / 180), multiplierTexture, gameTimer.RawTime); playerInteractableList.Add(mp); } //determine if this ship will drop a powerup DropPowerup((Enemy)e); //remove from list EnemyList.RemoveAt(index); } } }
/// <summary> /// Activate the powerup's ability. In this case, give health /// </summary> /// <param name="s">The ship receiving health</param> public override void ActivateAbility(Ship s) { s.giveHealth(s.MaxHealth / 10); //give back 10% of health }
/// <summary> /// Activate the PlayerInteractable's ability (if it has one) /// </summary> /// <param name="s">The ship that will receive the benefit from the PlayerInteractable</param> public abstract void ActivateAbility(Ship s);
/// <summary> /// Handles changing position, c_direction and angle when applicable /// </summary> /// <param name="player">Player data so that the object can respond to player events accordingly</param> /// <param name="gameTime">Snapshot of timing values from game</param> public virtual void Update(Ship player, TimeSpan gameTime) { float distanceFromPlayer = Vector2.Distance(this.position, player.Position); //Update movement if (distanceFromPlayer <= player.Texture.Width/2 + this.Texture.Width/2 + 15) { this.angle = TurnToFace(position, player.Position, angle, 10); RectangleF.WrapAngle(this.angle); this.speed *= 2; } Vector2 heading = new Vector2((float)Math.Cos(this.angle), (float)Math.Sin(this.angle)); this.position += heading * this.speed; //Update fade //object should start to flash 2 seconds before it is removed (5-3 = 2) if (gameTime - spawnTime >= startBlink) { if (gameTime - lastFade >= fadeDelay) { if (faded == true) faded = false; else faded = true; lastFade = gameTime; } } if (gameTime - spawnTime >= timeAllowedOnScreen) timedOut = true; }