Jump to content
  • Advertisement
Sign in to follow this  

Advice on Structuring My Classes

This topic is 4887 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

I'm currently implementing the enemy class into my game engine. However, I'm trying to decide where to put the class and how to go about getting access to variables in other classes. Consider this: I have my master class, CEngine. It includes the CPlayer class and the CMap class (as well as countless others, of course, but that's beside the point). Now, my CEnemy class requires information about the tiles from the map (CMap), as well as the stats of the player (CPlayer). Where would you stick CEnemy and why? And how will you go about getting the above information from CPlayer and CMap? I have came up with a few solutions that you can feel free to criticize. 1. Put CEnemy into CEngine, and keep a local copy of the map and the player inside CEnemy. When CEnemy is done with a function that affects something from the map or the player, CEngine should take CEnemy's local copies and copy them over CMap's or CPlayer's data. 2. Put CEnemy into CEngine, and give CEnemy pointers to CMap and CPlayer. This way, any alterations will occur automatically (though it sounds good, someone told me this is bad. I forget why...) 3. Put CEnemy into CEngine, and every time you need to run a function in CEnemy, you give it the required information via parameters. Then, changes can be returned from the function (this way, there are no local copies) 4. Your suggestion here. EDIT: forgot my third method in the original post.

Share this post


Link to post
Share on other sites
Advertisement
Why not have two function in CEngine one of which returns a pointer to the player and another a pointer to the map? Then when a CEnemy wants to access them for whatever reason it can.

Share this post


Link to post
Share on other sites
A member class (CEnemy) doesn't have access to its owner class (CEngine). It's no good having a pointer in the owner class when, really, it's the member class that needs it.

Unless, of course, you meant that I should pass that pointer to the CEnemy class, which is really my idea #2 from the original post.

EDIT: Whoa, bad terminology there. Used "parent" and "child" instead of "owner" and "member", misleading Koobazaur in the post right under me :P

Share this post


Link to post
Share on other sites
I'm no pro by all means, but here's my advice...

First of all, I would advice against putting cMap, cPlayer and cUnit into cEngine class. If I am understanding you correctly, cEngine would be a parent to those classes, thus they would all inherit the variables and functions of cEngine and honestly I don't see why would you want that. But that's just my way of thinking o_0

About your actual question... maybe just implement a GetValue() function(s) for the cMap and cPlayer, which would return specified info? Or maybe create a PlayerInfo and MapInfo class which would be filled with necessary stuff and passed to cEnemy (ala what windows does with some stuff)?
If you like, however, to take care of these things globally, instead of each unit controling itself, you might want to create a global function like Attack(cEnemy AttackingEnemy, cPlayer PlayerToAttack) ?
Last think I can think of is making a cUnit class and plugging cPlayer and cEnemy into it so that they are more uniform and thus can be managed more easily (like cUnit would have a function AttackUnit(cUnit UnitToAttack) ).

I know I didn't give you a definite answer cause I supposed I'm not skilled enough to make decisions for you ;) Hopefully I gave you some good ideas...

Share this post


Link to post
Share on other sites
Quote:
First of all, I would advice against putting cMap, cPlayer and cUnit into cEngine class. If I am understanding you correctly, cEngine would be a parent to those classes, thus they would all inherit the variables and functions of cEngine and honestly I don't see why would you want that. But that's just my way of thinking o_0
I think he means that his CEngine contains CMap and CPlayer, not that CMap and CPlayer inherits from CEngine.

I'd go with the approach Monder suggested.

Share this post


Link to post
Share on other sites
Quote:
Original post by Koobazaur
...
maybe just implement a GetValue() function(s) for the cMap and cPlayer, which would return specified info?
...


Well, once again, that comes back to the same problem discussed in my post right above yours.

