Animation Library, Scene Library, and Game Library
Category: SDL Adventure Game
After repeating a lot of code, I began to recognize some emerging patterns.
Animation Library
Previously, an animation was a reference to an SDL_Texture
containing an animation sprite image data and an array of SDL_Rects
to store each frame’s coordinates in the sprite.
I consolidated all the metadata of an animation into a new struct called animation_data
and defined a new type AnimationData
.
I combined all animation rendering functions into a single render_animation
function, which accepts an SDL_Renderer*
, an AnimationData*
, and an SDL_Point
, rendering a single frame of the animation on the screen.
Due to my inexperience with C, I faced an issue with the memory management of new AnimationData
values. When you create a new struct value in a function (on the stack), its memory gets deallocated after the function returns. In my case, I was creating new AnimationData
values in the init
function and encountered errors when trying to reference them in the render_animation
function. The solution was to allocate memory on the heap and return a pointer. I created a make_animation_data
constructor function to encapsulate the logic for creating a new AnimationData
value.
lldb
Commands
I debugged the AnimationData
memory issue a bit and found this list of lldb
commands useful, especially print
: lldb.llvm.org/use/map.html.
struct
and typedef
I’m still unsure why struct animation_data
can’t automatically define a new animation_data
type without also adding typedef struct animation_data AnimationData
. In any case, I decided to use the convention I’ve seen used in SDL, which is prepending typedef
on struct definitions like this:
1
2
3
typedef struct foo {
int bar;
} Foo;
Scene Library (Function Pointers, Basic Interface)
All scenes must implement the same set of functions, so I decided to create a new Scene
struct that models a game scene.
All the fields in the struct are function pointers, so the struct acts as an interface.
Scene headers declare an external scene variable; for instance, intro.h
declares: extern Scene intro_scene;
, then intro.c
initializes the variable with the correct functions.
One issue with this approach is that if I add a new function to the Scene
struct, the compiler doesn’t throw an error if the scene instances don’t initialize it.
Game Library
I extracted some logic from main.c
into a new game.c
/game.h
library.
For now, I just rearranged the code, so the actual utility of this refactoring is limited.
game.h
defines most of the functions of a Scene
. I think the game library could implement the Scene
interface, but then Scene
would become the wrong kind of abstraction.
I defined set_active_scene
, a function to transition from the current scene to a new scene. An on_scene_inactive
callback is executed on the current scene to perform some cleanup (stop music, etc.). An on_scene_active
callback is executed on the new scene to perform some initialization (start music, etc.).
Checkpoint
At this stage, I had the two initial scenes (intro and playground entrance) with placeholder images: