嗨,我正在使用 love2d 创建一个简单的平台游戏,我在碰撞中遇到了问题

问题描述 投票:0回答:1

在我的播放器脚本中。我调用了一个函数来检查图块是否与玩家发生碰撞。

基本的图块碰撞已经完成,但我遇到了一些问题。

  1. 当玩家跳跃并碰撞墙壁时,玩家会停止。
  2. 当玩家在碰撞墙壁时掉落时,玩家会停止。

我认为问题出在Y碰撞检查部分,但我不知道如何解决它。

--------------------- Collision Check ----------------------

local box = Vt2:new(self.pos.x + self.vel.x * dt * self.dirXTemp, 
            self.pos.y + self.vel.y * dt)

for i = 1, #collTile do

    local tile = collTile[i]

    local isColl = BdBoxCollision(box, self.size, tile.pos, tile.size)

    if 
        isColl[1] == true and
        isColl[2] == true and
        isColl[3] == true and
        isColl[4] == true then

        local isOnWall = false

        if self.pos.y + self.size.y > tile.pos.y then -- X Collision 

            if box.x + self.size.x / 2 < tile.pos.x + tile.size.x / 2 then
                
                if box.x + self.size.x > tile.pos.x  then
                    
                    if self.dirX == 1 then
                        self.vel.x = 0
    
                        isOnWall = true
                    end

                end

            end

            if box.x + self.size.x / 2 > tile.pos.x + tile.size.x / 2 then
                
                if box.x < tile.pos.x + tile.size.x then
                    
                    if self.dirX == -1 then
                        self.vel.x = 0
                    
                        isOnWall = true
                    end

                end

            end

        end

        if box.y + self.size.y / 2 < tile.pos.y + tile.size.y / 2 then -- Y Collision

            if box.y + self.size.y > tile.pos.y and
                self.pos.y + self.size.y < tile.pos.y + 8  then

                if isOnWall == false then

                    self.pos.y = tile.pos.y - self.size.y 
                    self.vel.y = 0
                end
            end

        elseif box.y + self.size.y / 2 > tile.pos.y + tile.size.y / 2 then

            if box.y < tile.pos.y + tile.size.y then
                
                self.vel.y = self.gravity

            end

        end

    end 

end

::skip::

self.pos.x = self.pos.x + self.vel.x * dt
self.pos.y = self.pos.y + self.vel.y * dt
lua collision-detection game-development collision love2d
1个回答
0
投票

请尝试这个解决方案,逻辑读起来更清晰:

--------------------- Collision Check----------------------

local function AABBCollision (x1,y1,w1,h1, x2,y2,w2,h2)
-- Function to check for axis-aligned bounding box (AABB) collision between two rectangles
    return x1<x2+w2 and x2<x1+w1 and y1<y2+h2 and y2<y1+h1
end

local function isOnFloor (y, h, ty, th)
-- Function to check if the player is on the floor
    -- positive y directon is downwards
    -- lower value is vertical higher
    -- y, h - position and heigh of player
    -- ty - position of tile
    -- middle is higher than tile middle and it touch
    return (y+h/2 < ty+th/2) and (y + h >= ty)
end

local function isOnRightWall (x, w, tx, tw)
-- Function to check if the player is on the right wall
    -- tx - x position of tile
    -- x, w - position and width of player
    -- dx, w - horizontal movement of player
    -- middle is lefts than tile middle and it touch
    return (x + w/2 < tx + tw/2) and (x + w >= tx)
end

local function isOnLeftWall (x, w, tx, tw)
-- Function to check if the player is on the left wall
    -- tx - x position of tile
    -- x, w - position and width of player
    -- dx, w - horizontal movement of player
    -- middle is rights than tile middle and it touch
    return (x + w/2 > tx + tw/2) and (x <= tx + tw)
end

local function isRightDirected (dirX)
-- Function to check if the player is moving to the right
    return dirX > 0
end

local function isLeftDirected (dirX)
-- Function to check if the player is moving to the left
    return dirX < 0
end

function Player:update (dt)
-- Current position of the player
    local x, y = self.pos.x, self.pos.y
-- Width and height of the player
    local w, h = self.size.x, self.size.y
-- Gravity affecting the player
    local gravity = self.gravity

    if love.keyboard.isScancodeDown('d') then 
        self.dirX = 1 -- going right
    elseif love.keyboard.isScancodeDown('a') then 
        self.dirX = -1 -- going left
    else -- nothing is pressed: reset dirX:
        self.dirX = 0
    end

-- get delta velocity
    local dvy = dt*gravity

-- get delta movement of player
    local dx = dt*self.dirX*math.abs(self.vel.x)
    local dy = dt*(self.vel.y + dvy/2)

-- update vertical velocity
    self.vel.y = self.vel.y + dvy

    -- check all rectangles:
    for i = 1, #collTiles do
        local tile = collTiles[i]
        local tx, ty = tile.pos.x, tile.pos.y
        local tw, th = tile.size.x, tile.size.y-- width, heigh
        local isColl = AABBCollision(x+dx, y+dy, w, h, tx, ty, tw, th)
        if isColl then -- something collides
            if isOnFloor (y+dy, h, ty, th) then
                -- onFloor
                if stateJumping  then
                    -- keep flying
                else
                    -- not falling, 
                    -- adjust y-position to be on top of the tile
--                  y+dy + h >= ty
                    dy = ty - y - h
                    self.vel.y = 0
                end

                if stateOnPlatform then
                    if tile.vx then
                        local tvx = tile.vx
                        local tdirX = tile.dirX
                        local tdx = dt*tdirX*math.abs(tvx)
                        dx = dx + tdx
                    end
                end

                if isRightDirected (self.dirX) then
                    if isOnRightWall (x+dx, w, tx, tw) then
                        dx = tx - x - w
                        self.vel.x = 0
                    end
                elseif isLeftDirected (self.dirX) then
                    if isOnLeftWall (x+dx, w, tx, tw) then
                        dx = tx + tw - x
                        self.vel.x = 0
                    end
                end
                -- end of onFloor
            else 
                -- not onFloor
                if isRightDirected (self.dirX) then
                    if isOnRightWall (x+dx, w, tx, tw) then
                        -- onWall state
                        -- adjust dx to collision
                        dx = tx - x - w
                        -- no horizontal speed
                        self.vel.x = 0
                        if stateJumping then

                        else
                            -- not falling
                            dy = 0
                            self.vel.y = 0
                        end
                    end
                elseif isLeftDirected (self.dirX) then
                    if isOnLeftWall (x+dx, w, tx, tw) then
                        -- onWall state
                        -- adjust dx to collision
                        dx = tx + tw - x
                        -- no horizontal speed
                        self.vel.x = 0
                        if stateJumping then

                        else
                            -- not falling
                            dy = 0
                            self.vel.y = 0
                        end
                    end
                else
                    -- (not directed)
                end
                -- end of not onFloor
            end
        else
            -- no collision
        end
    end

    self.pos.x = x + dx
    self.pos.y = y + dy
end
© www.soinside.com 2019 - 2024. All rights reserved.