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

Time for action – rotating pieces

  1. Open your existing Flood Control project in Visual Studio, if it is not already active.
  2. Add a new class to the project called RotatingPiece.
  3. Under the class declaration (Public Class RotatingPiece), add the following line:
    Inherits GamePiece
  4. 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
  5. 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
  6. 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
  7. 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).