Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Setting game speeds the same on all computers

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Setting game speeds the same on all computers
Danex!
Member #7,759
September 2006
avatar

ok so i have my pong game working and everything is fine and i feel great about it so i decided to send it out to sum friends to show them my work and see if they can find flaws in the program through playing it, the first thing they noticed is how fast the ball moves when the game starts....however when i complie and run the game the ball starts out and a speed barely above crawling, so whats goin on here??

second they noticed the lack of a start menu of any kind so they can be ready to play right when they start the game and not be shocked into the game with the ball already moveing and they don't even know the controls(lack of a readme or instruction which should also be on a menu) i looked at another game's menu screen and thought it was cool and then looked at its code...and its probably more lines of code than my entire game ha ha ha so any suggestions for either of these?
Danex!

HardTranceFan
Member #7,317
June 2006
avatar

I assume you had a peek at my game code. I didn't think it was THAT long ;D

For you ball speed problem, use timers to work out how much time has elapsed since the last frame was blatted to the screen, and use this to multiply your speed variables.

Say you want 10 ball movements done per second. Then you would use something along the lines of:

#define ballMovements 10

timeMultiplier = ballMovements/ticksPerSecond;
deltaTime = timeNow() - lastTime;
position = position + (speed * timeMulitplier * deltaTime);
lastTime = timeNow();

On slower machines the steps between sequential ball placements would be larger than faster on machines. It's pseudo code (ie you need to determine what you want to use for timeNow() and ticksPerSecond).

One way of implementing a menu system would be to print a list of options and highlight the chosen menu option (a pointer next to the text, changing the colour of the text, a coloured box behind the text...), and move the highlight with the cursor keys, selecting the option when space or return are pressed.

Jeroen

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Matt Weir
Member #7,476
July 2006
avatar

You could always just have a start screen for the game that has the control keys written on it somewhere if you want to take the easy way out for your game. ;)

HardTranceFan
Member #7,317
June 2006
avatar

That reminds me of the good old days, when you had to enter the letter of the option you wanted to choose (Press 'S' to start, 'E' to exit', 'O' for options...)

Sigh. :D

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Danex!
Member #7,759
September 2006
avatar

hey hardtrace, i am trying to implement a moves per second like u said but i don't really understand what you are saying and therefore could not implement it :/... so could you clarify or help or something?
Danex!

imaxcs
Member #4,036
November 2003

nm :-X

HardTranceFan
Member #7,317
June 2006
avatar

OK, I'll try it by explaining what is happening, and then giving a little definition of each variable involved in my pseudo code.

The idea is to move the ball at a set speed by altering the ball's position on the screen a set number of times per second, regardless of how fast or slow the PC runs.

The PC timer works on clock ticks. I assume faster PCs have more clock ticks per second than slower PCs. Dividing the number of ball speed updates by the number of clock ticks per second, you get a multiplier. Using this multiplier on the number of clock ticks that have passed determines the number of times the speed factor should be added to the ball's position.

For example: Say you have 2 PCs, PC1 with 1000 clock ticks per second, PC2 with 5000 clock ticks per second, and you want the speed component to be added 10 times per second. The multiplier for PC1 will be 10/1000 = 1/100 (add the speed component once every 100 clock ticks). The multiplier for PC2 will be 10/5000 = 1/500.

Now, just for explanations sake, assume the speed is 1 (pixel) this is to be added 10 times per second. Say PC1 updates the ball position every 250 clock ticks (deltaTime = 250, which is the same on PC1 as 4 times a second) and PC2 updates the ball position every 200 clock ticks (deltaTime = 200, equivalent to 25 times a second). For PC1, the position update will be 1 * 250 * (1/100), or 2.5 pixels every update. This still achieves the 10 updates per second (2.5 * 4 = 10). For PC2, the position update will be 1 * 200 * (1/500) = 0.4 pixels per update. This too achieves the 10 updates per second (0.4 * 25 = 10)

The pseudo code names stand for:

timeMultiplier is calculated to be the minimum number of clock ticks that need to occur before the ball should be redrawn to the screen.

ballMovements is the number of times you want the speed component to be added to the ball's position per second. Play with this to get a reasonable speed.

ticksPerSecond is the number of clock cycles (?) that occur per second (=CLOCKS_PER_SEC in time.h from memory)

deltaTime is the elapsed time between the last time the ball was drawn to the screen and now

timeNow() is a made up function name that gets the number of cycles elapsed (=clock() in time.h, again from memory)

lastTime is the number of cycles when the ball was last redrawn to the screen.

position is the x or y component of the ball's screen position

speed is the x or y speed value of the ball

To add to this all, an alternative is to check that a set number of clock ticks have passed (ie deltaTime > ticksPerSecond / ballMovements), and then adding the speed component accordingly.

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Danex!
Member #7,759
September 2006
avatar

Ok so everything resets itself.
Also i should declare all of your intergers as global floats correct.
How do i get the time_now() from <time.h> shoudl i set timenow() = time.h? Can you even do this without errors?
Also ticks per second would also be taken from time.h right? So how to you get that out of there?
So basically my questions are:

1) Can i set time_now = <time.h>. If not what should i do to do this?

2) How do i pull ticks_per_second out of the computer?
Danex!

HardTranceFan
Member #7,317
June 2006
avatar

Quote:

1) Can i set time_now = <time.h>. If not what should i do to do this?

Err, no. timeNow() was a pseudo code for a function that gets the current number of clock ticks. As per definition, in time.h it's clock(). time.h is a standard C library.

Quote:

2) How do i pull ticks_per_second out of the computer?

As I explained the definitions, use CLOCKS_PER_SEC.

Check out http://www.cplusplus.com/ref/ctime/ , and look for some tutorials on timers. You can also look at the source code of my game for timer usage.

Jeroen

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Danex!
Member #7,759
September 2006
avatar

I see now, i just over analyzed it thinking that you were useing other names besides clock() and the other one for a specific reason cause it might cause errors in the program.(I guess you giving me the pseudo then the acual function confused me.) However i understand now :), back to work then, Thankyou for your help!
Danex!

HardTranceFan
Member #7,317
June 2006
avatar

I had thought using the pseudo code may help in case you used a different timer library, but looks like it confused the issue a little. I'll try making it clearer next time. Good luck making it all work in your game :)

Jeroen

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Danex!
Member #7,759
September 2006
avatar

 timeMultiplier = ballMovements/CLOCKS_PER_SEC;
deltaTime = clock() - lastTime;
ball_x = ball_x + (x_speed * timeMulitplier * deltaTime);
lastTime = clock();
ball_y = ball_y + y_speed;

Above is what i am working with.
When you complie the program it returns the error:
`timeMulitplier' undeclared (first use this function)
Why is it counting timeMultiplier as a function when i declared it as a float?
Danex!

Thomas Fjellstrom
Member #476
June 2000
avatar

Its not counting it as a function. its saying its not been defined or declared anywhere this function can see. and won't repeat the warning again after this first message.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Danex!
Member #7,759
September 2006
avatar

Its defined as a global, how can it not be seen?
Danex!

Zaphos
Member #1,468
August 2001

Quote:

Its defined as a global, how can it not be seen?

If it's defined below where it's used, or in a different (not included) file? Or if you made a typo ...

HardTranceFan
Member #7,317
June 2006
avatar

You'll also need to apply the timeMulitplier * deltaTime bit to the ball_y calculation (or the ball will travel slowly vertically on your machine, and race along on your mates PCs).

Jeroen

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Danex!
Member #7,759
September 2006
avatar

thats my code with comments where i defined timeMultiplier and where it showed error

1//global stuff
2 
3#include <allegro.h>
4#include <cstdlib>
5#include <time.h>
6#define ballMovements 10
7BITMAP *buffer;
8void menu();
9void game();
10volatile long speed_counter;
11void increment_speed_counter() {
12speed_counter ++; }
13END_OF_FUNCTION(increment_speed_counter)
14float ball_x = 320;
15float ball_y = 240;
16int paddle_speed_up = 2;
17int paddle_speed_down = 2;
18int paddle_1_y = 240;
19int paddle_1_height = 79;
20int paddle_2_height = 79;
21int paddle_2_y = 240;
22int paddle_1_x = 0;
23int paddle_2_x = 0;
24float x_speed=-1;
25float y_speed=-1;
26float deltaTime, lastTime;
27float timeMultiplier; //defined as a global float
28 
29//main
30 
31int main() {
32 allegro_init();
33 install_timer();
34 LOCK_VARIABLE(speed_counter);
35 LOCK_FUNCTION(increment_speed_counter);
36 install_int_ex(increment_speed_counter,BPS_TO_TIMER(60));
37 install_keyboard();
38 set_color_depth(16);
39 set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
40
41 BITMAP *paddle_1;
42 BITMAP *paddle_2;
43 paddle_1 = load_bitmap("paddle1.bmp",NULL);
44 paddle_2 = load_bitmap("paddle2.bmp",NULL);
45 buffer = create_bitmap(640,480);
46 menu();
47 while (!key[KEY_ESC])
48 {
49
50 while (speed_counter >0)
51 {
52 if (key[KEY_DOWN]){
53 paddle_1_y = paddle_1_y + paddle_speed_up; }
54 else if (key[KEY_UP]){
55 paddle_1_y = paddle_1_y - paddle_speed_up; }
56 if (key[KEY_S]) {
57 paddle_2_y = paddle_2_y + paddle_speed_up; }
58 else if (key[KEY_W]){
59 paddle_2_y = paddle_2_y - paddle_speed_up; }
60 speed_counter --;
61 if (paddle_1_y < 0){
62 paddle_1_y = 0;}
63 if (paddle_2_y < 0){
64 paddle_2_y = 0;}
65 if (paddle_1_y + paddle_1_height > 480){
66 paddle_1_y = 480 - paddle_1_height;}
67 if (paddle_2_y + paddle_2_height > 480){
68 paddle_2_y = 480 - paddle_2_height;}
69
70 }
71
72 game();
73 textout_ex(buffer, font, "PongGame // Press ESC to leave", 0, 0, makecol( 255, 0, 0), makecol( 0, 0, 0));
74 draw_sprite(buffer, paddle_1, 20, paddle_1_y);
75 draw_sprite(buffer, paddle_2, 620, paddle_2_y);
76 blit(buffer,screen,0,0,0,0,640,480);
77 clear_bitmap(buffer); }
78destroy_bitmap(paddle_1);
79destroy_bitmap(paddle_2);
80destroy_bitmap(buffer);
81return 0;}
82END_OF_MAIN()
83 
84 
85
86void game(){
87 
88timeMultiplier = ballMovements/CLOCKS_PER_SEC;
89deltaTime = clock() - lastTime;
90ball_x = ball_x + (x_speed * timeMulitplier * deltaTime);//error
91ball_y = ball_y + (y_speed * timeMulitplier * deltaTime);//error
92lastTime = clock();
93 
94if (ball_y < 0){
95ball_y = 0;
96y_speed = -y_speed;}
97if (ball_y > 475){
98ball_y = 475;
99y_speed = -y_speed;}
100if (ball_x < 20 && ball_y >= paddle_1_y && ball_y <= paddle_1_y + paddle_1_height){
101 x_speed = -x_speed;
102 y_speed += (float) rand() / RAND_MAX * .4;
103 if (x_speed > 19) {
104 x_speed = 19;}
105 if (paddle_speed_up > 4)
106 {paddle_speed_up = 4;}
107 else{
108 x_speed++;
109 paddle_speed_up = paddle_speed_up + 1;}
110
111 }
112if (ball_x > 620 && ball_y >= paddle_2_y && ball_y <= paddle_2_y + paddle_2_height){
113 x_speed = -x_speed;
114 y_speed += (float) rand() / RAND_MAX * .4;
115 if (x_speed > 19) {
116 x_speed = 19;}
117 
118 }
119if (ball_x > 640) {
120ball_x =320;
121textout_ex( screen, font, "Player 1 Wins!", 320, 240, makecol( 255, 0, 0), makecol( 0, 0, 0));
122rest(3000);
123exit(EXIT_FAILURE);
124}
125if (ball_x < 0){
126ball_x = 320;
127textout_ex( screen, font, "Player 2 Wins!", 320, 240, makecol( 255, 0, 0), makecol( 0, 0, 0));
128rest(3000);
129exit(EXIT_FAILURE);
130}
131circlefill( buffer, ball_x, ball_y , 5, makecol( 0,255, 0)); }
132
133void menu() {
134 textout_ex( screen, font, "Press any key to begin!", 320, 240, makecol( 255, 0, 0), makecol( 0, 0, 0));
135readkey(); }

HardTranceFan
Member #7,317
June 2006
avatar

You've got a typo - timeMulitplier should be timeMultiplier ::)

Jeroen

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Danex!
Member #7,759
September 2006
avatar

:-[He he makes me feel dumb cause i checked that but i just can't spell.
Well now the program compiles but the ball never starts moving? Whats goin on there. With the old system it moved but jsut to fast on some computers, now its not moving at all. Could it be that my comp is so slow that its just takeing that long to move?
Danex!

HardTranceFan
Member #7,317
June 2006
avatar

I copied the first spelling of it and did a repeated search in the code - it only found 2, hence it was a spelling difference.

As for your latest problem, I'm tempted to say debug, but that might not solve it. Visit the time.h link I gave you earlier, and look the data type clock() returns.

Jeroen

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Danex!
Member #7,759
September 2006
avatar

Ok I tried to run debug useing the dev C++ debug function but it just produced an error that turned my screen blue and i have to click to restore and it had shut down dev c++ so thats out. As for clock() it says for most compiliers it returns long int. Should i change it to long int type?
Danex!
[edit]
Did that and it did nothing...makes me mad that the game works perfectly on my system but differnetly on other systems

HardTranceFan
Member #7,317
June 2006
avatar

Try setting it to type clock_t.

Remember to cast in the calculations.

Debugging is not just a matter of running a program in debug mode. Debugging is the process of working out what is going wrong by whatever means you can. If debug mode won't work, try using output statements to the screen or a file to see what certain values are set to.

And I repeat, look at examples of time.h being used in other programs. It's one of the best ways of learning of how things are done.

Jeroen

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

LennyLen
Member #5,313
December 2004
avatar

Quote:

He he makes me feel dumb cause i checked that but i just can't spell.

Unless you've set your compiler to not report a single error or warning, then it should have complained about an undeclared variable.

Bob
Free Market Evangelist
September 2000
avatar

What's wrong with the Allegro FAQ?

--
- Bob
[ -- All my signature links are 404 -- ]

Kitty Cat
Member #2,815
October 2002
avatar

clock() isn't the function you want, as it only measures time for the process, not the whole system time. The standard functions to use would be gettimeofday, or clock_gettime (both POSIX standard). Of course, Windows doesn't have these, so you'll need to use QueryPerformanceFrequency and QueryPerformanceCounter.

However, I'd recommend against delta time methods for newbies. A fixed logic rate, as described in Allegro's FAQ, would be much simpler and work just as good.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

 1   2 


Go to: