SDL "Sprite" handling

Hi,

I’m looking to add some sprite handling to my little project - ie. a small
bitmap image that I can move over (on top of) the screen according to
program control.

I just want to make sure I’m not being too naive and not missing something
obvious!

Looking at this:

http://gamedevgeek.com/tutorials/moving-sprites-with-sdl/

it seems straightforward, however that program re-draws the entire screen
every frame. I want my sprites to “float” on-top of any background without
having to re-draw the background, so … For each sprite, If I

blit the screen rectangle (same x,y,size as sprite) into a temp. buffer,
blit the sprite to the screen,
update/flip,
blit the screen temp. buffer back to the screen

lather rise, repeat with new sprite position and so on. Each sprite
needing a Surface to hold the sprite and another the same size to hold the
copy of the background.

I’m fairly sure that will work, but it will be doing a lot of memory moves
(even if rather small, say 20x20 pixels) and as long as I draw then /erase
them in the same order (or erase in reverse order) then the background
ought to stay untouched and sprites can happily move on-top of each other.
Although its will be doing a lot less memory moves than the example in
that website above!

I have seen SDL-Layer, but in its absence is the above OK, or am I
missing a trick?

Cheers,

Gordon

[…]

http://gamedevgeek.com/tutorials/moving-sprites-with-sdl/

it seems straightforward, however that program re-draws the entire screen
every frame.

The reason for doing it that way is that it’s simple, handles all sorts of
situations, including full-screen scrolling, and tends to run fast enough on
most platforms (that is, those with hardware acceleration) without relying on
or suffering from API, driver or hardware quirks.

[…]

blit the screen rectangle (same x,y,size as sprite) into a temp. buffer,
blit the sprite to the screen,
update/flip,
blit the screen temp. buffer back to the screen

This is indeed how many games did “software sprites” on 8 and 16 bit systems;
IIRC STOS did something very much like this on the Atari ST, although I think
it used a third full-screen buffer for the sprite “backsave.”

The problem with this approach these days is that basically any modern
graphics system makes it EXTREMELY expensive to read from the frame buffer.
(Sometimes slower than reading from the hard disk. Not kidding!) Modern PCs
(and most other devices) just aren’t designed for software rendering, and
reads from VRAM are particularly problematic. Also, hardware accelerated
rendering adds the need for synchronization, making this even slower.

The proper way is to always render in the “forward” direction. What you can do
in a case like this is to remove the sprites by restoring the affected parts
of the background directly from the source; ie tiled map, background image or
whatever you’re using.

If rendering the background is too complex and/or expensive to do like that,
render the full background into an off-screen surface first, and keep that
surface around for sprite removal.

Of course, you should SDL_DisplayFormat() the source graphics for maximum
speed - but actually, I think even SDL converting pixels on the fly (say, if
you have custom software rendering code that supports only 32 bit RGBA) is
going to be a lot faster than anything involving reading from the frame
buffer.

Oh, BTW, I once wrote an example, Fixed Rate Pig (playable minigame), that
demonstrates this, among other things. Apart from only updating the areas
around the sprites, it also has a simple “smart refresh” engine that avoids
restoring the same area over and over if multiple sprites hang around in the
same general area.

IIRC, it keeps track of doublebuffering as well (one set of "dirty rectangles"
for each buffer), so it should work on an actual double buffered display as
well.

http://olofson.net/mixed.htmlOn Wednesday 18 April 2012, at 16.18.33, Gordon Henderson  <gordon+sdl at drogon.net> wrote:


//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://consulting.olofson.net http://olofsonarcade.com |
’---------------------------------------------------------------------’

There are only 2 ways to handle blits in software with SDL.
The first is the easiest which is bliting each image on top of each other to
the framebuffer for every frame. This of course is wasteful if areas of the
screen are not changing.

The second is to only copy/update the areas of the frame buffer which are
changing. For instance you draw your background in full one time. You then draw
your sprite, entire framebuffer is flipped. On the second frame you move the
sprite to the right. You only then need to redraw the part of the background
where the sprite was and draw the sprite where it is now. This method is tedious
but saves on the memory copies, if your background is not moving.

So you would use SDL_Blitsurface with a defined srect to only draw the part of
the background you need to update. Then you would use SDL_Blitsurface again to
blit the entire sprite.
http://www.libsdl.org/cgi/docwiki.cgi/SDL_BlitSurface
Then you would keep rects of the areas you need to update and pass those to
SDL_UpdateRect or SDL_UpdateRects.
http://www.libsdl.org/cgi/docwiki.cgi/SDL_UpdateRects

Another option is to use OpenGL to do the rendering.________________________________
From: gordon+sdl@drogon.net (Gordon Henderson)
To: sdl at lists.libsdl.org
Sent: Wed, April 18, 2012 10:18:42 AM
Subject: [SDL] SDL “Sprite” handling…

Hi,

I’m looking to add some sprite handling to my little project - ie. a small
bitmap image that I can move over (on top of) the screen according to program
control.

I just want to make sure I’m not being too naive and not missing something
obvious!

Looking at this:

http://gamedevgeek.com/tutorials/moving-sprites-with-sdl/

it seems straightforward, however that program re-draws the entire screen every
frame. I want my sprites to “float” on-top of any background without having to
re-draw the background, so … For each sprite, If I

blit the screen rectangle (same x,y,size as sprite) into a temp. buffer,
blit the sprite to the screen,
update/flip,
blit the screen temp. buffer back to the screen

lather rise, repeat with new sprite position and so on. Each sprite needing a
Surface to hold the sprite and another the same size to hold the copy of the
background.

I’m fairly sure that will work, but it will be doing a lot of memory moves (even
if rather small, say 20x20 pixels) and as long as I draw then /erase them in the
same order (or erase in reverse order) then the background ought to stay
untouched and sprites can happily move on-top of each other. Although its will
be doing a lot less memory moves than the example in that website above!

I have seen SDL-Layer, but in its absence is the above OK, or am I missing a
trick?

Cheers,

Gordon


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

[…]

http://gamedevgeek.com/tutorials/moving-sprites-with-sdl/

it seems straightforward, however that program re-draws the entire screen
every frame.

The reason for doing it that way is that it’s simple, handles all sorts of
situations, including full-screen scrolling, and tends to run fast enough on
most platforms (that is, those with hardware acceleration) without relying on
or suffering from API, driver or hardware quirks.

[…]

blit the screen rectangle (same x,y,size as sprite) into a temp. buffer,
blit the sprite to the screen,
update/flip,
blit the screen temp. buffer back to the screen

This is indeed how many games did “software sprites” on 8 and 16 bit systems;
IIRC STOS did something very much like this on the Atari ST, although I think
it used a third full-screen buffer for the sprite “backsave.”

The problem with this approach these days is that basically any modern
graphics system makes it EXTREMELY expensive to read from the frame buffer.
(Sometimes slower than reading from the hard disk. Not kidding!) Modern PCs
(and most other devices) just aren’t designed for software rendering, and
reads from VRAM are particularly problematic. Also, hardware accelerated
rendering adds the need for synchronization, making this even slower.

The proper way is to always render in the “forward” direction. What you can do
in a case like this is to remove the sprites by restoring the affected parts
of the background directly from the source; ie tiled map, background image or
whatever you’re using.

If rendering the background is too complex and/or expensive to do like that,
render the full background into an off-screen surface first, and keep that
surface around for sprite removal.

OK - The issue I have is that I have no control over the background -
because it’s generated by another program that my program is interpreting.
ie. this is my BASIC interpreter, so the user could have written a program
to display some nice pictures, then wants to move a sprite over it…

I think I am keeping everything in the forward direction though - at least
that’s what I’m assuming - I create my screen with:

myScreen = SDL_SetVideoMode (screenWidth, screenHeight, 32, SDL_SWSURFACE) ;

Then poke pixels into it along the lines of:

*((uint32_t *)myScreen->pixels + y * hgWidth + x) = plotColour ;

then call

 SDL_UpdateRect (myScreen, 0,0,0,0) ;

to make it visible… So I’m assuming that myScreen is actually a software
copy of the real screen, so pulling stuff out of it might not be that high
an overhead.

But I think I need to run some tests just to make sure!

Of course, you should SDL_DisplayFormat() the source graphics for maximum
speed - but actually, I think even SDL converting pixels on the fly (say, if
you have custom software rendering code that supports only 32 bit RGBA) is
going to be a lot faster than anything involving reading from the frame
buffer.

