simple game engine design caving in on me -- suggestions pls!

Started by
3 comments, last by tomersaban 16 years, 10 months ago
Hello Everyone, I'm a noob, I need some help, badly. I'm trying to implement a simple all-round C++ / Win32 game engine for simple 2D games (think Pong) - however there always seems to be some flaws in the design. Here, some object hierarchy: Object (abstract) - has a position (Vec3D) - pure virtual function for drawing itself to a given HDC MovingObject (abstract) - is an Object - has a velocity (Vec3D) - virtual function for updating it's position ( pos += vel * timeDelta ) MovingMass (abstract) - is a MovingObject - has a mass (float) Shape (abstract) - is an Object - pure virtual functions for * determining if given point is inside the Shape * getting the closest point inside the Shape to a given point Rect, Circle, Polygon - are Shapes - drawing's implemented Entity - is a MovingMass - has a type (word -- character, projectile, movable, breakable etc.) - has a Bounds (Shape*) - has a CollisionShape (Shape*) - functions for detecting collision with another Entity (if the other's closest point is inside the Entity's CollisionShape), drawing's implemented (ATM it calls the CollisionShape's drawing method) EntityManager - has a map of entities <names to Entity*'s> - has a map of behaviors <pairs of Entity types to pairs of CollisionHandlers> - functions for adding and removing Entities and Behaviors (the pairs of CollisionHandlers), and to batch update & draw entities CollisionHandler - typedef void (*CollisionHandler)( Entity*, const Entity*, double timeDelta ) -- the colliding Entity (about to change), the Entity it's colliding with (it's going to change in it's own CollisionHandler call, not this one), and the elapsed time The problems at this point are the following: - an Entity and it's CollisionShape live separate lives: they both have their own positon and I'm looking for a consensual solution where to synchronise the two, or how to find a better implementation, the CollisionShape depending on the Entity. I haven't found one yet. - on collision check, when I'm calling the second handler, the first Entity's state has already been changed. for this, I'd need to save a copy of it's state before any ColisionHandlers are applied - but I don't know how to copy the polymorphic CollisionShape. - I haven't decided "where" should I be checking the input ("how" is Controls -- another polymorphic solution to handle player input and AI's on a common base). I'm really clueless... what's the commonly applied approach? How do the Big Ones do this? Thanks for all the help in advance.
Advertisement
Quote:Original post by trajectorymodifier
- an Entity and it's CollisionShape live separate lives: they both have their own positon and I'm looking for a consensual solution where to synchronise the two, or how to find a better implementation, the CollisionShape depending on the Entity. I haven't found one yet.


Don't give them their own position, let CollisionShape reference a provided position instead of having its own, and have Entity provide the CollisionShape with the ad hoc position.

Quote:- on collision check, when I'm calling the second handler, the first Entity's state has already been changed. for this, I'd need to save a copy of it's state before any ColisionHandlers are applied - but I don't know how to copy the polymorphic CollisionShape.


Don't do this separately. Use the visitor pattern to determine which situation the objects are in (Player-Buller, Player-Enemy, and so on), and call a single standalone two-argument function on them both to perform the modification. This way, they are altered simultaneously.

Quote:- I haven't decided "where" should I be checking the input ("how" is Controls -- another polymorphic solution to handle player input and AI's on a common base).


The creator of the Control object decides where the input comes from. It may decide to give the control information about the keyboard, for instance.
Quote:- an Entity and it's CollisionShape live separate lives: they both have their own positon and I'm looking for a consensual solution where to synchronise the two, or how to find a better implementation, the CollisionShape depending on the Entity. I haven't found one yet.


You can try a solution similar to the one below to make the CollisionShape follow its entity.

const BoundingRect& Entity::getBounds() {	if(_moved) {		_boundsMoved.x = _boundsOriginal.x + _pos.x;		_boundsMoved.y = _boundsOriginal.y + _pos.y;		_boundsMoved.w = _boundsOriginal.w;		_boundsMoved.h = _boundsOriginal.h;		_moved = false;	}	return _boundsMoved;}


Quote:- on collision check, when I'm calling the second handler, the first Entity's state has already been changed. for this, I'd need to save a copy of it's state before any ColisionHandlers are applied - but I don't know how to copy the polymorphic CollisionShape.


In my opinion, for a simple game as pong or similar, the problem with one object's state being changed before the others will not be a big problem. Often the effects mostly depends on the type of object you've collided with, not its state. Otherwise, a solution where each object stores it's changes, but only commits them after all collisions has been handled is probably prefered.

void Bomb::collide( const Entity &ent) {	if( !isDead()) {		switch( ent.getType()) {			case entityScreen:			case entityPlayer:				remove(); // Either change state directly or remember change for a future commit				break;			default:				break;		}	}}


Regarding copying a polymorphic object. A virtual copy method returning the base class works for at least dynamic objects. Then every derived class overrides with its own.
class base {  virtual base *copy() { return new base(); }};class derived : public base {  base *copy() { return new derived(); }};


Phew, a bit more than I planned. =)
Thanks for the heads up, ToohrVyk & Necator!

I had some trouble with the virtual copy(), as Shape is abstract. In the end I've just defined copy() as pure virtual.

As how things stand now, Shape is NOT an Object anymore, it's changed to LShape (L for Logical) - it doesn't have a position_ (it treats as it's position was the origin -- a (const) nullVector). There, however is a new class, RShape (R for Relative), which is-an LShape. It has a reference to a position vector and a pointer to a LogicalShape. (Entity's gonna create its own RShape CollShape_; from a given LShape and it's own position_.)

Now, the only (I mean most conspicuous=) ) awkwardness in the design is that as the draw()ing having to be implemented on the level of LShapes (who don't have a position, therefore that having to be passed to them), I'd still have to pass a position vector to RShape::draw(), who would at most ignore it. Awkward!
(For now I'll go with RShape::draw()'s position vector parameter defaulted to nullVector, which I used as a constant for LShape's & derivatives' calculation anyway). Any suggestions to resolve this would still be very much welcome. (is the RShape is-an LShape relationship alright, or should I go for has-a or IITO-a relationship?)

I'm gone testing, will check back to let anyone interested know.

[Edited by - trajectorymodifier on June 22, 2007 5:25:34 AM]
i , my name is tomer , i have read about your project and i will be
glad if you will send me the source , zue i need some ideas for my game engine that i m doing as a course in oop. . in my college .

plz send it to: tomersaban77@gmail.com

10x

tomer

This topic is closed to new replies.

Advertisement