I'm thinking that I'll stick to pointers (idea #2). Since CEnemy will constantly be altering CPlayer and CMap, it would be a good idea to have CEnemy just point to the original player and map instead of making needless copies.

Share this post


Link to post
Share on other sites
What i would do is have the overall engine grouped into large pieces.

So:

- Visuals.
- Controls, input etc.
- Backbone of the window, in windows it would be the messaging system the bits of the win32 api that give u the ability to havea d3d or ogl window.
- Sound.
- Support classes, like error handling, lists and vectors (if u ahev written your own) and other generic functions.
- networking etc.
- Game stuff, all the things like the entities for the enemies and objects etc.

For me it feels important to have these split up in such away that the interface between these groups is only one class. Maybe not one for each relationship but even just one over all, like an fsm class that could pass the pointers around.

I also feel that it is important for the classes to be as independant as possible. This would help make things more reusable, so that things that are being depended on are not so engine specific.

Visuals=======

I have decided, in my engine, that everything should revolve around a rasteriser, a class that actually does the drawing. This means that when the app is running, from the FSM class u only have to operate upon the rasteriser.

Controls
========

Everything should revolve around 1 class that controls 3 or more other classes which in turn would be 'setup' and 'updated' when appropriate.

Backbone
========
This should all revolve around an FSM.

ill leave the other 2 groups to you and bare in mind that this is only the basics.

Setting things out like this really has helped me envisage the way the engien should be pieced together and i hope it helps you too.

ace

Share this post


Link to post
Share on other sites
This design decision mostly depends on which instances you're going to need multiple instances of. Having multiple games running simultaneously (on a multiplayer sever) would rule out the singleton approach, supporting multiple players or maps (over- and underworld maps in RPGs) means that you'll need some kind of list per game.

As for the solutions
1. Just don't do this, keeping a seperate copy of the game map per enemy is horribly wasteful.
2. This can work, but it's still doesn't support multiple players or maps. Keeping track of multiple object pointers also greatly increases the probability of objects getting out of sync. A better version of this would be to hand out CEngine/CGame pointers from which the actors can retrieve any other game objects.
3. This is a good solution for certain objects. But it really depends on how often you need them, so it's probably not such a good idea for something as common as the game map.

How about using CActor as a base class for both CEnemy and CPlayer, and then placing both of these in an actor list? Maybe togheter with dedicated lists for actor subgroups.

Personally I'd go with global pointers to any objects I'm never going to have multiple instances of. Wheter this is accomplished through a simple global pointer or a nifty templated singleton class is up to you, it's still the same design.

Share this post


Link to post
Share on other sites
Quote:
Original post by doynax
This design decision mostly depends on which instances you're going to need multiple instances of. Having multiple games running simultaneously (on a multiplayer sever) would rule out the singleton approach, supporting multiple players or maps (over- and underworld maps in RPGs) means that you'll need some kind of list per game.

As for the solutions
1. Just don't do this, keeping a seperate copy of the game map per enemy is horribly wasteful.
2. This can work, but it's still doesn't support multiple players or maps. Keeping track of multiple object pointers also greatly increases the probability of objects getting out of sync. A better version of this would be to hand out CEngine/CGame pointers from which the actors can retrieve any other game objects.
3. This is a good solution for certain objects. But it really depends on how often you need them, so it's probably not such a good idea for something as common as the game map.

How about using CActor as a base class for both CEnemy and CPlayer, and then placing both of these in an actor list? Maybe togheter with dedicated lists for actor subgroups.

Personally I'd go with global pointers to any objects I'm never going to have multiple instances of. Wheter this is accomplished through a simple global pointer or a nifty templated singleton class is up to you, it's still the same design.


All right, based on your advice, I'm thinking of a combination of my #2 and #3. How's this:

Since copying the map per enemy is a bad, bad idea, we won't have that. Instead, we pass a pointer to the original map to every function that requires it. Obvious pseudocode example:

CEnemy::Move( const CMap& map )
{
if( map.can_move_east(enemy_location))
{
move_enemy
}
}

Passing the map as a pointer (err... reference) won't copy the map, will it? Would this be a viable solution?

Share this post


Link to post
Share on other sites
Quote:
Original post by v0dKA
Passing the map as a pointer (err... reference) won't copy the map, will it?
It won't make a copy. References are little more than an alternative syntax for pointers.
Quote:
Original post by v0dKA
Would this be a viable solution?
I would advice against this in this specific case (the map pointer). However it can be a better option for other systems.

Many virtual methods would have to take these objects as parameters just in case some specific class would need it thirteen levels lower in the inheritance chain.
There's also the problem of having too many such objects. It wouldn't be fun to have to pass around the map, player, audio manager, etc to every function that *might* require it somewhere deep in a call chain.
Not to mention that it would make it impossible to access the map in destructors.

This design is a much better choice for those objects that should only be accessed under very specific circumstances. Lets say passing around the frame buffer to a virtual draw method implemented by each actor. It might also work for passing players/enemies to eachother since it's usually some external system that introduces them anyway (i.e. the collision system).

As always this depends a lot on the complexity of your game.
Try experimenting with a few different solutions, it'll only cost time. You'll learn much more trial and error than you ever could from listening to my ramblings.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

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

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!