private static ObjectAction GetSatelliteShootAction( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, GuidGenerator guidGenerator) { IMathExpression initialShootCooldownInMillis = MathExpression.RandomInteger(6000); IMathExpression shootCooldownInMillis = MathExpression.Add(5000, MathExpression.RandomInteger(1000)); string cooldownVariableName = guidGenerator.NextGuid(); ObjectAction initialStartCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, initialShootCooldownInMillis); ObjectAction startCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, shootCooldownInMillis); ObjectAction decrementCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, MathExpression.Subtract(MathExpression.Variable(cooldownVariableName), MathExpression.ElapsedMillisecondsPerIteration())); ObjectAction createBulletAction = SpawnSatelliteBullet( spriteNameToImageDictionary: spriteNameToImageDictionary, enemyObjectTemplates: enemyObjectTemplates, guidGenerator: guidGenerator); var createBulletWhenCooldownFinishedAction = ObjectAction.Condition( condition: BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(cooldownVariableName), MathExpression.Constant(0)), action: ObjectAction.Union(startCooldownAction, createBulletAction)); return(ObjectAction.ConditionalNextAction( currentAction: initialStartCooldownAction, condition: BooleanExpression.True(), nextAction: ObjectAction.Union(decrementCooldownAction, createBulletWhenCooldownFinishedAction))); }
public static ObjectAction DoOnce(ObjectAction action) { return(ObjectAction.ConditionalNextAction( currentAction: action, condition: BooleanExpression.True(), nextAction: ObjectActionGenerator.Noop())); }
private static ObjectAction GetShootBulletAction( Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, GuidGenerator guidGenerator) { IMathExpression initialShootCooldownInMillis = MathExpression.RandomInteger(2750); IMathExpression shootCooldownInMillis = MathExpression.Add(1750, MathExpression.RandomInteger(1000)); string cooldownVariableName = guidGenerator.NextGuid(); string childObjectTemplateName = guidGenerator.NextGuid(); string enemyBulletSpriteName = guidGenerator.NextGuid(); IMathExpression facingAngleInMillidegrees = DTDanmakuMath.GetMovementDirectionInMillidegrees( currentX: MathExpression.XMillis(), currentY: MathExpression.YMillis(), desiredX: MathExpression.PlayerXMillis(), desiredY: MathExpression.Min(MathExpression.PlayerYMillis(), 300 * 1000)); DTDanmakuMath.MathExpressionOffset deltaXAndY = DTDanmakuMath.GetOffset( millipixels: MathExpression.Constant(40000), movementDirectionInMillidegrees: facingAngleInMillidegrees); ObjectAction initialStartCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, initialShootCooldownInMillis); ObjectAction startCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, shootCooldownInMillis); ObjectAction decrementCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, MathExpression.Subtract(MathExpression.Variable(cooldownVariableName), MathExpression.ElapsedMillisecondsPerIteration())); ObjectAction createBulletAction = ObjectAction.SpawnChild( childXMillis: MathExpression.Add(MathExpression.XMillis(), deltaXAndY.DeltaXInMillipixels), childYMillis: MathExpression.Add(MathExpression.YMillis(), deltaXAndY.DeltaYInMillipixels), childObjectTemplateName: childObjectTemplateName, childInitialNumericVariables: null, childInitialBooleanVariables: null); List <ObjectBox> collisionBoxes = new List <ObjectBox>(); collisionBoxes.Add(new ObjectBox(lowerXMillis: -4000, upperXMillis: 4000, lowerYMillis: -4000, upperYMillis: 4000)); enemyObjectTemplates.Add(childObjectTemplateName, EnemyObjectTemplate.EnemyBullet( action: ObjectAction.Union(GetBulletMovementAction(guidGenerator: guidGenerator), GetBulletAnimationAction(guidGenerator: guidGenerator)), initialMilliHP: null, damageBoxes: null, collisionBoxes: collisionBoxes, spriteName: enemyBulletSpriteName)); spriteNameToImageDictionary.Add(enemyBulletSpriteName, DTDanmakuImage.EliteSniperEnemyBullet); var createBulletWhenCooldownFinishedAction = ObjectAction.Condition( condition: BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(cooldownVariableName), MathExpression.Constant(0)), action: ObjectAction.Union(startCooldownAction, createBulletAction)); return(ObjectAction.ConditionalNextAction( currentAction: initialStartCooldownAction, condition: BooleanExpression.True(), nextAction: ObjectAction.Union(decrementCooldownAction, createBulletWhenCooldownFinishedAction))); }
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 Delay( ObjectAction action, long milliseconds, GuidGenerator guidGenerator) { string guid = guidGenerator.NextGuid(); return(ObjectAction.ConditionalNextAction( currentAction: ObjectAction.SetNumericVariable(guid, MathExpression.Constant(0)), condition: BooleanExpression.True(), nextAction: ObjectAction.ConditionalNextAction( currentAction: ObjectAction.SetNumericVariable(guid, MathExpression.Add(MathExpression.ElapsedMillisecondsPerIteration(), MathExpression.Variable(guid))), condition: BooleanExpression.GreaterThanOrEqualTo(MathExpression.Variable(guid), MathExpression.Constant(milliseconds)), nextAction: action))); }
public static ObjectAction ShootBulletStraightDownAction( IMathExpression initialShootCooldownInMillis, IMathExpression shootCooldownInMillis, // Where the bullet should spawn (relative to the enemy shooting the bullet) long xOffset, long yOffset, long bulletSpeedInPixelsPerSecond, Dictionary <string, DTDanmakuImage> spriteNameToImageDictionary, Dictionary <string, EnemyObjectTemplate> enemyObjectTemplates, GuidGenerator guidGenerator) { string cooldownVariableName = guidGenerator.NextGuid(); string childObjectTemplateName = guidGenerator.NextGuid(); string enemyBulletSpriteName = guidGenerator.NextGuid(); ObjectAction initialStartCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, initialShootCooldownInMillis); ObjectAction startCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, shootCooldownInMillis); ObjectAction decrementCooldownAction = ObjectAction.SetNumericVariable(cooldownVariableName, MathExpression.Subtract(MathExpression.Variable(cooldownVariableName), MathExpression.ElapsedMillisecondsPerIteration())); ObjectAction createBulletAction = ObjectAction.SpawnChild( childXMillis: MathExpression.Add(MathExpression.XMillis(), MathExpression.Constant(xOffset)), childYMillis: MathExpression.Add(MathExpression.YMillis(), MathExpression.Constant(yOffset)), childObjectTemplateName: childObjectTemplateName, childInitialNumericVariables: null, childInitialBooleanVariables: null); List <ObjectBox> collisionBoxes = new List <ObjectBox>(); collisionBoxes.Add(new ObjectBox(lowerXMillis: -3000, upperXMillis: 3000, lowerYMillis: -23000, upperYMillis: 23000)); enemyObjectTemplates.Add(childObjectTemplateName, EnemyObjectTemplate.EnemyBullet( action: BulletStraightDownAction(bulletSpeedInPixelsPerSecond: bulletSpeedInPixelsPerSecond), initialMilliHP: null, damageBoxes: null, collisionBoxes: collisionBoxes, spriteName: enemyBulletSpriteName)); spriteNameToImageDictionary.Add(enemyBulletSpriteName, DTDanmakuImage.EnemyBullet); var createBulletWhenCooldownFinishedAction = ObjectAction.Condition( condition: BooleanExpression.LessThanOrEqualTo(MathExpression.Variable(cooldownVariableName), MathExpression.Constant(0)), action: ObjectAction.Union(startCooldownAction, createBulletAction)); return(ObjectAction.ConditionalNextAction( currentAction: initialStartCooldownAction, condition: BooleanExpression.True(), nextAction: ObjectAction.Union(decrementCooldownAction, createBulletWhenCooldownFinishedAction))); }
// 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 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)))); }
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 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)); }
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(); } }
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))))))))); }