/// <summary> /// takes the destruction action. /// </summary> /// <param name="attackerPosition">the position of attacker</param> public override void ActionDead(Vector3 attackerPosition) { engageAction = Action.Dead; MoveStop(); // Remove collision colLayerEnemyMech.RemoveCollide(this.Collide); colLayerAllMech.RemoveCollide(this.Collide); GameSound.Stop(soundMove); soundDestroy1 = GameSound.Play3D(SoundTrack.DestroyHeavyMech1, this); Matrix world = Matrix.CreateTranslation(WorldTransform.Translation); GameParticle.PlayParticle(ParticleType.DestroyTank1, world, Matrix.Identity); Material.alpha = 1.0f; Material.diffuseColor = Color.Black; Material.specularColor = Color.Black; Material.emissiveColor = Color.Black; Material.vertexColorEnabled = true; this.SourceBlend = Blend.SourceAlpha; this.DestinationBlend = Blend.InverseSourceAlpha; this.AlphaBlendEnable = true; this.ReferenceAlpha = 0; // AI process stop AIContext.Enabled = false; turretAngleSpeed = 0.0f; }
/// <summary> /// takes the destruction action. /// </summary> /// <param name="attackerPosition">the position of attacker</param> public override void ActionDead(Vector3 attackerPosition) { Vector3 dir = Vector3.Normalize(attackerPosition - Position); float FrontDot = Vector3.Dot(Direction, dir); float RightDot = Vector3.Dot(Right, dir); if (FrontDot > 0.5f) { // Hit from front engageAction = Action.BackwardDead; } else if (FrontDot < -0.5f) { // Hit from back engageAction = Action.ForwardDead; } else if (RightDot >= 0.0f) { // Hit from right engageAction = Action.LeftDead; } else if (RightDot < 0.0f) { // Hit from left engageAction = Action.RightDead; } soundDestroy1 = GameSound.Play3D(SoundTrack.DestroyHeavyMech1, this); Matrix world = Matrix.CreateTranslation(WorldTransform.Translation); GameParticle.PlayParticle(ParticleType.DestroyHeavyMech1, world, Matrix.Identity); // Remove collision colLayerEnemyMech.RemoveCollide(Collide); MoveStop(); GameSound.Stop(soundMove); Material.alpha = 1.0f; Material.diffuseColor = Color.Black; Material.specularColor = Color.Black; Material.emissiveColor = Color.Black; Material.vertexColorEnabled = true; this.SourceBlend = Blend.SourceAlpha; this.DestinationBlend = Blend.InverseSourceAlpha; this.AlphaBlendEnable = true; this.ReferenceAlpha = 0; // AI process stop AIContext.Enabled = false; }
/// <summary> /// tank's A.I. function. /// moves to the position and stops when collides with others. /// </summary> /// <param name="aiBase">current A.I.</param> /// <param name="gameTime"></param> public override void OnAIMoveEvent(AIBase aiBase, GameTime gameTime) { if (aiBase.IsActive) { Vector3 vMoveVelocity = new Vector3(0.0f, 0.0f, SpecData.MoveSpeed); CollisionResult result = MoveHitTest(gameTime, vMoveVelocity); if (result != null) { if (GameSound.IsPlaying(soundMove)) { GameSound.Stop(soundMove); } MoveStop(); // Cannot move } else { Move(vMoveVelocity); if (!GameSound.IsPlaying(soundMove)) { soundMove = GameSound.Play3D(SoundTrack.TankMove, this); } } } else { if (GameSound.IsPlaying(soundMove)) { GameSound.Stop(soundMove); } MoveStop(); turretAngleSpeed = 0.0f; SetNextAI(AIType.Search, HelperMath.RandomNormal()); } }
/// <summary> /// reloads weapon. /// plays reloading particle depending on unit type. /// </summary> /// <param name="type">unit type</param> /// <returns></returns> public bool Reload(UnitTypeId type) { this.state = WeaponState.Reloading; ParticleType reloadParticle = ParticleType.Count; SoundTrack reloadSound = SoundTrack.Count; switch (this.WeaponType) { case WeaponType.PlayerMachineGun: { reloadParticle = ParticleType.PlayerMachineGunReload; switch (type) { case UnitTypeId.Grund: case UnitTypeId.Kiev: reloadSound = SoundTrack.PlayerMachineGunGrundReload; break; case UnitTypeId.Mark: case UnitTypeId.Yager: reloadSound = SoundTrack.PlayerMachineGunMarkReload; break; } } break; case WeaponType.PlayerShotgun: { // Shotgun reload is no particle reloadSound = SoundTrack.PlayerShotgunReload; } break; case WeaponType.PlayerHandgun: { reloadParticle = ParticleType.PlayerHandgunReload; reloadSound = SoundTrack.PlayerHandgunReload; } break; } // Play a reloading particle if (reloadParticle != ParticleType.Count) { for (int i = 0; i < SpecData.ModelCount; i++) { int boneIdx = -1; Matrix boneTransform = Matrix.Identity; boneIdx = this.indexWeaponFireDummy[i]; boneTransform = modelWeapon[i].BoneTransforms[boneIdx]; if (reloadParticle != ParticleType.Count) { GameParticle.PlayParticle(reloadParticle, boneTransform, Matrix.CreateRotationX(MathHelper.ToRadians(-90.0f))); } } } switch (this.WeaponType) { case WeaponType.PlayerMachineGun: { if (GameSound.IsPlaying(soundFire)) { GameSound.Stop(soundFire); } } break; } // Play a reload sound if (reloadSound != SoundTrack.Count) { if (RobotGameGame.CurrentGameLevel.Info.GamePlayType == GamePlayTypeId.Versus) { soundReload = GameSound.Play3D(reloadSound, RobotGameGame.SinglePlayer.Emitter); } else { soundReload = GameSound.Play3D(reloadSound, this.OwnerUnit.Emitter); } } return(true); }
/// <summary> /// checks for the collision at the aiming angle. /// If it collides with an enemy mech, calls ActionHit() function. /// Weapon’s collision checks the world and enemy both. /// When playing firing particle, the number of the weapon’s model /// must be considered. /// Since the player’s weapon is a dual weapon system, there are two models. /// However, for enemies, there are enemies with single weapon system. /// Therefore, it plays firing particle at the gun point /// as many as the number of models. /// </summary> /// <param name="position">the start position of firing</param> /// <param name="direction">the direction of firing</param> /// <param name="distance">the range of firing</param> /// <param name="targetCollisionLayer">target collision layer</param> /// <param name="worldCollisionLayer">world collision layer</param> /// <param name="fireBone1">the fire matrix of first weapon</param> /// <param name="fireBone2">the fire matrix of second weapon</param> /// <returns></returns> public bool Fire(Vector3 position, Vector3 direction, float distance, ref CollisionLayer targetCollisionLayer, ref CollisionLayer worldCollisionLayer, Matrix?fireBone1, Matrix?fireBone2) { bool hit = false; Vector3 firePosition = Vector3.Zero; Vector3 targetPosition = position + (direction * distance); SoundTrack fireSound = SoundTrack.Count; ParticleType fireParticle = ParticleType.Count; ParticleType unitHitParticle = ParticleType.Count; ParticleType worldHitParticle = ParticleType.Count; Matrix fixedAxis = Matrix.CreateRotationX(MathHelper.ToRadians(-90.0f)); this.state = WeaponState.Firing; if (this.currentAmmo <= 0) { return(hit); } // Reduces a bullet. this.currentAmmo--; switch (this.WeaponType) { case WeaponType.PlayerMachineGun: { fireSound = SoundTrack.PlayerMachineGunFire; fireParticle = ParticleType.PlayerMachineGunFire; unitHitParticle = ParticleType.PlayerMachineGunUnitHit; worldHitParticle = ParticleType.PlayerMachineGunWorldHit; } break; case WeaponType.PlayerShotgun: { fireSound = SoundTrack.PlayerShotgunFire; fireParticle = ParticleType.PlayerShotgunFire; unitHitParticle = ParticleType.PlayerShotgunUnitHit; worldHitParticle = ParticleType.PlayerShotgunWorldHit; } break; case WeaponType.PlayerHandgun: { fireSound = SoundTrack.PlayerHandgunFire; fireParticle = ParticleType.PlayerHandgunFire; unitHitParticle = ParticleType.PlayerHandgunUnitHit; worldHitParticle = ParticleType.PlayerHandgunWorldHit; } break; case WeaponType.CameleerGun: { fireSound = SoundTrack.CameleerFire; fireParticle = ParticleType.EnemyGunFire; unitHitParticle = ParticleType.EnemyGunUnitHit; worldHitParticle = ParticleType.EnemyGunWorldHit; } break; case WeaponType.MaomingGun: { fireSound = SoundTrack.MaomingFire; fireParticle = ParticleType.PlayerMachineGunFire; unitHitParticle = ParticleType.EnemyGunUnitHit; worldHitParticle = ParticleType.EnemyGunWorldHit; } break; case WeaponType.DuskmasCannon: { fireSound = SoundTrack.DuskmasFire; fireParticle = ParticleType.EnemyCannonFire; unitHitParticle = ParticleType.EnemyCannonUnitHit; worldHitParticle = ParticleType.EnemyCannonWorldHit; } break; case WeaponType.TigerCannon: { fireSound = SoundTrack.TankFire; fireParticle = ParticleType.EnemyCannonFire; unitHitParticle = ParticleType.EnemyCannonUnitHit; worldHitParticle = ParticleType.EnemyCannonWorldHit; } break; case WeaponType.HammerCannon: { fireSound = SoundTrack.HammerFire; fireParticle = ParticleType.EnemyCannonFire; unitHitParticle = ParticleType.EnemyCannonUnitHit; worldHitParticle = ParticleType.EnemyCannonWorldHit; } break; case WeaponType.PhantomMelee: { fireSound = SoundTrack.BossMelee; fireParticle = ParticleType.Count; unitHitParticle = ParticleType.EnemyMeleeUnitHit; worldHitParticle = ParticleType.EnemyCannonWorldHit; } break; } if (this.WeaponType != WeaponType.PlayerShotgun && this.WeaponType != WeaponType.PlayerHandgun) { StopFireSound(); } // Play a weapon firing sound if (RobotGameGame.CurrentGameLevel.Info.GamePlayType == GamePlayTypeId.Versus) { soundFire = GameSound.Play3D(fireSound, RobotGameGame.SinglePlayer.Emitter); } else { soundFire = GameSound.Play3D(fireSound, this.OwnerUnit.Emitter); } // Play firing particles if (specData.ModelAlone) { // Multi fire if (this.SpecData.FireCount == 1) { for (int i = 0; i < SpecData.ModelCount; i++) { int boneIdx = indexWeaponFireDummy[i]; Matrix boneTransform = modelWeapon[i].BoneTransforms[boneIdx]; GameParticle.PlayParticle(fireParticle, boneTransform, fixedAxis); } // In case of two handed weapons, the index is changed // so that the tracer bullet will fire alternatively. if (dummySwichingIndex == 0) { dummySwichingIndex = 1; } else { dummySwichingIndex = 0; } int boneIndex = indexWeaponFireDummy[dummySwichingIndex]; firePosition = modelWeapon[dummySwichingIndex].BoneTransforms[ boneIndex].Translation; } // Delayed fire else { if (this.fireCount == 0) { GameParticle.PlayParticle(fireParticle, this.RightFireBone, fixedAxis); firePosition = this.RightFireBone.Translation; } else if (this.fireCount == 1) { GameParticle.PlayParticle(fireParticle, this.LeftFireBone, fixedAxis); firePosition = this.LeftFireBone.Translation; } } } else { Matrix fireMatrix = Matrix.Identity; if (fireBone1 != null) { GameParticle.PlayParticle(fireParticle, (Matrix)fireBone1, fixedAxis); } if (fireBone2 != null) { GameParticle.PlayParticle(fireParticle, (Matrix)fireBone2, fixedAxis); } if (fireBone1 != null && fireBone2 != null) { // In case of two handed weapons, the index is changed // so that the tracer bullet will fire alternatively. if (dummySwichingIndex == 0) { fireMatrix = (Matrix)fireBone1; dummySwichingIndex = 1; } else { fireMatrix = (Matrix)fireBone2; dummySwichingIndex = 0; } } else if (fireBone1 != null) { fireMatrix = (Matrix)fireBone1; } else if (fireBone2 != null) { fireMatrix = (Matrix)fireBone2; } firePosition = fireMatrix.Translation; } // Hit testing CollisionResult collideResult = FireHitTest(position, direction, distance, ref targetCollisionLayer, ref worldCollisionLayer); if (collideResult != null) { // Play hitting particle { ParticleType hitParticle = ParticleType.Count; // To player if (collideResult.detectedCollide.Owner is GameUnit) { GameUnit detectGameUnit = collideResult.detectedCollide.Owner as GameUnit; // Calculate a random intersect point for // hitting particle in unit sphere CollideSphere sphere = collideResult.detectedCollide as CollideSphere; switch (this.WeaponType) { case WeaponType.PlayerMachineGun: case WeaponType.PlayerShotgun: case WeaponType.PlayerHandgun: case WeaponType.CameleerGun: case WeaponType.MaomingGun: { Vector3 dir = this.OwnerUnit.Position - detectGameUnit.Position; dir.Normalize(); dir.X += HelperMath.RandomNormal2(); dir.Y += HelperMath.RandomNormal2(); dir.Normalize(); collideResult.normal = (Vector3)dir; collideResult.intersect = sphere.BoundingSphere.Center + ((Vector3)dir * sphere.Radius); } break; case WeaponType.DuskmasCannon: case WeaponType.HammerCannon: case WeaponType.TigerCannon: case WeaponType.PhantomMelee: { Vector3 dir = this.OwnerUnit.Position - sphere.BoundingSphere.Center; dir.Normalize(); collideResult.normal = (Vector3)dir; collideResult.intersect = sphere.BoundingSphere.Center; } break; } hitParticle = unitHitParticle; targetPosition = (Vector3)collideResult.intersect; } // To world else { hitParticle = worldHitParticle; targetPosition = (Vector3)collideResult.intersect; } if (collideResult.normal != null) { GameParticle.PlayParticle(hitParticle, (Vector3)collideResult.intersect, (Vector3)collideResult.normal, Matrix.CreateRotationX(MathHelper.ToRadians(-90.0f))); } else { GameParticle.PlayParticle(hitParticle, Matrix.CreateTranslation((Vector3)collideResult.intersect), Matrix.CreateRotationX(MathHelper.ToRadians(-90.0f))); } } // Hit to other mech if (collideResult.detectedCollide.Owner is GameUnit) { GameUnit HitUnit = (GameUnit)collideResult.detectedCollide.Owner; // Call hit function to unit HitUnit.ActionHit(this.OwnerUnit); if (HitUnit.IsDead) { if (this.OwnerUnit is GamePlayer) { // If the versus mode, you'll be get kill point if (RobotGameGame.CurrentStage is VersusStageScreen) { VersusStageScreen stage = RobotGameGame.CurrentStage as VersusStageScreen; GamePlayer player = this.OwnerUnit as GamePlayer; player.KillPoint++; stage.DisplayKillPoint((int)player.PlayerIndex, player.KillPoint); } } } hit = true; } } // Fire the tracer bullet particle if (this.specData.TracerBulletFire) { RobotGameGame.CurrentStage.TracerBulletManager.Fire(0, firePosition, targetPosition, this.specData.TracerBulletSpeed, this.specData.TracerBulletLength, this.specData.TracerBulletThickness, true); } // Cannot fire return(hit); }
/// <summary> /// processes the current action info. /// </summary> /// <param name="gameTime"></param> protected void ProcessAction(GameTime gameTime) { switch (CurrentAction) { // Playing damage animation process case Action.Damage: { // Return to idle state ActionIdle(); this.actionElapsedTime = 0.0f; } break; case Action.Fire: { if (this.actionElapsedTime >= CurrentWeapon.SpecData.FireIntervalTime) { // Return to idle state ActionIdle(); this.actionElapsedTime = 0.0f; } else { this.actionElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } } break; case Action.Reload: { if (this.actionElapsedTime >= CurrentWeapon.SpecData.ReloadIntervalTime) { // Return to idle state ActionIdle(); this.actionElapsedTime = 0.0f; } else { this.actionElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } } break; // Playing dead animation process case Action.Dead: { const float duration = 1.0f; const float secondDestroyGap = 1.0f; if (this.actionElapsedTime < duration + secondDestroyGap) { if (this.actionElapsedTime >= secondDestroyGap) { Material.alpha = ((duration + secondDestroyGap) - this.actionElapsedTime) / secondDestroyGap; // Second destroy particle if (GameSound.IsPlaying(soundDestroy2) == false) { soundDestroy2 = GameSound.Play3D( SoundTrack.DestroyHeavyMech2, this); Matrix world = Matrix.CreateTranslation( WorldTransform.Translation); GameParticle.PlayParticle(ParticleType.DestroyTank2, world, Matrix.Identity); } } } if (this.actionElapsedTime >= duration + secondDestroyGap) { this.Enabled = false; this.Visible = false; } else { this.actionElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } } break; } }
/// <summary> /// decides the moving animation according to velocity. /// </summary> /// <param name="gameTime"></param> /// <param name="vMoveVelocity"></param> public void ActionMovement(GameTime gameTime, Vector3 vMoveVelocity) { bool canMove = true; // Forward if (vMoveVelocity.Z > 0.0f) { if (CurrentAction != Action.ForwardWalk) { engageAction = Action.ForwardWalk; } } // Backward else if (vMoveVelocity.Z < 0.0f) { if (CurrentAction != Action.BackwardWalk) { engageAction = Action.BackwardWalk; } } else if (vMoveVelocity.X > 0.0f) { if (CurrentAction != Action.RightWalk) { engageAction = Action.RightWalk; } } // Backward else if (vMoveVelocity.X < 0.0f) { if (CurrentAction != Action.LeftWalk) { engageAction = Action.LeftWalk; } } // Move Stop else { canMove = false; ActionIdle(); } if (canMove) { // Play a moving sound if (engageAction == Action.ForwardWalk || engageAction == Action.BackwardWalk || engageAction == Action.RightWalk || engageAction == Action.LeftWalk) { if ((CurrentAction != Action.ForwardWalk && CurrentAction != Action.BackwardWalk && CurrentAction != Action.RightWalk && CurrentAction != Action.LeftWalk) || moveElapsedTime == 0.0f) { GameSound.Stop(soundMove); soundMove = GameSound.Play3D(SoundTrack.BossWalk, this); moveElapsedTime = 0.0f; } // Calculate run animation playing time for run sound if (moveDurationTime > moveElapsedTime) { moveElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } else { moveElapsedTime = 0.0f; } } } else { if (GameSound.IsPlaying(soundMove)) { GameSound.Stop(soundMove); } } }
/// <summary> /// determines the animation according to velocity. /// </summary> /// <param name="gameTime"></param> /// <param name="vMoveVelocity"></param> public void ActionMovement(GameTime gameTime, Vector3 vMoveVelocity) { bool canMove = true; // Forward if (vMoveVelocity.Z > 0.0f) { if (CurrentAction != Action.ForwardWalk) { engageAction = Action.ForwardWalk; } } // Backward else if (vMoveVelocity.Z < 0.0f) { if (CurrentAction != Action.BackwardWalk) { engageAction = Action.BackwardWalk; } } else if (vMoveVelocity.X > 0.0f) { if (CurrentAction != Action.RightWalk) { engageAction = Action.RightWalk; } } // Backward else if (vMoveVelocity.X < 0.0f) { if (CurrentAction != Action.LeftWalk) { engageAction = Action.LeftWalk; } } // Move Stop else { canMove = false; ActionIdle(); } SoundTrack moveSound = SoundTrack.CameleerWalk; switch (this.UnitType) { case UnitTypeId.Cameleer: moveSound = SoundTrack.CameleerWalk; break; case UnitTypeId.Maoming: moveSound = SoundTrack.MaomingWalk; break; case UnitTypeId.Duskmas: moveSound = SoundTrack.DuskmasWalk; break; case UnitTypeId.Tiger: moveSound = SoundTrack.TankMove; break; case UnitTypeId.Hammer: moveSound = SoundTrack.HammerWalk; break; } if (canMove) { // Play a moving sound if (engageAction == Action.ForwardWalk || engageAction == Action.BackwardWalk || engageAction == Action.RightWalk || engageAction == Action.LeftWalk) { if ((CurrentAction != Action.ForwardWalk && CurrentAction != Action.BackwardWalk && CurrentAction != Action.RightWalk && CurrentAction != Action.LeftWalk) || moveElapsedTime == 0.0f) { GameSound.Stop(soundMove); soundMove = GameSound.Play3D(moveSound, this); moveElapsedTime = 0.0f; } // Calculate run animation playing time for run sound if (moveDurationTime > moveElapsedTime) { moveElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } else { moveElapsedTime = 0.0f; } } } else { if (GameSound.IsPlaying(soundMove)) { GameSound.Stop(soundMove); } } }
/// <summary> /// processes the current action info. /// </summary> /// <param name="gameTime"></param> protected void ProcessAction(GameTime gameTime) { switch (CurrentAction) { // Playing damage animation process case Action.Damage: { AnimationSequence animation = GetAnimation(indexAnimation[(int)CurrentAction]); if (this.actionElapsedTime >= animation.Duration) { // Return to idle state ActionIdle(); this.actionElapsedTime = 0.0f; } else { this.actionElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } } break; case Action.Fire: case Action.Melee: { if (this.actionElapsedTime >= CurrentWeapon.SpecData.FireIntervalTime) { // Return to idle state ActionIdle(); this.actionElapsedTime = 0.0f; } else { this.actionElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } } break; case Action.Reload: { if (this.actionElapsedTime >= CurrentWeapon.SpecData.ReloadIntervalTime) { // Return to idle state ActionIdle(); this.actionElapsedTime = 0.0f; } else { this.actionElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } } break; // Playing dead animation process case Action.ForwardDead: case Action.BackwardDead: case Action.LeftDead: case Action.RightDead: { AnimationSequence animation = GetAnimation(indexAnimation[(int)CurrentAction]); const float secondDestroyGap = 0.5f; if (this.actionElapsedTime < animation.Duration + secondDestroyGap) { if (this.actionElapsedTime >= animation.Duration - 0.5f) { ParticleType type = ParticleType.Count; SoundTrack sound = SoundTrack.DestroyLightMech2; Material.alpha = ((animation.Duration + secondDestroyGap) - this.actionElapsedTime) / secondDestroyGap; switch (this.UnitClass) { case UnitClassId.LightMech: { sound = SoundTrack.DestroyLightMech2; type = ParticleType.DestroyLightMech2; } break; case UnitClassId.HeavyMech: { sound = SoundTrack.DestroyHeavyMech2; type = ParticleType.DestroyHeavyMech2; } break; } ; // Second destroy particle if (GameSound.IsPlaying(soundDestroy2) == false) { soundDestroy2 = GameSound.Play3D(sound, this); Matrix world = Matrix.CreateTranslation( WorldTransform.Translation); GameParticle.PlayParticle(type, world, Matrix.Identity); } } } if (this.actionElapsedTime >= animation.Duration + secondDestroyGap) { this.Enabled = false; this.Visible = false; } else { this.actionElapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds; } } break; } }