Naive C Code Generation

Tags

,

About half an hour ago I had this idea that I could write a pretty simple C code generator given two files: a quasi-C source code file, an input file guiding the generator on processing the quasi-C source file.

The guiding input is a key=value per line kind of file. For example: http://pastie.org/pastes/10259660/text?key=spolb8zdffeuwyypmapng

The quasi-C source code file is pretty much a C source file with some @{…} placeholders which will be replaced by some value according to the guiding input file. For example: http://pastie.org/pastes/10259662/text?key=esfdye9mxip2mhcbptuvug

After the processing, the result is: http://pastie.org/pastes/10259661/text?key=rctyfb2y6cufoehvspjpq

It’s no surprise this is a small python script: http://pastie.org/pastes/10259663/text?key=yawd6vshlqlxz6hywz5blg. And it’s executed as `python cdgen.py vec.cds < in.cdi > FloatArray.c` where cds is supposed to mean “C description source” (i.e. the quasi-C file) and cdi “C description input” (i.e. the guiding input file).

The whole thing was so simple that it took I think less than 30 min to have the idea and get to the point I was writing this blog post (having already had experimented a bit with it playing with those files).

This is a simpler (i.e. less features) version of the preprocessor, however possibly a bit better in some aspects (e.g. no concatenation operator mess).

Note: Please don’t mind the code in the example. It’s just to experiment with the generator.

imgsplit

Tags

,

I’ve written this small command line utility called imgsplit. It’s capable of splitting images into smaller rectangular regions following a particular grid pattern.

It’s written in C (C99) using the SDL2 and SDL2_image libraries. You can find more about it on github: https://github.com/phao/imgsplit

There is a C API as well, but it’s so small and simple that it’s almost pointless. It’s there anyway though.

On Its Programming

First of all, it was a small project. The line count was small (498 lines of C total), and the difficulty was also small.

It took me two programming sessions to do it, each containing from 1 to 1.5 hours. An extra session was needed for me to document what it did (check the README and C_API files on the github repository).

Explosions-ish Particles Systems

Tags

, , ,

I was exploring with SDL2 and C programming. And this time I decided to try another idea for a simple particles system. The goal was to simulate things like impact explosions (e.g. a rocket hits a target, or a laser shot hits a target), or just plain common explosions.

In the end, I found out that it could be used for much more interesting things. Here follows some examples.

This one is a bunch of colorful simple explosions. You can imagine laser shots impacting, poison arrows effects, and so on.

Then I decided to put a bunch of those in the same place “continuously”, with a slight larger velocity focused on a small direction range:

The idea was to get something that looked like a fire-ish thing. Then, I realized that if I used something better as the underlying image for the particles system, I could get much more interesting results. As of now, all that had a “radial-gradient-white-transparent-circle” as the underlying particle. What I did then is to make something a bit more elaborate on gimp using its built-in brushes. The effect really amazed me!

It seemed like the inferno spell of Diablo 2! I’m really glad with the results. I’m really looking forward to working with much more interesting particle systems ideas in the future.

The source code is available. It’s on github. Check the sparts003 folder in my topshooter_xp repo.

Game Art by Tatermand

Tags

,

There is a OpenGameArt user called tatermand.

He has published some extremely interesting shooter 2D game art in his profile page at OpenGameArt.

Check out his posts. He has published extremely interesting art pieces for a space shooter game, and also for a top down soldiers shooter game. It’s extremely well done and all under the creative commons license.

I’ve started looking into his art pieces and playing with them. I did this simple animation in less than an hour of C+SDL2 coding. The video quality isn’t very good, and I really only use 1 of his images, but I liked the starting point.

Another experiment I did with Tatermand’s art is using the plasma shot graphics. This one didn’t end up being so great though.

Improvements on imgpacker

Tags

, , ,

Not long ago, I’ve written imgpacker. It’s a program which packs images from various files into a single output PNG image. The idea is to use it to build stuff like tile sets and sprite sheets.

In my previous post on imgpacker, I mentioned there were 3 future plans:

  1. A -f option, which would let me specify input images from a text file containing one path per line.
  2. The guarantee to have the regions output list regions in the same order as the input images came in. So the region matching the N-th input image will be the N-th region output line in the CSV file.
  3. More tests.

Well, item 3 wasn’t achieve, but I’ve just finished items 1 and 2. The code is on github.

Implementation – The Command Line -f Option

To implement this option, I had to modify the struct which held configuration values based on which the program runs. It included a new field: a const char* to hold the command line parameter for the -f option.

After going through all the command line options in the build_cfg function inside Main.c, it’s verified if a input file was specified for the images file list. If yes, then the files list is read off it, but if it’s not, then the file list merely refers to somewhere in the arguments list (i.e. argv) where the image files begin to be listed.

Using my small AllocUtil library, implementing a file reading procedure wasn’t much work because the allocation/reallocation work was done by the library.

Implementation – Matching Input/Output Order

It involved adding a new field in the struct for the image to keep “the image index”, which is its position in the image input list. Before printing the CSV output, I sort the data based on the image index.

Overall

The major complication (if you can call it that way) in this whole process of adding these two features was dealing with the fact that I didn’t know how many lines the file (for the -f option) had and how long each line was prior to reading them. The allocation/reallocation done by the AllocUtil library took care of all that though.

AllocUtil – Allocation utilities for C programming

Tags

, ,

Throughout my C programming time, I’ve written small allocation utilities sort of “here and there”. Recently though, I’ve decided to put some of them inside a library and see where that leads. I’ve also decided to learn some few new ones along the way.

The library, as it currently stands isn’t complete. It has only three types (byte builder, fixed size builder, variable size builder) so far. More types are being added these days.

An explanation of what can be expected of the library is in the README file. All the documentation that exists as of now is in that README file and in the main header file for the library: AU.h.

The code is on github. Development just got started. I haven’t dedicated much more than 5-10 hours to it total. A lot of things are yet to be decided, and so on and so forth. There is actually a lot of things that are inconsistent, and sometimes just plain wrong in there. As times go and I develop more of it, these things will be dealt with.

I’ll start using it in my own projects (imgpacker, for example, seems like an interesting candidate), and let usage guide the evolution of the library.

imgpacker

Tags

, , ,

Recently I’ve written a tool to pack images together into a single output image file. This can be used to generate tile sets or sprite sheets for example. It’s called imgpacker and it’s on github.

Check also this other post on imgpacker. It’s an update on this one.

Algorithm

It tries to solve the 2D bin pack problem (i.e. on how to arrange 2D shapes so that they occupy the smallest area) given some constraints. In the case of imgpacker, all shapes are rectangles. For all I understand, the 2D bin pack problem is hard computational problem. This means that in practice, we try to approximate a solution instead of solving the exact problem (i.e. maybe it won’t give you the optimal area usage, but it’ll be good enough). Fortunately, I was able to find an algorithm which seems to approximate a solution extremely well:

The algorithm is also simple. The author of that blog post explained it well and shortly, even presenting code in javascript.

Output

In the end, the program produces 2 outputs:

  • A PNG containing all input images as subregions of it.
  • A CSV file containing regions descriptions telling where each input image is in the output image.

Implementation

The program is in C, and it uses LibPNG, SDL2 and SDL2_image for dealing with images. The code isn’t at its best. It works, but it could use some refactoring.

There are basically three units: Main, xPNG and BinPack2D.

  • Main does the input reading, command line options processing, control the usage of the other units and so forth. That is, it puts things together. CSV output is also simple enough that it’s part of Main instead of being on its own unit.
  • xPNG is concerned with taking a SDL_Surface* and output it into a png file.
  • BinPack2D is responsible for implementing the bin pack 2D algorithm. It’s lets you pass in a sequence of images, and it’ll pack them for you. As a result, it’ll give you the SDL_Surface* with the output image (that you can then pass on to the xPNG unit) and also region information about the sub images inside the whole output image (this is what is used to generate the CSV output in Main).

Program Performance

The code right now is very simple-minded and it doesn’t specially care about CPU or primary memory performance. Most of the time is spent on image I/O. This shouldn’t come as a surprise when the program has to load something like hundreds of images before running the algorithm. And after it has to output a large png image from a SDL_Surface*.

These are the potentially time-consuming parts of the program I identified:

  1. There is a load step to fetch input images into main memory.
  2. A worst case quadratic time (on the number of input images) algorithm (i.e. the packing algorithm) which works on the dimensions of the images (i.e. the packing algorithm doesn’t deal with the contents of images, it only looks at their dimensions).
  3. A sequence of copy operations (from input images to regions in the output image) which look at the arrangement of images produced by the packing algorithm and produce the output image.
  4. The production of a PNG file out of the SDL_Surface* output image.
  5. The production of a CSV file out of the images arrangement regions information.

For all I can tell from timing the execution of the program step 1 and 4 are the most time-consuming, specially 4.

LibPNG

I don’t know how to use LibPNG, but the program needs to generate an output image in the png format. The reason for this is to allow for packed images which contain transparency. I basically got a code from the web which knows how to take an SDL_Surface* and output a png file from it.

It sort of stinks taking code like that, but I didn’t want to wait until I learned how to use LibPNG so I could write it on my own.

Extras

If you check the source code, you’ll find some code which is extra to the C implementation of the program. As of now, they are: toC_impl, toC_inter, csv_rem_prefix, and some text files.

These text files describe some of what I intended for the program to be before starting it out (pre_analysis.txt and pre_impl_design.txt), but also some retrospective thoughts after getting it done (post_analysis.0.txt). These documents are interesting because they’re the best thing to a specification the software has (besides what you can find by looking at the source code).

The pre_analysis.txt file tells you, for example, that the CSV file output has the following format: name,x,y,w,h. The purpose of the CSV file is to describe how each input image fits in the single output image the program generates. The describing is done by listing each image and its coordinates/dimensions inside the output image.

Still in the same document, it describes how the name for each image is generated. It’s from the image file name. The idea is to try to generate a C identifier from a file path. This is done by transforming anything which isn’t a valid C identifier character into an underscore character. This leads to CSV files which have all lines with repeating prefixes like this:

The script csv_rem_prefix is meant to remove this common prefix that all lines have. For example, applying it on the this pasted CSV file results in this:

Having the prefix removed, the CSV content is better suited for use with the two other scripts: toC_impl and toC_inter.

Those two scripts are still incomplete and need to be thought out (they weren’t yet). The idea is that you can use them to generate some C source code which can work specifically with the output PNG images. The C code is generated from the CSV output. Here is an example of toC_inter and toC_impl in action:

Again, it’s still incomplete. About the intended final version:

  • It’s supposed to have code for load, cleanup and fetches for names (const char*) and bounding rectangles (SDL_Rect).
  • It’ll use SDL_Rect instead of having its own x,y,w,h fields.
  • It’ll stop calling the struct SpriteSheetPiece and will use something else, like ImagePiece or SurfaceRegion.
  • It should also let you get at the loaded SDL_Surface* so you can do your own manipulations (of course this opens up the possibility for dangerous programming, but I’m not about to encapsulate every possible sdl call just to prevent you from doing something stupid [hint: don’t do it]).

Future Plans

The program is highly incomplete. It doesn’t work the way I’d like it to work. The algorithm is in place, and it’s producing a good enough output, but there is more I’d like:

  • Making sure that the order of input files is kept in the CSV output (currently, it isn’t). This is important so that I can make without any major effort toC_impl and toC_inter generate code in which the enum values for the different images satisfy a particular order (imposed by the order of input images). For example, maybe you have images for digits (0..9), and you’d like your enum code identifying number 0 to be 1 less than the enum code identifying number 1, and so forth. To do that, all you’d need (given this feature was in place) is to have your input images (for those digits) sequentially ordered from digit 0 to 9.
  • Specifying input images as a file containing one image path per line. That way, I could invoke the program as imgpacker -f imgslist.txt instead of trying to place it all (the paths of all input images) in the command line parameters list. This also plays well with the point above.
  • Tests. Currently, there is a couple of assertions in the code. That’s the extent to what tests are done. I’d like to add more tests (automated) to the program.

Examples

By default, imgpacker will try to generate a square-ish image (as suggested in the algorithm explanation page), but you can ask it to be limited by a certain width and/or height.

Here is an output (from the same input), but for width limited to 500 pixels.

Curiosity

While writing this article, I found a bug in the program (it’s already fixed).

Input Images

If you liked the images above, check out more from the author, Kenney, in his opengameart.org page. The ones I used come from his Space Shooter Redux package.

XError – Error Reporting Handling in C

While creating a tetris clone in C, I came up with an error reporting handling utility that I thought was quite interesting. Recently, I’ve decided to turn it into a library of its own.

I’ve already written a bit about (it’s in the README file of the github repository). In my last post about my tetris clone, I talk about this error reporting system quite a lot. Check it out if you’re interested:

I’m in the process of writing modifying XError and making it more fit as a standalone library. I’ll probably be writing more about it.

Tetris Clone in C and SDL2 – Post C++ Rewrite C Refactoring

This is the third retrospective document about this project. The first one was about my actual specs for the program. The second was a post analysis of the project’s implementation. This one is the result of a refactor due to a code review I had to do while doing the C++ re-write of this project, which actually also yield a document as well.

It all started with a tetris clone I wrote in C and SDL2.

Notice that unless said differently, “object” has its C meaning, which is pretty much a memory region.

The Major Change – Error Handling

As was mentioned several times when an error happens, the program quits with an
error message.

One of the things I’ve noticed in my code review is that the error handling
mechanism had a too much complicated clean up scheme. It depended on series of
labels whose cascading would lead to the right clean up. This scheme had an
advantage. It was local. It also required a lot of those clean up code
everywhere, and sometimes even duplication of clean up code (one under the
error related labels, and another in a destroy function). For example, while
loading a screen, if it fails, init must clean up, but the screen abstract
object must also contain a destroy function will cleans up the screen.

So the first change in error handling is that although local clean up is still
allowed (and done in some places), it’s no longer necessary. All modules will
have their destroy functions called at the end, and they should be able to
do something reasonable even if the module hasn’t been initialized yet.

For example, if initializing the assets module fails, the program shuts down by
calling all the clean up procedures available (more on this later), reporting
the error, and exiting. One of the available modules is the music module. The
music module is only initialized after the assets module as it happens to be
right now (that is not to be relied upon, but it is how it is). So its destroy
procedure gets called even though it wasn’t initialized. It should be, and is,
able to deal with such cases.

In general, what this first change means is that if a clean up function gets called, it should be able to deal with an “uninitialized situation” in the case of a module. This last point should be clear: “in the case of a module”. Although there is a module implementing the data type TextImage, an instance of TextImage itself isn’t a module. This first change isn’t saying that destroy_text_image has to work on an uninitialized TextImage object.

The way modules can deal with this first change is by using module local variables. It’s no big deal, but it makes cleanup much easier.

The second change has to do with reporting the error. Back then, when an error happened, what one would see is the error message from a direct call to one of (SDL|IMG|TTF|Mix)_GetError. There were problems with this approach. I never faced those problems, but I thought it’d be interesting to fix them anyway.

For example, once an error is identified, errorFn, which doesn’t exist anymore, was set to the appropriated function pointer ((SDL|IMG|TTF|Mix)_GetError for example) and a goto statement to the appropriated clean up label was executed. During the clean up SDL functions would be called to clean up previously set up state. The issue is that some SDL functions set the error message even though they don’t fail. So after the clean up, the error message set internally in the SDL and helper libraries could be completely different from what it was when the error happened.

This means that I should be saving the contents of the message at the point of failure instead of saving the function pointer.

Another issue with error handling was that there was no trace. I don’t mean a full stack trace, but there is a sequence of calls which lead to failure, and I’d like to know what is that sequence. My attempt to do that led me to complete a simple, but pretty useful as it seems, error reporting system. Here is an example:

[tetris] (master)$ ./main
Error! Aborting program.
Bread Crumbs:
=============
text_image.c: init_text_image: L30: (missing message)
FAILED CHECK: !stext
menu.c: init_menu: L71: (missing message)
FAILED CHECK: init_text_image(&title, title_font, "Tetris", g_rend, &DEFAULT_FG_COLOR)
main.c: init_screens: L51: (missing message)
FAILED CHECK: init_menu(rend, &screen_size)
main.c: init: L67: (missing message)
FAILED CHECK: init_screens()
main.c: main: L182: (missing message)
FAILED CHECK: init()

SDL_GetError() => (empty)
IMG_GetError() => (empty)
TTF_GetError() => (empty)
Mix_GetError() => (empty)

This is a report of what gets collected when an error happens. It points that there was a sequence of calls: main -> init -> init_screens -> init_menu -> init_text_image. It points out which checks failed, the line of code in which the check was being performed, and also the file name. The message, which is missing in all of the entries is something custom (at error checking point, it has to be provided, or it’ll be missing). The error message is used only for the case in which I want to copy the error message contents from (SDL|IMG|TTF|Mix)_GetError. The 4 last lines tell the current messages reported by the (SDL|IMG|TTF|Mix)_GetError functions at error reporting time. This could be useful, but I’m not so sure.

Here is an example of when there is an error message to set:

[tetris] (master)$ ./main
Error! Aborting program.
Bread Crumbs:
=============
assets.c: init_assets: L44: Couldn't open arcade.sttf
FAILED CODE: large_font
main.c: init: L65: (missing message)
FAILED CODE: init_assets(rend)
main.c: main: L173: (missing message)
FAILED CODE: init()

SDL_GetError() => Couldn't open arcade.sttf
IMG_GetError() => Couldn't open arcade.sttf
TTF_GetError() => Couldn't open arcade.sttf
Mix_GetError() => Couldn't open arcade.sttf

This is all using standard C. I imagine that going OS specific, something better can be done.

The way this is done is by changing how to error macros work. Doing something like

COND_ERROR_SET(error_check, label, function_pointer);

would expand to pretty much into

do {
  if (!error_check) {
    errorFn = function_pointer;
    goto label;
  }
} while (0)

Now what happens is that there are other macros. This one (COND_ERROR_SET) and its friend (COND_ERROR) are gone. What exists now is for example, COND_ERET_LT0. Here is how you’d use it:

COND_ERET_LT0(SDL_Init(SDL_INIT_VIDEO), SDL_GetMessage());

It’s defined as follows:

#define COND_ERET_LT0(EXPR, MSG) do { \
    int ERROR_H__err = (EXPR); \
    if (ERROR_H__err < 0) { \
      link_error((MSG), __LINE__, __FILE__, __func__, # EXPR); \
      return ERROR_H__err; \
    } \
  } while (0)

The call to link_error adds an entry to the error module, which maintains an internal structure of error entries. Each entry you add is chained together with the existing ones. At any point you can ask for a copy of the error chain (which you’d have to free yourself later on through a call to free_error).

There are macros for:

  • return and gotos (RET, GOTO);
  • true conditionals, false conditionals and less than 0 results (no suffix, IF0, LT0);
  • when there is a message, and when there isn’t (E, P).

So for example, COND_PGOTO_LT0 will goto the given label if the given expression is less than 0, and also it’ll provide no error message.

Error messages are always the last parameter to the macro application, and the error check always the first. Some times, three parameters are needed, and the one in the middle has custom semantics. For example, COND_ERET_LT0 will return whatever the failing expression will return in the case of an error, but COND_ERET_IF0 needs a parameter which indicates which is the return value:

COND_ERET_IF0(sdl_renderer, -1, SDL_GetError());

Will return -1 if sdl_renderer is false-ish. It’ll also add the error message returned by SDL_GetError in the case of an error.  The downside of this approach is that it fills the code with macro applications, which were already in for the old error handling approach (they were just different macros), so that didn’t make the code any worse. Another downside is the use of that ERROR_H__err variable inside a do..while block. I don’t think that’s going to be an issue. The error module relies on the ability to declare variables whose identifiers are prefixed with ERROR_H inside those do..while blocks.

As a final, and less important downside, the error module relies heavily on dynamic allocation, which I was hoping to avoid in this program, but since it’s only for the error gathering/reporting mechanism, which is only used when the program is about the shut down, I don’t think it’ll be an issue.

A benefit is that it’s general. It doesn’t depend on this tetris program at all.

The struct ErrorInfo

These are the two structs that power error handling.

struct BasicString {
  char *data;
  int len;
};

struct ErrorInfo {
  struct BasicString msg, file_name, func_name, code;
  int line;
  struct ErrorInfo *next;
};

This is a basic linked list structure. Each link has information abouts its error entry and a pointer to the call which led to it. There are them 3 functions for error handling:

int
link_error(const char *msg,
           int line,
           const char *file_name,
           const char *func_name,
           const char *code);

struct ErrorInfo*
get_error(void);

void
free_error(struct ErrorInfo *err);

Notice that link_error, alone, is very clumsy to use. It’s not meant to be used directly, even though you can. It’s meant to be used through the error handling macros.

When you ask for error information with get_error, you get a copy of the internal error structure, which you should free once you’re done with it through the free_error function. If you pass null to free_error, it’s going to free the internall error structure. This is useful for program shutdown. It may be a bad feature to have because it means you have check for null before calling it if you don’t want to free the internet structure.

Freeing the internal structure isn’t a problem if you don’t care about losing it. In fact, if you want to recover from an error, what you should do is free the internal structure so it gets out of the way of newer error messages after the recovery.

Error recovery, though, isn’t much supported by this module. As I said before, error handling in the program is pretty much: clean up, report, and quit. However, it wouldn’t be hard to add more information to the ErrorInfo structure so that it can record error problems. For example:

  • It could have an error code (int) and context memory (void*) that is fully user manipulated.
  • Users could create their own special macros that work in terms of ones provided by the error module. These macros would call the underlying error.h macros with the right error code and context creation code.
  • Convention such as ERROR_H prefixed identifiers could be used to avoid major identifier clashing.

It wouldn’t be the best or a pleasant system to work with. Error handling in C isn’t something I know how to deal with in a way that I find enjoyable. But it would be useful and allow for the kinds of operations I want to work with: error issuing, reporting, handling/recovering.

Bugs

Doing the C++ rewrite showed me that it was useful to have a SDL wrapper for raising exceptions whenever SDL failed underneath. This made the C++ code for error issuing and reporting much more convenient to deal with than the C version.

As a side note, the C++ error issuing/reporting code is still more convenient to work with in my opinion, even after the C refactoring. However, the current C version of the error handling code is much more useful. A similar mechanism would also be possible in C++, but it’d take away its convenience.

During the creation of that SDL wrapper, I had to look at the docs of many SDL functions and found out I didn’t know SDL as well as I thought. I hadn’t realized how many SDL calls can actually fail. As of now, writing this document, the bugs I can remember all had to do with that: making calls to SDL functions without realising they could fail.

Single Threading

The system is currently single threaded. The error handling system can be made multi threaded simply by making use of thread local variables. Each thread needs its own error handling subsystem. Their data aren’t supposed to be shared.

For the other system, something message passing-wise seems appropriated, but I haven’t thought of anything yet. The games I have in mind are too simple to need any of the complications of multi-threaded code.

The Quake Games

The Quake games (by ID software) were all done mostly in C. Maybe I’ll look how error handling was done in there when I get to more complicated games.

Tetris Clone Rewrite – in C++ and SDL2

Tags

, , , , , ,

Some weeks ago, I’ve written a tetris clone in C. I decided then to work a little more on the project to experiment with some ideas. One of which is to see what I could do differently, if not better, by rewriting the code in C++. The result is in this github repository for the C++ rewrite. The C version is on github at http://github.com/phao/tetris. I’ve decided to rewrite the code in C++ to see if I could improve it somehow. I’ve rewritten, and this document is a post-analysis of the whole process and end results.

Code Size

The C++ the line count is higher.

  • C is 1566 LOC
  • C++ is 1927 LOC

This isn’t to say that the C++ version was worse in any way. The increase in LOC has to do with the following:

  • Larger header files to contain class definitions. The C version has separate modules for different functionalities while the C++ code has different classes.
  • The C++ version has a wrapper on the SDL library while the C version doesn’t. This wrapper alone is 397 LOC.

These LOC values include comments, blank lines and so forth. There was no attempt to make it “more meaningful”, whatever that means to you.

C Modules and C++ Classes

The solution/implementation involved many concepts, including:

  • 3 “alike” screens;
  • an assets gateway;
  • a music player;
  • a text image GUI widget.

In the C version, these items mapped into modules. The last item also involves a non-opaque data type.

Everyone knows that C doesn’t really have a modules system. In here, I just mean a separate compilation unit in a C file, with an accompanying header file describing its interface.

A module can implement a data type which you can instantiate and whose instances you can manipulate through functions. That is the case for the text image GUI widget.

A module can also encapsulate access to something through functions and other language features. This “something” is usually a set of data structures, but it can be anything (a collection of constants for example, or even a set of other functions). The first three items were implemented through modules like this. This is what is called an abstract object (definition from end of section 19.1 of C Programming – A Modern Approach Second Edition). If you’ve never heard of this before image it being an ADT, but with only one instance of it.

For example, the assets gateway is an abstract object. It has basically 3 kinds of functions: init, shutdown, and assets accessors. Clients of this module only need to know the functions to access the assets they need. Internally, the assets module knows which state to maintain and which functions to call in order to be an assets gateway.

The three screens are also abstract objects. However, they’re not manipulated directly. The screens are “alike” because they’re all manipulated in the same way. As explained in my older documents, whatever is the screen currently active, it has to handle events, do updates, rendering, and so forth. It doesn’t matter which of the three screens is currently active, the screen manipulation logic is the same.

This led to the following design. Each screen is an abstract object, but the only function directly exposed is the init function, which sets up the internal data structures used by the screen, and also indirectly exposes its other operations through a pack of function pointers. Indirect exposure also uses a function from the main module called register_screen.

An ID is conventionally assigned to each screen, and during its setup function, each screen will register its pack of function pointers giving its ID. Like this:

register_screen(MENU_SCREEN, my_operations);

This way, the main module can receive and store the packs, and manipulate screens by keeping a pointer to the pack of the currently active screen. To manipulate a different screen, it can simply point at a different pack of function pointers.

Here is game.h (header file for the game screen module). Notice how it only exposes its init function.

#ifndef GAME_H
#define GAME_H

#include "screens.h"

int
init_game(const struct GameContext *gx);

#endif

Here is the header file for the assets module.

#ifndef ASSETS_H
#define ASSETS_H

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

static const struct SDL_Color DEFAULT_BG_COLOR = {25, 25, 25, 255};
static const struct SDL_Color DEFAULT_FG_COLOR = {225, 225, 225, 255};
static const int LARGE_FONT_SIZE = 46;
static const int MEDIUM_FONT_SIZE = 34;
static const int SMALL_FONT_SIZE = 22;
static const int BLOCK_WIDTH = 30;
static const int BLOCK_HEIGHT = 30;
static const int NUM_SONGS = 5;

int
init_assets(SDL_Renderer *r);

TTF_Font*
get_large_font(void);

TTF_Font*
get_medium_font(void);

TTF_Font*
get_small_font(void);

void
destroy_assets(void);

SDL_Texture*
get_tetris_block_img(void);

SDL_Texture*
get_bg_img(void);

#endif

This is one of the most complicated header files I had, in pair with screens.h. Here is music.h (much simpler):

#ifndef MUSIC_H
#define MUSIC_H

int
init_music(void);

int
play_new(void);

int
destroy_music(void);

#endif

The music player module also is for an abstract object. Internally, a Mix_Music* is used to play the tetris background music.

An advantage of having abstract objects represented through modules is how simple things get. Main is also an abstract object whose purpose is to start the program, control setup and shutdown of other abstract objects, and implement/run the game loop.

Main overall:

  • init
  • game loop
  • cleanup

An evident problem with this approach is that if I ever wanted two assets gateways, or seven (for whatever reason), I’d be screwed. In this case, a tetris clone, I knew I would only need one. So there was no harm in making it an abstract object. The same is true for the music player, for each of the screens, and so forth.

C++ makes it seem like a small leap to turn modules like those into classes. So I took the bait.

The class feature in C++ is a general mechanism to represent in your program arbitrary concepts of your solution. In C++, you can use a class to do OOP, but that’s not all there is to it. OOP is one kind of solution, and classes are really a general solution-representation mechanism.

OOP, as Alan Kay said, involves message passing (which today we call method [or member function in C++] calling so it’s not confused with the concurrent programming concept of message passing), late binding (which in C++ is achieved through virtual member functions) and state retention (which in C++ is sort of difficult to achieve, but can be with discipline and the right programming practices).

In the C++ version of the tetris clone, OOP isn’t practiced very much (not any more than in the C version). The rewrite wasn’t so that I could make the code more OO. I don’t think much benefit, if any at all, will come from that.

State retention is there, but not quite. Clients of classes generally have no choice but to rely on private aspects of a class, such as which private members are there, simply because the header files exposes those aspects. This means that a client depends in the structure of the class’ private members, and thus will have to be recompiled in the case of a change in those aspects (the recompilation isn’t always necessary by the way).

Although things are not simple as I made them sound, it is true that a client will end up eventually in need of a recompilation because of a change in an implementation aspect of a class it merely has a pointer to. This is the kind of thing state retention attempts to avoid (dependency of any kind on implementation detail so that change in implementation details won’t affect client code).

C++ lets you enforce state retention to its full utility, but I’m not looking for that much in this program.

Notice that in the C code the natural way of programming modules enforced state retention well enough because I was dealing mostly with abstract objects. With the text image GUI widget, which isn’t an abstract object, similar state retention issues as in C++ appear. This way of programming (with abstract objects) can also be done in C++, but I didn’t choose it because I wanted to see how much of an improvement using classes would have caused.

