private static ObjectAction GetBulletMovementAction( GuidGenerator guidGenerator) { long bulletSpeedInPixelsPerSecond = 250; ObjectAction moveAction = ObjectActionGenerator.MoveTowardsLocation( currentX: MathExpression.XMillis(), currentY: MathExpression.YMillis(), desiredX: MathExpression.PlayerXMillis(), desiredY: MathExpression.Min(MathExpression.PlayerYMillis(), 300 * 1000), movementSpeedInPixelsPerSecond: MathExpression.Constant(bulletSpeedInPixelsPerSecond), shouldSnapshot: true, guidGenerator: guidGenerator); 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()); return(ObjectAction.Union(moveAction, destroyAction)); }
public static ObjectAction DestroyWhenHpIsZeroAndMaybeDropPowerUp( long chanceToDropPowerUpInMilliPercent, // ranges from 0 (meaning 0%) to 100,000 (meaning 100%) Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, Dictionary <string, DTDanmakuSound> soundNameToSoundDictionary, GuidGenerator guidGenerator) { string soundEffectName = guidGenerator.NextGuid(); BooleanExpression isHpZero = BooleanExpression.LessThanOrEqualTo( MathExpression.MilliHP(), MathExpression.Constant(0)); ObjectAction playEnemyDeathSoundEffectAction = ObjectAction.PlaySoundEffect(soundEffectName: soundEffectName); soundNameToSoundDictionary.Add(soundEffectName, DTDanmakuSound.EnemyDeath); DestructionAnimationGenerator.GenerateDestructionAnimationResult generateDestructionAnimationResult = DestructionAnimationGenerator.GenerateDestructionAnimation( orderedSprites: new List <DTDanmakuImage> { DTDanmakuImage.Explosion1, DTDanmakuImage.Explosion2, DTDanmakuImage.Explosion3, DTDanmakuImage.Explosion4, DTDanmakuImage.Explosion5, DTDanmakuImage.Explosion6, DTDanmakuImage.Explosion7, DTDanmakuImage.Explosion8, DTDanmakuImage.Explosion9 }, millisecondsPerSprite: 20, guidGenerator: guidGenerator); foreach (var entry in generateDestructionAnimationResult.spriteNameToImageDictionary) { spriteNameToImageDictionary.Add(entry.Key, entry.Value); } foreach (var entry in generateDestructionAnimationResult.enemyObjectTemplates) { enemyObjectTemplates.Add(entry.Key, entry.Value); } ObjectAction possiblySpawnPowerUpAction = ObjectAction.Condition( condition: BooleanExpression.LessThan( MathExpression.RandomInteger(MathExpression.Constant(100 * 1000)), MathExpression.Constant(chanceToDropPowerUpInMilliPercent)), action: ObjectAction.SpawnPowerUp()); return(ObjectAction.Condition( condition: isHpZero, action: ObjectAction.Union( playEnemyDeathSoundEffectAction, generateDestructionAnimationResult.objectAction, possiblySpawnPowerUpAction, ObjectAction.Destroy()))); }
private static ObjectAction GetSatelliteMoveAndDestroyAction( long initialAngleInMillidegrees, GuidGenerator guidGenerator) { string angleVariableName = guidGenerator.NextGuid(); ObjectAction initializeAngleVariableAction = ObjectActionGenerator.DoOnce( ObjectAction.SetNumericVariable(angleVariableName, MathExpression.Constant(initialAngleInMillidegrees))); ObjectAction updateAngleVariableAction = ObjectAction.Union( ObjectAction.SetNumericVariable( angleVariableName, MathExpression.Add(MathExpression.Variable(angleVariableName), MathExpression.Multiply(MathExpression.Constant(50), MathExpression.ElapsedMillisecondsPerIteration()))), ObjectAction.Condition( condition: BooleanExpression.GreaterThan(MathExpression.Variable(angleVariableName), MathExpression.Constant(360 * 1000)), action: ObjectAction.SetNumericVariable(angleVariableName, MathExpression.Subtract(MathExpression.Variable(angleVariableName), MathExpression.Constant(360 * 1000)))), ObjectAction.Condition( condition: BooleanExpression.GreaterThan(MathExpression.Variable(angleVariableName), MathExpression.Constant(360 * 1000)), action: ObjectAction.SetNumericVariable(angleVariableName, MathExpression.Constant(0)))); long radius = 110; ObjectAction setPositionAction = ObjectAction.SetPosition( xMillis: MathExpression.Add(MathExpression.ParentXMillis(), MathExpression.Multiply(MathExpression.Constant(radius), MathExpression.CosineScaled(MathExpression.Multiply(MathExpression.Variable(angleVariableName), MathExpression.Constant(-1))))), yMillis: MathExpression.Add(MathExpression.ParentYMillis(), MathExpression.Multiply(MathExpression.Constant(radius), MathExpression.SineScaled(MathExpression.Multiply(MathExpression.Variable(angleVariableName), MathExpression.Constant(-1)))))); string facingAngleVariableName = guidGenerator.NextGuid(); ObjectAction initializeFacingAngleVariableAction = ObjectActionGenerator.DoOnce( ObjectAction.SetNumericVariable(facingAngleVariableName, MathExpression.RandomInteger(360 * 1000))); ObjectAction updateFacingAngleVariableAction = ObjectAction.Union( ObjectAction.SetNumericVariable( facingAngleVariableName, MathExpression.Add(MathExpression.Variable(facingAngleVariableName), MathExpression.Multiply(MathExpression.Constant(500), MathExpression.ElapsedMillisecondsPerIteration()))), ObjectAction.Condition( condition: BooleanExpression.GreaterThan(MathExpression.Variable(facingAngleVariableName), MathExpression.Constant(360 * 1000)), action: ObjectAction.SetNumericVariable(facingAngleVariableName, MathExpression.Subtract(MathExpression.Variable(facingAngleVariableName), MathExpression.Constant(360 * 1000)))), ObjectAction.Condition( condition: BooleanExpression.GreaterThan(MathExpression.Variable(facingAngleVariableName), MathExpression.Constant(360 * 1000)), action: ObjectAction.SetNumericVariable(facingAngleVariableName, MathExpression.Constant(0)))); ObjectAction setFacingDirectionAction = ObjectAction.SetFacingDirection(MathExpression.Multiply(MathExpression.Variable(facingAngleVariableName), MathExpression.Constant(-1))); ObjectAction destroyAction = ObjectAction.Condition( condition: BooleanExpression.IsParentDestroyed(), action: ObjectAction.Destroy()); return(ObjectAction.Union( initializeAngleVariableAction, updateAngleVariableAction, setPositionAction, initializeFacingAngleVariableAction, updateFacingAngleVariableAction, setFacingDirectionAction, destroyAction)); }
public static ObjectAction MoveToSpecifiedLocations( // enemy will teleport to this initial location long initialXMillis, long initialYMillis, List <Tuple <long, long> > movementPath, long speedInPixelsPerSecond, bool shouldStrafe, bool shouldDestroyAtEndOfMovementPath, GuidGenerator guidGenerator) { ObjectAction currentAction = shouldDestroyAtEndOfMovementPath ? ObjectAction.Destroy() : ObjectActionGenerator.Noop(); for (int i = movementPath.Count - 1; i >= 0; i--) { long endingX = movementPath[i].Item1; long endingY = movementPath[i].Item2; long startingX = i == 0 ? initialXMillis : movementPath[i - 1].Item1; long startingY = i == 0 ? initialYMillis : movementPath[i - 1].Item2; Tuple <ObjectAction, BooleanExpression> helper = MoveToSpecifiedLocations_Helper( startingXMillis: startingX, startingYMillis: startingY, endingXMillis: endingX, endingYMillis: endingY, speedInPixelsPerSecond: speedInPixelsPerSecond, shouldStrafe: shouldStrafe, guidGenerator: guidGenerator); currentAction = ObjectAction.ConditionalNextAction( currentAction: helper.Item1, condition: helper.Item2, nextAction: currentAction); } ObjectAction teleportToInitialLocation = ObjectAction.SetPosition( xMillis: MathExpression.Constant(initialXMillis), yMillis: MathExpression.Constant(initialYMillis)); return(ObjectAction.ConditionalNextAction( currentAction: teleportToInitialLocation, condition: BooleanExpression.True(), nextAction: currentAction)); }
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)); }
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 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 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 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))); }
// 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 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)); }
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)); }
// 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); } }
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))))))))); }