A simple collision approach

Collision is one of the core elements in game-development. Without collision we weren’t able to bring the most simple games to life. But there are a LOT of ways to start dealing with this particular problem since it’s not as simple as it sounds.

Possible complications:

  • We have to figure out who is colliding with each other
  • We have to specify who is allowed to interact with each other
  • We need a system which is not to complicated to expand
  • How detailed will our collision be?
  • How much performance can we sacrifice for convenience?

These are just some of the problems and questions you might face if you are dealing with this particular problem.

The big engines solved this very well with some interesting approaches, but this article is going to show, how one COULD!!! implement an own 2D collision approach.

I will try to focus on the theoretical part of the idea and how the idea works instead of coding everything into the last detail.

There will be a bit of code, some explanation, some code… aaand so on.

Ok let’s start. First of all I will implement a little helper class to deal with coordinates:

struct Vector2
{
 Vector2(int x = 0, int y = 0)
 : X(x), Y(y)
 {}

 int X;
 int Y;
};

static const Vector2 Origin;

Vector2 contains two int values, our X and our Y position. This class can be used to represent points as well as motions in a 2D space (I am going to presuppose that you guys are familiar with vectors in math). Our Origin is our base-Vector2 with a position of (0|0).

Now we need something which holds the info where our “collidable” begins/ends. We could save this information directly in our Actor (you will see later) but I prefer to outsource such kind of functionality to other components. We will implement a BaseCollisionBody from which we can inherit different CollisionBodies (like squares/circles) so we can easily change the collision body for our later Actors.

class CollisionBody
{
public:
 virtual bool IsCollidingWith(CollisionBody* target) = 0;
 virtual bool Contains(Vector2 pos)= 0;

 std::vector<Vector2>& GetBorderPositions()
 {
  return m_Points;
 }

 virtual ~CollisionBody(){}

 virtual void Move(Vector2 motion)
 {
  for (auto point : m_Points)
  {
   point.X += motion.X;
   point.Y += motion.Y;
  }
 }

private:
 std::vector<Vector2> m_Points;
};

This is our BaseBody. We got an IsCollidingWith() pure virtual function which will allow us to check if two Bodies are colliding with each other. We got a dynamic array which stores our border points so we can implement different forms with a different number of points. Futhermore we got a Contains() function which will later on implement the functionality to check if a point is contained by our body. Last but not least we got a Move() function which allows us to move our body.

Now we need at least one specified CollisionBody to cover the form of a sprite where we want to add collision to. I decided to go with a square.

class SquareCollisionBody : public CollisionBody
{
public:
 SquareCollisionBody(Vector2 position, int sideLength)
 {
 Vector2 pointA = position;

 pointA.X -= sideLength / 2;
 pointA.Y -= sideLength / 2;

 Vector2 pointB = position;

 pointB.X += sideLength / 2;
 pointB.Y -= sideLength / 2;

 Vector2 pointC = position;

 pointC.X += sideLength / 2;
 pointC.Y += sideLength / 2;

 Vector2 pointD = position;

 pointD.X -= sideLength / 2;
 pointD.Y += sideLength / 2;

 GetBorderPositions().push_back(pointA);
 GetBorderPositions().push_back(pointB);
 GetBorderPositions().push_back(pointC);
 GetBorderPositions().push_back(pointD);
 }

 bool IsCollidingWith(CollisionBody* target)
 {
  std::vector<Vector2>& targetPoints = target->GetBorderPositions();

  bool areColliding = false;

  for (unsigned int currentPoint = 0; targetPoints.size() > currentPoint; ++currentPoint)
  {
   Vector2 point = targetPoints.at(currentPoint);

   if (Contains(point)
   {
    areColliding = true;
    break;
   }
  }

  if(!areColliding)
  {
    bool condition1 = target->Contains(pointA) || target->Contains(pointB);
    bool condition2 = target->Contains(pointC) || target->Contains(pointD);

    areColliding = condition1 || condition2;
  }

  return areColliding;
 }

 bool Contains(Vector2 point)
 {
  Vector2 pointA = GetBorderPositions().at(0);
  Vector2 pointB = GetBorderPositions().at(1);
  Vector2 pointC = GetBorderPositions().at(2);
  Vector2 pointD = GetBorderPositions().at(3);

  if (point.X >= pointA.X && point.X <= pointB.X && point.Y >= pointA.Y && point.Y <= pointD.Y)
  {
   return true;
  }

  return false;
 }

private:
};

Ok, here we go, that’s our SquareBody implementation. In the constructor we are setting four points A(upper left), B(upper right), C(lower right) and D(lower left) and then we add them to our BaseBody::m_Points vector. We only need those four points to recognize if our square is colliding with something since we can simply check if one of the points is contained in our square. This leads to our simple two functions we are implementing for our BaseClass, Contains & IsCollidingWith. I don’t think I will have to explain those since they are quite simple. (And yes one could do this better, but this will suit our needs for this example)

The next class we will create is our Actor. I added some functions to the actor as placeholder which will give you a little view of how the class might work later. I won’t deal with these placeholders. Our Actor class will serve as base class for our other interactive classes like Character (Actors which have animations or can be moved around or which will be possessed by the AI later), EnviromentActors (Stones, Barriers etc…) or even projectiles.

class Actor
{
public:
 enum Type
 {
  actor,
  character,
  projectile,
  enviroment,
  background
 };

 class CollisionProperties
 {
 public:
  CollisionProperties(Actor::Type myType, CollisionBody* body, int n, ...)
  : m_CollisionBody(body)
  {
   va_list params;
   va_start(params, n);
 
   for (int currentArg = 0; currentArg < n; ++currentArg)
   {
     m_TypesToInteract.push_back(va_arg(params, Actor::Type));
   }
   va_end(params);
  }

  ~CollisionProperties()
  {
   if (m_CollisionBody != nullptr)
   {
    delete
    m_CollisionBody = nullptr;
   }
  }

  bool CanCollideWith(Type collisionType) const
  {
   return m_TypesToInteract.end() != std::find(m_TypesToInteract.begin(), m_TypesToInteract.end(), collisionType);
  }

  bool IsColliding(Actor* target) const
  {
   if (m_CollisionBody != nullptr)
   {
    const Actor::CollisionProperties& props = target->GetCollisionProps();

    if (CanCollideWith(props.m_CollisionType))
    {
     return
    }
   }
   return false;
  }

  void Move(Vector2 motion)
  {
   m_CollisionBody->Move(motion);
  }

private:
  Actor::Type m_CollisionType;
  CollisionBody* m_CollisionBody;
  std::vector<Actor::Type> m_TypesToInteract;
 };

 Actor(Actor::CollisionProperties* props, Vector2 position)
 : m_CollisionProps(props), m_Position(position)
 {}

 virtual ~Actor()
 {
  if (m_CollisionProps != nullptr)
  {
   delete m_CollisionProps;
   m_CollisionProps = nullptr;
  }
 }

 virtual bool IsColliding(Actor* actor)
 {
  return m_CollisionProps->IsColliding(actor);
 }

 virtual void Move(Vector2 motion)
 {
  m_CollisionProps->Move(motion);
  m_Position.X += motion.X;
  m_Position.Y += motion.Y;
 }

 virtual void Update()
 {
 //Some Stuff...
 }

 virtual void Draw()
 {
 //Some Stuff...
 }

 virtual const CollisionProperties& GetCollisionProps() const
 {
  return *m_CollisionProps;
 }

private:
 //...
 //Some Stuff...
 //...

 CollisionProperties* m_CollisionProps;
 Vector2              m_Position;
};

So this is our actor. Our actor contains a subclass CollisionProperties which will handle the collision for the actor. The properties class contains an Actor::Type member which specifies, which kind of actor we got (environment etc. see the enum) as well as the CollisionBody and a vector which contains the collision types, our actor can interact with. Our Actor is basically calling the functions we already implemented in our CollisionBody with the little difference that we can specify in our m_TypesToInteract which kind of collisions shall be ignored by our later implemented inherited subactors.

Let’s take a character for instance:

class Character : public Actor
{
 Character(const std::string& name, CollisionBody* body)
 : Actor(new Actor::CollisionProperties(Actor::character, body, 3, Actor::character, Actor::enviroment, Actor::projectile), Origin), m_CharacterName(name)
 {}

 std::string m_CharacterName; 
};

This class get’s all its features like update, draw and move from our Actor class, but it specifies which kind of actor(Actor::character) we got and which classes can collide with our character (other characters, environment actors and projectiles). This class got close to all functionalities a character needs (motion, collision, updates etc) but it remains pretty slim by now.

Okay that was a whole lot of stuff. Now we got close to all components we need for our collision together. There are only a few little things missing:

A little event class and an inherited collision event.

class Event
{
public:
 enum Type
 {
 collision
 //...
 //Some Others...
 //
 };

Event(Type type)
 : m_EventType(type)
 {}

Type GetEventType()
 {
 return m_EventType;
 }

private:
 Type m_EventType;
};

class CollisionEvent : public Event
{
public:
 CollisionEvent(Actor* a, Actor* b)
 : Event(Event::collision), m_ParticipantA(a), m_ParticipantB(b)
 {}

Actor* GetPA()
 {
 return m_ParticipantA;
 }

Actor* GetPB()
 {
 return m_ParticipantB;
 }

private:
 Actor* m_ParticipantA;
 Actor* m_ParticipantB;
};

Since you are pretty smart guys, I am pretty sure I won’t have to explain this classes to you because they are actually pretty simple so I will go on with a simple usage example of the collision eco system we just created. I will leave or actor/character creation and focus on the collection of collision events per frame.

class Engine
{
public:
 void Play()
 {
 while (m_Running)
 {
 Collision();
 Update();
 Draw();
 Present();
 }
 }
private:
 void Collision()
 {
 for (unsigned int currentActorA = 0; m_ActorPipeline.size() > currentActorA; ++currentActorA)
 {
 if (m_ActorPipeline.size() < 2)
 {
 return;
 }

for (unsigned int currentActorB = currentActorA; m_ActorPipeline.size() > currentActorB; ++currentActorB)
 {
 Actor* a = m_ActorPipeline.at(currentActorA);
 Actor* b = m_ActorPipeline.at(currentActorB);

if (a != b && a->IsColliding(b))
 {
 m_EventPipeline.push_back(new CollisionEvent(a, b));
 }
 }
 }
 }

void Update()
 {
 std::for_each(m_ActorPipeline.begin(), m_ActorPipeline.end(), [](Actor* actor)->void{actor->Update(); });
 }

void Draw()
 {
 std::for_each(m_ActorPipeline.begin(), m_ActorPipeline.end(), [](Actor* actor)->void{actor->Draw(); });
 }

void Present()
 {
 //Some Stuff...
 }

 //...
 //Some Stuff...
 //...

