GameObjects and Code Structure

2019-09-19 01:09发布

问题:

I have the following GameObject interface:

public interface GameObject {
     void viewDetails();    
}

Character Interface:

interface Character{   
    void pickUp(Weapon weapon);
    void use(Weapon weapon);
}

and abstract Weapon class:

public abstract class Weapon implements GameObject {

  //left out constructor to focus on methods

   @Override
   public abstract void viewDetails();
   public abstract void attack(Enemy enemyObj);
   //Could be bullets, could be a mystical item.
   public abstract void replenish(ReplenishItem rpItem);
}

The problem with this is, a GameObject sometimes can be used in different ways. For example, the primary use of a game weapon is to attack a target, but what if I wanted to reload? How do I let my character interface reload or beware that reload is an option?

回答1:

I would use the following approach.

I would declare interfaces:

interface MeleeWeapon {
    void hit();
    void cut();
}

interface FirearmWeapon {
   void fire();
   void reload();
}

interface MagicWeapon {
   void throw();
   void apply();
   void recharge();
}

Then implement classes, like these:

class Knife implements MeleeWeapon {
     public void hit() {

     } 

     public void cut() {

     } 
}

class Dagger implements MeleeWeapon {
     public void hit() {

     } 

     public void cut() {

     }     
}

class GarandRifle implements FirearmWeapon {
     public void fire() {

     } 

     public void reload() {

     }     
}

class Fireball implements MagicWeapon {
     public void throw() {

     } 

     public void apply() {

     }     

     public void recharge() {

     }     
}

Then, I would declare these interfaces:

interface MeleeWeaponUser {
    void use(MeleeWeapon weapon);
}

interface  FirearmWeaponUser {
    void use(FirearmWeapon weapon);
}

interface MagicWeaponUser {
    void use(MagicWeapon weapon);
}

And, I would declare character classes:

class Peasant implements MeleeWeaponUser {
    public void use(MeleeWeapon weapon) {

    }
}

class Marine implements MeleeWeaponUser, FirearmWeaponUser {
    public void use(FirearmWeapon weapon) {

    }

    public  void use(MeleeWeapon weapon) {

    }
}

class Sorcerer implements MeleeWeaponUser, MagicWeaponUser {
    public  void use(MeleeWeapon weapon) {

    }

    public  void use(MagicWeapon weapon) {

    }
}

This approach let us add new weapons and characters without sufficient effort later.

In your use() method you can call reload() if there is no more ammo in the weapon dispenser.

But if your game character receives signal from outside, for example, reload the gun, even there is enough ammo to fire, then have an Event->Listener approach implemented.

Create a WeaponEvent class, extend this class to have FirearmWeaponEvent, MeleeWeaponEvent etc.

Make your game character class(es) as a listener to WeaponEvent events, then in your game character class have a method processEvent(WeaponEvent event), and act accordingly to the event you have received.