jjzjj

c++ - 零星碰撞检测

coder 2024-02-21 原文

我一直致力于检测游戏中对象之间的碰撞。现在一切都是垂直的,但希望保持其他运动的选择。这是经典的 2d 垂直空间射击游戏。

现在我遍历每个对象,检查碰撞:

for(std::list<Object*>::iterator iter = mObjectList.begin(); iter != mObjectList.end();) {
    Object *m = (*iter);
    for(std::list<Object*>::iterator innerIter = ++iter; innerIter != mObjectList.end(); innerIter++ ) {
            Object *s = (*innerIter);

            if(m->getType() == s->getType()) {
                break;
            }

            if(m->checkCollision(s)) {
                m->onCollision(s);
                s->onCollision(m);
            }
        }
    }

这是我检查碰撞的方法:

bool checkCollision(Object *other) {
        float radius = mDiameter / 2.f;
        float theirRadius = other->getDiameter() / 2.f;
        Vector<float> ourMidPoint = getAbsoluteMidPoint();
        Vector<float> theirMidPoint = other->getAbsoluteMidPoint();

        // If the other object is in between our path on the y axis
        if(std::min(getAbsoluteMidPoint().y - radius, getPreviousAbsoluteMidPoint().y - radius) <= theirMidPoint.y &&
            theirMidPoint.y <= std::max(getAbsoluteMidPoint().y + radius, getPreviousAbsoluteMidPoint().y + radius)) {

                // Get the distance between the midpoints on the x axis
                float xd = abs(ourMidPoint.x - theirMidPoint.x);

                // If the distance between the two midpoints
                // is greater than both of their radii together
                // then they are too far away to collide
                if(xd > radius+theirRadius) {
                    return false;
                } else {
                    return true;
                }

        }
        return false;
}

问题是它会随机正确地检测到碰撞,但其他时候根本检测不到。这不是 if 语句脱离对象循环,因为对象确实有不同的类型。物体离屏幕顶部越近,正确检测到碰撞的可能性就越大。越靠近屏幕底部,它被正确检测到甚至根本检测不到的可能性就越小。然而,这些情况并不总是会发生。物体的直径很大(10 和 20)以查看这是否是问题所在,但它根本没有多大帮助。

编辑 - 更新代码

bool checkCollision(Object *other) {
    float radius = mDiameter / 2.f;
    float theirRadius = other->getDiameter() / 2.f;
    Vector<float> ourMidPoint = getAbsoluteMidPoint();
    Vector<float> theirMidPoint = other->getAbsoluteMidPoint();

    // Find the distance between the two points from the center of the object
    float a = theirMidPoint.x - ourMidPoint.x;
    float b = theirMidPoint.y - ourMidPoint.y;

    // Find the hypotenues
    double c = (a*a)+(b*b);
    double radii = pow(radius+theirRadius, 2.f);

    // If the distance between the points is less than or equal to the radius
    // then the circles intersect
    if(c <= radii*radii) {
        return true;
    } else { 
        return false;
    }
}

最佳答案

当两个圆形物体的中心距离足够小时,它们就会发生碰撞。您可以使用以下代码进行检查:

double distanceSquared =
    pow(ourMidPoint.x - theirMidPoint.x, 2.0) +
    pow(ourMidPoint.x - theirMidPoint.x, 2.0);
bool haveCollided = (distanceSquared <= pow(radius + theirRadius, 2.0));

为了检查两个时间点之间是否存在碰撞,您可以在时间间隔的开始和结束时检查碰撞;但是,如果物体移动得非常快,碰撞检测可能会失败(我猜你遇到过这个问题,因为物体在屏幕底部以最快的速度坠落)。

以下内容可能会使碰撞检测更加可靠(尽管仍不完美)。假设物体以恒定速度运动;然后,他们的位置是时间的线性函数:

our_x(t) = our_x0 + our_vx * t;
our_y(t) = our_y0 + our_vy * t;
their_x(t) = their_x0 + their_vx * t;
their_y(t) = their_y0 + their_vy * t;

现在您可以将它们之间的(平方)距离定义为时间的二次函数。找出它在什么时候取最小值(即它的导数为 0);如果这个时间属于当前时间间隔,则计算最小值并检查是否有碰撞。

这必须足以几乎完美地检测到碰撞;如果您的应用程序大量使用自由落体物体,您可能希望将运动函数细化为二次函数:

our_x(t) = our_x0 + our_v0x * t;
our_y(t) = our_y0 + our_v0y * t + g/2 * t^2;

关于c++ - 零星碰撞检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5413822/

有关c++ - 零星碰撞检测的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  3. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  4. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  5. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  6. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  7. ruby - 检测由 RSpec、Ruby 运行的代码 - 2

    我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题

  8. ruby - 使用 Ruby Daemons gem 检测停止 - 2

    我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe

  9. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

  10. ruby - Ruby 中字符串运算符 + 和 << 的区别 - 2

    我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc

随机推荐