How could I implement tilemap collisions for my platformer?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
MaxGamz
Party member
Posts: 107
Joined: Fri Oct 28, 2022 3:09 am

How could I implement tilemap collisions for my platformer?

Post by MaxGamz »

I found many tutorials relating to this topic but most of them had to deal with box2d and windfield. I heard I can implement this using a Grid but I am not familiar with this method at all. I don't plan to use box2d or windfield since I don't want realistic physics in my game, but I'm not sure what other options I have.
User avatar
darkfrei
Party member
Posts: 1216
Joined: Sat Feb 08, 2020 11:09 pm

Re: How could I implement tilemap collisions for my platformer?

Post by darkfrei »

MaxGamz wrote: Fri Apr 28, 2023 3:26 am I found many tutorials relating to this topic but most of them had to deal with box2d and windfield. I heard I can implement this using a Grid but I am not familiar with this method at all. I don't plan to use box2d or windfield since I don't want realistic physics in my game, but I'm not sure what other options I have.

Code: Select all

function isGridCollision (grid, gx, gy, cValue) -- grid as map[y][x]; gx, gy as integer grid position
	if grid[gy] and grid[gy][gx] ~= nil then
		-- tile exists
		if grid[gy][gx] == cValue then -- cValue as collision value: wall, floor etc.
			return true
		else
			return false -- no collision
		end
	else
		-- tile not exist
		return true -- collision to out-of-map
	end
end
Optional can be rounding as

Code: Select all

gx = math.floor (x)
gy = math.floor (y)
So position x=3.14, y=6.98 can have collision with tile gx=3, gy=6, but not with gx=3, gy=7

The block object can have a list of tiles:

Code: Select all

blockObj1 = {
	x=3, y=6,
	tiles = {0,0, -- in the grid the position will be {x=3, y=6} for this tile
	1,0, 0,1, 1,1}, -- the block has 2x2 shape now
	w=2, h=2, -- the dimension of this block for rough_not_collision_detection, 
	-- that compares just AABB (minus one)
}
https://love2d.org/wiki/BoundingBox.lua

Code: Select all

function isRoughBBCollision (block1, block2) -- rough block-to-block collision (not tested)
	if block2.x > block1.x+block1.w-1 or block2.y > block1.y+block1.h-1
	or block1.x > block2.x+block2.w-1 or block1.y > block2.y+block2.h-1 then 
		return false -- collision is not possible
	end
	return true -- may be collision, need for tile-by-tile comparing
end

Code: Select all

function isFineBBCollision (block1, block2) -- fine block-to-block collision (not tested)
	local x1, y1, tiles1 = block1.x, block1.y, block1.tiles
	local x2, y2, tiles2 = block2.x, block2.y, block2.tiles
	for index1 = 1, #tiles1 -1, 2 do
		for index2 = 1, #tiles2-1, 2 do
			if x1+tiles1[index1] == x2+tiles2[index2] and
			   y1+tiles1[index1+1] == y2+tiles2[index2+1] then
			   	-- the tiles have collision, optionally the position of it.
				return true, x1+tiles1[index1], y1+tiles1[index1+1]
			end
		end
	end
	return false
end
The object-to-grid collision detection is almost same:

Code: Select all

function isBGCollision (grid, block) -- block-to-grid collision (not tested)
	local x, y, tiles = block.x, block.y, block.tiles
	for index = 1, #tiles -1, 2 do
		local gx, gy = x+tiles[index], y+tiles[index+1] 
		if isGridCollision (grid, gx, gy, 1) then -- collision on value = 1
			return true, gx, gy
		end
	end
	return false
end
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
MaxGamz
Party member
Posts: 107
Joined: Fri Oct 28, 2022 3:09 am

Re: How could I implement tilemap collisions for my platformer?

Post by MaxGamz »

darkfrei wrote: Fri Apr 28, 2023 7:18 am
MaxGamz wrote: Fri Apr 28, 2023 3:26 am I found many tutorials relating to this topic but most of them had to deal with box2d and windfield. I heard I can implement this using a Grid but I am not familiar with this method at all. I don't plan to use box2d or windfield since I don't want realistic physics in my game, but I'm not sure what other options I have.

Code: Select all

