Time for action - update Game1 to draw animated pieces

  1. Add methods to the Game1 class to draw each potential type of game piece (animated and non-animated):
    private void DrawEmptyPiece(int pixelX, int pixelY)
    {
    spriteBatch.Draw(
    playingPieces,
    new Rectangle(pixelX, pixelY,
    GamePiece.PieceWidth, GamePiece.PieceHeight),
    EmptyPiece,
    Color.White);
    }
    private void DrawStandardPiece(int x, int y,
    int pixelX, int pixelY)
    {
    spriteBatch.Draw(
    playingPieces, new Rectangle(pixelX, pixelY,
    GamePiece.PieceWidth, GamePiece.PieceHeight),
    gameBoard.GetSourceRect(x, y),
    Color.White);
    }
    private void DrawFallingPiece(int pixelX, int pixelY,
    string positionName)
    {
    spriteBatch.Draw(
    playingPieces,
    new Rectangle(pixelX, pixelY -
    gameBoard.fallingPieces[positionName].VerticalOffset,
    GamePiece.PieceWidth, GamePiece.PieceHeight),
    gameBoard.fallingPieces[positionName].GetSourceRect(),
    Color.White);
    }
    private void DrawFadingPiece(int pixelX, int pixelY,
    string positionName)
    {
    spriteBatch.Draw(
    playingPieces,
    new Rectangle(pixelX, pixelY,
    GamePiece.PieceWidth, GamePiece.PieceHeight),
    gameBoard.fadingPieces[positionName].GetSourceRect(),
    Color.White *
    gameBoard.fadingPieces[positionName].alphaLevel);
    }
    private void DrawRotatingPiece(int pixelX, int pixelY,
    string positionName)
    {
    animated piecesdrawingspriteBatch.Draw(
    playingPieces,
    new Rectangle(pixelX + (GamePiece.PieceWidth / 2),
    pixelY + (GamePiece.PieceHeight / 2),
    GamePiece.PieceWidth,
    GamePiece.PieceHeight),
    gameBoard.rotatingPieces[positionName].GetSourceRect(),
    Color.White,
    gameBoard.rotatingPieces[positionName].RotationAmount,
    new Vector2(GamePiece.PieceWidth / 2,
    GamePiece.PieceHeight / 2),
    SpriteEffects.None, 0.0f);
    }
    
  2. Modify the Draw() method of the Game1 class by replacing the for loop that currently draws the playing pieces with:
    for (int x = 0; x < GameBoard.GameBoardWidth; x++)
    for (int y = 0; y < GameBoard.GameBoardHeight; y++)
    {
    int pixelX = (int)gameBoardDisplayOrigin.X +
    (x * GamePiece.PieceWidth);
    int pixelY = (int)gameBoardDisplayOrigin.Y +
    (y * GamePiece.PieceHeight);
    DrawEmptyPiece(pixelX, pixelY);
    bool pieceDrawn = false;
    string positionName = x.ToString() + "_" + y.ToString();
    if (gameBoard.rotatingPieces.ContainsKey(positionName))
    {
    DrawRotatingPiece(pixelX, pixelY, positionName);
    pieceDrawn = true;
    }
    if (gameBoard.fadingPieces.ContainsKey(positionName))
    {
    DrawFadingPiece(pixelX, pixelY, positionName);
    pieceDrawn = true;
    }
    if (gameBoard.fallingPieces.ContainsKey(positionName))
    {
    DrawFallingPiece(pixelX, pixelY, positionName);
    pieceDrawn = true;
    }
    if (!pieceDrawn)
    {
    DrawStandardPiece(x, y, pixelX, pixelY);
    }
    }
    
  3. Try it out! Run your game and complete a few rows.

What just happened?

To keep things organized, we have split the drawing of each of the different potential piece types into its own small method. These methods (DrawEmptyPiece(), DrawStandardPiece(), DrawFallingPiece(), DrawFadingPiece(), and DrawRotatingPiece()) each contain only a single statement to draw the piece.

Before we look at how each of the pieces is actually drawn, let's examine the way we determine which of these methods to call when drawing a piece. The structure of the drawing loop is still the same as it was before we added animated pieces: each square on the board is looped through, with a blank square being drawn first in each position.

After the blank space, a new Boolean value called pieceDrawn is declared and set to false. If an animated piece occupies a square, only the animated piece will be drawn, and not the underlying game piece.

The reason for this is that when the user clicks on the mouse button to rotate a piece, in memory the piece is rotated immediately. The animated piece that the user sees is inserted into the drawing process so it looks like the piece is turning. If both the animated piece and the real underlying piece were to be drawn, the final rotation position would be visible overlaid on top of the rotating piece while the rotation animation was playing.

The positionName string contains the dictionary key for the space we are currently drawing (in "X_Y" format). We use this to check each of the animated piece dictionaries to see if they contain an entry for that key.

If they do, the animated piece is drawn and the pieceDrawn variable is set to true. If the piece still has not been drawn after all of the dictionaries have been checked, the base piece is drawn just as it was before.

SpriteBatch overloads

Both falling and fading pieces are drawn using the SpriteBatch.Draw() overload that we are already familiar with; where a Texture2D, destination Rectangle, source Rectangle, and Color are specified when drawing. By multiplying our base drawing color (white) by the alpha value for a fading piece, we cause the whole piece to be drawn partially transparent. As the time passes, the alpha value will reach zero, and the piece will be fully transparent.

However, rotated pieces need to use an extended version of the SpriteBatch.Draw() call. The first four parameters are the same as our existing Draw() calls. To these parameters, we add a float for the rotation amount, a Vector2 for the origin around which the rotation takes place, a SpriteEffects property (set to SpriteEffects.None in this case) and a sorting depth (set to 0, or the top level).

When using a rotation with this form of the SpriteBatch.Draw() call, it is necessary to specify the point around which the sprite should be rotated. If we were to set the origin to Vector2.Zero (equivalent to 0, 0) the sprite would rotate around the upper left corner of the image, swinging into the spaces of other tiles on the board. The center point of the sprite is specified in local sprite coordinates (as opposed to screen coordinates, or even coordinates within the texture the sprite is being pulled from). The local coordinates of the sprite range from 0, 0 in the upper left corner to the height and width of the sprite in the lower right. In our case, the lower right corner of the sprite is GamePiece.PieceWidth, GamePiece.PieceHeight, or 40, 40.

By specifying new Vector2(GamePiece.PieceWidth/2, GamePiece.PieceHeight/2) we are setting the origin to the center of the sprite, meaning it will rotate in place as expected.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.147.215