Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
开发者_开发技巧 Improve this questionI am going to be re-creating a game engine I created awhile back. This time I want to do it right, so I did some research into design patterns and tried to put pieces together to accomplish my goal. The idea of the game engine is simplicity, but at the same time I don't want to sacrifice usability.
Here is a blueprint of what I am thinking, let me know if you can see any downfalls especially in expandability:
class Object
{
public:
string name;
}
class Object3D : public Object
{
public:
int x;
int y;
int z;
}
class Object2D : public Object
{
public:
int x;
int y;
}
class cube : public Object3D
{
cube() : x(0), y(0), z(0), name("cube") {}
}
class square
{
...
}
int main()
{
SGL Engine(paramters);
c = cube();
s = square();
Engine->Lib3D->AddCube(&c, "cube");
Engine->Lib2D->AddSquare(&s, "square");
Engine->Input->keyboard(&kbevent);
while(Engine->running())
{
if (x)
Engine->Draw("cube");
else
Engine->Draw("square");
}
}
void kbevent(event-paramteres)
{
if (key.up)
engineptr->objects["cube"]->move(x,y);
}
The target language is C++.
First, read this.
The only way to do it "right" is to turn the process upside down. Make the engine after you've used it in a game.
Second. C++ isn't Java. C++ doesn't have a base Object
class, and it doesn't need one either. Don't try to fit everything into an inheritance hierarchy. If every object is polymorphic you're crippling yourself (everything has to be heap-allocated and passed by reference or pointer to avoid slicing, for example, and it doesn't even make your code any clearer)
An object in the world has a position. It is not one. So don't inherit x, y, z
coordinates. Put them in a coordinate class, which can be added as a member in the classes that need it.
String lookups are slow, and you need to handle the case when strings are not unique. (What if I accidentally add two objects with name "cube".
Why not rely on plain references or pointers as much as possible?
Why can't I simply do Engine->Draw(c)
to tell the engine to draw the cube?
But really, the most important piece of advice is, don't try to write a shrink-wrapped game engine for later use. You're going to end up exactly where you are now: needing to "rewrite it, and this time do it right". If you want to get something out of it that works, you need to start with its use case. Write the game first. When you've done that, you can start refactoring the code to separate the engine out. That way, you end up with an engine that works.
Unless you are using hash mapping, string lookup is slow. Besides once you have added the objects to the engine you should be able to do something like:
Engine->Draw();
Which will go through all objects added to the engine and draw them.
The Object should have a virtual Draw function and Object2d and Object3d should override that function. Then the Engine would just loop through all the objects and call draw on them.
The other thing is that you shouldn't need an add function for the different types. You should be able to do something like:
Engine->AddObject(&c);
Engine->AddObject(&s);
And it will figure out what to do with it. The way you have it now you are requiring the user of the engine to know what they want to do, whereas it should be encapsulated enough that you don't need to, but open enough that it doesn't get in your way if you want to do something not supported by the Engine you can, so I would keep the Lib2d and Lib3d accessors, though purists would say the encapsulation was broken.
- I'm pretty sure you should use floats instead of ints for object coordinates. With floats you can run the game at any framerate. With ints there will be problems.
- Ideally, class names should start with capital letters (
class Cube
) unless you use prefixes to indicate types (class CCube
). - (most important one) Before making object hierarchy, you should know what exactly you want to create. Imagine game level, think what objects are present, categorize them, and then try to make a hierarchy. You don't need to make a class for everything (and maybe you don't even need a complex hierarchy, maybe you can write entire thing without ever using inheritance), but you should be able to imagine final product while you're writing code. Don't introduce new concepts unless you need them. Right it looks like you have no idea of what you want to make, and now there are few classes that may be completely unsuitable for final product.
First of all, try not to fit a design pattern onto a problem. Read http://realtimecollisiondetection.net/blog/?p=44 and http://realtimecollisiondetection.net/blog/?p=81 regarding that kind of solutions.
Second, It's important that you look at what kind of game(s) you will be doing when writing an engine. Therefor it is of the absolute interest to lay out what kind of data you will process and how.
Third, when it comes to game-engine development I would recommend reading into the Bitsquid blog http://bitsquid.blogspot.com/, which are currently writing some interesting topics regarding their new engine. I would also recommend watching/reading as much as possible from Mike Acton who is the Lead Engine Architecture at Insomniac Games. He frequently recommends that you look at the data first and develop your engine around what kind of data that it will process. This one: http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-189-multicore-programming-primer-january-iap-2007/lecture-notes-and-video/embed17/ is an interesting ground-base runthrough that Mike Acton does regarding their engine development.
The link to Mike Acton's general blog is http://www.insomniacgames.com/blogcast/blog/mike_acton. I would also suggest reading through a lot of their topics since they're very good and interesting.
Regarding your code I see no reason as to why you need your inheritance structure. Why is a Cube a 3d-object? Why does Cube inherit from anything at all? A Cube or a Box is simply 3 floats that defines the extents (or half extents) of it. I would suggest that you have an Object that then uses a HAS-A relationship to cubes or boxes or squares. There are some topics at Insomniac regarding component-based game entities, I suggest you read it: http://www.insomniacgames.com/assets/filesadynamiccomponentarchitectureforhighperformancegameplay.pdf (I think that's the correct link).
The three big lies of software development: http://www.insomniacgames.com/blogcast/blog/all_categories/1500756
精彩评论