Shade: status update 2

Second month of development and second status update on Shade, a cross-platform framework for 2D games which will be the core technology of all my next mobile and desktop games.

This month I’ve been busy with other stuff for more than 2 weeks, so I’ve been able to work full time on Shade only a couple weeks and few spare days, but I’m quite happy with what I’ve achieved at the end, even if it could/should have been more.

During this month there’s been a lot of refactoring going on, but most of the work went on a new module: display.

The display module

The main duties of the display module are abstracting the screen resolution and managing nested objects.

It can be considered as a higher level rendering which automatically scales graphic objects (primitives and text) to adapt to any resolution and which allows to create nested objects in a way similar to what you can do with Sprites in AS3/Flash. This allows the end user to write a generic code once without having to worry about the different resolutions. Obviously some “flexibility” is required and the system is not perfect yet, but it’s already quite usable.

Even if inspired by the display AS3 module I decided to not have a Graphics object which handles drawing of primitives for Shapes and Sprites, but to go for several concretes objects like Quad or Image which makes creating primitives easier and faster. In the future this will be extended with a Canvas object which will allow to draw primitives the same way AS3 does, but that’s not a priority for now.

Just to give you an idea of the differences between AS3 and Shade here some example code:

First the AS3 code to create a red quad

var square:Shape = new Shape(); square.graphics.beginFill(0xFF0000); square.graphics.drawRect(0, 0, w, h); square.graphics.endFill();

then the C++ code using Shade to achieve the same:

Display::FilledQuad * quad = new Display::FilledQuad(w, h); quad->SetColor(255, 0, 0, 255);

When creating an image things get even simpler:

This is the AS3 code

var img:Bitmap; // create or get the Bitmap... var square:Shape = new Shape(); square.graphics.beginBitmapFill(img.bitmapData); square.graphics.drawRect(0, 0, img.width, img.height); square.graphics.endFill();

and this the C++ code using Shade

Diplay::Image * img = new Display::Image(DisplayTestResources::TEX_IMG1);

where DisplayTestResources::TEX_IMG1 is a constant which identifies a Texture within the TextureResourceManager (more info in the next section).

I do know the AS3 approach is more flexible and probably better from a design point of view, but at the end of the day being able to write less code is always a good thing so I’m happy with my decision, especially considering it will be extended and improved by the Canvas object.

Resource managers

Another key area of this month work has been the development of two ResourceManagers for handling Textures and Fonts. The former is part of the rendering module, whereas the latter is part of the text module.

The two ResourceManagers are fully integrated with the display module and are an important part of the technology behind the abstraction of the screen resolution as they always provide the best possible version of a resource given the current resolution.

In the short time I had this month I’ve managed to implement only the basic features needed to make things work, but with few more days of work and a bit of refactoring the ResourceManagers will offer a powerful way to control and access resources.

At the moment I’m still allowing to create primitive objects in the display module without using the ResourceManagers (i.e.: passing a file path to an image or a font), but I think this won’t be an option any more in few weeks as it may create some inconsistencies with the automatic resolution management.

Shade on Android

Yesterday I tried to build Shade and the new tests on Android for the first time this month and the initial result was pretty depressing, the build was failing to link due to this error:

undefined reference to ‘__atomic_fetch_add_4’

After panicking a little I managed to fix the build adding the following line to the Application.mk file:

LIBCXX_FORCE_REBUILD := true

That wasn’t the only issue I had to face as there were few bugs which were not affecting the Linux build, but which were crashing the tests on Android. After several hours of swearing, debugging, more swearing a little reasoning and some coding I managed all the new tests to run on my Android devices.

In the picture above you can see one test running on 5 different devices:

Google Nexus 7 2013: Android 4.4.2 – resolution 1920×1200

Android 4.4.2 – resolution 1920×1200 Sony Xperia S: Android 4.1.2 – resolution 1280×720

Android 4.1.2 – resolution 1280×720 Google Nexus S: Android 4.1.2 – resolution 800×480

Android 4.1.2 – resolution 800×480 Sony Xperia U: Android 4.0.4 – resolution 854×480

Android 4.0.4 – resolution 854×480 Samsung Galaxy Ace: Android 2.3.6 – resolution 480×320

One feature that was totally missing in the Android code was some kind of debug/logging code to get some debug text from the application. This made my life a little harder when things were not working, so I hacked some “quick & dirty” defines like this one:

#include <android/log.h> #include <sstream> #define DEBUG_COUT(msg) do{ std::ostringstream s; s << "[DBG] " << msg << std::endl; __android_log_print(ANDROID_LOG_DEBUG, APP_TAG, "%s", s.str().c_str()); }while(0)

Probably not a masterpiece, but it works and it complies with the (hacked) debug code I’m using for Linux which is entirely based on std::cout. At some point I’ll have to spend some time on the debug module, but for now it gets the job done so I can focus on more important things.

Obviously the same tests runs on Linux as well, even if I’ve not implemented a way to change the resolution at runtime yet, but that’s not a priority for now.

After this frightening experience I had yesterday I decided to change few things regarding my Android development. Above all I decided I’m going to build for Android any time I implement something new and at least once a week. Hopefully this will avoid further surprises at the end of the month.

The bug of the month

I mentioned I had to fight with few bugs in order to get the tests running on Android, so I thought to write down the “worst” one as future reference for me and the others.

The original code was something like this:

std::list<DisplayObjectComponent *>::iterator it = mChildren.begin(); std::advance(it, index); mChildren.erase(it); OnChildRemovedAt(*it, index);

which seems perfectly fine at glance, but… after calling erase on a container the iterator is invalidated, so there’s no warranty the last call will succeed (indeed on android it was crashing the app).

The fix for this bug was quite easy, copying the value pointed by the iterator before calling erase and working with that copy after.

What’s next

I’m definitely going to spend most of next month improving and finishing the main features of the display module and the ResourceManagers, but I will have to create the iOS projects too (for real this time).

I’m also going to spend some time working on a complex TextField object which will allow to create and edit text in several flexible ways. This will be part of the display module, but it will be strongly connected with some low level classes from the text module.

I will probably need to spend some time on the events module too as at the moment it can’t handle touch events yet. All this plus some extra bits which always come out at some point during the development… it’s going to be a busy month! 🙂