How to structure a game engine.

Started by
24 comments, last by speciesUnknown 16 years, 2 months ago
Quote:Original post by ChugginWindex
Finally, Captain P I like your idea of building multiple games until I've refined my code into something like an engine, my only problem with that is that I've written small games before, I could write pong or tetris in a day or less depending on how much to add, the problem is that doing so would mean deliberately ignoring certain things such as a manager for input versus just checking for 4 or 5 keys that only work in THAT game, or something similar for other aspects.


One thing to remember is that just because you only need to check 4 or 5 keys doesn't mean you should do it in some hard coded manner. Why not create a system to manage keyboard input. Create commands for the keys pressed which can be remapped to different keycodes. There's lot of things like this which even a game like tetris if you do it right can then be reused in other games.

This is what is meant by building games not engines. Build the proper systems and controls but concentrate on the game at hand rather then concentrating on an engine that can be used for any game.

Another thing you could try doing rather then building an engine is a map/character/terrain/etc editor for your game, this can lead to needing a lot of the same systems which a game will need and provide a fullfilling result when you complete it.

Advertisement
Quote:Original post by Dancin_Fool
One thing to remember is that just because you only need to check 4 or 5 keys doesn't mean you should do it in some hard coded manner. Why not create a system to manage keyboard input. Create commands for the keys pressed which can be remapped to different keycodes. There's lot of things like this which even a game like tetris if you do it right can then be reused in other games.

This is what is meant by building games not engines. Build the proper systems and controls but concentrate on the game at hand rather then concentrating on an engine that can be used for any game.

Another thing you could try doing rather then building an engine is a map/character/terrain/etc editor for your game, this can lead to needing a lot of the same systems which a game will need and provide a fullfilling result when you complete it.


Also true. I'm starting to regret saying that I was trying to build a 2D engine in my original post. There is a game that I am working on as a proof that I can design something more than just pong or tetris, and now I'm trying to write the inner workings of the game, in a more professional situation what I'm trying to write would be the engine; in my case it's just what makes the game work I suppose.

I've thought about what I would need, and I'm currently trying to develop those pieces for use in the game "engine". Like I said, it was more getting those pieces to function without knowing everything there was to know about the engine that was starting to confuse me, and the posts in this thread are certainly shedding some much-needed light on the subject.

Didn't mean to insult you ;)

Using your example of render data, maybe this makes it a bit clearer:

Think of the system as data which is held in parallel, suited to the needs of each subsystem (render, control, model) and is linked by some common denominator (like an ID or whatever).

So, the renderer has it's own list of data (sprite, spatial etc.),
the view has it's own data (which object is controlled by which controller),
and the model has its own data (the objects).

Everything is tied together by a high-level object containing the game loop,
which knows all the subsystems and talks to them directly (by using interfaces rather than classes).

So, there would be three Interfaces for the three subsystems:
IRenderer, IController, IModel (or, IPresenter, IView, IModel)

The controller would know the model (by using the IModel interface) and the renderer, the renderer would know the controller.

The model would need to know the controller, too.

On this level, the three subsystems would be able to communicate changes
without knowing the classes of the other systems - as long as they implement their respective interfaces, everyone's fine.

So, if a tank was destroyed while it was visible, the model would notify the controller of the fact that that tank was destroyed.
The controller would notify the owner of that object (let's make it an AI player) that is was destroyed, which will delete it from it's list of inventory.
The controller would also notify the renderer about the destruction of that tank, causing the renderer to remove the corresponding sprite from its own data.

As you can see, all subsystems keep their own data, and synchronisation between them is done via messaging (method calls, events, whatever).
The systems can interact with one another, but do not have to know about the other systems' data or implementation details.

In the end, you'll have a robust system, that is easily understandable and is less error-prone.
Plus, you can easily modify your renderer without it affecting the game model representation of a tank!
Using your brain doesn't hurt at all.
Quote:Original post by lucem
The renderer is responsible for drawing everything, finding the right sprite to draw, and all stuff graphics.

So, how to do that?

Well, there comes in an architectural pattern that's called MVP.
Model View Presenter is about a three-tier design where there is
(in this case) game data (model), a renderer (presenter) and someone
in the middle that intermediates between them (view).

So, in your case, the view is the center of all attention, and it interacts with the model data, and is interacted with by the presenter.
The presenter doesn't talk to any game object in the model tier.
It gets all that there is to know using a defined interface that is implemented either by view alone (using delegation of certain request to model) or by view and model.

So, each system is responsible for one task only, and using interfaces here provides you with the possibility of e.g. re-using the renderer in the next game, while the view and the model change.


The MVP pattern can indeed be used, but to correct Lucem, the View corresponds to the renderer and the Presenter corresponds to the intermediary.

MVC is another useful pattern for entities in the game world. MVC stand for Model-View-Controller, where model and view are basically the same as in MVP, and controller corresponds to an object which directs the behavior of the model. I've used this pattern in my projects to implement AI and player input as entity controllers. Often times in MVC, the View takes on many of the responsibilities of Presentation (mostly because MVC addresses a different concern than MVP) but there's no reason you can't have a Presentation layer applied to MVC, I guess you might call it the MVCP pattern.

throw table_exception("(? ???)? ? ???");

Oh, thanks, I always get those two wrong :)

MVC is mainly used in GUI, half of Windows consists of that pattern -
but, the problem is, MVC makes it hard to correctly identify the responsibilities, as ravyne pointed out.
MVP makes that a lot clearer, IMO (though both are related, it does make a huge difference after all).

By the way, you shouldn't worry too much, write your game.
Just put some thought in advance on how you can deal with different responsibilities of different "components" of your engine.
In the end, there are only two rules:
- Make it fun. If it's not fun, it's not a game.
- Keep it simple.

Anything else is subject to discussion, and there is no clear wrong and right.
It all depends...
Using your brain doesn't hurt at all.
Alright, this is starting to make a lot more sense now. I just have a few more questions:

When I think of interfaces I think of the one such as iDirect3D9 which as far as I know there can only be one copy of (and then you call CreateDevice() and get a pointer to the device and so on blah blah blah). How would I do this with the IModel, IPresenter and IController interfaces though? Say I want to put a tank on the screen, if I have this right, would I just have something like a Tank class, that has the name of the texture to use, the world position, health of the tank etc. Then the IModel interface would notify IController of the Tank object's world position and health, and IController would notify IPresenter on stuff like whether to draw the texture or not or if it was destroyed. Also, would the IModel just notify the IController->IPresenter right away of the name of it's texture so it could be looked up, or would the texture be accessed / defined a different way.

Am I getting this at all? (I really have not found any info on the web that is half as in depth as you're describing, so thanks, this is all new to me.)

-Also, I've actually got a bit of experience in UnrealScript and modding for Unreal Tournament 2004, and a lot of what you describe with this MVC and MVP design actually seems very similar to what they use for managing most of the "actors" in the engine. That alone is making this a lot more understandable (unless I'm totally wrong somehow and the three are unrelated)
Actually, you'd have different sets of data.

For convenience, you'd have a factory of some form which you tell to build a new tank.

This would create the game object "tank", attach it to some owner (AI, human player, whatever) and tell the renderer to create a new sprite for a tank, along with the initial data (position etc.).

How this creation of objects is done would be up to you.
You could create everything in there and "inject" it to the subsystems, or you could delegate object creation to factories inside the subsystems which will do locally (and transparently).

After that, all three subsystems would have their own "tank" object, having the data they need.
So, one monolithic "tank" is split up in 3+ smaller objects that only contain the data that's needed for the specific subsystem.


iDirect3D9 is not an interface, but an adaptor class (see the adaptor pattern) -
it presents you with some of the functionality Direct3D provides, and gathers them in one place.
So, it is an interface, but on a larger scale. It's an interface for a lot of other classes, not only one.
iDirect3D9 itself would talk to a lot of other classes inside the D3D library, which you do not have to know, so it hides this information from you and presents you only the things you need to know.

In a smaller scale, the MVP works the same.
For your game, you might implement all your game code in "model", and use renderer and controller (or presenter) as adaptors to the underlying subsystems.

