Page 1 of 1

Collision between a player and a wall

Posted: Fri Jul 12, 2013 5:33 am
by carbajosa
Collision test.love
Collision Trial
(1.72 KiB) Downloaded 234 times
Okay, so first of all (as my very first post here in the forums) I wanted to say that LOVE2D is really awesome and the easiest to learn out of all the engines and libraries that I have tested (And I believe that I will be using this for a veeery veeeeeeeeery long time)

Now about my question. I know that this has been asked so much here in the forums. I have searched and found some really good examples about COLLISIONS and stuffs. I have been coding this for about 2 days and I can't seem to get it or solve it on my own. I wanted to create a little game which the player can move in all four directions (up, down, left, right) and the game is divided into stages. Each stage has its own .png picture file as the map (and a transparent bounding boxes for collision. each box is 32x32 big and also the player). The camera view is on the top of the player, by the way. It's zelda-like view.

But here's where my problem is, I can't solve the collision detection between the player and the wall! I have seen many examples but I just don't get it. Could someone explain it to me? I have plenty of test codes that I have created and all is not working as it should:

Code: Select all

function check_touch(a, coll_type)
	--CHECK COLLISION BETWEEN PLAYER AND GROUND
	if ( player.getHeight() + player.getY() ) == a.getY() then
		player.isTouchingFloor = true
	else
		player.isTouchingFloor = false
	end

	--CHECK COLLISION BETWEEN PLAYER AND CEILING
	if player.getHeight() == ( a.getHeight() + a.getY() ) then
		player.isTouchingCeiling = true
	else
		player.isTouchingCeiling = false
	end

	--CHECK COLLISION BETWEEN PLAYER AND WALL
	if ( player.getWidth() + player.getX() ) == a.getX and
		player.getX() == ( a.getWidth() + a.getX() ) then

		player.isTouchingWall = true
	else
		player.isTouchingWall = false
	end

end


function colliding(a, b)
	if (a.height + a.y) == b.y or
		a.height == (b.height + b.y) or
	   (a.width + a.x) == b.x or
	    a.width == (b.width + b.x) then return true
		else return false
	end
end

function colliding(a, b)
	
    for grid_y, value  in  ipairs(tiletable) do
        for grid_x, tile  in  ipairs(value) do
            if tile == 1  and  a + tileW  >  (grid_x - 1) * b.width and 
                b + b.height  >  (grid_y - 1) * b.height and 
                a  <  (grid_x - 1) * tileW + tileW and 
                y  <  (grid_y - 1) * tileH + tileH 

                then col = true end
        end
    end

    return col
end


function colliding (a, b)

	for grid_y, v in ipairs(stage_level) do

		for grid_x, tile in ipairs(v) do

				if tile == 1 then
					if
						(a.height + a.y) == (b.height * grid_y) or
						a.y == (b.height * grid_y) or
						(a.width + a.x) == 1+(b.x * grid_x) or
						a.width == (b.width + b.x) * grid_x
						then return true
						else return false
					end
				end
		end --END INNER LOOP
	end --END OUTER LOOP

end

function check_box_coll(x, y)
	local col=false

    for grid_y, v  in  ipairs(stage_level) do
        for grid_x, tile  in  ipairs(v) do
            if tile == 1  and  x + stage_level.width  >  (grid_x - 1) * stage_level.width and 
                y + stage_level.height  >  (grid_y - 1) * stage_level.height and 
                x  <  (grid_x - 1) * stage_level.width + stage_level.width and 
                y  <  (grid_y - 1) * stage_level.height + stage_level.height

                then col = true end
        end
    end
end



function check_passable_tile(a, b, dir)
local coll = false

	if dir == "down" then
		for grid_y, index in ipairs(b) do
			for grid_x, tile in ipairs(index) do
				if tile == 1 then
					if (a.height + a.y) == ((grid_y - 1) * (b.height * 6))  then
						col = true
						return col
					end
				end
			end
		end
	end

	if dir == "up" then
		for grid_y, index in ipairs(stage_level) do
			for grid_x, value in ipairs(index) do
				if value == 1 and a.y == (grid_y * b.height) + (b.height * grid_y)  then
					return true
				end
			end
		end
	end

	if dir == "left" then
		for grid_y, index in ipairs(stage_level) do
			for grid_x, value in ipairs(index) do
				if value == 1 and a.x == (grid_x * b.width) + (b.width * grid_x) then
					return true
				end
			end
		end
	end

	if dir == "right" then
		for grid_y, index in ipairs(stage_level) do
			for grid_x, value in ipairs(index) do
				if value == 1 and (a.width + a.x) == (grid_x * b.width) + (b.width * 4) then
					return true
				end
			end
		end
	end
 
end
'a' is the player and 'b' is the stage_level or the walls. my map is inside an array called stage_level and it looks something like:

Code: Select all

map = {
{1, 1, 1, 1},
{1, 0, 0, 1},
{1, 1, 1, 1}
}

1 => box / impassable tile
0 => empty / player can walk on it
But I can't implement it to my game. Could someone please help me? explain how they work? explain why my code doesn;t work? I cannot provide a .love file at the moment because I kinda messed up my test project for solving the collision detection.

Thank you :)

EDIT

I created a love file without any collision to it. How do I add collisions between a player and wall? I tried many things, followed many tutorials but I can't seem to get it right.

Re: Collision between a player and a wall

Posted: Fri Jul 12, 2013 4:44 pm
by davisdude
First of all I would like to tell you that this is a very good start to a game!

Note that to be zelda like the movement would have to be tile-based. But that is irrelevant right now.
I got rid of player-controls and replaced it with player.update() just to make your game more efficient (and since it was sort of repetitive to have and entire file just for movement.
I also changed screen_x and screen_y to screen_w and screen_h just to avoid confusion for myself. :P
Made player movement based on dt to make sure that the frame rate of your game doesn't suffer later on.
That being said, the move-speed had to be increased as well, so I changed that too.
I changed movement to be a bit more easy to apply stopping to.
I added stage.dims to hold the x and y of all the blocks that weren't 0.

I left one thing for you, though:
Say for example, that you are going up, towards the top wall. Once you hit it, try going left. You can't.
Your mission, if you choose to accept it, is to add code to prevent this from happening. davisdude out. :cool:

Re: Collision between a player and a wall

Posted: Sat Jul 13, 2013 12:38 am
by carbajosa
Ah, thank you for responding to my help and sorry for alot of classes LOL. I was experimenting how LUA works because I'm new to LUA Programming.

about this part

Code: Select all

	for i = 1, #stage.dims do
		if next_x + player.width >= stage.dims[i][1] and
		next_x <= stage.dims[i][1] + 32 and
		next_y + player.height >= stage.dims[i][2] and
		next_y <= stage.dims[i][2] + 32 then
			player.x_velocity = 0
			player.y_velocity = 0
		end
	end

Code: Select all

	next_y + player.height >= stage.dims[i][2] and
		next_y <= stage.dims[i][2] + 32 then[i][2]
Is this line calculating if the player is colliding the top and bottom side of the wall? i kinda don't get how the second column is the top or bottom part. Oh and what's the Love2D console for? Sorry for being slow lol. I am used to visual c++ where you can debug and watch each line of the code to see what values are being passed to each other.

Re: Collision between a player and a wall

Posted: Sat Jul 13, 2013 1:05 am
by davisdude
The console just makes it easier to test if things work. It is much easier to read messages printed to the console (using print) rather than reading things flashing very quickly (using love.graphics.print())

Code: Select all

next_y + player.height >= stage.dims[i][2] and
That deals with the top part, since you are taking the player's next y, adding the height, then checking if it is greater than the tiles y.

Code: Select all

next_y <= stage.dims[i][2] + 32 then[i][2]
Opposite of top

Re: Collision between a player and a wall

Posted: Sat Jul 13, 2013 1:38 am
by carbajosa
Ohh I see... I think I got it! For now, I'm going to try and memorize the logic behind all this. Then I'm going to solve the sticky collision to make the player (sort-of) slide on the wall when moving in diagonal.

Thank you again, davisdude. :)

Re: Collision between a player and a wall

Posted: Sat Jul 13, 2013 1:54 am
by davisdude
No problem! :)
If you're ever having trouble with a mathematical concept, try sketching it out on a piece of paper or something. That at least helps me, anyway. :P

Re: Collision between a player and a wall

Posted: Sat Jul 13, 2013 2:32 am
by carbajosa
Yup! I tried doing it on a paper first then made gridlines and some paper cut-outs for a 2x2 tile and a 1x1 player.

I solved the the logic about collisions and it's correct in the paper. but when it comes to actually coding it, I failed. :awesome:
Doesn't work correctly like it was written on my papers.

Re: Collision between a player and a wall

Posted: Sat Jul 13, 2013 2:41 am
by davisdude
That happens to me a lot. It's usually just because my logic was off on the paper, or I forgot to move a bit of code in, or something like that. :P

Re: Collision between a player and a wall

Posted: Sat Jul 13, 2013 7:30 am
by carbajosa
So I've been reviewing the logic for quite some time now and rewritten the collision part then wrapped it as a function so that the player could slide when hugging the wall pressing diagonal keys. I couldn't think of a better way to do this lol.
Collision test with diagonal.love
Mission Complete!
(1.91 KiB) Downloaded 467 times

Re: Collision between a player and a wall

Posted: Sat Jul 13, 2013 12:22 pm
by davisdude
Good job agent carbajosa. :cool: