1 - installing the tools and running samples
2 - calling C++ library from Java
3 - abstracting types and logging
4 - timing service
Last time we ended with displaying green screen. We set all the needed things on java side and we created Main.cpp on C++ side. Today we will do things that will prepare our engine for going multiplatform. So, there will not be to much fun but it will pay soon in next parts of this series.
Project structureAfter the last article we ended with jni folder in our project with structure like this:
When we finish today the structure will look like this:
So, first go into jni folder and create all new subfolders: src, Engine, Game, System and under System also the Android folder. In future there will be some common system files in System folder. Usually some abstraction of some feature like touch input and in folder with concrete system name there will be implementation of this feature.
Adjusting Main.cppGo to Main.cpp and in the top remove these lines:
and replace it with these lines:
The purpose of the LOG_TAG will be clear soon. You can also see that we will structure our engine with namespaces to keep it clean.
ParametersAs the engine will grow and support more platforms and features, we will need some way how to parametrize it. So in the same folder as Main.cpp resides, create file params.h with the following content:
In this file additional parameters will be added in future. From here I am switching various debugging features on and off.
What we set now is that we say we are using Android (PLATFORM_ID = PLATFORM_ANDROID). We plan to use OpenGL in its version 2.0 and the target resolution for our game is 1280 x 800. The target resolution is not size of your device screen but buffer the OpenGL draws in. It is than scaled to your device screen.
Now go to System folder and create file _parameters.h in it. The only purpose is to suck content of params.h into engine. As the params.h can be different for different platforms and we do not want to change or set up anything in System folder in future we are doing it in this way. The file looks like this:
Abstract systemIn System folder create file system.h. If you later in your engine or game will need some system features like logging you will call it every time in the same way regardless of the actual system. Put these lines into the file:
As you can see, while we are working with Android today I left also other systems there. In Eclipse it will be grayed out to mark that preprocessor is skipping it.
Next create Log.h and Types.h that have similar structure.
You see that its purpose is again just to load concrete implementation from selected system folder. Now we can go into Android folder and implement it.
Android implementationWe have selected Android in parameters and our engine now awaits concrete implementation for system, logging and types. Let's make it happy.
First create file AndroidTypes.h in Android folder and fill it like this:
You see that we abstracted C++ types with our own. In the rest of the engine we will use s32 instead of int or u16 instead of unsigned short. In this way we can construct 32 signed integer needed by engine from int on most of today platforms but in case int was only 16bits on some platform we can construct it from long which will probably be 32bit. But our engine will use s32 and will not be interested what is behind.
Now to logging. It is nice that Android has __android_log_print function in log.h file. But again it is not general enough for multiplatform engine. So, we will abstract it in file AndroidLog.h like this:
We defined four macros and in the rest of the engine we will use it just like: LOGD("Hello");
Here comes into play the LOG_TAG we defined in the top of the Main.cpp. We will define it in every source file so logging will always say us where we used it.
Finally create file AndroidSystem.h with this content:
You can see that we are benefiting from our parameter file params.h where we set OpenGL version 2. Without any further settings it is processed inside system files and the system is parametrized from one place.
Let's try itToday there will not be any wow effect when running the engine. But we can at least prove that what we did is working. Go to Main.cpp and add these lines to our native methods:
With this you should see log messages in the the LogCat.
ConclusionToday we put base for spreading our engine to more platforms in future. Next time we will focus on measuring time.