Game framework architecture - view components or MVC?
I have a question for my learned readers - if anyone has an answer, please leave a comment. Here it is:
I'm trying to build a very light reusable framework for my games, rather than starting from scratch each time I start a game. I have a component driven architecture - e.g. Entity model composes a Position component, a Health component, an Ai component, etc.
My big question is whether my model composes view components to allow for more than one view of the model, or whether to use a truer MVC where the model does not know about its views, and they are managed externally.
I have tried both methods but if anyone knows the pros and cons of each approach and which is the industry standard, it would be great to know. I'd particularly like to hear from people who have tried both methods.
Comments
For example I add a body for collisions and an image for the graphics.
To add ai I have a IActor Interface that has a act() in it. In there you can add pretty much anything, from IA to weird logic.
It seems to be very flexible and fast (performance is priority).
The only problem I'm trying to figure out is how separate the different gameObject clases with the game engine to reduce the compilation time witch can take up to 50 seconds in my athlon 3000+ (the game engine with objects and editor is 350 classes big). I can easily separete the editor but I have to figure out the way to separate the actual gameobjects and the object factory.
The AS3 PushButton engine from GarageGames could have an answer.
SP.
Pushbutton are doing a lot of things via string look-ups so that they have less co-dependancy between components and greater interoperability. This is going to slow the engine down quite a bit. They openly admit on their site that pbe is not optimised for performance.
As my engine is just for me, I'll feel a lot happier using properties rather than these lookups. They are doing a lot of stuff with Singletons and God objects which is not very OOP. but I guess it gets the job done.
I plan to do a project in PBE and borrow the ideas that I like for my engine.
I have this:
AppContext (dictionary, has reference to view and GuideMgr, that it, used for injection).
BaseView (has stage, contains Models, frameloop).
ModelMgr (has a model is something you put on view(ex sprite ), has events, "self aware", encapuslated)
GuideMgr (guides view/models, has dataproxies)
DataProxy (talks to service).
hth
In games I am interested to make I have physics engines and other "behind the scene" things that are separated from graphics usually anyways + MVC makes it easier to use same M and C in other projects while changing V.
Another thing why I use MVC in some form is that it makes a lot easier to make things like replays, save/load games and checkpoints etc etc as it is just Model that is already separate and it is usually made out of common data structures which can be saved/loaded or transformed in to strings pretty efficiently and without much of code.
So I am for MVC here as it makes game engine more versatile and game independent if made right.
1. when you need access to the view for collision detection - e.g. built-in hitTest or potentially use of 3D geometry for collisions.
2. writing a lot of code to bind models and views
With a component based-system it is still easy to change the view and serialise objects etc, because these facets are still compartmentalised.
Hmm... Rewriting this answer 3rd time... Kind of hard to make it a small answer :)
1. Well here question is what you find to be a rule and what you find to be an exception. Is "physics influenced by graphics" a rule and "there are objects that are not drawn but participate in physics" and exception or other way around. For me usage of graphical information in physics is exception.
For example I often try to create a query system where I can ask physics engine things like "give me objects in that circle" which is actually a case when object does not exist in game world and is not drawn but exists in model and it is pretty often like drawing of the bullet having nothing to do with how it is represented in model.
2. And from above comes fact that often graphical objects and effects have their geometrical representation in physical model meaning that some kind of binding or synchronization will need to have place anyways.
Tough I agree that it is possible to make some MVC like but not truly MVC system that will work better but still at least for me it will have separate data-model to at least be able to save/load stuff, and it have separate graphics and physics models that will need to be binded/synchronized.
"some MVC like but not truly MVC system" - I think this is what I am striving for. If you are using a physics engine e.g. box2d or glaze then by definition you are seperating your model and view. The question is whether you let the entity know it has views or not. I don't use hitTest often but it is nice to have as an option.
Classes:
Entities have basic position info, size/dimensions, health, etc. But doesn't know how to represent itself to screen.
EntityRepresentations draw the entities to screen, generate sounds, draw special effects such as particles. Can be multiple Representations for a given Entity - I use this for health UI, Lives, different views etc
EntityControllers handle both user and ai controls - KeyboardController, MouseController, AIController
EntityResouce handles the load of all external assets and variables such as models, sprites etc related to an Entity and its Representation.
Managers:
ResouceManager instantiates all EntityResources required and loads all resources for a game up front.
EntityManager handles entities add and removal from system during gameplay.
RepresentationManager handles representation adds and removes by listening to the entitymanager
The benefits of this allow the EntityManager to update at a faster tick than the RepresentationManager - this is handy for physics based stuff that might need to update faster than the framerate the visuals are displayed.
I'm still refining this system, but it's allowing me to create external XML that describes a game map, or an entity etc that gets instatiated at runtime, meaning that we can change game paramaters without recompiling (most of the time).
Two type of objects:
GameObject:
- buildFromXML(xml).
- act(time).
- doPhysics() (body with x, y, vx, vy, polygons, etc).
- render(). (Sprite or MovieClip updates itself).
Links:
- is also an actor.
- creates additional game logic BETWEEN objects: grabs two or more objects and listens events from them to open doors with switches, triggers game gameover event by listening to the spaceship died event, etc.
- extremely flexible and eliminates the need for classes that are external to the engine for additional logic (except stats tracking logic) since they are considered a special type of game object without image or physical body.
With that type of engine in mind MVC seems to be too slow. I prefer to have objects closer to each other using a well organized composition. The game we are building does a 50 fps in my crappy Athlon 3000+ with worlds built from polygons, huge bitmap graphics, brute force physics (no broad phase since the physics engine is work in progress), and no DisplayObject optimization (no "broad phase" either: the bitmaps are not removed from stage when not visible).
I would say that optimization in Flash it the most important part of a gameEngine and will prefer composition over MVC.
MVC is clean but would slow down the game a lot and you can still have a well organized engine without it. MVC from my experience is amazing for pretty much anything that is not performance critical.
Hope it helps.
SP.
If we ever make a certain games, we can usually test different views (2D or 3D) using the same Model and Controller. Then controller changes based on Platform.
Your question regarding Collision detection is one which can be answered based on your engine.
Lets say you have a Factory that creates bullets, AI, collectables, etc. Then Factory can also be a manager(or delegate to one) by keeping track of all objects created. So your CollisionManager class will then simply check if objects are colliding and the use Double Dispatch if you want or notify ITypes that the should doSomethng() base on who collided with who.
The CollisionManager would check objects in the Factory or Manager class, using thier objects property.
And then notify objects to doSomething()
This brings s back to loose coupling.
K