Oh, BTW, I once wrote an example, Fixed Rate Pig (playable minigame), that
demonstrates this, among other things. Apart from only updating the areas
around the sprites, it also has a simple “smart refresh” engine that avoids
restoring the same area over and over if multiple sprites hang around in the
same general area.

IIRC, it keeps track of doublebuffering as well (one set of "dirty rectangles"
for each buffer), so it should work on an actual double buffered display as
well.

http://olofson.net/mixed.html

I’ll have a look at that, thanks!

GordonOn Wed, 18 Apr 2012, David Olofson wrote:

On Wednesday 18 April 2012, at 16.18.33, Gordon Henderson <gordon+sdl at drogon.net> wrote:

[…]

I think I am keeping everything in the forward direction though - at least
that’s what I’m assuming - I create my screen with:

myScreen = SDL_SetVideoMode (screenWidth, screenHeight, 32,
SDL_SWSURFACE) ;

Then poke pixels into it along the lines of:

*((uint32_t *)myScreen->pixels + y * hgWidth + x) = plotColour ;

then call

 SDL_UpdateRect (myScreen, 0,0,0,0) ;

to make it visible… So I’m assuming that myScreen is actually a software
copy of the real screen, so pulling stuff out of it might not be that high
an overhead.

Ah! Yes, that should be a software surface (which is what you want for this
type of work) - and it also has the bonus of blitting from the "display"
surface actually being all software work in system memory, so no VRAM read
issue there.

BTW, SDL_UpdateRect() is potentially quite expensive. (Not like reading VRAM,
but still.) If you can somehow extract information about areas touched by the
interpreter without too much overhead, and use SDL_UpdateRects() instead, that
might improve performance a great deal. That said, there can be a fair bit of
per-rectangle overhead as well, so one should keep the “smartness” on a
reasonable level.On Wednesday 18 April 2012, at 18.15.37, Gordon Henderson <gordon+sdl at drogon.net> wrote:


//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://consulting.olofson.net http://olofsonarcade.com |
’---------------------------------------------------------------------’

[…]

I think I am keeping everything in the forward direction though - at least
that’s what I’m assuming - I create my screen with:

myScreen = SDL_SetVideoMode (screenWidth, screenHeight, 32,
SDL_SWSURFACE) ;

Then poke pixels into it along the lines of:

*((uint32_t *)myScreen->pixels + y * hgWidth + x) = plotColour ;

then call

 SDL_UpdateRect (myScreen, 0,0,0,0) ;

to make it visible… So I’m assuming that myScreen is actually a software
copy of the real screen, so pulling stuff out of it might not be that high
an overhead.

Ah! Yes, that should be a software surface (which is what you want for this
type of work) - and it also has the bonus of blitting from the "display"
surface actually being all software work in system memory, so no VRAM read
issue there.

OK, thanks. That keeps things somewhat simple then.

BTW, SDL_UpdateRect() is potentially quite expensive. (Not like reading VRAM,
but still.) If you can somehow extract information about areas touched by the
interpreter without too much overhead, and use SDL_UpdateRects() instead, that
might improve performance a great deal. That said, there can be a fair bit of
per-rectangle overhead as well, so one should keep the “smartness” on a
reasonable level.

I did think about that - ie. trying to keep track of what the BASIC
program draws - and then quietly forgot about it :wink: Mostly because it’s
fast enough. So-far.

Still impressed with SDL - I’m doing things in BASIC now that I never
dreamt of 30 years ago - e.g. drawing a spiral using turtle graphics, then
(in basic!) sitting in a loop, draw in black, change start angle, draw in
green, update to get the while thing rotating - and I’m seeing 200
frames/sec on utterly trivial stuff - it does slow down a bit, but even on
my crappy old laptop I was seeing 30 fps. My old turtle interpreter on the
Apple II would take 5 minutes to draw a single frame of the same thing.

Now to write the sprite editor (in basic :wink:

Cheers,

GordonOn Wed, 18 Apr 2012, David Olofson wrote:

On Wednesday 18 April 2012, at 18.15.37, Gordon Henderson <gordon+sdl at drogon.net> wrote: