Can anyone help me with simple Tile Collisons?

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
User avatar
Deltise
Prole
Posts: 26
Joined: Sat May 18, 2013 7:23 pm

Can anyone help me with simple Tile Collisons?

Post 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:
Attachments
TestGame.zip
Here's the Game
(54.87 KiB) Downloaded 112 times
Joemag
Prole
Posts: 24
Joined: Sun Apr 14, 2013 5:42 pm

Re: Can anyone help me with simple Tile Collisons?

Post 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
User avatar
Deltise
Prole
Posts: 26
Joined: Sat May 18, 2013 7:23 pm

Re: Can anyone help me with simple Tile Collisons?

Post 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?
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Can anyone help me with simple Tile Collisons?

Post 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
}
Help us help you: attach a .love.
User avatar
Deltise
Prole
Posts: 26
Joined: Sat May 18, 2013 7:23 pm

Re: Can anyone help me with simple Tile Collisons?

Post 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
User avatar
MadByte
Party member
Posts: 533
Joined: Fri May 03, 2013 6:42 pm
Location: Braunschweig, Germany

Re: Can anyone help me with simple Tile Collisons?

Post 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 ? :/
Joemag
Prole
Posts: 24
Joined: Sun Apr 14, 2013 5:42 pm

Re: Can anyone help me with simple Tile Collisons?

Post 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.
User avatar
MadByte
Party member
Posts: 533
Joined: Fri May 03, 2013 6:42 pm
Location: Braunschweig, Germany

Re: Can anyone help me with simple Tile Collisons?

Post 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
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 5 guests