I need to say that the PIMPL pattern isn’t an alternative here. The PIMPL pattern involves some form of allocation scheme because you hold a pointer to the implementation class type, which will have to be set up properly later. In all the examples I’ve seen, that is through some form of dynamic allocation with the new operator or some custom allocator that relies on new behind the scenes (but does so more efficiently). The C version doesn’t have any dynamic allocation in it (this was an implementation constraint I wanted to satisfy from the beginning), and I wanted the C++ version also like that. So, unless I learn how to apply the PIMPL pattern without dynamic allocation, it won’t be applicable in here.

Another reason why OOP isn’t much present in this program has to do with late binding. Very little of the program is actually late bound. Most calls are statically bound.

OOP isn’t fully absent though. It’s present in the game loop function, in the screen classes, and in main’s cleanup function. The game loop function in main uses screen objects through late bound method calls. Although state retention isn’t quite there in the program as a whole, that game loop function makes no assumption about the implementation details of the screen objects. This isn’t a special property of the C++ version of the program, this was also present in the C version.

So it should be clear that C++ wasn’t used for its special OOP support. The C++ version actually involves no more OOP concepts than the C version.

In C++, instead of implementing abstract objects, what I did was to have a class instead and leave to the client code to decide where to allocate the instances. Taking away decision making from classes and letting client code provide context made things more flexible. It’s a weird benefit though because it seems useful, but nowhere in the program it’s used. For example:

  • Instead of depending on a fixed single assets module, a screen receives a pointer to an Assets instance, and then could work with any Assets instance. So if you have three assets instances and want each screen to use a different on, in the C++ version, you can easily do that. Nowhere in the code this is done.
  • Client code can decide to dynamically allocate a music player (or an assets instance, or a menu screen, …) instead of using automatic storage or static storage. Nowhere in the code this is done. The old C code used static storage, and the C++ code also does the same. However, the C++ code could have used automatic storage for example.

The transition from C modules to C++ classes was the major one. It was the most time consuming one, and the one most difficult to implement in comparison. The benefits from doing so seemed pretty small for this program in particular. The benefits of being able to have many instances instead of only one is real, but not here it seems.

Error Handling

The major reason why a SDL wrapper was written has to do with error handling. A huge number of SDL calls can fail. It’s easy to forget which calls can fail and which can’t. Also, with a SDL call failing, error handling is basically:

  • clean up
  • print error message
  • exit

In the C version, I made a mess out of error handling (I’ll fix that), but even without my mess I reckon the C++ version of error handling is way more convenient to deal with. The SDL wrapper makes the underlying call, check for errors and throw an exception if there were any. A single try/catch statement exists in the main function and that’s it. In the case of an error, the catch block in main knows what to cleanup, report and how to exit.

Figuring out which functions throw and which functions don’t throw so I could annotate them with noexcept appropriately was annoying and seemed highly error prone. It was a downside. Maybe I shouldn’t be annotating functions with noexcept. I know it’s important to do so for constructors (default, copy, move, …) of types you intend to use with the standard library (e.g. you want to have a vector<T> where T is a custom type of yours). For other functions that don’t throw, it seems logical that I should annotate them with noexcept, but I’m not sure (again, highly annoying and it seems extremely error prone).

The error proneness of annotating with noexcept, for all I can tell, comes from the fact that you need to keep in sync the noexcept specifier and the implementation of the function. If the implementation code changes, you may have to change the noexcept specifier. Even though you can make your noexcept specifier dependent on arbitrary conditionals, even involving the noexcept-ness of other code, the error proneness is still there. The noexcept-ness of a function is part of its interface, which means this whole noexcept conditional specifier will have to be exposed as part of the function interface (in a header file), which means that if you depend on some call to be noexcept or not in the implementation, you might have to place that call code in the function’s declaration in the header file for noexcept’s sake. I’m not much familiar with C++’s noexcept, so I may be wrong here, but this seems a whole new level of mess. Until I learn more, I’ll stick to simpler noexcept specifier (mostly those that don’t depend on anything else, or on very simple and harmless conditionals).

Discipline in using exceptions is needed though. In all the cases, all I can do when an error happens is what I told before (clean, print, exit), so exceptions seem to apply effortlessly. In so many cases I see people using exceptions for more complicated decision making, and they don’t seem fit for that. If you have ever written Java code before, maybe you’ve came across code trying to parse integers and floats, and maybe you’ve seen how much of a mess it is dealing with errors in such code exactly because of exceptions.

In a more elaborate program, I won’t just print something to the console. The exception instances could be enriched with values known at the point of failure. Some report could be generated in main’s catch block and maybe an email could be sent to communicate the error to the development team’s. Maybe the email could be archived for later if no internet connection is available. C++’s exceptions support that approach as well.

In C, dealing with errors is less nice. It involves a combination of error codes, global variables (errno and friends), and even non-local jumps in some cases. In my C version of this tetris clone, error handling was done with:

  • error (return) codes
  • helper macros
  • a single global variable for error information

C++ is a clear winner here as far as I can tell. Exceptions didn’t make the code any harder to write. Even though the SDL wrapper was needed, it’s a one time thing, meaning I’d have to write it once and simply use it the next times. The code also wasn’t any harder to read because of exceptions. On the contrary actually the code was easier to read because all the code needed to propagate the error and perform cleanup became much simpler using exceptions.

