调用事件后,我无法让Player对象继续执行其操作。
我正在使用Monogame开发一款小型平台游戏,但遇到了一些问题。我处理碰撞的方式是,我有一个容纳游戏区实心碰撞蒙版(简单的矩形)的容器,而我的玩家有一个蒙版。当玩家移动时,它将调用一个提议其新位置的事件。 GameController接收该事件,并使用它比较玩家的拟议位置和实体的碰撞蒙版,并与实体进行比较,如果发现任何碰撞,则将这些碰撞传递给玩家,然后由玩家对其进行处理以调整其建议位置并最终移动。
问题在于,似乎事件一旦被调用,GameController就会执行它的工作,直到我故意移动之前,我再也不会回到Player中的代码。我对事件和事件处理还比较陌生,听起来这是让GameController和Player进行交流的好方法,但是它会中断Player的代码流并且从不返回吗?我想我的思维过程是游戏将处理其事件处理方法,然后返回到播放器代码中我们停下来的位置,但这不是它的工作方式,或者我错过了一步。
ActorPlayer属性 创建当玩家指示任何移动时要触发的事件。
public delegate void PlayerMoveEventHandler(object source, EventArgs e);
public event PlayerMoveEventHandler PlayerMoved;
GameController初始化 订阅Player的PlayerMoved事件,并为其分配OnPlayerMove方法(请参见下面的方法)
Player = new ActorPlayer(0, PlayerIndex.One, new Vector2(112, 104));
Player.PlayerMoved += OnPlayerMove;
ActorPlayer更新 在第23行,ActorPlayer调用OnPlayerMove()方法,该方法将为所有订阅者触发事件
public void Update(GameTime gameTime)
{
float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
ProcessInput(deltaTime);
if(IsGrounded == false)
{
// Add Gravity
FallVector = FallVector + new Vector2(0, Global.GRAVITY_RATE * deltaTime);
if (FallVector.Y > 4f)
{
FallVector = new Vector2(0, 6f);
}
Velocity = Velocity + FallVector;
}
if (Velocity != new Vector2(0))
{
ProposedPosition = Position + Velocity;
CreateProposalMask(16, 24);
OnPlayerMoved();
if (IsColliding == true)
{
for (int i = Collisions.Count - 1; i >= 0; i--)
{
HandleCollision(Collisions.ElementAt(i));
Collisions.RemoveAt(i);
}
IsColliding = false;
}
Position = ProposedPosition;
Velocity = new Vector2(0);
CreateCollisionMask(16, 24);
}
}
ActorPlayer OnPlayerMoved 如果有任何订阅者正在收听,则触发事件
protected virtual void OnPlayerMoved()
{
PlayerMoved?.Invoke(this, EventArgs.Empty);
}
GameController OnPlayerMove 如果触发了我的Player的PlayerMoved事件,则GameController方法将运行
public void OnPlayerMove(object source, EventArgs e)
{
// Check for Collisions against ProposedPosition on Player
foreach (EntityCollisionSolid solid in MapContainer.CollisionSolids)
{
if (Player.CollisionMask.Intersects(solid.CollisionMask) == true)
{
Rectangle _collision = Rectangle.Intersect(Player.CollisionMask, solid.CollisionMask);
Player.AddCollision(_collision);
}
}
if(Player.IsGrounded == true)
{
Rectangle belowPlayerMask = new Rectangle(Player.CollisionMask.X, Player.CollisionMask.Bottom, Player.CollisionMask.Width, 1);
foreach (EntityCollisionSolid solid in MapContainer.CollisionSolids)
{
if (belowPlayerMask.Intersects(solid.CollisionMask) == true)
{
return;
}
}
Player.PlayerFalling();
}
}
我的假设是它会像这样流动: 玩家检查输入/重力。创建力度。 玩家将其当前位置与速度结合起来以创建运动建议。 如果存在任何Velocity,则Player会调用其OnPlayerMoved事件。 GameController订阅了该事件,因此它跳入并使用ProposalPosition检查如果玩家移动会发生的碰撞。 如果GameController发现任何碰撞,则会将“碰撞矩形”添加到“玩家”列表中以调整其“提议”并避免进入墙壁/地板。 播放器此后继续,检查是否有任何碰撞添加到其列表中。如果是这样,它将调整其ProposalPosition。 最后,将职位更新为ProposalPosition。
实际上发生的是,当OnPlayerMoved事件触发时,GameController完全按照要求进行操作,但是直到我再次提供输入后,什么都没有发生。好像它在事件调用期间离开了播放器的Update方法,并且从不返回该方法。这可能就是事件应该如何工作的方式,我只是不知道。
编辑:感谢大家的建议!我对此还很陌生,因此对于以前共享的乱七八糟的代码表示歉意:)我已经更新了上面的代码段,以正确显示委托和EventHandler的创建,订阅,触发和处理,如下所示!上面的设置适用于我要完成的工作。
答案 0 :(得分:0)
哇,所以我让GameController订阅了该事件,但是GameController尚未结束,所以碰撞检测的某些部分仍在Main()循环中处理。将这些移动到我的GameController并调整Update方法可解决此问题。非常感谢Peter帮助我更好地理解了活动!如果没有他的投入,我将完全放弃这个想法:)