Merge pull request #1 from Dangrainage/to-be-pushed

Added collision detection (kind off), added agent_jump.png, white.png and updated main.lua file
This commit is contained in:
Dangrain 2024-09-27 22:37:29 +02:00 committed by GitHub
commit e3e780ae2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 629 additions and 2 deletions

View file

@ -0,0 +1,499 @@
-- Collider v2.0
local collider = {}
collider.colliders = {}
collider.boxIDs = {}
collider.circleIDs = {}
function collider.newBox(x, y, width, height, tag, trigger, debugColor)
local newBox = {}
newBox.x = x
newBox.y = y
newBox.width = width
newBox.height = height or newBox.width
newBox.tag = tag or 'none'
if trigger == nil then
newBox.trigger = false
else
newBox.trigger = trigger
end
newBox.debugColor = debugColor or {1,1,1}
newBox.ID = tostring('B'..#collider.boxIDs+1)
newBox.onTriggerEnter = onTriggerEnter or function(collider) end
newBox.onTriggerExit = onTriggerExit or function(collider) end
newBox.collisions = {}
newBox.lastFrameCollisions = {}
newBox.type = 'box'
newBox.superPoints = {
{
x = newBox.x,
y = newBox.y
},
{
x = newBox.x + newBox.width,
y = newBox.y + newBox.height
},
updatePoint = function(point, x, y)
newBox.superPoints[point].x = x
newBox.superPoints[point].y = y
end
}
function newBox.updatePos(newX, newY, center)
if center == nil then
center = false
end
if center == true then
newBox.x = newX - newBox.width/2
newBox.y = newY - newBox.height/2
else
newBox.x = newX
newBox.y = newY
end
newBox.superPoints.updatePoint(1, newBox.x, newBox.y)
newBox.superPoints.updatePoint(2, newBox.x + newBox.width, newBox.y + newBox.height)
end
function newBox.collidingWith(id)
return newBox.collisions[id] ~= nil
end
function newBox.getID()
return newBox.ID
end
-- NOT WORKING
function newBox.destroy()
for k,v in ipairs(collider.boxIDs) do
if v == newBox.ID then
v = nil
end
end
collider.colliders[newBox.ID] = nil
end
collider.colliders[newBox.ID] = newBox
newBox.IDindex = #collider.boxIDs + 1
collider.boxIDs[newBox.IDindex] = newBox.ID
return newBox
end
function collider.newCircle(x, y, radius, tag, trigger, debugColor)
local newCircle = {}
newCircle.x = x
newCircle.y = y
newCircle.radius = radius or 50
newCircle.tag = tag or 'none'
if trigger == nil then
newCircle.trigger = false
else
newCircle.trigger = trigger
end
newCircle.debugColor = debugColor or {1,1,1}
newCircle.ID = tostring('C'..#collider.circleIDs+1)
newCircle.onTriggerEnter = onTriggerEnter or function(collider) end
newCircle.onTriggerExit = onTriggerExit or function(collider) end
newCircle.collisions = {}
newCircle.lastFrameCollisions = {}
newCircle.type = 'circle'
function newCircle.updatePos(newX, newY)
newCircle.x = newX
newCircle.y = newY
end
function newCircle.collidingWith(id)
return newCircle.collisions[id] ~= nil
end
function newCircle.getID()
return newCircle.ID
end
-- NOT WORKING
function newCircle.destroy()
for k,v in ipairs(collider.circleIDs) do
if v == newCircle.ID then
v = nil
end
end
collider.colliders[newCircle.ID] = nil
end
collider.colliders[newCircle.ID] = newCircle
newCircle.IDindex = #collider.circleIDs + 1
collider.circleIDs[newCircle.IDindex] = newCircle.ID
return newCircle
end
function collider.update()
collider.updateBoxes()
collider.updateCircles()
end
function collider.overlapBox(boxX, boxY, width, height)
local collisions = {}
local superPoints = {
{
x = boxX,
y = boxY
},
{
x = boxX + width,
y = boxY + height
},
}
-- Against every other box
for kk,other in ipairs(collider.boxIDs) do
other = collider.colliders[other]
-- Look for an x plane and y plane intersection in superPoints
local spX = {false, false}
local spY = {false, false}
-- Loop through superPoints
for kkk,sp in ipairs(superPoints) do
if sp.x > other.superPoints[1].x and sp.x < other.superPoints[2].x then
spY[kkk] = true
end
if sp.y > other.superPoints[1].y and sp.y < other.superPoints[2].y then
spX[kkk] = true
end
end
-- Check if superPoints show a collision between my and other
if (spX[1] and spY[1]) or (spX[2] and spY[2]) or (spX[1] and spY[2]) or (spX[2] and spY[1]) then
collisions[other.ID] = other
end
end
-- Against every other circle
for kk,other in ipairs(collider.circleIDs) do
other = collider.colliders[other]
local testX = other.x
local testY = other.y
if (other.x < boxX) then
testX = boxX -- left edge
elseif (other.x > boxX + width) then
testX = boxY + width -- right edge
end
if (other.y < boxY) then
testY = boxY -- top edge
elseif (other.y > boxY + height) then
testY = boxY + height -- bottom edge
end
local distX = other.x - testX;
local distY = other.y - testY;
local distance = (distX * distX) + (distY * distY);
if distance <= other.radius * other.radius then
collisions[other.ID] = other
end
end
return collisions
end
function collider.overlapCircle(x, y, radius)
local collisions = {}
-- Against every other box
for kk,other in ipairs(collider.boxIDs) do
other = collider.colliders[other]
local testX = x
local testY = y
if (x < other.x) then
testX = other.x -- left edge
elseif (x > other.x + other.width) then
testX = other.x + other.width -- right edge
end
if (y < other.y) then
testY = other.y -- top edge
elseif (y > other.y + other.height) then
testY = other.y + other.height -- bottom edge
end
local distX = x - testX;
local distY = y - testY;
local distance = (distX * distX) + (distY * distY);
if distance <= radius * radius then
collisions[other.ID] = other
end
end
-- Against every other circle
for kk,other in ipairs(collider.circleIDs) do
other = collider.colliders[other]
local distX = x - other.x;
local distY = y - other.y;
local distance = (distX*distX) + (distY*distY);
if (distance <= (radius+other.radius) * (radius+other.radius)) then
collisions[other.ID] = other
end
end
return collisions
end
function collider.updateBoxes()
for k,v in ipairs(collider.boxIDs) do
v = collider.colliders[v]
for kk in pairs (v.collisions) do
v.collisions[kk] = nil
end
end
-- Check every box for any collisions
for k,my in ipairs(collider.boxIDs) do
my = collider.colliders[my]
-- Against every other box
for kk,other in ipairs(collider.boxIDs) do
other = collider.colliders[other]
-- Ignore if it is yourself
if kk ~= k then
-- Look for an x plane and y plane intersection in superPoints
local spX = {false, false}
local spY = {false, false}
-- Loop through superPoints
for kkk,sp in ipairs(my.superPoints) do
if sp.x > other.superPoints[1].x and sp.x < other.superPoints[2].x then
spY[kkk] = true
end
if sp.y > other.superPoints[1].y and sp.y < other.superPoints[2].y then
spX[kkk] = true
end
end
-- Check if superPoints show a collision between my and other
if (spX[1] and spY[1]) or (spX[2] and spY[2]) or (spX[1] and spY[2]) or (spX[2] and spY[1]) then
if not my.collisions[other.ID] ~= nil or not other.collisions[my.ID] ~= nil then
my.collisions[other.ID] = other
other.collisions[my.ID] = my
end
end
end
end
-- Against every other circle
for kk,other in ipairs(collider.circleIDs) do
other = collider.colliders[other]
local testX = other.x
local testY = other.y
if (other.x < my.x) then
testX = my.x -- left edge
elseif (other.x > my.x + my.width) then
testX = my.x + my.width -- right edge
end
if (other.y < my.y) then
testY = my.y -- top edge
elseif (other.y > my.y + my.height) then
testY = my.y + my.height -- bottom edge
end
local distX = other.x - testX;
local distY = other.y - testY;
local distance = (distX * distX) + (distY * distY);
if distance <= other.radius * other.radius then
my.collisions[other.ID] = other
other.collisions[my.ID] = my
end
end
end
-- Update collision status
for k,my in ipairs(collider.boxIDs) do
my = collider.colliders[my]
for kk,other in pairs(my.collisions) do
-- Check if its a new collision
if my.lastFrameCollisions[other.ID] == nil then
my.lastFrameCollisions[other.ID] = other
my.onTriggerEnter(collider.colliders[other.ID])
collider.colliders[other.ID].lastFrameCollisions[my.ID] = my
collider.colliders[other.ID].onTriggerEnter(my)
end
end
for kk,other in pairs(my.lastFrameCollisions) do
-- Check if collisions from last frame aren't there anymore
if my.collisions[other.ID] == nil then
my.lastFrameCollisions[other.ID] = nil
my.onTriggerExit(collider.colliders[other.ID])
collider.colliders[other.ID].lastFrameCollisions[my.ID] = nil
collider.colliders[other.ID].onTriggerExit(my)
end
end
end
end
function collider.updateCircles()
for k,v in ipairs(collider.circleIDs) do
v = collider.colliders[v]
for kk in pairs (v.collisions) do
v.collisions[kk] = nil
end
end
-- Check every circle
for k,my in ipairs(collider.circleIDs) do
my = collider.colliders[my]
-- Against every other box
for kk,other in ipairs(collider.boxIDs) do
other = collider.colliders[other]
local testX = my.x
local testY = my.y
if (my.x < other.x) then
testX = other.x -- left edge
elseif (my.x > other.x + other.width) then
testX = other.x + other.width -- right edge
end
if (my.y < other.y) then
testY = other.y -- top edge
elseif (my.y > other.y + other.height) then
testY = other.y + other.height -- bottom edge
end
local distX = my.x - testX;
local distY = my.y - testY;
local distance = (distX * distX) + (distY * distY);
if distance <= my.radius * my.radius then
my.collisions[other.ID] = other
other.collisions[my.ID] = my
end
end
-- Against every other circle
for kk,other in ipairs(collider.circleIDs) do
if k ~= kk then
other = collider.colliders[other]
local distX = my.x - other.x;
local distY = my.y - other.y;
local distance = (distX*distX) + (distY*distY);
if (distance <= (my.radius+other.radius) * (my.radius+other.radius)) then
my.collisions[other.ID] = other
other.collisions[my.ID] = my
end
end
end
end
-- Update collision status
for k,my in ipairs(collider.circleIDs) do
my = collider.colliders[my]
for kk,other in pairs(my.collisions) do
-- Check if its a new collision
if my.lastFrameCollisions[other.ID] == nil then
my.lastFrameCollisions[other.ID] = other
my.onTriggerEnter(collider.colliders[other.ID])
collider.colliders[other.ID].lastFrameCollisions[my.ID] = my
collider.colliders[other.ID].onTriggerEnter(my)
end
end
for kk,other in pairs(my.lastFrameCollisions) do
-- Check if collisions from last frame aren't there anymore
if my.collisions[other.ID] == nil then
my.lastFrameCollisions[other.ID] = nil
my.onTriggerExit(collider.colliders[other.ID])
collider.colliders[other.ID].lastFrameCollisions[my.ID] = nil
collider.colliders[other.ID].onTriggerExit(my)
end
end
end
end
function collider.draw()
for k,id in ipairs(collider.boxIDs) do
local v = collider.colliders[id]
if v ~= nil then
love.graphics.setColor(v.debugColor)
love.graphics.rectangle('line', v.x, v.y, v.width, v.height)
love.graphics.circle('fill', v.x + v.width/2, v.y + v.height/2, 3)
for kk,vv in ipairs(v.superPoints) do
love.graphics.circle('fill', vv.x, vv.y, 3)
end
love.graphics.print(v.ID, v.x + 5, v.y - 15)
love.graphics.print(v.tag, v.x + 5, v.y)
end
end
for k,id in ipairs(collider.circleIDs) do
local v = collider.colliders[id]
if v ~= nil then
love.graphics.setColor(v.debugColor)
love.graphics.circle('line', v.x, v.y, v.radius)
love.graphics.circle('fill', v.x, v.y, 3)
love.graphics.print(v.ID, v.x + 5, v.y - 15)
love.graphics.print(v.tag, v.x + 5, v.y)
end
end
end
return collider

View file

@ -0,0 +1,86 @@
--Transform v0.1
local transform = {}
function transform.new(newX, newY, rotation, scale)
local newT = {}
newT.position = { x = newX, y = newY }
newT.rotation = rotation or 0
newT.scale = scale or 1
function newT.Translate(newx, newy)
if type(newx) ~= 'number' then -- Not a Number
if type(newx) == 'table' and newx.x == nil then -- Table
newy = newx[2]
newx = newx[1]
elseif newx.x ~= nil then --Vector
newy = newx.y
newx = newx.x
end
end
newT.position.x = newT.position.x + newx
newT.position.y = newT.position.y + newy
end
function newT.Set(newx, newy, newrot, newscale)
newT.position.x = newx
newT.position.y = newy
newT.rotation = newrot or newT.rotation
newT.scale = newscale or newT.scale
end
function newT.GetNewPosition(newx, newy)
return newT.position.x + newx, newT.position.y + newy
end
function newT.Request(newx, newy, colliderID)
local c = collider.colliders[colliderID]
local collisions = nil
local collisionsY = nil
if c.type == 'box' then
collisions = collider.overlapBox(newT.position.x + newx, newT.position.y, c.width, c.height)
collisionsY = collider.overlapBox(newT.position.x, newT.position.y + newy, c.width, c.height)
else
collisions = collider.overlapCircle(newT.position.x + newx, newT.position.y, c.radius)
collisionsY = collider.overlapCircle(newT.position.x, newT.position.y + newy, c.radius)
end
local moveMult = {1, 1}
for k,v in pairs(collisions) do
if v.trigger == false and v.ID ~= c.ID then
moveMult[1] = 0
break
end
end
for k,v in pairs(collisionsY) do
if v.trigger == false and v.ID ~= c.ID then
moveMult[2] = 0
break
end
end
for k,v in pairs(collisionsY) do table.insert(collisions, v) end
for k,v in pairs(collisions) do
c.collisions[v.ID] = v
v.collisions[c.ID] = c
end
newT.Translate(newx * moveMult[1], newy * moveMult[2])
end
function newT.get()
return newT.position.x, newT.position.y, newT.rotation, newT.scale
end
return newT
end
return transform

View file

@ -4,7 +4,22 @@ love.graphics.setBackgroundColor(r, g, b)
local timer = 0 local timer = 0
local int = math.ceil(timer) local int = math.ceil(timer)
collider = require 'libs/collider'
function love.load() function love.load()
local dbgcol = {1,1,1}
-- THE RIGHT ONE WILL
-- collision thing
wall = {x = 100, y = 100, width = 50, height = 50}
wall.sprite = love.graphics.newImage('sprites/white.png')
-- If you installed transform.lua
local transform = require 'libs/transform'
anim8 = require 'libs/anim8' anim8 = require 'libs/anim8'
love.graphics.setDefaultFilter("nearest", "nearest") love.graphics.setDefaultFilter("nearest", "nearest")
checker = 0 checker = 0
@ -19,6 +34,9 @@ function love.load()
agent.animations = {} agent.animations = {}
agent.animations.right = anim8.newAnimation( agent.grid('1-3', 1),0.15) agent.animations.right = anim8.newAnimation( agent.grid('1-3', 1),0.15)
agent.animations.left = anim8.newAnimation( agent.grid('1-3', 2),0.15) agent.animations.left = anim8.newAnimation( agent.grid('1-3', 2),0.15)
agent.jumped = love.graphics.newImage('sprites/agent_jump.png')
agent.width = 64
agent.height = 64
agent.anim = agent.animations.right agent.anim = agent.animations.right
@ -27,6 +45,10 @@ function love.load()
end end
function love.update(dt) function love.update(dt)
collider.update()
t = 0 -- counter thing
timer = timer + dt timer = timer + dt
local distance local distance
local isMoving = false local isMoving = false
@ -85,23 +107,33 @@ function love.update(dt)
agent.vy = 0 agent.vy = 0
end end
if checkCollision(agent, wall) then
t = 0 + 1
end
-- collision checker thingy
end end
-- Draw a coloured rectangle. -- Draw a coloured rectangle.
function love.draw() function love.draw()
-- In versions prior to 11.0, color component values are (0, 102, 102) -- In versions prior to 11.0, color component values are (0, 102, 102)
love.graphics.print(agent.x, 10, 210) love.graphics.print(agent.x, 10, 210)
love.graphics.print(int, 350, 0) love.graphics.print(int, 350, 0)
agent.anim:draw(agent.spriteSheet, agent.x, agent.y, nil, 1) agent.anim:draw(agent.spriteSheet, agent.x, agent.y, nil, 1)
love.graphics.rectangle("fill", wall.x, wall.y, wall.width, wall.height)
love.graphics.print(t)
if isMouseDown then if isMouseDown then
drawDottedArc(agent.x, agent.y, mouseX, mouseY) drawDottedArc(agent.x, agent.y, mouseX, mouseY)
love.graphics.draw(agent.jumped, agent.x, agent.y, nil, 1)
end end
collider.draw()
end end
function drawDottedArc(x1, y1, x2, y2) function drawDottedArc(x1, y1, x2, y2)
@ -115,3 +147,13 @@ function drawDottedArc(x1, y1, x2, y2)
love.graphics.circle("fill", cx, cy, 2) love.graphics.circle("fill", cx, cy, 2)
end end
end end
-- thanks google
function checkCollision(obj1, obj2)
return obj1.x < obj2.x + obj2.width and
obj1.x + obj1.width > obj2.x and
obj1.y < obj2.y + obj2.height and
obj1.y + obj1.height > obj2.y
end
-- THE ACTUAL THING!!!