Exemple #1
0
        /// <summary>
        /// Adds and repositions the block stack from the board.
        /// </summary>
        /// <param name="stack"></param>
        private void AddGrabStack()
        {
            // Ignore nulls stacks
            if (currentStack == null)
            {
                return;
            }

            // Figure out the top-most block that isn't moving
            float topPosition  = GetTopPosition();
            float grabPosition =
                Math.Max(topPosition + Constants.GrabStackOffset,
                         Constants.MinimumGrabHeight);

            // Move the selector
            selector.BottomPosition = topPosition;
            currentStack.Add(selector);

            // Go through the blocks
            for (int i = 0; i < grabStack.Length; i++)
            {
                // Stop processing when we hit a null
                if (grabStack[i] == null)
                {
                    break;
                }

                // Reset the position
                currentStack.Add(grabStack[i]);
                grabStack[i].BottomPosition = grabPosition + (float)i;
            }
        }
Exemple #2
0
        /// <summary>
        /// Migrates the current board to the other one, dropping
        /// everything on top.
        /// </summary>
        /// <param name="board"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void MigrateBoard(Board board, int x, int y)
        {
            // Go through the columns
            for (int i = 0; i < Columns; i++)
            {
                // Get the data for speed
                IList <BlockStack> stacks  = Game.State.Board[x + i];
                IList <BlockStack> stacks0 = this[i];

                // Go through the rows
                for (int j = 0; j < Rows; j++)
                {
                    // Get the stacks
                    BlockStack stack  = stacks[y + j];
                    BlockStack stack0 = stacks0[j];

                    // Get the position
                    Block bBlock   = stack.TopBlock;
                    float position = stack.TopPosition;

                    // Move everything but the bottom-most one
                    foreach (Block block in stack0)
                    {
                        // Seal it to change how it looks on the
                        // mini map
                        switch (block.Sprite.ID)
                        {
                        case "Water Block":
                            bBlock.Sprite = AssetLoader.Instance
                                            .CreateSprite("Sealed Water Block");
                            bBlock.Data = false;
                            break;

                        case "Grass Block":
                            bBlock.Sprite = AssetLoader.Instance
                                            .CreateSprite("Sealed Grass Block");
                            bBlock.Data = false;
                            break;

                        case "Dirt Block":
                            bBlock.Sprite = AssetLoader.Instance
                                            .CreateSprite("Sealed Dirt Block");
                            bBlock.Data = false;
                            break;
                        }

                        // Positions 0's are sealed
                        if (block.BottomPosition != 0)
                        {
                            // Move it over to the new one and add the position
                            // to the bottom, minus one because we ignore the
                            // bottom row
                            block.BottomPosition += position - 1f;
                            stack.Add(new Block(block));
                        }
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// This creates a new stage for the game, using the
        /// properties of the state to determine how the board is
        /// generated.
        /// </summary>
        public void GenerateStage()
        {
            // See if we already have a gate column (i.e. if we have
            // any columns, then we do).
            int newColumns = Constants.StageWidth;

            // Extend the board by the number of columns
            int oldColumns = Columns;

            Columns = Columns + newColumns;

            // Populate the base level board
            for (int i = 0; i < newColumns; i++)
            {
                // Get the column
                IList <BlockStack> stacks = this[oldColumns + i];

                // Go through the rows
                for (int j = 0; j < Constants.BoardRows; j++)
                {
                    // Get the stack
                    BlockStack stack = stacks[j];
                    stack.IsInInitialPlacement = true;

                    // Set a new immobile block into place
                    Block block = AssetLoader.Instance
                                  .CreateBlock(Constants.ImmobileBlockName);
                    block.BottomPosition = 0;
                    block.Height         = 1;

                    // Add it to the stack
                    stack.Add(block);
                }
            }

            // Populate the additional immobile boards
            AddBlocks(Game.State.ImmobileCount, Constants.ImmobileBlockName);

            // Add the grass, dirt, and water blocks
            AddBlocks();

            // Add the character prayer, but not on the far-right side
            Prayer prayer = new Prayer();
            int    px     = Entropy.Next(0, Constants.StageWidth - 1);
            int    py     = Entropy.Next(0, Constants.BoardRows);

            prayer.X = px + oldColumns;
            prayer.Y = py;
            Game.State.Prayers.Add(prayer);

            BlockStack ps = Game.State.Board[oldColumns + px, py];

            prayer.BottomPosition = ps.TopPosition;
            prayer.Vector         = Constants.DroppedVector;
            ps.Add(prayer);
        }
Exemple #4
0
        /// <summary>
        /// Internal function to determine if the target is valid or
        /// not.
        /// </summary>
        private bool IsInvalidTarget(BlockStack srcStack, BlockStack destStack)
        {
            // Remove ourselves to take ourselves out of the calculation
            srcStack.Remove(this);

            try
            {
                // Make sure the destination is a ground block or an
                // immobile one, but nothing else
                Block dest = destStack.TopBlock;

                if (!Board.IsGroundBlock(dest) &&
                    !Board.IsImmobileBlock(dest))
                {
                    // Neither ground or immobile
                    return(true);
                }

                // We need the distance to be 1 or less
                float dist =
                    Math.Abs(srcStack.TopPosition - destStack.TopPosition);

                if (dist > 1)
                {
                    // Too much to jump
                    return(true);
                }

                // It is good
                return(false);
            }
            finally
            {
                // Put ourselves back
                srcStack.Add(this);
            }
        }
Exemple #5
0
        /// <summary>
        /// Adds a number of blocks of the give name to the board. This
        /// only places blocks in the last Constants.StateWidth rows.
        /// </summary>
        /// <param name="count"></param>
        /// <param name="name"></param>
        private void AddBlocks(int count, string name)
        {
            // Loop through the blocks
            for (int i = 0; i < count; i++)
            {
                // Create a new block
                Block block = CreateBlock(name);

                // Since we have a maximum count here, we loop until we
                // find a valid stack to drop it on
                while (true)
                {
                    // Figure out a random position
                    int col = Entropy.Next(0, Constants.StageWidth)
                              + Columns - Constants.StageWidth;
                    int        row   = Entropy.Next(0, Constants.BoardRows);
                    BlockStack stack = this[col, row];

                    // Make sure the stack doesn't have too many items
                    if (stack.Count >= Constants.MaximumPlacementCount)
                    {
                        continue;
                    }

                    // Set the position based on the count
                    block.BottomPosition =
                        2f + (float)stack.Count * Constants.PlacementSpacing;
                    block.Vector   = Constants.DroppedVector;
                    block.IsMoving = true;
                    stack.Add(block);

                    // Break out of the loop
                    break;
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Internal function to populate the board with random
        /// blocks.
        /// </summary>
        private void PopulateBoard()
        {
            for (int x = 0; x < BoardColumns; x++)
            {
                for (int y = 0; y < BoardRows; y++)
                {
                    // Get the stack
                    BlockStack stack = board[x, y];

                    // Add 1-4 blocks
                    int total = Entropy.Next(4) + 1;

                    for (int i = 0; i < total; i++)
                    {
                        Block block = new Block(RandomBlock());
                        block.BottomPosition = i;
                        block.CastsShadows   = true;
                        block.Height         = 1;
                        block.Mass           = Constants.BlockMass;
                        stack.Add(block);
                    }
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// This event is used to handle jumping from one block to
        /// another.
        /// </summary>
        private void OnDirectionChanged(
            object sender,
            BlockStackEventArgs args)
        {
            // At the apex, we change our direction by moving to the
            // next stack as appropriate. Start by ignoring direction
            // 0 since that is an inplace jumping.
            if (direction == 0)
            {
                return;
            }

            // Get the destination stack
            Board      board     = Game.State.Board;
            BlockStack srcStack  = board[X, Y];
            BlockStack destStack = null;

            if (direction == 1)
            {
                destStack = board[X, Y - 1];
            }
            else if (direction == 2)
            {
                destStack = board[X + 1, Y];
            }
            else if (direction == 3)
            {
                destStack = board[X, Y + 1];
            }
            else if (direction == 4)
            {
                destStack = board[X - 1, Y];
            }

            // Make sure we are still a valid destination
            if (IsInvalidTarget(srcStack, destStack))
            {
                // We want to reverse the direction, but stay in the
                // same stack because our destination became
                // invalid. This works because the code will show them
                // "bouncing" back.
                if (direction == 1)
                {
                    direction = 3;
                }
                else if (direction == 2)
                {
                    direction = 4;
                }
                else if (direction == 3)
                {
                    direction = 1;
                }
                else if (direction == 4)
                {
                    direction = 2;
                }

                // We are done
                srcStack.Add(this);
                return;
            }

            // Move this block to the next one
            srcStack.Remove(this);
            destStack.Add(this);

            // Change our coordinates
            if (direction == 1)
            {
                BottomPosition -= 4;
                Y--;
            }
            else if (direction == 2)
            {
                OffsetX -= 101;
                X++;
            }
            else if (direction == 3)
            {
                BottomPosition += 1;
                Y++;
            }
            else if (direction == 4)
            {
                OffsetX += 101;
                X--;
            }
        }
Exemple #8
0
        /// <summary>
        /// This function causes the prayer to jump and potentially
        /// move around the board.
        /// </summary>
        public void Jump()
        {
            // Reset the time
            timeUntilBounce = Entropy.NextDouble(
                Constants.MinimumCharacterBounce,
                Constants.MaximumCharacterBounce);

            // We want the characters to bounce around a bit, so
            // we randomly pick a direction to jump into. We get a
            // random number between 0 and 4:
            //   0 no change
            //   1 north
            //   2 east
            //   3 south
            //   4 west
            // Actually, 0 happens because of fallback
            direction = Entropy.Next(4) + 1;

            // East/West only
            // TODO Fix
            if (direction == 1 || direction == 3)
            {
                direction++;
            }

            // If we haven't been accepted, we don't move around
            if (!IsAccepted)
            {
                direction = 0;
            }

            // Do sanity checking on the bounds of the stage. If
            // we are on the end and we would have jumped off, set
            // the direction to "none"
            Board board = Game.State.Board;

            if (direction == 1 && Y == 0)
            {
                direction = 0;
            }
            else if (direction == 2 && X == board.Columns - 1)
            {
                direction = 0;
            }
            else if (direction == 3 && Y == board.Rows - 1)
            {
                direction = 0;
            }
            else if (direction == 4 && X == 0)
            {
                direction = 0;
            }

            // If we still non-zero, then get the appropriate
            // stacks
            BlockStack myStack   = board[X, Y];
            BlockStack destStack = myStack;

            if (direction > 0)
            {
                // Get the proper stack and make sure it is a
                // valid target
                if (direction == 1)
                {
                    destStack = board[X, Y - 1];
                }
                else if (direction == 2)
                {
                    destStack = board[X + 1, Y];
                }
                else if (direction == 3)
                {
                    destStack = board[X, Y + 1];
                }
                else if (direction == 4)
                {
                    destStack = board[X - 1, Y];
                }

                // We don't jump if the destination block isn't a
                // ground or immobile block. We also don't jump if
                // the difference in height is more than one.
                if (IsInvalidTarget(myStack, destStack))
                {
                    direction = 0;
                    destStack = myStack;
                }
            }

            // Figure out the vector, we need a higher one if we
            // are jumping north and/or if the destination block
            // is higher.
            myStack.Remove(this);
            float myTop   = myStack.TopPosition;
            float destTop = destStack.TopPosition;
            float vector  = Constants.PrayerBounceVector;

            myStack.Add(this);

            if (direction == 1)
            {
                vector += Constants.PrayerBounceNorthVector;
            }

            if (destTop > myTop)
            {
                vector += Constants.PrayerBounceUpVector;
            }

            // Add a positive vector
            Vector += vector;
        }
Exemple #9
0
 BlockStack MergeStacks(IBlock b1, IBlock b2)
 {
     BlockStack ret = new BlockStack();
     if ((b1 is BlockStack))
     {
         BlockStack bs1 = b1 as BlockStack;
         ret.AddRange(bs1);
     }
     else
     {
         // We need to remove b1 from its parent before adding it to the newly merged stack
         // otherwise consider such a scenario:
         // 1- We drag a stack block into an existing stackBlock in a C block
         // 2- 'b1' is the existing stackBlock, it is not added to ret, but is still an arg of the C block
         // 3- after merge is called, we'll try to set ret as the arg of the C block; the C will try
         // to remove the old arg (b1)...but it doesn't have C as a parent! exception thrown
         b1.ParentRelationship.Detach(this);
         ret.Add(b1);
     }
     if ((b2 is BlockStack))
     {
         BlockStack bs2 = b2 as BlockStack;
         ret.AddRange(bs2);
     }
     else
     {
         b2.ParentRelationship.Detach(this);
         ret.Add(b2);
     }
     return ret;
 }
        private IBlock ToBlockStack(JToken json)
        {
            BlockStack b = new BlockStack();

            for (int i = 1; i < json.Count(); ++i)
            {
                IBlock subBlock = ToBlock(json[i]);
                if (i == 1 && subBlock is ProcDefBlock)
                    currentProcDef = subBlock as ProcDefBlock;
                b.Add(subBlock);
            }
            currentProcDef = null;
            return b;
        }
Exemple #11
0
        /// <summary>
        /// Adds some bugs into the stage.
        /// </summary>
        public void AddBugs(int howMany)
        {
            // Loop through the bugs
            for (int i = 0; i < howMany; i++)
            {
                // Create a bug
                Bug bug = new Bug();

                // Place the bug
                while (true)
                {
                    // Find a random location
                    int        col   = Entropy.Next(0, Columns);
                    int        row   = Entropy.Next(0, Constants.BoardRows);
                    BlockStack stack = this[col, row];

                    // Go through the stack, looking for bugs
                    float immobilePosition = 0;
                    bool  foundGround      = false;
                    bool  validStack       = false;

                    foreach (Block block in stack)
                    {
                        // Don't bother if we already have a bug here
                        if (block.Sprite.ID == Constants.BugBlockName)
                        {
                        }

                        // Make sure we have at least one land block
                        else if (IsGroundBlock(block))
                        {
                            foundGround = true;
                        }

                        // If we have an immobile, keep it
                        else if (block.Sprite.ID ==
                                 Constants.ImmobileBlockName)
                        {
                            immobilePosition =
                                Math.Max(block.TopPosition, immobilePosition);
                            validStack = true;
                        }

                        // Not valid, a character or someting
                        else
                        {
                            validStack = false;
                            break;
                        }
                    }

                    // See if we have a valid one
                    if (!validStack || !foundGround)
                    {
                        continue;
                    }

                    // Put the bug in
                    bug.BottomPosition = immobilePosition;
                    bug.X          = col;
                    bug.Y          = row;
                    bug.BlockStack = stack;
                    stack.Add(bug);
                    stack.Sort();
                    Game.State.Bugs.Add(bug);
                    break;
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Random grabs or drops a block on the board.
        /// </summary>
        private void ChangeBoard(UpdateArgs args)
        {
            // Loop through the blocks to see if they are too high. If
            // they are, remove them.
            LinkedList <Block> tmpBlocks = new LinkedList <Block>();

            tmpBlocks.AddAll(blocks);

            foreach (Block b in tmpBlocks)
            {
                if (b.BottomPosition > 10)
                {
                    stacks[b].Remove(b);
                    blocks.Remove(b);
                    stacks.Remove(b);
                }
            }

            // Decrement the counter for the timeout
            secondsUntilChange -= args.SecondsSinceLastUpdate;

            if (secondsUntilChange > 0)
            {
                // We aren't changing anything
                return;
            }

            // Reset it
            secondsUntilChange = Entropy.NextDouble() * 2;

            // Pick a random coordinate
            int        x     = Entropy.Next(0, BoardColumns);
            int        y     = Entropy.Next(0, BoardRows);
            BlockStack stack = board[x, y];

            // Make sure we aren't already doing something here
            foreach (Block b in blocks)
            {
                if (stacks[b] == stack)
                {
                    // Don't bother this time
                    return;
                }
            }

            // We have a stack, decide if we are going to drop or grab
            // something from the stack.
            bool drop = Entropy.Next(0, 2) == 0;

            if (stack.Count > 5)
            {
                // Don't go over 5 high
                drop = false;
            }

            if (stack.Count == 1)
            {
                // Don't go below 1 high
                drop = true;
            }

            // Figure out what to do
            if (drop)
            {
                // Create a new block
                Block nb = new Block(RandomBlock());
                nb.BottomPosition = 10;
                nb.Vector         = Constants.DroppedVector;
                nb.Mass           = Constants.BlockMass;
                nb.IsMoving       = true;
                nb.CastsShadows   = true;
                nb.Height         = 1;
                stack.Add(nb);
            }
            else
            {
                // Grab the top block
                Block tb = stack.TopBlock;
                tb.Vector   = -Constants.DroppedVector;
                tb.Mass     = 0;
                tb.IsMoving = true;
            }
        }
Exemple #13
0
        /// <summary>
        /// Internal function to determine if the target is valid or
        /// not.
        /// </summary>
        private bool IsInvalidTarget(BlockStack srcStack, BlockStack destStack)
        {
            // Remove ourselves to take ourselves out of the calculation
            srcStack.Remove(this);

            try
            {
                // Make sure the destination is a ground block or an
                // immobile one, but nothing else
                Block dest = destStack.TopBlock;

                if (!Board.IsGroundBlock(dest) &&
                    !Board.IsImmobileBlock(dest))
                {
                    // Neither ground or immobile
                    return true;
                }

                // We need the distance to be 1 or less
                float dist =
                    Math.Abs(srcStack.TopPosition - destStack.TopPosition);

                if (dist > 1)
                {
                    // Too much to jump
                    return true;
                }

                // It is good
                return false;
            }
            finally
            {

                // Put ourselves back
                srcStack.Add(this);
            }
        }