Physics Engine Runs In Background

Hello. Something I noticed was that the physics engine runs while your program is in the background but all of your other code doesnt. As you can imagine, this can cause problems for games that use the physics engine when the player exists the app while playing.

A solution to this is to use os.clock and the collide function. Since os.clock doesnt grow while your program is in the background, you can compare the values of the old os.clock and the current os.clock during collide since thats the only function I’ve found to be called while in the background.

You could set up a tiny ball in a tiny box somewhere in the physics so that that rate of collisons is highly increased to check if the program is in the background at a higher rate.

Is this intend? I’d like to hear your guys thoughts on this.

The only problem with that is the extra collisions that are constantly occurring. It might be better to have a pause button and call physics.pause() when it’s pressed. If someone doesn’t pause the game when they switch apps, then it’s their fault.

I messaged @Simeon not long ago about pausing the box2D timestep or just box2D altogether when Codea is paused, he was looking in to adding something to fix it so maybe we’ll see it in the next update.

Also, I found that the physics ran in my latest project WHILE the terrain was being generated. Weird. :stuck_out_tongue:

@dave1707 Do you think that the extra collisions would slow down the engine? The problem with making the player pause before leaving is that if they dont, they’ll get an ugly error code if they reopen and it will degrade there opinion of my app.

@Luatee Sounds promising.

@TheSolderKing Was that during start up?

@Goatboy76 If you have a lot of collisions happening now, then you probably don’t need to add the extra collisions. If you don’t have a lot of collisions, then adding a few more probably won’t matter. I guess you’ll have to try your suggestion and see how well it works. Let us know. But the best fix would be a change to Codea to let the program know it’s in the background.

@Goatboy76 Yes, this was during startup. Before the physics object had even rendered, or anything else for that matter.

So the problem with my idea is when theres multiple collisons events inbetween frames since you dont know how many there need to be resolved. You cant tell the difference in between there being just 23 collisions to resolve when its in the forground, and the app running in the background. I’ve got a few more tricks up my sleeve that I’ll try.

Information on when collide is called in relation to everything else would help.

@dave1707 I hope Codea is given that feature.

@TheSolderKing Thats odd.

@Goatboy76 Yes, though quite a bit of calculations were being done. I know because I would set the object to be at WIDTH/2, HEIGHT/2 and by the time everything rendered it would be at the bottom of the screen already.

My understanding (which doesn’t affect the problem and solution) isn’t that it’s running in the background. While you app is off it’s off. The issue is that when physics hits it’s next run it says last physics run was at timestamp x, it is now timestamp y and physics then processes enough steps to bridge the elapsed time.

This is it’s inbuilt mechanism to make physics run consistently regardless of framerate, but obviously backgrounding the app and returning is effectively one very long frame.

Another potential fix that could come from this would be to not allow physics to process a longer period than say .5 seconds in a cycle. So while background or anything else that stopped your game would then proceed with physics, it wouldn’t miss much. And if your game is running at lower than 2fps and then physics slowed down… I don’t see that as a big issue.

Also, while we are on this, what about being able to accelerate and slow down physics? This same processing bit of Box2d could be easily tweaked so I could say physics.speed(2) as in it runs at twice the clock speed or physics.speed(0.5) and it runs slow.

@spacemonkey @Goatboy76 The thing that needs to be done is to know when the app goes to the background. If that can be done then physics.pause() can be called which stops the physics engine. Once the app comes to the foreground, a button can be pressed to call physics.resume() which starts it without any physics jumps. So far I haven’t found any consistent way of knowing when the app goes to the background. Using collide works sometimes, but most of the time it thinks it’s in the background when it’s not. Using collide and a time stamp isn’t reliable.

@dave1707 I think the core of the problem with this solution is that there can be more then one collision event in between when draw is called. If there was only one event in-between draw being called, you’d keep a tally of how many collision events there have been and set that value back to zero at the start of every frame. If that value exceeds 1 then you know that the program is in the background.

We’d need to find something distinguishable about how the physics engine behaves in the background and in the foreground.

What if there was a scenario where something constantly needed a nudge to keep moving. If the program was in the background, the nudge wouldn’t be applied, would it? During collide you could check the stats of that body and compare them with what they should be in the program was in the foreground. I’ll try and test this out sometime soon.

@Goatboy76 I was playing with the collide function to see how many collisions can occur between draw cycles and I got about 54. So I’m not sure setting anything in draw() to try and determine that something doesn’t change will work.

You could write an addon that calls a lua function when the app goes into the background

@dave1707 I agree. We’d need something that could change in between collide calls.

@JakAttak Does one such add on exist? Illl look into making one.

@Goatboy76 Try this. I added this to one of my physics programs that had a lot of collisions. When I moved the program to the background and then brought it back, the physics engine was paused. Apparently things still run a little before it totally gets to the background because when it’s brought back to the foreground, it still jumps a little. But a least it was paused. You’ll have to add a screen tap to call physics.resume for it to continue. I’m not sure how well this works on other iPads. You might have to tweek the .3 value.

function collide(contact)
    if contact.state == BEGAN then
        if DeltaTime>.3 then
            physics.pause()
        end
    end
end

@Goatboy76 Forget the above routine. I did more testing on it. Apparently physics.pause() doesn’t execute when the physics engine is running in the background. It looks like it executes and pauses everything as soon as the program is brought back to the foreground. It just looked like it worked. If that’s the case, I don’t think a flag indicating the program is in the background will help any.

@dave1707 I don’t use physics.pause. As a part of my pause routine, I set all of my objects .active to false. So this way, the flag for the program entering the background could still work.

What if you had a circle that, every draw, was being set to +50 y linear velocity with gravity applied. Since its moving vs gravity, as soon as its y velocity is no longer being set to 50 (like when the program is in the background), its velo will change and start to fall. You also have a ball bouncing off two walls at a high pace to increase the rate and which collide is called. You check to see if the first balls velo is close to 50 and if its less, then the program is in the background. I should have a example of this posted soon.

@dave1707 you won’t have any luck getting this done inside of Codea using physics.pause as it will execute after box2D has moved the objects that frame meaning it’s not much use. If @Simeon could make it so box2D is paused as soon as the app is pushed in to the background, although I’m not sure how that works in Xcode.

I’m sure it’d be fairly easy to hook up a physics.(pause/resume) to the background function in Xcode, that way it would be executed while the frame is still running and box2D wouldn’t move further than that.

@Luatee @dave1707 I think this is a pretty reliable solution. These objects shouldn’t have any effect on any of your other physics objects unless they’re in catorgies 10 or 11. Its bundled up in a class to use conveniently.

Edit: You should change the senstivity based on the frame rate. The higher the frame rate the more sensitive it can be. Change the sensitivty by changing the subtract number in ProjectIsInBackground. The higher the number the less sensitive it is. After testing for a while this I’ve have yet to get any false alarms.

-- Background Detection2

function setup()
    inBackgroundDetector = InBackgroundDetector()  
    inBackgroundDetector:SetRectVeloToStartingVelo()
end

function draw()
    background(40, 40, 50)
    inBackgroundDetector:SetRectVeloToStartingVelo()
    inBackgroundDetector:draw()
end

function collide(contact)
    if inBackgroundDetector:ProjectIsInBackground() then 
        print("In background")
    else
        print("In forground")
    end
end

InBackgroundDetector = class()

function InBackgroundDetector:init(x)
    self.radius = 10
    self.p1 = vec2(WIDTH/2 - self.radius + 1,HEIGHT/2 - 20)
    self.p2 = vec2(WIDTH/2 + self.radius + 1,HEIGHT/2 - 20)
    self.p3 = vec2(WIDTH/2 - self.radius + 1,HEIGHT/2+ 20)
    self.p4 = vec2(WIDTH/2 + self.radius + 1,HEIGHT/2 + 20)
    
    -- bottom
    self.b = physics.body(EDGE,self.p1,
                               self.p2)
    self.b.mask = {11}
    self.b.categories = {11}
    -- right
    self.rw = physics.body(EDGE,self.p2,
                               self.p4)
    self.rw.mask = {11}
    self.rw.categories = {11}
    -- top
    self.t = physics.body(EDGE,self.p3,
                                self.p4)
    self.t.mask = {11}
    self.t.categories = {11}
    -- left
    self.l = physics.body(EDGE,self.p3,
                               self.p1)
    self.l.mask = {11}
    self.l.categories = {11}

    self.ball = physics.body(CIRCLE,self.radius)
    local ballPos = vec2(WIDTH/2,HEIGHT/2)
    self.ball.x = ballPos.x
    self.ball.y = ballPos.y
    self.ball.restitution = 1
    self.ball.gravityScale = 0
    self.ball.mask = {11}
    self.ball.categories = {11}
    self.ball.linearVelocity = vec2(0,400)

    
    self.w = 50
    self.h = 50
    self.rect = physics.body(POLYGON,vec2(self.w/2,self.h/2),vec2(-self.w/2,self.h/2),
                            vec2(-self.w/2,-self.h/2),vec2(self.w/2,-self.h/2))
    self.rect.gravityScale = 1
    self.rect.x = self.w/2
    self.rect.y = self.h/2
    self.rect.mask = {10}
    self.rectVelo = vec2(0,50)
end

function InBackgroundDetector:draw()
    pushStyle()
    stroke(255, 255, 255, 255)
    strokeWidth(2)
    line(self.p1.x,self.p1.y,self.p2.x,self.p2.y)
    line(self.p2.x,self.p2.y,self.p4.x,self.p4.y)
    line(self.p3.x,self.p3.y,self.p4.x,self.p4.y)
    line(self.p3.x,self.p3.y,self.p1.x,self.p1.y)
    popStyle()
    
    pushStyle()
    fill(255, 0, 0, 255)
    ellipse(self.ball.x,self.ball.y,self.radius*2)
    rectMode(CENTER)
    rect(self.rect.x,self.rect.y,self.w,self.h)
    popStyle()
end

function InBackgroundDetector:SetRectVeloToStartingVelo()
    self.rect.linearVelocity = self.rectVelo
end

function InBackgroundDetector:GetVelo()
    return self.rect.linearVelocity
end

function InBackgroundDetector:ProjectIsInBackground()
    local retBool = false
    if self.rect.linearVelocity.y < self.rectVelo.y - 60 then
        retBool = true
    end
    return retBool
end