Accessing instantiated object from another class -

2019-07-21 23:27发布

问题:

I have a Player class, NPC class, BattleManager class, and Game class.

Player class stores/gets/sets player stats such as health, stamina, level, experience. NPC is similar, but is for NPCs. Game class instantiates Player class and NPC class. Game glass has two GameStates, battle and non-battle.

When the player is in battle, GameState goes to battle, when the battle finishes, it switches to non-battle.

What I'm trying to do is have the BattleManager class manage battles between the NPC and player, however, since the player and NPC object's are instantiated in Game class, I need to know how to pass that object or access it from BattleManager without instantiating a new one.

Can anyone suggest a general flow of how that might work? I know this is wrong, but is there a way to do something like Game.Player.Health -= damage;? For example, within the player class is public int Health get/set, how can I edit health from other classes when the Player class is instantiated in the Game class? Is there a way to pass the Player object around or just access the instantiated object created in the Game class from other classes?

回答1:

I liked to think that players and npcs are actors in a scenary... so I used to make a ActorManager class with the singleton pattern...

public interface IActor {
   Stats Stats {get;}
   Vector2 Position {get;}
   bool IsFighting {get;}
   bool IsActive {get;}  // Or whatever you need
}

public class ActorManager {

     public static readonly Instance = new ActorManager();

     ActorManager();

     List<IActor> _actors = new List<IActor>();

     public IEnumerable<IActor> Actors {get{ return _actors;}}

     public void Addactor(IActor actor) { ... }

     public IEnumerable<IActor> GetActorsNear(IActor actor, float Radius)
     {
         return _actors.Where( 
               secondary => actor != secondary 
               && Vector2.Distance(actor.Position, secondary.Position)<Radius);
     }

     // or whatever you want to do with actors

}

public abstract class Actor : IActor
{
   public Stats Stats {get; protected set;}
   public Vector2 Position {get;protected set;}
   public bool IsFighting {get;protected set;}
   public bool IsActive {get;protected set;} 

       public Actor() {
           ActorManager.Instance.Add(this);
       }

   public abstract void Controller();
}

public class Player : Actor { }  // Implements an input controller
public class Npc : Actor { } // Implements a cpu IA controller


回答2:

I agree with the first comment that it would be worthwhile to explore some design patterns.

If you want a quick and dirty answer then:

Modify your Player and NPC class to take the Game instance in on the constructor (another pattern is to have the Game object be global singleton... another pattern to explore).

Using the simpler approach here:

public class Game
{
    public Player PlayerProperty {get; set;}
    public NPC NPCProperty {get; set;}

    public foo() //some method to instantiate Player and NPC
    {
       PlayerProperty = new Player(this); //hand in the current game instance
       NPCProperty = new NPC(this);  //hand in the current game instance
    }
}

Then, in your Player and NPC class...

//Only example for Player class here... NPC would be exact same implementation
public class Player
{

    public Game CurrentGame {get; set;}

    public Player(Game gameInstance)
    {
        CurrentGame = gameInstance;
    }

    //then anywhere else in your Player and NPC classes...
    public bar() //some method in your Player and NPC classes...
    {
        var pointerToNPCFromGame = this.CurrentGame.NPCProperty;
        //here you can access the game and NPC from the Player class
        //would be the exact same for NPC to access Player class
    }
}

Typing this out of my poor tired brain so pardon any errors. Hope this helps.