Trying to make collisions work

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
darkfrei
Party member
Posts: 1181
Joined: Sat Feb 08, 2020 11:09 pm

Re: Trying to make collisions work

Post by darkfrei »

notcl4y wrote: Mon Jun 12, 2023 8:00 am
darkfrei wrote: Sun Jun 11, 2023 9:00 pm
notcl4y wrote: Sun Jun 11, 2023 8:30 pm So it only works via dx and dy? No checking if the collider collides with another one and separate it from that collider just via setting the position but dx and dy?
If nothing moves then nothing collides! But if you move something, then you need to solve this for all colliding objects.
The system I'm trying to make is if it collides then it will separate, so it means that if the object will move or instantly teleport into a collider then it will separate. Not when a collider moves into another one.
If you move object by the dx, dy then you teleport this object to the new position, same as it was by the mouse position.

Code: Select all

function moveObj (obj, dx, dy)
  obj.x = obj.x + dx 
  obj.y = obj.y + dy
end

Code: Select all

function teleportObj (obj, x, y)
  obj.x = x
  obj.y = y
end
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
notcl4y
Citizen
Posts: 85
Joined: Fri Nov 25, 2022 12:23 pm

Re: Trying to make collisions work

Post by notcl4y »

darkfrei wrote: Mon Jun 12, 2023 9:27 am
notcl4y wrote: Mon Jun 12, 2023 8:00 am
darkfrei wrote: Sun Jun 11, 2023 9:00 pm

If nothing moves then nothing collides! But if you move something, then you need to solve this for all colliding objects.
The system I'm trying to make is if it collides then it will separate, so it means that if the object will move or instantly teleport into a collider then it will separate. Not when a collider moves into another one.
If you move object by the dx, dy then you teleport this object to the new position, same as it was by the mouse position.

Code: Select all

function moveObj (obj, dx, dy)
  obj.x = obj.x + dx 
  obj.y = obj.y + dy
end

Code: Select all

function teleportObj (obj, x, y)
  obj.x = x
  obj.y = y
end
Would you like me to share the code of the library I am trying to make so you can find out how it works and how to make the separate() function. Sorry for me being like this.

Code: Select all

loves_lua = "not so",
wants_to = true
User avatar
darkfrei
Party member
Posts: 1181
Joined: Sat Feb 08, 2020 11:09 pm

Re: Trying to make collisions work

Post by darkfrei »

notcl4y wrote: Mon Jun 12, 2023 9:51 am
Wouldn't you mind me sharing the code of the library I'm trying to make so you can find out how it works and how to make the separate() function. Sorry for me being like this.
You can share your lib and we are trying to fix it. Here dx and dy are just the position difference, we don't change the velocity of object, but position.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
notcl4y
Citizen
Posts: 85
Joined: Fri Nov 25, 2022 12:23 pm

Re: Trying to make collisions work

Post by notcl4y »

darkfrei wrote: Mon Jun 12, 2023 10:04 am
notcl4y wrote: Mon Jun 12, 2023 9:51 am
Wouldn't you mind me sharing the code of the library I'm trying to make so you can find out how it works and how to make the separate() function. Sorry for me being like this.
You can share your lib and we are trying to fix it. Here dx and dy are just the position difference, we don't change the velocity of object, but position.

Code: Select all

local lCollision = {}

local function range(x1, y1, width1, height1, x2, y2, width2, height2)
  if x1 >= x2 and x1 + width1 <= x2 + width2 and y1 >= y2 and y1 + height1 <= y2 + height2 then
    return true
  end
  
  return false
end

local function rangeWhole(x1, y1, width1, height1, x2, y2, width2, height2)
  --if x1 >= x2 and x1 + width1 <= x2 + width2 + width1 and y1 >= y2 and y1 + height1 <= y2 + height2 + height1 then
  if x1 + width1 >= x2 and x1 <= x2 + width2 and y1 + height1 >= y2 and y1 <= y2 + width2 then
    return true
  end
  
  return false
end

lCollision.Collider = {}
lCollision.Collider.__index = lCollision.Collider

function lCollision.Collider:new(x, y, width, height)
  local collider = setmetatable({}, self)
  
  collider.x = x
  collider.y = y
  collider.width = width
  collider.height = height
  
  return collider
end

function lCollision.Collider:draw()
  love.graphics.rectangle("line", self.x, self.y, self.width, self.height)
end

-- This function used to be called collider:collides(collider) until it showed that it can detect if a collider is INSIDE of another one
function lCollision.Collider:insideOf(collider)
  if range(self.x, self.y, self.width, self.height, collider.x, collider.y, collider.width, collider.height) then
    return true
  end
  
  return false
end

function lCollision.Collider:collides(collider)
  if rangeWhole(self.x, self.y, self.width, self.height, collider.x, collider.y, collider.width, collider.height) then
    return true
  end
  
  return false
end

