Box2d, collisions and how it fails sometimes.

Before I begin, I will let you know I have read extensively box2d manual, I utilize every API in Corona for physics and I have looked at every post regarding this issue, including "resolutions to most common physics issues"

If you are lazy, I created video at bottom, and also what I need :)

I've read the following

general information about bodies

http://developer.anscamobile.com/content/game-edition-physics-bodies#physics.addBody

more detailed information

http://developer.anscamobile.com/content/game-edition-box2d-physics-engine

note for box2d users

http://developer.anscamobile.com/content/game-edition-box2d-physics-engine#A_note_for_current_Box2D_users

corona sdk collision detection

http://developer.anscamobile.com/content/game-edition-collision-detection

The problem I face is I think A common one, but seems to be one of those issues I have not seen one person solve completely, or at least to a point of where its acceptable.

HEre is the scenario, I'm not providing code at this point, as the issue is pretty easy to describe.

The problem is this:

Lets say I have a long rectangle, which is "static".

Now, I spawn a ball on top and let it fall onto the object. The ball will bounce off the rectangle and will not even get anywhere close to going partially through the object.

Now, if I have that same rectangle in place and it's welded to a couple of anchor points and the rectangle is "dynamic" and the rectangle is NOT moving AND I let the ball fall onto the rectangle the ball will partially penetrate the rectangle.

What gets me is how Box2d treats a dynamic object that isn't moving.. it's just ODD.

That's scenario 1, now we have scenario 2:

Same rectangle, but now it's a draggable. I could use it to drag the rectangle around to bounce the ball around have fun etc.

The ball would sometimes penetrate the rectangle. Sometimes the ball would just go through it, and it was like the rectangle wasn't even considered in the first place. It's like sometimes the box2d engine forgets what it's doing and just allows the ball to pass through.

So I said ok, I'll go to battle on this thing! Here is what I tried

physics.setPositionIterations(128)
physics.setVelocityIterations(128)
physics.setDrawMode( "normal")
physics.setScale(60 )

body.angularDamping
body.linearDamping
body.angularVelocity
body:setLinearVelocity
body.isBullet = true
body.isBodyActive
body.isAwake
body.isSleepingAllowed
body:getLinearVelocity( )
body:resetMassData( )

I've played with those numbers, and on iterations I've done 0 through 5000! It seems above 128 to 200 the effectiveness fades with a sort of heavy performance hit.

The scale, I've been up and down from 0 to a 1000, it doesn't seem to matter. I've tried combinations of things. This has been going on for at least 2 months.

So then, iNSERTCODE on twitter reached out to me and pointed me to this:

http://www.gamedev.net/blog/1350/entry-2253939-intelligent-2d-collision-and-pixel-perfect-precision/

This is a pretty interesting read. The problem I have is this is I think for cocos2d or something, which me being a coding noob, I can't decipher it. I get the logic, but the code usually tells more than what's being said. I was wondering, anyone want to take a stab at this and see if this would be applicable for Corona SDK and translate it to Corona SDK.

I think this would be helpful to everyone who has this problem, right now It's the #1 thing preventing me from releasing. Character going through walls and off screen is a big big bug, which I can't release it that way. So basically, I'm spinning my wheels trying to figure this out.

If someone really wants sample code, I could whip something up. But since this is more of an advanced topic......ok I changed my mind lol. Here is some sample code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
        local physics = require "physics"
 
        --physics.setGravity(0, 80)  -- set this down at the bottom!!
        physics.setPositionIterations(128)
        physics.setVelocityIterations(128)    
        physics.setDrawMode( "hybrid")
        physics.setScale(30)
        physics.start(true)
        
        --shorcut variables to call the content width and height
        local _W = display.contentWidth
        local _H  = display.contentHeight       
        
 
 
local ball = display.newCircle (_W/2 -30, _H/2-300, 11)
physics.addBody( ball, { density=.01, friction=.50, bounce=0.01, radius=11} )
ball.linearDamping = 0
ball.isBullet = true
ball:setFillColor (30,144,255)
ball.alpha = 1
 
 
        
        local Lrect = display.newRect (3,20, 20, _H -20)
physics.addBody( Lrect, "static")
Lrect.alpha = 0
 
local Rrect = display.newRect (747,20, 20, _H-18)
physics.addBody( Rrect, "static")
Rrect.alpha = 0
 
local Trect = display.newRect (_W/2 -385,0, _W+10, 20)
physics.addBody( Trect, "static")
Trect.alpha = 0
 
local Brect = display.newRect (_W/2 -400,1005, _W, 20)
physics.addBody( Brect, "static")
Brect.alpha = 0
 
local platform = display.newRect (_W/2,_H/2,200,20)
physics.addBody( platform, "static")
platform.isFixedRotation = true
platform.alpha = 1
 
 
local ground = display.newRect (0, _H/2+200,800,20)
ground.isFixedRotation = true
physics.addBody(ground, "static")
 
local function dragBody( event )
        local body = event.target
        local phase = event.phase
        local stage = display.getCurrentStage()
 
        if "began" == phase then
                stage:setFocus( body, event.id )
                body.isFocus = true
                                --Change body to dynamic while we are moving the maze around
                event.target.bodyType = "dynamic"
 
                -- Create a temporary touch joint and store it in the object for later reference
                body.tempJoint = physics.newJoint( "touch", body, event.x, event.y )
 
        elseif body.isFocus then
                if "moved" == phase then
                
                        -- Update the joint to track the touch
                        body.tempJoint:setTarget( event.x, event.y )
 
                elseif "ended" == phase or "cancelled" == phase then
                        stage:setFocus( body, nil )
                        body.isFocus = false
                        event.target:setLinearVelocity( 0, 0 )
                event.target.angularVelocity = 0
                                
                                --After the event ends, change body back to static. 
                                --event.target.bodyType = "static"
 
                        -- Remove the joint when the touch ends                 
                        body.tempJoint:removeSelf()
                        
                end
        end
 
        -- Stop further propagation of touch event
        return true
end
 
 
platform:addEventListener( "touch", dragBody )  

In config.lua are you using 30 or 60 fps?

Jay

I have the same problem in my game when you drag basket fast:

http://itunes.apple.com/us/app/eggz-saver/id480545649?l=pl&ls=1&mt=8

(game is free right now).

It happens on Corona simulator, Xcode simulator and on device with 30 and 60fps.

Corona use quite old Box2D implementation.

I think Corona can only update things as quickly as 60 times per second, so could you be moving your objects faster than that? In other words, you whip one object past another in less than 1/60 of a second and that's how it is able to slip past.

Yes? No? Not sure if that's technically possible but it sounds good to me. :)

Could you test it programmatically so you can see if the movement of one object at a certain speed is what triggers the problem?

Just program that test case in the video to have the bar smack that ball every second for a hundred times or so, every tenth second for anther hundred, every twentieth second, etc. Whenit switches have it print the speed to the terminal and just watch and see if the problem happens at the same speed threshold each time.

Something to think about?

Jay

Major issue is implementation of Box2D dependent on fps. Time based implementation should be available for fast moving object.

@Jay

on my config it's 60fps, but doesn't matter.

Build settings are based on ipad.

Basically, have to do some time stepping offset to get it right, I think?

Hmmmm....grrr.

I could just be blowing smoke, because I haven't been at a very low level since the "olden days" when I was doing assembly language game programming. I can remember chasing bugs that resulted from moving objects too fast -- before the screen even had a chance to refresh it would be somewhere else and so didn't look like it was even there.

Not sure if that type of thing could be happening in your case, but creating test case to discard or highlight that possibility might be worth the time.

Especially if you're at the point where you're just throwing things at it to see what happens. :)

Jay

The problem with the "too fast" theory is WHY would it happen at a lower velocity, and happen at a higher velocity.

The problem I have is my whole world moves as a whole, with a lot of interactive stuff that goes on. That's the most I can say about it :)

For demonstrative purposes, the video shows what I need it to. But perhaps I can show another one that shows some different examples and post the code here.

What I find interesting is it happens MORE after something moves fast and then interacts with a slower object. It's almost like the physics engine forgets what the hell is going on.

I'm exploring alternate methods to control the speed, but I rather not :)

-ng

I have made some progress tonight.

So there are a few things I tried that GREATLY reduced my problems. I can't say that it eliminated, but I can say over the last several tests, I only had one incident of pass through vs several pass throughs on each play through.

