CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Jun 2011
    Posts
    0

    Angry Magically static members

    I have a simple MovingSquare class. I create an array of several of them and then randomly assign some values in the constructor. Each square has their own separate random color and random rotation velocity set in the constructor. When i create individual MovingSquare objects and then update and draw them to the screen, they are all identical. I ran the debugger and saw that during the constructor random values ARE assigned, but by the time update and draw are called, all the values that are RANDOMLY assigned during the NON static constructor in a NON static class are all the same.

    <code>

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;

    namespace TestVectors
    {
    public class MovingSquare
    {
    private Vector2 position;
    private Vector2 direction;
    private float velocity;
    private Texture2D texture;
    private float rotation; //not static
    private float rotationVelocity; //not static
    private Rectangle source;
    private Vector2 center;
    private Color randColor; //not static
    private Random rand = new Random(); //not static

    public const int SCREEN_WIDTH = 800;
    public const int SCREEN_HEIGHT = 600;

    public MovingSquare(Texture2D texture, Vector2 position, Vector2 direction)
    {
    this.texture = texture;
    this.position = position;
    this.direction = direction;
    center = position + new Vector2(source.Width / 2, source.Height / 2);
    source = new Rectangle(0, 0, 16, 16);
    velocity = 1.5f;
    randColor = new Color(rand.Next(0, 256), rand.Next(0, 256), rand.Next(0, 256));
    rotation = (MathHelper.ToRadians((float)rand.Next(0, 360))) % MathHelper.TwoPi;
    rotationVelocity = (float)(rand.Next(1, 20) * .01);
    }

    //all instance variables that are assigned in the constructor are considered "static" here
    public void Update(GameTime gameTime)
    {
    float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
    rotation = rotation + rotationVelocity;

    direction.Normalize();
    this.position = new Vector2(position.X + (direction.X * velocity), position.Y + (direction.Y * velocity));

    if (position.X < -1.0f)
    {
    position.X = SCREEN_WIDTH;
    }
    else if (position.X > SCREEN_WIDTH + 1)
    {
    position.X = 0.0f;
    }

    if (position.Y < -1.0f)
    {
    position.Y = SCREEN_HEIGHT;
    }
    else if (position.Y > SCREEN_HEIGHT + 1)
    {
    position.Y = 0.0f;
    }
    }

    //and here
    public void Draw(SpriteBatch spriteBatch)
    {
    spriteBatch.Draw(texture, position, source, randColor, rotation, new Vector2(source.Width / 2, source.Height / 2), 1.0f, SpriteEffects.None, 0.0f);
    }
    }
    }
    </code>

    Example:

    in Game1.cs, I construct the objects individually:

    in LoadContent()
    square1 = new MovingSquare(texture, startingPosition, randomDirection);
    square2 = new MovingSquare(texture, startingPosition, randomDirection);

    you would think the instance variables have random values here but they have the same "random" values that the first square have.

    then in Update() method
    square1.Update(gameTime);
    square2.Update(gameTime); //square2's instance variables are now identical to square1's instance variables that were randomly generated in the constructor.

    My first solution to this problem was to create properties for each one and then assign them when constructing the individual squares. Any values assigned to the objects outside the class (in Game1.cs) are not treated as static variables. I decided that this was an insane hack that shouldnt be necessary and would like a solution to this problem. Thanks for reading my post!

  2. #2
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Magically static members

    The documentation is your friend and should be your first resource:

    The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated. One way to produce different sequences is to make the seed value time-dependent, thereby producing a different series with each new instance of Random. By default, the parameterless constructor of the Random class uses the system clock to generate its seed value, while its parameterized constructor can take an Int32 value based on the number of ticks in the current time. However, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.
    If you want to create new random objects quickly then you should provide your own seed value as your code is likely running under the resolution of the system timer.

  3. #3
    Join Date
    Jul 2008
    Location
    WV
    Posts
    5,362

    Re: Magically static members

    By using the system timer as a seed you will get random numbers, I've been using this method in VB for years without issue. Failure to provide the parameter defaults to the clock and will often result in the same sequence of numbers as pointed out in the document above. Likewise if you provide a static number as a seed then your random sequence will repeat every time an instance is created.
    Always use [code][/code] tags when posting code.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured