Detecting multiple physics objects "at rest" (not moving)?

Greetings all,

I’m curious if anybody has tackled (solved?) the issue of detecting if multiple physics bodies have come to a basic resting point. This would be, for example, in a game like (*sigh*) Angry Birds…no… Ghosts vs. Monsters! where the “structure” is collapsing, and the user must wait until all objects have essentially finished falling/colliding/interacting before they can launch the next ghost.

The most obvious solution seems to be a Runtime listener checking if the bodies are “awake” or not ("body.isAwake"). My initial testing indicates that this works properly; it basically detects if the objects are sufficiently “at rest” as expected. Heck, why not let Box2D do the tedious work? But I wonder if this approach might cause other problems. Perhaps Box2D is TOO sensitive and won’t put an object to sleep until it’s literally not moving at all. Then you might have an object sliding down a gradual slope at a visually undetectable speed, and the user is sitting there wondering why they can’t launch the next ghost. I suppose setting the friction on all objects to a suitable level would ensure that they do, in fact, come to a resting point and don’t slide around indefinitely.

Another approach I considered was a Runtime listener that constantly loops over the objects involved (say, 20 pieces of a tower, added to a table when the tower begins to crumble). I could loop over each object in the table and check their motion using "body:getLinearVelocity()" and "body.angularVelocity". If either velocity was above a certain threshold (very small) then the simulation would continue checking until otherwise. I just worry that this approach would cause considerable overhead processing (especially with the looping), thus causing potential slow-down if there were several (20+) objects involved.

Any other thoughts or suggestions? Specific advice from anybody who has experimented with this?

Thanks in advance!
Brent Sorrentino
Ignis Design
[import]uid: 9747 topic_id: 18713 reply_id: 318713[/import]

i had a ball that I did not want to let it come to a rest.

So I used some Corona code to make it not sleep - see below code

local function createBall()
local theBall = display.newCircle( 170, 25, 6 )
theBall:setFillColor(128,128,128)
physics.addBody( theBall, “dynamic”, { density=3.0, friction=0, bounce=0.3, radius = 5 } )
theBall.myName = “theBall”
–true = object CAN eventually goto sleep
theBall.isSleepingAllowed = false
end
notice the “isSleepingAllowed” method ? this is where you do it.
hope this helps
[import]uid: 11094 topic_id: 18713 reply_id: 71946[/import]

Hey Brent!

I would go with the second solution that Naomi is mentioning aswell.
Have been using this aswell and haven’t found any problems. (I wanted the user to be able to shoot a ball once it’s not moving anymore (or at least very slowly)).
body.isAwake was giving odd results, since it took way too long until the body was really sleeping…
body:getLinearVelocity() will give you way more control - and maybe you don’t have to check it every frame, but every second or so.

Good luck with that,
Chris [import]uid: 13097 topic_id: 18713 reply_id: 71949[/import]

Hey, Brent @IgnisDesign, towards the end of each game session in my game, I trigger a function that checks the motion of all applicable physics objects using body:getLinearVelocity(). This function is called with a runtime listener with enterFrame (with my game, fps is 30).

The function loops through all objects, and when all objects return (vx > 5) or (vx < -5) or (vy > 5) or (vy < -5), the function triggers game over screen. (I also provide “End Now” button, which triggers the very same game over screen, for users who don’t want to wait for all pieces to stop moving.)

It appears to be working fine for me even when there are well over a couple dozen objects to loop through. I haven’t seen performance issue associated with this at all. (But then, in my game, by the time this enterFrame listener is called, nothing much else is happening on screen that demands more CPU.)

I hope this helps.

Naomi

EDIT: I mis-spoke slightly about the velocity. It’s odd how a thought pops up on my head when I’m doing unrelated thing (like re-filling my coffee). Anyhow, what I meant is, in my code, when any objects return the velocity of (vx > 5) or (vx < -5) or (vy > 5) or (vy < -5), then the object is considered still moving. When after the function loops through all applicable objects and finds there are no more objects still in motion, it triggers the game over function.
[import]uid: 67217 topic_id: 18713 reply_id: 71917[/import]

Hi Naomi,

Thanks for the testing report/advice. I’m going to use a similar function (looping) in my game, since you and @xxxFanta both confirm it seems to work fine, and it’s more customizable versus Box2D’s “isAwake” test.

One other suggestion for you: have you added a “break” command in your loop to improve efficiency? If you’re looping through 50 objects to determine if any of them are still moving, there’s no reason to continue the loop after it encounters the first occurrence. I assume you’re just looping through a table incrementally, as follows (a little hack-code here, but you can see the point):

objects = {} --table containing all objects to check  
-- Runtime listener open  
for i=1,#objects do  
 local thisOne = objects[i]  
 if (...) then --if "thisOne" is moving, according to your math check:  
 break --stop the loop!  
 end  
end  
-- Runtime listener close  

This way, if you encounter a moving object at increment #3, it just stops right there and the remaining 47 objects go unchecked, which should improve performance. :slight_smile:

Brent
[import]uid: 9747 topic_id: 18713 reply_id: 72221[/import]

(I guess you are asking Naomi, since I had to check every object and couldn’t break the loop ^^)

If you run into problems, use timers instead enterFrame Listener (though I have problems cancelling those…).

Also I would recommend using pythagorean theorem to check how fast the objects move. :wink: [import]uid: 13097 topic_id: 18713 reply_id: 72224[/import]

Hey, Brent @IgnisDesign, thank you for the advice. It’s a great advice. I know of “break” command but somehow I haven’t thought of using it in my code. When I heard of it not so long ago, I thought it was super useful and cool command. My game currently do not seem to have any performance issue, even with tons of physics objects moving around (and even on 2G device with iOS 3.1.3, which makes me really happy). But yes, I totally agree, I should include the break command.

Naomi [import]uid: 67217 topic_id: 18713 reply_id: 72230[/import]