 std::vector<Actor*> m_ActorPipeline;
 std::vector<Event*> m_EventPipeline;

bool m_Running;
};

Okay, what do we got here. An Update() function, a draw function and our present function. Pretty basic if you ask me so I am going to leave them out. Collision().. well, that’s the interesting part. In this function we are handling our collision and there we will create our CollisionEvents and add them to our EventPipeline.

Basically we are iterating through out actor pipeline and we check our actors for collisions. If we detect a collision (remember, we specify which kind of actor may collide with which other types.), we will save a CollisionEvent with the two participating actors to our EventPipeline. What you will do with them from there on is no longer my concern since that is not part of this tutorial/article 😉

Puh, that was a whole lot of info I pushed out there. I hope some of you can get some helpful information out of this article. But hey, I know there is a lot of optimization potential in this code but optimal performance wasn’t the goal I wanted to archive with that.

The thing I like most about this approach is the little effort you will have to put into changing this one into a concurrent environment. Basically you have two ways of doing this:

First (and less effective way): You could create a task for every collision check and hand this task over to a thread pool to collect the results in future objects and process them later.

Second: You could add a pipeline for every type of collision object that you have a pipeline for environment actors, one for projectile actors and for each pipeline an own EventPipeline and so on. This way you could process one pipelines per thread and merge the events together in the end. (That’s how I would handle this, but I would handle the collision threads in a pool anyway.)

I hope you liked today’s post, that’s all for today. Have a nice day/evening whatever 😉

Advertisements

Concurrency the little bitch

Hey folks, todays post will feature some ideas, advises and conclusions about task-based concurrency programming (mostly in C++).

First of all, what actually is task-based concurrency? If it comes to threading there are basically two and a half approaches you can choose from: multithreading, multitasking, – multiprocessing.

Multithreading: This approach relies on multiple threads on which the developer can spread his workloads to reach an even resource usage and optimal performance. This approach is very low-level and requires a lot of knowledge and care of the person who is coordinating the threads. He always have to know: How many threads do I have, which threads are doing what and also (he better knows) where his threads are running. (On which cpu core for instance)

Multitasking: This one is a more high-level approach. There are some ways to get things done here. The first way: thread pooling. The developer initializes a pool of threads which keep active after they finished their work so he can pass them tasks and don’t have to create new threads all over. He (usually) don’t knows which thread is executing which task (and he also doesn’t care about it) since he just queues tasks up in the pool and the pool decides where they are going. The Second way: One could use wrappers like C++ std::async. Asyncs are (kind of) used like a thread pool. There is simply one difference. Not the developer but the “std::async framework” decides where or how the tasks are executed. If you hand a task to a std::async it could also be executed on the same thread where the result is required until you don’t explicitly tell the async object to behave another way.

Multiprocessing: You spawn multiple processes and let them communicate with each other. You are (kind of) running multiple programs wich do multiple tasks.

I will focus on multithreading/tasking in this post since I have little to no experience with multiprocessing.

Okay, this might sound like you have very little differences from multithreading to multitasking with the exception that multithreading seems to be more work. And in some way, this is actually not to far away from reality. But, and here is the point, there are reasons for both to exist.

A Realworld example for multithreading:

MessageLoop and GUI/Game thread. Let’s consider we have the following code:msgloop_m

We have our main thread which is basically our main function and we have our game thread, which is spawned and will run until the main thread exits it. The only communication between the two threads is managed through the function calls on the game object and the join on the game thread.

And an example for multitasking:update_m

We have our game thread which does some logic and which is containing the game loop ( run() ) and a thread pool which is executing little independent tasks (in this case updating actors) which won’t report back to the game thread.

Alright, let’s see: On our msgloop/gamethread example exactly know which thread is dealing with which piece of work (main() with the msg loop, gameThread with the gameloop). But how does is look for the update example? Well, until we try to figure out which thread of our pool is executing which task we would have to call any kind of thread identification from our task, so simple we don’t know who is who.

And these two examples are good for two things: Giving you guys an example where which approach may fit and giving you an example how these approaches are working.

In example one each thread executes some work completely independent from each other and sometimes they communicate to trigger actions on the other one which is basically a simple event handling pattern.

In example two one thread is creating tasks, the others are just “consuming” the tasks the game thread generates. That’s why it’s called the producer-consumer pattern.

Both of those patterns are suited for different use cases as you might recognize. The first pattern is very handy if it comes to things like controls or long-term work wich can be handled parallel or any kind of input loop or audio output, the producer-consumer pattern on the other hand is better suited if you need some small pieces of independent work to be done in parallel to the work of your long running other threads, like drawing, animation updates or simple outputs.

The p-c-pattern benefits a lot from lock free tasks but suffers even more if you need to synchronize the tasks you are pooling, since if you are locking a pool thread, you also lock some future tasks from being executed while you can easily create a new worker thread if you are managing your thread lifetimes on your own.

The best performance you can reach with a thread pool depends on the continuous and spike free stream of tasks you assign to your pool. Let’s display this in a little image:

queue_opt

In this image we got 4 pool threads which are executing work and 4 more tasks which are queued up. The next step would be each thread would grab one tasks and the queue would be empty again (or 4 more tasks could be queued). Pretty optimal isn’t it? All work is getting done fast and clean.

And this is the way you won’t like it:queue_erro

Again, 4 threads, but this time there are 6 tasks scheduled. Now let’s consider 4 are executed, 2 remain in the queue 5 more are getting added. As you might recognize (easy calculation 6 – 4 + 5 = 7) now we got 7 threads in the queue. And that’s the danger with pooling up threads and using task queues. If you throw too much work at a pool which is to small you will generate a growing backlog which will hurt your performance pretty bad. And that’s the reason why the std::async object has the option to spawn additional threads. Basically it’s the hybrid from pool to thread. I personally don’t like it too much since the standard constructor does not guarantee a parallel execution. Nevertheless, with some tricks (like the launch flag) it can get pretty handy since (at least the MSVC++ version) internally relies on a thread pool with the option to spawn a new thread if the pool is under heavy load. I have to admit, I did what each professional programmer would call bad style and implemented my own one with my own rules so I basically know how it will behave since I feel pretty confident with C++ as such but well that’s nothing I can recommend to others…

Ok, that was tasking, threading on the other hand needs a lot of synchronization to work well and sometimes it might be better for your performance since you don’t have to rely on such high-level constructs like async or pools, but well… it’s pain in the ass to get it working as intended. Your parallelization is good as long as you don’t need to access resources from multiple threads but even then, you won’t block other threads from spawning. You always have to remember: If you try to access a locked item, actually your program gets serial instead of parallel. The trick is to get your work lock free and good timed. Try to split task well thought to threads to minimize data sharing between threads and you will se a huge gain.

Usually I would hand you a picture about regular threading now but this time I decided to simply leave it be since in my opinion you can imagine it pretty well your self.

Try this. You got a railway with a crossing in the middle where the rails change the sides. (Don’t ask why, they simply do.) Now you have a train on each of the rails. Well, one of them will have to wait until the other one is passed since they don’t want to crash. And that’s exactly what your locks do. Now imagine you would do those change-of-side very often. The trains would take a lot longer to the end of the track if they would try to go parallel as they would do if they would go one after another since both could go, none of them had to wait.

Super beautiful metaphor of mine with one simple conclusion. Sometime it’s better to go for single threaded application instead of forcing threading into a super complicated program with a lot of locking work to do.

 

I hope this one were helpful to some of you. If you have any ideas, suggestions or criticism, feel free to comment.

It’s a start

Today I finished my first little animation. It may look a bit awkward, but I am pretty satisfied for my first animation and happy that is does not look completely stupid, well It’s a start.

Say hello to Tiki-Jack.

TikiJack1_0

I also started to develop in Unity and by now, it’s really nice as far as I can say. A lot of workflows aren’t new to me and the engine is actually pretty handy. I am looking forward to show you guys my first “real” game in Unity. But until then I will continue practicing drawing and designing.

That’s all for now. For those who are interested, some date next week I am going to release some build suggestions for gaming pc since Ryzen 5 is released and in my opinion it’s a perfect time to give some hints since I can take Vega into the picture later.

It is something

Todays post won’t feature a lot of wise words about technical stuff. Today I am just going to line up some “game” projects I made to give you some hints where to start. (Ofc. that’s not all stuff I made, but it covers stuff from different difficulty levels of development I passed through)

The sprites (and meshes) you see are free ones from different websites, please don’t ask me where I downloaded them, I can’t remember anyway (meshes aside… they are from mixiamo.com.)

The first game project I started has been my biggest mistake in this area… starting with a 3D game while having no idea of DirectX/OpenGL or any other 3D API. For this project I started to learn how to use DirectX with C++ and this almost stopped me from continuing my efforts to get into game development. I never finished it.

3D game

The second game I started were better straight through but still not the best choice I for a beginner since I also used plan DirectX and C++, but the game made it to an actually pretty well working status. (for the beginning)

invaders.gif

After this game I decided to go back to more basic games which are a bit less complicated so I can focus on more Important things like how to build an easy-to-use gamedev framework for minor tasks, and that’s where this attempt came to life:

snake

This very basic snake clone is made with GDI+ and runs in the windows console. I decided to go away from plain DirectX since I got the concept, I got the basics and I wanted to see more progress instead of pumping a lot of time into understanding the API. This snake game later became my multithreading test playground. Actually snake is to simple to use concurrency in the implementation but it were a good starting point to learn what kind of workloads you can spread best over multiple threads.

Later on I continued with this one:

tron

That one were my first step back to actual sprites instead of just drawing pixels. Not much to tell about it, tron is very simple so I were able to concentrate on implement a sprite system into my little framework and start using frame animations.

After tron my next project were a little tetris clone:

tetris

Actually I made this just for fun.

And my latest project in progress is a 2D shooter I am currently working on. Atm. I got dummy sprites which look like shit but which are serving their purpose and I am working on a level from file system so I load complete levels from files.

scroller

Well that’s all I made so far. After the sidescroller attempt I am going to start over with Unity3D for some more serious stuff. Until then I am going to practice with mini games and things like my little physic framework.

I only can show you the mistakes I made in the past. Don’t start to complicated. I can’t tell you often enough. Starting with DirectX and 3D just were too much. Start simple and if you got a feeling how stuff is working you can start to do more complicated projects.

If you feel lost, it’s ok to take one step back to get another 10 steps forward in the future. Just don’t stop trying as long as you have fun doing what you do.

That’s all for now guys.

Of threads and games

Hey guys, today’s post will address threading in video games.

In times where multicore CPUs are pretty common, multithreading becomes a really obvious choice for performance improvements in video games. But multithreading isn’t always the answer. This post is supposed to deal with two common issues I noticed again and again over the last few years.

The first one: Improving (render) thread counts in .ini files of video games to tweak performance.

Well that one might be a bit complicated so I decided to address it first. Sometimes when I read forum entries where people are complaining about bad performing video games, a couple of times someone came up with a lot of .ini tweaks to improve performance. Basically there is nothing wrong with that, but as you might guess already, not all of these tweaks are really helpful. Improving the “render thread count” for instance is not worth it (in most cases). More threads do not automatically mean better performance. Quite the contrary, often this will make things worse.

DirectX x to 11 and openGL aren’t capable of multithreaded GPU/CPU communication (or at lest not very good at it). And that’s one of the core issues. Yes multithreading in games makes totally sense, but only at some very special points and in a “very limited” range. Throwing 32 threads at a game and thinking it will work better is a wrong approach which usually comes from people who have less or no experience with multithreading and/or game development.

Ok back to our DirectX/OpenGL description. I will stick with DirectX in this post since I am more familiar with that, but most of the points will apply to OpenGL in a very close manner.

As I already mentioned: You won’t be able to pass render tasks to your graphics card from multiple threads at the same time. This leads us to a more or less annoying issue.

In a beautiful world, filled with rainbows unicorns and a multithreaded D3D(11)DeviceContext, rendering would work like this:

ParallelDraw

Sadly our context isn’t threadsafe. What does that mean? Well, it’s actually not very complex. As you can see in the picture above, if the world were a better place, we could draw completely parallel but in reality things behave a bit different. If we want to access the D3D11Context, we will have to hide it behind a lock to serialize the access, otherwise our game would crash or at least begin to behave in a strange way. That means our rendering would look like this:

Draw

You might recognize that this will prevent us from taking advantage of our multithreading capabilities in our game, even worse we are facing the threading overhead (yes, spawning tasks and assigning them to threads also takes time) without getting any performance benefits –> our performance decreases. And for the DirectX pros who are laughing at me right now: Yes I am aware of Deferred Context and CommandList but this image is thought to simplify the whole thing for those who have no experience with DirectX since basically you giving tasks to a threadsafe container and execute them all in one thread with an immediate context is the same principe as seriallizing the draw-calls per mutex. The immediate context will execute them one by one anyway. (remember? we are still in DirectX 11)

This might sound like: Multithreading in games is bullshit…. It isn’t. There are other ways to bypass this issue.

Things like animation updates, collision, position updates, sound, physic or even preparing draw-calls can be paralleled very well (that’s why people might have multiple threads for rendering). This is an example how a parallelized frame could be prepared/executed:

frame

This pretty much shows how I am processing my frames (with sometimes more, sometimes fewer threads… it depends on the complexity of my update/collision functions). And yes, sometimes I am doing my collision check twice, first at the beginning of my ->Move() function, one time after my ->Move() function. (One may argue about efficiency but that’s not the topic of this post).

Okay I think this gave you a little insight how multithreading could be implemented in a video game and wich problems you might have, but that’s not all folks.

As a little conclusion you might take the following. There are developers who use multiple threads for graphic tasks (as I already mentioned, to prepare their draw calls), but that’s not the rule (at least as far as I know). And even if there is a render thread counter inside of an .ini file, leave it how it is. In the best case you get 1-5 FPS. In the worst case, the engine can’t handle the increased parallelization workload and your game looses FPS. Developers do not chose this numbers for fun. They know how their engine works (at least I hope so), so they probably will know better how many render threads will be appropriate.

And this leads me to the second issue (I promised you two issues 😉 ):

It’s not always a good idea to throw threads on a game. There are beginners out there who feel forced to use multithreading in games since there are multithreaded CPUs out there. That’s not always a good idea. If you have a game with simple physic, simple collision, low graphics (that does not mean bad graphics), you don’t want to throw multiple threads at it. Take a very basic tetris-game for instance. It could look like this one:

tetris

Why the hell should you throw multithreading at this? Actually you will put a lot of work into getting the same if not worse performance out of your engine just to say: Well it’s multithreaded. I know, this is a really trivial example but it suits my needs. Most likely you won’t need multiple threads in your game until physic enters the field. And that’s another point. I can’t tell it often enough… Don’t use too much threads! Maybe you remember the little physic framework I introduced in my last post. It’s back.

less threads

In the right upper corner you see the FPS. (Yes, it’s running at higher FPS than the gif I uploaded does.) Atm, the engine is running at 4 threads and everything is fine. And this happens if you add another 2 threads to the pool:

more threads

Again, FPS counter upper corner. Well you might recognize that the FPS decreased a little bit. (basically 1 fps and the FPS are at a lower point in the average) One FPS might sound like absolutely no problem (and that’s actually right). But it would be performance you might get for free. And if I would increase the thread count even further, the FPS would decrease even wider. The impact on this example might sound negligible, but you are forgetting that this is a really simple example. The framework is very basic and there never were performance issues by now (unless you triple the square number). If the performance draw would increase, the FPS loss might increase as well. That’s the reason I recommend finding the sweet spot where you get the best FPS with as few threads as possible.

That’s all for now, I hope some of you may be smarter than you were before reading this post.

Physic frameworks from hell

Hey guys, let’s get straight to the point. I am developing an own small game engine at the moment (the physic framework of the engine in particular) and I wanted to give you some opinions about rolling your own engine.

This post won’t feature any code since I don’t want to bore you with C++.

My first advice to you is: If you want to understand features which are implemented in other engines, don’t try to roll your own ones to get a feeling why they might be designed like this. You will get frustrated, I guarantee it. That’s a totally stupid idea (that’s why I am doing it 😉 ).  Try to stick with the documentation and tutorials of the engine you are using and you will come out much wiser than you are now.

Well this advice only addresses big features and core libraries, it won’t hurt to take plain DirectX (or at least XNA) to look how to implement a little render backend (and if it’s only for drawing lines). When I tried to work with DirectX first, I was really confused and experienced a rollercoaster of emotions from joy to hate to despair and back to feeling like a god when my first mini-game worked (a space invaders clone). But at least I understand the basics now.

Drawing lines with DirectX is no big deal. You initialize your components (swap chain, dxdevice, dxcontext etc.), you take some vertices and put them in the buffer and then you swap the buffers. But you won’t know that if you haven’t at least read a bit about the basic functionalities of DirectX and co and the naming scheme of DirectX is hell (at least for me). What you shouldn’t do (at least if you aren’t one of those mega mind programmers who read something and instantly know what to do…. I am not on of those guys…).

Well that leads me to my next advice. If you want to develop a serious game and you not part of an AAA studio you don’t want to roll your own engine. Trust me, it’s not worth the trouble. There is a really good chance someone somewhere did id better anyway.

Unity, Unreal and co aren’t around for all this time without a reason. They are well-tested, good developed and very comfortable to use. It’s ok to roll your own engine if you have the experience, time and money to do so, but overall you will be doing better with a third-party engine as a beginner and/or indie developer.

Well I can tell you a lot….. really I can… and you know what? I do! And you know what’s next? I will give you an example how annoying it get’s to roll your own engine features. That’s where my little physic framework enters the game.

physic

It’s nothing big, it’s nothing shiny but it’s mine, and I love it for being mine. But here comes the problem…. While watching the gif you may recognize some of the little squares vibrating instead of coming to a resting position. I recognized it to late and that’s where the trouble started… It took me 4 hours to figure out what’s wrong with this stupid physic calculation. 4 hours of my life.

When I found the issue I got mad. Really mad. Basically when I calculate my speed I round to whole numbers since my minimal motion range is 1 pixel. And that’s where the problem was. By rounding the numbers the falling speed of my squares sometimes if I hit an unlucky number remain at 1 and go down to 0.9 and then they get rounded back to 1. 4 hours for this little shit of a bug. And this is actually a very simple (and not very realistic physic) framework.

I am doing this for training purposes. I am planning to get my hands on Unity 3D (yes I could also start with Unreal or s.th else but I decided to go with Unity). But until I start using a “real” engine (every engine is a real engine… is it a good one, that’s the right question) I want to learn a bit about general design possibilities of engine features and since I feel pretty secure in C++ I decided to do what I told you not to do. And you know what? Sometimes I hate my self for not listening to my own advice. Actually I could be much smarter than me…

Ok enough trolling for one day, serious guys. You will do yourself a favour if you use a third-party engine. If you learned how to use them, you can start customizing them and if you learned how to do that, it might be a good idea to roll your own engine. But until that happens, the chances are good that you will destroy your motivation with rolling your own stuff. At the very beginning I got really frustrated (exactly by doing this kind of mistakes) and stopped trying to learn more about game development. I had a functionally little 3D graphics engine (very basic, bad graphics etc) but it was a start… and then I stopped working on it.

Now I went back to a little 2D engine which is much easier and is really enough to learn the basics. Sometimes even this is a start. If it get’s to hard, go back and start with something smaller. Just don’t stop trying if you really want to do this.

I hope I helped someone with that advice.