Esempio n. 1
0
        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)));
        }
Esempio n. 2
0
 public static ObjectAction DoOnce(ObjectAction action)
 {
     return(ObjectAction.ConditionalNextAction(
                currentAction: action,
                condition: BooleanExpression.True(),
                nextAction: ObjectActionGenerator.Noop()));
 }
Esempio n. 3
0
        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)));
        }
Esempio n. 4
0
        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));
        }
Esempio n. 5
0
        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)));
        }
Esempio n. 6
0
        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)));
        }
Esempio n. 7
0
        // 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);
            }
        }
Esempio n. 8
0
        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))));
        }
Esempio n. 9
0
        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)));
        }
Esempio n. 10
0
        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));
        }
Esempio n. 11
0
        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();
            }
        }
Esempio n. 12
0
        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)))))))));
        }