Showing posts with label 2D Game Engine. Show all posts
Showing posts with label 2D Game Engine. Show all posts

Thursday, February 6, 2014

C++ Build Preprocessing Thoughts

Something that's been on my mind lately is how you could automatize many otherwise tedious and repetitive programming tasks by using custom build preprocessing tools.

If you're familiar with Qt's meta object compiler (moc) then you should have a good understanding of what I'm trying to talk about in this post.

When I first thought of useful C/C++ build preprocessing steps I was adding reflection and serialization to my engine.

Serialization, for instance, was just filling out a virtual serialize() function, where each member variable of a class was written to a binary stream.

Basically it was like this:

 Example::serialize(Stream& p_Stream)  
 {  
    p_Stream << m_Value1;  
    p_Stream << m_Value2;  
    p_Stream << m_Value3;  
    //custom class  
    m_Value4->serialize(p_Stream);  
    //...and so on  
 }  

As you can imagine, this got tedious and boring pretty quick...And that was when I though about a more elegant solution for this.

A few days later, build preprocessing came to my mind.

The basic idea is to use some kind of parser-tool (clang anyone? Getting a hang of clang can be pretty tedious, but it will pay off eventually) to parse your C/C++ code and
identify variables by using custom type qualifier. The information you gather by identifying your variables like this can be used to automatically create various function (like the serialize() function in this example)
In my codebase this would look like:

 #define serializable  
 class Example  
 {  
 public:  
    Example();  
    ~Exmaple();  
 private:  
    serializable int m_Value1;  
    serializable float m_Value2;  
    serializable bool m_Value3;  
    serializable CustomClass m_Value4;  
 };  

The tool I build (in lua - still learning how to use clang) scans my codebase for variables with the custom qualifier 'serializable'. It then saves these variables and automatically creates the serialize() function with the information it gathered during the codebase parsing.

This approach saved me various hours of tedious code doublication so far :)

Some more examples I thought of that would make sense would be

  • Code reflection (again using custom qualifiers)
  • Enum <--> String conversion 

Monday, March 5, 2012

New splitscreen approach.

As posted here, I implemented a splitscreen mode for the engine.
The implementation is sort of dirty as all graphics are getting recreated per camera.

For instance: you want to draw a graphic with 4 player split screen.The graphic will then get created 3 times (1 graphic for each camera). That ensures that every camera has its own graphic with which it can do what ever it wants (like zoom, rotation, etc.)

As you can imagine, that is quite expensive and for many graphics on screen pretty memory consuming.
That seemed like a wasteful but working implementation until now.

It's just theoretical, but I'm pretty sure it is possible to reimplement it so that every graphic will only get drawn only for one camera per tick. If there's more than one camera, the graphic will get drawn for the next camera the next frame.

It'll go like this (C style pseudocode):

 void draw(IGraphic graphics*[]){  
      if(CURRENT_CAMERA < AMOUNT_CAMERA){   
           CURRENT_CAMERA = 1;               // Start from first camera  
      }  
      for(int i = 0;i < AMOUNT_GRAPHICS;i++){ //go through all graphics.  
           m_cameras[CURRENT_CAMERA]->draw(graphics[i]); //draw graphics into buffer of the current camera  
      }  
      CURRENT_CAMERA++; //Increment to camera counter and leave the draw function.  
 }  

So if the game uses 3 cameras it'll look like this:

Frame 1 : Draw graphics for camera 1
Frame 2 : Draw graphics for camera 2
Frame 3 : Draw graphics for camera 3

Frame 4 : Draw graphics for camera 1
Frame 5 : Draw graphics for camera 2
Frame 6 : Draw graphics for camera 3
....

I don't know if this implementation will cause a big delay, but I guess it's for me to find out ;)

Edit:
This approach will obviously split the FPS in half.
e.g. 60FPS / 2 Cameras = 30 FPS per camera.

That means that the game needs to run with ~120 FPS to look smooth with 4 cameras....
Shouldn't be a problem with a 2D game.

Monday, January 23, 2012

Splitscreen

Wohoo!
10 lines of code changed = splitscreen :) (Up to 4 cameras will be supported by the engine)


Saturday, January 21, 2012

Generic 2D collision system.

Today I want to explain the system I use in my engine for collision detection.
I tried to keep the collision system as generic as possible.

