游戏开发 - 在跳跃期间遇到AABB碰撞检测问题

时间:2015-12-15 17:48:45

标签: lua collision-detection game-engine aabb

我的碰撞检测通过获取矩形之间的交叉并反转效果来工作。这是在每一帧中发生的。除了玩家坐在角落顶部并跳跃之外,它的效果很好。每隔一段时间垂直交叉点大于水平交叉点,这使得我的玩家向下滑动到平台的一侧。有什么建议吗?

enter image description here

    -- detect initial collision
    if mathy.hasCollided(player, platform) then

        local playerBoundaries = player:boundaries()

        -- list of intersections between platform and player
        local bottomBoundary = mathy.bottomBoundary( playerBoundaries, platform )
        local topBoundary = mathy.topBoundary( playerBoundaries, platform )
        local rightBoundary = mathy.rightBoundary( playerBoundaries, platform )
        local leftBoundary = mathy.leftBoundary( playerBoundaries, platform )

        local smallestDist = ""
        local smallestBoundary
        local boundaries = {
            bottom = bottomBoundary,
            top = topBoundary,
            right = rightBoundary,
            left = leftBoundary
        }

        -- get the smallest intersection (thats the side we're probably closest to)
        for direction, boundary in pairs(boundaries) do
            if not smallestBoundary then
                smallestBoundary = boundary
                smallestDist = direction
            end

            if smallestBoundary > boundary then
                smallestBoundary = boundary
                smallestDist = direction
            end
        end

        -- reverse effects depending on collision location
        if smallestDist == "bottom" then
            player.desiredPos:add(diffX, -bottomBoundary)
            player.velocity.y = 0
            player.onGround = true
        elseif smallestDist == "top" then
            player.velocity.y = 250
            player.desiredPos:add(0, topBoundary)
        elseif smallestDist == "right" then
            player.desiredPos:add(-rightBoundary, 0)
        elseif smallestDist == "left" then
            player.desiredPos:add(leftBoundary, 0)
        end
    end

1 个答案:

答案 0 :(得分:0)

很难从短片中分辨出来,但我认为问题是检查最小的交叉点而不是检查物体速度方向的交点。您可以尝试这样的代替smallestBoundary循环:

local boundary = nil
if (player.velocity.y > 0) then
  boundary = topBoundary
elseif (player.velocity.y < 0) then
  boundary = bottomBoundary
elseif (player.velocity.x > 0) then
  boundary = rightBoundary
elseif (player.velocity.x < 0) then
  boundary = leftBoundary
end

当然,这并不像它那样强大。您也可以尝试将这两种方法结合起来,并采用类似的方法代替smallestBoundary循环:

    local yMod = math.abs(player.velocity.y)
    local xMod = math.abs(player.velocity.x)
    local topMod = player.velocity.y > 0 and yMod or 1
    local bottomMod = player.velocity.y < 0 and yMod or 1
    local rightMod = player.velocity.x > 0 and xMod or 1
    local leftMod = player.velocity.x < 0 and xMod or 1
    local boundaries = {
        bottom = (bottomMod / MAX_VELOCITY) * bottomBoundary,
        top = (topMod / MAX_VELOCITY) * topBoundary,
        right = (rightMod / MAX_VELOCITY) * rightBoundary,
        left = (leftMod / MAX_VELOCITY) * leftBoundary
    }

    for direction, boundary in pairs(boundaries) do
        if not smallestBoundary then
            smallestBoundary = boundary
            smallestDist = direction
        end

        if smallestBoundary > boundary then
            smallestBoundary = boundary
            smallestDist = direction
        end
    end

这将完成你现在正在做的事情,但是会根据玩家在该方向上的速度调整边界的大小(仅在比较的上下文中)。因此,如果您将x-5一起移动,y-10一起移动,则y平面中的向下碰撞的重量将是左向碰撞的两倍在x平面。当然,在每个碰撞平面上总是有另一种调整玩家的选择:

    if bottomBoundary > 0 then
        player.desiredPos:add(diffX, -bottomBoundary)
        player.velocity.y = 0
        player.onGround = true
    end
    if topBoundary > 0 then
        player.velocity.y = 250
        player.desiredPos:add(0, topBoundary)
    end
    if rightBoundary > 0 then
        player.desiredPos:add(-rightBoundary, 0)
    end
    if leftBoundary > 0 then
        player.desiredPos:add(leftBoundary, 0)
    end

最后一种方法最有意义,除了你似乎无论如何都无法统一处理所有方向的碰撞,因此它可能不适合你的架构。

请记住,我不熟悉您正在使用的框架,因此此代码可能无法正常使用。另外,这篇文章假设+y已启动,-y已关闭,+x正确,-x已离职。