Reputation: 55
In my player script. I called a function to check is if a tile is collided with the player.
The basic tile collisions has been made, but I got some problems.
I think the problem is in the Y collision checking part, but I can't figure out how to solve it.
--------------------- 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
Upvotes: 2
Views: 108
Reputation: 566
Please try this solution, the logic is more clear to read:
--------------------- 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
Upvotes: 0