Jump to content
  • Advertisement
Sign in to follow this  
Tilt_

Engine Advice

This topic is 2398 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am creating a 2d game engine, and could use some advice / direction on a few areas.

Currently I am using a singleton EventManager class that registers Event Handlers. Event handlers have the ability to send events to the Event Manager to be distributed to other handlers. Events are just structs with the event information and a identifying variable for the purpose of proper typecasting.

My issue is that I have Managers for many parts of my engine like Graphics, Sound, Actors, etc. Currently I find myself holding references between Managers and calling appropriate methods from that reference. This has all of my Managers coupled and makes me feel uneasy for some reason....

My question is would it be better to uncouple all my managers and pass events / processes using my EventManager, or keep my Managers coupled?

If I uncouple I think I will have to use void* and reinterpret_cast calls to properly typecast my event data in some cases, which also makes me feel very uneasy.

Share this post


Link to post
Share on other sites
Advertisement
Here's a good link - http://www.gamedev.net/topic/613027-question-about-managers/

Also might be easier to use C#/Java/Lua if you're just starting out.

Share this post


Link to post
Share on other sites

Here's a good link - http://www.gamedev.n...about-managers/

Also might be easier to use C#/Java/Lua if you're just starting out.


I read through that thread and it is mostly a discussion of whether to use manager's and singletons. I already plan on having one singleton for event management and several managers with sub classes to handle specific engine functionality. I'm just curious in the best practice of communicating between several classes, mainly if its better to hold references between them or use the event system I have implemented. I've heard a lot of talk about decoupling classes and using an event driven approach but I'm having a hard time justifying its use.

I hope that clears up what I'm asking. Sorry if my question was not clear. I have intermediate level c++ knowledge and have already gotten my game running I'm questioning some of my architecture decisions.

Share this post


Link to post
Share on other sites
My question is would it be better to uncouple all my managers and pass events / processes using my EventManager, or keep my Managers coupled?
Whether your different systems are communicating via direct function calls, or communicating via event structs, they're still tightly coupled in either case. The event structs that they can process form an implicit interface, even though you've not actually coded that interface.

Share this post


Link to post
Share on other sites
I think it is good that you feel uneasy about how tightly coupled your managers are.
If you wanted only the sound library you would have to also take the completely unrelated graphics library just because they are bound at the hip by a global resource manager.

If you read the other thread you should have no reason to be using singletons in the first place, and here I can see only that a singleton has actually caused more clutter and harm than good (the standard reason not to use them).

There is no justification for a unifying manager that re-issues calls to other managers.
Why would an object issue a command to the general manager instead of just directly to the graphics manager?
I would also question the legitimacy of having a graphics manager at all. Yes sorting render calls is a valuable feature, but that requires only 1 or 2 instances of a single class which only perform that one task. The same applies to nearly every other sub-system related to graphics.

A sound manager on the other hand makes perfect sense. In most cases you want to just dump a sound into a bin running on a second thread and let it be updated (load streamed data, juggle sound buffers, etc.) on its own without ever having to be concerned with it again.
Let a manager handle that.

But when it comes time to throw a sound into that manager, why not just do it directly?


What kinds of events are you planning to use here? What is your justification for the current system?


L. Spiro

Share this post


Link to post
Share on other sites

There is no justification for a unifying manager that re-issues calls to other managers.
Why would an object issue a command to the general manager instead of just directly to the graphics manager?


Well I was trying to avoid having every Manager holding references or pointers to one another because that seemed cluttered and messy to handle as my program gets larger. Currently every manager is a child of event handler and is able send Events to my Event Manager to distribute accordingly.


I would also question the legitimacy of having a graphics manager at all. Yes sorting render calls is a valuable feature, but that requires only 1 or 2 instances of a single class which only perform that one task. The same applies to nearly every other sub-system related to graphics.


Currently my graphics manager manages my game view and resolution settings. It receives game events for window resize or view movement and updates accordingly. I also have it check whether objects are within the game view for drawing. I'm probably abusing the word "manager".


What kinds of events are you planning to use here? What is your justification for the current system?


Like I said early I'm really just trying to avoid having to reference all my different managers directly because it seems really sloppy and the initialization order is troublesome. Currently I'm using the Event system for user input. For example when the player gives a move input its distributed to my ActorManager to update my player position and to my GraphicsManager to do the same for my view.


Share this post


Link to post
Share on other sites

Well I was trying to avoid having every Manager holding references or pointers to one another because that seemed cluttered and messy to handle as my program gets larger. Currently every manager is a child of event handler and is able send Events to my Event Manager to distribute accordingly.

Every manager should not be holding pointers or references to each other anyway. There is no reason for a graphics "manager" not to live in it's own cave separate from every other manager, and likewise with the other managers.
Avoiding having managers connected to each other is a matter of simply not connecting them to each other.
I guess my last question was meant to determine why your managers would ever need a pointer or reference to any other manager.



Currently my graphics manager manages my game view and resolution settings. It receives game events for window resize or view movement and updates accordingly. I also have it check whether objects are within the game view for drawing. I'm probably abusing the word "manager".


Nothing wrong with having the graphics library keep track of screen resolution, reset the DirectX device when necessary, provide a few utility graphics classes such as render queues, and to provide wrappers for the DirectX or OpenGL textures, vertex buffers, index buffers, etc.
But that really isn't a "manager". It is just a graphics module.

However there is a problem with the graphics module checking for things being within the view for culling.
#1: The scene manager should do this. It knows about each object and stores them in a structure that can provide accelerated culling functions. For example octrees, etc. Offloading this to the graphics manager is asking the graphics manager to do too much. The graphics manager should not be organizing a bunch of AABB's inside octrees and pretending it knows the best way to run over them and render them. The graphics module simply provides a bunch of graphics-related functions and lets the other systems orchestrate the overall rendering process using those functions. The scene manager is the only object that has global knowledge of what is in the scene, so it is the only manager that can perform rendering of the scene.
#2: In its bare minimum, frustum culling is basically checking a bounding box (sphere, OBB, or AABB) for being inside 6 planes (a frustum). Because you only want to do this for rendering, you may want to associate this process with the renderer. In fact, planes, frustums, bounding boxes, etc., are general structures related to general math. Physics simulators want the same information. So these again should be part of some kind of math library, separate from the graphics module.




Like I said early I'm really just trying to avoid having to reference all my different managers directly because it seems really sloppy and the initialization order is troublesome. Currently I'm using the Event system for user input. For example when the player gives a move input its distributed to my ActorManager to update my player position and to my GraphicsManager to do the same for my view.

Normally you will initialize your managers in a specific order during engine initialization.
But here you seem to be talking about run-time order of in-game events being troublesome.
This is caused by a few things:
#1: Again your graphics manager is being asked to do something it should not. The graphics module is not responsible for the view of the player. A camera attached to the player is responsible for the view of the player, and as a child of the player it would be updated automatically when the player moves. The graphics module simply provides a set of functions that allow the camera to set the current view matrix and projection matrix. And the actual setting of these matrices is done by the scene manager. It knows about all of the actors in your scene and all of the cameras. It knows which camera is your main at any given moment. So when you simply tell the scene manager to Render(), it will automatically apply the camera matrices, using the helper functions generously provided by the graphics module, and then cull objects and orchestrate the whole rendering process.
#2: Having a system in which things triggering in a specific order in order is required for it to work is a huge headache. Part of your problem is the entire event system itself.
Event systems have a place in games, but only after you have a huge foundation that can abstract away the event system itself. You need in-game triggers (boxes usually), scripting systems, and a plethora of other systems that help reduce the complexity of the underlying event system. The event system is something you nearly never want to touch directly. For it to be one of the first things you add instead of the last will leave you with a lasting and hard-learned lesson.
There are of course simpler event systems that you can manage near the start. Distributing input events is simple enough, though I would still look at a different architecture before implementing this, because who is to say the input events should only be sent to the player? But it is okay for starting out.

However from the sounds of it you have 2 problems. Your event-based system has been taken a bit too far, and this is compounded by the fact that you have subsystems handling things they should not be handling.


If you are new to making engines, I would suggest scrapping events entirely. Keep a buffer of the input data and let all the systems access it that need to access it. On a low level, this will probably be nothing, in fact.
As your engine grows you will reach a few more-specialized classes that act specifically as "the player", and then you could add some access to the input from there to control the player (given that the way input affects the player can be overridden).
That way all other sub-systems still have access to input. Such as the menu system, which could provide you with a HUD.
If you click on the HUD, the menu manager can check for itself to see if it has been clicked when it is given a copy of the current input data.

An event-based system overcomplicates this because you also have to register and unregister input targets, such as the HUD and anything else that can take input. When trying to build your final scene you are really micro-managing exactly how the events are distributed, when, why, etc.
Micromanaging is a job the engine is supposed to do, while you the user are supposed to just throw up a HUD, put objects into the scene, and let it rip.


L. Spiro


P.S.: I forgot we were talking about a 2D engine, but nothing changes. Just replace 3D bounding boxes with their 2D equivalents.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!