Page 1 of 3

help with collisions [Solved]

Posted: Wed Sep 04, 2019 5:55 pm
by bobbymcbobface
Hi all, i need some help introducing collision and collision detection to my game

things you need you might need to know

my game is top down
i need to allow certain tiles to have collision
i need to detect when a tile is collided with
I'm a complete noob at this and have no idea how collision works but i do have basic love2d knowledge :ultraglee:

Re: help with collisions

Posted: Wed Sep 04, 2019 8:40 pm
by pgimeno
My advice: don't try to come up with your own system. Use the built-in Box2D (love.physics) or a library that handles collisions like Bump or HC.

The simplest collision model is that where the colliding shapes are axis-aligned bounding boxes (AABBs). If you can get away with that in your game, then Bump is highly recommended. But if the shapes can be at an angle, or be non-rectangular, Bump won't help you, and you need either Box2D or HC.

Box2D has the advantages that it's in C/C++, that it's integrated with LÖVE, and that it handles collision response automatically (like Bump). The drawbacks are that it's more heavyweight and harder to manage, especially when you prefer cartoonish movement over physically realistic movement. For those cases, you may prefer HC, but IIRC you need to implement the collision response yourself. Fortunately it provides tools for that.

Re: help with collisions

Posted: Thu Sep 05, 2019 5:50 am
by raidho36
If you want to get a game done, don't reinvent the wheels, find a pre-made tool and use it. If you want to get good, then by all means take your time to reinvent everything, but don't expect to actually make any games any time soon.

Games don't need high quality source code, they just need to function. But not having good programming skills will bottleneck a complicated or computationally intensive project.

Re: help with collisions

Posted: Thu Sep 05, 2019 6:35 am
by bobbymcbobface
Ok thanks guys

And raidho36 I understand what you mean and I will admit my source code is a bit messy at the moment but in future when I get a better grasp at löve2d I'll fix it up, sure this may cause complications later on in the code but I don't mind re inventing it. Also does one of you or someone mind giving me an example of bump on a top down map since last time I tried it didn't even spawn the bump script

Thank you.

Re: help with collisions

Posted: Thu Sep 05, 2019 1:15 pm
by pgimeno
bobbymcbobface wrote: Thu Sep 05, 2019 6:35 amAlso does one of you or someone mind giving me an example of bump on a top down map since last time I tried it didn't even spawn the bump script
Not sure what you mean by "spawn" the bump script. There's nothing special about a top-down map when it comes to handling collisions. Any example of bump is good. Some examples will apply gravity to some entities if they are a side view (like platformers) but that doesn't change the idea. You can check the "simpledemo" here: http://github.com/kikito/bump.lua/tree/simpledemo

The main idea of Bump is that every collidable surface is a box. If your map is made of tiles, and the tiles are either fully collidable or not collidable at all, then you just add to the Bump world the rectangles that correspond to the collidable tiles. If they are more complex, with some tiles subdivided into more rectangles, you need some way to store that info in the map, so that you can add each individual rectangle to the Bump world.

Re: help with collisions

Posted: Thu Sep 05, 2019 6:25 pm
by bobbymcbobface
Ok I've had a look at the demo and a look around the internet and unfortunately I'm still extremely confused i understand how bump works (kind of) but I'm having troubles knowing the code for how i would store the data collisions for the map here's the code for my map i need to add collisions to:

Code: Select all

lobby = {}

