XNA 4.0 Game Development by Example Beginner's Guide(Visual Basic Edition)
上QQ阅读APP看书,第一时间看更新

Time for action – drawing the screen – the play screen

  1. In the GameBoard class, add the Draw() method to allow the game board to draw itself:
    Public Sub Draw(
      spriteBatch As SpriteBatch,
      DisplayOrigin As Vector2)
    
      Dim x As Integer, y As Integer
    
      For x = 0 To GameBoardWidth
        For y = 0 To GameBoardHeight
          Dim pixelX As Integer = CInt(DisplayOrigin.X + (x * GamePiece.PieceWidth))
          Dim pixelY As Integer = CInt(DisplayOrigin.Y + (y * GamePiece.PieceHeight))
    
          spriteBatch.Draw(
            playingPieces,New Rectangle(
              pixelX,pixelY,GamePiece.PieceWidth,GamePiece.PieceHeight),EmptyPiece,Color.White)
    
          spriteBatch.Draw(
            playingPieces,New Rectangle(
              pixelX,pixelY,GamePiece.PieceWidth,GamePiece.PieceHeight),GetSourceRect(x, y),Color.White)
        Next
      Next
    End Sub
  2. Update the Draw() method of the Game1 class to add the code to call the Draw() method of GameBoard. Place this code after the code that draws the title screen:
    If gameState = GameStates.Playing Then
      spriteBatch.Begin()
      spriteBatch.Draw(background,
            New Rectangle(0, 0,
                          Me.Window.ClientBounds.Width,
                          Me.Window.ClientBounds.Height),
            Color.White)
        _gameBoard.Draw(spriteBatch, gameBoardDisplayOrigin)
    
        Me.Window.Title = playerScore.ToString()
    
        spriteBatch.End()
    End If

What just happened?

The GameBoard class will be responsible for drawing itself, so we begin by creating a Draw() method that accepts a SpriteBatch to use for drawing, and a Vector2 pointing to the upper-left corner of the drawing area. The method loops through each of the squares on the gameboard and calculates the X and Y location, where the piece should be drawn.

Since both x and y begin at 0, the (x * GamePiece.PieceWidth) and (y * GamePiece.PieceHeight) will also be equal to 0, resulting in the first square being drawn at the location specified by the gameBoardDisplayOrigin vector.

As x increments, each new piece is drawn 40 pixels further to the right than the previous piece. After a row has been completed, the y value increments, and a new row is started 40 pixels below the previous row.

The first spriteBatch.Draw() call uses Rectangle(pixelX, pixelY, GamePiece.PieceWidth, GamePiece.PieceHeight) as the destination rectangle and EmptyPiece as the source rectangle. Recall that we added this rectangle to our declarations area as a shortcut to the location of the empty piece on the sprite sheet.

The second spriteBatch.Draw() call uses the same destination rectangle, overlaying the playing piece image onto the empty piece that was just drawn. It asks _gameBoard to provide the source rectangle for the piece it needs to draw.

The Game1 portion of the code to draw the game board begins exactly like the code to draw the title screen. Since we are using a background image that takes up the full screen, we draw it exactly the same way as the title screen. After the background has been displayed, we call the method we just created in the GameBoard class to draw the board.

The player's score is displayed in the window title bar, and spriteBatch.End() is called to finish up the Draw() method.

Keeping score

Longer chains of filled water pipes score the player more points. However, if we were to simply assign a single point to each piece in the pipe chain, there would be no scoring advantage to making longer chains versus quickly making shorter chains.