在尝试为游戏设计碰撞检测组件时,我提出了以下解决方案.我定义了一个类似于ICollideable的界面:
interface ICollideable
{
Sprite Sprite { get; }
int Damage { get; }
void HandleCollision(ICollideable collidedWith);
}
Run Code Online (Sandbox Code Playgroud)
基本上,任何想要参与碰撞检测的游戏对象都必须实现此接口,然后将其自身注册到检测器,该检测器维护一个ICollideable列表.当它检测到碰撞时,它会调用对象上的HandleCollision方法并传入对它碰撞的对象的引用.
我喜欢这个,因为它允许我将所有碰撞算法保存在一个地方,让游戏对象自己决定如何处理碰撞.但由于后者,我发现我必须检查底层对象类型.例如,我不希望玩家互相碰撞,因此在玩家类中可能会有以下内容:
void HandleCollision(ICollideable collidedWith)
{
if (!(collidedWith is Player)) { // do stuff }
}
Run Code Online (Sandbox Code Playgroud)
等等,我想知道这是否告诉我我的设计不好以及替代品可能是什么.
第二个问题,进一步沿着第一个问题.出于评分的目的,如果一个敌人被一个射弹摧毁,有人需要知道射弹类的"拥有玩家"成员.但是,我的其他碰撞物都没有或者不需要这个属性,所以我发现自己想做(在Enemy HandleCollision中):
void HandleCollision(ICollideable collidedWith)
{
if (collidedWith is Projectile) {
Health -= collidedWith.Damage;
if (Health <= 0) {
Player whoDestroyedMe = (collidedWith as Projectile).FiredBy
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不清楚如何用更好的设计来处理这个问题.任何见解将不胜感激.
编辑:我想把焦点放在第二个问题上,因为我的直觉告诉我处理这个问题的方法将解决第一个问题.至于第一个问题,我想到了一种抽象这种行为的方法.我可以定义一个枚举:
enum Team
{
Player,
Enemy,
Neither
}
Run Code Online (Sandbox Code Playgroud)
并让ICollideables实现此属性.然后碰撞检测器根本不记录同一"团队"上的可碰撞物之间的碰撞.因此,玩家和玩家弹丸将在一个团队中,敌人和敌人的弹丸将在另一个团队中,并且环境(可能会损坏两者)都不会出现.它不必是枚举,可以是int或字符串或任何东西,并且认为具有相同值的对象不会相互冲突.
我喜欢用简单属性建模行为的想法.例如,如果我想打开"允许友好射击",我所要做的就是创建一个Team值不是玩家团队值的Projectiles.但是,我仍然可能有这种情况还不够.例如,玩家可能拥有暂时不受射弹影响但不能防止与敌人直接碰撞的盾牌,等等.
对于第一种情况,我将向 ICollidable 添加以下额外方法:
bool CanCollideWith(ICollidable collidedWith)
Run Code Online (Sandbox Code Playgroud)
顾名思义,它会返回 true 或 false,具体取决于它是否可以与传入的对象发生碰撞。
您的 Player.HandleCollision 方法只会执行其操作,因为调用方法可以执行该测试,如果不需要,甚至不会调用该方法。
| 归档时间: |
|
| 查看次数: |
1117 次 |
| 最近记录: |