Sign in to follow this  

XNA problem with my game...

This topic is 2628 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey everyone,

Im working on my first XNA game, a space shooter and I have a problem where I cant find a solution...

Its a problem with my enemy objects which should spawn on a random coordinate on the Y axis. I created a procedur which refreshes the coordinates of the enemies when they reach the end of the screen. This procedur is called by every update.

the routin to create random cordinates
The parameter is needed to get the Y axis from the screen.

for (int i = 0; i < maxEnemys; i++)
{
if (aEnemy[i].Active == false)
{
aEnemy[i].SetSpawn(graphics);
}
}



this routin works when I go through the debug mode step by step. Every enemy gets an individual Y cordinate. When I run the debug mode without any breakpoints all enemie objects get the same Y cordinate.

Random spawnpoint method:

public void SetSpawn(GraphicsDeviceManager g)
{
Random r = new Random();
position = new Vector2(g.PreferredBackBufferWidth, r.Next(g.PreferredBackBufferHeight));
}


anyone got an advice or an answer why this happens? :(

Share this post


Link to post
Share on other sites
It is because the Random default constructor uses a Time dependant initial seed value.

So when you are debugging, if you set break points, the initial seed will change. But if you run your game, because the loop is executed really quickly, the random will use the same initial seed value.

I suggest you move the creation of the Random object outside your SetSpawn function. So that the initial seed is only inited one time for all your coordinates.

Share this post


Link to post
Share on other sites
There has been lots of discussions about this. Long story short, there Random object does produce the same values under some circumstances. I recommend that you multiply the result of Next() with something that changes all the time, like DateTime.Now.Ticks.

By the way, creating a new Random object in each iteration might not be the best approach. Try to use one Random object for all enemies, or create a static one.

Share this post


Link to post
Share on other sites
Don't initialize a new instance of Random each time you call SetSpawn(). Make a Random a static member variable of the enemy class and initialize it there.

class Enemy
{
static Random rand = new Random();
...
// rest of code
...
}

Random generates random numbers based on a seed number that it's given. Given the same seed number, each instance of Random will produce the same results each time. When you don't specify this value, time is used as the random seed. The problem is the value Random uses for time is very low resolution (it is only accurate to the second) so when you create new instances of Random within one second, they'll always generate the same "random" numbers.

The solution to this problem is to create one instance of Random and use that instance instead of creating many.

Share this post


Link to post
Share on other sites
Quote:
Original post by YoYoFreakCJ
There has been lots of discussions about this. Long story short, there Random object does produce the same values under some circumstances. I recommend that you multiply the result of Next() with something that changes all the time, like DateTime.Now.Ticks.
DateTime.Now.Ticks is the default seed for Random so if you're seeing the same values over and over in a loop like this, multiplying the value by DateTime.Now.Ticks will still yield the same value.

Share this post


Link to post
Share on other sites
Like Flimflam said, I would create an instance variable for Random and then in your SetSpawn method, call random.Next().


class Enemy
{
Random random = new Random();
...
}

public void SetSpawn(GraphicsDeviceManager g)
{
position = new Vector2(g.PreferredBackBufferWidth, r.Next(g.PreferredBackBufferHeight));
}

Share this post


Link to post
Share on other sites
Quote:
Original post by fkhan
Like Flimflam said, I would create an instance variable for Random and then in your SetSpawn method, call random.Next().

*** Source Snippet Removed ***


Actually, an member variable would probably do little good unless it was explicitly defined static.

If each Enemy has its own random, he'll fall into the trap he had when he initialized a new Random for each enemy, unless enemies are created at different times. Since he's probably initializing all his enemies at the same time, they'd all have the same time seed. Using a static member variable is the easiest way to deal with this.

Share this post


Link to post
Share on other sites
I have a static 'Calc' class which holds a lot of various common calculations, I also use it to hold a static random generator that I call through a static method in the class.

Though having a static variable like Flimflam says would work perfectly too.

Share this post


Link to post
Share on other sites

This topic is 2628 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this