function lobby:load()
  love.window.setFullscreen(true, "desktop")
  TileW, TileH = 32,32
  
  Tileset = love.graphics.newImage('mytileset.png')
  
  local tilesetW, tilesetH = Tileset:getWidth(), Tileset:getHeight()

  local quadInfo = {
    { 'o', 64, 0 },
    { 'O', 96, 0},
    
    { '[', 65, 32 },
    { '{', 65, 64 },
    
    { '-', 96, 32 },
    { '_', 96, 64 },
    
    { ']', 125, 32},
    { '}', 125, 64},
    
    { 'p', 224, 32},
    { ';', 224, 64}
  }

  Quads = {}
  for _,info in ipairs(quadInfo) do
    -- info[1] = character, info[2]= x, info[3] = y
    Quads[info[1]] = love.graphics.newQuad(info[2], info[3], TileW, TileH, tilesetW, tilesetH)
  end


  local tileString = [[
[----------]p[----------]
{__________};{__________}
ooooooooooooooooooooooooo
ooooooooooooooOoooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooOoooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooOoooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
oooooooooooOooooooooooooo
ooooooooooooooooooooooooo
]]

  TileTable = {}
  
  local width = #(tileString:match("[^\n]+"))
  
  for x = 1,width,1 do TileTable[x] = {} end

  local rowIndex,columnIndex = 1,1
  for row in tileString:gmatch("[^\n]+") do
    assert(#row == width, 'Map is not aligned: width of row ' .. tostring(rowIndex) .. ' should be ' .. tostring(width) .. ', but it is ' .. tostring(#row))
    columnIndex = 1
    for character in row:gmatch(".") do
      TileTable[columnIndex][rowIndex] = character
      columnIndex = columnIndex + 1
    end
    rowIndex=rowIndex+1
  end
end


function lobby:draw()
  
  for columnIndex,column in ipairs(TileTable) do
    for rowIndex,char in ipairs(column) do
      local x,y = (columnIndex-1)*TileW, (rowIndex-1)*TileH
      love.graphics.draw(Tileset, Quads[char], x, y)
    end
  end

end

return lobby

--- exit to room needed
--- character needed
---                       |
--- remember to use these V
---                      sprite:move_true()
---                      sprite:draw()
---                      menu:allow()
and here's the tile set image:
mytileset.png
mytileset.png (8.87 KiB) Viewed 6081 times
Can anyone help me implement it into my code or just give me a nudge in the correct direction

Re: help with collisions

Posted: Thu Sep 05, 2019 8:27 pm
by pgimeno
You create a world first with bump.newWorld(size) (I'll talk about size later). Then right after this line:

Code: Select all

TileTable[columnIndex][rowIndex] = character
you need to check if the character is one of the collidable map elements. If it is, you add the tile to the world. For example:

Code: Select all

world:add({x=columnIndex, y=rowIndex}, (columnIndex - 1)*TileW, (rowIndex - 1)*TileH, TileW, TileH)
That's assuming that your player position will be in pixels. If you wish the positions of your entities (e.g. the player) to be in map coordinates, it would be something like this instead:

Code: Select all

world:add({x=columnIndex, y=rowIndex}, columnIndex, rowIndex, 1, 1)
About size: creating the world with something like twice the size of your rectangles is OK, but take into account that the size of a map rectangle is 1 if you're using map coordinates, and 32 if you're using pixels with TileW=TileH=32.

Re: help with collisions

Posted: Fri Sep 06, 2019 3:17 pm
by bobbymcbobface
ok thankyou pgimeno, so how would i go on about doing this:

"you need to check if the character is one of the collidable map elements."

Re: help with collisions

Posted: Fri Sep 06, 2019 8:29 pm
by pgimeno
One straightforward way is:

Code: Select all

 if character == "collidable_tile_1" or character == "collidable_tile_2" or character == "collidable_tile_3" or ... then
But you can define a table near the beginning instead, which is easier to modify later:

Code: Select all

local collidable_chars = { ["collidable_tile_1"] = true, ["collidable_tile_2"] = true, ... }

...

  if collidable_chars[character] then
I'm not sure which characters in your map represent collidable tiles, but assuming for example that 'o' and 'O' are both collidable, one way to start would be:

Code: Select all

local collidable_chars = { ["o"] = true, ["O"] = true, ... }

Re: help with collisions

Posted: Sat Sep 07, 2019 6:31 am
by bobbymcbobface
Ah thankyou, I'll try this as soon as I get a chance

EDIT: ok i managed to experiment with the code and so far i have this:

Code: Select all

lobby = {}

local sprite = require('sprite')
local bump = require('bump')

function lobby:load()
  sprite:move_true()
  --sprite:add_collision({x=columnIndex, y=rowIndex}, columnIndex, rowIndex, 1, 1)
  
  print('map check:')
  
  world = bump.newWorld(32)

  TileW, TileH = 32,32
  
  Tileset = love.graphics.newImage('mytileset.png')
  
  local tilesetW, tilesetH = Tileset:getWidth(), Tileset:getHeight()
  
  local collidable_chars = { ["p"] = true, ["p"] = true}
  
  local quadInfo = {
    { 'o', 64, 0 },
    { 'O', 96, 0},
    
    { '[', 65, 32 },
    { '{', 65, 64 },
    
    { '-', 96, 32 },
    { '_', 96, 64 },
    
    { ']', 125, 32},
    { '}', 125, 64},
    
    { 'p', 224, 32},
    { ';', 224, 64}
  }

  Quads = {}
  for _,info in ipairs(quadInfo) do
    -- info[1] = character, info[2]= x, info[3] = y
    Quads[info[1]] = love.graphics.newQuad(info[2], info[3], TileW, TileH, tilesetW, tilesetH)
  end


  local tileString = [[
[----------]p[----------]
{__________};{__________}
ooooooooooooooooooooooooo
ooooooooooooooOoooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooOoooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooOoooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
ooooooooooooooooooooooooo
oooooooooooOooooooooooooo
ooooooooooooooooooooooooo
]]

  TileTable = {}
  
  local width = #(tileString:match("[^\n]+"))
  
  for x = 1,width,1 do TileTable[x] = {} end

  local rowIndex,columnIndex = 1,1
  for row in tileString:gmatch("[^\n]+") do
    assert(#row == width, 'Map is not aligned: width of row ' .. tostring(rowIndex) .. ' should be ' .. tostring(width) .. ', but it is ' .. tostring(#row))
    columnIndex = 1
    for character in row:gmatch(".") do
      TileTable[columnIndex][rowIndex] = character
      
      if collidable_chars['o'] then
        sprite:add_collision({x=columnIndex, y=rowIndex}, (columnIndex - 1)*TileW, (rowIndex - 1)*TileH, TileW, TileH)
        
      end
      columnIndex = columnIndex + 1
    end
    rowIndex=rowIndex+1
  end
end


function lobby:draw()
  for columnIndex,column in ipairs(TileTable) do
    for rowIndex,char in ipairs(column) do
      local x,y = (columnIndex-1)*TileW, (rowIndex-1)*TileH
      love.graphics.draw(Tileset, Quads[char], x, y)
    end
  end
  
  sprite:draw()

end

return lobby

--- exit to room needed
--- character needed
---                       |
--- remember to use these V
---                      sprite:move_true()
---                      sprite:draw()
---                      menu:allow()
---                      themap:load()
---                      love.graphics.draw(tilesetBatch)
and this doesn't seem to sort out any collsion can someone do some debugging on my code and help me out

also for reference here is the code for sprite:add_collision() :

Code: Select all

function sprite:add_collision(item, x, y, w ,h)
    world:add(item, x, y, w, h)
end
thankyou