[bump] how to detect side collision

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
maxtrautwein
Prole
Posts: 13
Joined: Sun Apr 14, 2019 5:14 pm

[bump] how to detect side collision

Post by maxtrautwein » Sat Aug 24, 2019 4:50 pm

Hi, I use bump.lua, the collision library, and i have a small issue :

I can detect when a collision is happening on the down side of my cube, the print is working ->

Code: Select all

player.x, player.y, cols, len = world:move(player, player.x, player.y + player.vy)
for i = 1, len do
    	local col = cols[i]
    	if col.normal.y == -1 then
    		print('DOWN')
    	end	
    end	
But i can't detect any other collision like on the left or right side of my cube, the print is not working ->

Code: Select all

player.x, player.y, cols, len = world:move(player, player.x, player.y + player.vy)
for i = 1, len do
    	local col = cols[i]
    	if col.normal.x == -1 then
    		print('LEFT')
    	end	
    end		
I am new to bump so I am sure it's easy...
If you have any ideas it could help me a lot! thanks!!

User avatar
pgimeno
Party member
Posts: 1905
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

Re: [bump] how to detect side collision

Post by pgimeno » Sat Aug 24, 2019 5:33 pm

What value do you get for col.normal.x when you expected a collision?

maxtrautwein
Prole
Posts: 13
Joined: Sun Apr 14, 2019 5:14 pm

Re: [bump] how to detect side collision

Post by maxtrautwein » Sun Aug 25, 2019 1:08 am

everytime i expected a collision the value of col.normal.x stay at 0

User avatar
pgimeno
Party member
Posts: 1905
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

Re: [bump] how to detect side collision

Post by pgimeno » Sun Aug 25, 2019 11:13 am

Works for me. Can you post your project? Or at least a trimmed down version that still shows the problem, but that we can run.

Here's my test (it doesn't require LÖVE, it can be run with the command-line LuaJIT):

Code: Select all

local bump = require 'bump'
local world = bump.newWorld()

local A = {name = 'A'}
local B = {name = 'B'}
local C = {name = 'B'}
local x, y = 32, 0
world:add(A, x, y, 32, 32)
world:add(B, 0, 0, 32, 32)
world:add(C, 32, 32, 32, 32)

local function moveA(xd, yd)
  local xf, yf, coll, len = world:move(A, xd, yd)
  print(string.format("A is now at %.17g, %.17g", xf, yf))
  for i = 1, len do
    local normal = coll[i].normal
    print(string.format("Normal is %.17g, %.17g", normal.x, normal.y))
  end
  x = xf
  y = yf
end

moveA(x, y+1) -- collision down (negative y)
moveA(x-1, y) -- collision left (positive x)
--[[
Output:

A is now at 32, 0
Normal is 0, -1
A is now at 32, 0
Normal is 1, 0
--]]

maxtrautwein
Prole
Posts: 13
Joined: Sun Apr 14, 2019 5:14 pm

Re: [bump] how to detect side collision

Post by maxtrautwein » Sun Aug 25, 2019 11:32 am

Here is the entire code, sorry i don't know how to attach a file. You can focus on the 'playerf' functions. I don't know why but col.normal.y seems to work but col.normal.x doesn't work.

Code: Select all

 io.stdout:setvbuf('no')
love.graphics.setDefaultFilter("nearest")

local bump = require('bump')
local world = bump.newWorld()

-- listes fonctions --
local tween = {}
local transition = {}
local cubes = {liste={}}
local menu = {}
local playerf = {}
local game = {}
---
local gravity = 7
local gameScreen = 'game'

function setColor(r,g,b,a) return love.graphics.setColor((r or 255)/255, (g or 255)/255, (b or 255)/255, (a or 255)/255) end 

-- TWEEN --
function tween.quadratic(in_or_out,t,b,c,d)
	if in_or_out == 'in' then 
		local s = t/d
		return c*s*s + b
	elseif in_or_out == 'out' then
		local i = t/d
		return -c * i*(i-2) + b	  
    end	
end	
---

-- TRANSITION --
function transition.load()
	transition.alpha = 0
	transition.alphaMax = 1.2
	transition.vitesse = 4
	transition.state = 1
	transition.play = false
	transition.goal = nil
end	

function transition.to(goal_screen)
	transition.play = true 
	transition.goal = goal_screen
end		

function transition.update(dt)
	if transition.play == true then 
		if transition.state == 1 then 
			transition.alpha = transition.alpha + transition.vitesse*dt
			if transition.alpha > transition.alphaMax then 
				transition.state = 2
			end	
		elseif transition.state == 2 then 
				gameScreen = transition.goal	
				transition.alpha = transition.alpha - transition.vitesse*dt
			if transition.alpha <= 0 then 
				transition.state = 1
				transition.play = false
			end
		end	
	end	
end

function transition.draw()
	love.graphics.setColor(67/255,109/255,118/255,transition.alpha)
	love.graphics.rectangle('fill', 0, 0, largeurScreen, hauteurScreen)
	love.graphics.setColor(1,1,1)
end	
---

-- CUBES --
function cubes.add(x,y,w,h)
	local cube = {x=x,y=y,w=w,h=h}
	cubes.liste[#cubes.liste+1] = cube
	world:add(cube,x,y,w,h)
end 
 
function cubes.draw()
	for _,cube in ipairs(cubes.liste) do
		setColor()
    	love.graphics.rectangle("line", cube.x, cube.y, cube.w, cube.h)
    end
end
---

-- MENU --
function menu.load()
end

function menu.update(dt)
end

function menu.draw(dt)
end

function menu.keypressed(key)
end	
---

-- PLAYER --
function playerf.load()
	player = {x=120,y=100,vx=0,vy=0,w=30,h=30,acceleration=60,decceleration=50,max_speed=8,jump1=false,jump2=false,max_height=12.5}
	world:add(player,player.x,player.y,player.w,player.h)
end	

function playerf.resetVelocity()
	for i = 1, len do
    	local col = cols[i]
    	if col.normal.y == -1 or col.normal.y == 1 then 
    		player.vy = 0
    		print('up and down collision detection ok') 
    	end	
    	if col.normal.y == -1 then
    		player.jump1 = false
    		player.jump2 = false
    	end	

    	if col.normal.x == -1 or col.normal.x == 1 then 
    		print('SIDE COLLISION OK') -- doesn't print anything 
    	end	
    end	
end

function playerf.gravity(dt)
	player.vy = player.vy + tween.quadratic('in',0.01,1,100,100)*dt*50
	player.x, player.y, cols, len = world:move(player, player.x, player.y + player.vy)
   	playerf.resetVelocity()
end	

function playerf.movements(dt)
	if love.keyboard.isDown('right') then 
		player.vx = player.vx + tween.quadratic('in',1,3,3,3)*dt*60 
		if player.vx > player.max_speed then 
			player.vx = player.max_speed
		end
	elseif love.keyboard.isDown('left') then 
		player.vx = player.vx - tween.quadratic('in',1,3,3,3)*dt*60
		if player.vx < -player.max_speed then 
			player.vx = -player.max_speed
		end	
	else 
		if player.vx > 0 then 
			player.vx = player.vx - (player.decceleration*dt)	
			if player.vx < 0 then 
				player.vx = 0
			end	
		elseif player.vx < 0 then 
			player.vx = player.vx + (player.decceleration*dt)	
			if player.vx > 0 then 
				player.vx = 0
			end	
		end	
	end	

	player.x, player.y, cols, len = world:move(player, player.x+(player.vx or 0), player.y+(player.vy or 0))
end

function playerf.update(dt)
	playerf.movements(dt)
	playerf.gravity(dt)
end	

function playerf.draw()
	love.graphics.rectangle('fill',player.x,player.y,player.w,player.h)

	love.graphics.print(player.vx)
end	

function playerf.keypressed(key)
	if key == 'up' then 
		if player.jump1 == false then 
			player.jump1 = true 		
			player.vy = -player.max_height
		elseif player.jump1 == true and player.jump2 == false then 
			player.jump2 = true 		
			player.vy = -player.max_height/1.5
		end	
	end	
end	
---

-- GAME --
function game.load()
	playerf.load()
	cubes.add(100,400,600,30)
	cubes.add(0,0,100,600)
	cubes.add(200,50,200,100)
end

function game.update(dt)
	playerf.update(dt)
end

function game.draw()
	cubes.draw()
	playerf.draw()
end

function game.keypressed(key)
	playerf.keypressed(key)
end	
---

-- MAIN FUNCTIONS --
function love.load()
	love.window.setMode(810, 600)
    largeurScreen, hauteurScreen = love.window.getMode()
    love.graphics.setBackgroundColor(0,0,0)

    game.load()
    transition.load()
end

function love.update(dt)
	if gameScreen == 'game' then 
    	game.update(dt)
    else 
    	menu.update(dt)	
    end

    transition.update(dt)
end

function love.draw()
	if gameScreen == 'game' then 
    	game.draw()
    else 
    	menu.draw()	
    end

    transition.draw()
end	

function love.keypressed(key)
	if gameScreen == 'game' then 
		game.keypressed(key)
	else  
		menu.keypressed(key)
	end
end
---
I want to detect side collisions in order to create wall jumping effects.

MrFariator
Party member
Posts: 117
Joined: Wed Oct 05, 2016 11:53 am

Re: [bump] how to detect side collision

Post by MrFariator » Sun Aug 25, 2019 1:21 pm

For wall-jumps, in my game I simply use bump's queryRect method: When player presses the jump button while in mid-air, query a couple pixels wide rectangle on either side of the player's collision box for tiles (remember to use an appropriate filter), check if there is a surface the player can jump off of (simply check if len > 0), and act accordingly. This works well enough for a simple quick implementation, unless you want to integrate the wall detection into the regular physics upates for objects.

User avatar
pgimeno
Party member
Posts: 1905
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

Re: [bump] how to detect side collision

Post by pgimeno » Sun Aug 25, 2019 2:42 pm

maxtrautwein wrote:
Sun Aug 25, 2019 11:32 am
Here is the entire code, sorry i don't know how to attach a file.
You can't attach files in "quick reply" mode. You have to press press "Full editor and preview" to get the interface that allows you to submit attachments. Anyway, the code you posted helped because it's self-contained. Thanks.

maxtrautwein wrote:
Sun Aug 25, 2019 11:32 am
You can focus on the 'playerf' functions. I don't know why but col.normal.y seems to work but col.normal.x doesn't work.
The collision you expect is happening, but in playerf.movements(), and you don't detect it there.

In a certain sense, Bump doesn't report collisions that are already resolved. More specifically, when the objects are touching but one of the objects is not moving towards the other, you don't get a collision. So, the resolution in playerf.movements() detects the contact and places the object touching the wall, but there's no code that checks the resulting collision at that point. When execution reaches playerf.gravity(), the wall and the player are already touching and you don't get the collision for it.

To avoid a problem such as the one you're having, you should call world:move() only once per frame, and check collisions there.

Post Reply

Who is online

Users browsing this forum: No registered users and 8 guests