It’s true that my error handling C code is much more complicated than it needs to be, but even if it wasn’t the C++ version would be still simpler.

RAII

The big thing I hear about C++ is RAII. It’s how class type instances can be used to control init and shutdown of various resources automatically through static scoping rules. This is a very attractive idea, and even though I make use of RAII, I don’t think it made this particular code any better (or any worse).

Operator Overloading

There are two uses of operator overloading that I found particularly interesting. One is operator == and operator != for the SDL_Color type. The other is operator= for the std::array type. Mainly the second one.

This second one replaced a few calls to memcpy that existed in the code. It made the code significantly more readable in those particular sections (i.e. the functions that used to call memcpy and now simply run an assignment).

Copying and Moving

C++ introduces language mechanisms supporting moving and copying. They are pretty straightforward to deal with those for simpler types (e.g. Scores), but for some cases I’ve found much easier to simply use C++11’s delete feature to disable moving and/or copying. For all I can tell, this is perfectly fine. Not all types are supposed to be copyable, and moving seems more like an optimization possibility for copyable types, but it can be used for non-copyable types (and it is useful to do so in some cases).

Deleting these seems specially fine for types which represent IO concepts like classes for the screens, for the music player, for the assets gateway. Moving can make sense for those. For example, it’d allow for a function which returns a new instance of a class, and I have implemented moving for some types, but it was mostly as a curiosity thing. Generally, I don’t make much use of copying and moving for the custom types I’ve created.

In the process of deleting the copy constructors and assignment operators, I was generally fine with the decision of doing so. However, for moving, it was clear to me that in most cases (if not all) there was a plausible implementation for move. Implementing it though would have been a waste of time since I didn’t see the need to use it anywhere in the program. This was apparent based on the C implementation, and it became clearer as I dug deeper into the C++ rewrite.

Copy and move aren’t completely absent though. For example, the Scores type is pretty much a traditional value type “like int”, and it behaves so nicely that the defaults (copy, move, and destruct) work just fine for it. However, it’s good to point out that this doesn’t contradict what was said earlier: move and copy constructor/assignment isn’t used in this program for the custom types I’ve implemented. Even though the Scores type have it, it isn’t used by this program.

The Manual “Hack”

There is a class template called Manual. It serves to let you manually call the destructor/constructor in case you want to delay when the constructor is called or hurry up when the destructor gets called. This template is used throughout the program.

In many cases, I found myself wanting to delay initialization (see the Scores class), keep the storage after deletion for reutilizing later for a newer instance (also see the Scores class). In some other cases, my problem was that I couldn’t find a way to use initialization lists to get the members to be initialized. The screen classes also use the Manual template.

The reason why I’m calling it a hack is because I can’t help myself but to think this is all because I’m not structuring my solution into classes that play well with the C++’s way of doing things.

I feel like it’s important to point out that using Manual<T> instead of just T didn’t make the code any more difficult to understand as far as I could tell.

In many cases (if not all), dynamic allocation could have been used instead of the Manual template. Reutilization of storage could be done with placement new, and deletion without deallocation could be done by calling the destructor directly. There are two reasons why I didn’t do this:

  • I wanted to avoid dynamic allocation as an implementation constraint I imposed upon this project.
  • It seems like a much more error prone approach than using Manual.

In C, life cycle is always manually controlled.

Looking Back and Ahead

Looking back from now, what I’d like to see is what would happen if I only used C++ for error handling support, which was where there was a big win. Instead of trying that however, what I’ll probably do is adjust the C version.

During the C++ rewrite, I’ve found places in which the C version was way more complicated than what it needed to be. I also found bugs in it. My next step is dealing with those issues. Then, I’ll polish this project’s documents, and then move to another game.

In general, I think the code became better. I think it could become even better if I knew more about C++. But in many cases, advantages are clear. For example, one thing I didn’t mention much before was the use of virtual functions and purely abstract base classes. In large projects, these seem much better tools than structs of function pointers, specially because packs of function pointers won’t always cut it.

C++ seem to introduce many interesting ideas through language features, and although the ideas are interesting, the language features aren’t nearly as so much in my opinion.

The Major Benefit of It All

The major benefit wasn’t the rewrite. It was the review needed for the rewrite. During this review I’ve found bugs in the program, unnecessary complexity in my error handling code, design flaws and so many other little things to fix.

For example, there were many SDL functions that I thought couldn’t fail that actually can. In the middle of the C++ rewrite, I decided to take a look at those (for other reasons besides error handling) and noticed that SDL_RenderCopy can fail. This was when it hit me that maybe I wasn’t checking for errors in all my SDL calls. This led to extending my SDL wrapper to add many more entries than it had, and also led to a reminder that I should fix my C code.

In the end, the benefit wasn’t rewriting it in C++. It was taking a second look at the code. As someone else said out there, “Writing is rewriting.” and I think this quote is highly applicable here.

Follow

Get every new post delivered to your Inbox.