Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am making a game in XNA, and I am trying to make a dog move randomly. The game is platform, so he only moves left and right. I put this code in the Update() method: int random = dog.Next(0, 2);

        if (random == 0)
        {
            dogPosition.X -= 20;
        }

        if (random == 1)
        {
            dogPosition.X += 20;
        }

I want him to move right or left a little, then stop, then move again like in Terraria or MapleStory. What happens is he changes direction too fast. Is there a way to do this with timers? I couldn't figure the timers out, so I put it in the Draw() method and added a for loop:

        for (int dogTimer = 0; dogTimer > 40; dogTimer++)
        {
            int random = dog.Next(0, 2);

            if (random == 0)
            {
                dogPosition.X -= 200;
            }

            if (random == 1)
            {
                dogPosition.X += 200;
            }
        }

When I run that code, he does not move at all. Can someone tell me how to use timers to do this, or how to fix the problem in the second code? Any help is appreciated. Thanks is advance :)

share|improve this question
2  
Your loop is bugged. You want dogTimer < 40; However, if that is in your draw loop it won't work because it won't update what's on screen inside that loop. SalmonMoose beat me to the answer. –  Byte56 Mar 14 '12 at 2:21
    
You could also try setting a direction vector and moving your object in the direction of that vector. Then rotate the vector with a maximum of x-degrees per seconds, this should give smoother results. But be sure to commit to going left, right, or forward, for at least a few 100 miliseconds. –  Roy T. Mar 14 '12 at 7:07
add comment

4 Answers

up vote 3 down vote accepted

It seems to me like people missed the XNA tag on the question, so here's an XNA-specific answer.

First of all, you need to add two variables to your Dog class (if you don't have a Dog class, add them to the class where your Update method is located):

float elapsedTime = 0; //Time elapsed since the last check
int direction = 1; //Default travel direction

Then, you'll want to change your update statement to say this:

elapsedTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (elapsedTime > 1) { //Get a new random direction every 1 second
    elapsedTime -= 1; //Subtract the 1 second we've already checked
    direction = dog.Next(0, 2); //Set the direction to a random value (0 or 1)
}

if (direction == 0) {
    dogPosition.X -= 200;
} else {
    dogPosition.X += 200;
}

Simply put, it gets a new direction once per second and updates the dog's position.

More in-depth explanation:
This code keeps a count of the elapsed time between each Update statement (in seconds). Once that count has reached a certain value (in this case, 1 second), we get a new random direction. It's possible that the dog will continue in the same direction it's going, or it may turn around. It then updates the current X value based on the value of the direction variable.

The reason it seemed so random and weird for your previous code, is because Update gets run 60 times per second (in theory). This means that you were giving the dog a random direction 60 times per second which would cause it to be jittery. Not only that, but since you put it in a for loop, if you had written it correctly, you would have been updating it 60 * 40 = 2400 times per second!

share|improve this answer
add comment

You need to set him targets, and randomize those.

update():
    if(position.x = target.x):
        target.x = rand(position.x-range, position.x+range)
    if(position.x < target.x):
        position.x += speed
    else:
        position.x -= speed

This should select a destination somewhere within range, walk towards it at speed, and then select a new destination, and walk towards that.

This is pretty simplified, you should be scaling movement against time rather than frames, and there'd usually be some sort of path-finding going on as well.

share|improve this answer
1  
There's a problem with this code: if the dog starts at x=30 and moves at a speed of 5, it will never ever reach a target that isn't at a coordinate that is a multiple of 5. –  Jonathan Hobbs Mar 14 '12 at 2:30
1  
Indeed, you'd want to add clauses like this one for the position.x < target.x condition: if(position.x + speed >= target.x) { position.x = target.x; } else { position += speed; } –  Byte56 Mar 14 '12 at 3:20
add comment

You can try something like this:

Define a class for a movement event

Class MovementEvent
{
    Vector2 startplace;
    Vector2 endplace;
    float currentTime;
    float endTime;
    float idleTime;
}

You can create movements like this:

dog::CreateMovement()
{
    Movement = new Movement();
    Movement.startPlace = this.Position;
    Movement.endPlace = new Vector2();
    Movement.endPlace.X = this.Position.X + RN; //Guarantee that RN is a random number that will keep the dog in the platform without falling.
    Movement.endPlace.Y = this.Position.Y;
    Movement.currentTime = 0;
    Movement.endTime = (Movement.startPlace - Movement.endPlace).Length() / dogSpeed;
    Movement.idleTime = RID; //Where RID is a random amount of seconds to the dog wait before start walking again. Like MapleStory NPCS do.
}

On the dog class, store a MovementEvent. Every frame, check this MovementEvent and do something about it, like this:

if(dog.Movement == null)
{
    dog.CreateMovementEvent();
}
if(dog.Movement.currentTime >= dog.Movement.endTime)
{
    dog.Movement.idletime -= gameTime.ElapsedGameTime.TotalSeconds;
    if(dog.Movement.idleTime <= 0) dog.Movement = null;
}
else
{
    Vector2.Lerp(dog.Movement.startPlace, dog.Movement.endPlace, dog.Movement.currentTime / dog.Movement.endTime, dog.position);
}

Not sure if this is what you want, but is what I understood about your problem.

If you need any definitions:
Vector2
Vector2.Lerp
Vector2.Length

share|improve this answer
add comment

Or for simplicity just use a 'direction'

dx=1; //move right
dx=-1; move left

and change that direction sometimes, say every some random seconds, like

if(((random() % 500) == 1)

in the main loop you'd just move the dog every frame according to dx:

dogPosition.X += dx;
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.