function isGridCollision (grid, gx, gy, cValue) -- grid as map[y][x]; gx, gy as integer grid position
	if grid[gy] and grid[gy][gx] ~= nil then
		-- tile exists
		if grid[gy][gx] == cValue then -- cValue as collision value: wall, floor etc.
			return true
		else
			return false -- no collision
		end
	else
		-- tile not exist
		return true -- collision to out-of-map
	end
end
Optional can be rounding as

Code: Select all

gx = math.floor (x)
gy = math.floor (y)
So position x=3.14, y=6.98 can have collision with tile gx=3, gy=6, but not with gx=3, gy=7

The block object can have a list of tiles:

Code: Select all

blockObj1 = {
	x=3, y=6,
	tiles = {0,0, -- in the grid the position will be {x=3, y=6} for this tile
	1,0, 0,1, 1,1}, -- the block has 2x2 shape now
	w=2, h=2, -- the dimension of this block for rough_not_collision_detection, 
	-- that compares just AABB (minus one)
}
https://love2d.org/wiki/BoundingBox.lua

Code: Select all

function isRoughBBCollision (block1, block2) -- rough block-to-block collision (not tested)
	if block2.x > block1.x+block1.w-1 or block2.y > block1.y+block1.h-1
	or block1.x > block2.x+block2.w-1 or block1.y > block2.y+block2.h-1 then 
		return false -- collision is not possible
	end
	return true -- may be collision, need for tile-by-tile comparing
end

Code: Select all

function isFineBBCollision (block1, block2) -- fine block-to-block collision (not tested)
	local x1, y1, tiles1 = block1.x, block1.y, block1.tiles
	local x2, y2, tiles2 = block2.x, block2.y, block2.tiles
	for index1 = 1, #tiles1 -1, 2 do
		for index2 = 1, #tiles2-1, 2 do
			if x1+tiles1[index1] == x2+tiles2[index2] and
			   y1+tiles1[index1+1] == y2+tiles2[index2+1] then
			   	-- the tiles have collision, optionally the position of it.
				return true, x1+tiles1[index1], y1+tiles1[index1+1]
			end
		end
	end
	return false
end
The object-to-grid collision detection is almost same:

Code: Select all

function isBGCollision (grid, block) -- block-to-grid collision (not tested)
	local x, y, tiles = block.x, block.y, block.tiles
	for index = 1, #tiles -1, 2 do
		local gx, gy = x+tiles[index], y+tiles[index+1] 
		if isGridCollision (grid, gx, gy, 1) then -- collision on value = 1
			return true, gx, gy
		end
	end
	return false
end
So the cValue is the name of the layer? Like the collidable layer? Sorry I'm just trying to understand but thanks for helping!
User avatar
darkfrei
Party member
Posts: 1216
Joined: Sat Feb 08, 2020 11:09 pm

Re: How could I implement tilemap collisions for my platformer?

Post by darkfrei »

MaxGamz wrote: Fri Apr 28, 2023 11:15 am So the cValue is the name of the layer? Like the collidable layer? Sorry I'm just trying to understand but thanks for helping!
It's just the collision layer value, the collision can be just be the 1 as wall or floor:

Code: Select all

if grid[gy][gx] == 1 then
	return true -- collision
end
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
MaxGamz
Party member
Posts: 107
Joined: Fri Oct 28, 2022 3:09 am

Re: How could I implement tilemap collisions for my platformer?

Post by MaxGamz »

darkfrei wrote: Fri Apr 28, 2023 11:21 am
MaxGamz wrote: Fri Apr 28, 2023 11:15 am So the cValue is the name of the layer? Like the collidable layer? Sorry I'm just trying to understand but thanks for helping!
It's just the collision layer value, the collision can be just be the 1 as wall or floor:

Code: Select all

if grid[gy][gx] == 1 then
	return true -- collision
end
Does this method also work for STI implementation?
User avatar
darkfrei
Party member
Posts: 1216
Joined: Sat Feb 08, 2020 11:09 pm

Re: How could I implement tilemap collisions for my platformer?

Post by darkfrei »

MaxGamz wrote: Fri Apr 28, 2023 12:18 pm Does this method also work for STI implementation?
Yes, you can change it as you will, but I've never used STI and cannot help you with it.
But this method works here: viewtopic.php?p=246641#p246641
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
Post Reply

Who is online

Users browsing this forum: No registered users and 6 guests