## [SOLVED] adnzzzzZ windfield collision classes confusion

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
kuzika
Prole
Posts: 16
Joined: Tue Apr 21, 2020 3:58 pm

### [SOLVED] adnzzzzZ windfield collision classes confusion

pushstuff.png (85.33 KiB) Viewed 2914 times
Hi guys, I'm having some trouble understanding collision classes with a box2d physics library called windfield by adnzzzzZ.

The documentation says.
Capture collision events
Collision events can be captured inside the update function by calling the enter, exit or stay functions of a collider. In the example below, whenever the box collider enters contact with another collider of the Solid collision class it will get pushed to the right:

function love.update(dt)
...
if box:enter('Solid') then
box:applyLinearImpulse(1000, 0)
box:applyAngularImpulse(5000)
end
end

So basically what I want to do is switch animations to a pushing animation when the player is in contact with ObjectA pushable objects by switching the players state to "pushing" if the player collider is staying on contact with the box or pot of ObjectA class. I cant really seem to get the collision to check and when it does its only like for a mirco split second when I use the collider:enter("ObjectA") and it then skips to the walking state imedietly. Its a logical error so they syntax seems fine but the way i'm doing it must be wrong or something.

Firstly I set up a physics world called myWorld in main.lua line 4.

Code: Select all

wf = require("libs/windfield-master/windfield")
myWorld = wf.newWorld()

Second I declared some collision classes in object.lua line 2, the player is set up to ignore ObjectB type classes such as chairs but ObjectA type classes cannot overlap ObjectB such as a box can not be pushed over a chair. ObjectA class is what we want to check when we make contact and mostly if we are staying on this contact, this means the player.state should switch to "pushing".

Code: Select all

myWorld:addCollisionClass("ObjectA")

I defined the player collider in objects.lua line 36, its part of a large layer table because we are using "sti" simple tiled implementation to draw all instances on a special layer in between other layers that go over and under the player and instances.

Code: Select all

layer.player = {}
layer.player.collider =  myWorld:newCircleCollider(
player.x + player.width/2,
player.y + player.height/2,
player.width/3
)
layer.player.vx = 0
layer.player.vy = 0
layer.player.ox = player.width/2
layer.player.oy = player.height/1.5
layer.player.direction = "south"
layer.player.state = "standing"
layer.player.speed = 16*4
layer.player.collider:setFixedRotation(true)
layer.player.collider:setCollisionClass("Player") --player object ignores static objects
layer.player.collider:setObject(layer.player)

Then in a layer.update(dt, self) function in object.lua line 115, I update the player state which should change to "pushing" when I am staying in contact with "ObjectA". at least thats how I interpreted the documentation. It glitches with enter but sort of works anyway this is where I am not to clear and probably where the logical error is.

Code: Select all

  --control player state
if self.player.collider:stay("ObjectA") then
self.player.state = "pushing"
else
if self.player.vx == 0 and self.player.vy == 0 then
self.player.state = "standing"
else
self.player.state = "walking"
end
end

I have attached a full .love file with everything as it is up and running with windfield. There is a sprite sheet in the sprites folder called pushing_cycle.png, it is the animation that is supposed to switch to when the player is in contact with ObjectA. I am using LOVE 11.3 as of this post.
pushstuff.love
.love
Last edited by kuzika on Wed May 06, 2020 2:16 pm, edited 1 time in total.
"kuzika" literally means "to burry"
4vZEROv
Party member
Posts: 123
Joined: Wed Jan 02, 2019 8:44 pm

### Re: adnzzzzZ windfield collision classes confusion

When I tried the windfield library I believe I also had some problems with the stay function, maybe it's a bug ?

