0

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

在此处输入图像描述

    -- 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
4

1 回答 1

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

这将完全按照您现在所做的那样做,但会根据玩家在该方向上的速度来调整边界的大小(仅在比较的上下文中)。因此,如果您在xwith-5和 in 中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向左。

于 2015-12-15T22:26:53.847 回答