-- Ah yes, the function that gave a lot of PAIN to make
function lCollision.Collider:separate(collider)
  if self.x + self.width / 2 < collider.x + collider.width / 2 then
    -- middle point of agent is more left than by the box
    self.x = -self.width + (collider.x - self.x)
  else
    self.x = collider.width - (self.x - collider.x)
  end
  
  if self.y + self.height / 2 < collider.y + collider.height / 2 then
    -- middle point of agent is higher than by the box
    self.y = -self.height + (collider.y - self.y)
  else
    self.x = collider.height - (self.y - collider.y)
  end
  
  --[[local centerX, centerY = self:getCenter()
  local rightSide = self.x + self.width
  local bottomSide = self.y + self.height
  local colliderCenterX, colliderCenterY = collider:getCenter()
  local colliderRightSide = collider.x + collider.width
  local colliderBottomSide = collider.y + collider.height
  
  if bottomSide >= collider.y and self.y <= colliderBottomSide then
      if rightSide >= collider.x and rightSide < colliderCenterX then
        self.x = collider.x - self.width
      elseif self.x <= colliderRightSide and rightSide > colliderCenterX then
        self.x = collider.x + collider.width
      end
    elseif rightSide >= collider.x and self.x <= colliderRightSide then
      if bottomSide >= collider.y and bottomSide < colliderCenterY then
        self.y = collider.y - self.height
      elseif self.y <= colliderBottomSide and bottomSide > colliderCenterY then
        self.y = collider.y + collider.height
      end
    end]]
    
  --while self:collides(collider) do
  --  local centerX, centerY = self:getCenter()
  --  local rightSide = self.x + self.width
  --  local bottomSide = self.y + self.height
  --  local colliderCenterX, colliderCenterY = collider:getCenter()
  --  local colliderRightSide = collider.x + collider.width
  --  local colliderBottomSide = collider.y + collider.height
    
    --[[if bottomSide >= collider.y and self.y <= colliderBottomSide then
      if rightSide >= collider.x and rightSide < colliderCenterX then
        self.x = self.x - 1
      elseif self.x <= colliderRightSide and rightSide > colliderCenterX then
        self.x = self.x + 1
      end
    elseif rightSide >= collider.x and self.x <= colliderRightSide then
      if bottomSide >= collider.y and bottomSide < colliderCenterY then
        self.y = self.y - 1
      elseif self.y <= colliderBottomSide and bottomSide > colliderCenterY then
        self.y = self.y + 1
      end
    end]]
    --[[if self.x <= colliderX then
      self.x = self.x - 1
    end
    
    if self.x >= colliderX then
      self.y = self.y + 1
    end
    
    if self.y <= colliderY then
      self.y = self.y - 1
    end
    
    if self.y >= colliderY then
      self.y = self.y + 1
    end]]
    
    --[[if self.y > collider.y and self.y + self.height < collider.y + collider.height then
      if self.x <= colliderX then
        self.x = self.x - 1
      end
      
      if self.x >= colliderX then
        self.x = self.x + 1
      end
    elseif self.x > collider.x and self.x + self.width < collider.x + collider.width then
      if self.y <= colliderY then
        self.y = self.y - 1
      end
      
      if self.y >= colliderY then
        self.y = self.y + 1
      end
    end]]
  --end
end

function lCollision.Collider:getCenter()
  local x = self.x + self.width / 2
  local y = self.y + self.height / 2
  
  return x, y
end

return lCollision
And here's the library's github repo, but it doesn't have the current changes like in the code I've sent above: https://github.com/notcl4y14/lCollision

Code: Select all

loves_lua = "not so",
wants_to = true
User avatar
darkfrei
Party member
Posts: 1181
Joined: Sat Feb 08, 2020 11:09 pm

Re: Trying to make collisions work

Post by darkfrei »

notcl4y wrote: Mon Jun 12, 2023 11:26 am And here's the library's github repo, but it doesn't have the current changes like in the code I've sent above: https://github.com/notcl4y14/lCollision
Thanks, here some fixes:
https://github.com/notcl4y14/lCollision

Code: Select all

-- lCollision.lua
-- https://github.com/notcl4y14/lCollision/blob/main/lCollision.lua

local lCollision = {}
lCollision.__index = lCollision


local function checkCollision(x1,y1,w1,h1, x2,y2,w2,h2)
-- from https://love2d.org/wiki/BoundingBox.lua
	return x1 < x2+w2 and x2 < x1+w1 and y1 < y2+h2 and y2 < y1+h1
end


function lCollision:collides(collider)
	if checkCollision(self.x, self.y, self.width, self.height, collider.x, collider.y, collider.width, collider.height) then
		return true
	end
	return false
end


function lCollision:insideOf(collider)
	if checkCollision(
		self.x, self.y, self.width, self.height, 
		collider.x+self.width, collider.y+self.height, collider.width-2*self.width, collider.height-2*self.height
		) then
		return true
	end
	
	return false
end

function lCollision:onBorder(collider)
	if self:collides(collider) and not self:insideOf(collider) then
		return true
	end
	return false
end

