Page 1 of 1

How could I implement tilemap collisions for my platformer?

Posted: Fri Apr 28, 2023 3:26 am
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.

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

Posted: Fri Apr 28, 2023 7:18 am
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

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

Posted: Fri Apr 28, 2023 11:15 am
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!

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

Posted: Fri Apr 28, 2023 11:21 am
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

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

Posted: Fri Apr 28, 2023 12:18 pm
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?

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

Posted: Fri Apr 28, 2023 1:17 pm
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