public override void Initialize() { // Define initial state of the catapult currentState = CatapultState.Idle; // Load the idle texture idleTexture = curGame.Content.Load <Texture2D>(idleTextureName); // Initialize the projectile Vector2 projectileStartPosition; if (isAI) { projectileStartPosition = new Vector2(630, 340); } else { projectileStartPosition = new Vector2(175, 340); } // TODO: Update hit offset projectile = new Projectile(curGame, spriteBatch, "Textures/Ammo/rock_ammo", projectileStartPosition, 60, isAI, gravity); projectile.Initialize(); IsActive = true; AnimationRunning = false; stallUpdateCycles = 0; // Initialize randomizer random = new Random(); base.Initialize(); }
private void OnMouseOver() { switch (state) { case CatapultState.powering: if (Input.GetMouseButtonDown(0)) { state = CatapultState.recharging; isReady = false; StartCoroutine(Recharge()); } break; case CatapultState.recharging: if (isReady) { state = CatapultState.aiming; } break; default: case CatapultState.aiming: if (Input.GetMouseButtonDown(0)) { direction = (Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position).normalized; state = CatapultState.powering; StartCoroutine(PoweringShoot()); } break; } }
/// <summary> /// Start Hit sequence on catapult - could be executed on self or from enemy in case of hit /// </summary> public void Hit() { AnimationRunning = true; animations["Destroyed"].PlayFromFrameIndex(0); currentState = CatapultState.Hit; self.Weapon = WeaponType.Normal; }
/// <summary> /// Start Hit sequence on catapult - could be executed on self or from enemy in case of hit /// </summary> public void Hit() { AnimationRunning = true; animations["Destroyed"].PlayFromFrameIndex(0); animations["hitSmoke"].PlayFromFrameIndex(0); currentState = CatapultState.Hit; }
private void EnterFire() { state = CatapultState.Fire; SetArmed(value: false); UnlockPull(); UnlockTrigger(); fired = false; }
/// <summary> /// Check if projectile hit some catapult. The possibilities are: /// Nothing hit, Hit enemy, Hit self /// </summary> /// <returns></returns> private bool CheckHit() { bool bRes = false; // 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 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++; bRes = true; } } // 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++; bRes = true; } currentState = CatapultState.Reset; } return(bRes); }
private bool CheckHit() { bool bRes = false; // Build a sphere around the 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 // TODO: Take asset size into account Vector3 min = new Vector3(catapultPosition, 0); Vector3 max = new Vector3(catapultPosition + new Vector2(75, 60), 0); BoundingBox selfBox = new BoundingBox(min, max); // Check enemy - create a bounding box around the enemy // TODO: Take asset size into account min = new Vector3(enemy.Catapult.Position, 0); max = new Vector3(enemy.Catapult.Position + new Vector2(75, 60), 0); BoundingBox enemyBox = new BoundingBox(min, max); // Check self hit if (sphere.Intersects(selfBox) && currentState != CatapultState.Hit) { // TODO: Play self hit sound // Launch hit animation sequence on self Hit(); enemy.Score++; bRes = true; } // Check if enemy was hit else if (sphere.Intersects(enemyBox) && enemy.Catapult.CurrentState != CatapultState.Hit && enemy.Catapult.CurrentState != CatapultState.Reset) { // TODO: Play enemy hit sound // Launch enemy hit animaton enemy.Catapult.Hit(); self.Score++; bRes = true; currentState = CatapultState.Reset; } return(bRes); }
private void OnMouseOver() { if (EventSystem.current.IsPointerOverGameObject()) { return; } switch (state) { case CatapultState.powering: if (Input.GetMouseButtonDown(0)) { if (ammo != null) { state = CatapultState.recharging; isReady = false; ProjectilesManager.PM.CheckSpecialAmmoUsed(); StartCoroutine(Recharge()); } else { state = CatapultState.aiming; } } break; case CatapultState.recharging: if (isReady) { state = CatapultState.aiming; } break; default: case CatapultState.aiming: if (Input.GetMouseButtonDown(0)) { direction = (Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position).normalized; state = CatapultState.powering; StartCoroutine(PoweringShoot()); } break; } }
private void SetState(CatapultState newState) { if (newState != state) { switch (state) { case CatapultState.Idle: LeaveIdle(); break; case CatapultState.Wind: LeaveWind(); break; case CatapultState.Trigger: LeaveTrigger(); break; case CatapultState.Fire: LeaveFire(); break; } state = newState; switch (state) { case CatapultState.Idle: EnterIdle(); break; case CatapultState.Wind: EnterWind(); break; case CatapultState.Trigger: EnterTrigger(); break; case CatapultState.Fire: EnterFire(); break; } } }
/// <summary> /// Start Hit sequence on catapult - could be executed on self or from enemy in case of hit /// </summary> public void Hit(bool isKilled) { AnimationRunning = true; if (isKilled) { animations["Destroyed"].PlayFromFrameIndex(0); } animations["hitSmoke"].PlayFromFrameIndex(0); if (isKilled) { currentState = CatapultState.HitKill; } else { currentState = CatapultState.HitDamage; } }
// Reset the catapult and pumpkin to default positions private void ResetCatapult() { basePosition.X = -100; basePosition.Y = 430; baseSpeed = 0; pumpkinPosition = Vector2.Zero; armRotation = MathHelper.ToRadians(0); currentState = CatapultState.Rolling; pumpkinPosition = Vector2.Zero; pumpkinVelocity = Vector2.Zero; pumpkinPosition.X = pumpkinLaunchPosition = basePosition.X + 120; pumpkinPosition.Y = basePosition.Y + 80; pumpkinRotation = 0; boostPower = 0; }
/// <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); if (self.IsActive) { self.Score++; if (App.g_isTwoHumanPlayers) { Dictionary<string, object> scoreProperties = new Dictionary<string, object>(); if (GlobalContext.PlayerIsFirstOnAppWarp) { GlobalContext.tableProperties["Player1Score"] = self.Score; scoreProperties.Add("Player1Score", self.Score); } else { scoreProperties.Add("Player2Score", self.Score); GlobalContext.tableProperties["Player2Score"] = self.Score; } WarpClient.GetInstance().UpdateRoomProperties(GlobalContext.GameRoomId, scoreProperties, null); } } } 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; }
public override void Update(GameTime gameTime) { bool isGroundHit; CatapultState postUpdateStateChange = 0; if (gameTime == null) { throw new ArgumentNullException("gameTime"); } if (!IsActive) { base.Update(gameTime); return; } switch (currentState) { case CatapultState.Idle: // Nothing to do break; case CatapultState.Aiming: if (lastUpdateState != CatapultState.Aiming) { // TODO: Play sound AnimationRunning = true; if (isAI == true) { // TODO: Play animation stallUpdateCycles = 20; } } // Progress Aiming "animation" if (isAI == false) { // TODO: Play animation } else { // TODO: Play animation // TODO: take �startStall� into account currentState = (true) ? CatapultState.Stalling : CatapultState.Aiming; } break; case CatapultState.Stalling: if (stallUpdateCycles-- <= 0) { // We've finished stalling, fire the projectile Fire(ShotVelocity); postUpdateStateChange = CatapultState.Firing; } break; case CatapultState.Firing: // Progress Fire animation if (lastUpdateState != CatapultState.Firing) { // TODO: Play Sounds and animate } // TODO: Play animation // TODO: Fire at the appropriate animation frame postUpdateStateChange = currentState | CatapultState.ProjectileFlying; projectile.ProjectilePosition = projectile.ProjectileStartPosition; break; case CatapultState.Firing | CatapultState.ProjectileFlying: // Progress Fire animation // TODO: Play animation // Update projectile velocity & position in flight projectile.UpdateProjectileFlightData(gameTime, wind, gravity, out isGroundHit); if (isGroundHit) { // Start hit sequence postUpdateStateChange = CatapultState.ProjectileHit; // TODO: Play animation } 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; // TODO: Play animation } break; case CatapultState.ProjectileHit: // Check hit on ground impact if (!CheckHit()) { if (lastUpdateState != CatapultState.ProjectileHit) { // TODO: Vibrate device and play sound } // TODO: Relate to animation when changing state postUpdateStateChange = CatapultState.Reset; // TODO: Update animation } else { // TODO: Vibrate the device } break; case CatapultState.Hit: // TODO: only check score when animation is finished if (enemy.Score >= winScore) { GameOver = true; break; } postUpdateStateChange = CatapultState.Reset; // TODO: Update animation break; case CatapultState.Reset: AnimationRunning = false; break; default: break; } lastUpdateState = currentState; if (postUpdateStateChange != 0) { currentState = postUpdateStateChange; } base.Update(gameTime); }
private void EnterTrigger() { state = CatapultState.Trigger; UnlockTrigger(); }
// Change state to firing and play fire sound private void Fire() { currentState = CatapultState.Firing; pumpkinRotationPosition = pumpkinPosition; curGame.SoundBank.PlayCue("ThrowSound"); }
public override void Update(GameTime gameTime) { if (gameTime == null) { throw new ArgumentNullException("gameTime"); } // Do we need to reset if (currentState == CatapultState.Reset) { ResetCatapult(); } // Are we currently rolling? if (currentState == CatapultState.Rolling) { // Add to current speed float speedAmt = curGame.CurrentGamePadState.Triggers.Left; if (curGame.CurrentKeyboardState.IsKeyDown(Keys.Right)) { speedAmt = 1.0f; } baseSpeed += speedAmt * gameTime.ElapsedGameTime.Milliseconds * 0.001f; // Move catapult based on speed basePosition.X += baseSpeed * gameTime.ElapsedGameTime.Milliseconds; // Move pumpkin to match catapult pumpkinPosition.X = pumpkinLaunchPosition = basePosition.X + 120; pumpkinPosition.Y = basePosition.Y + 80; // Play moving sound if (playingCue == null && baseSpeed > 0) { playingCue = curGame.SoundBank.GetCue("Move"); playingCue.Play(); } // Check to see if we fire the pumpkin if ((curGame.CurrentGamePadState.Buttons.A == ButtonState.Pressed && curGame.LastGamePadState.Buttons.A != ButtonState.Pressed) || (curGame.CurrentKeyboardState.IsKeyDown(Keys.Space) && curGame.LastKeyboardState.IsKeyUp(Keys.Space))) { Fire(); if (playingCue != null && playingCue.IsPlaying) { playingCue.Stop(AudioStopOptions.Immediate); playingCue.Dispose(); playingCue = curGame.SoundBank.GetCue("Flying"); playingCue.Play(); } } } // Are we in the firing state else if (currentState == CatapultState.Firing) { // Rotate the arm if (armRotation < MathHelper.ToRadians(81)) { armRotation += MathHelper.ToRadians(gameTime.ElapsedGameTime.Milliseconds); Matrix matTranslate, matTranslateBack, matRotate, matFinal; matTranslate = Matrix.CreateTranslation((-pumpkinRotationPosition.X) - 170, -pumpkinRotationPosition.Y, 0); matTranslateBack = Matrix.CreateTranslation(pumpkinRotationPosition.X + 170, pumpkinRotationPosition.Y, 0); matRotate = Matrix.CreateRotationZ(armRotation); matFinal = matTranslate * matRotate * matTranslateBack; Vector2.Transform(ref pumpkinRotationPosition, ref matFinal, out pumpkinPosition); pumpkinLaunchPosition = pumpkinPosition.X; pumpkinRotation += MathHelper.ToRadians( gameTime.ElapsedGameTime.Milliseconds / 10.0f); } // We are done rotating so send the pumpkin flying else { currentState = CatapultState.ProjectileFlying; pumpkinVelocity.X = baseSpeed * 2.0f + 1; pumpkinVelocity.Y = -baseSpeed * 0.75f; // Add extra velocity for Right trigger float rightTriggerAmt = curGame.CurrentGamePadState.Triggers.Right; if (rightTriggerAmt > 0.5f) { rightTriggerAmt = 1.0f - rightTriggerAmt; } if (curGame.CurrentKeyboardState.IsKeyDown(Keys.B)) { rightTriggerAmt = 0.5f; } rightTriggerAmt *= 2; pumpkinVelocity *= 1.0f + rightTriggerAmt; // Check for extra boost power if (basePosition.X > 620) { boostPower = 3; pumpkinVelocity *= 2.0f; curGame.SoundBank.PlayCue("Boost"); } else if (basePosition.X > 600) { boostPower = 2; pumpkinVelocity *= 1.6f; curGame.SoundBank.PlayCue("Boost"); } else if (basePosition.X > 580) { boostPower = 1; pumpkinVelocity *= 1.3f; curGame.SoundBank.PlayCue("Boost"); } } } // Pumpkin is in the flying state else if (currentState == CatapultState.ProjectileFlying) { // Update the position of the pumpkin pumpkinPosition += pumpkinVelocity * gameTime.ElapsedGameTime.Milliseconds; pumpkinVelocity += pumpkinAcceleration * gameTime.ElapsedGameTime.Milliseconds; // Move the catapult away from the pumpkin basePosition.X -= pumpkinVelocity.X * gameTime.ElapsedGameTime.Milliseconds; // Rotate the pumpkin as it flys pumpkinRotation += MathHelper.ToRadians(pumpkinVelocity.X * 3.5f); // Is the pumpkin hitting the ground if (pumpkinPosition.Y > 630) { // Stop playing any sounds if (playingCue != null && playingCue.IsPlaying) { playingCue.Stop(AudioStopOptions.Immediate); playingCue.Dispose(); playingCue = null; } // Play the bounce sound // curGame.SoundBank.PlayCue("Bounce"); // Move the pumpkin out of the ground and Change the pumkin velocity pumpkinPosition.Y = 630; pumpkinVelocity.Y *= -0.8f; pumpkinVelocity.X *= 0.7f; // Stop the pumpkin if the speed is too low if (pumpkinVelocity.X < 0.1f) { currentState = CatapultState.ProjectileHit; curGame.SoundBank.PlayCue("Hit"); if (curGame.HighScore == (int)curGame.PumpkinDistance && curGame.HighScore > 1000) { curGame.SoundBank.PlayCue("HighScore"); } } } } // Did we crash into the log if (basePosition.X > 650) { currentState = CatapultState.Crash; if (playingCue != null && playingCue.IsPlaying) { playingCue.Stop(AudioStopOptions.Immediate); playingCue.Dispose(); playingCue = null; if (crashCue != null) { crashCue.Stop(AudioStopOptions.Immediate); crashCue.Dispose(); crashCue = null; } crashCue = curGame.SoundBank.GetCue("Crash"); crashCue.Play(); } } // If the projectile hit or we crashed reset the catapult if ((currentState == CatapultState.Crash || currentState == CatapultState.ProjectileHit) && (curGame.CurrentGamePadState.Buttons.A == ButtonState.Pressed || curGame.CurrentKeyboardState.IsKeyDown(Keys.Space)) && curGame.CurrentGamePadState.Triggers.Left == 0 && curGame.CurrentKeyboardState.IsKeyUp(Keys.Right)) { currentState = CatapultState.Reset; } base.Update(gameTime); }
public void Update(GameTimerEventArgs 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 (isLeftSide == true && !isHuman) { animations["Aim"].PlayFromFrameIndex(0); stallUpdateCycles = 20; startStall = false; } } // Progress Aiming "animation" if (isHuman) { UpdateAimAccordingToShotStrength(); } else if (isLeftSide && !isHuman) { 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, ShotAngle); } 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.HitDamage: if (animations["hitSmoke"].IsActive == false) postUpdateStateChange = CatapultState.Reset; animations["hitSmoke"].Update(); break; case CatapultState.HitKill: // Progress hit animation if ((animations["Destroyed"].IsActive == false) && (animations["hitSmoke"].IsActive == false)) { if (enemy.Score >= winScore) { GameOver = true; break; } self.Health = 100; 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; } // 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); }
public void Hit() { AnimationRunning = true; // TODO: Start animations currentState = CatapultState.Hit; }
/// <summary> /// Start Hit sequence on catapult - could be executed on self or from enemy in case of hit /// </summary> public void Hit(bool isKilled) { AnimationRunning = true; // TODO: Handle hit animations if (isKilled) currentState = CatapultState.HitKill; else currentState = CatapultState.HitDamage; self.Weapon = WeaponType.Normal; }
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) { // TODO: Play rope stretch AnimationRunning = true; if (isLeftSide == true && !isHuman) { // TODO: Play aim animation stallUpdateCycles = 20; startStall = false; } } // Progress Aiming "animation" if (isHuman) { // TODO: Update aim } else { // TODO: Update aim // TODO: Aim reach shot strength currentState = (true) ? 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) { // TODO: Play firing sounds } // TODO: Play firing animation // TODO: Fire at the appropriate animation frame postUpdateStateChange = currentState | CatapultState.ProjectileFlying; Fire(ShotVelocity, ShotAngle); break; case CatapultState.ProjectilesFalling: // End turn if all projectiles have been destroyed // TODO: Handle projectiles falling break; case CatapultState.HitDamage: // TODO: Handle hit damage break; case CatapultState.HitKill: // Progress hit animation // TODO: Handle hit kill break; case CatapultState.Reset: AnimationRunning = false; break; default: break; } lastUpdateState = currentState; if (postUpdateStateChange != 0) { currentState = postUpdateStateChange; } // TODO: Update active projectiles base.Update(gameTime); }
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> /// 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); if (self.IsActive) { self.Score++; if (App.g_isTwoHumanPlayers) { Dictionary <string, object> scoreProperties = new Dictionary <string, object>(); if (GlobalContext.PlayerIsFirstOnAppWarp) { GlobalContext.tableProperties["Player1Score"] = self.Score; scoreProperties.Add("Player1Score", self.Score); } else { scoreProperties.Add("Player2Score", self.Score); GlobalContext.tableProperties["Player2Score"] = self.Score; } WarpClient.GetInstance().UpdateRoomProperties(GlobalContext.GameRoomId, scoreProperties, null); } } } 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); }
public override void Initialize() { // Define initial state of the catapult currentState = CatapultState.Idle; // Load the idle texture idleTexture = curGame.Content.Load<Texture2D>(idleTextureName); // Initialize the projectile Vector2 projectileStartPosition; if (isAI) projectileStartPosition = new Vector2(630, 340); else projectileStartPosition = new Vector2(175, 340); // TODO: Update hit offset projectile = new Projectile(curGame, spriteBatch, "Textures/Ammo/rock_ammo", projectileStartPosition, 60, isAI, gravity); projectile.Initialize(); IsActive = true; AnimationRunning = false; stallUpdateCycles = 0; // Initialize randomizer random = new Random(); base.Initialize(); }
/// <summary> /// Check if projectile hit some catapult. The possibilities are: /// Nothing hit, Hit enemy, Hit self /// </summary> /// <returns></returns> private bool CheckHit() { bool bRes = false; // 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 hit if (sphere.Intersects(selfBox) && currentState != CatapultState.Hit) { AudioManager.PlaySound("catapultExplosion"); // Launch hit animation sequence on self Hit(); enemy.Score++; bRes = true; } // Check if enemy was hit else if (sphere.Intersects(enemyBox) && enemy.Catapult.CurrentState != CatapultState.Hit && enemy.Catapult.CurrentState != CatapultState.Reset) { AudioManager.PlaySound("catapultExplosion"); // Launch enemy hit animaton enemy.Catapult.Hit(); self.Score++; bRes = true; currentState = CatapultState.Reset; } return bRes; }
public override void Update(GameTime gameTime) { bool isGroundHit; CatapultState postUpdateStateChange = 0; if (gameTime == null) throw new ArgumentNullException("gameTime"); if (!IsActive) { base.Update(gameTime); return; } switch (currentState) { case CatapultState.Idle: // Nothing to do break; case CatapultState.Aiming: if (lastUpdateState != CatapultState.Aiming) { // TODO: Play sound AnimationRunning = true; if (isAI == true) { // TODO: Play animation stallUpdateCycles = 20; } } // Progress Aiming "animation" if (isAI == false) { // TODO: Play animation } else { // TODO: Play animation // TODO: take �startStall� into account currentState = (true) ? CatapultState.Stalling : CatapultState.Aiming; } break; case CatapultState.Stalling: if (stallUpdateCycles-- <= 0) { // We've finished stalling, fire the projectile Fire(ShotVelocity); postUpdateStateChange = CatapultState.Firing; } break; case CatapultState.Firing: // Progress Fire animation if (lastUpdateState != CatapultState.Firing) { // TODO: Play Sounds and animate } // TODO: Play animation // TODO: Fire at the appropriate animation frame postUpdateStateChange = currentState | CatapultState.ProjectileFlying; projectile.ProjectilePosition = projectile.ProjectileStartPosition; break; case CatapultState.Firing | CatapultState.ProjectileFlying: // Progress Fire animation // TODO: Play animation // Update projectile velocity & position in flight projectile.UpdateProjectileFlightData(gameTime, wind, gravity, out isGroundHit); if (isGroundHit) { // Start hit sequence postUpdateStateChange = CatapultState.ProjectileHit; // TODO: Play animation } 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; // TODO: Play animation } break; case CatapultState.ProjectileHit: // Check hit on ground impact if (!CheckHit()) { if (lastUpdateState != CatapultState.ProjectileHit) { // TODO: Vibrate device and play sound } // TODO: Relate to animation when changing state postUpdateStateChange = CatapultState.Reset; // TODO: Update animation } else { // TODO: Vibrate the device } break; case CatapultState.Hit: // TODO: only check score when animation is finished if (enemy.Score >= winScore) { GameOver = true; break; } postUpdateStateChange = CatapultState.Reset; // TODO: Update animation break; case CatapultState.Reset: AnimationRunning = false; break; default: break; } lastUpdateState = currentState; if (postUpdateStateChange != 0) { currentState = postUpdateStateChange; } base.Update(gameTime); }
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> /// Function initializes the catapult instance and loads the animations from XML definition sheet /// </summary> public override void Initialize() { // Define initial state of the catapult IsActive = true; AnimationRunning = false; currentState = CatapultState.Idle; stallUpdateCycles = 0; // Load multiple animations form XML definition XDocument doc = XDocument.Load("Content/Textures/Catapults/AnimationsDef.xml"); XName name = XName.Get("Definition"); var definitions = doc.Document.Descendants(name); // Loop over all definitions in XML foreach (var animationDefinition in definitions) { bool?toLoad = null; bool val; if (bool.TryParse(animationDefinition.Attribute("IsAI").Value, out val)) { toLoad = val; } // Check if the animation definition need to be loaded for current catapult if (toLoad == isAI || null == toLoad) { // Get a name of the animation string animatonAlias = animationDefinition.Attribute("Alias").Value; Texture2D texture = curGame.Content.Load <Texture2D>(animationDefinition.Attribute("SheetName").Value); // Get the frame size (width & height) Point frameSize = new Point(); frameSize.X = int.Parse(animationDefinition.Attribute("FrameWidth").Value); frameSize.Y = int.Parse(animationDefinition.Attribute("FrameHeight").Value); // Get the frames sheet dimensions Point sheetSize = new Point(); sheetSize.X = int.Parse(animationDefinition.Attribute("SheetColumns").Value); sheetSize.Y = int.Parse(animationDefinition.Attribute("SheetRows").Value); // If definition has a "SplitFrame" - means that other animation should start here - load it if (null != animationDefinition.Attribute("SplitFrame")) { splitFrames.Add(animatonAlias, int.Parse(animationDefinition.Attribute("SplitFrame").Value)); } // Defing animation speed TimeSpan frameInterval = TimeSpan.FromSeconds((float)1 / int.Parse(animationDefinition.Attribute("Speed").Value)); Animation animation = new Animation(texture, frameSize, sheetSize); // If definition has an offset defined - means that it should be rendered relatively // to some element/other animation - load it if (null != animationDefinition.Attribute("OffsetX") && null != animationDefinition.Attribute("OffsetY")) { animation.Offset = new Vector2(int.Parse(animationDefinition.Attribute("OffsetX").Value), int.Parse(animationDefinition.Attribute("OffsetY").Value)); } animations.Add(animatonAlias, animation); } } // Load the textures idleTexture = curGame.Content.Load <Texture2D>(idleTextureName); // Initialize the projectile Vector2 projectileStartPosition; if (isAI) { projectileStartPosition = new Vector2(630, 340); } else { projectileStartPosition = new Vector2(175, 340); } projectile = new Projectile(curGame, spriteBatch, "Textures/Ammo/rock_ammo", projectileStartPosition, animations["Fire"].FrameSize.Y, isAI, gravity); projectile.Initialize(); // Initialize randomizer random = new Random(); base.Initialize(); }
private bool CheckHit() { bool bRes = false; // Build a sphere around the 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 // TODO: Take asset size into account Vector3 min = new Vector3(catapultPosition, 0); Vector3 max = new Vector3(catapultPosition + new Vector2(75, 60), 0); BoundingBox selfBox = new BoundingBox(min, max); // Check enemy - create a bounding box around the enemy // TODO: Take asset size into account min = new Vector3(enemy.Catapult.Position, 0); max = new Vector3(enemy.Catapult.Position + new Vector2(75, 60), 0); BoundingBox enemyBox = new BoundingBox(min, max); // Check self hit if (sphere.Intersects(selfBox) && currentState != CatapultState.Hit) { // TODO: Play self hit sound // Launch hit animation sequence on self Hit(); enemy.Score++; bRes = true; } // Check if enemy was hit else if (sphere.Intersects(enemyBox) && enemy.Catapult.CurrentState != CatapultState.Hit && enemy.Catapult.CurrentState != CatapultState.Reset) { // TODO: Play enemy hit sound // Launch enemy hit animaton enemy.Catapult.Hit(); self.Score++; bRes = true; currentState = CatapultState.Reset; } return bRes; }
/// <summary> /// Function initializes the catapult instance and loads the animations from XML definition sheet /// </summary> public override void Initialize() { // Define initial state of the catapult IsActive = true; AnimationRunning = false; currentState = CatapultState.Idle; stallUpdateCycles = 0; // Load multiple animations form XML definition XDocument doc = null; #if ANDROID using(var stream = Game.Activity.Assets.Open(@"Content/Textures/Catapults/AnimationsDef.xml")) { doc = XDocument.Load(stream); } #else doc = XDocument.Load("Content/Textures/Catapults/AnimationsDef.xml"); #endif XName name = XName.Get("Definition"); var definitions = doc.Document.Descendants(name); // Loop over all definitions in XML foreach (var animationDefinition in definitions) { bool? toLoad = null; bool val; if (bool.TryParse(animationDefinition.Attribute("IsAI").Value, out val)) toLoad = val; // Check if the animation definition need to be loaded for current catapult if (toLoad == isAI || null == toLoad) { // Get a name of the animation string animatonAlias = animationDefinition.Attribute("Alias").Value; Texture2D texture = curGame.Content.Load<Texture2D>(animationDefinition.Attribute("SheetName").Value); // Get the frame size (width & height) Point frameSize = new Point(); frameSize.X = int.Parse(animationDefinition.Attribute("FrameWidth").Value); frameSize.Y = int.Parse(animationDefinition.Attribute("FrameHeight").Value); // Get the frames sheet dimensions Point sheetSize = new Point(); sheetSize.X = int.Parse(animationDefinition.Attribute("SheetColumns").Value); sheetSize.Y = int.Parse(animationDefinition.Attribute("SheetRows").Value); // If definition has a "SplitFrame" - means that other animation should start here - load it if (null != animationDefinition.Attribute("SplitFrame")) splitFrames.Add(animatonAlias, int.Parse(animationDefinition.Attribute("SplitFrame").Value)); // Defing animation speed TimeSpan frameInterval = TimeSpan.FromSeconds((float)1 / int.Parse(animationDefinition.Attribute("Speed").Value)); Animation animation = new Animation(texture, frameSize, sheetSize); // If definition has an offset defined - means that it should be rendered relatively // to some element/other animation - load it if (null != animationDefinition.Attribute("OffsetX") && null != animationDefinition.Attribute("OffsetY")) { animation.Offset = new Vector2(int.Parse(animationDefinition.Attribute("OffsetX").Value), int.Parse(animationDefinition.Attribute("OffsetY").Value)); } animations.Add(animatonAlias, animation); } } // Load the textures idleTexture = curGame.Content.Load<Texture2D>(idleTextureName); // Initialize the projectile Vector2 projectileStartPosition; if (isAI) projectileStartPosition = new Vector2(630, 340); else projectileStartPosition = new Vector2(175, 340); projectile = new Projectile(curGame, spriteBatch, "Textures/Ammo/rock_ammo", projectileStartPosition, animations["Fire"].FrameSize.Y, isAI, gravity); projectile.Initialize(); // Initialize randomizer random = new Random(); base.Initialize(); }
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); 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); }
public override void Initialize() { // Define initial state of the catapult IsActive = true; AnimationRunning = false; currentState = CatapultState.Idle; stallUpdateCycles = 0; // Load multiple animations form XML definition XDocument doc = XDocument.Load( "Content/Textures/Catapults/AnimationsDef.xml"); XName name = XName.Get("Definition"); var definitions = doc.Document.Descendants(name); // Loop over all definitions in XML foreach (var animationDefinition in definitions) { bool? toLoad = null; bool val; if (bool.TryParse(animationDefinition.Attribute("IsAI").Value, out val)) toLoad = val; // Check if the animation definition need to be loaded // for current catapult if (toLoad == isLeftSide || null == toLoad) { // Get a name of the animation string animatonAlias = animationDefinition.Attribute("Alias").Value; Texture2D texture = curGame.Content.Load<Texture2D>( animationDefinition.Attribute("SheetName").Value); // Get the frame size (width & height) Point frameSize = new Point(); frameSize.X = int.Parse( animationDefinition.Attribute("FrameWidth").Value); frameSize.Y = int.Parse( animationDefinition.Attribute("FrameHeight").Value); // Get the frames sheet dimensions Point sheetSize = new Point(); sheetSize.X = int.Parse( animationDefinition.Attribute("SheetColumns").Value); sheetSize.Y = int.Parse( animationDefinition.Attribute("SheetRows").Value); // If definition has a "SplitFrame" - means that other // animation should start here - load it if (null != animationDefinition.Attribute("SplitFrame")) splitFrames.Add(animatonAlias, int.Parse( animationDefinition.Attribute("SplitFrame").Value)); // Defing animation speed TimeSpan frameInterval = TimeSpan.FromSeconds((float)1 / int.Parse(animationDefinition.Attribute("Speed").Value)); // TODO: Construct animations // If definition has an offset defined - means that it should // be rendered relatively to some element/other animation - // load it if (null != animationDefinition.Attribute("OffsetX") && null != animationDefinition.Attribute("OffsetY")) { // TODO: Set animation offset } // TODO: Add animation alias } } // Load the textures idleTexture = curGame.Content.Load<Texture2D>(idleTextureName); activeProjectiles = new List<Projectile>(MaxActiveProjectiles); activeProjectilesCopy = new List<Projectile>(MaxActiveProjectiles); destroyedProjectiles = new List<Projectile>(MaxActiveProjectiles); // TODO: Update normalProjectile instantiation normalProjectile = new Projectile(curGame, spriteBatch, activeProjectiles, "Textures/Ammo/rock_ammo", ProjectileStartPosition, 0, isLeftSide, gravity); normalProjectile.Initialize(); // TODO: Add split projectile // TODO: Add SupplyCrate // Initialize randomizer random = new Random(); base.Initialize(); }
/// <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(0, 0), 0); // TODO: Support fire size BoundingBox selfBox = new BoundingBox(min, min); // Check enemy - create a bounding box around the enemy min = new Vector3(enemy.Catapult.Position, 0); max = new Vector3(enemy.Catapult.Position + new Vector2(0, 0), 0); // TODO: Support fire size BoundingBox enemyBox = new BoundingBox(min, min); // Check self-crate - Create bounding box around own crate // TODO: Check self crate // Check enemy-crate - Create bounding box around enemy crate // TODO: Check enemy crate // Check self hit if (sphere.Intersects(selfBox) && currentState != CatapultState.HitKill) { // TODO: Play explosion sound // 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) { // TODO: Play explosion sound // 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 // TODO: Handle crate checking return hitRes; }
/// <summary> /// Start Hit sequence on catapult - could be executed on self or from enemy in case of hit /// </summary> public void Hit(bool isKilled) { AnimationRunning = true; if (isKilled) animations["Destroyed"].PlayFromFrameIndex(0); animations["hitSmoke"].PlayFromFrameIndex(0); if (isKilled) currentState = CatapultState.HitKill; else currentState = CatapultState.HitDamage; self.Weapon = WeaponType.Normal; }