function lCollision:separate(collider)
	if not checkCollision(self.x,self.y,self.width,self.height, collider.x,collider.y,collider.width,collider.height) then
		-- no collision: nothing to do
		return
	end
	
	-- (dx, dy) will be orthogonal separation vector
	local dx = collider.x - self.x
	local dy = collider.y - self.y
	if self.x + self.width / 2 < collider.x + collider.width / 2 then
		-- middle point of agent is more left than by the box
		dx = dx - self.width
	else
		dx = dx + collider.width
	end
	
	if self.y + self.height / 2 < collider.y + collider.height / 2 then
		-- middle point of agent is higher than by the box
		dy = dy - self.height
	else
		dy = dy + collider.height
	end
	
	-- making the separation vector orthogonal:
	if math.abs (dx) > math.abs (dy) then
		dx = 0 -- dx was longer than dy
	else
		dy = 0
	end
	
	-- moving the self
	self.x = self.x + dx
	self.y = self.y + dy
end


--------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------

function lCollision:new(x, y, width, height)
	local collider = setmetatable({x=x, y=y, width=width, height=height}, self)
	return collider
end


function lCollision:draw()
	love.graphics.rectangle("line", self.x, self.y, self.width, self.height)
end


return lCollision
Screenshot 2023-06-12 175938.png
Screenshot 2023-06-12 175938.png (13.19 KiB) Viewed 1718 times
Attachments
lCollision-01.love
(1.55 KiB) Downloaded 56 times
Last edited by darkfrei on Tue Jun 13, 2023 10:34 am, edited 1 time in total.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
notcl4y
Citizen
Posts: 85
Joined: Fri Nov 25, 2022 12:23 pm

Re: Trying to make collisions work

Post by notcl4y »

darkfrei wrote: Mon Jun 12, 2023 4:01 pm
notcl4y wrote: Mon Jun 12, 2023 11:26 am And here's the library's github repo, but it doesn't have the current changes like in the code I've sent above: https://github.com/notcl4y14/lCollision
Thanks, here some fixes:

Code: Select all

-- lCollision.lua
-- https://github.com/notcl4y14/lCollision/blob/main/lCollision.lua

local lCollision = {}
lCollision.__index = lCollision


local function checkCollision(x1,y1,w1,h1, x2,y2,w2,h2)
-- from https://love2d.org/wiki/BoundingBox.lua
	return x1 < x2+w2 and x2 < x1+w1 and y1 < y2+h2 and y2 < y1+h1
end


function lCollision:collides(collider)
	if checkCollision(self.x, self.y, self.width, self.height, collider.x, collider.y, collider.width, collider.height) then
		return true
	end
	return false
end


function lCollision:insideOf(collider)
	if checkCollision(
		self.x, self.y, self.width, self.height, 
		collider.x+self.width, collider.y+self.height, collider.width-2*self.width, collider.height-2*self.height
		) then
		return true
	end
	
	return false
end

function lCollision:onBorder(collider)
	if self:collides(collider) and not self:insideOf(collider) then
		return true
	end
	return false
end

function lCollision:separate(collider)
	if not checkCollision(self.x,self.y,self.width,self.height, collider.x,collider.y,collider.width,collider.height) then
		-- no collision: nothing to do
		return
	end
	
	-- (dx, dy) will be orthogonal separation vector
	local dx = collider.x - self.x
	local dy = collider.y - self.y
	if self.x + self.width / 2 < collider.x + collider.width / 2 then
		-- middle point of agent is more left than by the box
		dx = dx - self.width
	else
		dx = dx + collider.width
	end
	
	if self.y + self.height / 2 < collider.y + collider.height / 2 then
		-- middle point of agent is higher than by the box
		dy = dy - self.height
	else
		dy = dy + collider.height
	end
	
	-- making the separation vector orthogonal:
	if math.abs (dx) > math.abs (dy) then
		dx = 0 -- dx was longer than dy
	else
		dy = 0
	end
	
	-- moving the self
	self.x = self.x + dx
	self.y = self.y + dy
end


--------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------

function lCollision:new(x, y, width, height)
	local collider = setmetatable({x=x, y=y, width=width, height=height}, self)
	return collider
end


function lCollision:draw()
	love.graphics.rectangle("line", self.x, self.y, self.width, self.height)
end


return lCollision
Screenshot 2023-06-12 175938.png
Thanks! Should I put the credits only in the library file as a comment?

Code: Select all

loves_lua = "not so",
wants_to = true
User avatar
darkfrei
Party member
Posts: 1181
Joined: Sat Feb 08, 2020 11:09 pm

Re: Trying to make collisions work

Post by darkfrei »

notcl4y wrote: Tue Jun 13, 2023 5:16 am Thanks! Should I put the credits only in the library file as a comment?
As you want, it's more education project, I am sure that anyone wrote almost same lib, but we are making it for better understanding and for experience for next more complicated projects.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
notcl4y
Citizen
Posts: 85
Joined: Fri Nov 25, 2022 12:23 pm

Re: Trying to make collisions work

Post by notcl4y »

darkfrei wrote: Tue Jun 13, 2023 8:20 am As you want
Ok, thanks!

Code: Select all

loves_lua = "not so",
wants_to = true
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 50 guests