Rolling dice in XNA – complete code and sample
Wednesday, July 25th, 2012I saw a post on the Microsoft XNA forums asking for hints on how to get a die rolling on the screen, so I’ve put together a little sample here, for your enjoyment
This small “game” does nothing but roll six dice when you press SPACE, and sums them up for you.
Complete code here.
Short presentation of the program
As you can see above, there are six dice, instantiated to different positions in a diagonal line. The program listens for the SPACE bar being pushed. If all dice are stationary at that moment, then all the dice have their Roll() method invoked, which changes their state to Rolling and sets the MsLeftInRoll to 1000 (meaning a roll takes 1 second), and their Update method nudges their CurrentPosition property downward slowly for the full second. When all dice have stopped rolling, their ToString() implementation is used to display the result of the roll onscreen.
The Die class
The Die is a subclass of DrawableGameComponent, which makes Updating and Drawing easier. Just create a new Die object and add it to Game.Components. This will make sure that the Game objects’s Update and Draw calls Update and Draw on each die added.
for (int i = 0; i < 6; i++) { //creates a new die, a bit further to the left and below the previous Die die = new Die(this, new Vector2(100 + 120 * i, 100 + 25 * i)); //adds it to the Game's components, to make sure it gets updated and drawn Components.Add(die); }
Here is the class diagram of the Die:
Creating a die
When the Die is created it is passed a reference to the Game object, and its OriginalPosition (where it begins every new roll).
Drawing the die
The die draws itself by finding the source-rectangle to draw from this PNG ( 100 x 600 pixels ) based on the current value of the die.
Here's the math to find the current rectangle.
Rectangle sourceRect = new Rectangle(_dieFaceSize * (this.Value - 1) ,0, _dieFaceSize, _dieFaceSize);
_dieFaceSize is 100 pixels in this case, but is set dynamically based on the height of the Texture2D used.
When drawing the die's face, it is moved up and left by half of a _dieFaceSize (50 pixels in this case) so the texture is centered on the CurrentPosition of the Die. A shadow is created by first drawing the face with a semiopaque, black version of the face.
Rolling the die
Rolling the die is pretty straightforward:
//starts the die rolling public void Roll() { //if the die isn't already rolling if (this.State != DieState.Rolling) { //move it back to its starting position this.ReturnToOriginalPosition(); //start it rolling this.State = DieState.Rolling; //reset the time to roll MsLeftInRoll = _msForRoll; } }
Updating the die
For every Update, the time left in the MsLeftInRoll has the gameTime.ElapsedGameTime.TotalMiliseconds subtracted from it, and if it is below zero, the State of the Die changes to Stationary.
public override void Update(GameTime gameTime) { base.Update(gameTime); //if the die is rolling if (this.State == DieState.Rolling) { //subtract the time since last Update from the rolltime MsLeftInRoll -= gameTime.ElapsedGameTime.TotalMilliseconds; //if time is up if (MsLeftInRoll <= 0) { //set the state to stationary this.State = DieState.Stationary; } else { //give the die a new value from 1 to 6 this.Value = _rnd.Next(6) + 1; //move the offset a bit down along the Y axis this.CurrentPosition += Vector2.UnitY * 2; } } }
Hope this helps somebody when implementing their own diceroller