I am trying to move a ball using time. The ball must move 5 pixel per second.
In my code the ball is moving faster. Why is it moving faster? What is wrong with my code?

#include <allegro.h>
#include <cstdlib>
#include <time.h>

int ball_x = 320;
int ball_y = 240;

int ball_tx;
int ball_ty;

BITMAP *buffer; //This will be our temporary bitmap for double buffering
float timer(){

	clock_t cur_time,start_time;
	cur_time = clock();
	start_time = cur_time + 1;
	return difftime(start_time,cur_time);

}
void moveBall(){

	ball_tx = ball_x;
	ball_ty = ball_y;
	int speed = timer() * 5;

	if(key[KEY_LEFT])ball_x = ball_x - speed;
	else if(key[KEY_RIGHT])ball_x = ball_x + speed;
	else if(key[KEY_UP])ball_y = ball_y - speed;
	else if(key[KEY_DOWN])ball_y = ball_y + speed;


	acquire_screen();
	textprintf(buffer,font,10,10,makecol(255,255,255),"ball x = %d" "ball y = %d",ball_x,ball_y);
	circlefill ( buffer, ball_tx, ball_ty, 5, makecol( 0, 0, 0));	
	circlefill ( buffer, ball_x, ball_y, 5, makecol( 255, 255, 255));
	draw_sprite( screen, buffer, 0, 0);
	release_screen();


}
int main(){

	allegro_init();
	install_keyboard();
	set_color_depth(16);
	set_gfx_mode( GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
	buffer = create_bitmap( 640, 480); 

	while( !key[KEY_ESC]){

		moveBall();

	}

	return 0;

}
END_OF_MAIN();

Dani AI

Generated

A few concrete points that explain what went wrong and how to fix it (drawing on ’s observation about the timer and on the code examples posted by and ).

The real problems were: a broken timer (mixing time APIs or returning a constant), confusing units (speed must be pixels per second and multiplied by elapsed seconds), and unsafe drawing that can look like “weird” movement or even corrupt memory if coordinates go out of bitmap bounds. After fixing the timer it’s normal that the on-screen velocity changes — the numeric speed is literal pixels/sec (set it to 5 for 5 px/s). Also avoid passing fractional or out-of-range coordinates directly to Allegro draw calls; clamp and cast to ints before drawing.

Checklist of practical fixes

  • Use a proper elapsed-time measurement (steady/high-resolution clock) and compute dt in seconds. Do not mix time()/difftime() with clock() incorrectly.
  • Keep speed as pixels/second. Movement per frame = speed * dt.
  • Clamp dt (e.g. if (dt > 0.05) dt = 0.05;) to avoid huge jumps after a stall.
  • Clear the backbuffer each frame (or redraw the background) instead of trying to “erase the old ball” only. Call clear_bitmap(buffer) or fill the background.
  • Clamp positions to [radius, width-radius] and [radius, height-radius] before calling circlefill. Convert to ints for drawing to avoid passing floats into Allegro drawing code.

Example (modern, different from the original posted snippets):

using namespace std::chrono;
auto last = steady_clock::now();

while(!key[KEY_ESC]) {
  auto now = steady_clock::now();
  double dt = duration<double>(now - last).count();
  last = now;
  if(dt > 0.05) dt = 0.05; // clamp

  // movement in pixels/sec
  const double speed = 5.0;
  if(key[KEY_LEFT])  ball_x -= speed * dt;
  if(key[KEY_RIGHT]) ball_x += speed * dt;
  if(key[KEY_UP])    ball_y -= speed * dt;
  if(key[KEY_DOWN])  ball_y += speed * dt;

  // clamp positions and draw safely
  ball_x = std::max(radius, std::min(ball_x, WIDTH - radius));
  ball_y = std::max(radius, std::min(ball_y, HEIGHT - radius));
  clear_bitmap(buffer);
  circlefill(buffer, int(ball_x+0.5), int(ball_y+0.5), radius, makecol(255,255,255));
  blit(buffer, screen, 0,0,0,0, buffer->w, buffer->h);
  rest(1);
}

If the Y coordinate still “jumps” when X crosses a value, reproduce with clamped coordinates and small radius; if the jump disappears then out-of-bounds drawing was the culprit (drawing off the bitmap can corrupt memory). Adding a debug print of dt and the per-frame delta (e.g. (int)(speed*dt)) will quickly show whether the timing or the drawing is the cause.

Recommended Answers

All 5 Replies

I doubt that using difftime with clock_t is a good idea. difftime works with data of type time_t, which is obtained from the function time(). The clock() function returns clock ticks since the start of the program, and if I'm not mistaken, the clock ticks are only those counted towards this program (it is not a measure of real time elapsing, it is a measure of how much time this program has spent executing stuff, which is only a fraction of the overall time the computer spends executing stuff (which is real time consumption)).

To get the difference between clock ticks, you can do:

return float(cur_time - start_time) / float(CLOCKS_PER_SEC);

To use time() instead of clock, you can do:

float timer(){
  time_t cur_time, start_time;
  cur_time = time();
  start_time = cur_time + 1; //???? THIS MAKES NO SENSE AT ALL ?????
  return difftime(start_time,cur_time);
}

The above just fixes the obvious problem (that you shouldn't mix time_t and clock_t). However, I cannot, for the life of me, understand how your function is supposed to work. Right now, all the timer() function does is return a constant value, whose value is undefined (implementation-specific). What did you expect the function to do? If you expected that function to cause the program to sleep for X amount of time, you are mistaken. You need to use a sleep function for that (Sleep() in Windows, and usleep() in Linux). Essentially, this program you have executes at the maximum speed it can, and the value of "speed" will be constant and will be anything.

My guess is that this is the function you are looking for:

float timer(){
  static time_t start_time = time(); //initialize the start_time once only.
  time_t cur_time = time(); //get the current time
  float result = difftime(cur_time,start_time); //take the time-difference
  start_time = cur_time; //record the current time as the start of next iteration.
  return result; //return the time-difference that was measured.
}

I am trying to move the ball 5 pixel per second. The problem must be in the timer. I am trying to create a timer to move the ball 5 pixels per second. How can I fix the timer? Thanks in advance.

I fixed the timer. After I fixed the timer I found another error. I discovered that 5 pixels per second is too slow. Now it is moving 100 pixels per second.
When ball_x < 100, Ball_y changes. Why does it changes? What is wrong with my code?

#include <allegro.h>
#include <time.h>

int speed = 100;
double ball_x = 320;
double ball_y = 240;


BITMAP *buffer; //This will be our temporary bitmap for double buffering
clock_t final, initial;
double elapsed;

void moveBall(){

	circlefill ( buffer, ball_x, ball_y, 5, makecol( 0, 0, 0));	//Erase the old ball

	if(key[KEY_LEFT] && ball_x > 0 + 5)
		ball_x = ball_x - speed*elapsed;
	else if(key[KEY_RIGHT] && ball_x < 640 -5)
		ball_x = ball_x + speed*elapsed;
	if(key[KEY_UP] && ball_y > 0 + 5)
		ball_y = ball_y - speed*elapsed;
	else if(key[KEY_DOWN] && ball_y < 480 - 5)
		ball_y = ball_y + speed*elapsed;

	textprintf(buffer,font,10,10,makecol(255,255,255),"ball x = %d, ball y = %d",(int)ball_x,(int)ball_y);
	circlefill ( buffer, ball_x, ball_y, 5, makecol( 255, 255, 255));

	acquire_screen();
	draw_sprite( screen, buffer, 0, 0);
	release_screen();


}
int main(){

	allegro_init();
	install_keyboard();
	set_color_depth(16);
	set_gfx_mode( GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
	buffer = create_bitmap( 640, 480); 
	initial = clock();
	final = clock();
	while( !key[KEY_ESC]){

		elapsed = (double)(clock() - initial)/(double) CLOCKS_PER_SEC;
		initial = clock();

		moveBall();
		
		rest(20);
	}

	return 0;

}
END_OF_MAIN();

Line 4 says it should move that speed.

Thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.