I also made a box2d wrapper if you want to try it out (https://github.com/4v0v/physics).
kuzika
Prole
Posts: 16
Joined: Tue Apr 21, 2020 3:58 pm

### Re: adnzzzzZ windfield collision classes confusion

4vZEROv wrote: Wed May 06, 2020 3:46 am When I tried the windfield library I believe I also had some problems with the stay function, maybe it's a bug ?

I also made a box2d wrapper if you want to try it out (https://github.com/4v0v/physics).
Great, I’ll implement your library and get back to you if there any problems. Thanks a lot.
-------------------------------------------------------------------------------------------------------------------------------------------------------------
EDIT:
@4vZEROv
Everything is working fine except the actual collision checking, I'm not sure how to implement this code with your library. objects.lua line 119. It seems there is no stay equivalent, I'm thinking I should use postSolve or something but maybe you could clear this up for me.

Code: Select all

  if self.player.collider:stay("ObjectA") then
self.player.state = "pushing"
else
if self.player.vx == 0 and self.player.vy == 0 then
self.player.state = "standing"
else
self.player.state = "walking"
end
end

The documentation says something like this from the 4v0v/Physics wiki
set...()
collider:setEnter(function(shape1, shape2, contact, inverted) end)
collider:setExit(function(shape1, shape2, contact, inverted) end)
collider:setPresolve(function(shape1, shape2, contact, inverted) end)
collider:setPostsolve(function(shape1, shape2, contact, inverted, ...) end)
shape1(Shape): the Shape of the current Collider.
shape2(Shape): the Shape of the other Collider.
contact(Contact): Contact
inverted(boolean): if true then the first love.physics shape returned by Contact:getNormal() and Contact:getPositions() correspond to shape2 and the second to shape1.
...: normal_impulse1, tangent_impulse1, normal_impulse2, tangent_impulse2 (see the Notes part).
shape1 and shape2 are NOT love.physics shapes, they are Shapes.

return : self
Attached is the .love file with your library implemented. I commented out the if statement in objects.lua line 119.
pushstuff2.love
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
SOLUTION:
pushstuff3.png (85.72 KiB) Viewed 2813 times
As I thought it was postSolve to get it to work like a stay would. So I changed the code from object.lua line 119 to this after checking out Demo2 from the 4v0v/Physics library.

Code: Select all

  --control player state
self.player.collider:setPostsolve(function(s1,s2)
if s2:getClass() == "ObjectA" then
self.player.state = "pushing"
end
end)
if self.player.vx == 0 and self.player.vy == 0 then
self.player.state = "standing"
else
self.player.state = "walking"
end

Here is the fixed .love incase anyone comes across a similar problem with trying to check collision with a box2d physics wrapper for love 11.3.
pushstuff3.love
Once again THANK YOU
Last edited by kuzika on Wed May 06, 2020 2:15 pm, edited 1 time in total.
"kuzika" literally means "to burry"
4vZEROv
Party member
Posts: 123
Joined: Wed Jan 02, 2019 8:44 pm

### Re: adnzzzzZ windfield collision classes confusion

Code: Select all


--outside layer.update
local player_is_pushing = false
layer.player.collider:setEnter(function(s1, s2, c, i)
if s2:getClass() == "ObjectA" then
player_is_pushing = true
end
end)

layer.player.collider:setExit(function(s1, s2, c, i)
if s2:getClass() == "ObjectA" then
player_is_pushing = false
end
end)

-- inside  layer.update
if self.player.vx == 0 and self.player.vy == 0 then
self.player.state = "standing"
elseif player_is_pushing then
self.player.state = "pushing"
else
self.player.state = "walking"
end

Something like that.
I made a wiki here : https://github.com/4v0v/physics/wiki if you didn't see it

The presolve / Postsolve event are called every frames where 2 colliders are in contact.
Presolve before the physic is applied, postsolve after.
Last edited by 4vZEROv on Wed May 06, 2020 2:24 pm, edited 1 time in total.
kuzika
Prole
Posts: 16
Joined: Tue Apr 21, 2020 3:58 pm

### Re: [SOLVED] adnzzzzZ windfield collision classes confusion

Hmmm, I think I prefer it with Postsolve since as you said it is called when 2 colliders are in contact and after the physics is applied.

Code: Select all

  --control player state
self.player.collider:setPostsolve(function(s1,s2)
if s2:getClass() == "ObjectA" then
self.player.state = "pushing"
end
end)
if self.player.vx == 0 and self.player.vy == 0 then
self.player.state = "standing"
else
self.player.state = "walking"
end

Still its good to know how it all works. Thanks to your awesome physics wrapper I can do some really complex collision checks. Thumbs up bro (or sis...).
"kuzika" literally means "to burry"
4vZEROv
Party member
Posts: 123
Joined: Wed Jan 02, 2019 8:44 pm

### Re: [SOLVED] adnzzzzZ windfield collision classes confusion

:setEnter/Exit/Postsolve/presolve must be called only when then collider is initialized.

Postsolve/Presolve are called once every frame, it's not a good idea to use it like a switch for your states.

Every callback function that you've setted is called inside 'myWorld:update(dt)'

Code: Select all

  if self.player.vx == 0 and self.player.vy == 0 then
self.player.state = "standing"
else
self.player.state = "walking"
end

override the comportement you've previoulsy setted.
kuzika
Prole
Posts: 16
Joined: Tue Apr 21, 2020 3:58 pm

### Re: [SOLVED] adnzzzzZ windfield collision classes confusion

pushstuff5.png (54.98 KiB) Viewed 2753 times
Thanks this is what worked for me.

player.lua 103

Code: Select all

  --outside update
function player_state()
p.player.collider:setEnter(function(s1,s2,c,i)
if s2:getClass() == "ObjectA" and
(p.player.vx > 0 or p.player.vy > 0)
then
p.player.state = "pushing"
end
end)
p.player.collider:setExit(function(s1,s2,c,i)
if s2:getClass() == "ObjectA" and
(p.player.vx > 0 or p.player.vy > 0)
then
p.player.state = "walking"
elseif p.player.vx == 0 and p.player.vy == 0 then
p.player.state = "standing"
end
end)
return p.player.state
end

player.lua 75

Code: Select all

--inside player draw function
local pose = sprites.stand_cycle
if player_state() == "pushing" then
pose = sprites.player_pushing
elseif player_state() == "walking" then
pose = sprites.player_walking
elseif player_state() == "standing" then
pose = sprites.player_standing
end

updated .love
pushstuff4.love
"kuzika" literally means "to burry"
4vZEROv
Party member
Posts: 123
Joined: Wed Jan 02, 2019 8:44 pm

### Re: [SOLVED] adnzzzzZ windfield collision classes confusion

Code: Select all

  local pushing = false
p.pushing = function()
p.player.collider:setEnter(function(s1,s2,c,i)
if s2:getClass() == "ObjectA" then
pushing = true
end
end)
p.player.collider:setExit(function(s1,s2,c,i)
if s2:getClass() == "ObjectA" then
pushing = false
end
end)
return pushing
end

Don't do that T_T

If you want to do the equivalent as :enter() :exit() :stay() you need to play with what is in the "world._collisions" table.
Also now that I see my code it look pretty bad. Maybe i'll try to implement those methods in the near future.
kuzika
Prole
Posts: 16
Joined: Tue Apr 21, 2020 3:58 pm

### Re: [SOLVED] adnzzzzZ windfield collision classes confusion

Is this better? I used myWorld instead of the player collider to check setEnter and setExit. I think this is what you meant right?

Code: Select all

function player_state()
myWorld:setEnter(function(s1,s2,c,i)
if s2:getClass() == "ObjectA" and
(p.player.vx > 0 or p.player.vy > 0)
then
p.player.state = "pushing"
end
end)
myWorld:setExit(function(s1,s2,c,i)
if s2:getClass() == "ObjectA" and
(p.player.vx > 0 or p.player.vy > 0)
then
p.player.state = "walking"
elseif p.player.vx == 0 and p.player.vy == 0 then
p.player.state = "standing"
end
end)
return p.player.state
end

Also now that I see my code it look pretty bad. Maybe i'll try to implement those methods in the near future.
Hey man, don't say that. I've been trying out a bunch of box2d physics wrappers like breezefield and windfield mainly and even just pure love.physics on its own but your lib is probably the easiest to understand and best of all the collision actually works perfect, as far as I'm concerned this might be the best physics wrapper I've come across so far. I know it might have some bugs only you understand but no need to try to force in other methods like push() stay() exit() since already those methods where buggy in those other libraries in the first place.

And once again thanks for helping me, I was on the verge of giving up entirely until I discovered this library. So stay encouraged o.k.
"kuzika" literally means "to burry"
4vZEROv
Party member
Posts: 123
Joined: Wed Jan 02, 2019 8:44 pm

### Re: [SOLVED] adnzzzzZ windfield collision classes confusion

Ahah my code being bad is a fact, doesn't mean it does the job wrong.

The problem you raised, if I understand correctly is that atm i forces you to write game logic at 2 separate places:
-inside love.update()
-inside physic_world:enter/exit

I've made this decision because it's the box2d way (https://love2d.org/wiki/World:setCallbacks) but I understant the need of a enter() function to put inside love.update().

The enter() function should make you able to to check if a collider collide with a specific class, a specific collider or specific shape. In my code I already register every collision (in the world._collisions table) but only with ids so i need to change so that I can check the shapes/class/colliders.

As for you code it's still not good, I know you want to keep game logic at only one place but you currently cant .

Code: Select all

function love.load()
world = Physics()

world:setEnter(function()
--code
end)

world:setExit(function()
--code
end)
end

function love.update(dt)
world:update(dt)
end

Is what you code should look like, you don't want to change the callback functions every time you call your 'player_state()' function.

### Who is online

Users browsing this forum: Google [Bot] and 33 guests