From 3d87aaf5e378c83adba9ee356f3d7a61546e10c3 Mon Sep 17 00:00:00 2001 From: Dangrain Date: Fri, 27 Sep 2024 22:35:30 +0200 Subject: [PATCH] Add files via upload --- actual game/libs/collider.lua | 499 +++++++++++++++++++++++++++++++++ actual game/libs/transform.lua | 86 ++++++ actual game/main.lua | 46 ++- 3 files changed, 629 insertions(+), 2 deletions(-) create mode 100644 actual game/libs/collider.lua create mode 100644 actual game/libs/transform.lua diff --git a/actual game/libs/collider.lua b/actual game/libs/collider.lua new file mode 100644 index 0000000..2261cf0 --- /dev/null +++ b/actual game/libs/collider.lua @@ -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 \ No newline at end of file diff --git a/actual game/libs/transform.lua b/actual game/libs/transform.lua new file mode 100644 index 0000000..14d21fa --- /dev/null +++ b/actual game/libs/transform.lua @@ -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 \ No newline at end of file diff --git a/actual game/main.lua b/actual game/main.lua index c2abc2b..9261150 100644 --- a/actual game/main.lua +++ b/actual game/main.lua @@ -4,7 +4,22 @@ love.graphics.setBackgroundColor(r, g, b) local timer = 0 local int = math.ceil(timer) +collider = require 'libs/collider' + + 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' love.graphics.setDefaultFilter("nearest", "nearest") checker = 0 @@ -19,6 +34,9 @@ function love.load() agent.animations = {} 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.jumped = love.graphics.newImage('sprites/agent_jump.png') + agent.width = 64 + agent.height = 64 agent.anim = agent.animations.right @@ -27,6 +45,10 @@ function love.load() end function love.update(dt) + + collider.update() + + t = 0 -- counter thing timer = timer + dt local distance local isMoving = false @@ -85,23 +107,33 @@ function love.update(dt) agent.vy = 0 end - + if checkCollision(agent, wall) then + t = 0 + 1 + end + -- collision checker thingy end + + + -- Draw a coloured rectangle. function love.draw() -- In versions prior to 11.0, color component values are (0, 102, 102) love.graphics.print(agent.x, 10, 210) love.graphics.print(int, 350, 0) 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 drawDottedArc(agent.x, agent.y, mouseX, mouseY) + love.graphics.draw(agent.jumped, agent.x, agent.y, nil, 1) end - + collider.draw() end function drawDottedArc(x1, y1, x2, y2) @@ -115,3 +147,13 @@ function drawDottedArc(x1, y1, x2, y2) love.graphics.circle("fill", cx, cy, 2) 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!!!