My engine provides a class called "CollisionComponent". You can add one or more components to a game objects to make them collidable. (Collision detection is done via collision rectangles).

To make the collision handling as generic as possible I decided to realize the handling "response" (the point where it'll get decided what to do with the collided objects) with function pointers.

You can "subscribe" gameobjects via typename (String) or a specific id (int) and with a pointer to a function that receives two pointer to game objects(first is the object that did "the impact" and the second is the object that got hit) and returns void.

Here's a little code snippet to make it more clear how that works:
 void collision_handler(GameObject *object1,GameObject *object2)  
 {  
    //...Do fancy stuff here  
 }  
 int main()  
 {  
    GameObject object1("Type1");  
    GameObject object2("Type2");  
    //...  
    //...  
    CollisionComponent *collComp = new CollisionComponent();  
    CollisionComponent *collComp2 = new CollisionComponent();  
    object1.addComponent(collComp);  
    object2.addComponent(collComp2);  
    //..  
    //subscription with type  
    CollisionManager::subscribe(object1.getType(),object2.getType(),collision_handler);  
    //..  
    //subscription with id  
    CollisionManager::subscribe(object1.getID(),object2.getID(),collision_handler);  
    //..  
 }  

The difference between subscription via type and id is that multiple game object can have the same type (for very generic collision handling like "bullet hits player" or "weapon hits enemy").If you want to make more specific collision handling you can use the subscribe function that uses ids because the ids of the objects are unique.

The only problem is that each tick each game object gets checked with every other game object.
That's not very performant, but I don't know how to do it better, yet.

Monday, December 5, 2011

Make your Engine more dynamic!


When I started to program my Engine, I wanted to create a somewhat portable Engine.
I wanted to support different libraries like OpenGL, OpenAL or DirectX to make my Engine run under Windows and other platforms.

My first attempt was to differentiate with the Preprocessor variables given by the OS
(For example _WIN32 under Windows).

That worked, but was somewhat ugly...

It was indeed so ugly that I decided to give it another try.
So I split everything into separate dynamic libraries.

At the end I had one library for every replaceable feature of my engine.
Here are some of them:

K15_GraphicModule.dll / K15_GraphicModule.so
K15_SoundModule.dll / K15_SoundModule.so
K15_InputQueueModule.dll / K15_InputQueueModule.so
They were implement as subsystems.

I'll try to explain the idea behind the subsystems by the example of the GraphicModule.

The GraphicModule is, for example, a subsystem of the Engine's GraphicManager.
The GraphicManager will try to find a "K15_GraphicModule.dll" or "K15_GraphicModule.so" (depends on the OS) in it's initialize function. When it finds the dynamic library, it loads it and tries to perform the function "createGraphicModule()" within the library.

The function createGraphicModule will return an implementation of a GraphicModule interface that is declared inside the Engine's library file.

Here's some code to clarify my example.

 GraphicManager::GraphicManager  
 {  
      typedef createGraphicModule IGraphicManagerModule* (*createGraphicModule)(void);  
      DynLib graphicLib("K15_GraphicModule") // load library (without extension...Determined by the current OS)  
      if(graphicLib.loadedSuccessful()){ //Check if library has been loaded.  
           createGraphicModule func = (createGraphicModule)graphiclib.getFuction("createGraphicModule");  
           if(func != NULL){ // function loaded?  
                this->m_subsystem = func(); //get Subsystem from dynamic library.  
           }  
      }  
 }  

This system allows me to switch between OpenGL and DirectX just by replacing the dynamic library files...Or to switch from Windows File Manager to some Unix File Manager just by replacing the library file.

I just implemented this system about a few days ago, so I don't know how well that will work in an actual game...But it's only a matter of time 'till I know it ;-)

Sunday, March 20, 2011

Rendering of levels complete!

I just finished the part of my engine where the levels that got created with the leveleditor gets rendered.
















The left window with the black background is ingame and right window is the leveleditor.

Thursday, March 10, 2011

New video of the current state (finally!)

I finally managed it to create and upload a new video of the current state of the leveleditor. As you can see, I added several new features like the toolbar (on the left - with the ugly icons ;) ), multilayer drawing, event creation and several other things.



I once again recommend to watch it in fullscreen.