The Unreal Tournament thing:
Yeah, believe it or not, that's how things work.
Every good programmer and system architect out there has read the GoF "Design Patterns", and knows how to use them.
You come across patterns everywhere today - even inside programming languages and their runtime environments (Java and .Net are prominent examples of that).
Using your brain doesn't hurt at all.
I guess I don't understand why something like IModel would store a smaller class that only had information about a specific tank object such as the health and world position rather than just storing a pointer to the actual Tank object and relaying the info to the IController in that way. I also don't understand why IController would need to store it's own information if it's purpose is to coordinate what IPresenter does based on what it determines from IModel. (I suspect I'm still not grasping something here for some reason, usually stuff like this doesn't take this much explaining for me).
This is going to be my last post for now, I need to get some sleep...
it's past 3 am and at 10:30 I need to write an exam.

You could mail me at sebastian.porstendorfer@web.de if there are any further questions, and I'll try to answer them.

The reason for separating the data is actually two reasons.
First, game objects ( as in model ) do not have to know implementations details like what texture they use, or their position on the screen.

Second, if for whatever reason you decide to change your renderer, you would have to change your "tank" class as well.
( Like, switching from SDL to SDL+OpenGL, you would suddenly have to have normal vectors inside your game model... )

Thus, data is split up by responsibility of the objects that use it.
It just allows for greater modularity and flexibility (what if you decide to support multiple renderers? dx9, opengl, software rendering...).

Plus, if you've got everything in one class, and you derive from that class, everything is derived, even the things that are general enough to not have to be derived from - a sprite is a sprite, you adapt it to your needs by using its data, but you hardly ever subclass from it.
Using your brain doesn't hurt at all.
So to clarify, the responsibility of the Model is to hold the data and rules that make a tank a tank for example. It has nothing to do with its representation, such as its graphic or 3D model, because those things don't make it a tank. To borrow a phrase "If it walks like a duck and talks like a duck, it must be a duck." -- notice no mention of it looking like a duck? The duck is defined by a function of its behavior rather than its appearance. So a Model in the MVC/MVP patterns is much like a scientific model in that it is an abstract representation, rather than a tangible one.

For a tank, the Model holds things such as position within the world, orientation, damage percentage, ammo count, etc. It also has an interface which allows its various externally-visible state information to be queried. This is how the View and/or Presenter are able to build a visualization of the tank object -- They ask the Model for its position and orientation, combine that with what they know about what a tank looks like, and draw it appropriately. Another portion of the interface exists to allow the Controller to issue high-level commands like "drive to this position X, Y" or "Fire on this target." The controller doesn't need to tell the tank how to move, how fast to go or how steep of a hill it can climb. Similarly, it doesn't need to tell the tank to deduct a shell from its ammo count when it fires because the Fire() command knows this, and also knows that it can't fire unless it has ammo. You get to choose exactly how high-level the commands that the controller will issue will be, it might be a valid choice to implement path-finding as part of the Controller for instance, in which case the movement interface for the tank Model would be at a lower-level than had path-finding been implemented within the tank Model itself. Either approach is equally valid and the conditions and assignment of responsibilities will dictate which is most appropriate in a given situation. The common thread, however, is that the Model implements just enough "smarts" to
be able to follow the Controller's commands and maintain a consistent internal state; nothing more.

Although this Wikipedia article has a heavy GUI slant (that is what the MVC pattern was designed to address, after all) its not hard to read through it with a mind for game entities and other game systems, and you'll come to understand that it applies 100% as is.

This image also has a GUI slant, but is equally relevant to game systems. Even the portion where the View and/or Presenter communicates the "User Gestures" to the Controller is valid. For example, it can be interpreted as a user click into the view port where View and/or Presenter have the responsibility of identifying what was clicked, since only they know the screen coordinates of UI elements or game units.

It also shows the possibility that a Model can push updates to the View and/or Presenter. Many games implement a pure poling system, but its easy to imagine that rare state changes or those that affect the internal state of View and/or Presenter might be pushed, rather than having the View/Presenter query the Model for all possible state changes every single frame.

throw table_exception("(? ???)? ? ???");

This topic is closed to new replies.

Advertisement