So, what I did is I dumped scale down to 1 and started messing with damping, Here it's commented out with a few things and the velocity I had tied to another function. I basically provided it as something for others to mess with. :)

1
2
3
4
5
6
7
8
9
10
11
        physics.setPositionIterations(128)
        physics.setVelocityIterations(128) --   
        physics.setDrawMode( "normal")
        physics.setScale(5 )
        --
local ball = display.newCircle (_W/2 -30, _H/2-300, 15)
physics.addBody( ball, { density=.1, friction=.50, bounce=0.01, radius=15} )
--ball.angularDamping = 40
ball.linearDamping = 0 --.50
--ball.angularVelocity = 10
ball.isBullet = true

Well, I used to get pass through objects within seconds, even after all the position iterations and damping etc etc etc.

What does it take to basically 99,99% cure this problem with pass through objects.

A LOT OF DAMN TIME THATS WHAT.

You REALLY REALLY REALLY REALLY REALLY REALLY REALLY REALL (100 more reallys in there) mess with things. I mean TEAR THINGS APART!!!!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
        local physics = require "physics"
        physics.setPositionIterations(128)
        physics.setVelocityIterations(128) --   
        physics.setDrawMode( "normal")
        physics.setScale(7 )
 
 
        --for some of the bodies in my game
        myBody.angularDamping = 1 
 
       --Some other options that may or may not work for you
--myBody.linearDamping = 25
--myBody.angularVelocity = 10

Hi,

first of all thanks a lot for this blog. I am racking my brain with similar problem.

I'm using: Corona SDK on MacOSX

Steps to reproduce:

In Simple Pool game try to strike the cue at the edge of any other balls it
simply passes through it.
----------------------------------------------------------------
Similar behavior with games involving pucks or short cylindrical(round)
objects.

-take two pucks and strike one puck using function cueShot()
on the edge of another puck in a board game.
-when you hit the edge of another puck with speed, the collision is not
detected and the first puck simply passes through the edge of the second
puck.

--------------------------------------------------------------

(Tried to set the bullet property but its not working)

@girishvinr

Challenge accepted. Ok so I'm going to go ahead and get the pool project and take a look.

Let's see what I come up with

First I am going to focus on this, which usually will solve some other problems:

#1 In Simple Pool game try to strike the cue at the edge of any other balls it
simply passes through it.

I'll take a crack at this, then post the code here ( I won't post the entire project, just the lines or chunks of code modified.

-Keep an eye on this thread :)

ng

Ok, I was just taking a look at simple pool and simple pool plus, but I am not sure what you might be talking to in regards to

#1 In Simple Pool game try to strike the cue at the edge of any other balls it
simply passes through it.

1
2
3
        physics.setPositionIterations(128)
        physics.setVelocityIterations(128) --   
        physics.setDrawMode( "normal")

Hi,
Thanks for the quick reply.

When I pull the "cue" back, I don't have a choice of a "side" it's just a circle target that allows me to pull back. Could you shed some more light on what you are after?

-> When you pull the "cue" back, aim at the edge of the any other ball.
-> Use maximum speed of the cue.
-> When you take the shot, you'll see that the cue simply passes through the targeted ball.
-> The "hybrid" mode also shows that the collision is detected but the target ball remains at its place.

Ideally the cue should hit the other ball at the edge and they both should divert at an angle.
(Might I suggest that you run the iPad version of the Game so that it'll be easy to observe the collision)

physics.setPositionIterations(128)
physics.setVelocityIterations(128)

is not solving my problem completely. I might be missing something.

I have a board game similar to the pool game where I am using Pucks instead of the object balls in the pool game. I have a "striker" and a number of "coins" (both pucks). I want the user to be able to take an angular shot at the coin with the striker. However the collisions are not detected when the striker hits the coin on its circumference.
Interestingly the collision is detected if the striker is aiming at the center of the coin. The collision is not detected when the striker aims at the edge of the coin.

I found similar bugs in the Corona's sample apps.
Let me know if the scenario is clear to you or not, also if you'd like me to send you the part of the code of my project.

i have the same problem, when i hit the cueball with full speed and aim at the edge of the any other ball, it doesnt collide, anyone found a solution?

physics.setPositionIterations(128)
physics.setVelocityIterations(128)

doesnt work for me either.

views:2792 update:2012/2/8 8:46:10
corona forums © 2003-2011