Page 1 of 1

Can anyone help me with simple Tile Collisons?

Posted: Sat Jun 08, 2013 2:52 pm
by Deltise
I have no idea how to approach this problem, except trying to assign certain tiles to be collideable and other tiles as not, I've seen many solutions but found them difficult to integrate into my code without breaking my brain. My code uses ASCII maps to create it's levels, and the Arrow Keys to move the player, as of now there are no collisions, and the player is free to float around whimsically. Can anyone please aid in helping me with code to create tile collisions for the darker walls around the level, and after that I could probably figure out the rest for other tiles.

(Oh yeah, I also don't have camera scrolling yet, so much of the map will be off of the 300 x 300 window, I'll mess with scaling later and cameras later)

Image

The game has a rather simple main menu, with 'esc' allowing you to return to the main menu from the game.
The zip is below. Thanks ahead of time for your help. :awesome:

Re: Can anyone help me with simple Tile Collisons?

Posted: Sat Jun 08, 2013 4:23 pm
by Joemag
Before you change the position of the player you should save the new position in an other variable:

Code: Select all

function playerMove(dt)
	local newx, newy = player.x, player.y

	if love.keyboard.isDown("right") then
		newx = newx + player.speed * dt
	end
	
	if love.keyboard.isDown("left") then
		newx = newx - player.speed * dt
	end

	if love.keyboard.isDown("up") then
		newy = newy - player.speed * dt
	end
	
	if love.keyboard.isDown("down") then
		newy = newy + player.speed * dt
	end
end
Next check if the player can be at the new position.
This returns the block which is at the new position of the left top corner:

Code: Select all

TileTable[ math.floor( newx / TileW ) + 1 ][ math.floor( newy / TileH ) + 1 ]
You should check all four corners of the player and change the x and y positions separately:

Code: Select all

player.height = 19
player.width = 19
collideTiles = {
	b = true,
	x = true
}
function collision(newx, newy)
	if collideTiles[ TileTable[ math.floor( newx / TileW ) + 1 ][ math.floor( newy / TileH ) + 1 ] ] or
	  collideTiles[ TileTable[ math.floor( (newx + player.width) / TileW ) + 1 ][ math.floor( newy / TileH ) + 1 ] ] or
	  collideTiles[ TileTable[ math.floor( newx / TileW ) + 1 ][ math.floor( (newy + player.height) / TileH ) + 1 ] ] o
	  collideTiles[TileTable[math.floor((newx + player.width) / TileW)+ 1][math.floor((newy + player.height)/TileH)+ 1]] then
		return true
	end
	return false
end
function playerMove(dt)
	local newx, newy = player.x, player.y
	if love.keyboard.isDown("right") then
		newx = newx + player.speed * dt
	end
	
	if love.keyboard.isDown("left") then
		newx = newx - player.speed * dt
	end

	if love.keyboard.isDown("up") then
		newy = newy - player.speed * dt
	end
	
	if love.keyboard.isDown("down") then
		newy = newy + player.speed * dt
	end
	if not collision(newx, player.y) then
		player.x = newx
	end
	if not collision(player.x, newy) then
		player.y = newy
	end
end

Re: Can anyone help me with simple Tile Collisons?

Posted: Sat Jun 08, 2013 9:28 pm
by Deltise
Joemag wrote:
This is all great, but quick question, which part of the code dictates which tiles the player can walk on, and which tiles the player runs into?

Re: Can anyone help me with simple Tile Collisons?

Posted: Sat Jun 08, 2013 9:33 pm
by Robin
Deltise wrote:This is all great, but quick question, which part of the code dictates which tiles the player can walk on, and which tiles the player runs into?

Code: Select all

collideTiles = {
   b = true,
   x = true
}

Re: Can anyone help me with simple Tile Collisons?

Posted: Sun Jun 09, 2013 3:05 am
by Deltise
Robin wrote:
Deltise wrote:This is all great, but quick question, which part of the code dictates which tiles the player can walk on, and which tiles the player runs into?

Code: Select all

collideTiles = {
   b = true,
   x = true
}
I feel a bit silly actually
Thank you

Re: Can anyone help me with simple Tile Collisons?

Posted: Sun Jun 09, 2013 10:06 am
by MadByte
I don't want to create a new topic for this:

I'm also trying to apply collision, but I use a img to load my map and got this so far:

Code: Select all

