- Switch back to your Visual C# window if you have your image editor open.
- Right-click on Flood Control in Solution Explorer and select Add | Class…
- Name the class GamePiece.cs and click on Add.
- At the top of the
GamePiece.cs
file, add the following to theusing
directives already in the class:using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework;
- In the class declarations section, add the following:
public static string[] PieceTypes = { "Left,Right", "Top,Bottom", "Left,Top", "Top,Right", "Right,Bottom", "Bottom,Left", "Empty" }; public const int PieceHeight = 40; public const int PieceWidth = 40; public const int MaxPlayablePieceIndex = 5; public const int EmptyPieceIndex = 6; private const int textureOffsetX = 1; private const int textureOffsetY = 1; private const int texturePaddingX = 1; private const int texturePaddingY = 1; private string pieceType = ""; private string pieceSuffix = "";
- Add two properties to retrieve information about the piece:
public string PieceType { get { return pieceType; } } public string Suffix { get { return pieceSuffix; } }
You have created a new code file called GamePiece.cs
and included the using
statements necessary to access the pieces of the XNA Framework that the class will use.
Tip
Using Directives
Adding the XNA Framework using
directives at the top of the class file allows you to access classes like Rectangle
and Vector2
without specifying their full assembly names. Without these statements, you would need Microsoft.Xna.Framework.Rectangle
in your code every time you reference the type, instead of simply typing Rectangle
.
In the declarations area, you have added an array called PieceTypes
that gives a name to each of the different types of game pieces that will be added to the game board. There are two straight pieces, four angled pieces, and an empty tile with a background image on it, but no pipe. The array is declared as static
because all instances of the GamePiece class will share the same array. A static
member can be updated at execution time, but all members of the class will see the same changes.
Then, you have declared two integer constants that specify the height and width of an individual playing piece in pixels, along with two variables that specify the array index of the last piece that can be placed on the board (MaxPlayablePieceIndex
) and of the fake "Empty" piece.
Next are four integers that describe the layout of the texture file you are using. There is a one pixel offset from the left and top edge of the texture (the one pixel border) and a single pixel of padding between each sprite on the sprite sheet.
Tip
Constants vs. Numeric literals
Why create constants for things like PieceWidth
and PieceHeight
and have to type them out when you could simply use the number 40
in their place? If you need to go back and resize your pieces later, you only need to change the size in one place instead of hoping that you find each place in the code where you entered 40
and change them all to something else. Even if you do not change the number in the game you are working on, you may reuse the code for something else later and having easily changeable parameters will make the job much easier.
There are only two pieces of information that each instance of GamePiece will track about itself—the type of the piece and any suffix associated with the piece. The instance members pieceType
and pieceSuffix
store these values. We will use the suffix to determine if the pipe that the piece represents is empty or filled with water.
However, these members are declared as private
in order to prevent code outside the class from directly altering the values. To allow them to be read but not written to, we create a pair of properties (pieceType
and pieceSuffix
) that contain get blocks but no set blocks. This makes these values accessible in a read-only mode to code outside the GamePiece class.