mail

Own OpenGL engine

Portfolio Page

Introduction

In my first year I made my own OpenGL engine that I used for making 2D games in. This was a free time project since you could also choose to use the template provided by the school (I did this for the first half year). I finished making this engine in my third block of the year.

Beforehand I did not know anything about making own engines or OpenGL, I learned a lot about designing an engine by the mistakes I made in this project. I started with following OpenGL tutorials to get the rendering part working, from there on I made my own collision, physics, GUI, game objects and scene systems. In the end I also integrated FMod for music. The target of the engine was 2D games made in C++.

My work

I used for the interface between the engine and game code a pimpl idiom to hide the engine code. The classes you made in your game code all inherit from interfaces I build, this hide again the engine code so it looks clean for the user. There are a lot of different interfaces to inherit from. You have scene interfaces that you can use to create your game scene, this will make sure you always have an init, update and destroy function that is called from the engine side. You have object interface that gets used for the game object itself, it uses rigid body and collision interfaces to handle collision calls, other than that it has standard functions like position, size etc. The rigid body and collision interfaces make sure you have OnCollisionEnter functions and such, it also hides the engine code. In the engine self the game objects that need collision and have rigidbodies get registered and will be handled by the physics and collision managers.

1
2
3
4
5
6
//Make the ball the player has  to shoot
ControllableBall* b = new ControllableBall();
m_PlayerBall = m_Engine->CreateGameObject("assets/Sprites/player_ball.png", b, "PlayerBall", true);
m_PlayerBall->sprite->SetPosition(500, 500);

m_Engine->AddCollision(m_PlayerBall, CollisionTypes::CIRCLE, true, false);

Above you see how I make in the game.cpp the player ball. I first make a class, ControllableBall, which is an inheritance of ball, which on its turn it inherits from ObjectInterface which is an engine class. Then I call an engine function which registers the ControllableBall as a game object within the engine. As arguments, I give it an url to a sprite, the class, the name of the object and lastly true for rigid body. This will make sure it gets a rigid body which means I can apply forces to it easily with the AddForce engine function. Then I set a position on the sprite via the engine. I then add a circle collision to it with the AddCollision call. In this call you give the object, then the type of collision, then if it has motion (needed for calculations) and then if it is a trigger or not.

Now we will dive deeper into the engine code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
for (auto itMCol = m_MotionColliders.begin(); itMCol != m_MotionColliders.end(); ++itMCol)
{
	for (auto itCol = m_CollidersList.begin(); itCol != m_CollidersList.end(); ++itCol)
	{

		//If the colliders are active and they have to check (like in screen)
		if (itCol->second->IsActive() && itCol->second->HasToCheck() && itCol->second->GetID() != itMCol->second->GetID())
		{		
			if (CheckIfCollide(itMCol->second, itCol->second))
			{
				itCol->second->OnCollision(itMCol->second);
				itMCol->second->OnCollision(itCol->second);
				if (!AlreadyHit(itMCol->second, itCol->second))
				{
					//itCol->second->OnCollisionEnter(itMCol->second);
					itMCol->second->OnCollisionEnter(itCol->second);

					itMCol->second->m_CollidersHit[itCol->second->GetID()] = true;
				}
			}
			else
			{
				itMCol->second->m_CollidersHit[itCol->second->GetID()] = false;

				GameObject* g = itMCol->second->GetGameObjectEngine();
				if (g != nullptr)
				{
					if (g->GetRigidBody() != nullptr)
					{
						CalculateCollisionSteps(itMCol->second, itCol->second, g->GetRigidBody());
					}
				}

			}
		}

		
	}
}

The code above is from my collision manager, this is all engine code. First, it will go through the motion colliders and normal colliders. It then checks if the colliders are active, are within the screen (else they get skipped), and if they not have the same ID. The idea is that only he motion colliders get checked against all colliders, this since only motion colliders are moving, other colliders can never have a collision with each other since they do not move. After that it checks if they collide, it uses circle vs circle collision, box vs box collision and box vs circle collision to check the colliders. It first gets the type of collision from the collider and then checks according to the type, box, circle, or box and circle. After there is a collision back it will check if they already hit each other, if not it will call collision enter event that goes through to the game code. It then always calls the colliders hit function too, which also goes through to game code. After that it checks if it is a rigid body, because if it is it will calculate the upcoming collisions, this so that the rigid body can never get stuck in an object, also it is useful for the gameplay coder to know the traction of the rigid body.

Unfortunately I can not show you the entire engine since it is quite big, there are still more managers, handlers and the like. The engine has some design flaws since it was the first engine I ever made, but I since have learned a lot about both C++ and engine making.