To answer your question on collisions, here's how I do it.
My game uses a grid based two-dimensional array for the tile data.
Code: Select all
function overlap(x1,y1,w1,h1,x2,y2,w2,h2)
if (x2 >= x1 and x2 <= (x1 + w1)) and (y2 >= y1 and y2 <= (y1 + h1)) then tl = true else tl = false end
if (x2+w2 >= x1 and x2+w2 <= (x1 + w1)) and (y2 >= y1 and y2 <= (y1 + h1)) then tr = true else tr = false end
if (x2 >= x1 and x2 <= (x1 + w1)) and (y2+h2 >= y1 and y2+h2 <= (y1 + h1)) then bl = true else bl = false end
if (x2+w2 >= x1 and x2+w2 <= (x1 + w1)) and (y2+h2 >= y1 and y2+h2 <= (y1 + h1)) then br = true else br = false end
if tl and tr and bl and br then return 2 elseif tl or tr or bl or br then return true else return false end
end
function checkCollision(x,y,w)
cpx, cpy = math.floor(x / 32), math.floor(y / 32)
if pushTime > 0 then pushingX, pushingY = cpx, cpy else pushingX, pushingY = -1, -1 end
if mapHit[cpx][cpy] == "x" or (mapHit[cpx][cpy] == "w" and w ~= 2) then
return true
else
return false
end
end
The overlap function is used for checking if one shape is inside another. (Rectangles only right now) Pass the x, y, width and height of the first box then the x, y, width and height of the second, in my case, the x and y of the player or enemy or projectile and their width and heights and check it against the x, y, width and height of another enemy, projectile or the player if it happens to belong to an enemy.
And the checkCollision function is used for the rest. This checks the position of the player against the tile hit map of the level/map. I also use various collision types. Like impassible by anything, or it might be water or a bush or a waist high wall. In my example, an x means impassible for anything and w means it is water or low walls so projectiles can still go through (over) it but characters cannot walk through. Basically you'd pass a 2 if the thing you are checking it for is a projectile and anything else (Like a 1 for an enemy or a 0 for a player) 32 is the width and height of each tile on my grid.
Then when moving an object such as the player:
Code: Select all
kLeft = love.keyboard.isDown(love.key_left)
kRight = love.keyboard.isDown(love.key_right)
kUp = love.keyboard.isDown(love.key_up)
kDown = love.keyboard.isDown(love.key_down)
if kLeft and kRight == false then
tpx = playerX - playerSpeed * dt
if checkCollision(tpx, playerY+16) == false and checkCollision(tpx, playerY + 31) == false then
playerX = tpx
else
playerX = (math.floor(tpx / 32)+1) * 32
end
playerFacing = 1
end
if kRight and kLeft == false then
tpx = playerX + playerSpeed * dt
if checkCollision(tpx+32, playerY+16) == false and checkCollision(tpx+32, playerY + 31) == false then
playerX = tpx
else
playerX = (math.floor(tpx / 32)) * 32
end
playerFacing = 3
end
if kUp and kDown == false then
tpy = playerY - playerSpeed * dt
if checkCollision(playerX+4, tpy+16) == false and checkCollision((playerX+24), tpy+16) == false then
playerY = tpy
else
playerY = ((math.floor(tpy / 32)+1) * 32) - 16
end
playerFacing = 2
end
if kDown and kUp == false then
tpy = playerY + playerSpeed * dt
if checkCollision(playerX + 4, tpy + 32) == false and checkCollision(playerX + 24, tpy + 32) == false then
playerY = tpy
else
playerY = (math.floor(tpy / 32)) * 32
end
playerFacing = 4
end
This is just how I do it of course. Everyone will do it differently. See, the tpx or tpy variables are calculated first, then a collision is checked against the new variable and if it isn't collided then the player/enemy's X or Y location is updated. I also put the arrow key status into a variable ahead of time to save code and typing for later checks. But that's only because of the complexity of my game.
I would't use this code outright, rather study it and see how it works, then implement your own method based on how your games variables work in engine.