tags:

views:

74

answers:

1

Hi, I have a question re object-oriented design - I have two classes, a Map (in effect an x,y grid) and Items placed on the map. The Map holds all the items and their locations and controls the program flow. The Items have some intelligence and determine if the wish to move around on the map.

For instance the map code may look like:

class Map
{
    ...
    Items[,] map;

    public void DoItemUpdate()
    {
        ...
        for (x = 0 to MaxX)
        {
            for (y = 0 to MaxY)
            {
                    map[x,y].UpdateItem();
            }
        }
    }
}

And the Item code may look like:

class Items
{
    ...
    Vector2 location;

    public void UpdateItem()
    {
        // determine if we want to move the unit
        ....

        // if yes, move the unit
        this.Move(fromXY, toXY);
    }

    public void Move(Vector2 from, Vector2 to)
    {
        // what goes in here - raise event, use reference to Map class?
    }
}

Basically what I'm trying to work out is how the move code should be structured so that it asks the map if the move is legal, and then registers the move in the map.

I have thought of a couple of approaches

  1. Pass a reference to the parent Map class to the Item and call a function from there
  2. Use a delegate / event structure to "callback" the map

Any comments on these approaches - what is the best/cleanest/most appropriate for OO code? Thanks!

+3  A: 

Neither. I'd add a method to your Items (should that be Item?) class:

Vector2 GetMoveRequest();

Define a constant value that the Item can return to indicate that it does not want to be moved. (0, 0) if the return value indicates a delta, or (-1, -1) if the return value indicates an absolute position. Or if you don't want to define a magic value:

bool TryGetMoveRequest(out Vector2 request);

Advantages:

You've now separated the move logic appropriately across the two classes. The Item knows if it wants to move, and if so where. The Map can evaluate the legality of the move, then perform or ignore the Item's move request based on your logic. No reference handling, no awkward callback mechanism.

In addition, the logic within your Map class will be able to grow in complexity. Consider a scenario in which one Item's move may prevent, or be prevented by another Item's move. This would be considerably difficult to implement with either of the approaches that you've listed.

anthony
Keep in mind the sequence <Item> get evaluated affect the behavior of the system.
YeenFei
yes but by separating the move request from the move operation, you can adjust that sequence as appropriate in between collecting the requests and performing the moves.
anthony
Thanks Anthony - to paraphrase, the Item could store a queue of move requests, the Map can assess them through Item.TryGetMoveRequest(out ...), establish legality and make a call to a method such as Item.PerformMove()?
mecharius