Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Gwahir

Can't find ANY info about how to get data from one part of an OOP to another.

This topic is 5734 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

It''s driving me nuts. I''ve read three books on the subject, and none of them address the problem specifically, but rather ramble on and on about abstraction and encapsulation and other useful yet irrelevant subjects. All about how hiding data is so great, yet I can''t hide every variable from every other variable lest my program become inoperable, but they give no hints as to the proper ways to share data. I am left with a firm conviction that information hiding is good, but have no clue how to share the information that it is neccesary to share, or how to make classes know how to call other classes. Their example programs aren''t even any help, since they seem to always be some lame finance program that has no complex data structures and no complex output to the screen. For instance, I am currently in the concept stages of a simple hack''n''slash RPG. I''m trying to figure out what kind of code structure I''m going to use, and I''ve pretty much decided OOP is the way to go. It''s go so many nice features. So I lay out which classes I need. Well, it''s pretty obvious I''ll need classes for the game world, the current map, the player, monsters, items, ect. And a class to put everything on the screen, and to a class to recive input from the player, and a class for file IO. But these classes are not all self-sufficient entities. The player class needs to know about the game world. The monsters need to know about the player. The player needs to know about items. Most importantly, the display needs to know everything, and everything needs to be able to get input. I can''t figure it out... The only way it could work at all is if all the instances of classes were global variables and every class knew the name of every other class, hardcoded into it''s methods. But unless I misunderstand my books, this goes against all the principles of information hiding and encapsulation. If every class knows all about every other class, then what''s the point of using OOP at all? Any help would be greatly appreciated.

Share this post


Link to post
Share on other sites
Advertisement
Ever consider using singletons? There is a GD article somewhere around here, but if you are serious about OO Programming in C++ (I assume you are using C++), I suggest you read the book "Modern C++ Design". Either way, singletons use a static method to access an instance of the singleton, and also maintain that only one instance of the class ever exists. So from anywhere in your code you could access the object.



_______________________________
It''s not reality that''s important, but how you perceive things.

A man''s reach should exceed his grasp.

Share this post


Link to post
Share on other sites
What I would suggest is to not make your game too general. A game has several components (input, audio, graphics) -- so why is it bad design or not a good idea to allow one class the ability to "know" about some other class?

Share this post


Link to post
Share on other sites
I''m trying to use a system with a CGame class that contains instances of the other main classes - CInput, CGraphics, etc. Cgame knows about and interfaces with the other classes, and those don''t know about each other.

I haven''t gotten very far with it yet, so I''m not sure how well it''ll work, but it''s a thought.

Share this post


Link to post
Share on other sites
First off. Good work Gwahir.
I can tell your new to programming, but youll make an awesome programmer. I''m sure of that.
Taking the time to formulate a good question, and do your research as you did is the most important thing. (If only more people on these forums would do just that, we''d all be a happier bunch.)

I found myself asking those same questions when I was learning about OOP.

What people mean when they talk about Abstraction, and Encapsulation is clearly seperating details and implementation from the purpose.

For example, say you have a class that represents a creature in your program. (don''t mind the psuedo-code )

If it was a C style structure, it might look like this:

struct Creature {
int health;
char* name;
};

The C++ style, object oriented equivalent would look like this:

class Creature {
public:
int GetHealth();
void ChangeHealth(int Delta);
string GetName();
void SetName(string Name);

private:
int m_health;
int m_name;
}

The purpose of the variables, is to keep track of a name, and a quantity of health for a creature. _HOW_ the name is stored, and how health is stored should never need to be known by another class.

If another class wants to find out the health of a creature, it does SomeCreature->GetHealth() and gets an int.
However, SomeCreature doesnt need to store an int internally, it could in fact keep the health in a database, as a string. Its all up the the implementation of Creature.

So whats all this shit mean?

You want program code to look like:
Creature SomeCritter;
cout << SomeCritter.GetName();
SomeCritter.ChangeHealth(-25); // Wound the critter

Never like this:
Creature SomeCritter;
cout << SomeCritter.m_name;
SomeCritter.m_health -= 25;

They may look the same at first, but the first one is the object oriented way.

-------

The names of methods shouldnt change ever really (provided you picked em right the first time hehe).
However, the details inside can change alot. So don''t worry about ''hard-coding'' the method names. Thats what there for.

...
The name and parameters of a method is its interface.
The code block that is executed when called is the implementation.

Interfaces should seldom change, implementation changes all the time.
...

-------

So now your probobly thinking "okay, I understand that.. So how do I organize all these little instances of my neat, properly written clases?"

Ha.. This is where the fun begins.
Perhaps you have one or two global variables, or one or two singletons.
C++ isnt java. You need _some_ global shit. So don''t be scared to have a few things global (but I do mean a FEW).

Inside those global objects, youll have either arrays, vectors, or maby something like trees populated with objects.

Objects communicate between eachother by sending events. (In the real world of C++ ... ''events'' are actually method calls)

-----------

Hope that helps you understand,
Feel free to ask me to clear up any vauge parts. (There is probobly a ream of them)

NOTE to potential flamers:
Drop that flamethrower. I am not saying OOP is good, or bad. I''m not saying globals are good or bad. I am not promoting or insulting Java, or C++. I''m not telling kids to play in traffic. I am just attempting to smash some confusion.
So please, dont flame me on details. Its just the idea that matters after all.
Thanks!
- Jacob

Share this post


Link to post
Share on other sites
Hey cool, I''m doing the same thing

Only problem I''ve really come accross is putting to much stuff into my COpenGLSubsystem

I think thats mostly because I''m still at renderer development stages, so I need a lot of test info in there. Eventually I''ll ship it out to seperate classes and stuff.



