Page 1 of 1

Collision with walls

Posted: Sun Apr 10, 2016 9:24 pm
by Teshi
Hi im trying to do collision with walls myself but its just hitting the fan. It works kinda, but when i add more walls it just goes to shit. Could anyone offer any help? Im not the best coder and my head is just melting trying to solve this. The problem i think is because of the two "left" walls, collision works for one of them but not the other and i know its to do with how i reset the playercanwalk variable but i dont know how to write it in such a way that it works :(

Code: Select all

map =                                  
{
  walls = 
  {
    wall1 = 
    {
      id = 1, x = 100, y = 605, w = 190, h = 35, block = "up"
    },
    wall2 = 
    {
      id = 2, x = 300 - 40, y = 640-200, w = 35, h = 195, block = "left"
    },
    wall3 =
    {
      id = 3, x = 100, y = 735, w = 300, h = 35, block = "down"
    },
    wall4 =
    {
      id = 4, x = 65, y = 605, w = 35, h = 165, block = "left"
    },
    wall5 =
    {
      id = 5, x = 400, y = 440, w= 35, h = 330, block = "right"
    }
  }
}

function drawWalls(x, y, w, h) 
  love.graphics.setColor(50, 50, 200, 255)
  love.graphics.rectangle("fill", x, y, w, h)
end

function updateWalls()     
  local i,v
  for i,v in pairs(map.walls) do
    local px,py = player:getPos()
    local pxo, pyo = player:getOffset()
    local x, y, w, h, block = v.x, v.y, v.w, v.h, v.block 
    local col = checkCollision(px-pxo, py-pyo, player.width, player.height, x, y, w, h)
    if col == true then
      if block == "left" and player.canwalk.left == true then       
        player.canwalk.left = false                                                     
        
      elseif block == "up" then
        player.canwalk.up = false
        
      elseif block == "down" then
        player.canwalk.down = false
        
      elseif block == "right" then    
        player.canwalk.right = false
      end
    end
    
    if col == false then
      if block ~= "left" and player.canwalk.left == false then
        
        player.canwalk.left = true
      
      end
      if block == "right" then
        player.canwalk.right = true
      
      end
      if block == "up" then    
        player.canwalk.up = true
        
      end
      if block == "down" then
        player.canwalk.down = true
        
      end
    end
  end
end

Re: Collision with walls

Posted: Mon Apr 11, 2016 8:24 am
by Vimm
Teshi wrote:Hi im trying to do collision with walls myself but its just hitting the fan. It works kinda, but when i add more walls it just goes to shit. Could anyone offer any help? Im not the best coder and my head is just melting trying to solve this. The problem i think is because of the two "left" walls, collision works for one of them but not the other and i know its to do with how i reset the playercanwalk variable but i dont know how to write it in such a way that it works :(

Code: Select all

map =                                  
{
  walls = 
  {
    wall1 = 
    {
      id = 1, x = 100, y = 605, w = 190, h = 35, block = "up"
    },
    wall2 = 
    {
      id = 2, x = 300 - 40, y = 640-200, w = 35, h = 195, block = "left"
    },
    wall3 =
    {
      id = 3, x = 100, y = 735, w = 300, h = 35, block = "down"
    },
    wall4 =
    {
      id = 4, x = 65, y = 605, w = 35, h = 165, block = "left"
    },
    wall5 =
    {
      id = 5, x = 400, y = 440, w= 35, h = 330, block = "right"
    }
  }
}

function drawWalls(x, y, w, h) 
  love.graphics.setColor(50, 50, 200, 255)
  love.graphics.rectangle("fill", x, y, w, h)
end

function updateWalls()     
  local i,v
  for i,v in pairs(map.walls) do
    local px,py = player:getPos()
    local pxo, pyo = player:getOffset()
    local x, y, w, h, block = v.x, v.y, v.w, v.h, v.block 
    local col = checkCollision(px-pxo, py-pyo, player.width, player.height, x, y, w, h)
    if col == true then
      if block == "left" and player.canwalk.left == true then       
        player.canwalk.left = false                                                     
        
      elseif block == "up" then
        player.canwalk.up = false
        
      elseif block == "down" then
        player.canwalk.down = false
        
      elseif block == "right" then    
        player.canwalk.right = false
      end
    end
    
    if col == false then
      if block ~= "left" and player.canwalk.left == false then
        
        player.canwalk.left = true
      
      end
      if block == "right" then
        player.canwalk.right = true
      
      end
      if block == "up" then    
        player.canwalk.up = true
        
      end
      if block == "down" then
        player.canwalk.down = true
        
      end
    end
  end
end

Why dont you test the collision using the method on the wiki? https://love2d.org/wiki/BoundingBox.lua

Code: Select all

function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
	return x1 < x2+w2 and
		x2 < x1+w1 and
		y1 < y2+h2 and
		y2 < y1+h1
end

Re: Collision with walls

Posted: Mon Apr 11, 2016 8:28 am
by Teshi
Vimm wrote:
Why dont you test the collision using the method on the wiki? https://love2d.org/wiki/BoundingBox.lua

Code: Select all

function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
	return x1 < x2+w2 and
		x2 < x1+w1 and
		y1 < y2+h2 and
		y2 < y1+h1
end
The collision does work and I am using that function but my issue is that when i add 2 walls that block movement in the same direction, only one of them works.

Re: Collision with walls

Posted: Mon Apr 11, 2016 10:33 am
by DaedalusYoung
Set the player.canwalk booleans all to true before you start the for loop, and get rid of them in the if col == false block. My guess is that alone should work, but you could also try that once you determined that there is a collision, you iterate the walls table, then as soon as you've found the block direction you break out of that loop. The problem is that you find a collision, so you set col to true and search the table to determine the block direction and set player.canwalk to false. All fine, but then you keep searching the walls, only to find there is no collision on later tiles, so you reset the player.canwalk back to true. If you'd break out of the loop after you've found the first collision, no further check will be done, so the player.canwalk boolean will not be reset.

Also...

Code: Select all

local i,v
This is completely unnecessary. :)

Re: Collision with walls

Posted: Mon Apr 11, 2016 3:28 pm
by Teshi
DaedalusYoung wrote:Set the player.canwalk booleans all to true before you start the for loop, and get rid of them in the if col == false block. My guess is that alone should work, but you could also try that once you determined that there is a collision, you iterate the walls table, then as soon as you've found the block direction you break out of that loop. The problem is that you find a collision, so you set col to true and search the table to determine the block direction and set player.canwalk to false. All fine, but then you keep searching the walls, only to find there is no collision on later tiles, so you reset the player.canwalk back to true. If you'd break out of the loop after you've found the first collision, no further check will be done, so the player.canwalk boolean will not be reset.

Also...

Code: Select all

local i,v
This is completely unnecessary. :)
Oh wow thank you dude, its working now! Oh right, I think I read it in a tutorial for shooting and since then it became habit to do local i,v.

Re: Collision with walls

Posted: Mon Apr 11, 2016 8:42 pm
by DaedalusYoung
Glad it works :)

Yeah, you don't need to declare them as local, they automatically are:
http://www.lua.org/pil/4.3.5.html wrote:The loop variables are local to the loop body (...)