(Discussion) Effective C++ wrapping of SDL

Hello,

While developing my “ZXLIB” library (www.hogweed.org/zxlib) to abstract
SDL using C++, aiming for
ease of use and 2D game specificity, I’ve come across one or two problems
which I have solved in a particular way. However I’m keen to know what
other people think of my way of doing them compared to other alternatives.

The main challenge has been to take advantage of the greater speed of
using SDL_UpdateRects to update all changed rectangles at once, compared
to using SDL_UpdateRect() on each updated rectangle. The former offers an
approximate 120% speed advantage. However, if I want to use a C++ class
for my Sprites this poses a problem; I would have to store the sprites’
rectangles as an array outside the sprite objects to take advantage of
SDL_UpdateRects().

The way I have solved this is rather convoluted internally but clean at
the level of my ZXLIB API. I also have an Arena class which essentially
encapsulates the screen. When I construct a new Sprite I call a method of
Arena which allocates an SDL_Rect within an array inside the Arena class
(but outside the Sprite class) to that Sprite, by giving the Sprite a
numerical ID number which can then be used as a handle to obtain its
corresponding update rectangle from the Arena. (each sprite stores a
pointer to its parent Arena).

The alternative way I can think of, which would be simpler internally,
would be to store an array of Sprites inside the Arena, each containing
its own update SDL_Rect. However, as I said, this would not permit the use
of SDL_UpdateRects().

Does anyone have any comments as to either method or, any possible
alternatives? My aim is to make ZXLIB as user friendly as possible without
incurring a significant speed hit with respect to raw SDL.

Thanks,
NIck

I’ve come across the same problem while writing my own game. I didn’t intend
to write a C++ wrapper, but as I was using C++ anyway I ended up wrapping
groups of related SDL functions under a single class. One of these is what I
call a “Graphics Server”, which initilaizes the screen surface, updates it,
etc. It also has an SDL_Rect queue, preallocated with an expected maximum
size for speed reasons. There’s only one Graphics Server per application, and
each sprite has access to it, so whenever an object needs to draw to screen,
it blits the new pixels and tells the graphics server to append the updated
rect to the queue. When it’s time for a screen update, the graphics server
either uses SDL_UpdateRects() on the queue (which is flushed after that), or
calls SDL_Flip() if the screen surface is double buffered.

Hope this helps,
Mahmoud Al Gammal>Hello,

While developing my “ZXLIB” library (www.hogweed.org/zxlib) to abstract
SDL using C++, aiming for
ease of use and 2D game specificity, I’ve come across one or two problems
which I have solved in a particular way. However I’m keen to know what
other people think of my way of doing them compared to other alternatives.

The main challenge has been to take advantage of the greater speed of
using SDL_UpdateRects to update all changed rectangles at once, compared
to using SDL_UpdateRect() on each updated rectangle. The former offers an
approximate 120% speed advantage. However, if I want to use a C++ class
for my Sprites this poses a problem; I would have to store the sprites’
rectangles as an array outside the sprite objects to take advantage of
SDL_UpdateRects().

The way I have solved this is rather convoluted internally but clean at
the level of my ZXLIB API. I also have an Arena class which essentially
encapsulates the screen. When I construct a new Sprite I call a method of
Arena which allocates an SDL_Rect within an array inside the Arena class
(but outside the Sprite class) to that Sprite, by giving the Sprite a
numerical ID number which can then be used as a handle to obtain its
corresponding update rectangle from the Arena. (each sprite stores a
pointer to its parent Arena).

The alternative way I can think of, which would be simpler internally,
would be to store an array of Sprites inside the Arena, each containing
its own update SDL_Rect. However, as I said, this would not permit the use
of SDL_UpdateRects().

Does anyone have any comments as to either method or, any possible
alternatives? My aim is to make ZXLIB as user friendly as possible without
incurring a significant speed hit with respect to raw SDL.

Thanks,
NIck


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Nick Whitelegg wrote:

The way I have solved this is rather convoluted internally but clean at
the level of my ZXLIB API. I also have an Arena class which essentially

This solution does not seem terribly convoluted to me. You’ve just
added a few layers of indrection, that’s all. You could probably hide
all this behind a function call, perhaps a protected method called
GetRect(), which contains a line like:

pArena->GetRect(hMyRect);

where pArena is a pointer to the arena object and hMyRect is the handle
to this Sprite object’s rectangle. If the array of rectangles never
moves in memory and is also therefore never resized, you could remove
one layer of indirection by having Arena::GetRect() return a pointer to
the SDL_Rect instance within its internal array, which each Sprite could
maintain a pointer to.

The queue idea mentioned by another poster also makes sense. In that
case, Sprite::GetRect() could look like:

pArena->GetARect();

which would return the next free rectangle in the queue. Then you’d
call pArena->UpdateRect(pRect) to mark it as changed, so that it gets
blitted on the next screen update.

The alternative way I can think of, which would be simpler internally,
would be to store an array of Sprites inside the Arena, each containing
its own update SDL_Rect. However, as I said, this would not permit the use
of SDL_UpdateRects().

Not so. It would merely mean that Array would have to traverse the list
of Sprites, find out how many rectangles there are that need updating,
collect them into a single array of SDL_Rects, and send that to
SDL_UpdateRects(). This would be moderately expensive, but it shouldn’t
entirely eat away your 120% speed gain.