[C++] Delayed action of srand() - coordinates for object

Started by
22 comments, last by L. Spiro 11 years, 4 months ago
Hi,
I've created the small program where the ball is moving all the time on the screen to random coordinates made like that:

[source lang="cpp"]srand(time(NULL));
do
{
ballX = randx;
ballY = randy;
}while(abs(oldx-ballX) > 300 && abs(oldy-ballY) > 300);
oldx = ballX;
oldy = ballY;[/source]
It's included in while(!gameover) function. That moves the ball:

[source lang="cpp"]void moveBall()
{
if(ballposition.x > ballX)
{
ballposition.x -= ballspeed;
}
if(ballposition.x < ballX)
{
ballposition.x += ballspeed;
}
if(ballposition.y > ballY)
{
ballposition.y -= ballspeed;
}
if(ballposition.y < ballY)
{
ballposition.y += ballspeed;
}
}[/source]

The only problem is that the ball is moving to the right coordinates X and Y, then sometimes stays for a moment and then another move and so on. When I try to delete the "srand(time(NULL));" it causes the ball to move really fast in each direction but no lag. How can I fix this?
Advertisement
I don't see any calls to rand() in that code, so I am having a hard time following what it's doing. What exactly are `randx' and `randy'?
How is randx and randy being set?

I'm not yet sure if this is your problem, I think you should post a bit more code, but srand(time(NULL)); should (in most simple programs) only be called once: when your game starts up. Not every frame of your game.

Could you post your entire main loop, cutting out the portions that don't involve randomness or the ball movement? I'd like to see the flow of your code, to mentally walk through it and see what's up.
What is the intent of your program? Should it pick a random point, move to it, pick a new point, moves slowly to it, etc, etc? Or should the ball just meander around in a random fashion?
Oh, sorry. Random numbers are defined here:
[source lang="cpp"]#define randx rand()*100%1175
#define randy rand()*100%585[/source]

The whole code:

[source lang="cpp"]#include "SDL/SDL.h"
#include "SDL/SDL_ttf.h"
#include "SDL/SDL_mixer.h"
#include "SDL/SDL_image.h"
#include <windows.h>
#include <stdbool.h>
#include <time.h>
#define randx rand()*100%1175
#define randy rand()*100%585

using namespace std;

SDL_Surface * screen;
SDL_Surface * background;
SDL_Surface * ball;
SDL_Rect ballposition;
SDL_Event event;
int mouseX, mouseY;
int ballX = randx, ballY = randy;
int oldx, oldy;
int ballspeed = 1;
bool gameover = false;

void moveBall()
{
if(ballposition.x > ballX)
{
ballposition.x -= ballspeed;
}
if(ballposition.x < ballX)
{
ballposition.x += ballspeed;
}
if(ballposition.y > ballY)
{
ballposition.y -= ballspeed;
}
if(ballposition.y < ballY)
{
ballposition.y += ballspeed;
}
}

int main(int argc, char * args[])
{
SDL_Init(SDL_INIT_EVERYTHING);
Mix_OpenAudio(22050,MIX_DEFAULT_FORMAT,2,4096);
Mix_Chunk * click = Mix_LoadWAV("sounds/click.wav");
screen = SDL_SetVideoMode(1280, 720, 32, SDL_DOUBLEBUF | SDL_SWSURFACE);
background = IMG_Load("images/texture.jpg");
ball = IMG_Load("images/ball.png");
ballposition.x = 500;
ballposition.y = 400;
ballposition.h = 80;
ballposition.w = 80;
while(!gameover)
{
srand(time(NULL));
do
{
ballX = randx;
ballY = randy;
}while(abs(oldx-ballX) > 300 && abs(oldy-ballY) > 300);
oldx = ballX;
oldy = ballY;

while(SDL_PollEvent(event))
{
if(event.type == SDL_QUIT)
{
SDL_Quit();
return 0;
}
if(event.type == SDL_MOUSEMOTION)
{
mouseX = event.motion.x;
mouseY = event.motion.y;
}
if(event.button.button == SDL_BUTTON_LEFT
&&
( mouseX >= ballposition.x &&
mouseX <= ballposition.x + ballposition.w ) &&
( mouseY >= ballposition.y &&
mouseY <= ballposition.y + ballposition.h ) )
{
ballspeed++;
Mix_PlayChannel(0, click, 0);
}
}
moveBall();
SDL_BlitSurface(background, NULL, screen, NULL);
SDL_BlitSurface(ball, NULL, screen, &&ballposition);
SDL_Flip(screen);
}
}
[/source]

The point of the game is just to click on the moving ball which causes increase of its speed.
With the srand line in your program, ballX and ballY are being set to a single value for an entire second, then changes to another value. This is because the 'time' function precision is only one second, and you're using that to seed the random number generator.

With the srand removed (it should be removed, generally you only want to seed your RNG once), then your code is setting ballX and ballY to a new value every single frame, so the balls movement is more volatile.

What I guess you really want to do is change your code so that srand is called only during program initialisation, and add a condition so that you only set ballX and ballY to new values once the ball has reached the target.
So how should it look like?
I've did this in ball moving function:
[source lang="cpp"]if(ballposition.x == ballX && ballposition.y == ballY)
{
targetreached = true;
}
[/source]
And this in while(!gameover):
[source lang="cpp"]if(targetreached)
{
srand(time(NULL));
do
{
ballX = randx;
ballY = randy;
}while(abs(oldx-ballX) > 300 && abs(oldy-ballY) > 300);
oldx = ballX;
oldy = ballY;
targetreached = false;
}
[/source]

But it is still not working ;/ The ball is just moving to one position and then doesn't move any more.

So how should it look like?
I've did this in ball moving function:
[source lang="cpp"]if(ballposition.x == ballX &amp;&amp; ballposition.y == ballY)
{
targetreached = true;
}
[/source]
And this in while(!gameover):
[source lang="cpp"]if(targetreached)
{
srand(time(NULL));
do
{
ballX = randx;
ballY = randy;
}while(abs(oldx-ballX) > 300 &amp;&amp; abs(oldy-ballY) > 300);
oldx = ballX;
oldy = ballY;
targetreached = false;
}
[/source]

But it is still not working ;/ The ball is just moving to one position and then doesn't move any more.


I'm sure I saw a couple of clever minds in this thread commenting on the behaviour of srand() and rand()
and also, where srand() should be placed due to this behavior: on startup.
I'm also sure you'll be better off not using #defines when you can avoid it.

while(!gameover)
{
srand(time(NULL));



if(targetreached)
{
srand(time(NULL));



You are not supposed to srand so much. srand should only be used right at the beginning of the program, in the main function.

int main(void)
{
srand(time(0));
/*main loop...*/
return 0;
};


Also, don't use those misleading macros, just use the expression explicitly.

#define SCREEN_WIDTH 1175
#define SCREEN_HEIGHT 585
...
ballX = (rand() * 100) % SCREEN_WIDTH;
ballY = (rand() * 100) % SCREEN_HEIGHT;
As SuperVGA is saying, call srand() a single time at the beginning of your program and don't use macros. You could also benefit from better variable names. In particular ballX and ballY look like they would describe the ball's position, but they actually represent the target position for the ball.

Since you are using ballposition.x and ballposition.y somewhere in the code, you must already have a type to represent positions, so use it: Instead of ballX and ballY have a single variable ball_target.

Also, what's the point of having oldx and oldy? In the part of the code where they are used it looks like the position of the ball already contains that information, and I am guessing the code would become more readable if you use that instead.

Oh, the `while' condition in the loop selects a random point that is in the 300-pixel-wide cross centered around the current location of the ball. Is that what the intention was?

This topic is closed to new replies.

Advertisement