private static ObjectAction GetPhase3Action( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, Dictionary <string, DTDanmakuSound> soundNameToSoundDictionary, GuidGenerator guidGenerator) { string milliHpVariable = guidGenerator.NextGuid(); string amountOfDamageTakenVariableName = guidGenerator.NextGuid(); ObjectAction setInitialDamageTakenAction = ObjectActionGenerator.DoOnce(ObjectAction.SetNumericVariable(amountOfDamageTakenVariableName, MathExpression.Constant(0))); ObjectAction setInitialMilliHpVariable = ObjectActionGenerator.DoOnce(ObjectAction.SetNumericVariable(milliHpVariable, MathExpression.MilliHP())); ObjectAction setDamageTakenVariableAction = ObjectAction.SetNumericVariable( amountOfDamageTakenVariableName, MathExpression.Add( MathExpression.Variable(amountOfDamageTakenVariableName), MathExpression.Subtract(MathExpression.Variable(milliHpVariable), MathExpression.MilliHP()))); ObjectAction setMilliHpVariable = ObjectAction.SetNumericVariable(milliHpVariable, MathExpression.MilliHP()); long phase3InitialMilliHp = 200 * 1000; IMathExpression currentMilliHp = MathExpression.Max( MathExpression.Subtract(MathExpression.Constant(phase3InitialMilliHp), MathExpression.Variable(amountOfDamageTakenVariableName)), MathExpression.Constant(0)); ObjectAction displayHpBarAction = ObjectAction.DisplayBossHealthBar( healthBarMeterNumber: MathExpression.Constant(1), healthBarMilliPercentage: MathExpression.Divide(MathExpression.Multiply(currentMilliHp, MathExpression.Constant(100 * 1000)), MathExpression.Constant(phase3InitialMilliHp))); string soundEffectName = guidGenerator.NextGuid(); ObjectAction playEnemyDeathSoundEffectAction = ObjectAction.PlaySoundEffect(soundEffectName: soundEffectName); soundNameToSoundDictionary.Add(soundEffectName, DTDanmakuSound.EnemyDeath); DestructionAnimationGenerator.GenerateDestructionAnimationResult generateDestructionAnimationResult = DestructionAnimationGenerator.GenerateDestructionAnimation( orderedSprites: new List <DTDanmakuImage> { DTDanmakuImage.Explosion1, DTDanmakuImage.Explosion2, DTDanmakuImage.Explosion3, DTDanmakuImage.Explosion4, DTDanmakuImage.Explosion5, DTDanmakuImage.Explosion6, DTDanmakuImage.Explosion7, DTDanmakuImage.Explosion8, DTDanmakuImage.Explosion9 }, millisecondsPerSprite: 20, guidGenerator: guidGenerator); foreach (var entry in generateDestructionAnimationResult.spriteNameToImageDictionary) { spriteNameToImageDictionary.Add(entry.Key, entry.Value); } foreach (var entry in generateDestructionAnimationResult.enemyObjectTemplates) { enemyObjectTemplates.Add(entry.Key, entry.Value); } ObjectAction destroyBoss = ObjectAction.Union( playEnemyDeathSoundEffectAction, generateDestructionAnimationResult.objectAction, ObjectAction.Destroy()); ObjectAction destroyAndEndLevelAction = ObjectAction.Condition( condition: BooleanExpression.Equal(currentMilliHp, MathExpression.Constant(0)), action: ObjectAction.Union( ObjectAction.EndLevel(), destroyBoss)); ObjectAction shootBulletAction = Phase3ShootAction( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, guidGenerator: guidGenerator); return(ObjectAction.Union( setInitialDamageTakenAction, setInitialMilliHpVariable, setDamageTakenVariableAction, setMilliHpVariable, displayHpBarAction, GetMoveAction(guidGenerator: guidGenerator), destroyAndEndLevelAction, shootBulletAction)); }
public static ObjectAction DestroyWhenHpIsZeroAndMaybeDropPowerUp( long chanceToDropPowerUpInMilliPercent, // ranges from 0 (meaning 0%) to 100,000 (meaning 100%) Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, Dictionary <string, DTDanmakuSound> soundNameToSoundDictionary, GuidGenerator guidGenerator) { string soundEffectName = guidGenerator.NextGuid(); BooleanExpression isHpZero = BooleanExpression.LessThanOrEqualTo( MathExpression.MilliHP(), MathExpression.Constant(0)); ObjectAction playEnemyDeathSoundEffectAction = ObjectAction.PlaySoundEffect(soundEffectName: soundEffectName); soundNameToSoundDictionary.Add(soundEffectName, DTDanmakuSound.EnemyDeath); DestructionAnimationGenerator.GenerateDestructionAnimationResult generateDestructionAnimationResult = DestructionAnimationGenerator.GenerateDestructionAnimation( orderedSprites: new List <DTDanmakuImage> { DTDanmakuImage.Explosion1, DTDanmakuImage.Explosion2, DTDanmakuImage.Explosion3, DTDanmakuImage.Explosion4, DTDanmakuImage.Explosion5, DTDanmakuImage.Explosion6, DTDanmakuImage.Explosion7, DTDanmakuImage.Explosion8, DTDanmakuImage.Explosion9 }, millisecondsPerSprite: 20, guidGenerator: guidGenerator); foreach (var entry in generateDestructionAnimationResult.spriteNameToImageDictionary) { spriteNameToImageDictionary.Add(entry.Key, entry.Value); } foreach (var entry in generateDestructionAnimationResult.enemyObjectTemplates) { enemyObjectTemplates.Add(entry.Key, entry.Value); } ObjectAction possiblySpawnPowerUpAction = ObjectAction.Condition( condition: BooleanExpression.LessThan( MathExpression.RandomInteger(MathExpression.Constant(100 * 1000)), MathExpression.Constant(chanceToDropPowerUpInMilliPercent)), action: ObjectAction.SpawnPowerUp()); return(ObjectAction.Condition( condition: isHpZero, action: ObjectAction.Union( playEnemyDeathSoundEffectAction, generateDestructionAnimationResult.objectAction, possiblySpawnPowerUpAction, ObjectAction.Destroy()))); }
public GameLogic( int fps, IDTDeterministicRandom rng, GuidGenerator guidGenerator, int soundVolume, bool debugMode) { this.fps = fps; this.elapsedTimeMillis = 0; long elapsedMillisPerFrame = 1000 / this.fps; this.soundVolume = soundVolume; this.debugMode = debugMode; this.rng = rng; this.rng.Reset(); this.spriteNameToImageDictionary = new Dictionary <string, DTDanmakuImage>(); this.enemyObjectTemplates = new Dictionary <string, EnemyObjectTemplate>(); this.soundNameToSoundDictionary = new Dictionary <string, DTDanmakuSound>(); List <DTDanmakuImage> playerDeadExplosionSprites = new List <DTDanmakuImage>(); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion1); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion2); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion3); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion4); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion5); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion6); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion7); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion8); playerDeadExplosionSprites.Add(DTDanmakuImage.Explosion9); DestructionAnimationGenerator.GenerateDestructionAnimationResult playerDeadDestructionAnimationResult = DestructionAnimationGenerator.GenerateDestructionAnimation( orderedSprites: playerDeadExplosionSprites, millisecondsPerSprite: 200, guidGenerator: guidGenerator); foreach (var entry in playerDeadDestructionAnimationResult.spriteNameToImageDictionary) { this.spriteNameToImageDictionary.Add(entry.Key, entry.Value); } foreach (var entry in playerDeadDestructionAnimationResult.enemyObjectTemplates) { this.enemyObjectTemplates.Add(entry.Key, entry.Value); } this.player = new Player(playerDeadDestructionAnimationResult.objectAction); this.playerBullets = new List <PlayerBullet>(); this.powerUps = new List <PowerUp>(); GenerateEnemiesResult enemies = GenerateEnemiesForLevel.GenerateEnemies( elapsedMillisecondsPerIteration: elapsedMillisPerFrame, rng: rng, guidGenerator: guidGenerator); this.enemyObjects = enemies.enemyObjects; foreach (var entry in enemies.spriteNameToImageDictionary) { this.spriteNameToImageDictionary.Add(entry.Key, entry.Value); } foreach (var entry in enemies.enemyObjectTemplates) { this.enemyObjectTemplates.Add(entry.Key, entry.Value); } foreach (var entry in enemies.soundNameToSoundDictionary) { this.soundNameToSoundDictionary.Add(entry.Key, entry.Value); } this.gameOverCountdownInMillis = null; this.levelFinishedCountdownInMillis = null; this.shouldPlayPlayerShootSound = false; this.playerShootSoundCooldownInMillis = 0; this.soundsThatNeedToBePlayed = new List <DTDanmakuSound>(); this.bossHealthBar = new BossHealthBar(); /* * Note that since these debug things bypass regular game logic, they may break other stuff or crash the program * (Should be used for debugging / development only) */ if (this.debugMode) { this.player.numLivesLeft = 200; } this.debug_renderHitboxes = false; }