游戏碰撞处理

发布于 2024-10-05 23:35:07 字数 1402 浏览 1 评论 0原文

给出的代码仅用于示例目的,而不是从我的代码库

中 复制 SDL,我想知道实现碰撞处理的最佳方法是什么(不是碰撞检测)。到目前为止,我一直在使用单分派的想法,带有丑陋的意大利面条代码,如下所示:

void Snake::CollisionHandler(const WorldObject& obj)
{
    // collided with self
    if(obj.GetObjectType() == snake)
        Die();
    ...
    ...
}

此外,我有一个“全局”碰撞处理程序,它执行与碰撞相关的操作,例如,这些操作与每个对象无关:


void GameWorld::CollisionHandler(WorldObject& obj1, WorldObject& obj2)
{
    if(obj1.GetObjectType() == snake && obj2.GetObjectType() == snake)
        PlayDeathSound();
    ...
    ...
}

避免诸如声音因碰撞而播放两次之类的情况。

我也考虑过双重调度,如下所示:


void Snake::CollisionHandler(WorldObject& obj) const
{
    // invoke obj's collision handler with a const Snake& parameter
    obj.CollisionHandler(*this);
}
// collided with self
void Snake::CollisionHandler(const Snake& obj)
{
    Die();
}

这还包括与上面类似的全局碰撞处理程序。

然后是有一个全局碰撞处理程序(这是所有游戏对象的友元函数)的方法,如下所示:


void GameWorld::CollisionHandler(WorldObject& obj1, WorldObject& obj2)
{
    // snake collided with self
    if(obj1.GetObjectType() == snake && obj2.GetObjectType() == snake)
    {
        obj1.Die();
        obj2.Die();
        PlayDeathSound();
    }
    ...
    ...
}

我缺少任何策略吗?其中哪一个最终是最好的?它们似乎都涉及一些丑陋的代码,并且单分派和双分派代码涉及多态性,我个人试图回避这一点。

The code given is for example purposes, not copypasta from my codebase

I'm writing a primitive, cross-platform Snake game in C++ with Boost & SDL, and I'm wondering what the best way to implement collision-handling is (not collision-detection). So far, I've been using a single-dispatch idea, with ugly spaghetti code, like so:

void Snake::CollisionHandler(const WorldObject& obj)
{
    // collided with self
    if(obj.GetObjectType() == snake)
        Die();
    ...
    ...
}

Also, I have a "global" collision handler, which does things involved in a collision, which are independent of each object, for example:


void GameWorld::CollisionHandler(WorldObject& obj1, WorldObject& obj2)
{
    if(obj1.GetObjectType() == snake && obj2.GetObjectType() == snake)
        PlayDeathSound();
    ...
    ...
}

To avoid things like sounds being played twice for collisions.

I've also considered double-dispatch, like so:


void Snake::CollisionHandler(WorldObject& obj) const
{
    // invoke obj's collision handler with a const Snake& parameter
    obj.CollisionHandler(*this);
}
// collided with self
void Snake::CollisionHandler(const Snake& obj)
{
    Die();
}

This also includes a similar global collision handler like above.

Then there's the approach of only having a global collision handler (which is a friend function to all game objects), like so:


void GameWorld::CollisionHandler(WorldObject& obj1, WorldObject& obj2)
{
    // snake collided with self
    if(obj1.GetObjectType() == snake && obj2.GetObjectType() == snake)
    {
        obj1.Die();
        obj2.Die();
        PlayDeathSound();
    }
    ...
    ...
}

Are there any strategies I'm missing? Which of these ends up being the nicest? They all seem to have some ugly code involved, and the single- and double- dispatch ones involve polymorphism, which I personally try to shy away from.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

脸赞 2024-10-12 23:35:07

冲突处理是 C++/Java 风格的面向对象(单分派)不够灵活的领域。碰撞的结果取决于两个碰撞对象的类型,因此您需要多个调度来处理它。 (维基百科多重调度文章中的激励示例是碰撞处理,这并非巧合!)

我认为全局碰撞处理程序then 分派到各个对象方法是解决 C++ 中这一缺陷的最佳解决方法。

Collision handling is an area where C++/Java-style object orientation (with single dispatch) is not flexible enough. The result of a collision depends on the types of both colliding objects, so you need multiple dispatch to handle it. (It's no coincidence that the motivating example on Wikipedia's multiple dispatch article is collision handling!)

I think that a global collision handler that then dispatches to individual object methods is the best workaround for this inadequacy in C++.

讽刺将军 2024-10-12 23:35:07

IMO 让游戏类完全处理碰撞和其他全局事件的最后一种方法是最明智的,也可能是最“正确”的方法。
以国际象棋程序为例。很明显,游戏类应该处理其中一名玩家获胜或失败的情况,而不是玩家类。
它在实践中也更有效。考虑一下您想要添加更多类(例如另一种类型的蛇)的情况,您可以让游戏类以更少的努力来处理它,而不是重复代码或覆盖 CollisionHandler。

但是,如果您的唯一目的是一个简单的贪吃蛇游戏,那么您选择如何实现它可能并不那么重要。

IMO the last approach of letting the game class completely handle collisions and other global events is the wisest and possibly the most "correct" way of doing it.
For example take a chess program. It is pretty obvious that the game class should handle the case of win or lose by one of the players, and not the player class.
It is also more more effective practically. Think of a case where you want to add more classes (e.g another type of snake), instead of duplicating code or overriding CollisionHandler you can just let the game class handle it with much less effort.

However, if your only purpose is a simple snake game it is probably not that important how you choose to implement it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文