Time for action – rotating pieces
- Open your existing Flood Control project in Visual Studio, if it is not already active.
- Add a new class to the project called
RotatingPiece
. - Under the class declaration (
Public Class RotatingPiece
), add the following line:Inherits GamePiece
- Add the following declarations to the
RotatingPiece
class:Public Clockwise As Boolean Public Shared RotationRate As Single = (MathHelper.PiOver2/10) Private _rotationAmount As Single Public rotationTicksRemaining As Single = 10
- Add a property to retrieve the current
RotationAmount
:Public ReadOnly Property RotationAmount As Single Get If Clockwise Then Return _rotationAmount Else Return (MathHelper.Pi * 2) - _rotationAmount End If End Get End Property
- Add a constructor for the
RotatingPiece
class as follows:Public Sub New(type As String, clockwise As Boolean) MyBase.New(type) Me.Clockwise = clockwise End Sub
- Add a method to update the piece as follows:
Public Sub UpdatePiece() _rotationAmount += RotationRate rotationTicksRemaining = CInt(MathHelper.Max(0, rotationTicksRemaining - 1)) End Sub
What just happened?
In step 3, we modified the RotatingPiece
class by adding Inherits GamePiece
on the line after the class declaration. This indicates to Visual Basic that the RotatingPiece
class is a child of the GamePiece
class.
The Clockwise
variable stores a true value if the piece will be rotating clockwise, and false if the rotation is counter clockwise.
When a game piece is rotated, it will turn a total of 90 degrees (or pi/2 radians) over 10 animation frames. The MathHelper
class provides a number of constants to represent commonly used numbers, with MathHelper.PiOver2
being equal to the number of radians in a 90 degree angle. We divide this constant by 10 and store the result as the rotationRate
for use later. This number will be added to the _rotationAmount single
, which will be referenced when the animated piece is drawn.
Tip
Working with radians
All angular math is handled in radians in XNA. A complete (360 degree) circle contains 2*pi radians. In other words, one radian is equal to about 57.29 degrees. We tend to relate to circles more often in terms of degrees (a right angle being 90 degrees, for example), so if you prefer to work with degrees, you can use the MathHelper.ToRadians()
method to convert your values when supplying them to XNA classes and methods.
The final declaration, rotationTicksRemaining
, is reduced by one, each time the piece is updated. When this counter reaches zero, the piece has finished animating.
When the piece is drawn, the RotationAmount
property is referenced by a spriteBatch.Draw()
call and returns either the _rotationAmount
variable (in the case of a clockwise rotation), or 2*pi (a full circle) minus the _rotationAmount
if the rotation is counter clockwise.
The constructor in step 6 illustrates how the parameters passed to a constructor can be forwarded to the class' parent constructor via the MyBase
call. Since the GamePiece
class has a constructor that accepts a piece type, we can pass that information along to its constructor, while using the second parameter (clockwise
) to update the clockwise
member that does not exist in the GamePiece
class. In this case, since both the Clockwise
member variable and the clockwise
parameter have identical names, we specify Me.Clockwise
to refer to the clockwise
member of the RotatingPiece
class. Simply, clockwise
in this scope refers only to the parameter passed to the constructor.
Tip
Me notation
You can see that it is perfectly valid for Visual Basic code to have method parameter names that match the names of class variables, thus potentially hiding the class variables from being used in the method (since referring to the name inside the method will be assumed to refer to the parameter). To ensure that you can always access your class variables even when a parameter name conflicts, you can preface the variable name with Me.
when referring to the class variable. Me.
indicates to Visual Basic that the variable you want to use is part of the class and not a local method parameter. In C#, a similar type of notation is used, prefacing class-level members with this.
to access a hidden variable.
Lastly, the UpdatePiece()
method simply increases the _rotationAmount
member, while decreasing the rotationTicksRemaining
counter (using MathHelper.Max()
to ensure that the value does not fall below zero).