如何重构我的代码以避免从类外部引发事件?

Posted

技术标签:

【中文标题】如何重构我的代码以避免从类外部引发事件?【英文标题】:How to refactor my code to avoid raising events from outside the classes? 【发布时间】:2018-11-09 04:40:28 【问题描述】:

我正在开发一个游戏,其中包含一些用于不同任务的管理器,例如碰撞检测等。一旦检测到碰撞,受此碰撞影响的每个游戏对象都应该引发 OnCollided 事件,这样我就可以轻松播放声音,制作对象消失,打开一扇门或其他任何东西,但如果不从CollisionSystem 引发事件,而不是让每个GameObject 引发自己的事件,我就无法获得这种行为。

这是一个简化的例子,希望它有意义:

Class CollisionSystem

    // It is called when a collision has been detected between two objects (code not included)
    public void HandleCollision(GameObject gameObject1, GameObject gameObject2)
    
        //Do whatever
        //How can trigger each corresponding game object event from here?
    


Class GameObject

    protected event GameEventHandler Collided;

    protected void OnCollided(GameEventArgs e)
    
        if (Collided != null)
            Collided(this, e);
    

我已经测试了诸如公开 OnCollided 方法之类的东西,但是应该从类内部引发事件......而且,另一方面,游戏对象本身无法确定它何时发生碰撞,原因,好吧,这就是CollisionSystem 所做的。

提前致谢。

【问题讨论】:

请修复代码格式,它让我的强迫症感到不安,一个智能捆绑游戏开发绝地应该没有问题 就我在这里看到的情况而言,您的做法是错误的。 OnCollided 不应该引发事件,而是监听 Co​​llisionSystem 引发的 OnCollided 事件。但是,您希望能够将其提升为处于冲突中的对象,而不是所有订阅该事件的对象。 CollisionSistem 调用GameObject 中的公共方法(应该是带有y 的“系统”,除非它不是英语)然后引发事件? 抱歉,我是盲人,我很难在这里格式化代码,TheGeneral。 【参考方案1】:

好吧,这就是我能想出的应该体现你想要做的事情:

public class CollisionSystem

    Public void HandleCollision(IGameObject[] objects)
    
        foreach (IGameObject obj in objects)
        
            //call the function that tells the object it collided
            obj.CollisionDetected()
        
    

你会希望你的游戏对象实现一个接口

public interface IGameObject

    public void CollisionDetected()

这意味着你的游戏对象类看起来像这样;

public class GameObject : IGameObject

    //constructors, params, whatever
    public void CollisionDetected()
    
        //play some sound, remove object, whatever
    

问题是;我不知道是什么引发了您的碰撞事件。

编辑:所以我重读了你的问题,看到你提到它是从物理引擎开始调用的。无论在哪里/无论如何,如果您在物理引擎类中声明了您的CollisionSystem,您可以从那里调用HandleCollision()-方法,然后您就完成了。

【讨论】:

实际上,物理系统是指碰撞系统。当检测到碰撞时会调用 HandleCollision() 方法,因此参数只是发生碰撞的对象。我正在测试,但我认为你的答案效果更好! @D646 如果CollisionSystem-class 正在检测冲突,您可以简单地调用HandleCollision()-方法并给它一个数组(在我的示例中)IGameObjects(或其他任何东西您可能正在使用可能会发生碰撞的事件),而不必从外部引发事件,这使事情变得更加容易。 所以,我只是从 gameobject 类中删除事件,并实现一个公共方法,如 gameObject.hasCollided()¿ @D646 是的。请注意,您描述的HasCollided()-方法应该在GameObject-class 中。但是,我假设门可能不是GameObject,而是例如TerrainObject。这就是我提出接口的原因。这样,当您将碰撞的所有对象交给HandleCollision()-方法时,您可以将它们放在同一个数组中,正如我在回答中所展示的那样。

以上是关于如何重构我的代码以避免从类外部引发事件?的主要内容,如果未能解决你的问题,请参考以下文章

重构以避免在使用抽象类而不是接口时进行多重继承

修改/重构产品代码以支持集成测试的正确方法是啥?

重构时无法提取对封闭类方法的引用

重构 python 模块配置以避免相对导入

如何在颤动中从类(小部件外部)打开屏幕

由一个系统重构引发的思考