🔒 Locked
Engine Architecture
Advertisement
Original Post
I would like to write a flexible and (if possible) fast 2D Engine. It should be flexible enough to make it possible to create RPGs as well as RTSes using it.
Are there any good tutorials on structuring an engine (perhaps even an engine like this).
And do you have any good hints on what to look out for and on the dos and don''ts ?
I had the same problem when I started my 2D Engine, I wasn't sure what was the best way to structure it. I ended up coming up with my own design. It still might not be the best.
The basic class structure of the engine is as follows:
CEngine - contains engine functions, ex: debugging.
COS - contains general interfaces for creating windows, window objects, etc.
CRender - contains general interfaces for rendering graphics.
CScript - contains general interfaces for using a scripting lang.
CFile - contains general interfaces for loading different filetypes.
CGame - contains any game specific functions.
[edited by - Dustino on May 18, 2003 6:08:11 PM]
The basic class structure of the engine is as follows:
CEngine
|
COS --- [Class for OS, ex: CWin32]
|
CRender --- [Class for Rendering API, ex: COpenGL]
|
CScript --- [Class for Scripting Language, ex: CPython]
|
CFile -- [Classes for Filetypes, ex: CXML]
|
CGame
CEngine - contains engine functions, ex: debugging.
COS - contains general interfaces for creating windows, window objects, etc.
CRender - contains general interfaces for rendering graphics.
CScript - contains general interfaces for using a scripting lang.
CFile - contains general interfaces for loading different filetypes.
CGame - contains any game specific functions.
[edited by - Dustino on May 18, 2003 6:08:11 PM]
Three words - modularity, loose coupling.
The first place to start is to stop thinking of a graphics renderer in terms of game genres. I think it''s safe to say that the ultimate goal of any graphics engine is to put pixels on the screen.
From there, you can look at what all games have in common from a graphics perspective. This will help you to get a general idea of a framework to build around the raw pixel output. Getting this far alone will enable you to make games which require no specialization.
Once that is done, then you can start looking at what different genres require to extend the framework, and do so only as needed. That is, if you are the end-user of your engine, don''t worry about supporting a specific genre until you want to make a game from that genre.
This is a very simple process when you break it down in steps like I have above, but it becomes convoluted by worries about which class should go where or do what or extend what or... If you can learn to think modularly, you will be able to better design modularly.
And to truly achieve flexibility, loose coupling is essential. The more your objects depend on each other, the less flexible your engine becomes. When you are in the process of identifying the vaious components of your framework, try to visualize them as being independent of other components. Where they can''t be independent (for example, a Sprite must know something about the renderer to draw itself), try to keep the interface between the objects as clean and simple as possible. This will allow you to switch objects beneath the interface (for example, DDraw, D3D, and OpenGL renderers) without our Sprite knowing or even caring.
The first place to start is to stop thinking of a graphics renderer in terms of game genres. I think it''s safe to say that the ultimate goal of any graphics engine is to put pixels on the screen.
From there, you can look at what all games have in common from a graphics perspective. This will help you to get a general idea of a framework to build around the raw pixel output. Getting this far alone will enable you to make games which require no specialization.
Once that is done, then you can start looking at what different genres require to extend the framework, and do so only as needed. That is, if you are the end-user of your engine, don''t worry about supporting a specific genre until you want to make a game from that genre.
This is a very simple process when you break it down in steps like I have above, but it becomes convoluted by worries about which class should go where or do what or extend what or... If you can learn to think modularly, you will be able to better design modularly.
And to truly achieve flexibility, loose coupling is essential. The more your objects depend on each other, the less flexible your engine becomes. When you are in the process of identifying the vaious components of your framework, try to visualize them as being independent of other components. Where they can''t be independent (for example, a Sprite must know something about the renderer to draw itself), try to keep the interface between the objects as clean and simple as possible. This will allow you to switch objects beneath the interface (for example, DDraw, D3D, and OpenGL renderers) without our Sprite knowing or even caring.
Well, I thought of what you said and came up with the following components:
-CLevel: controls several maps and everything that is associated to them, namely the textures, scripts, particle scripts and so on.
-CMap: represents a 2D tile map (most 2D games should be based on one)
-CSpriteManager: manages all the sprites
-CSprite: a simple sprite
-CParticleSystem: controls several script driven ''Particle Sources''
-CParticleSource: normally one would refer to this as a particle system but I used the term above. An instance of this class could be the rain, for example.
-CParticle: pretty obvious
-CArchive: manages file access by providing means of compressing data into a single archive
-CFile: provides access to a single file
CDevice: provides access to the rendering functionality
CScriptSystem: can load and run scripts.
What is left to do is:
-invent some kind of generalized pipeline for rendering dynamic geometry (e.g. sprites)
-Consider which classes should be abstract and so on
Do you have any suggestions?
Am I making some ugly design errors already?
-CLevel: controls several maps and everything that is associated to them, namely the textures, scripts, particle scripts and so on.
-CMap: represents a 2D tile map (most 2D games should be based on one)
-CSpriteManager: manages all the sprites
-CSprite: a simple sprite
-CParticleSystem: controls several script driven ''Particle Sources''
-CParticleSource: normally one would refer to this as a particle system but I used the term above. An instance of this class could be the rain, for example.
-CParticle: pretty obvious
-CArchive: manages file access by providing means of compressing data into a single archive
-CFile: provides access to a single file
CDevice: provides access to the rendering functionality
CScriptSystem: can load and run scripts.
What is left to do is:
-invent some kind of generalized pipeline for rendering dynamic geometry (e.g. sprites)
-Consider which classes should be abstract and so on
Do you have any suggestions?
Am I making some ugly design errors already?
Its always good to just start coding before overthinking. That''s when you start to realize what you''re truly missing.
For example, how do you plan to take care of timing issues each frame? Hopefully you will not be creating/querying multiple timers each frame. Then there is error checking/catching, which can be done individually and tediously or using a completely non-oo and 100% effective global error handling class.
Of course, you should also be able to handle input and music is cool too.. unless you are just making the interface solely for graphics.
Another thing I learned was a rather fanatical obsession with seperation between data and code. Of course this always makes sense for each individual class, but I ended up making a global data holding object conglomerate. Not even a singleton, just a global class. OO isn''t god.
This makes things infinitely more convienant, since it gets rid of pointless interface functions such as. "GetContextHandle", "GetDeviceHandle", "GetReferenceCount", etc..
Of course this is all just opinion. My developement was inspired after devouring the quake 2 code for a couple of weeks, and one could easily argue its not a good design to follow after. But my engine is fast, and more importantly- working. So now I am getting to work on fun rendering implementations, rather than planning out the perfect design. Of course planning out the perfect design is also fun, but implementing it will not be!
Of course, you should also be able to handle input and music is cool too.. unless you are just making the interface solely for graphics.
Another thing I learned was a rather fanatical obsession with seperation between data and code. Of course this always makes sense for each individual class, but I ended up making a global data holding object conglomerate. Not even a singleton, just a global class. OO isn''t god.
This makes things infinitely more convienant, since it gets rid of pointless interface functions such as. "GetContextHandle", "GetDeviceHandle", "GetReferenceCount", etc..
Of course this is all just opinion. My developement was inspired after devouring the quake 2 code for a couple of weeks, and one could easily argue its not a good design to follow after. But my engine is fast, and more importantly- working. So now I am getting to work on fun rendering implementations, rather than planning out the perfect design. Of course planning out the perfect design is also fun, but implementing it will not be!
quote:
Original post by haro
Its always good to just start coding before overthinking.
Hmmm. That''s gotten me into trouble more than once
Hippokrates - I misunderstood your original post, it looks like. When you said ''fast 2D engine'' I assumed you were talking graphics alone. But most of what I said still applies.
Let''s look at what you listed. I think it''s safe to say that CSprite and CParticle have a common trait - they both represent a renderable object. Depending on your conception of CMap, it could also represent a renderable object. Now we have a good case for inheritance.
You cay CMap represents a 2D tile map. IMO, that''s a bit too much detail for what should be a high level interface. CMap should represent a Map, nothing more. This is a good class to make abstract. You could subclass to make tile maps, iso maps, hex maps, parallax scrolling maps... you get the idea. This helps you achieve loose coupling. Figure out what all maps have in common and you should be able to come up with a list of functions (most of which should be pure virtual) that CMap can define.
Personally, I think your CLevel doesn''t belong in there. That would be better left to the actual game implementation.
That''s a great start. Once you''ve gotten a good idea of the structure, start drilling down deeper and decide what each interface will expose. Decide how the objects will communicate with each other, keeping in mind that you want as little direct communication as possible. Factories, Delegates, Observers, Commands - learn the design patterns that can help you.
There is no perfect design. But I really think that in order to make life easier down the road, programmers should always strive to make the end result as extendable/flexible/scalable as possible. This makes it much easier to go in and refactor code when you realize a major flaw later, without having to go back and start over again.
Wow, that was more help than I expected ^__^
Well, concerning the CLevel idea: what it is meant to do is the following:
I assumed that every ''Level'' in practically every game is a combination of maps, scripts, sprites, particle systems, sounds and so on. Since this is so, all that the Level class has to do is have the scripts processed, the graphics rendered and the music played. This should be the same for all games...?
Well, concerning the CLevel idea: what it is meant to do is the following:
I assumed that every ''Level'' in practically every game is a combination of maps, scripts, sprites, particle systems, sounds and so on. Since this is so, all that the Level class has to do is have the scripts processed, the graphics rendered and the music played. This should be the same for all games...?
quote:
Original post by Aldacron
You cay CMap represents a 2D tile map. IMO, that''s a bit too much detail for what should be a high level interface. CMap should represent a Map, nothing more. This is a good class to make abstract. You could subclass to make tile maps, iso maps, hex maps, parallax scrolling maps... you get the idea. This helps you achieve loose coupling. Figure out what all maps have in common and you should be able to come up with a list of functions (most of which should be pure virtual) that CMap can define.
...
That''s a great start. Once you''ve gotten a good idea of the structure, start drilling down deeper and decide what each interface will expose. Decide how the objects will communicate with each other, keeping in mind that you want as little direct communication as possible. Factories, Delegates, Observers, Commands - learn the design patterns that can help you.
So mister wizard, any advise on pushing on thru to an rts style of gameplay? ie Telling a unit to goto this location and attack this thing with a mouse click? Pathfinding? Where does the user interface fit in here? Howabout changing inventory in an rpg? Unlocking a treasure chest?
quote:
So mister wizard, any advise on pushing on thru to an rts style of gameplay? ie Telling a unit to goto this location and attack this thing with a mouse click? Pathfinding? Where does the user interface fit in here? Howabout changing inventory in an rpg? Unlocking a treasure chest?
First of all, no need to be sarcastic (which is the only way I can take the ''mister wizard'' comment). The guy asked for advice and I''m giving it. It''s the way I would approach the problem, but it doesn''t mean it''s the only way.
While the user interface would be a prime candidate for the core of the engine, the rest is more specific to the games. Personally, I would put all of the RTS and RPG-centric stuff in seperate libs. The end result woud be core.dll (graphics, input, sound, etc...), rpg.dll, rts.dll - or something similar.
quote:
Well, concerning the CLevel idea: what it is meant to do is the following:
I assumed that every ''Level'' in practically every game is a combination of maps, scripts, sprites, particle systems, sounds and so on. Since this is so, all that the Level class has to do is have the scripts processed, the graphics rendered and the music played. This should be the same for all games...?
I see where you''re coming from. What I would probably do is make something like a Scene class to handle all of the graphics-related objects. Music and sound would go in a Player. The game would have its own Level class, which would be responsible for loading all of the data and then sending it to the appropriate manager. The reason is that not every game will store data the same way.
But again, these are just ideas off the top of my head. How you design your engine is ultimately up to you.
well, of course, every game stores its information differently. But things like maps, sprites, music and particle scripts will be handled by the engine anyway so I though I could perhaps put them into a central class...
What I dreamed of is something like this:
And the rest is done by the engine.
And I believe this could be possible because all the actual game specific stuff is done by scripts.
Correct me if I am horribly wrong
(as so often before (which is in fact not sarcastic or the likes))
[edited by - Hippokrates on May 20, 2003 3:17:17 PM]
What I dreamed of is something like this:
CLevel level;
level.load("UltimateLevel.lvl");
level.run()
And the rest is done by the engine.
And I believe this could be possible because all the actual game specific stuff is done by scripts.
Correct me if I am horribly wrong
[edited by - Hippokrates on May 20, 2003 3:17:17 PM]
quote:
Original post by Aldacron
First of all, no need to be sarcastic (which is the only way I can take the ''mister wizard'' comment). The guy asked for advice and I''m giving it. It''s the way I would approach the problem, but it doesn''t mean it''s the only way.
Believe it or not, that wasn''t supposed to be sarcastic (just another instance of my off beat sense humor getting me in trouble again, and another instance of why this form of communications leaves much to be desired.)
You gave the OP alot of good advice and I was wondering what ideas you had on the UI of a game like an rts or rpg.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement