C#当您发现自己需要按特定顺序执行事件时的设计模式
我正在用C#制作一个游戏,当玩家移动时,通过事件通知两个不同的类 其中一个类是C#当您发现自己需要按特定顺序执行事件时的设计模式,c#,events,design-patterns,observer-pattern,C#,Events,Design Patterns,Observer Pattern,我正在用C#制作一个游戏,当玩家移动时,通过事件通知两个不同的类 其中一个类是RenderGrid,当玩家移动RenderGrid时,RenderGrid将只实例化现在在屏幕上可见的新游戏块。它还包含两个向量,描述当前正在渲染的栅格的左下角和右上角 另一个是WorldManager类,当玩家移动时,该类将检查是否需要加载和创建游戏世界的新区块。为此,它需要检查RenderGrid的角点,以确保它们仍在已加载块的边界内 这就是问题所在,因为WorldManager依赖于首先在RenderGrid上
RenderGrid
,当玩家移动RenderGrid时,RenderGrid将只实例化现在在屏幕上可见的新游戏块。它还包含两个向量,描述当前正在渲染的栅格的左下角和右上角
另一个是WorldManager
类,当玩家移动时,该类将检查是否需要加载和创建游戏世界的新区块。为此,它需要检查RenderGrid
的角点,以确保它们仍在已加载块的边界内
这就是问题所在,因为WorldManager
依赖于首先在RenderGrid
上处理的事件,然后在WorldManager
上处理,从而打破了事件模式
在伪代码中,以下是RenderGrid:
public class RenderGrid
{
public Vector2 bottomLeft;
public Vector2 topRight;
public RenderGrid()
{
Player.onPlayerMoved += playerMoved;
}
~RenderGrid()
{
Player.onPlayerMoved -= playerMoved;
}
private void playerMoved(Vector2 delta, Vector2 position)
{
// updates the bottomLeft and topRight corners
}
}
和世界网格:
public class WorldGrid
{
public WorldGrid()
{
Player.onPlayerMoved += playerMoved;
}
~WorldGrid()
{
Player.onPlayerMoved -= playerMoved;
}
private void playerMoved(Vector2 delta, Vector2 position)
{
// it needs the corners of the renderGrid, but since those are also updated when player moves, we can't be sure
// wheter they've been updated here or not
}
}
使用一个单独的事件来通知
RenderGrid
角落已更新,听它似乎是确定的意大利面,我不确定如何从这里开始除了关于事件顺序是否得到保证的传说争议之外:
问问你自己,谁对这个事件负有最大的责任,那么这个人应该首先做出反应。在此基础上,在WorldGrid和RenderGrid之间注册另一个事件(使用不同的名称)有什么不对
如果RenderGrid归WorldGrid所有,反之亦然,您甚至可以定义并调用RenderGrid.NotifyContentLoaded或WorldGrid.NotifyBordersChanged。链接事件
看起来RenderGrid
应该处理指示玩家移动的事件RenderGrid
然后可以发布自己的事件。WorldGrid
将订阅这些事件,因此只有在Rendergrid完成处理后才会触发
典型的模式是设置自定义事件参数、委托和处理程序,如下所示:
自定义事件参数,处理程序委托:
public class PlayerMovedEventArgs
{
public Vector2 Delta { get; set; }
public Vector2 Position { get; set; }
}
public delegate void PlayerMovedHandler(object sender, PlayerMovedEventArgs e);
然后渲染网格:
public class RenderGrid
{
public Vector2 bottomLeft;
public Vector2 topRight;
public Player _player;
public event PlayerMovedHandler Changed;
public RenderGrid(Player player)
{
_player = player;
_player.OnPlayerMoved += PlayerMovedInGrid;
}
private void UpdateCorners(Vector2 delta, Vector2 position)
{
//ToDo: Update corners
}
private void PlayerMovedInGrid(object sender, PlayerMovedEventArgs e)
{
UpdateCorners(e.Delta, e.Position);
OnChanged(e);
}
protected void OnChanged(PlayerMovedEventArgs e)
{
if (Changed != null) Changed(this, e);
}
}
最后是世界网格。这里的重要变化是WorldGrid订阅RenderGrid的事件(而不是玩家的)
也许是某种优先级队列?单独的活动似乎是正确的方式,你没有选择,真的。不能保证多播委托调用顺序。当需要执行两个以上的委托调用时,优先级队列不是更适合吗?我的印象是C#中不支持析构函数,您应该使用
Dispose()
方法,并确保您的类实现了IDisposable
。我一定会仔细研究它,谢谢大家的宝贵意见
public class WorldGrid
{
private readonly Player _player;
private readonly RenderGrid _renderGrid;
public WorldGrid(Player player, RenderGrid renderGrid)
{
_player = player;
_renderGrid = renderGrid;
_renderGrid.Changed += this.PlayerMovedInWorld;
}
private void PlayerMovedInWorld(object sender, PlayerMovedEventArgs e)
{
// it needs the corners of the renderGrid, but since those are also updated when player moves, we can't be sure
// wheter they've been updated here or not
}
}