private static ObjectAction Phase3ShootAction( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, GuidGenerator guidGenerator) { string angleVariable = guidGenerator.NextGuid(); string shootCooldownVariable = guidGenerator.NextGuid(); ObjectAction initializeAngleVariable = ObjectActionGenerator.DoOnce( ObjectAction.SetNumericVariable(angleVariable, MathExpression.Constant(0))); ObjectAction updateAngleVariableAction = ObjectAction.Union( ObjectAction.SetNumericVariable( angleVariable, MathExpression.Add(MathExpression.Variable(angleVariable), MathExpression.Multiply(MathExpression.Constant(431), MathExpression.ElapsedMillisecondsPerIteration()))), ObjectAction.Condition( condition: BooleanExpression.GreaterThan(MathExpression.Variable(angleVariable), MathExpression.Constant(360 * 1000)), action: ObjectAction.SetNumericVariable(angleVariable, MathExpression.Subtract(MathExpression.Variable(angleVariable), MathExpression.Constant(360 * 1000)))), ObjectAction.Condition( condition: BooleanExpression.GreaterThan(MathExpression.Variable(angleVariable), MathExpression.Constant(360 * 1000)), action: ObjectAction.SetNumericVariable(angleVariable, MathExpression.Constant(0)))); ObjectAction createBulletAction1 = SpawnPhase3Bullet( bulletDirectionInMillidegrees: MathExpression.Multiply(MathExpression.ParentVariable(angleVariable), MathExpression.Constant(1)), spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, guidGenerator: guidGenerator); ObjectAction createBulletAction2 = SpawnPhase3Bullet( bulletDirectionInMillidegrees: MathExpression.Multiply(MathExpression.ParentVariable(angleVariable), MathExpression.Constant(-1)), spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, guidGenerator: guidGenerator); IMathExpression shootCooldownInMillis = MathExpression.Constant(20); ObjectAction startCooldownAction = ObjectAction.SetNumericVariable(shootCooldownVariable, shootCooldownInMillis); ObjectAction decrementCooldownAction = ObjectAction.SetNumericVariable(shootCooldownVariable, MathExpression.Subtract(MathExpression.Variable(shootCooldownVariable), MathExpression.ElapsedMillisecondsPerIteration())); ObjectAction createBulletWhenCooldownFinishedAction = ObjectAction.Condition( condition: BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(shootCooldownVariable), MathExpression.Constant(0)), action: ObjectAction.Union(startCooldownAction, createBulletAction1, createBulletAction2)); return(ObjectAction.Union( initializeAngleVariable, updateAngleVariableAction, ObjectActionGenerator.DoOnce(ObjectAction.SetNumericVariable(shootCooldownVariable, MathExpression.Constant(1000))), decrementCooldownAction, createBulletWhenCooldownFinishedAction)); }
public static ObjectAction BulletStraightDownAction( long bulletSpeedInPixelsPerSecond) { var enemyBulletMovementAction = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Add( MathExpression.YMillis(), MathExpression.Multiply( MathExpression.Constant(-bulletSpeedInPixelsPerSecond), MathExpression.ElapsedMillisecondsPerIteration()))); var enemyBulletDestroyAction = ObjectAction.Condition( condition: BooleanExpression.LessThanOrEqualTo(MathExpression.YMillis(), MathExpression.Constant(-700 * 1000)), action: ObjectAction.Destroy()); return(ObjectAction.Union(enemyBulletMovementAction, enemyBulletDestroyAction)); }
public static EnemyObjectTemplate Enemy(ObjectAction action, IMathExpression initialMilliHP, List <ObjectBox> damageBoxes, List <ObjectBox> collisionBoxes, string spriteName) { EnemyObjectTemplate template = new EnemyObjectTemplate(); template.ObjectType = EnemyObjectType.Enemy; template.Action = action; template.InitialMilliHP = initialMilliHP; if (damageBoxes != null) { template.DamageBoxes = new DTImmutableList <ObjectBox>(list: damageBoxes); } if (collisionBoxes != null) { template.CollisionBoxes = new DTImmutableList <ObjectBox>(list: collisionBoxes); } template.SpriteName = spriteName; return(template); }
// Returns true if player still has at least one life remaining // Returns false if game over public bool DestroyPlayer( List <EnemyObject> enemyObjects, long elapsedMillisecondsPerIteration, IDTDeterministicRandom rng) { if (this.isDead) { throw new Exception(); } long playerXMillis = this.xMillis; long playerYMillis = this.yMillis; EnemyObjectTemplate template = EnemyObjectTemplate.Placeholder(action: ObjectAction.ConditionalNextAction( currentAction: this.playerDeathSpawnDestructionAnimationAction, condition: BooleanExpression.True(), nextAction: ObjectAction.Destroy())); enemyObjects.Add(new EnemyObject( template: template, initialXMillis: playerXMillis, initialYMillis: playerYMillis, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, isPlayerDestroyed: true, parent: null, initialNumericVariables: null, initialBooleanVariables: null, rng: rng)); this.isDead = true; if (this.numLivesLeft > 0) { this.numLivesLeft = this.numLivesLeft - 1; this.respawnTimeRemainingMillis = 750; return(true); } else { return(false); } }
public static ObjectAction SpawnBossEnemy( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, Dictionary <string, DTDanmakuSound> soundNameToSoundDictionary, GuidGenerator guidGenerator) { string spriteName = guidGenerator.NextGuid(); spriteNameToImageDictionary.Add(spriteName, DTDanmakuImage.Boss); List <ObjectBox> damageBoxes = new List <ObjectBox>(); damageBoxes.Add(new ObjectBox(lowerXMillis: -96500, upperXMillis: 96500, lowerYMillis: -10000, upperYMillis: 30000)); damageBoxes.Add(new ObjectBox(lowerXMillis: -71500, upperXMillis: 71500, lowerYMillis: -35000, upperYMillis: 30000)); damageBoxes.Add(new ObjectBox(lowerXMillis: -50000, upperXMillis: 50000, lowerYMillis: -81000, upperYMillis: 48000)); damageBoxes.Add(new ObjectBox(lowerXMillis: -35000, upperXMillis: 35000, lowerYMillis: 0, upperYMillis: 68000)); List <ObjectBox> collisionBoxes = new List <ObjectBox>(); collisionBoxes.Add(new ObjectBox(lowerXMillis: -20000, upperXMillis: 20000, lowerYMillis: -50000, upperYMillis: 50000)); collisionBoxes.Add(new ObjectBox(lowerXMillis: -50000, upperXMillis: 50000, lowerYMillis: -20000, upperYMillis: 20000)); EnemyObjectTemplate enemyObjectTemplate = EnemyObjectTemplate.Enemy( action: GetBossAction( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator), initialMilliHP: MathExpression.Constant(50L * 1000L * 1000L * 1000L * 1000L), damageBoxes: damageBoxes, collisionBoxes: collisionBoxes, spriteName: spriteName); string templateName = guidGenerator.NextGuid(); enemyObjectTemplates.Add(templateName, enemyObjectTemplate); return(ObjectAction.SpawnChild( childXMillis: MathExpression.Constant(-1000 * 1000), childYMillis: MathExpression.Constant(-1000 * 1000), childObjectTemplateName: templateName, childInitialNumericVariables: null, childInitialBooleanVariables: null)); }
private static ObjectAction GetMoveAction(IMathExpression xMillis) { ObjectAction teleportToInitialLocation = ObjectAction.SetPosition( xMillis: xMillis, yMillis: MathExpression.Constant(900 * 1000)); ObjectAction moveDown = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Subtract(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.Constant(35), MathExpression.ElapsedMillisecondsPerIteration()))); ObjectAction destroyAction = ObjectAction.Condition( condition: BooleanExpression.LessThanOrEqualTo(MathExpression.YMillis(), -200 * 1000), action: ObjectAction.Destroy()); return(ObjectAction.Union( ObjectActionGenerator.DoOnce(teleportToInitialLocation), moveDown, destroyAction)); }
private static ObjectAction GetSpawnOrbiterSatellitesAction( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, GuidGenerator guidGenerator) { string spriteName = guidGenerator.NextGuid(); spriteNameToImageDictionary.Add(spriteName, DTDanmakuImage.EliteOrbiterSatellite); List <ObjectAction> objectActions = new List <ObjectAction>(); for (long i = 0; i < 5; i++) { EnemyObjectTemplate orbiterSatelliteTemplate = EnemyObjectTemplate.EnemyBullet( action: ObjectAction.Union( GetSatelliteMoveAndDestroyAction( initialAngleInMillidegrees: 72L * 1000L * i, guidGenerator: guidGenerator), GetSatelliteShootAction( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, guidGenerator: guidGenerator)), initialMilliHP: null, damageBoxes: null, collisionBoxes: null, spriteName: spriteName); string templateName = guidGenerator.NextGuid(); enemyObjectTemplates.Add(templateName, orbiterSatelliteTemplate); ObjectAction spawnSatelliteAction = ObjectAction.SpawnChild( childXMillis: MathExpression.Constant(-1000 * 1000), childYMillis: MathExpression.Constant(-1000 * 1000), childObjectTemplateName: templateName, childInitialNumericVariables: null, childInitialBooleanVariables: null); objectActions.Add(spawnSatelliteAction); } return(ObjectActionGenerator.DoOnce(ObjectAction.Union(objectActions))); }
private static Tuple <ObjectAction, EnemyObjectTemplate> SpawnOneDestructionSpriteImage( long startMilliseconds, long endMilliseconds, string childObjectTemplateName, string spriteName, bool isLast) { List <ObjectAction> destroyActions = new List <ObjectAction>(); destroyActions.Add(ObjectAction.Destroy()); destroyActions.Add(ObjectAction.DestroyParent()); ObjectAction destroySelfAction = ObjectAction.Condition( condition: BooleanExpression.GreaterThanOrEqualTo( leftSide: MathExpression.ParentVariable(elapsedTimeInMillisVariableName), rightSide: MathExpression.Constant(endMilliseconds)), action: isLast ? ObjectAction.Union(destroyActions) : ObjectAction.Destroy()); ObjectAction spawnChildAction = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: childObjectTemplateName, childInitialNumericVariables: null, childInitialBooleanVariables: null); ObjectAction delayedSpawnChildAction = ObjectAction.Condition( condition: BooleanExpression.GreaterThanOrEqualTo( leftSide: MathExpression.Variable(elapsedTimeInMillisVariableName), rightSide: MathExpression.Constant(startMilliseconds)), action: ObjectActionGenerator.DoOnce(spawnChildAction)); EnemyObjectTemplate template = EnemyObjectTemplate.Enemy( action: destroySelfAction, initialMilliHP: null, damageBoxes: null, collisionBoxes: null, spriteName: spriteName); return(new Tuple <ObjectAction, EnemyObjectTemplate>(delayedSpawnChildAction, template)); }
private static ObjectAction GetBossAction( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, Dictionary <string, DTDanmakuSound> soundNameToSoundDictionary, GuidGenerator guidGenerator) { ObjectAction setPhaseVariableAction = ObjectActionGenerator.DoOnce(ObjectAction.SetNumericVariable(CurrentPhaseVariableName, MathExpression.Constant(0))); ObjectAction phase0Action = ObjectAction.Condition( condition: BooleanExpression.Equal(MathExpression.Variable(CurrentPhaseVariableName), MathExpression.Constant(0)), action: GetMoveAction_Phase0()); ObjectAction phase1Action = ObjectAction.Condition( condition: BooleanExpression.Equal(MathExpression.Variable(CurrentPhaseVariableName), MathExpression.Constant(1)), action: GetPhase1Action( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, guidGenerator: guidGenerator)); ObjectAction phase2Action = ObjectAction.Condition( condition: BooleanExpression.Equal(MathExpression.Variable(CurrentPhaseVariableName), MathExpression.Constant(2)), action: GetPhase2Action( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, guidGenerator: guidGenerator)); ObjectAction phase3Action = ObjectAction.Condition( condition: BooleanExpression.Equal(MathExpression.Variable(CurrentPhaseVariableName), MathExpression.Constant(3)), action: GetPhase3Action( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator)); return(ObjectAction.Union( setPhaseVariableAction, phase0Action, phase1Action, phase2Action, phase3Action)); }
public ResultOfAction( ObjectAction newObjectAction, bool shouldEndLevel, List <EnemyObject> newEnemyObjects, List <Tuple <long, long> > newPowerUps, List <string> newSoundEffectsToPlay, long?bossHealthMeterNumber, long?bossHealthMeterMilliPercentage) { if (newObjectAction == null || newEnemyObjects == null || newPowerUps == null || newSoundEffectsToPlay == null) { throw new Exception(); } this.NewObjectAction = newObjectAction; this.ShouldEndLevel = shouldEndLevel; this.NewEnemyObjects = newEnemyObjects; this.NewPowerUps = newPowerUps; this.NewSoundEffectsToPlay = newSoundEffectsToPlay; this.BossHealthMeterNumber = bossHealthMeterNumber; this.BossHealthMeterMilliPercentage = bossHealthMeterMilliPercentage; }
public static ObjectAction Union( ObjectAction action1, ObjectAction action2, ObjectAction action3, ObjectAction action4, ObjectAction action5, ObjectAction action6, ObjectAction action7, ObjectAction action8) { List <ObjectAction> list = new List <ObjectAction>(); list.Add(action1); list.Add(action2); list.Add(action3); list.Add(action4); list.Add(action5); list.Add(action6); list.Add(action7); list.Add(action8); return(ObjectAction.Union(list)); }
private static ObjectAction GetMoveAction_Phase0() { ObjectAction teleportToInitialLocation = ObjectActionGenerator.DoOnce( ObjectAction.SetPosition( xMillis: MathExpression.Constant(500 * 1000), yMillis: MathExpression.Constant(850 * 1000))); ObjectAction moveAction = ObjectAction.Union( ObjectAction.StrafeMove(moveToXMillis: MathExpression.XMillis(), moveToYMillis: MathExpression.Constant(0)), ObjectAction.SetSpeed(MathExpression.Constant(20))); BooleanExpression shouldStopMoving = BooleanExpression.LessThanOrEqualTo( MathExpression.YMillis(), MathExpression.Constant(500 * 1000)); ObjectAction stopMovingAction = ObjectAction.SetSpeed(MathExpression.Constant(0)); ObjectAction setPhaseAction = ObjectAction.SetNumericVariable(CurrentPhaseVariableName, MathExpression.Constant(1)); return(ObjectAction.ConditionalNextAction( currentAction: ObjectAction.Union(teleportToInitialLocation, moveAction), condition: shouldStopMoving, nextAction: ObjectActionGenerator.DoOnce(ObjectAction.Union(stopMovingAction, setPhaseAction)))); }
public static ObjectAction SpawnChild( IMathExpression childXMillis, IMathExpression childYMillis, string childObjectTemplateName, List <InitialChildNumericVariableInfo> childInitialNumericVariables, List <InitialChildBooleanVariableInfo> childInitialBooleanVariables) { ObjectAction action = new ObjectAction(); action.ObjectActionType = Type.SpawnChild; action.SpawnChildXMillis = childXMillis; action.SpawnChildYMillis = childYMillis; action.SpawnChildObjectTemplateName = childObjectTemplateName; if (childInitialNumericVariables != null) { action.SpawnChildInitialChildNumericVariables = new DTImmutableList <InitialChildNumericVariableInfo>(list: childInitialNumericVariables); } if (childInitialBooleanVariables != null) { action.SpawnChildInitialChildBooleanVariables = new DTImmutableList <InitialChildBooleanVariableInfo>(list: childInitialBooleanVariables); } return(action); }
private static EnemyObject CreateActionExecutor( long millisecondsToWait, ObjectAction action, long elapsedMillisecondsPerIteration, IDTDeterministicRandom rng, GuidGenerator guidGenerator) { return(new EnemyObject( template: EnemyObjectTemplate.Placeholder( action: ObjectActionGenerator.Delay( action: ObjectAction.Union(action, ObjectAction.Destroy()), milliseconds: millisecondsToWait, guidGenerator: guidGenerator)), initialXMillis: 0, initialYMillis: 0, playerXMillis: 0, playerYMillis: 0, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, isPlayerDestroyed: false, parent: null, initialNumericVariables: null, initialBooleanVariables: null, rng: rng)); }
private static ObjectAction SpawnPhase3Bullet( IMathExpression bulletDirectionInMillidegrees, Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, GuidGenerator guidGenerator) { string bulletSpriteName = guidGenerator.NextGuid(); spriteNameToImageDictionary.Add(bulletSpriteName, DTDanmakuImage.BossPhase3EnemyBullet); string snapshotBulletDirectionInMillidegreesVariable = guidGenerator.NextGuid(); ObjectAction snapshotDirectionAction = ObjectActionGenerator.DoOnce(ObjectAction.SetNumericVariable( snapshotBulletDirectionInMillidegreesVariable, bulletDirectionInMillidegrees)); long buffer = 100; BooleanExpression shouldDestroy = BooleanExpression.Or( BooleanExpression.GreaterThan(MathExpression.XMillis(), MathExpression.Constant((1000 + buffer) * 1000)), BooleanExpression.LessThan(MathExpression.XMillis(), MathExpression.Constant((0 - buffer) * 1000)), BooleanExpression.GreaterThan(MathExpression.YMillis(), MathExpression.Constant((700 + buffer) * 1000)), BooleanExpression.LessThan(MathExpression.YMillis(), MathExpression.Constant((0 - buffer) * 1000))); ObjectAction destroyAction = ObjectAction.Condition( condition: shouldDestroy, action: ObjectAction.Destroy()); DTDanmakuMath.MathExpressionOffset offset = DTDanmakuMath.GetOffset( millipixels: MathExpression.Multiply(MathExpression.Constant(200), MathExpression.ElapsedMillisecondsPerIteration()), movementDirectionInMillidegrees: MathExpression.Variable(snapshotBulletDirectionInMillidegreesVariable)); List <ObjectBox> collisionBoxes = new List <ObjectBox>(); collisionBoxes.Add(new ObjectBox(lowerXMillis: -3000, upperXMillis: 3000, lowerYMillis: -5000, upperYMillis: 5000)); collisionBoxes.Add(new ObjectBox(lowerXMillis: -5000, upperXMillis: 5000, lowerYMillis: -3000, upperYMillis: 3000)); EnemyObjectTemplate bulletTemplate = EnemyObjectTemplate.EnemyBullet( action: ObjectAction.Union( snapshotDirectionAction, ObjectAction.SetFacingDirection(MathExpression.Variable(snapshotBulletDirectionInMillidegreesVariable)), ObjectAction.SetPosition( xMillis: MathExpression.Add(MathExpression.XMillis(), offset.DeltaXInMillipixels), yMillis: MathExpression.Add(MathExpression.YMillis(), offset.DeltaYInMillipixels)), destroyAction), initialMilliHP: null, damageBoxes: null, collisionBoxes: collisionBoxes, spriteName: bulletSpriteName); string templateName = guidGenerator.NextGuid(); enemyObjectTemplates.Add(templateName, bulletTemplate); return(ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.Subtract(MathExpression.YMillis(), MathExpression.Constant(60000)), childObjectTemplateName: templateName, childInitialNumericVariables: null, childInitialBooleanVariables: null)); }
private static ObjectAction GetMoveAndSetCanShootVariableAction( IMathExpression xMillis, GuidGenerator guidGenerator) { string variableName = guidGenerator.NextGuid(); ObjectAction initializeVariable = ObjectAction.SetNumericVariable( variableName: variableName, variableValue: MathExpression.Constant(0)); ObjectAction incrementVariable = ObjectAction.SetNumericVariable( variableName: variableName, variableValue: MathExpression.Add(MathExpression.Variable(variableName), MathExpression.ElapsedMillisecondsPerIteration())); ObjectAction initializeAndIncrementVariable = ObjectAction.ConditionalNextAction( currentAction: initializeVariable, condition: BooleanExpression.True(), nextAction: incrementVariable); ObjectAction teleportToInitialLocation = ObjectAction.SetPosition( xMillis: xMillis, yMillis: MathExpression.Constant(800 * 1000)); ObjectAction moveDownSpeed1 = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Subtract(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.Constant(100), MathExpression.ElapsedMillisecondsPerIteration()))); ObjectAction moveDownSpeed2 = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Subtract(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.Constant(70), MathExpression.ElapsedMillisecondsPerIteration()))); ObjectAction moveDownSpeed3 = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Subtract(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.Constant(30), MathExpression.ElapsedMillisecondsPerIteration()))); ObjectAction stopMovement = ObjectAction.Union( ObjectActionGenerator.Noop(), ObjectActionGenerator.DoOnce(ObjectAction.SetBooleanVariable("can shoot", BooleanExpression.True()))); ObjectAction moveUpSpeed1 = ObjectAction.Union( ObjectActionGenerator.DoOnce(ObjectAction.SetBooleanVariable("can shoot", BooleanExpression.False())), ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.Constant(30), MathExpression.ElapsedMillisecondsPerIteration())))); ObjectAction moveUpSpeed2 = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.Constant(70), MathExpression.ElapsedMillisecondsPerIteration()))); ObjectAction moveUpSpeed3 = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.Constant(100), MathExpression.ElapsedMillisecondsPerIteration()))); ObjectAction destroyAction = ObjectAction.Condition( condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.YMillis(), MathExpression.Constant(800 * 1000)), action: ObjectAction.Destroy()); return(ObjectAction.Union( ObjectActionGenerator.DoOnce(ObjectAction.SetBooleanVariable("can shoot", BooleanExpression.False())), initializeAndIncrementVariable, ObjectActionGenerator.DoOnce(teleportToInitialLocation), ObjectAction.ConditionalNextAction( currentAction: moveDownSpeed1, condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(variableName), MathExpression.Constant(3000)), nextAction: ObjectAction.ConditionalNextAction( currentAction: moveDownSpeed2, condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(variableName), MathExpression.Constant(4000)), nextAction: ObjectAction.ConditionalNextAction( currentAction: moveDownSpeed3, condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(variableName), MathExpression.Constant(5000)), nextAction: ObjectAction.ConditionalNextAction( currentAction: stopMovement, condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(variableName), MathExpression.Constant(12000)), nextAction: ObjectAction.ConditionalNextAction( currentAction: moveUpSpeed1, condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(variableName), MathExpression.Constant(13000)), nextAction: ObjectAction.ConditionalNextAction( currentAction: moveUpSpeed2, condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(variableName), MathExpression.Constant(14000)), nextAction: ObjectAction.Union(moveUpSpeed3, destroyAction))))))))); }
// Spawns 12 bullets (30 degrees apart) private static ObjectAction SpawnSatelliteBullet( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, GuidGenerator guidGenerator) { string singleBulletSpriteName = guidGenerator.NextGuid(); spriteNameToImageDictionary.Add(singleBulletSpriteName, DTDanmakuImage.EliteOrbiterEnemyBullet); long buffer = 100; BooleanExpression shouldDestroySingleBullet = BooleanExpression.Or( BooleanExpression.GreaterThan(MathExpression.XMillis(), MathExpression.Constant((1000 + buffer) * 1000)), BooleanExpression.LessThan(MathExpression.XMillis(), MathExpression.Constant((0 - buffer) * 1000)), BooleanExpression.GreaterThan(MathExpression.YMillis(), MathExpression.Constant((700 + buffer) * 1000)), BooleanExpression.LessThan(MathExpression.YMillis(), MathExpression.Constant((0 - buffer) * 1000))); ObjectAction destroySingleBulletAction = ObjectAction.Condition( condition: shouldDestroySingleBullet, action: ObjectAction.Destroy()); DTDanmakuMath.MathExpressionOffset singleBulletOffset = DTDanmakuMath.GetOffset( millipixels: MathExpression.Multiply(MathExpression.Constant(100), MathExpression.ElapsedMillisecondsPerIteration()), movementDirectionInMillidegrees: MathExpression.Variable("direction")); List <ObjectBox> collisionBoxes = new List <ObjectBox>(); collisionBoxes.Add(new ObjectBox(lowerXMillis: -3000, upperXMillis: 3000, lowerYMillis: -5000, upperYMillis: 5000)); collisionBoxes.Add(new ObjectBox(lowerXMillis: -5000, upperXMillis: 5000, lowerYMillis: -3000, upperYMillis: 3000)); EnemyObjectTemplate singleBulletTemplate = EnemyObjectTemplate.EnemyBullet( action: ObjectAction.Union( ObjectAction.SetFacingDirection(MathExpression.Variable("direction")), ObjectAction.SetPosition( xMillis: MathExpression.Add(MathExpression.XMillis(), singleBulletOffset.DeltaXInMillipixels), yMillis: MathExpression.Add(MathExpression.YMillis(), singleBulletOffset.DeltaYInMillipixels)), destroySingleBulletAction), initialMilliHP: null, damageBoxes: null, collisionBoxes: collisionBoxes, spriteName: singleBulletSpriteName); string singleBulletTemplateName = guidGenerator.NextGuid(); enemyObjectTemplates.Add(singleBulletTemplateName, singleBulletTemplate); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables1 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables1.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(0)))); ObjectAction spawnSingleBulletAction1 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables1, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables2 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables2.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(30 * 1000)))); ObjectAction spawnSingleBulletAction2 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables2, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables3 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables3.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(60 * 1000)))); ObjectAction spawnSingleBulletAction3 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables3, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables4 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables4.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(90 * 1000)))); ObjectAction spawnSingleBulletAction4 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables4, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables5 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables5.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(120 * 1000)))); ObjectAction spawnSingleBulletAction5 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables5, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables6 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables6.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(150 * 1000)))); ObjectAction spawnSingleBulletAction6 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables6, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables7 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables7.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(180 * 1000)))); ObjectAction spawnSingleBulletAction7 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables7, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables8 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables8.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(210 * 1000)))); ObjectAction spawnSingleBulletAction8 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables8, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables9 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables9.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(240 * 1000)))); ObjectAction spawnSingleBulletAction9 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables9, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables10 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables10.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(270 * 1000)))); ObjectAction spawnSingleBulletAction10 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables10, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables11 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables11.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(300 * 1000)))); ObjectAction spawnSingleBulletAction11 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables11, childInitialBooleanVariables: null); List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables12 = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables12.Add(new ObjectAction.InitialChildNumericVariableInfo(name: "direction", value: MathExpression.Add(MathExpression.Variable("random offset"), MathExpression.Constant(330 * 1000)))); ObjectAction spawnSingleBulletAction12 = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables12, childInitialBooleanVariables: null); List <ObjectAction> actionList = new List <ObjectAction>(); actionList.Add(ObjectAction.SetNumericVariable("random offset", MathExpression.RandomInteger(MathExpression.Constant(360 * 1000)))); actionList.Add(spawnSingleBulletAction1); actionList.Add(spawnSingleBulletAction2); actionList.Add(spawnSingleBulletAction3); actionList.Add(spawnSingleBulletAction4); actionList.Add(spawnSingleBulletAction5); actionList.Add(spawnSingleBulletAction6); actionList.Add(spawnSingleBulletAction7); actionList.Add(spawnSingleBulletAction8); actionList.Add(spawnSingleBulletAction9); actionList.Add(spawnSingleBulletAction10); actionList.Add(spawnSingleBulletAction11); actionList.Add(spawnSingleBulletAction12); actionList.Add(ObjectAction.Destroy()); EnemyObjectTemplate placeholderTemplate = EnemyObjectTemplate.Placeholder( action: ObjectAction.Union(actionList)); string placeholderTemplateName = guidGenerator.NextGuid(); enemyObjectTemplates.Add(placeholderTemplateName, placeholderTemplate); return(ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: placeholderTemplateName, childInitialNumericVariables: null, childInitialBooleanVariables: null)); }
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)); }
private static ObjectAction GetMoveAction( GuidGenerator guidGenerator) { string movementCooldownVariable = guidGenerator.NextGuid(); ObjectAction setMovementCooldownAction = ObjectAction.SetNumericVariable( movementCooldownVariable, MathExpression.Add(MathExpression.Constant(500), MathExpression.RandomInteger(5000))); ObjectAction decrementMovementCooldownAction = ObjectAction.SetNumericVariable( movementCooldownVariable, MathExpression.Subtract(MathExpression.Variable(movementCooldownVariable), MathExpression.ElapsedMillisecondsPerIteration())); BooleanExpression shouldChangeMovement = BooleanExpression.LessThanOrEqualTo( MathExpression.Variable(movementCooldownVariable), MathExpression.Constant(0)); IMathExpression randomMilliAngle = MathExpression.RandomInteger(MathExpression.Constant(360 * 1000)); string angleVariable = guidGenerator.NextGuid(); ObjectAction writeNewAngleToVariable = ObjectAction.SetNumericVariable( angleVariable, randomMilliAngle); ObjectAction normalizeAngleVariable = ObjectAction.Union( ObjectAction.Condition( condition: BooleanExpression.LessThan(MathExpression.Variable(angleVariable), MathExpression.Constant(0)), action: ObjectAction.SetNumericVariable(angleVariable, MathExpression.Add(MathExpression.Variable(angleVariable), MathExpression.Constant(360 * 1000)))), ObjectAction.Condition( condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(360 * 1000)), action: ObjectAction.SetNumericVariable(angleVariable, MathExpression.Subtract(MathExpression.Variable(angleVariable), MathExpression.Constant(360 * 1000))))); BooleanExpression tooCloseToLeftEdge = BooleanExpression.LessThanOrEqualTo( MathExpression.XMillis(), MathExpression.Constant(200 * 1000)); ObjectAction updateAngleVariableLeft = ObjectAction.Condition( condition: BooleanExpression.And(tooCloseToLeftEdge, BooleanExpression.And( BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(180 * 1000)), BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(360 * 1000)))), action: ObjectAction.SetNumericVariable( angleVariable, MathExpression.Multiply(MathExpression.Variable(angleVariable), MathExpression.Constant(-1)))); BooleanExpression tooCloseToRightEdge = BooleanExpression.GreaterThanOrEqualTo( MathExpression.XMillis(), MathExpression.Constant(800 * 1000)); ObjectAction updateAngleVariableRight = ObjectAction.Condition( condition: BooleanExpression.And(tooCloseToRightEdge, BooleanExpression.And( BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(0 * 1000)), BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(180 * 1000)))), action: ObjectAction.SetNumericVariable( angleVariable, MathExpression.Multiply(MathExpression.Variable(angleVariable), MathExpression.Constant(-1)))); BooleanExpression tooCloseToTopEdge = BooleanExpression.GreaterThanOrEqualTo( MathExpression.YMillis(), MathExpression.Constant(600 * 1000)); ObjectAction updateAngleVariableTop = ObjectAction.Condition( condition: BooleanExpression.And(tooCloseToTopEdge, BooleanExpression.Or( BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(270 * 1000)), BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(90 * 1000)))), action: ObjectAction.SetNumericVariable( angleVariable, MathExpression.Subtract( MathExpression.Multiply(MathExpression.Add(MathExpression.Variable(angleVariable), MathExpression.Constant(90 * 1000)), MathExpression.Constant(-1)), MathExpression.Constant(90 * 1000)))); BooleanExpression tooCloseToBottomEdge = BooleanExpression.LessThanOrEqualTo( MathExpression.YMillis(), MathExpression.Constant(400 * 1000)); ObjectAction updateAngleVariableBottom = ObjectAction.Condition( condition: BooleanExpression.And(tooCloseToBottomEdge, BooleanExpression.And( BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(90 * 1000)), BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(angleVariable), MathExpression.Constant(270 * 1000)))), action: ObjectAction.SetNumericVariable( angleVariable, MathExpression.Subtract( MathExpression.Multiply(MathExpression.Add(MathExpression.Variable(angleVariable), MathExpression.Constant(90 * 1000)), MathExpression.Constant(-1)), MathExpression.Constant(90 * 1000)))); string angleSnapshotVariable = guidGenerator.NextGuid(); ObjectAction initializeAngleSnapshotVariable = ObjectActionGenerator.DoOnce( ObjectAction.SetNumericVariable(angleSnapshotVariable, MathExpression.RandomInteger(360 * 1000))); DTDanmakuMath.MathExpressionOffset offset = DTDanmakuMath.GetOffset( millipixels: MathExpression.Multiply(MathExpression.Constant(80), MathExpression.ElapsedMillisecondsPerIteration()), movementDirectionInMillidegrees: MathExpression.Variable(angleSnapshotVariable)); ObjectAction updatePositionAction = ObjectAction.SetPosition( xMillis: MathExpression.Add(MathExpression.XMillis(), offset.DeltaXInMillipixels), yMillis: MathExpression.Add(MathExpression.YMillis(), offset.DeltaYInMillipixels)); ObjectAction updatePositionWhenCooldownIsZero = ObjectAction.Condition( condition: shouldChangeMovement, action: ObjectAction.Union( ObjectAction.SetNumericVariable(angleSnapshotVariable, MathExpression.Variable(angleVariable)), setMovementCooldownAction)); ObjectAction immediateMoveWhenTooClose = ObjectAction.Condition( condition: BooleanExpression.Or(tooCloseToLeftEdge, tooCloseToRightEdge, tooCloseToTopEdge, tooCloseToBottomEdge), action: ObjectAction.SetNumericVariable(movementCooldownVariable, MathExpression.Constant(0))); List <ObjectAction> actionList = new List <ObjectAction>(); actionList.Add(initializeAngleSnapshotVariable); actionList.Add(ObjectActionGenerator.DoOnce(setMovementCooldownAction)); actionList.Add(decrementMovementCooldownAction); actionList.Add(writeNewAngleToVariable); actionList.Add(updateAngleVariableLeft); actionList.Add(normalizeAngleVariable); actionList.Add(updateAngleVariableRight); actionList.Add(normalizeAngleVariable); actionList.Add(updateAngleVariableTop); actionList.Add(normalizeAngleVariable); actionList.Add(normalizeAngleVariable); actionList.Add(updateAngleVariableBottom); actionList.Add(normalizeAngleVariable); actionList.Add(normalizeAngleVariable); actionList.Add(updatePositionWhenCooldownIsZero); actionList.Add(updatePositionAction); actionList.Add(immediateMoveWhenTooClose); return(ObjectAction.Union(actionList)); }
/* * If (currentX, currentY) == (desiredX, desiredY), then * the resulting movement direction is arbitrary. */ public static ObjectAction MoveTowardsLocation( IMathExpression currentX, IMathExpression currentY, IMathExpression desiredX, IMathExpression desiredY, /* * Note that movement speed is not affected by shouldSnapshot */ IMathExpression movementSpeedInPixelsPerSecond, /* * When true, will decide movement direction on the first frame, and keep that direction. * When false, will continuously move towards (desiredX, desiredY) */ bool shouldSnapshot, GuidGenerator guidGenerator) { string deltaXVariable = guidGenerator.NextGuid(); string deltaYVariable = guidGenerator.NextGuid(); ObjectAction setDeltaX = ObjectAction.SetNumericVariable(deltaXVariable, MathExpression.Subtract(desiredX, currentX)); ObjectAction setDeltaY = ObjectAction.SetNumericVariable(deltaYVariable, MathExpression.Subtract(desiredY, currentY)); BooleanExpression areDeltasBothZero = BooleanExpression.And( BooleanExpression.Equal(MathExpression.Variable(deltaXVariable), MathExpression.Constant(0)), BooleanExpression.Equal(MathExpression.Variable(deltaYVariable), MathExpression.Constant(0))); string angleInMillidegreesVariable = guidGenerator.NextGuid(); ObjectAction setAngle = ObjectAction.Union( shouldSnapshot ? ObjectActionGenerator.DoOnce(setDeltaX) : setDeltaX, shouldSnapshot ? ObjectActionGenerator.DoOnce(setDeltaY) : setDeltaY, ObjectAction.Condition( condition: areDeltasBothZero, action: ObjectAction.SetNumericVariable(angleInMillidegreesVariable, MathExpression.Constant(0))), ObjectAction.Condition( condition: BooleanExpression.Not(areDeltasBothZero), action: ObjectAction.SetNumericVariable(angleInMillidegreesVariable, MathExpression.ArcTangentScaled(MathExpression.Variable(deltaXVariable), MathExpression.Variable(deltaYVariable), false))), ObjectAction.SetNumericVariable(angleInMillidegreesVariable, MathExpression.Multiply(MathExpression.Variable(angleInMillidegreesVariable), MathExpression.Constant(-1))), ObjectAction.SetNumericVariable(angleInMillidegreesVariable, MathExpression.Add(MathExpression.Variable(angleInMillidegreesVariable), 90 * 1000))); IMathExpression xMillis = MathExpression.Divide( MathExpression.Multiply( movementSpeedInPixelsPerSecond, MathExpression.ElapsedMillisecondsPerIteration(), MathExpression.SineScaled(MathExpression.Variable(angleInMillidegreesVariable))), MathExpression.Constant(1000)); IMathExpression yMillis = MathExpression.Divide( MathExpression.Multiply( movementSpeedInPixelsPerSecond, MathExpression.ElapsedMillisecondsPerIteration(), MathExpression.CosineScaled(MathExpression.Variable(angleInMillidegreesVariable))), MathExpression.Constant(1000)); string xMillisVariable = guidGenerator.NextGuid(); string yMillisVariable = guidGenerator.NextGuid(); ObjectAction setXMillisVariable = shouldSnapshot ? ObjectActionGenerator.DoOnce(ObjectAction.SetNumericVariable(xMillisVariable, xMillis)) : ObjectAction.SetNumericVariable(xMillisVariable, xMillis); ObjectAction setYMillisVariable = shouldSnapshot ? ObjectActionGenerator.DoOnce(ObjectAction.SetNumericVariable(yMillisVariable, yMillis)) : ObjectAction.SetNumericVariable(yMillisVariable, yMillis); return(ObjectAction.Union( setAngle, setXMillisVariable, setYMillisVariable, ObjectAction.SetPosition( xMillis: MathExpression.Add(MathExpression.XMillis(), MathExpression.Variable(xMillisVariable)), yMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Variable(yMillisVariable))))); }
private static Tuple <ObjectAction, BooleanExpression> MoveToSpecifiedLocations_Helper( long startingXMillis, long startingYMillis, long endingXMillis, long endingYMillis, long speedInPixelsPerSecond, bool shouldStrafe, GuidGenerator guidGenerator) { string variableName = guidGenerator.NextGuid(); string variableName2 = guidGenerator.NextGuid(); long?direction = DTDanmakuMath.GetMovementDirectionInMillidegrees( currentX: startingXMillis, currentY: startingYMillis, desiredX: endingXMillis, desiredY: endingYMillis); if (direction == null) { throw new Exception(); } DTDanmakuMath.Offset offset = DTDanmakuMath.GetOffset( speedInMillipixelsPerMillisecond: speedInPixelsPerSecond, // millipixels/millisecond is equivalent to pixels/second movementDirectionInMillidegrees: direction.Value, elapsedMillisecondsPerIteration: 1000); // Use the 1000 to help prevent rounding issues ObjectAction moveAction = ObjectAction.SetPosition( xMillis: MathExpression.Add(MathExpression.XMillis(), MathExpression.Divide(MathExpression.Multiply(MathExpression.Constant(offset.DeltaXInMillipixels), MathExpression.ElapsedMillisecondsPerIteration()), MathExpression.Constant(1000))), yMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Divide(MathExpression.Multiply(MathExpression.Constant(offset.DeltaYInMillipixels), MathExpression.ElapsedMillisecondsPerIteration()), MathExpression.Constant(1000)))); ObjectAction setDirectionAction = shouldStrafe ? ObjectAction.SetFacingDirection(facingDirectionInMillidegrees: MathExpression.Constant(180 * 1000)) : ObjectAction.SetFacingDirection(facingDirectionInMillidegrees: MathExpression.Constant(direction.Value)); IMathExpression deltaX = MathExpression.AbsoluteValue(MathExpression.Subtract(MathExpression.XMillis(), MathExpression.Constant(endingXMillis))); IMathExpression deltaY = MathExpression.AbsoluteValue(MathExpression.Subtract(MathExpression.YMillis(), MathExpression.Constant(endingYMillis))); IMathExpression totalDelta = MathExpression.Add(deltaX, deltaY); ObjectAction setDeltaToVariable = ObjectAction.Union( ObjectAction.SetNumericVariable(variableName: variableName2, variableValue: MathExpression.Variable(variableName)), ObjectAction.SetNumericVariable(variableName: variableName, variableValue: totalDelta)); BooleanExpression reachedDestination = BooleanExpression.And( BooleanExpression.LessThanOrEqualTo( MathExpression.Variable(variableName2), MathExpression.Variable(variableName)), BooleanExpression.And( BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(variableName), MathExpression.Constant(0)), BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(variableName2), MathExpression.Constant(0)) )); ObjectAction initializeVariables = ObjectAction.Union( ObjectAction.SetNumericVariable(variableName: variableName, variableValue: MathExpression.Constant(-1)), ObjectAction.SetNumericVariable(variableName: variableName2, variableValue: MathExpression.Constant(-1))); return(new Tuple <ObjectAction, BooleanExpression>( ObjectAction.Union( moveAction, setDirectionAction, ObjectAction.ConditionalNextAction( currentAction: initializeVariables, condition: BooleanExpression.True(), nextAction: setDeltaToVariable)), reachedDestination)); }
public Player(ObjectAction playerDeathSpawnDestructionAnimationAction) { this.xMillis = SPAWN_LOCATION_X_MILLIS; this.yMillis = SPAWN_LOCATION_Y_MILLIS; this.isDead = false; this.respawnTimeRemainingMillis = null; this.numLivesLeft = 3; this.playerInvincibilityTimeRemainingMillis = null; this.playerShootCooldownInMillis = 0; this.playerPowerUpLevel = 0; this.playerDeathSpawnDestructionAnimationAction = playerDeathSpawnDestructionAnimationAction; this.playerBulletTypeToCollisionBoxesMapping = new Dictionary <PlayerBullet.PlayerBulletType, DTImmutableList <ObjectBox> >(); List <ObjectBox> collisionBoxesMain = new List <ObjectBox>(); collisionBoxesMain.Add(new ObjectBox(-4000, 4000, -4000, 4000)); collisionBoxesMain.Add(new ObjectBox(-4000, 4000, -25000, -17000)); collisionBoxesMain.Add(new ObjectBox(-4000, 4000, 17000, 25000)); this.playerBulletTypeToCollisionBoxesMapping[PlayerBullet.PlayerBulletType.Main] = new DTImmutableList <ObjectBox>(collisionBoxesMain); List <ObjectBox> collisionBoxesSide1Left = new List <ObjectBox>(); collisionBoxesSide1Left.Add(new ObjectBox(-4000, 4000, -4000, 4000)); collisionBoxesSide1Left.Add(new ObjectBox(-1000, 7000, -24000, -16000)); collisionBoxesSide1Left.Add(new ObjectBox(-7000, 1000, 16000, 24000)); this.playerBulletTypeToCollisionBoxesMapping[PlayerBullet.PlayerBulletType.Side1Left] = new DTImmutableList <ObjectBox>(collisionBoxesSide1Left); List <ObjectBox> collisionBoxesSide1Right = new List <ObjectBox>(); collisionBoxesSide1Right.Add(new ObjectBox(-4000, 4000, -4000, 4000)); collisionBoxesSide1Right.Add(new ObjectBox(-7000, 1000, -24000, -16000)); collisionBoxesSide1Right.Add(new ObjectBox(-1000, 7000, 16000, 24000)); this.playerBulletTypeToCollisionBoxesMapping[PlayerBullet.PlayerBulletType.Side1Right] = new DTImmutableList <ObjectBox>(collisionBoxesSide1Right); List <ObjectBox> collisionBoxesSide2Left = new List <ObjectBox>(); collisionBoxesSide2Left.Add(new ObjectBox(-4000, 4000, -4000, 4000)); collisionBoxesSide2Left.Add(new ObjectBox(3000, 11000, -23000, -15000)); collisionBoxesSide2Left.Add(new ObjectBox(-11000, -3000, 15000, 23000)); this.playerBulletTypeToCollisionBoxesMapping[PlayerBullet.PlayerBulletType.Side2Left] = new DTImmutableList <ObjectBox>(collisionBoxesSide2Left); List <ObjectBox> collisionBoxesSide2Right = new List <ObjectBox>(); collisionBoxesSide2Right.Add(new ObjectBox(-4000, 4000, -4000, 4000)); collisionBoxesSide2Right.Add(new ObjectBox(-11000, -3000, -23000, -15000)); collisionBoxesSide2Right.Add(new ObjectBox(3000, 11000, 15000, 23000)); this.playerBulletTypeToCollisionBoxesMapping[PlayerBullet.PlayerBulletType.Side2Right] = new DTImmutableList <ObjectBox>(collisionBoxesSide2Right); List <ObjectBox> collisionBoxesSide3Left = new List <ObjectBox>(); collisionBoxesSide3Left.Add(new ObjectBox(-4000, 4000, -4000, 4000)); collisionBoxesSide3Left.Add(new ObjectBox(7000, 15000, -22000, -14000)); collisionBoxesSide3Left.Add(new ObjectBox(-15000, -7000, 14000, 22000)); this.playerBulletTypeToCollisionBoxesMapping[PlayerBullet.PlayerBulletType.Side3Left] = new DTImmutableList <ObjectBox>(collisionBoxesSide3Left); List <ObjectBox> collisionBoxesSide3Right = new List <ObjectBox>(); collisionBoxesSide3Right.Add(new ObjectBox(-4000, 4000, -4000, 4000)); collisionBoxesSide3Right.Add(new ObjectBox(-15000, -7000, -22000, -14000)); collisionBoxesSide3Right.Add(new ObjectBox(7000, 15000, 14000, 22000)); this.playerBulletTypeToCollisionBoxesMapping[PlayerBullet.PlayerBulletType.Side3Right] = new DTImmutableList <ObjectBox>(collisionBoxesSide3Right); }
private static ResultOfAction HandleAction( ObjectAction action, EnemyObject obj, long playerXMillis, long playerYMillis, long elapsedMillisecondsPerIteration, bool isPlayerDestroyed, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, IDTDeterministicRandom rng) { bool?isParentDestroyed; if (obj.ParentObject == null) { isParentDestroyed = null; } else { isParentDestroyed = obj.ParentObject.IsDestroyed; } switch (action.ObjectActionType) { case ObjectAction.Type.Move: case ObjectAction.Type.StrafeMove: long desiredX = action.MoveToXMillis.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); long desiredY = action.MoveToYMillis.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); long?directionInMillidegrees = DTDanmakuMath.GetMovementDirectionInMillidegrees(currentX: obj.XMillis, currentY: obj.YMillis, desiredX: desiredX, desiredY: desiredY); if (directionInMillidegrees != null) { obj.MovementDirectionInMillidegrees = directionInMillidegrees.Value; if (action.ObjectActionType == ObjectAction.Type.Move) { obj.FacingDirectionInMillidegrees = directionInMillidegrees.Value; } else if (action.ObjectActionType == ObjectAction.Type.StrafeMove) { obj.FacingDirectionInMillidegrees = 180L * 1000L; } else { throw new Exception(); } } return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SetSpeed: case ObjectAction.Type.IncreaseSpeed: case ObjectAction.Type.DecreaseSpeed: long speed = action.SpeedInMillipixelsPerMillisecond.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); if (action.ObjectActionType == ObjectAction.Type.SetSpeed) { obj.SpeedInMillipixelsPerMillisecond = speed; } else if (action.ObjectActionType == ObjectAction.Type.IncreaseSpeed) { obj.SpeedInMillipixelsPerMillisecond += speed; } else if (action.ObjectActionType == ObjectAction.Type.DecreaseSpeed) { obj.SpeedInMillipixelsPerMillisecond -= speed; } else { throw new Exception(); } if (obj.SpeedInMillipixelsPerMillisecond < 0) { obj.SpeedInMillipixelsPerMillisecond = 0; } return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SetPosition: long newXMillisPosition = action.SetXMillisPosition.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); long newYMillisPosition = action.SetYMillisPosition.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); obj.XMillis = newXMillisPosition; obj.YMillis = newYMillisPosition; return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SetFacingDirection: long newFacingDirection = action.SetFacingDirectionInMillidegrees.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); obj.FacingDirectionInMillidegrees = newFacingDirection; return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.Destroy: obj.IsDestroyed = true; return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.DestroyParent: if (obj.ParentObject == null) { throw new Exception(); } obj.ParentObject.IsDestroyed = true; return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SpawnChild: long childXMillis = action.SpawnChildXMillis.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); long childYMillis = action.SpawnChildYMillis.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); EnemyObjectTemplate childObjectTemplate = enemyObjectTemplates[action.SpawnChildObjectTemplateName]; var childObjectNumericVariables = new Dictionary <string, IMathExpression>(); var childObjectBooleanVariables = new Dictionary <string, BooleanExpression>(); if (action.SpawnChildInitialChildNumericVariables != null) { for (int i = 0; i < action.SpawnChildInitialChildNumericVariables.Count; i++) { childObjectNumericVariables.Add(action.SpawnChildInitialChildNumericVariables[i].Name, action.SpawnChildInitialChildNumericVariables[i].Value); } } if (action.SpawnChildInitialChildBooleanVariables != null) { for (int i = 0; i < action.SpawnChildInitialChildBooleanVariables.Count; i++) { childObjectBooleanVariables.Add(action.SpawnChildInitialChildBooleanVariables[i].Name, action.SpawnChildInitialChildBooleanVariables[i].Value); } } var newEnemyObjects = new List <EnemyObject>(); newEnemyObjects.Add(new EnemyObject( template: childObjectTemplate, initialXMillis: childXMillis, initialYMillis: childYMillis, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, isPlayerDestroyed: isPlayerDestroyed, parent: obj, initialNumericVariables: childObjectNumericVariables, initialBooleanVariables: childObjectBooleanVariables, rng: rng)); return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: newEnemyObjects, newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SpawnPowerUp: var powerUpList = new List <Tuple <long, long> >(); powerUpList.Add(new Tuple <long, long>(obj.XMillis, obj.YMillis)); return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: powerUpList, newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SetNumericVariable: obj.NumericVariables[action.SetVariableName] = action.SetNumericVariableValue.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SetBooleanVariable: obj.BooleanVariables[action.SetVariableName] = action.SetBooleanVariableValue.Evaluate( obj.GetEnemyObjectExpressionInfo(), isParentDestroyed: isParentDestroyed, isPlayerDestroyed: isPlayerDestroyed, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SetParentNumericVariable: if (obj.ParentObject == null) { throw new Exception(); } obj.ParentObject.NumericVariables[action.SetVariableName] = action.SetNumericVariableValue.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.SetParentBooleanVariable: { if (obj.ParentObject == null) { throw new Exception(); } obj.ParentObject.BooleanVariables[action.SetVariableName] = action.SetBooleanVariableValue.Evaluate( obj.GetEnemyObjectExpressionInfo(), isParentDestroyed: obj.ParentObject.IsDestroyed, isPlayerDestroyed: isPlayerDestroyed, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); } case ObjectAction.Type.EndLevel: return(new ResultOfAction( newObjectAction: action, shouldEndLevel: true, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.PlaySoundEffect: { var newSoundEffectsToPlay = new List <string>(); newSoundEffectsToPlay.Add(action.SoundEffectName); return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: newSoundEffectsToPlay, bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); } case ObjectAction.Type.DisplayBossHealthBar: { long bossHealthMeterNumber = action.BossHealthBarMeterNumber.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); long bossHealthMeterMilliPercentage = action.BossHealthBarMilliPercentage.Evaluate( obj.GetEnemyObjectExpressionInfo(), playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: bossHealthMeterNumber, bossHealthMeterMilliPercentage: bossHealthMeterMilliPercentage)); } case ObjectAction.Type.SetSpriteName: obj.SpriteName = action.SpriteName; return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); case ObjectAction.Type.Conditional: bool shouldExecute = action.Conditional.Evaluate( obj.GetEnemyObjectExpressionInfo(), isParentDestroyed: isParentDestroyed, isPlayerDestroyed: isPlayerDestroyed, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); if (shouldExecute) { var a = HandleAction( action: action.ConditionalAction, obj: obj, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, isPlayerDestroyed: isPlayerDestroyed, enemyObjectTemplates: enemyObjectTemplates, rng: rng); return(new ResultOfAction( newObjectAction: ObjectAction.Condition(action.Conditional, a.NewObjectAction), shouldEndLevel: a.ShouldEndLevel, newEnemyObjects: a.NewEnemyObjects, newPowerUps: a.NewPowerUps, newSoundEffectsToPlay: a.NewSoundEffectsToPlay, bossHealthMeterNumber: a.BossHealthMeterNumber, bossHealthMeterMilliPercentage: a.BossHealthMeterMilliPercentage)); } else { return(new ResultOfAction( newObjectAction: action, shouldEndLevel: false, newEnemyObjects: new List <EnemyObject>(), newPowerUps: new List <Tuple <long, long> >(), newSoundEffectsToPlay: new List <string>(), bossHealthMeterNumber: null, bossHealthMeterMilliPercentage: null)); } case ObjectAction.Type.ConditionalNextAction: ResultOfAction actionResult = HandleAction( action: action.ConditionalNextActionCurrentAction, obj: obj, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, isPlayerDestroyed: isPlayerDestroyed, enemyObjectTemplates: enemyObjectTemplates, rng: rng); bool shouldMoveToNext = action.ConditionalNextActionConditional.Evaluate( obj.GetEnemyObjectExpressionInfo(), isParentDestroyed: isParentDestroyed, isPlayerDestroyed: isPlayerDestroyed, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng); return(new ResultOfAction( newObjectAction: shouldMoveToNext ? action.ConditionalNextActionNextAction : ObjectAction.ConditionalNextAction(actionResult.NewObjectAction, action.ConditionalNextActionConditional, action.ConditionalNextActionNextAction), shouldEndLevel: actionResult.ShouldEndLevel, newEnemyObjects: actionResult.NewEnemyObjects, newPowerUps: actionResult.NewPowerUps, newSoundEffectsToPlay: actionResult.NewSoundEffectsToPlay, bossHealthMeterNumber: actionResult.BossHealthMeterNumber, bossHealthMeterMilliPercentage: actionResult.BossHealthMeterMilliPercentage)); case ObjectAction.Type.Union: { bool shouldEndLevel = false; var newUnionActions = new List <ObjectAction>(); var enemyObjects = new List <EnemyObject>(); var newPowerUps = new List <Tuple <long, long> >(); var newSoundEffectsToPlay = new List <string>(); long?bossHealthMeterNumber = null; long?bossHealthMeterMilliPercentage = null; for (var i = 0; i < action.UnionActions.Count; i++) { ResultOfAction r = HandleAction( action: action.UnionActions[i], obj: obj, playerXMillis: playerXMillis, playerYMillis: playerYMillis, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, isPlayerDestroyed: isPlayerDestroyed, enemyObjectTemplates: enemyObjectTemplates, rng: rng); newUnionActions.Add(r.NewObjectAction); if (r.ShouldEndLevel) { shouldEndLevel = true; } foreach (EnemyObject newEnemyObj in r.NewEnemyObjects) { enemyObjects.Add(newEnemyObj); } foreach (var newPowerUp in r.NewPowerUps) { newPowerUps.Add(newPowerUp); } foreach (var newSoundEffect in r.NewSoundEffectsToPlay) { newSoundEffectsToPlay.Add(newSoundEffect); } if (r.BossHealthMeterNumber != null) { bossHealthMeterNumber = r.BossHealthMeterNumber; } if (r.BossHealthMeterMilliPercentage != null) { bossHealthMeterMilliPercentage = r.BossHealthMeterMilliPercentage; } } return(new ResultOfAction( newObjectAction: ObjectAction.Union(newUnionActions), shouldEndLevel: shouldEndLevel, newEnemyObjects: enemyObjects, newPowerUps: newPowerUps, newSoundEffectsToPlay: newSoundEffectsToPlay, bossHealthMeterNumber: bossHealthMeterNumber, bossHealthMeterMilliPercentage: bossHealthMeterMilliPercentage)); } default: throw new Exception(); } }
public static ObjectAction ConditionalNextAction(ObjectAction currentAction, BooleanExpression condition, ObjectAction nextAction) { ObjectAction action = new ObjectAction(); action.ObjectActionType = Type.ConditionalNextAction; action.ConditionalNextActionCurrentAction = currentAction; action.ConditionalNextActionConditional = condition; action.ConditionalNextActionNextAction = nextAction; return(action); }
public static ObjectAction SpawnEnemyThatMovesToSpecificLocation( long initialXMillis, long initialYMillis, List <Tuple <long, long> > movementPath, long movementSpeedInPixelsPerSecond, bool shouldStrafe, long bulletXOffset, long bulletYOffset, IMathExpression initialShootCooldownInMillis, IMathExpression shootCooldownInMillis, long bulletSpeedInPixelsPerSecond, IMathExpression initialMilliHP, long chanceToDropPowerUpInMilliPercent, // ranges from 0 (meaning 0%) to 100,000 (meaning 100%) List <ObjectBox> damageBoxes, // nullable List <ObjectBox> collisionBoxes, // nullable DTDanmakuImage sprite, Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, Dictionary <string, DTDanmakuSound> soundNameToSoundDictionary, GuidGenerator guidGenerator) { ObjectAction moveAction = MoveToSpecifiedLocations( initialXMillis: initialXMillis, initialYMillis: initialYMillis, movementPath: movementPath, speedInPixelsPerSecond: movementSpeedInPixelsPerSecond, shouldStrafe: shouldStrafe, shouldDestroyAtEndOfMovementPath: true, guidGenerator: guidGenerator); ObjectAction shootAction = ShootBulletStraightDownAction( initialShootCooldownInMillis: initialShootCooldownInMillis, shootCooldownInMillis: shootCooldownInMillis, xOffset: bulletXOffset, yOffset: bulletYOffset, bulletSpeedInPixelsPerSecond: bulletSpeedInPixelsPerSecond, spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, guidGenerator: guidGenerator); ObjectAction destroyAction = DestroyWhenHpIsZeroAndMaybeDropPowerUp( chanceToDropPowerUpInMilliPercent: chanceToDropPowerUpInMilliPercent, spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); string spriteName = guidGenerator.NextGuid(); spriteNameToImageDictionary.Add(spriteName, sprite); EnemyObjectTemplate enemyObjectTemplate = EnemyObjectTemplate.Enemy( action: ObjectAction.Union(moveAction, shootAction, destroyAction), initialMilliHP: initialMilliHP, damageBoxes: damageBoxes, collisionBoxes: collisionBoxes, spriteName: spriteName); string templateName = guidGenerator.NextGuid(); enemyObjectTemplates.Add(templateName, enemyObjectTemplate); return(ObjectAction.SpawnChild( childXMillis: MathExpression.Constant(initialXMillis), childYMillis: MathExpression.Constant(initialYMillis), childObjectTemplateName: templateName, childInitialNumericVariables: null, childInitialBooleanVariables: null)); }
public static ObjectAction Noop() { return(ObjectAction.IncreaseSpeed( speedInMillipixelsPerMillisecond: MathExpression.Constant(0))); }
public static GenerateDestructionAnimationResult GenerateDestructionAnimation( List <DTDanmakuImage> orderedSprites, long millisecondsPerSprite, GuidGenerator guidGenerator) { Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary = new Dictionary <string, DTDanmakuImage>(); Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates = new Dictionary <string, EnemyObjectTemplate>(); ObjectAction incrementElapsedTimeVariable = ObjectAction.SetNumericVariable( variableName: elapsedTimeInMillisVariableName, variableValue: MathExpression.Add( leftSide: MathExpression.Variable(variableName: elapsedTimeInMillisVariableName), rightSide: MathExpression.ElapsedMillisecondsPerIteration())); long startMilliseconds = 0; List <ObjectAction> actionsToUnionTogether = new List <ObjectAction>(); actionsToUnionTogether.Add(incrementElapsedTimeVariable); for (int i = 0; i < orderedSprites.Count; i++) { DTDanmakuImage image = orderedSprites[i]; string spriteName = guidGenerator.NextGuid(); string childObjectTemplateName = guidGenerator.NextGuid(); Tuple <ObjectAction, EnemyObjectTemplate> result = SpawnOneDestructionSpriteImage( startMilliseconds: startMilliseconds, endMilliseconds: startMilliseconds + millisecondsPerSprite, childObjectTemplateName: childObjectTemplateName, spriteName: spriteName, isLast: i == orderedSprites.Count - 1); startMilliseconds += millisecondsPerSprite; actionsToUnionTogether.Add(result.Item1); spriteNameToImageDictionary.Add(spriteName, image); enemyObjectTemplates.Add(childObjectTemplateName, result.Item2); } string placeholderObjectTemplateName = guidGenerator.NextGuid(); List <ObjectAction.InitialChildNumericVariableInfo> initialChildNumericVariables = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialChildNumericVariables.Add(new ObjectAction.InitialChildNumericVariableInfo(elapsedTimeInMillisVariableName, MathExpression.Constant(0))); ObjectAction action = ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.YMillis(), childObjectTemplateName: placeholderObjectTemplateName, childInitialNumericVariables: initialChildNumericVariables, childInitialBooleanVariables: null); EnemyObjectTemplate placeholderObjectTemplate = EnemyObjectTemplate.Enemy( action: ObjectAction.Union(actionsToUnionTogether), initialMilliHP: null, damageBoxes: null, collisionBoxes: null, spriteName: null); enemyObjectTemplates.Add(placeholderObjectTemplateName, placeholderObjectTemplate); return(new GenerateDestructionAnimationResult( objectAction: action, spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates)); }
public static GenerateEnemiesResult GenerateEnemies( long elapsedMillisecondsPerIteration, IDTDeterministicRandom rng, GuidGenerator guidGenerator) { List <EnemyObject> enemyObjects = new List <EnemyObject>(); Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary = new Dictionary <string, DTDanmakuImage>(); Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates = new Dictionary <string, EnemyObjectTemplate>(); Dictionary <string, DTDanmakuSound> soundNameToSoundDictionary = new Dictionary <string, DTDanmakuSound>(); ObjectAction spawnWave1Enemy = GenerateWave1Enemy( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnWave2Enemy = GenerateWave2Enemy( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnWave3Enemy = GenerateWave3Enemy( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnWave4Enemy = GenerateWave4Enemy( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnSniperEnemy = SniperEnemyGenerator.SpawnSniperEnemy( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnEliteSniperEnemy = EliteSniperEnemyGenerator.SpawnEliteSniperEnemy( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnOrbiterEnemy = OrbiterEnemyGenerator.SpawnOrbiterEnemy( xMillis: MathExpression.Add(MathExpression.Constant(300 * 1000), MathExpression.RandomInteger(400 * 1000)), spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnEliteOrbiterEnemy = EliteOrbiterEnemyGenerator.SpawnEliteOrbiterEnemy( xMillis: MathExpression.Add(MathExpression.Constant(300 * 1000), MathExpression.RandomInteger(400 * 1000)), spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnBarrageEnemy = BarrageEnemyGenerator.SpawnBarrageEnemy( xMillis: MathExpression.Add(MathExpression.Constant(300 * 1000), MathExpression.RandomInteger(400 * 1000)), spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnEliteBarrageEnemy = EliteBarrageEnemyGenerator.SpawnEliteBarrageEnemy( xMillis: MathExpression.Add(MathExpression.Constant(300 * 1000), MathExpression.RandomInteger(400 * 1000)), spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); ObjectAction spawnBoss = BossEnemyGenerator.SpawnBossEnemy( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary, guidGenerator: guidGenerator); for (int i = 0; i < 10; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 1000 * i, action: spawnWave1Enemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 10; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 3000 + 1000 * i, action: spawnWave2Enemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 6; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 16000 + 1000 * i, action: spawnSniperEnemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 6; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 20000 + 6000 * i, action: spawnOrbiterEnemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 6; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 23000 + 1500 * i, action: spawnWave3Enemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 6; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 25500 + 1500 * i, action: spawnWave4Enemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 4; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 29000 + 1700 * i, action: spawnBarrageEnemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 7; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 33000 + 1250 * i, action: spawnEliteSniperEnemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 4; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 38000 + 2100 * i, action: spawnEliteBarrageEnemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 8; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 43000 + 500 * i, action: spawnSniperEnemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 8; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 43250 + 500 * i, action: spawnEliteSniperEnemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } for (int i = 0; i < 2; i++) { enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 56000 + 6000 * i, action: spawnEliteOrbiterEnemy, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); } enemyObjects.Add(CreateActionExecutor( millisecondsToWait: 82000, action: spawnBoss, elapsedMillisecondsPerIteration: elapsedMillisecondsPerIteration, rng: rng, guidGenerator: guidGenerator)); return(new GenerateEnemiesResult( enemyObjects: enemyObjects, spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, soundNameToSoundDictionary: soundNameToSoundDictionary)); }
private static ObjectAction GetMoveAction( GuidGenerator guidGenerator) { string variableName = guidGenerator.NextGuid(); ObjectAction initializeVariable = ObjectAction.SetNumericVariable( variableName: variableName, variableValue: MathExpression.Constant(0)); ObjectAction incrementVariable = ObjectAction.SetNumericVariable( variableName: variableName, variableValue: MathExpression.Add(MathExpression.Variable(variableName), MathExpression.ElapsedMillisecondsPerIteration())); ObjectAction initializeAndIncrementVariable = ObjectAction.ConditionalNextAction( currentAction: initializeVariable, condition: BooleanExpression.True(), nextAction: incrementVariable); ObjectAction teleportToInitialLocation = ObjectAction.SetPosition( xMillis: MathExpression.Add(50 * 1000, MathExpression.RandomInteger(900 * 1000)), yMillis: MathExpression.Constant(800 * 1000)); ObjectAction faceTowardsPlayer = ObjectAction.Move( moveToXMillis: MathExpression.PlayerXMillis(), moveToYMillis: MathExpression.Min(MathExpression.PlayerYMillis(), 300 * 1000)); ObjectAction setInitialSpeed = ObjectActionGenerator.DoOnce( ObjectAction.SetSpeed( speedInMillipixelsPerMillisecond: MathExpression.Constant(60))); ObjectAction slowDownSpeed1 = ObjectAction.Condition( condition: BooleanExpression.GreaterThanOrEqualTo( MathExpression.Variable(variableName), 1 * 1000), action: ObjectActionGenerator.DoOnce( ObjectAction.SetSpeed( speedInMillipixelsPerMillisecond: MathExpression.Constant(40)))); ObjectAction slowDownSpeed2 = ObjectAction.Condition( condition: BooleanExpression.GreaterThanOrEqualTo( MathExpression.Variable(variableName), 2 * 1000), action: ObjectActionGenerator.DoOnce( ObjectAction.SetSpeed( speedInMillipixelsPerMillisecond: MathExpression.Constant(20)))); ObjectAction stopMovement = ObjectAction.Condition( condition: BooleanExpression.GreaterThanOrEqualTo( MathExpression.Variable(variableName), 3 * 1000), action: ObjectActionGenerator.DoOnce( ObjectAction.SetSpeed( speedInMillipixelsPerMillisecond: MathExpression.Constant(0)))); BooleanExpression ShouldLeave1 = BooleanExpression.GreaterThanOrEqualTo( MathExpression.Variable(variableName), 10 * 1000); ObjectAction leave1 = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.ElapsedMillisecondsPerIteration(), MathExpression.Constant(25)))); ObjectAction leave1ConditionalAction = ObjectAction.Condition( condition: ShouldLeave1, action: leave1); BooleanExpression shouldLeave2 = BooleanExpression.GreaterThanOrEqualTo( MathExpression.Variable(variableName), 11 * 1000); ObjectAction leave2 = ObjectAction.SetPosition( xMillis: MathExpression.XMillis(), yMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Multiply(MathExpression.ElapsedMillisecondsPerIteration(), MathExpression.Constant(50)))); ObjectAction leave2ConditionalAction = ObjectAction.ConditionalNextAction( currentAction: leave1ConditionalAction, condition: shouldLeave2, nextAction: leave2); ObjectAction shouldDestroy = ObjectAction.Condition( condition: BooleanExpression.And(shouldLeave2, BooleanExpression.GreaterThanOrEqualTo(MathExpression.YMillis(), 800 * 1000)), action: ObjectAction.Destroy()); return(ObjectAction.ConditionalNextAction( currentAction: teleportToInitialLocation, condition: BooleanExpression.True(), nextAction: ObjectAction.Union(faceTowardsPlayer, initializeAndIncrementVariable, setInitialSpeed, slowDownSpeed1, slowDownSpeed2, stopMovement, leave2ConditionalAction, shouldDestroy))); }
private static ObjectAction Phase1ShootAction( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, GuidGenerator guidGenerator) { string singleBulletSpriteName = guidGenerator.NextGuid(); spriteNameToImageDictionary.Add(singleBulletSpriteName, DTDanmakuImage.BossPhase1EnemyBullet); long buffer = 100; BooleanExpression shouldDestroySingleBullet = BooleanExpression.Or( BooleanExpression.GreaterThan(MathExpression.XMillis(), MathExpression.Constant((1000 + buffer) * 1000)), BooleanExpression.LessThan(MathExpression.XMillis(), MathExpression.Constant((0 - buffer) * 1000)), BooleanExpression.GreaterThan(MathExpression.YMillis(), MathExpression.Constant((700 + buffer) * 1000)), BooleanExpression.LessThan(MathExpression.YMillis(), MathExpression.Constant((0 - buffer) * 1000))); ObjectAction destroySingleBulletAction = ObjectAction.Condition( condition: shouldDestroySingleBullet, action: ObjectAction.Destroy()); DTDanmakuMath.MathExpressionOffset singleBulletOffset = DTDanmakuMath.GetOffset( millipixels: MathExpression.Multiply(MathExpression.Variable("speed"), MathExpression.ElapsedMillisecondsPerIteration()), movementDirectionInMillidegrees: MathExpression.Variable("direction")); List <ObjectBox> collisionBoxes = new List <ObjectBox>(); collisionBoxes.Add(new ObjectBox(lowerXMillis: -3000, upperXMillis: 3000, lowerYMillis: -5000, upperYMillis: 5000)); collisionBoxes.Add(new ObjectBox(lowerXMillis: -5000, upperXMillis: 5000, lowerYMillis: -3000, upperYMillis: 3000)); EnemyObjectTemplate singleBulletTemplate = EnemyObjectTemplate.EnemyBullet( action: ObjectAction.Union( ObjectAction.SetFacingDirection(MathExpression.Variable("direction")), ObjectAction.SetPosition( xMillis: MathExpression.Add(MathExpression.XMillis(), singleBulletOffset.DeltaXInMillipixels), yMillis: MathExpression.Add(MathExpression.YMillis(), singleBulletOffset.DeltaYInMillipixels)), destroySingleBulletAction), initialMilliHP: null, damageBoxes: null, collisionBoxes: collisionBoxes, spriteName: singleBulletSpriteName); string singleBulletTemplateName = guidGenerator.NextGuid(); enemyObjectTemplates.Add(singleBulletTemplateName, singleBulletTemplate); List <ObjectAction> spawnBulletActions = new List <ObjectAction>(); string randomOffsetVariable = guidGenerator.NextGuid(); for (int i = 0; i < 36; i++) { List <ObjectAction.InitialChildNumericVariableInfo> initialNumericVariables = new List <ObjectAction.InitialChildNumericVariableInfo>(); initialNumericVariables.Add( new ObjectAction.InitialChildNumericVariableInfo( name: "direction", value: MathExpression.Add(MathExpression.Variable(randomOffsetVariable), MathExpression.Constant(i * 10 * 1000)))); initialNumericVariables.Add( new ObjectAction.InitialChildNumericVariableInfo( name: "speed", value: MathExpression.Add(MathExpression.Constant(100), MathExpression.RandomInteger(100)))); spawnBulletActions.Add(ObjectAction.SpawnChild( childXMillis: MathExpression.XMillis(), childYMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Constant(-60000)), childObjectTemplateName: singleBulletTemplateName, childInitialNumericVariables: initialNumericVariables, childInitialBooleanVariables: null)); } List <ObjectAction> actionList = new List <ObjectAction>(); actionList.Add(ObjectAction.SetNumericVariable(randomOffsetVariable, MathExpression.RandomInteger(MathExpression.Constant(360 * 1000)))); foreach (ObjectAction spawnBulletAction in spawnBulletActions) { actionList.Add(spawnBulletAction); } ObjectAction shootBulletAction = ObjectAction.Union(actionList); string shootCooldown = guidGenerator.NextGuid(); ObjectAction initializeShootCooldown = ObjectAction.SetNumericVariable( variableName: shootCooldown, variableValue: MathExpression.Constant(2000)); ObjectAction decrementShootCooldown = ObjectAction.SetNumericVariable( variableName: shootCooldown, variableValue: MathExpression.Subtract(MathExpression.Variable(shootCooldown), MathExpression.ElapsedMillisecondsPerIteration())); ObjectAction shootWhenCooldownIsZero = ObjectAction.Condition( condition: BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(shootCooldown), MathExpression.Constant(0)), action: ObjectAction.Union(initializeShootCooldown, shootBulletAction)); return(ObjectAction.Union( ObjectActionGenerator.DoOnce(initializeShootCooldown), decrementShootCooldown, shootWhenCooldownIsZero)); }