public override void Update(GameTime gameTime) { bool isGroundHit; bool startStall; CatapultState postUpdateStateChange = 0; if (gameTime == null) { throw new ArgumentNullException("gameTime"); } // The catapult is inactive, so there is nothing to update if (!IsActive) { base.Update(gameTime); return; } switch (currentState) { case CatapultState.Idle: // Nothing to do break; case CatapultState.Aiming: if (lastUpdateState != CatapultState.Aiming) { AudioManager.PlaySound("ropeStretch", true); AnimationRunning = true; if (isAI == true) { animations["Aim"].PlayFromFrameIndex(0); stallUpdateCycles = 20; startStall = false; } } // Progress Aiming "animation" if (isAI == false) { UpdateAimAccordingToShotStrength(); } else { animations["Aim"].Update(); startStall = AimReachedShotStrength(); currentState = (startStall) ? CatapultState.Stalling : CatapultState.Aiming; } break; case CatapultState.Stalling: if (stallUpdateCycles-- <= 0) { // We've finished stalling, fire the projectile Fire(ShotVelocity, ShotAngle); postUpdateStateChange = CatapultState.Firing; } break; case CatapultState.Firing: // Progress Fire animation if (lastUpdateState != CatapultState.Firing) { AudioManager.StopSound("ropeStretch"); AudioManager.PlaySound("catapultFire"); StartFiringFromLastAimPosition(); } animations["Fire"].Update(); // If in the "split" point of the animation start // projectile fire sequence if (animations["Fire"].FrameIndex == splitFrames["Fire"]) { postUpdateStateChange = currentState | CatapultState.ProjectileFlying; projectile.ProjectilePosition = projectile.ProjectileStartPosition; } break; case CatapultState.Firing | CatapultState.ProjectileFlying: // Progress Fire animation animations["Fire"].Update(); // Update projectile velocity & position in flight projectile.UpdateProjectileFlightData(gameTime, wind, gravity, out isGroundHit); if (isGroundHit) { // Start hit sequence postUpdateStateChange = CatapultState.ProjectileHit; animations["fireMiss"].PlayFromFrameIndex(0); } break; case CatapultState.ProjectileFlying: // Update projectile velocity & position in flight projectile.UpdateProjectileFlightData(gameTime, wind, gravity, out isGroundHit); if (isGroundHit) { // Start hit sequence postUpdateStateChange = CatapultState.ProjectileHit; animations["fireMiss"].PlayFromFrameIndex(0); } break; case CatapultState.ProjectileHit: // Check hit on ground impact if (!CheckHit()) { if (lastUpdateState != CatapultState.ProjectileHit) { VibrateController.Default.Start( TimeSpan.FromMilliseconds(100)); // Play hit sound only on a missed hit, // a direct hit will trigger the explosion sound AudioManager.PlaySound("boulderHit"); } // Hit animation finished playing if (animations["fireMiss"].IsActive == false) { postUpdateStateChange = CatapultState.Reset; } animations["fireMiss"].Update(); } else { // Catapult hit - start longer vibration on any catapult hit // Remember that the call to "CheckHit" updates the catapult's // state to "Hit" VibrateController.Default.Start( TimeSpan.FromMilliseconds(500)); } break; case CatapultState.Hit: // Progress hit animation if ((animations["Destroyed"].IsActive == false) && (animations["hitSmoke"].IsActive == false)) { if (enemy.Score >= winScore) { GameOver = true; break; } postUpdateStateChange = CatapultState.Reset; } animations["Destroyed"].Update(); animations["hitSmoke"].Update(); break; case CatapultState.Reset: AnimationRunning = false; break; default: break; } lastUpdateState = currentState; if (postUpdateStateChange != 0) { currentState = postUpdateStateChange; } base.Update(gameTime); }
/// <summary> /// Runs one frame of update for the game. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen) { float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; // Check it one of the players reached 5 and stop the game if ((player.Catapult.GameOver || computer.Catapult.GameOver) && (gameOver == false)) { gameOver = true; if (player.Score > computer.Score) { AudioManager.PlaySound("gameOver_Win"); } else { AudioManager.PlaySound("gameOver_Lose"); } return; } // If Reset flag raised and both catapults are not animating - // active catapult finished the cycle, new turn! if ((player.Catapult.CurrentState == CatapultState.Reset || computer.Catapult.CurrentState == CatapultState.Reset) && !(player.Catapult.AnimationRunning || computer.Catapult.AnimationRunning)) { changeTurn = true; if (player.IsActive == true) //Last turn was a human turn? { player.IsActive = false; computer.IsActive = true; isHumanTurn = false; player.Catapult.CurrentState = CatapultState.Idle; computer.Catapult.CurrentState = CatapultState.Aiming; } else //It was an AI turn { player.IsActive = true; computer.IsActive = false; isHumanTurn = true; computer.Catapult.CurrentState = CatapultState.Idle; player.Catapult.CurrentState = CatapultState.Idle; } } if (changeTurn) { // Update wind wind = new Vector2(random.Next(-1, 2), random.Next(minWind, maxWind + 1)); // Set new wind value to the players and player.Catapult.Wind = computer.Catapult.Wind = wind.X > 0 ? wind.Y : -wind.Y; changeTurn = false; } // Update the players player.Update(gameTime); computer.Update(gameTime); // Updates the clouds position UpdateClouds(elapsed); base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen); }
/// <summary> /// Performs all logic necessary when a projectile hits the ground. /// </summary> /// <param name="projectile"></param> private void HandleProjectileHit(Projectile projectile) { projectile.HitHandled = true; switch (CheckHit(projectile)) { case HitCheckResult.SelfCrate: // Ignore self crate hits case HitCheckResult.Nothing: PerformNothingHit(projectile); break; case HitCheckResult.SelfCatapult: if ((CurrentState != CatapultState.Hit) && (CurrentState != CatapultState.Reset)) { // Catapult hit - start longer vibration on any catapult hit // Remember that the call to "CheckHit" updates the catapult's // state to "Hit" VibrateController.Default.Start(TimeSpan.FromMilliseconds(500)); AudioManager.PlaySound("catapultExplosion"); projectile.HitAnimation = animations["hitSmoke"]; // Launch hit animation sequence on self Hit(); enemy.Score++; } else { PerformNothingHit(projectile); } break; case HitCheckResult.EnemyCatapult: if ((enemy.Catapult.CurrentState != CatapultState.Hit) && (enemy.Catapult.CurrentState != CatapultState.Reset)) { // Catapult hit - start longer vibration on any catapult hit // Remember that the call to "CheckHit" updates the catapult's // state to "Hit" VibrateController.Default.Start(TimeSpan.FromMilliseconds(500)); AudioManager.PlaySound("catapultExplosion"); projectile.HitAnimation = animations["hitSmoke"]; // Launch enemy hit animaton enemy.Catapult.Hit(); self.Score++; } else { PerformNothingHit(projectile); } break; case HitCheckResult.EnemyCrate: if (enemy.Catapult.crate.CurrentState == CrateState.Idle) { AudioManager.PlaySound("catapultExplosion"); projectile.HitAnimation = animations["hitSmoke"]; enemy.Catapult.crate.Hit(); self.Weapon = WeaponType.Split; } else { PerformNothingHit(projectile); } break; default: throw new InvalidOperationException("Hit invalid entity"); } projectile.HitAnimation.PlayFromFrameIndex(0); }
public override void Update(GameTime gameTime) { bool startStall; CatapultState postUpdateStateChange = 0; if (gameTime == null) { throw new ArgumentNullException("gameTime"); } // The catapult is inactive, so there is nothing to update if (!IsActive) { base.Update(gameTime); return; } switch (currentState) { case CatapultState.Idle: // Nothing to do break; case CatapultState.Aiming: if (lastUpdateState != CatapultState.Aiming) { AudioManager.PlaySound("ropeStretch", true); AnimationRunning = true; if (isAI == true) { animations["Aim"].PlayFromFrameIndex(0); stallUpdateCycles = 20; startStall = false; } } // Progress Aiming "animation" if (isAI == false) { UpdateAimAccordingToShotStrength(); } else { animations["Aim"].Update(); startStall = AimReachedShotStrength(); currentState = (startStall) ? CatapultState.Stalling : CatapultState.Aiming; } break; case CatapultState.Stalling: if (stallUpdateCycles-- <= 0) { // We've finished stalling, fire the projectile postUpdateStateChange = CatapultState.Firing; } break; case CatapultState.Firing: // Progress Fire animation if (lastUpdateState != CatapultState.Firing) { AudioManager.StopSound("ropeStretch"); AudioManager.PlaySound("catapultFire"); StartFiringFromLastAimPosition(); } animations["Fire"].Update(); // If in the "split" point of the animation start // projectile fire sequence if (animations["Fire"].FrameIndex == splitFrames["Fire"]) { Fire(ShotVelocity); } if (animations["Fire"].IsActive == false) { postUpdateStateChange = CatapultState.ProjectilesFalling; } break; case CatapultState.ProjectilesFalling: // End turn if all projectiles have been destroyed if (activeProjectiles.Count == 0) { postUpdateStateChange = CatapultState.Reset; } break; case CatapultState.Hit: // Progress hit animation if (animations["Destroyed"].IsActive == false) { if (enemy.Score >= winScore) { GameOver = true; break; } postUpdateStateChange = CatapultState.Reset; } animations["Destroyed"].Update(); break; case CatapultState.Reset: AnimationRunning = false; break; default: break; } lastUpdateState = currentState; if (postUpdateStateChange != 0) { currentState = postUpdateStateChange; } // Update active projectiles destroyedProjectiles.Clear(); // Clean swap list activeProjectilesCopy.Clear(); // Copy the projectile list so that it may be modified while updating activeProjectilesCopy.AddRange(activeProjectiles); foreach (var projectile in activeProjectilesCopy) { projectile.Update(gameTime); // If the projectile hit the ground if ((projectile.State == ProjectileState.HitGround) && (projectile.HitHandled == false)) { HandleProjectileHit(projectile); } if (projectile.State == ProjectileState.Destroyed) { destroyedProjectiles.Add(projectile); } } // Filter out destroyed projectiles foreach (var projectile in destroyedProjectiles) { activeProjectiles.Remove(projectile); } // Update crate crate.Update(gameTime); base.Update(gameTime); }
/// <summary> /// Runs one frame of update for the game. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen) { float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; // Check it one of the players reached 5 and stop the game if ((player.Catapult.GameOver || computer.Catapult.GameOver) && (gameOver == false)) { gameOver = true; if (player.Score > computer.Score) { AudioManager.PlaySound("gameOver_Win"); } else { AudioManager.PlaySound("gameOver_Lose"); } return; } if (isFlying) { if (ScreenCenter == flightDestination) { isFlying = false; } else { // Find the direction in which we need to move to get from the // screen center to our flight destination Vector2 flightVector = flightDestination - ScreenCenter; Vector2 flightMovementVector = flightVector; flightMovementVector.Normalize(); flightMovementVector *= 10; flightMovementVector *= (float)(0.25 * (2 + Math.Log((flightVector.Length() + 0.2)))); if (flightMovementVector.Length() > flightVector.Length()) { DrawOffset -= flightVector; } else { DrawOffset -= flightMovementVector; } CorrectScreenPosition(40, 30); } } else { CorrectScreenPosition(0, 0); } // If Reset flag raised and both catapults are not animating - // active catapult finished the cycle, new turn! if ((player.Catapult.CurrentState == CatapultState.Reset || computer.Catapult.CurrentState == CatapultState.Reset) && !(player.Catapult.AnimationRunning || computer.Catapult.AnimationRunning)) { changeTurn = true; if (player.IsActive == true) // Last turn was a human turn? { CenterOnPosition(computer.Catapult.Position - catapultCenterOffset); player.IsActive = false; computer.IsActive = true; isHumanTurn = false; player.Catapult.CurrentState = CatapultState.Idle; computer.Catapult.CurrentState = CatapultState.Aiming; } else //It was an AI turn { isCameraMoving = true; player.IsActive = true; computer.IsActive = false; isHumanTurn = true; computer.Catapult.CurrentState = CatapultState.Idle; player.Catapult.CurrentState = CatapultState.Idle; } } if (changeTurn) { // Update wind wind = new Vector2(random.Next(-1, 2), random.Next(minWind, maxWind + 1)); // Set new wind value to the players and player.Catapult.Wind = computer.Catapult.Wind = wind.X > 0 ? wind.Y : -wind.Y; changeTurn = false; } // Update the players player.Update(gameTime); computer.Update(gameTime); // Updates the clouds position UpdateClouds(elapsed); base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen); }
/// <summary> /// Check what a projectile hit. The possibilities are: /// Nothing hit, Hit enemy, Hit self, hit own/enemy's crate. /// </summary> /// <param name="projectile">The projectile for which to /// perform the check.</param> /// <returns>A result inidicating what, if anything, was hit</returns> private HitCheckResult CheckHit(Projectile projectile) { HitCheckResult hitRes = HitCheckResult.Nothing; // Build a sphere around a projectile Vector3 center = new Vector3(projectile.ProjectilePosition, 0); BoundingSphere sphere = new BoundingSphere(center, Math.Max(projectile.ProjectileTexture.Width / 2, projectile.ProjectileTexture.Height / 2)); // Check Self-Hit - create a bounding box around self Vector3 min = new Vector3(catapultPosition, 0); Vector3 max = new Vector3(catapultPosition + new Vector2(animations["Fire"].FrameSize.X, animations["Fire"].FrameSize.Y), 0); BoundingBox selfBox = new BoundingBox(min, max); // Check enemy - create a bounding box around the enemy min = new Vector3(enemy.Catapult.Position, 0); max = new Vector3(enemy.Catapult.Position + new Vector2(animations["Fire"].FrameSize.X, animations["Fire"].FrameSize.Y), 0); BoundingBox enemyBox = new BoundingBox(min, max); // Check self-crate - Create bounding box around own crate min = new Vector3(crate.Position, 0); max = new Vector3(crate.Position + new Vector2(crate.Width, crate.Height), 0); BoundingBox selfCrateBox = new BoundingBox(min, max); // Check enemy-crate - Create bounding box around enemy crate min = new Vector3(enemy.Catapult.crate.Position, 0); max = new Vector3(enemy.Catapult.crate.Position + new Vector2(enemy.Catapult.crate.Width, enemy.Catapult.crate.Height), 0); BoundingBox enemyCrateBox = new BoundingBox(min, max); // Check self hit if (sphere.Intersects(selfBox) && currentState != CatapultState.HitKill) { AudioManager.PlaySound("catapultExplosion"); // Launch hit animation sequence on self UpdateHealth(self, sphere, selfBox); if (self.Health <= 0) { Hit(true); enemy.Score++; } hitRes = HitCheckResult.SelfCatapult; } // Check if enemy was hit else if (sphere.Intersects(enemyBox) && enemy.Catapult.CurrentState != CatapultState.HitKill && enemy.Catapult.CurrentState != CatapultState.Reset) { AudioManager.PlaySound("catapultExplosion"); // Launch enemy hit animaton UpdateHealth(enemy, sphere, enemyBox); if (enemy.Health <= 0) { enemy.Catapult.Hit(true); self.Score++; } hitRes = HitCheckResult.EnemyCatapult; currentState = CatapultState.Reset; } // Check if own crate was hit else if (sphere.Intersects(selfCrateBox)) { hitRes = HitCheckResult.SelfCrate; } // Check if enemy crate was hit else if (sphere.Intersects(enemyCrateBox)) { hitRes = HitCheckResult.EnemyCrate; } return(hitRes); }