Should I use tiles or a single large image for my games background

Started by
4 comments, last by Alberth 6 years, 9 months ago

I'm working on a 2D top down game in Python with Pygame. I was wondering if it is better to use one large image for a background or individual images? My problem with individual images is when I want to update a portion of the display without updating the entire display. How can I get a subsurface of multiple tiles if the location I need to update is between two tiles? Do I use layered surfaces?

Advertisement

Just update both tiles completely, or more general, expand area to update to tile boundaries, then update all tiles in the area.

The amount of work that you have to do for a full tile versus a partial tile is the same, except for some clipping perhaps, but that's hardly worth the effort on modern hardware.

However, Pygame uses ancient technology so re-rendering the whole screen each time is sometimes not ideal.

I would advise moving to Pyglet which uses more OpenGL for rendering, which means that redrawing the whole screen each frame is simple and efficient - which makes this question redundant.

On 7/4/2017 at 9:16 AM, Alberth said:

Just update both tiles completely, or more general, expand area to update to tile boundaries, then update all tiles in the area.

The amount of work that you have to do for a full tile versus a partial tile is the same, except for some clipping perhaps, but that's hardly worth the effort on modern hardware.

Is there a way to combine all tiles into one so I can do something like self.displaysurf.blit(self.background.subsurface(gameobject), gameobject_location). How do I subsurface multiple tiles? Right now I just get a subsurface of my background image at the gameobjects locations and of the gameobjects size.

 

On 7/4/2017 at 9:25 AM, Kylotan said:

However, Pygame uses ancient technology so re-rendering the whole screen each time is sometimes not ideal.

I would advise moving to Pyglet which uses more OpenGL for rendering, which means that redrawing the whole screen each frame is simple and efficient - which makes this question redundant.

I've heard of it and will definitely check it out in the future. Is Pyglet more difficult than Pygame? Is it just for graphics?

2 hours ago, mrpeed said:

Is there a way to combine all tiles into one so I can do something like self.displaysurf.blit(self.background.subsurface(gameobject), gameobject_location).

In the simplest case, you have a surface for each type of tile, and one for each kind of game object.

Updating the screen is then first drawing all tiles that need to be updated, and then drawing the game object over them at the right position. That is, you always draw everything, even though the tiles never move. The reason is that if the game object moves, the old position needs to display a tile-part. At the new position, you need to show a game object where there was a tile before.

If you want to combine drawing the tile background and the game object by using a single "draw" call, you need a surface that contains both items, with the game object at exactly the right position. Let's assume a game object is always at the center of a tile. Event in that case, this is feasible only if you have a very limited number of background tiles, or you have a very limited number of game object graphics. You make new graphics, one for each combination of background tile and game object (and one for each background tile without a game object). At runtime you decide which combination applies for each tile, and then draw the correct combination. To give you an idea how fast this explodes, if you have 8 game objects, and 4 tile backgrounds, you need 8*4 + 4 = 36 different images, a whole lot more than 8 + 4 = 12 if you draw background tiles and game objects independently.

When the game object is not always at the center of the tile, but something more to the left and sometimes more to the right, or it has different images (eg one for holding a sword and one for holding a spear), or you can have several game objects at the same tiile (or partly on the tile), Each combination here counts as "new game object" in counting the number of needed images.

As you can see, trying to draw the tile and the game object together in one draw call can make life very complicated.

 

3 hours ago, mrpeed said:

How do I subsurface multiple tiles?

In the simplest case, you don't. Each surface contains a single background tile, and you make a separate draw call for each tile. If your tile background doesn't change, you can consider making one very large background image (composed of some or all tiles), and use that to draw the tile background. (Sort of making a picture containing (part-of or) the entire level in tile backgrounds.) While it's possible (afaik you can create a new surface, and copy existing surfaces into it), I have doubts whether it is useful. You do get fewer draw calls, so it should be faster. On the other hand, you typically only want to draw a small part of the display, and clipping is usually done in rectangles. So if your update does not have a rectangular shape, you either have to split the update (meaning more draw calls), or you update more than you have to.

 

3 hours ago, mrpeed said:

Is Pyglet more difficult than Pygame? Is it just for graphics?

It does seem to do more: https://pyglet.readthedocs.io/en/pyglet-1.2-maintenance/

The big change of course is using OpenGL directly, instead of indirectly. (I don't know what pygame version you use. The 'old' pygame uses SDL, which was created before GPUs were common, so it has no GPU support whatsoever. There are newer pygame versions that use SDL2 (which does know about GPUs, although I don't understand how good the support is). PyGlet (and a few others) don't try to be pygame compatible at all, and just do everything with GPUs (I think). The latter is what pretty much every game does nowadays. Even drawing the entire screen every frame is not a problem there.

This topic is closed to new replies.

Advertisement