Collision Detection
Let's improve our collision detection to handle all sides of platforms, not just the top.
AABB Collision
We're using AABB (Axis-Aligned Bounding Box) collision - checking if two rectangles overlap:
luafunction checkCollision(a, b) return a.x < b.x + b.width and a.x + a.width > b.x and a.y < b.y + b.height and a.y + a.height > b.y end
Resolving Collisions
When a collision happens, we need to figure out which side was hit and push the player out:
luafunction love.load() player = { x = 50, y = 100, width = 30, height = 40, speed = 200, velocityY = 0, gravity = 800, jumpForce = -350, onGround = false } platforms = { {x = 0, y = 250, width = 400, height = 50}, {x = 100, y = 180, width = 80, height = 15}, {x = 220, y = 130, width = 100, height = 15}, {x = 50, y = 80, width = 70, height = 15}, } end function love.update(dt) -- Store previous position local prevX = player.x local prevY = player.y -- Horizontal movement if love.keyboard.isDown("left") or love.keyboard.isDown("a") then player.x = player.x - player.speed * dt end if love.keyboard.isDown("right") or love.keyboard.isDown("d") then player.x = player.x + player.speed * dt end -- Apply gravity player.velocityY = player.velocityY + player.gravity * dt player.y = player.y + player.velocityY * dt player.onGround = false -- Check collisions with platforms for i, plat in ipairs(platforms) do if checkCollision(player, plat) then -- Determine collision direction local overlapLeft = (player.x + player.width) - plat.x local overlapRight = (plat.x + plat.width) - player.x local overlapTop = (player.y + player.height) - plat.y local overlapBottom = (plat.y + plat.height) - player.y -- Find smallest overlap local minOverlap = math.min(overlapLeft, overlapRight, overlapTop, overlapBottom) if minOverlap == overlapTop and player.velocityY > 0 then -- Landing on top player.y = plat.y - player.height player.velocityY = 0 player.onGround = true elseif minOverlap == overlapBottom and player.velocityY < 0 then -- Hit head on bottom player.y = plat.y + plat.height player.velocityY = 0 elseif minOverlap == overlapLeft then -- Hit left side player.x = plat.x - player.width elseif minOverlap == overlapRight then -- Hit right side player.x = plat.x + plat.width end end end -- Screen boundaries if player.x < 0 then player.x = 0 end if player.x + player.width > 400 then player.x = 400 - player.width end if player.y < 0 then player.y = 0; player.velocityY = 0 end end function checkCollision(a, b) return a.x < b.x + b.width and a.x + a.width > b.x and a.y < b.y + b.height and a.y + a.height > b.y end function love.keypressed(key) if (key == "space" or key == "w" or key == "up") and player.onGround then player.velocityY = player.jumpForce end end function love.draw() love.graphics.setColor(0.4, 0.7, 1) love.graphics.rectangle("fill", 0, 0, 400, 300) love.graphics.setColor(0.4, 0.8, 0.4) for i, plat in ipairs(platforms) do love.graphics.rectangle("fill", plat.x, plat.y, plat.width, plat.height) end love.graphics.setColor(1, 0.3, 0.3) love.graphics.rectangle("fill", player.x, player.y, player.width, player.height) love.graphics.setColor(1, 1, 1) love.graphics.circle("fill", player.x + 10, player.y + 12, 5) love.graphics.circle("fill", player.x + 22, player.y + 12, 5) love.graphics.setColor(0, 0, 0) love.graphics.circle("fill", player.x + 12, player.y + 12, 2) love.graphics.circle("fill", player.x + 24, player.y + 12, 2) love.graphics.setColor(1, 1, 1) love.graphics.print("Full collision detection!", 10, 10) end
Try it! Notice how you can't pass through platforms from any direction now.