【问题标题】:OOP C# - Design pattern for MMO mechanics simulatorOOP C# - MMO 力学模拟器的设计模式
【发布时间】:2014-01-05 22:32:08
【问题描述】:

我一直在为 FFXIV 开发一个模拟器;

我一直非常接近完成,然后我陷入了一个对象访问问题,我无法访问主要玩家的统计数据。我的项目可以在:https://github.com/eein/chocobro

我知道,我可以优化很多东西。 :P

基本上,我是一种蛮力操纵它以使对象能够访问他们需要的对象,但我正在寻找正确的做事方式。

我将开始重写它,所以不要太拘泥于示例代码,但它在那里可以看到我遇到的问题。 :(

理想情况下,在下一次尝试中,这是我想做的: 从一个包含有关播放器对象的所有信息的播放器类开始(将来,我想为全组模拟创建多个)。

类似:

int main(){
Player p = new Player();

public void setJob()
{
  if (job == "bard"){ Player p = new Bard(); }
  if (job == "warrior"){ Player p = new Warrior(); }
}

public class Player 
{
    private string name {get;set;}
    private string job {get;set;}
    private string STR;
    private string DEX;
    private string VIT; 
    //etc..

    public virtual void rotation()
    {
    }    
}

//I want to make the program a bit modular for jobs (roles/classes)
//So.. 

public class Bard : Player
{
    public override void rotation()
    {
        heavyshot.execute();    
        //etc.
    }

    Ability heavyshot = new Heavyshot();

    public class Heavyshot : Ability 
    {
        public Heavyshot() 
        {
            name = "Heavy Shot";
            potency = 150;
            dotPotency = 0;
            recastTime = 2.5;
            TPcost = 60;
            animationDelay = 0.8;
            abilityType = "Weaponskill";
            castTime = 0.0;
            duration = 0.0;
        }

        public override void impact() 
        {
            //add heavier shot buff activation here
            base.impact(); 
        }
    }
}

public class Ability{
public int cooldown;
public int cost;

public virtual void impact()
{
    public virtual void impact() 
    {
      //Deal some damage.
      // !! - the key problem is here, i want to initiate a roll to compare to the players CRIT rating versus the roll to determine the bonus damage. But I can't access the initiated players crit from here. The rating may change depending on abilities used so I can't create a new object. I know i need an object reference but I can't figure it out...
      log(time.ToString("F2") + " - " +  name + 
          " Deals " + potency + 
          " Potency Damage. Next ability at: " + nextability);
    }
}

我可能不太清楚,但基本上我希望能够从技能中获取玩家的暴击,并且我假设技能不能以这种方式设置以使其发挥作用。有谁知道我应该使用什么样的设计模式,以便能力中的虚函数可以访问父类球员的统计数据?

理想情况下,我希望吟游诗人类包含与吟游诗人职业相关的所有能力和统计更新,一旦吟游诗人继承了玩家并且对象被更改为引用吟游诗人对象,我如何使它成为由能力类在访问该函数时不需要在创建时对父级的对象引用。

我自己很困惑,但非常感谢理解我的胡言乱语并且可以提供帮助的人!

【问题讨论】:

    标签: c# mmo


    【解决方案1】:

    一种选择是将crit 传递给Abillity 的构造函数。

    另一个选项,如果Ability 始终连接到播放器。 将暴击属性公有私有集:

    public class Player 
    {
        private double crit { get; private set;}
        ...
    }
    

    然后将Player 传递给Ability 的构造函数并将其保存在那里。 但是请注意,这会增加coupling

    这可以这样完成:

    public class Ability
    {
        protected Player _player;
        public Ability(Player player)
        {
            _player = player;
        }
    }
    

    您还想更改从 Ability 派生的 Headshot 类

    public class Headshot : Ability
    {
        public Headshot(Player player) : base(player)
        {
            ...
        }
    }
    

    【讨论】:

    • 目前在我的 Job 类(基本上是玩家类)中,我有一个公共的 Int Crit。见这里:link - 理想情况下,我想使用吟游诗人的暴击等级是:第 54 行here,并在开始计算伤害时传递一个布尔值作为真或假(这也需要访问吟游诗人的统计数据)跨度>
    • 你有能力扩展 MainWindow 这似乎不正确。我认为将 Player 引用添加到能力类将解决您的问题。
    • 就像我说的那样,我一直在破解它以使事情正常进行。我不是一个高级程序员,所以我试图把我的头绕在我做错的事情上。我假设它与我的对象关系有关。也许有些应该以不同的方式与另一个类相关联。 @c0deMonk3y
    • 我编辑了答案,包括将玩家添加到技能中。希望这会有所帮助
    • 谢谢,我想这就是我要找的。我会尝试移动一些东西,看看是否有帮助。感谢您的洞察力!
    【解决方案2】:

    不是直接执行技能轮换,而是将技能保存在一个列表中。这样,您可以在 Player 中使用 setup 方法,将玩家注入到轮换的所有能力中。添加条件和某种“使用能力”,否定下一个能力实际上是在某种列表中表达轮换的另一个理由。因此,您不必在任何地方都重复“使用能力”检查,而是将它放在一个地方。像这样的:

    public class Player 
    {
        private string name {get;set;}
        private string job {get;set;}
        private string STR;
        private string DEX;
        private string VIT; 
        //etc..
    
        public struct RotationAbility
        {
            public RotationAbility(Func<bool> cond, Ability ability)
            {
                this.cond = cond;
                this.ability = ability;
            }
    
            public Func<bool> cond;
            public Ability ability;
        }
    
        private List<RotationAbility> rotation = new List<RotationAbility>();
    
        public void execute()
        {
            foreach (var ab in rotation)
            {
                if (ab.cond())
                    ab.ability.execute();
            }
        }
    
        public void setUpRotation()
        {
            setUpRotation(rotation);
            foreach (var ab in rotation)
            {
                ab.ability.Player = this;
            }
        }
    
        protected virtual void setUpRotation(List<RotationAbility> rotation) { }
    }
    
    //I want to make the program a bit modular for jobs (roles/classes)
    //So.. 
    
    public class Bard : Player
    {
        protected override void setUpRotation(List<RotationAbility> rotation)
        {
            rotation.Add(new RotationAbility(()=>buff>0, new Heavyshot());
            //etc.
        }
    
        public class Heavyshot : Ability
        {
            public Heavyshot()
            {
                name = "Heavy Shot";
                potency = 150;
                dotPotency = 0;
                recastTime = 2.5;
                TPcost = 60;
                animationDelay = 0.8;
                abilityType = "Weaponskill";
                castTime = 0.0;
                duration = 0.0;
            }
    
            public override void impact()
            {
                //add heavier shot buff activation here
                base.impact();
            }
        }
    }
    
        public class Ability{
            public Player Player { get; set; }
    
            public int cooldown;
            public int cost;
            public virtual void impact() 
            {
                //Deal some damage.
                // !! - the key problem is here, i want to initiate a roll to compare to the players CRIT rating versus the roll to determine the bonus damage. But I can't access the initiated players crit from here. The rating may change depending on abilities used so I can't create a new object. I know i need an object reference but I can't figure it out...
                log(time.ToString("F2") + " - " +  name + 
                    " Deals " + potency + 
                    " Potency Damage. Next ability at: " + nextability);
            }
        }
    }
    

    【讨论】:

    • 设计意图阻止我这样做,因为旋转是自上而下解析的,每个循环的每个能力都有条件。
    • @WillVolin 究竟是什么样的条件?也许您可以创建某种封装它的RotationAbility 类。并且你可以使用 lambda 表达式来制作漂亮的语法。
    • if (buff > 0){ ability.execute(); } if (cooldown
    • 在我接受之前关于这个的最后一个问题:在技能类中,我假设 public Player Player {get; set;} 将该对象调用为能力(如您所说的那样注入?)说我想使用玩家的暴击值(未显示 atm,但它将是 public int CRIT = 341;)我是否只使用 Player.在公共虚拟虚空影响()时暴击? @欣快
    • @WillVolin 是的,没错。
    猜你喜欢
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    • 1970-01-01
    相关资源
    最近更新 更多