|
My Game runs Slow on PIII Machine |
armond
Member #8,282
January 2007
|
I got a 192 MB RAM and 933 Mhz PIII Machine. I was wondering why would my game run so slow on PIII Machines or below(although still acceptable)... I suspect this line... install_int(GameTimer::incrementGameTicker, 10); My game deoesn't seem to run at constant speed... Here is my ticker function... void GameTimer::incrementGameTicker() Thanks! |
Jeff Bernard
Member #6,698
December 2005
|
It runs so slow because you are telling the timer to be really slow. Instead you should try install_int_ex() as it gives better options for setting the speed of the timer (I like BPS_TO_TIMER). Or you can try to just fiddling with that 10, lowering it, until you get a speed that you like. -- |
Audric
Member #907
January 2001
|
This 100Hz timer (10ms) should run with no problem at all. |
armond
Member #8,282
January 2007
|
Hi! Sorry for the late response. I actually tried turning off everything leaving the ship to be the only thing visible. The scrolling background does take some time to process but it doesn't seem that heavy at all. I will try install_int_ex() and give you guys some feedback asap. Thanks! |
weapon_S
Member #7,859
October 2006
|
Is the PIII the computer you compiled the program on? |
armond
Member #8,282
January 2007
|
weapon_S Nope, it's not. But I was told that it wouldn't have any effect even if I compiled on that machine. I just run the binary there... |
Tobias Dammers
Member #2,604
August 2002
|
Care to share some more code? As in, a 20-100 line example that compiles as-is and reproduces the problem? --- |
Richard Phipps
Member #1,632
November 2001
|
Give us more details. If you are trying to scroll a 32bit screen on less than a 933Mhz Machine then I'm not surprised if you start getting slowdown. |
armond
Member #8,282
January 2007
|
Sure thing. Here is the code for my PlayState class which functions as the main entry of the game. Perhaps you could point out some problems here... 1#include "globals.h"
2
3PlayState::PlayState()
4{
5 currentLevel = 1;
6
7 GameManager::game_score = 0;
8
9 //create buffer image
10 GameManager::buffer = create_bitmap(SCREEN_W, SCREEN_H);
11
12 //load sprites
13 BitmapManager::addBitmap(SHIP_SPRITE, "graphics/fs.bmp");
14 BitmapManager::addBitmap(VULCAN_SPRITE, "graphics/vulcan.bmp");
15 BitmapManager::addBitmap(ASTEROID_SPRITE_FLYING, "graphics/asteroid_flying.bmp");
16 BitmapManager::addBitmap(ASTEROID_SPRITE_DYING, "graphics/asteroid_destroyed.bmp");
17 BitmapManager::addBitmap(BULLET_HEAD_SPRITE_FLYING, "graphics/bullet_head_flying.bmp");
18 BitmapManager::addBitmap(SPRITE_EXPLOSION, "graphics/explosion.bmp");
19
20 //load SFX
21 SoundManager::addSample(VULCAN_GUN_FIRE, "sfx/vulcan.wav");
22
23 //ship = new Ship(BitmapManager::SHIP_SPRITE, 50, 50, 50, 32, 1);
24 //Ship(int x, int y, int w, int h, int speed, int recoveryRate, int recoveryTime, Status stat, int lfe);
25 ship = new Ship(50, 50, 50, 45, 3, 5, 1000, ALIVE, MAX_PLAYER_LIFE);
26
27 //add a weapon for the ship
28 ship->addWeapon(VULCAN_GUN, WeaponFactory::getWeapon(VULCAN_GUN) );
29 ship->setCurrentWeapon(VULCAN_GUN);
30 ship->move(0, (SCREEN_H / 2) );
31}
32
33PlayState::~PlayState()
34{
35 BitmapManager::removeAll();
36
37 destroy_bitmap(GameManager::buffer);
38
39 delete ship;
40}
41
42PlayState* PlayState::getInstance()
43{
44 if (instance == NULL)
45 {
46 instance = new PlayState();
47 }
48
49 return instance;
50}
51
52void PlayState::init()
53{
54}
55
56void PlayState::pause()
57{
58}
59
60void PlayState::run()
61{
62 GameStateManager::pushState( GameOverState::getInstance() );
63 GameStateManager::getCurrentState()->run();//--execute run method
64 GameStateManager::popState(); //--pop the element on top
65
66 loadLevel(currentLevel);
67
68 //begin main game loop
69 while ( !key[KEY_ESC] )
70 {
71
72 while (GameTimer::game_ticker > 0)
73 {
74 //move left
75 if ( key[KEY_A] )
76 {
77 ship->move( ship->x - ship->getSpeed(), ship->y );
78 if ( ship->x <= 0 )
79 {
80 ship->move( ship->x + ship->getSpeed(), ship->y );
81 }
82 }
83 //move down
84 if ( key[KEY_S] )
85 {
86 ship->move( ship->x, ship->y + ship->getSpeed() );
87
88 if ( (ship->y + ship->height) >= SCREEN_H )
89 {
90 ship->move( ship->x, ship->y - ship->getSpeed() );
91 }
92 }
93 //move right
94 if ( key[KEY_D] )
95 {
96 ship->move( ship->x + ship->getSpeed(), ship->y );
97
98 if ( (ship->x + ship->width) >= SCREEN_W )
99 {
100 ship->move( ship->x - ship->getSpeed(), ship->y );
101 }
102 }
103 //move up
104 if ( key[KEY_W] )
105 {
106 ship->move( ship->x, ship->y - ship->getSpeed() );
107
108 if ( ship->y <= 20 )
109 {
110 ship->move( ship->x, ship->y + ship->getSpeed() );
111 }
112 }
113 //fire weapon
114 if ( key[KEY_K] )
115 {
116 ship->fireWeapon();
117 }
118 //change weapon
119 if ( key[KEY_TAB] )
120 {
121 //ship->fireWeapon();
122 }
123 //fire special
124 if ( key[KEY_L] )
125 {
126 }
127
128 //exit to menu
129 if ( key[KEY_ESC] )
130 {
131 break;
132 }
133
134 //scroll the background
135 bg->update();
136
137 //animate the ship
138 ship->update();
139
140 bg->draw();
141
142 //move all projectiles
143 for (std::vector<Projectile*>::iterator it = ProjectileFactory::projectilePool.begin(); it != ProjectileFactory::projectilePool.end(); ++it)
144 {
145 if ( (*it)->isVisible() == true )
146 {
147 Projectile* p = *it;
148 p->update(); //(*it)->update();
149 p->draw(); //(*it)->draw();
150
151 //check for collision on bullet and enemies
152 for(std::vector<Enemy*>::iterator eit = EnemyFactory::enemyPool.begin(); eit != EnemyFactory::enemyPool.end(); ++eit)
153 {
154 Enemy* e = *eit;
155
156 //projectile hits an enemy
157 if ( p->collides(e) && p->isActive() && e->isAlive() )
158 {
159 e->takeDamage(1); //TODO: change 1 to weapon power
160 p->makeInactive();
161
162 //player killed the enemy
163 if ( !( e->isAlive() ) )
164 {
165 GameManager::game_score += 10;
166 }
167
168 //exit the inner loop
169 break;
170 }
171 }
172
173 if ( !( p->isActive() ) )
174 {
175 Projectile* p = *it;
176 it = ProjectileFactory::projectilePool.erase(it);
177 // we must decrement, because it will be incremented when the loop starts over again
178 --it;
179 delete p;
180 }
181
182 }
183 else
184 {
185 Projectile* p = *it;
186 it = ProjectileFactory::projectilePool.erase(it);
187 // we must decrement, because it will be incremented when the loop starts over again
188 --it;
189 delete p;
190 }
191 }
192
193 //move all enemies
194 for(std::vector<Enemy*>::iterator it = EnemyFactory::enemyPool.begin(); it != EnemyFactory::enemyPool.end(); ++it)
195 {
196 Enemy* e = *it;
197
198 if ( e->isAlive() || e->isDying() )
199 {
200 e->update();
201 e->draw();
202
203 if ( e->isAlive() && ship->collides(e) )
204 {
205 ship->takeDamage(10); //TODO: change to enemy attack power
206 e->takeDamage(1);
207 }
208 }
209 }
210
211 //recharge weapon
212 ship->getCurrentWeapon()->recharge();
213
214 //control game speed
215 GameTimer::game_ticker--;
216
217 ship->draw();
218
219 textout_ex(GameManager::buffer, font, "Life: ", 10, 10, makecol(0, 0, 255), -1);
220 //drawLifeBar(int x, int y, int length, height, BITMAP* bitmap);
221 drawLifeBar(50, 0, ship->getLife() , 20, GameManager::buffer);
222
223 textprintf_centre_ex(GameManager::buffer, font, SCREEN_W/2, 10, makecol(255, 255, 255), makecol(0, 0, 0), "Current Weapon: %s", ship->getCurrentWeapon()->getWeaponName() );
224 textprintf_centre_ex(GameManager::buffer, font, (SCREEN_W - (SCREEN_W/8) ), 10, makecol(255, 255, 255), makecol(0, 0, 0), "Score: %d", GameManager::game_score);
225
226 textprintf_centre_ex(GameManager::buffer, font, SCREEN_W/2, 176, makecol(255, 255, 255), makecol(0, 0, 0), "num=%d", GameTimer::game_ticker);
227
228 //blit buffer
229 GameManager::blitBuffer();
230 }
231
232 }
233
234 unloadLevel(currentLevel);
235}
236
237void PlayState::update()
238{
239}
240
241void PlayState::clean()
242{
243}
244
245void PlayState::loadLevel(int level)
246{
247 PACKFILE* levelMap;
248
249 switch(level)
250 {
251 case 1:
252 SoundManager::addSample(METEOR_DESTROYED, "sfx/meteordestroyed.wav");
253
254 levelMap = pack_fopen("levels/level_01.lvl", "r");
255
256 createLevel(levelMap);
257
258 bg = new GameBackground(BitmapManager::addBitmap(SPACE_BACKGROUND, "graphics/bg.bmp"), HORIZONTAL_LEFT, 3, SCREEN_W, SCREEN_H);
259
260 break;
261 default:
262 break;
263 }
264
265 if (levelMap)
266 {
267 pack_fclose(levelMap);
268 }
269}
270
271void PlayState::createLevel(PACKFILE* packFile)
272{
273 std::string line;
274 char buf[255];
275
276 int currX = 0;
277 int currY = 0;
278 int xIncrement = (SCREEN_W / 20);
279 int yIncrement = (SCREEN_H / 20);
280
281 if (!packFile)
282 {
283 allegro_message("COULD NOT CREATE LEVEL!: %s", allegro_error);
284 }
285
286 while ( pack_feof(packFile) == 0 )
287 {
288 //read a line from the file (levelMap)
289 line = pack_fgets(buf, sizeof(buf), packFile);
290
291 //loop through each character in the line
292 for (int i = 0; i < line.length(); i++)
293 {
294 //only an empty space
295 if ( line.at(i) == ' ')
296 {
297 currX += xIncrement;
298 }
299 else //create an enemy object
300 {
301 Enemy* e = EnemyFactory::getEnemy( line.at(i) );
302 //set initial position of the enemy
303 e->move(currX, currY);
304 EnemyFactory::enemyPool.push_back(e);
305
306 e = NULL;
307
308 currX += xIncrement;
309 }
310 }
311
312 currX = 0;
313 currY += yIncrement;
314 }
315}
316
317void PlayState::unloadLevel(int level)
318{
319 switch(level)
320 {
321 case 1:
322 std::vector<Enemy*>().swap(EnemyFactory::enemyPool);
323 delete bg;
324 break;
325 default:
326 break;
327 }
328}
329
330void PlayState::drawLifeBar(int x, int y, int length, int height, BITMAP* bitmap)
331{
332 //rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
333 if (length <= 0)
334 {
335 length = 0;
336 }
337
338 rectfill(bitmap, x, y, (x + length), height, 255);
339}
340
341PlayState* PlayState::instance;
342int PlayState::currentLevel;
If you're interested on how the PlayState is loaded, here's my main cpp file. 1#include "globals.h"
2
3//declare all functions used
4int initAllegro();
5void deinitAllegro();
6
7int main(int* argc, char* argv[])
8{
9 //initialize allegro
10 if ( initAllegro() == -1 )
11 {
12 return -1;
13 }
14
15 //push states to gameManager stack
16 GameStateManager::pushState( PlayState::getInstance() );
17
18
19 //loop through gameManager stack
20 GameStateManager::getCurrentState()->run();//--execute run method
21 GameStateManager::popState(); //--pop the element on top
22
23
24 //deinitialize allegro
25 deinitAllegro();
26
27 return 0;
28}
29END_OF_MAIN()
30
31int initAllegro()
32{
33 allegro_init();
34 install_keyboard();
35
36 install_timer();
37
38 set_color_depth(GameManager::COLOR_DEPTH);
39
40 if ( set_gfx_mode(GFX_AUTODETECT, GameManager::GAME_WIDTH, GameManager::GAME_HEIGHT, 0, 0) != 0 )
41 {
42 allegro_message("Graphics Mode Could Not Be Set!: %s", allegro_error);
43 return -1;
44 }
45
46 if ( install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, 0) )
47 {
48 allegro_message("Sound Error: %s", allegro_error);
49 }
50
51 set_volume(255, 255);
52
53 LOCK_VARIABLE(GameTimer::game_ticker);
54 LOCK_FUNCTION(GameTimer::incrementGameTicker);
55
56 install_int(GameTimer::incrementGameTicker, 10);
57
58 return 0;
59}
60
61void deinitAllegro()
62{
63 allegro_exit();
64}
Here are the constants that I used for the game width, height and color depth. 1#include "globals.h"
2
3GameManager::GameManager()
4{
5}
6
7GameManager::~GameManager()
8{
9}
10
11void GameManager::blitBuffer()
12{
13 acquire_screen();
14
15 blit(buffer, screen, 0, 0, 0, 0, GAME_WIDTH, GAME_HEIGHT);
16
17 release_screen();
18
19 clear_bitmap(buffer);
20}
21
22BITMAP* GameManager::buffer;
23
24const short int GameManager::GAME_WIDTH = 640;
25const short int GameManager::GAME_HEIGHT = 480;
26const short int GameManager::COLOR_DEPTH = 16;
27
28int GameManager::game_score;
|
Andrei Ellman
Member #3,434
April 2003
|
Quote:
//move all projectiles Howmany enemies and projectyles do you have? If checking each projectyle against each enemy, the execution-time can grow very fast according to howmany of each there are. AE. -- |
Tobias Dammers
Member #2,604
August 2002
|
I agree with Andrei here. --- |
armond
Member #8,282
January 2007
|
Hi! I just tried doing install_int_ex(GameTimer::incrementGameTicker, BPS_TO_TIMER(100) ); doesn't make any change... I haven't tried Tobias Dammers's suggestion yet. But even when I don't fire any bullet(no instance created) and there is only 1 enemy it's still slow... Slow as in not as fast when I'm in a P-IV Machine... When I remove the scrolling background, it does get a little fast. But still not that fast... Here is the code for my scrolling bg BTW... I'd like to point out that this(the scrolling bg) isn't necessarily my problem.
I'm scrolling an 200x200 24-bit bitmap and drawing it repeatedly on screen to create an illusion of a scrolling background. |
Audric
Member #907
January 2001
|
24 bit bitmap? But your screen is 16bit... try to avoid run-time color conversion. If the animation is still choppy, the background drawing is not at fault and no optimization there will solve the problem. Last step: profile, using your compiler's options. edit: I just noticed you used draw_sprite() both times: If what you're copying is opaque, just blit() it, it will be quite faster. |
Richard Phipps
Member #1,632
November 2001
|
On low end machines drawing a 24 bit bitmap to the screen every frame is just slow at high resolutions. There is not much you can do if you have scrolling on such a machine. Looking into Video bitmaps might be your best bet.. |
armond
Member #8,282
January 2007
|
Thank you for your reply! Could you please explain what you meant by "Looking into Video bitmaps might be your best bet.."? |
Richard Phipps
Member #1,632
November 2001
|
Copying data from video bitmaps to the screen can be much faster that copying from a normal BITMAP if your card supports hardware acceleration. There is a section in the manual on it and many threads if you do a search on these forums. |
armond
Member #8,282
January 2007
|
Hi! I quick search from google tells me that you're talking about page flipping...? |
Richard Phipps
Member #1,632
November 2001
|
That's related, look in the manual in the gfx / bitmap sections. |
nonnus29
Member #2,606
August 2002
|
Armond, your noob code doesn't look like noob code. I'm not complaining, it's a nice change.... |
|