A lack of C++ encapulation makes me feel guilty

Started by
24 comments, last by Barn Door 21 years, 7 months ago
quote:Original post by petewood
Two things:

- code classes as though you don''t know what''s going on inside the others

- one class one responsibility

coderx75''s example sounds clever but very inflexible. what if you have different kinds of collision algorithms etc? the entity class has to manage everything, memomry, movement, collision detection, what about culling for the renderer too?

i feel uneasy and am just expressing that without any good suggestions


Actually, it allows me a lot of flexibility. The purpose of this is that I don''t need more than one collision algorithm. In this system, everything is an entity and viewed the same by the CEntity class. The way I''ve set it up is that I have a collision system that exerts force onto the colliding entities. This force not only cause the objects to react (bounce) but also inflicts damage. Therefore a bullet is only an entity with light mass and high velocity. When it hits something, the damage is distributed to the bullet and the target. The bullet, having few "hit points" is destroyed.

The CEntity class doesn''t actually know what''s happening in other instances. It can request that information through the methods of other instances... hmmm, I''ll post some code...

- Jay

"I have head-explody!!!" - NNY

Get Tranced!
Quit screwin' around! - Brock Samson
Advertisement
This is from memory so excuse any errors (I''m at work and my code is at home).


  class CPresence {public:    //place dimensions and position of entity here...};class CEntity:public CObject {private:    static CPresence presence[MAX_ENTITIES];    static short counter;protected:    CPresence *self;    void    Init ();public:    short   SetPosition (long x, long y, long z);    void    SetDimensions (...);    long    GetX ();    long    GetY ();    long    GetZ ();    virtual short   Move (long speed);};class CAsteroid:public CEntity {    //place asteroid specific interface here...public:    CAsteroid ();    //calls CEntity::Init()    short Move (...);    void  Update (...);};  


Okay, this ain''t pretty... I can post the actual header file tomorrow morning if you''re interested. (Notice I use integers for everything... I''m old-school =b) I''ll explain all this in better detail:

CPresence just holds whatever data your game objects require. CEntity is the parent class of all your game objects and holds an array of CPresence objects. This is very important: the array is both static and private. This means that all of your objects can view the data in the array ONLY if the methods allow it but no CEntity derivative can access it directly. CEntity has no idea what other "entities" are doing unless those entities allow that information to be passed. It is in fact very controlled.

The "counter" property simply counts how many of our CPresence objects have been used so we know what the next available presence is.

The "self" pointer points to its own presence in the array. This allows direct access only to its own data. Notice that this property is protected. This means that CAsteroid and other derivatives of CEntity can access their own data but only theirs and no other object can access it directly.

The Init() method (also protected) assigns a presence to the object. In reality, it only assigns presence[counter++] to *self.

SetPosition() does as its name implies but not without first checking for collisions. It returns true if there is a collision.

Move() accepts a parameter for speed in units per second. This is adjusted to the current framerate and the new position is calculated. That position is sent to SetPosition() where the collision is checked.

The other methods simply allow the outside world to "set" or "get" properties of the CPresence object that *self points to.

The CAsteroid object contains all asteroid specific properties and methods. Notice the constructor. This calls the CEntity::Init() method to snatch up a presence.

This very off-the-cuff. My actual header file includes a LOT more than this and would probably be more confusing. The presence array is actually organized into a two-dimensional array of linked lists (the b!tch can handle 8,000 entities at 66 fps! WOOHOO! ...on a P$ 1.4GHz, btw). Anywayz... is this clear?

btw, I think the CEntity constructor assigns the presence... not sure =/

- Jay

"I have head-explody!!!" - NNY

Get Tranced!
Quit screwin' around! - Brock Samson
Hi coderx75. Cheers for posting your code.

I''m interested to know how you would go about iterating through all the elements in the CPresence array from start to finish.

BD.
quote:Original post by Barn Door
Hi coderx75. Cheers for posting your code.

I''m interested to know how you would go about iterating through all the elements in the CPresence array from start to finish.

BD.


My guess is...a for loop? =)

Even though, I think an std::vector would work better instead of an array. Variable size, the ability to quickly remove an element from the middle of the vector, and ease of use are all pluses.
quote:
My guess is...a for loop? =)

What for loop?

The CPresence is ..
quote:only accessible through the CEntity methods.


.. but the CEntity methods are only accessible through an instance of a derived class such as an asteroid.

But the asteroid or entity..
quote:
can access its own data directly through the ptr but accesses the limited data of others via its own methods.


Key word being ''limited''.

So in order to iterate through all the objects in the array you''d have to put all your elements in another array and get each object, in turn, to pull out its data from the pool at the bottom.

Surely one of the arrays is redundant?

What am I missing?

BD.
Sorry it took so long to get back to ya...

The object does the work that it needs to do to itself. The rest of the program has no idea what the object is doing. It should look something like this:


  CAsteroid  asteroids[MAX_ASTEROID];CLaserFire laserfire[MAX_LASER_FIRE];CPlayers   players[MAX_PLAYERS];for (i = 0; i < MAX_ASTEROID; i++) asteroids[i].Update ();for (i = 0; i < MAX_LASER_FIRE; i++) laserfire[i].Update ();for (i = 0; i < MAX_PLAYERS; i++) players[i].Update ();  


In my implementation, the game goes on without the main loop of the game having any idea of what''s going on. If, for example, you need your graphics engine to draw all "entities", it would get the CPresence properties via GetX(), GetY(), etc.

- Jay

"I have head-explody!!!" - NNY

Get Tranced!
Quit screwin' around! - Brock Samson

This topic is closed to new replies.

Advertisement