Drawing map takes all CPU

Started by
5 comments, last by Sporniket 11 years, 2 months ago

I'm using tmx files for my map and finally got a tmx loader to work. The map drawing code is lagging my game because of the CPU usage. To draw my map, im using code which is:


for (int i = 0; i < map->GetNumLayers(); ++i) 
{
		// Get a layer.
		const Tmx::Layer *layer = map->GetLayer(i);

		for (int y = 0; y < 20; ++y) 
		{
			for (int x = 0; x < 20; ++x) 
			{
				// Get a test tile which is 32 x 32.
				Sprite* Suf2 = new Sprite(Surf_Tileset->getRect(TILE_SIZE, TILE_SIZE, TILE_SIZE, TILE_SIZE), 1, 0);
				// Draw tile to position on map
				Suf2->draw(Surf_Display, x * TILE_SIZE, y * TILE_SIZE);
			}
		}
}

So this code is on my Map::OnRender(SDL_Surface* Display). What can I do to keep my cpu from maxing?

Advertisement

Don't use new to create new Sprites every time (this is a memory leak BTW, because you're not deleting them...).

Do you actually notice it lagging, or are you assuming it's lagging because your CPU usage is 100%?

Are you actually measuring the milliseconds per frame (and not FPS)? smile.png

If your CPU is at 100%, that's because your program is basically saying, "Run as fast as you can, and we'll loop around and around the main loop until we decide to stop". If it's using 100%, it's because nothing else is currently using the processing power so the CPU just shrugs and runs your code faster.

The cheap and easy way to drop your CPU usage less than 100% is to just add a SDL_Delay(0) to the end of your main loop. It's not the best solution, but it'll suffice for a smaller project.

If your program is lagging, it's probably because you are calling 'new' every iteration of your two for() loops. 'new' can be expensive. If you just had one 'Sprite' created on the stack (not new'd, and not a pointer) and re-used it for every iteration, it'd go faster.

However, worse than that, is that you are using new wrong! Lesson one of using 'new' is the absolute rule: For every 'new' you must absolutely have a 'delete'*. You really shouldn't be using 'new' at all in this situation, but even if you are, you absolutely must learn how to use new before you actually use it. 'new' is not one of those things that you learn by using, it's something that must be learned firmly before using.

*And for every new[] a delete[], and for every malloc() a free(), and so on...

Don't use new to create new Sprites every time (this is a memory leak BTW, because you're not deleting them...).

Worked perfectly. Thank you, I should've known.

I got another question relating to this. How would I make it where I can use my Sprite class and use it in the loops? My loop loops through the different tiles and each of those tiles has a tileID from my bmp file. If the getTileID returns 23, it means it's the 23rd block in my bmp so I have to change my Surface for the new rectangle. I tried doing it but kept on getting the lagging problem because I frequently change the sprite for the different tiles.

SDL_Surface has built in ability to "draw" just portions of a larger image (like your tilesheet).

By not creating entirely new surfaces, you'll automatically gain enormous speedups (The fastest code is the code that never runs).

See Lesson 6, of Lazyfoo's SDL tutorials for a demonstration.

Not everything needs to be wrapped in classes - sometimes in an attempt to be "object oriented", we tend to over-use classes in our code and accidentally discard the other types of programming architectures or, like in this case, eliminate important functionality that used to exist before we wrapped the libraries.

SDL_Surface is perfectly good as it is, without being wrapped. wink.png

Not all OOP objects need to be C++-style classes, and not all code needs to be OOP.

If you are trying to code in OOP, I'd recommend not worrying about it, and instead focusing on the RAII, KISS, DRY, and SRP principles.

If you don't know what OOP is, or why I keep on yacking on about it, just focus on those last four links instead and forget I ever mentioned OOP.

I got another question relating to this. How would I make it where I can use my Sprite class and use it in the loops? My loop loops through the different tiles and each of those tiles has a tileID from my bmp file. If the getTileID returns 23, it means it's the 23rd block in my bmp so I have to change my Surface for the new rectangle. I tried doing it but kept on getting the lagging problem because I frequently change the sprite for the different tiles.

What you need to do in your initialisation part of your program is to build a collection of sprites, one per tile of your BMP file (and obviously, the n-th sprite in your collection is the sprite to display if the tileId is n).

Then, in your drawing loop, retrieve the sprite from your collection using the tileId, and draw it.

By the way, this principle is appliable to other game elements as well (game element, animation of these game elements and so on)

Space Zig-Zag, a casual game of skill for Android by Sporniket-Studio.com

This topic is closed to new replies.

Advertisement