tags:

views:

56

answers:

5

I have an abstract class Moveable with the method abstract void move() which is extended by the class Bullet and the abstract class Character, and Character is extended by the class Survivor and the class Zombie. In Survivor and Bullet the move() method doesnt require any parameters while in the class Zombie the move() method depends on the actual position of the survivor. The survivor and multiple zombies are created in the class Gui.

I wanted to access the survivor in Zombie - what's the best way of doing this? In Gui i wrote a method getSurvivor() but i don't see how to access this method in Zombie?

I am aware that as a workaround i could just pass a [Survivor survivor] as parameter in move() and ignore it in Bullet and Survivor, but that feels so ... bad practice.

A: 

It depends where your Survivor is being held. Your Zombie will need a reference to a Survivor from somewhere - what does it need it for? Who should be responsible for providing this?

It sounds like your Gui is doing too much actually, I'd prefer to have a class called something like GameState that manages the positions and then just have the Gui handle the output. In any case, if there's a single survivor you can simply have a getSurvivor() method on your Gui/Gamestate - and the Zombie should probably have a reference to the current game state that it's part of. Alternatively you could make the GameState a singleton, and the Zombies could access it that way.

Edit: In response to your comment, perhaps something like this:

public class Zombie
{
   private final Gui guiThatMadeMe;

   public Zombie(Gui owner)
   {
      guiThatMadeMe = owner;
   }

   ....

   public void move()
   {
      Survivor guy = guiThatMadeMe.getSurvivor();

      // Do whatever you need to with the survivor
   }
}


public class Gui
{
   private Survivor lonelyGuy;

   ... 

   public Survivor getSurvivor()
   {
      return lonelyGuy;
   }

   public void createNewGame() // I'm guessing you have some method like this
   {
       lonelyGuy = new Survivor();
       for (int i = 0; i < NUM_ZOMBIES; i++)
       {
          Zombie zombie = new Zombie(this); // pass in this reference
          // Do something with the zombie
       }
       // other setup
   }
}

In any case, the Zombie will have to obtain a reference to something that knows how to get the survivor. An alternative option would be to have the Survivor passed directly into the Zombie, but that doesn't feel quite as clean somehow. It might be a viable option if Zombies must always have one and exactly one Survivor, but that feels like an artificial limitation.

Andrzej Doyle
Hey, the gui creates one instance of Survivor (lets call it lonelyGuy), there is no grid, lonelyGuy has getX, getY methods.All zombies have to walk in the direction of lonelyGuy. (zombies = ArrayList<Zombie> created in gui), if i could address the gui (e.g. classThatMadeMe.getSurvivor()) all would be fine :), thanks for getting involved!
Samuel
How do i create the reference to the survivor?
Samuel
you need to have a game class or so that knows all players. game.getZombies() returns a List of zombies, game.getSurvivor() returns the survivor
seanizer
Yeah, there's no such implicit thing as `classThatMadeMe` (besides, it would be an *object instance* rather than a class most likely). What you can do is have your `Zombie` constructor take a `Gui` parameter, which you can then store as a field of the Zombie and hence call methods on it. See my edit for an example
Andrzej Doyle
Thank you, this way it seems clear to me :) (+ i could indeed add a second survivor)
Samuel
Two player mode is always more fun in zombie games. :-)
Andrzej Doyle
A: 

If there's only one Survivor, you should look into the Singleton design pattern.

crazyscot
Okay but how could i access the one instance of the Survivor class?
Samuel
@crazyshot I strongly disagree. Game (in an offline context), GUI, etc can be singletons, but making a player a singleton limits extendability (multi player is a no-go then)
seanizer
@seanizer Fair point. _Something_ could happily be a singleton, perhaps something implementing GameState as suggested in an earlier answer.
crazyscot
@Samuel: Go and read up about the http://en.wikipedia.org/wiki/Singleton_pattern . There'd normally be a static method named `getInstance()` or similar.
crazyscot
+2  A: 

In real world (hehe) the zombies start moving towards the survivor when they detect the survivor.

So you could start the modeling by adding method .detect(Survivor) to your Zombie class. Or .follow(Survivor). In this simplified model your Gui class that creates the survivor and the zombies you could simply call the detect method of the Zombie with a reference to the Survivor. And to Moveable you could add method for getting the current location.

And don't forget to pack a shotgun when you go out.

fish
Sounds good! (Moveable provides these methods), thank you :)Why no flamethrower?
Samuel
@Samuel: It's bulky, high risk of friendly fire (no pun intended) and the amount of ammo you can carry is relatively much lower than good ol' 12-gauge. No hopping over chain-link fences with one of those bad boys strapped to your back either!
Andrzej Doyle
In real world... :D (makes sense though)
Samuel
If Survivor is a Singleton then the risk of friendly fire is negligible. ;-)
DJClayworth
A: 

Actually, I would say that move() should not be a method without parameters. The semantics of Move imply that there is a target to move to, so it should be either

move(Target t)

where Target is an interface that is implemented by Zombie and Survivor or

move(Position p)

Preferably, you can find an abstraction that covers both (a Target, for example could be either a target person or a target position)

seanizer
I think you are on the right track, but this would imply that someone else decides how all different dudes move. When in reality the survivor is (probably) the only one moved by an outside force (player) and for example zombies make their decisions themselves. The bullet has a starting direction, but after that it "decides" its own movement according to its own rules. This of course contains a number of assumptions on the project... :)
fish
Well the main character is guided around using arrow keys, so his move method is basicly incrementing (decrementing) x or y values, he wouldnt have a real target
Samuel
@ fish good guess, pretty much how it works :)
Samuel
@fish: exactly. now the task would be to find a common abstraction for a) the keystroke, b) the zombies "strategy" and c) the bullet's direction of flight, the abstraction being on the base of "give me a new position based on this old position in the given time frame"
seanizer
A: 

Extending @Andrzej Doyle's GameState idea above...

If all the Zombie needs from the (potentially complex) Gui class is the position of the Survivor, have Gui implement a simple interface with just that method and have Gui pass an instance of itself to the Zombies when it constructs them.

That makes Zombie more testable as only a single method needs to be mocked out.

interface GameState {
  Survivor getSurvivor();
}

class Zombie extends Character {
  public Zombie(GameState gs, ...) {
    this.gs = gs;
    ...
  }
  ...
}

class Gui implements GameState {
  ...
  private createZombie(...) {
    return new Zombie(this, ...);
  }
  ...
}
pdbartlett
I don't think Zombies should have a GUI as a member, that's just not right (there's no has-a-relation between a zombie and a gui). There should be one GUI available (threadlocal or singleton or whatever) with a global access method, something like GameContext.currentInstance().getGui();
seanizer