function player:move(dt)
	local newx, newy = player.x, player.y

	if left and not right then
		newx = newx - self.xVel * dt
		if not collision(newx, player.y) then
			player.x = newx
		end
		
	elseif right and not left then
		newx = newx + self.xVel * dt
		if not collision(newx + player.w, player.y) then
			player.x = newx
		end
	end
end

function collision( xval, yval )
	local x = math.floor( xval/tileSize )
	local y = math.floor( yval/tileSize )
	if x >= 0 and x < getWidth() and y >= 0 and y <= getHeight() then
		local r, g, b, a = mapdata:getPixel( x, y ) 
		if compare(  {r,g,b,a}, {255,0,0,255} ) then -- Collidable tile
			return true
		end
		return false
	end
end
It kinda works but I'm still struggling with the tile width & tile height a bit. the player still goes through the first tile in a raw.
Here you can test what I mean:
tileCollision.love
Any ideas ? :/

Re: Can anyone help me with simple Tile Collisons?

Posted: Sun Jun 09, 2013 6:10 pm
by Joemag
MadByte wrote:I don't want to create a new topic for this:

I'm also trying to apply collision, but I use a img to load my map and got this so far:

Code: Select all

function player:move(dt)
	local newx, newy = player.x, player.y

	if left and not right then
		newx = newx - self.xVel * dt
		if not collision(newx, player.y) then
			player.x = newx
		end
		
	elseif right and not left then
		newx = newx + self.xVel * dt
		if not collision(newx + player.w, player.y) then
			player.x = newx
		end
	end
end

function collision( xval, yval )
	local x = math.floor( xval/tileSize )
	local y = math.floor( yval/tileSize )
	if x >= 0 and x < getWidth() and y >= 0 and y <= getHeight() then
		local r, g, b, a = mapdata:getPixel( x, y ) 
		if compare(  {r,g,b,a}, {255,0,0,255} ) then -- Collidable tile
			return true
		end
		return false
	end
end
It kinda works but I'm still struggling with the tile width & tile height a bit. the player still goes through the first tile in a raw.
Here you can test what I mean:
tileCollision.love
Any ideas ? :/
When you go down, it checks only if the bottom-left corner of the player collides.

Code: Select all

collision(player.x, newy + player.h)
The same problem is in the other directions.
You have to check also the bottom-right corner. And a point between that, because the player is bigger than the tiles.

Re: Can anyone help me with simple Tile Collisons?

Posted: Sun Jun 09, 2013 6:27 pm
by MadByte
hm I didn't updated the post,
in the .love I included above I tried this :

Code: Select all

-- Move the player
	if left and not right then
		newx = newx - self.xVel * dt
		if not collision(newx, player.y) then
			player.x = newx
		end
	elseif right and not left then
		newx = newx + self.xVel * dt
		if not collision(newx + player.w, player.y) then
			player.x = newx
		end
	end

	
	if up and not down then
		newy = newy - self.xVel * dt
		 if not collision(player.x, newy) then
			player.y = newy
		end
	elseif down and not up then
		newy = self.y + self.xVel * dt
		if not collision(player.x, newy + player.h) then
			player.y = newy
		end
	end
But there still seems to be a problem with it.
Thanks for the reply!

edit:

Now I understand what you said! :D... it works now, thanks!
(bit ugly but ... yeah :/ )

Code: Select all

-- Move the player
	if left and not right then
		newx = newx - self.xVel * dt
		if not collision(newx, player.y) 
			and not collision( newx, player.y + player.h ) 
			and not collision( newx, player.y + (player.h / 2) ) then
			player.x = newx
		end
	elseif right and not left then
		newx = newx + self.xVel * dt
		if not collision(newx + player.w, player.y) 
			and not collision( newx + player.w, player.y + player.h ) 
			and not collision( newx + player.w, player.y + (player.h / 2) )  then
			player.x = newx
		end
	end

	
	if up and not down then
		newy = newy - self.xVel * dt
		 if not collision(player.x, newy) 
			 and not collision(player.x + player.w , newy) 
			 and not collision(player.x + (player.w / 2) , newy)  then
			player.y = newy
		end
	elseif down and not up then
		newy = self.y + self.xVel * dt
		if not collision(player.x, newy + player.h) 
			and not collision(player.x + player.w , newy + player.h) 
			and not collision(player.x + (player.w / 2) , newy + player.h) then
			player.y = newy
		end
	end