Code design confusion

Started by
5 comments, last by ToohrVyk 15 years, 4 months ago
I made a topic a while ago with a similar problem. I'm just finding the design of OO programming difficult (no globals, lower-level objects shouldn't depend on high-level objects, etc). Let's say i have three classes. Map, Zone and Player. Zone stores a list of all the players and entities within the zone and it also stores a reference to a "map" which stores backgrounds, tiles, walls, spawn points. Let's say the player presses the Left key on his keyboard. How do i make the player move? Like this:
zone->CharacterJump(player);
or
player->Jump(zone); //now player depends on the zone...:(
What is the standard design that most people use for stuff like this?
Advertisement
Why do the zone or the player need to know about each other at all in order for the player to jump??
Quote:Original post by Nypyren
Why do the zone or the player need to know about each other at all in order for the player to jump??


The player can only jump if there is a wall below the player.
void Player::Update(){    if(is_wall_under_me() && jump_key_down()){        jump();    }}bool Player::is_wall_under_me(){    return zone->get_wall(my_position) != NULL;}


Or something like that. Just a thought.
Quote:Original post by 39ster
What is the standard design that most people use for stuff like this?


Pick one. Classes can depend on others. If a player is only usable with a zone, then do player->jump(zone) (or player->jump() and it can figure the zone from contained data). Or if applicable, a free function that knows about them both.

But pick one; make one know of the other, but not vice versa (or something know about them both, but they know nothing of each other or the 'tie' class). Dependency trees are easy to deal with; dependency webs are less good.
Whether or not the player is able to jump should not be determined by whether or not there is a wall beneath the player, it should be determined by what state the player is in. If the player is in the idle or running state they should be able to jump (assuming this is how your game works, ignoring the possibility of, say, an air hike). What state the player is in should depend on a number of factors, and a number of things should depend on the player state. I often see states implemented as a simple enumerated list of states, and a function that looks like Player::ChangeState(int newState) which the player or the zone for instance can call. Somewhere (possibly in your zone) you would likely want logic to handle collisions, possibly in a CollisionManager class which could have access to the map data in a number of ways. Then, when you loop over all your collidable entities (such as the player) you pass them (or just their bounding box rectangles) into this CollisionManager with a function like bool CollisionManager::CheckCollision(Rect *mapObjectBoundingBox) or something like CollisionVector CollisionManager::CheckCollisionAgainstMap(Rect *mapObjectBoundingBox, MapData *mapData), or if you wanted the CollisionManager to be able to call the change state or whatever tranlate/move/reposition function in the GameObject or Entity or whatever you just pass that in. Basically CollisionManager is a class that depends on a minimal subset of the dependencies of the Zone, so the logic could technically just be put in the Zone, but that would clutter things up pretty bad once you start putting like cross-entity collisions and all this other collision logic in there.
1° The player character is a self-contained model object (that is, it represents the internal state of the player character, without any kind of relationship to the outside world).

2° The zone is a model object representing the structure of the level.

3° The jumpRule is a model rule object which is used for having the player character jump inside a zone.

So, player.jump() does not check whether there's something below: it just jumps. The zone doesn't need to know whether a player exists within itself (it may only know, for instance, that a moving object is present, but not that it is a player). It does provide, however, an accessor zone.isSolid(position) to determine whether ground is present.

And then, your jump rule does the following:

class jumpRule{  public override void jump(Player p, Zone z)  {    if (z.isSolid(p.position().underfoot()))     {      p.jump();    }  }}


This way, neither zone nor player need to know about each other, and you can replace a jump rule with another (double-jumping, wall-jumping) as you wish, even at runtime.

This topic is closed to new replies.

Advertisement