Examples of "SDL Game Development" in ANSI C?

Started by
5 comments, last by vinnyvicious 10 years, 2 months ago

I've been reading "SDL Game Development" by Shaun Mitchell and it's an amazing book with lot's of great architecture insights. I've been thinking about implementing most concepts in ANSI C, mostly because i wanted to try pure C for knowledge purposes (C++ has spoiled me), but i have some questions for the gurus:

How would you guys implement a TextureManager and SceneManager in ANSI C? Shaun uses std::map and std::vector a lot, but i'm not really sure if C is able to support such dynamic structures well in ANSI C (while maintaining portability and not using third-party libs).

And what about memory allocation/deallocation? A scene manager is responsible for transitioning between scenes and cleaning stuff up. I imagine the scene class as a struct and many arrays with the objects in the scene. But to clean them up automagically on free(struct)?

Generics! They are all around in Shaun's code. Some abstracted classes can have different types assigned and the API ends up very clean for the user. Is it possible to write something like that in C? A struct with flexible types? Maybe something like this?


typedef struct
{
    int frames;
    int x;
    int y;
    ? *texture;
} Sprite;

void load_sprite()
{
    Sprite sprite;

    sprite.texture = load_sdl_sprite('test.png'); // This will return a SDL_Texture*
    sprite.texture = load_kgl_sprite('test.png'); // This will return a kgl_tex*
    sprite.texture = load_lib_sprite('test.png'); // This will return a sprite_t*
}
Advertisement

Do you have to use three different kinds of textures in one program? If you must, you can use a void pointer + enum flag to indicate which kind of texture you are using.

Don't try to translate c++ idioms to c, it's not always easy to achieve it if you want elegant code.

vectors, maps, and all the std:: stuff is not available in plain C. If you want dynamic lists you have to code yourself for every kind of structure you think at. It's not that difficult, it's only boring.

Generics? void*

C is a beauty language to me, but I quote ultramailman: use it in its original flavor of a procedural language, with elegant modules of functions, rather than push it to an unnatural OOP

Do you have to use three different kinds of textures in one program? If you must, you can use a void pointer + enum flag to indicate which kind of texture you are using.

Don't try to translate c++ idioms to c, it's not always easy to achieve it if you want elegant code.

Void pointers are never a good idea...

Anyway, you could do everything in C that you could in C++. However, AFAIK templates are not supported, just like inheritance and such. This makes object-oriented programming, which is usual for game development harder.

Is there a good reason you want to use C only without libraries except SDL of course?

Everything like vectors and such can be programmed using C, however, this is like arka80 said, a very boring task. The quality of your code may also be / probably is worse than the C++ standard library depending on your experience.

How would you guys implement a TextureManager and SceneManager in ANSI C?


There's nothing really different here. Just do it like you'd do it in C++, only manually performing every operation and hand-coding all the data structures you need. Structurally and algorithmically, it's basically the same. Remember that C++ is not _really_ an OOP language; it's just a bunch of syntactic sugar (mostly) over C, just like C is mostly just a bunch of syntactic sugar over assembly, which is just syntactic sugar over raw machine code. You can almost directly port any code from one "language layer" down to the next without much trouble; you'll just need to write a bunch of extra code for things that the higher layer did automatically (like instantiate template specializations, or automatically invoke destructors). There are some idioms that tend to differ as ultamailman said, but translating from the good practice of one layer to another is still fairly easy if you understand both.

Shaun uses std::map and std::vector a lot, but i'm not really sure if C is able to support such dynamic structures well in ANSI C (while maintaining portability and not using third-party libs).


It doesn't. The best you can do is to make some really gnarly macros. Some folks choose to make "generic" data structures that just hold void pointers to data and add in all the extra necessary casts (and pay the performance cost of the extra indirections and allocations). This is one of the most damning things about C. Expressing data structures in C is very difficult compared to what C++ does easily and generic C data structures usually have measurably worse performance than their C++ equivalents.

This is not too different from the case with generic data structures in old versions of Java or C# before they had generics. A statically-typed language without generics (like C) can be a huge pain in the butt to work with.

And what about memory allocation/deallocation? A scene manager is responsible for transitioning between scenes and cleaning stuff up. I imagine the scene class as a struct and many arrays with the objects in the scene. But to clean them up automagically on free(struct)?


This is all manual in C. You'll need some functions like scene_free(SceneMgr*) or the like that clean up resource trees in systems. Likewise for any shared resources, you need functions like game_object_acquire(GameObject*) and game_object_release(GameObject*) and be darn sure you call them manually everywhere you need to since none of it will ever be done automatically for you.

A struct with flexible types? Maybe something like this?


This could be done with a union, which is roughly what they're for. Just be aware that C/C++ unions are not "tagged" meaning that the language has no idea which element of the union is properly initialized and ready for use, so you usually need to keep some other piece of data along with the union (like an enum) to keep track yourself. If you're just dealing with different kinds of pointers you can also just store a void* and an enum and cast as appropriate whenever you use it.

You should probably just use C++. There's little good reason (in my opinion, at least) to favor pure C over C++. A lot of game developers that claim to prefer C really use a subset of C++ that just eschews all the things they don't like and makes minimal but effective use of the other non-C features. C is a decent choice for small libraries and tools; it's increasingly difficult to justify it in projects of today's games' scale, though.

Sean Middleditch – Game Systems Engineer – Join my team!

For some of your tasks, perhaps something like this could help:


struct Texture
{
  SDL_Surface* surface;
};

struct Sprite
{
  struct Texture texture; // *Not* a pointer to the struct
  int frames;
  int x;
  int y;
};

What is quite cool about this is that a Sprite can now be passed into a Texture function (in C, I don't even think you would need to cast it). i.e


struct Texture* tex = texture_create("someimage.png");
struct Sprite* sprite = sprite_create("someimage.png");
...
texture_get_width(tex);
texture_get_width(sprite);

This technique is used in large C libraries like Gtk+. It also means if you do this form of "poor man's inheritance" on all your structures in the game, you could use a generic type of Object as the array type for example.

When using the popular component entity system (preferring composition over inheritance), I find using C is much more feasible for games development.

http://tinyurl.com/shewonyay - Thanks so much for those who voted on my GF's Competition Cosplay Entry for Cosplayzine. She won! I owe you all beers :)

Mutiny - Open-source C++ Unity re-implementation.
Defile of Eden 2 - FreeBSD and OpenBSD binaries of our latest game.


Void pointers are never a good idea...

Could you elaborate on that?


Is there a good reason you want to use C only without libraries except SDL of course?

Portability. I'm writing ANSI C aimed at multiple platforms. In some, i use SDL. In others, i use a custom implementation. Or something similar to SDL. Each platform, a different taste.

This topic is closed to new replies.

Advertisement