8bitrocket.com
16Jan/090

Flash To Silverlight Game Development #2: Random Numbers For Multiple Class Objects

This might seem like a very simple topic, but it is something that confounded me for a few hours while translating a Flash AS2 game to Silverlight 2: Random Numbers. For many games, the concept of random numbers is essential. Nearly all programming languages have a function to create a random number, and most of them actually create "pseudo" random numbers (a list that could be replicated given the proper time and effort), but most of the time that is good enough. We will be concentrating on these "pseudo" random numbers for this discussion.

Generating numbers that appear to be random in Flash is quite easy. In AS2, to create a random number from 1-6 you would do something like this:

var random:Number = Math.ceil(Math.random() * 6);

In Silverlight C# code, the code would be something like this:

Random random = new Random();

value = random.Next(1, 7);

There is nothing wrong with this, and it works fine. However, if you are creating a game where you need several objects (i.e. dice for instance) to be created at the the same time, and also generate their own random numbers, there could be a problem.

In Flash AS2, this would be simple. Let's say I have a Die class and I want it create a random number for itself in the the constructor when created, I might do this:

Class creating Die Objects (AS2)

...

var dieArray:Array = new Array();

for (var i =0;i < 5; i++) {

dieArray.push(new Die()

}

...

Die Class (AS2)

class Die {

var dvalue:Number = 0;

public function Die() {

dvalue = Math.ceil(Math.random() * 6)

}


}

This would work to create 5 instances of Die, each set to a different random value. (i.e. 1,3,5,2,4). This is because we are creating a random number using Math's static random() function that gets seeded once at run-time.

Similar code in Silverlight might look like this:

 

Class creating Die Objects (C#)

...

diceArray = new Die[5] { null, null, null, null, null };
diceArray[0] = new Die();
diceArray[1] = new Die();
diceArray[2] = new Die();
diceArray[3] = new Die();
diceArray[4] = new Die();

...

Die Class (C#)

public partial class Die : UserControl
{

public int value = 0;

public Die()
{
Random random = new Random();

value = random.Next(1, 7);

}

}

You would think that this would work similar to the AS2 code and create 5 Die classes each with a different value. However, on new super-fast computers, this is not the case. In fact, most of the time you will get 5 Die classes, each with THE SAME number (i.e. 3,3,3,3,3). This appears to be because C# is able to create the Random classes at essentially the same time, and they are all seeded (and subsequently reseeded) with the same value. There are ways to seed the random generator in C#, but you would have to make sure to seed it with 5 different values, and generating those might again give you the same seed for each Random class, and so on and so on. However, there is a very simple way to solve this problem: use one random number generator for all instances.

Here is the same C# code from above, but instead of each class creating it's own instance of Random, we create one instance, and pass it to each Die class when they are instantiated:

Class creating Die Objects (C#)

Random randomSource;

randomSource = new Random();

diceArray = new Die[5] { null, null, null, null, null };
diceArray[0] = new Die(randomSource);
diceArray[1] = new Die(randomSource);
diceArray[2] = new Die(randomSource);
diceArray[3] = new Die(randomSource);
diceArray[4] = new Die(randomSource);

Die Class (C#)

public partial class Die : UserControl
{

public int value = 0;

public Random random;

public Die(Random rnd)
{

random = rnd;

value = random.Next(1, 7);

}

}

By doing it this way, we are certain that we will get random numbers for each Die (i.e. 4,5,3,3,6) and we do not have to wonder if the speed of the machine's clock ticks will seed each Random class with the same values at initialization time.

There are possibly other ways to do this. (i.e. to create a static Random instance that is shared by all instances of the Die class). The point is, you must make sure to not create multiple instances of the Random class in C# at the same time if you expect them to hold a different sequence of random numbers.

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.

This site is protected by Comment SPAM Wiper.