Friday, January 1, 2016

Game Engine Design 101: Handling Components

Hey all,

It's that time again! I'm gonna post another tutorial on designing your own game engine!

Before I continue, I need to do a shameless plug for my own engine. All of the code that you see in this tutorial can be found here: JFramework

It's open source, so you can poke around as much as you like! If you have a change that you'd like to see done, go ahead and change it! I do ask that if you do make a change, please notify me and make a pull request for me to integrate it into the main engine, you don't have to do this, but I'd appreciate it.

Now, onto the tutorial!

Last time I mentioned what components are and how they work, but how do you manage them? Why, managers of course!

What is a manager? It manages components, or it can handle a certain type of message, or even your levels! When a GameObject creates a new Surface, PhysicsObject, or otherwise, it needs to be registered to a manager. If input is received, it should be sent to a manager. If a level needs loading, a manager should handle it. See where this is going? The possibilities are wide and varied.

For example, do you want to draw an object to the screen? Why not have a GraphicsManager be made aware of the object that needs to be drawn, then during the manager's update loop, draw this object?

--------------------------------------------------------------------------------------
More Advanced Note
--------------------------------------------------------------------------------------

One could argue that the object could be responsible for drawing itself, but a solid counterpoint comes from performance. During the draw phase for your game, it is expensive to continuously make draw calls to your GPU, so the idea is that objects that use similar textures to be drawn during the same stroke, using THE SAME DRAW CALL (it's that important.)

This is known as Batching.

Because of this optimization, we set the drawing responsibility to a manager instead of the object itself.

We can go over this is a later post, in more depth. For now, trust me. Just do it.

-------------------------------------------------------------------------------------

Try your best to keep the logic for each manager as separated as possible, try to separate them by responsibility. PhysicsManager handles PhysicsObjects and interactions between them, GraphicsManager handles textures and drawn objects, InputManager handles input etc. etc. You get the point.

So, from the earlier example, how do we create a GraphicsManager and draw objects? Well, let's take another example from JFramework. First, we need a concept of a manager, what sorts of things does it need? An update loop? A unique identifier for quick searching? The ability to send and receive messages? An example that would cover all of these cases looks as such:

Note that we created this as an abstract class.

Now that we know the base, for the GraphicsManager itself, what does it contain? Is it also abstract? Is it aware of what objects it can draw? What else can a GraphicsManager do? Should it be able to translate an object's coordinates from relative (Camera) to an absolute (World) space and back again? Should the manager be aware of what screen it is drawing to?

Oftentimes, it is good to ask yourself what sorts of things an object can do, in this case, a manager, and understand the responsibility before you write any code. Always make sure that the responsibilities of your manager don't overlap with other managers or helper classes. Follow the "Don't Repeat Yourself" (DRY) principle.


This GraphicsManager can handle all the cases asked above, plus it can manage textures! What I mean by managing textures is that our GraphicsManager can save textures by an identifier (usually an int) so that any objects that use the same texture file can just use this cached texture. The update loop, thanks to knowing what objects to draw and the screen to draw to, looks this simple:


Now, when we want to perform an operation on all objects in the game, we can easily do so through this manager! Thanks to managers, we have increased the awareness of objects currently running through our engine, and also segmented atomic pieces of logic away from each other. (By atomic I mean graphics, physics, etc.) Yet, GameObjects are only aware of themselves and the components that they contain. The use of managers is clean and efficient. There are other ways, but JFramework uses this system at its core.

Now, for handling all of these managers, that part is completely up to you! I advise creating a class that has awareness of its managers, and just calls an update loop for them every frame. I will leave that as an exercise for you, or you can cheat and look at how JFramework does it. (GameApp.h and GameApp.cpp)

If you choose to do the exercise, just think about how the update loop for a manager looks, and now do that for your managers.

Next time, we can cover the basics of object positions. If you have any questions or comments, let me know!

PS I'm still looking for an artist for Chang-e, send an art sample to jimbobkr@me.com, standards aren't high, will pay.

Thanks,
Jimmy

No comments:

Post a Comment