Jump to content
  • Advertisement
Sign in to follow this  
Murmix

Send data between objects?

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

Hello game programmers,

I've been coding professionally for most of my life, sometimes games, sometimes other stuff. The reason I write this post is that I feel that I keep make (at least) one reoccuring "newbie design flaw" over and over again.

Let me try to explain with the current example:
I build a game. It's object oriented C#, everything is beautifully encapsulated and working fine.
There is a main "game" class and declarations of my objects:
public class MySuperGame : Microsoft.Xna.Framework.Game
{
MyPlayerClass thePlayer;
MyTilemapClass theTilemap;

//(...)
}

Problems begin when these objects need access to each other.
In this fabricated example, the "Player" class is doing collision checking with stuff on the Tilemap.

So, my options, I can either
1) Break out the logic, and do everything in the game class
MySuperGame.DoCollisionStuff(MyPlayerClass thePlayer, MyTilemapClass theTilemap)

or
2) cross-reference the pointers, for example initialize the player class with a reference to the tilemap
public MyPlayerClass(MyTilemapClass theTilemap [, textures and stuff]

or
3) just pass a pointer when it's needed:
protected override void Update(GameTime gameTime)
{
thePlayer.HandleCollisions(theGameTilemap);
//(...)
}


I have been mostly doing #3, but I feel that it's flawed design and it quickly becomes cluttered with unnecessary cross-referencing pointers and variables.

My next step is to make an "achievement system".
I imagine an AchievementHandler class that keeps track of everything that happens in the game, so this class needs to be accessible from every single corner of the code.

MyPlayerClass.DoJumpyStuff()
{
theAchievementHandler.Add(AchievementType.PlayerJumpCount, 1)
//(...)
}
MyLevelHandler.StartNewLevel()
{
theAchievementHandler.Add(AchievementType.LevelsPlayedTotal, 1)
//(...)
}
//etc.etc.


This makes me think even more urgently of a "good code"-solution to this dilemma.

I hope this makes sense. Thanks for reading, I value all feedback.

Cheers,
Murmix

PS: The game in question is Turtle Boogie, a little arcade action fun.
A concept prototype demo download is available here:
http://www.murmix.com/TurtleBoogie


Share this post


Link to post
Share on other sites
Advertisement
I prefer an own service (or sub-system if you like that term more) for e.g. collision detection, that is aware of structures especially to solve collisions but nothing else. Each object that want to participate in collision detection then has to register its appropriate structure with the service e.g. when the object is added to the scene. Perhaps like so:
void Player::onAddition( Scene & scene ) {
// registering with services
scene.collisionService->add( this->collisionVolume );
...
}

void CollisionService::detectAndCorrect( ) {
...
}

Share this post


Link to post
Share on other sites
This is a classic case of not applying the "single responsibility principle"; your player class, instead of just worrying about representing a player to the world is now worried about representing it AND how to collide with things.

The solution is to do what haegarr says and pull the logic out of the player class.

A setup I personally like for a 'player' class is not not have the player do much of anything, instead if acts more like a collection for various things.


// excuse the variable names, they are for example only
class Player
{
Renderable myModel;
CollisionVolume myCollisionMesh;

Controller myController; // gives the player instance input

// etc
}



The advantage here is that you don't need to worry about 'how' things are implemented, just that they are.

Your 'renderable' could be anything, from a model to a texture, came deal for the collision volume, and an input controller makes things like hooking network input up easy as it would translate both 'local' and 'remote' inputs into what is expected by the player logic.

You could even go one step further and have the 'update logic' be nothing more than a collection of function pointers/delegates which can be swapped/changed depending on game state.

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.

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!