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()
{
game_ticker++;
}
END_OF_FUNCTION(incrementGameTicker);
Thanks!
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.
This 100Hz timer (10ms) should run with no problem at all.
If something runs at varying speed, it's in your main program.
If you comment out the heaviest video operations (for example: background drawing), does it change the apparent speed?
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!
Is the PIII the computer you compiled the program on?
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...
Care to share some more code? As in, a 20-100 line example that compiles as-is and reproduces the problem?
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.
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...
If you're interested on how the PlayState is loaded, here's my main cpp file.
Here are the constants that I used for the game width, height and color depth.
//move all projectiles
for (std::vector<Projectile*>::iterator it = ProjectileFactory::projectilePool.begin(); it != ProjectileFactory::projectilePool.end(); ++it)
[...]
//check for collision on bullet and enemies
for(std::vector<Enemy*>::iterator eit = EnemyFactory::enemyPool.begin(); eit != EnemyFactory::enemyPool.end(); ++eit)
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.
I agree with Andrei here.
Although game logic is usually the least of your problems, in this case you might want to optimize.
There are numerous optimization techniques you can use here, and virtually all of them try to reduce the number of iterations (read: try to loop through less objects). This is better than optimizing the collision test itself (rule of thumb: optimize algorithms, not code).
The key to this common problem is space partitioning, which means that you divide the total space in which objects can lie into regions, and you only test objects against each other that share a region. The art is to define your regions in such a way that they are easy and fast to calculate, and that they don't produce double checking. Here are a few approaches:
1. Axis sort. Sort all your objects by one of the cardinal axes (x or y). Check in both directions, and stop iterating when you hit an object that is too far away. This will usually restrict checking to the nearest 10 or so objects.
2. Tilemap. Divide your scene into a tile grid (you don't need to use this for drawing, but if you draw using a tilemap anyway, you may want to add the collision detection features to it while you're at it), and give each tile a list (a vector is probably your best choice, or maybe even a static array - just be careful not to produce overflows) with pointers to all checkable objects that touch it. If your tile size is a power of 2, then finding the tile a character is on is as trivial as a binary & with tilesize-1. Downside: enormous memory consumption, and you need to be careful with those character lists. Upside: you only check against 4 tiles max (provided your character isn't larger than the tile size).
3. Quadtrees. Google for it. The idea is that you divide your space into 4 sectors, and divide those 4 again, and so on, until a given minimum size is reached, OR a maximum number of characters is found in the sector. When checking for collisions, you only check against objects that share a sector with the current object. This is the hardest to code, but it is the most efficient one for complex scenes, with very little overhead and adaptable to the most uneven distributions of objects (e.g. a hundred objects crowding in one corner of the screen).
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.
| 1 | #include "globals.h" |
| 2 | |
| 3 | |
| 4 | GameBackground::GameBackground(BITMAP* bitmap, BackgroundScrollType scrollType, int scrollSpeed, int x, int y) |
| 5 | { |
| 6 | this->bitmap = bitmap; |
| 7 | this->scrollType = scrollType; |
| 8 | this->scrollSpeed = scrollSpeed; |
| 9 | this->x = x; |
| 10 | this->y = y; |
| 11 | |
| 12 | tmpBuffer = create_bitmap(SCREEN_W, SCREEN_H); |
| 13 | } |
| 14 | |
| 15 | GameBackground::~GameBackground() |
| 16 | { |
| 17 | destroy_bitmap(tmpBuffer); |
| 18 | } |
| 19 | |
| 20 | void GameBackground::update() |
| 21 | { |
| 22 | scrollBackground(); |
| 23 | } |
| 24 | |
| 25 | void GameBackground::scrollBackground() |
| 26 | { |
| 27 | switch(scrollType) |
| 28 | { |
| 29 | case HORIZONTAL_LEFT: |
| 30 | scrollLeft(); |
| 31 | break; |
| 32 | default: |
| 33 | break; |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | void GameBackground::draw() |
| 38 | { |
| 39 | draw_sprite(GameManager::buffer, tmpBuffer, 0, 0); |
| 40 | } |
| 41 | |
| 42 | void GameBackground::setScrollSpeed(int speed) |
| 43 | { |
| 44 | scrollSpeed = speed; |
| 45 | } |
| 46 | |
| 47 | void GameBackground::scrollLeft() |
| 48 | { |
| 49 | x -= scrollSpeed; |
| 50 | |
| 51 | int bw = bitmap->w; |
| 52 | int bh = bitmap->h; |
| 53 | |
| 54 | int xOffSet = (SCREEN_W + bw); |
| 55 | |
| 56 | if ( x > bw || x < -(bw) ) |
| 57 | { |
| 58 | x = 0; |
| 59 | } |
| 60 | |
| 61 | int newX = 0; |
| 62 | |
| 63 | for (int i = -(bw); i < (xOffSet); i += bw) |
| 64 | { |
| 65 | newX = (x + i); |
| 66 | |
| 67 | for (int j = 0; j < SCREEN_H; j += bh) |
| 68 | { |
| 69 | //draw tile |
| 70 | //Optimization: draw only parts that are visible to the screen |
| 71 | if ( ( newX + bw) > 0 ) |
| 72 | { |
| 73 | draw_sprite(tmpBuffer, bitmap, newX, j); |
| 74 | } |
| 75 | else |
| 76 | { |
| 77 | break; |
| 78 | } |
| 79 | |
| 80 | } |
| 81 | } |
| 82 | } |
I'm scrolling an 200x200 24-bit bitmap and drawing it repeatedly on screen to create an illusion of a scrolling background.
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.
I guess the final blit to screen takes the biggest toll, but you can't easily reduce this cost (dirty rectangles on a 840x680 hardware scrolling bitmap? Seems far-fetched)
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.
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..
Thank you for your reply! Could you please explain what you meant by "Looking into Video bitmaps might be your best bet.."?
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.
Hi! I quick search from google tells me that you're talking about page flipping...?
That's related, look in the manual in the gfx / bitmap sections.
Armond, your noob code doesn't look like noob code. I'm not complaining, it's a nice change....