How To: Make Classes Include Eachother (or achieve the same effect)

Started by
16 comments, last by neonfaktory 20 years, 11 months ago
quote:Original post by neonfaktory
So, "Player" obviously has to include Ship so it can "AddControl()"
What does AddControl() do?
quote:
Naturally, you would include "Player" in "Ship" so you use Ship member function "Player* myPlayer" to be like "myPlayer->MAX_HEALTH.value" for special calculations that Ship handles, like recharging health to the max level that Player has. However, this wouldnt work because "Player" already has "Ship" included so it can "control" your Ship accordingly.
I don''t see a reason why it wouldn''t work. Ship has Player* myPlayer, and I assume it''s the owner of the ship, so of course, you can access every public member of Player from Ship. If you have problem with the access (and that''s why you want to use friend keyword), you can make get/set methods or make the members public, or make a public function recharge(), so that Ship can calls it, and Player handles the recharge algorithms.
quote:
Simple forward declaration doesn''t seem to work either. I *CAN* have a "Ship" member function "Player* myPlayer", but (I assume) because "Player" isn''t truely included in Ship, I can''t say "myPlayer->MAX_HEALTH.value".
"isn''t truely included in the Ship"? I don''t know what you mean in here, lol, sorry.
Advertisement
You can''t do what you want to do because it would create an infinite loop...what''s to stop you from accessing A::B::A::B::A::B::A:: etc.

Why not just make a new class, C, which contains the class definitions of A and B. Then you can declare C::A or C::B individually, or declare a C and its members.

Why don''t you explain your general problem, if you need to do this you''re concieving of your problem wrong.
Ok, now that I'm at work I took another look at this thread and it seems that what rypyr mentioned is what I need. I'll give an update when I can try it out tonight.

In response to alnite:
I was just using "AddControl()" as an example that I need to include "Ship" in "Player" so I can run "Ship" member functions - More specifically, "AddControl()" would be used like "myShip->AddControl(THRUST);" after "Player" gets the inputs from the input handlers.

The other questions you asked go hand in hand - When I forward declare "Player" in "Ship", I can then give "Ship" a pointer to a Player as a member. It doesnt, however, let me use functions of that member. I can't say "myPlayer->anything();", and I assume it is because "Player" is only forward declared, not actually "truely included".

Thanks for the help so far guys

*EDIT* Response to Ishan:
I said before that I understand why I can't do it literally, but that I want achieve the same effect doing so would have. Simple form of what I want to do in case you don't want to read the description I just put up:

I have classes Player and Ship. Not only do they need to know OF eachother, they need to be able to access the data members of eachother (something forward declaration doesn't let you do). For example, Player needs to know of and directly effect Ship it owns (control it) and Ship needs to know the information thier Player holds to determine how it moves (each Player has unique statistics that control thier ships: movement speed, turn rate, etc).
What I need is a method that will allow me to access the data equally back and forth without making accessor class "C" which seems very ugly and cumbersome (to me anyway). But as I said, rypyr seems to have given me the answer I was looking for, which I will try tonight when I get home .

[edited by - neonfaktory on May 1, 2003 2:33:09 PM]
weee!
You forward declare things in the header so that the compiler is satisfied that the class will exist somewhere. If the linker can''t find the implementation file it will come back with an error.

Forward declarations just decrease dependencies between headers. Don''t get stressed about it - it increases compile speeds.

In the implementation of ''Ship'' (the cpp file) you can include the Player.h file so myPlayer->anything() will be meaningful.
Okay, I know you dont want to hear this but trying to make sense of why you cannot use a better method is hard to accept so I just want to get a clear understanding of what you are trying to do. Here is what I understand (or something along these lines):

You have a Player that walks around with all the typical RPG attributes (speed, strength, agility, etc) and he notices a nice shiney new space ship. So you, the player, decide to jump in the space ship (read: you press ''w'' key to move him close, then ''e'' to enter the ship).

Now, this space ship is very intelligent and complex. It performs based on the players characteristics (speed, strength, agility, shields, max health, etc). So the ship reads information about the player, configures itself accordingly, and is ready to be flown (is this a word?). Now, as the player inside the ship, you press ''w'' again to fly the ship forward, as well as other keys to menouver the ship properly.

You then find this ship boring, so you fly it towards a platform, exit the ship with ''e'' and run away from it.


Does this scenario sound similar to what you want to do? (Please correct me if it does not)
neonfaktory: you still must make the data members accessible "outside" the class. Hopefully you know how to expose data to the outside world (i.e. you shouldn''t just blindly make all player and ship attributes public).

Hopefully you know this, but if you don''t here is an example.

in Player.h:

class Ship;class Player {  Ship* m_pShip;  int m_Intelligence;public:  int getIntelligence() const { return m_Intelligence; }  void flyShip();}; 


in Ship.h:

class Player;class Ship {  Player* m_pPlayer;  int m_ShieldStrength;public:  int getShieldStrength() const { return m_ShieldStrength; }  void fly();} 


in Player.cpp:

#include "Player.h"#include "Ship.h"void Player::flyShip() {  // do something with m_pShip->getShieldStrength() here...  m_pShip->fly();} 


in Ship.cpp:

#include "Ship.h"#include "Player.h"void Ship::fly() {  // do something with m_pPlayer->getIntelligence() here...} 


Regards,
Jeff
CActor - basic actor class in the universe.
CPlayer - the one and only
CVehicle : public CActor - something the player can drive/fly.
CShip : public CVehicle - cause it is one.
CInputHandler - handles input, pure virtual used as interface
CPlayerInputHandler - active when not in a vehicle
CShipInputHandler - active when in a ship
CCarInputHandler - active when in a car

When the game is first started, the player uses the CPlayerInputHandler to dispatch commands with. When the player enters a vehicle he/she requests the proper CInputHandler from the CVehicle class which a new derived class(i.e., CShip) can override through some virtual method like GetInputHandler.

The Player really only needs to know about a Vehicle. The Ship can know about the Player through the Vehicle base type (SetController(CActor* pActor), note: could be some AI code instead) so that it can adjust its flight characteristics and what not.

This also leads to nice grouping for your Customize Controls view.

[edited by - LordShade on May 1, 2003 5:10:55 PM]
Hahaha, ISOPimp, your description sounds funny, but I'll explain it.

Basically, each Player is just an "entity" of someone in the game - I guess kind of a way of leaving the door open for multiplayer. When you respawn, the Ship you will control is then tied to your Player object. Each Player object holds thier own set of attributes, like thrust speed, fire rate, etc., so each Player can create thier own play-style. These attributes determine how the Ship they are controlling performs.

To do this, I have 'Player' accept the input from the input handler and translate it to simplified actions that 'Ship' uses. So when the game loop handles the 'Player's, 'Player" is where it says "if(key == up) myShip->AddControl(THRUST);" When the game loop gets around to handling all the 'Ship's in the universe, it runs through a small queue of controls, acting accordingly.

So like in the example I gave, the Ship you are controlling sees a "THRUST" command, which then should access a "myPlayer" member to do something along the lines of "XVEL += myPlayer->thrust * cosf(angle);" (from the top of my head). Soo, to make this run smoothly I need to have access back and forth between these 2 classes, hence the "Include Eachother (or achieve the same effect)".

Thats just to clear everything up though, as it seems that I already have the answer to my solution (thanks rypyr), but thanks to everybody that helped and gave input. If it doesn't work out right, I'm sure to be back again .

[edited by - neonfaktory on May 2, 2003 12:39:27 PM]
weee!

This topic is closed to new replies.

Advertisement