"With my feet upon the ground I lose myself between the sounds and open wide to suck it in, I feel it move across my skin. I''m reaching up and reaching out. I''m reaching for the random or what ever will bewilder me, what ever will bewilder me. And following our will and wind we may just go where no one''s been. We''ll ride the spiral to the end and may just go where no one''s been." - Maynard James Keenan
Name: TheBlackJester
Team: Wildfire Studios

Projects
O A.D.
The Last Alliance

Share this post


Link to post
Share on other sites
quote:
Original post by Gwahir
But these classes are not all self-sufficient entities. The player class needs to know about the game world. The monsters need to know about the player. The player needs to know about items. Most importantly, the display needs to know everything,



Could the world ask the player object what it needs to know?
Could the world tell the player object what has been done to it?
Could the monster ask the player object what it needs to know?
Could the monster tell the player object what it has done to it?
Could the player ask each item about its properties?
Could the player tell each item what it is doing to it?
Could the display ask each displayable object how it looks?

This is actually not an OOP problem. It''s a large-scale project problem. The issue is circular dependencies, and it''s quite possible to run into the same issue in a strictly procudural design as well as OOP. I highly recommend reading Lakos''s "Large-Scale C++ Design"; he gives many methods of fixing circular dependencies.

quote:

and everything needs to be able to get input.


Ah, input is trickier, but there is a way to do it. I don''t know exactly what kind of input you''re using, but you probably need the "Visitor" design pattern.

Making everything global is not something that will scale well with project size. And I recommend against using singletons as a panacea.

HTTP 500 strike 1..

Share this post


Link to post
Share on other sites
The way I''m solving this sort of problem is by having a bunch of managers, or just one large manager. It''s a gateway of sorts to other classes and their functions.
But to do this I need to declare the manager as an extern in every file that needs to access the manager, so this solution is not as perfect as I want it to be, but it works pretty well and you can track things through classes without a problem.

You can also easily create a function like GetHwnd() within manager, this function then points to another GetHwnd()-function in the class that currenly has the Hwnd. So if you ever need to move the Hwnd(or whatever it is) you just need to rewrite one line of code inside the manager instead of repointing every line that accesses the variable/function of your choice. Hope I makes some sense, I''m a bit tired right now


Anyway, to the main benefit of this, if I created a creature in a class handling NPCs which in itself is a subclass to a game-class and then wanted to access the world-class from my creature it would look something like this:

(inside the creature-class)
(from Game->NPC->Creature)manager->Game->World->Whateverfunction();
If I want to access a creature from World it would look like this:
(from Game->World)manager->Game->NPC->Creature->GetState();

This strings become quite lengthy at times but you can copy the location of a class into a pointer to cut it down in size, this pointer is declared and created within the class you want to have the shortcut. So the long string above would instantly be cut down to Creature->GetState within the world-object.
If done right this system is quite good but it takes some planning to get right.

Share this post


Link to post
Share on other sites
Thanks guys, I'm glad I decided to ask here. Learned about as much in your posts as I did in reading a whole book full of techno-babble. Which has it's place, but it certainly isn't conductive to learning.

I'd like to clear up a few things, however...

quote:
Objects communicate between eachother by sending events. (In the real world of C++ ... 'events' are actually method calls)


Ok, I think I see that. But a class cannot call another class's method unless it knows the name of the other class... Let me try to show a quick example of my problem in the interaction between three classes: CPlayer, CMonster, and CInput.


  

class CPlayer
{
public:
void AttackMonster(CMonster &monster);
//other junk


private:
int damage;
//other junk

}

class CMonster
{
public:
void TakeHit(int damage);
//other junk


private:
int armor_value;
int hitpoints;
//other junk

}

class CInput
{
public:
void CheckKeyboard(void);
//other junk


private:
//other junk

}

void CPlayer::AttackMonster(CMonster &monster)
{
monster_ID->TakeHit(damage);
}

void CMonster::TakeHit(int damage)
{
hitpoints -= (damage - armor_value);
}

void CInput::CheckKeyboard(void)
{
if(keydown(x))
{
Player->AttackMonster(Monster);
}
}



So there I have my classes. That, to my best understanding, is a perfectly legitimate setup. But here comes my problem. In order for CInput::CheckKeyboard to function correctly, it needs to be able to acces the variables 'Player', an instance of CPlayer, and 'Monster', an instance of CMonster. How?

To have 'Player' and 'Monster' be global would work, but would quickly become cluttered and difficult in a large program.

To have 'Player' and 'Monster' be members of CInput would work, but would become totally unfeasable in a larger program, because there would be other classes besides CInput that would need acces to those variables.

And I can't think of any other way to do it. So how would you do what I tried to do in that code example?

And Stoffel, are you the same Stoffel from the Heavengames KoRT forum?

[edited by - Gwahir on December 6, 2002 3:51:22 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I would move this code out of CInput:

if(keydown(x))
{
Player->AttackMonster(Monster);
}


Instead, CInput could report what happened to the game world, say CGame:

if(keydown(x))
{
pGame->OnPlayerAttackAction();
}


CGame then determines the following:
If there is more than one player-controlled character, which one is active (has the focus)?
Is there a monster in front of player? If so, send that monster to the player''s method:

CPlayer* pCurrentPlayer = GetCurrentPlayerCharacter();
CMonster* pMonster = GetMonsterInFrontOfCharacter();
if (pMonster != NULL && pCurrentPlayer != NULL)
pCurrentPlayer->AttackMonster(*pMonster);


So, CInput has a pointer to CGame; or CGame can be a singleton, and CInput accesses it through GetInstance(). CGame needs to know about CPlayer and CMonster, but that seems logical...how could the game NOT know what it contains?

This also allows CInput to support customized key layouts...x could be mapped to "RunLikeHell()" instead of attack, simply by changing which function is called in pGame.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!