Slight imprecision in spawning physics objects (in paused physics and belonging to the same group)

Hi all, I have a game where my character falls from the top of the screen, goes through a passage at the bottom, the screen scrolls up (i.e. my “objects” group is shifted upwards) and a new level is revealed (i.e. new physics objects are spawned offscreen right before the scroll begins).  The “objects” group is a top level group and contains all the physics objects that form the level.  Now, each time I play the same level, the objects are either “slightly misplaced” or “correctly placed”.  I spawn the objects in a paused physics environment and re-start physics when the scrolling up is done.  Any idea what might be causing this imprecision?

The reason why this is important is that, when I design levels, there is an intended “collapse effect” that I want to achieve and object should therefore fall down always in the very same way.  Slight imprecision lead to a 2 very different fall patterns.

Any suggestion?  Maybe a rounding issue in Corona’s engine that can be addressed by rounding the coordinates where the objects are placed?  

Thanks in advance for helping.

PS: Excuse my spelling mistakes I really do miss my dear old Microsoft spell checker (learn Apple, oh please learn the basics before you pull up stuff like Siri!!!)

We would need to see some of you code in order to help.  We have no idea of how exactly you are creating your display objects and placing them on the screen. 

Hi JonPM, let me try and reproduce the issue away from my (modularised and quite long) code.  It will take some time.

And here it is.  Run in simulator.  Press the R button once and see the correct impact.  Press it again and you will see again the correct impact.  Press the R button repeatedly, quickly and see how the two balls are not in same relative position as before and bounce in a different way.

local widget = require("widget") local \_W = display.contentWidth local \_H = display.contentHeight local objects local mytimer local cleanUp local restart local start function cleanUp() timer.cancel(mytimer) mytimer = nil display.remove(objects) objects = nil end function restart() cleanUp() start() end function start() objects = display.newGroup() local physics = require("physics") physics.start() physics:setGravity(0, 30) physics.pause() local restartButton = widget.newButton{ id = "restart", width=200, height=200, label = "R", fontSize = 200, onRelease = restart, } restartButton:setReferencePoint( display.CenterReferencePoint ) restartButton.x = \_W - 105 restartButton.y = 105 local function drawBall(x, y) local ball = display.newCircle(x,y,25) local options = { bounce = 0.2, friction = 0.01, } physics.addBody(ball, "dynamic", options) return ball end local ball1 = drawBall(\_W/2 + 24, \_H - 50) local ball2 = drawBall(\_W/2, \_H - 300) ball2.gravityScale = 0 objects:insert(ball1) objects:insert(ball2) local function shoot() physics.start() ball1:applyLinearImpulse(0,-100, 0, -25) end mytimer = timer.performWithDelay(1000, shoot) end start()

The code is posted.  Although it is a different graphical representation of the problem I had originally posted, it is a very accurate description of what is happening with my code.

Anyone has have any insight?

I’m not able to replicate the issue.   I’ve reloaded many times, both quickly and slowly, and the positions and trajectories are the same each time.  

@JonPM.  On my simulator the relative position of the two balls changes.  Refresh slowly: one ball hits the other sideways.  Refresh frantically/quickly and one ball hits the other almost underneath (and I can clearly see that at the time of “launch” one ball skips in a different position).  I am on a Mac daly build 1219.  Really strange behaviour…

Hmm, still not seeing it.  I am using build 1232.   Maybe try a newer build?

  1. still there. top ball skips to the right and bottom ball skips to the left. point of impact changes significantly. You will need to hit the R button really quickly with mouse clicks but it is still there for me. I need to go now. I have not got a clue why you are not seeing it and I am: maybe somebody from Corona team can shed some light?

I have just tested that code and if tapping quickly I do get some inconsistent behaviour. IE quicker than the 1000 in the timer delay.

as I dont personally use widgets I created a quick basic button to see if there was a difference and the results were odd. The bottom ball flies off to the left, sometimes to the right. Different behaviour to using the widget button. Looks like some pipeline with touch event perhaps? Or Could just be simulator framerate issue?

Just stick this at the bottom.

local button=display.newRect(100,100,100,100)
button:addEventListener(“touch”,restart)

Hi Paolo,

I tried your code and I don’t see any issue either. The R button can only be pressed once (I can’t click it “repeatedly” as you say).  The same two balls appear in the same place every time, with the firing ball striking the stationary ball just below and right, so that the stationary one flies off the the left at about -60 degrees from top 0. The same exact thing happens if I click R once, twice, or 20 times in a sequence. I’m using build 1225 for this, but since others have been testing with various builds, I don’t think there’s a build # factor here.

Sincerely,

Brent Sorrentino

Hi Brent, so you are saying that you cannot press the R more than once before the ball flies off? I am confused as to why that is. Each time you press the scene should reset (at least that is what happens on my simulator and devices). It is also confusing that two of us see inconsistent behaviour, while two more people don’t see it. That makes it even odder. Nonetheless I have observed this in each physics game that I am working on. I usually don’t care but my latest effort rely on procedurally generated elvels where bits and pieces need to be placed perfectly in position. Would it help if I posted a video (on Monday at this point?

Hi Paolo,

This could be tricky to figure out, but I think a few general recommendations would be:

  1. Try to instantiate (declare) the physics library just once, at the top, instead of repeatedly each time the scenario restarts.

  2. Try to avoid pausing and restarting the physics engine so often. Try to get the objects placed (created) while the physics engine is running, not while it’s paused. If necessary, create the bodies and immediately make them inactive if you don’t want them to interact with anything until a certain point.

I’m not positive that this will change anything, but it’s worth a try. :slight_smile:

Brent

I have tried Brent’s suggestions one by one and only one of them solves the issue; namely creating objects in an inactive state and activate them only when I need them to start interacting.  This also solves the issue that BeatsnBobs observed.  Below is my new code: if you comment out every line where you see a isBodyActive statement and press the R button before the ball is shot up, then you can clearly see that the two balls skip in two different alternative positions (to the left and to the right) each time you press the button.  I am not sure why that is, I can only report here something else that I have observed and might (or might not) be related: when a collision takes place, the x and y coordinates of the same static object are sometimes different by a few decimals (I am not going to reproduce that here as I would need to make one ball static, but I have observed the behaviour in a game of mine).  So maybe (just a theory here) there is a small approximation issue in the engine (or it might even be Box2D) and it has something to do with where the objects are initially placed.  Or maybe (second theory) a time lag between the time when corona instructs Box2D and when Box2D does results in Box2D computing a new position for active objects (I do not believe too much in this second theory because the positioning imprecision I observe does not go in the direction of the gravity)?

In any event, try and document this behaviour in the addBody APIs, that would be useful for people relying on dynamic and/or procedural generation of levels (i.e. reliant on automatically calculating precise positions of objects).

local physics = require("physics") -- \*\*\*\* NEW \*\*\*\* physics.start() -- \*\*\*\* NEW \*\*\*\* physics:setGravity(0, 30) -- \*\*\*\* NEW \*\*\*\* local widget = require("widget") local \_W = display.contentWidth local \_H = display.contentHeight local objects local mytimer local cleanUp local restart local start function cleanUp() timer.cancel(mytimer) mytimer = nil display.remove(objects) objects = nil end function restart() cleanUp() start() end function start() objects = display.newGroup() --local physics = require("physics") -- \*\*\*\* NEW \*\*\*\* --physics.start() -- \*\*\*\* NEW \*\*\*\* --physics:setGravity(0, 30) -- \*\*\*\* NEW \*\*\*\* --physics.pause() -- \*\*\*\* NEW \*\*\*\* local restartButton = widget.newButton{ id = "restart", width=200, height=200, label = "R", fontSize = 200, onRelease = restart, } restartButton:setReferencePoint( display.CenterReferencePoint ) restartButton.x = \_W - 105 restartButton.y = 105 local function drawBall(x, y) local ball = display.newCircle(x,y,25) local options = { bounce = 0.2, friction = 0.01, } physics.addBody(ball, "dynamic", options) return ball end -- Alternative button -- \*\*\*\* NEW \*\*\*\* local button=display.newRect(100,100,100,100) -- \*\*\*\* NEW \*\*\*\* objects:insert(button) -- \*\*\*\* NEW \*\*\*\* button:addEventListener("touch",restart) -- \*\*\*\* NEW \*\*\*\* local ball1 = drawBall(\_W/2 + 24, \_H - 50) ball1.isBodyActive = false -- \*\*\*\* NEW \*\*\*\* local ball2 = drawBall(\_W/2, \_H - 300) ball2.gravityScale = 0 ball2.isBodyActive = false -- \*\*\*\* NEW \*\*\*\* objects:insert(ball1) objects:insert(ball2) local function shoot() --physics.start() ball1.isBodyActive = true -- \*\*\*\* NEW \*\*\*\* ball2.isBodyActive = true -- \*\*\*\* NEW \*\*\*\* ball1:applyLinearImpulse(0,-100, 0, -25) end mytimer = timer.performWithDelay(1000, shoot) end start()

We would need to see some of you code in order to help.  We have no idea of how exactly you are creating your display objects and placing them on the screen. 

Hi JonPM, let me try and reproduce the issue away from my (modularised and quite long) code.  It will take some time.

And here it is.  Run in simulator.  Press the R button once and see the correct impact.  Press it again and you will see again the correct impact.  Press the R button repeatedly, quickly and see how the two balls are not in same relative position as before and bounce in a different way.

local widget = require("widget") local \_W = display.contentWidth local \_H = display.contentHeight local objects local mytimer local cleanUp local restart local start function cleanUp() timer.cancel(mytimer) mytimer = nil display.remove(objects) objects = nil end function restart() cleanUp() start() end function start() objects = display.newGroup() local physics = require("physics") physics.start() physics:setGravity(0, 30) physics.pause() local restartButton = widget.newButton{ id = "restart", width=200, height=200, label = "R", fontSize = 200, onRelease = restart, } restartButton:setReferencePoint( display.CenterReferencePoint ) restartButton.x = \_W - 105 restartButton.y = 105 local function drawBall(x, y) local ball = display.newCircle(x,y,25) local options = { bounce = 0.2, friction = 0.01, } physics.addBody(ball, "dynamic", options) return ball end local ball1 = drawBall(\_W/2 + 24, \_H - 50) local ball2 = drawBall(\_W/2, \_H - 300) ball2.gravityScale = 0 objects:insert(ball1) objects:insert(ball2) local function shoot() physics.start() ball1:applyLinearImpulse(0,-100, 0, -25) end mytimer = timer.performWithDelay(1000, shoot) end start()

The code is posted.  Although it is a different graphical representation of the problem I had originally posted, it is a very accurate description of what is happening with my code.

Anyone has have any insight?

I’m not able to replicate the issue.   I’ve reloaded many times, both quickly and slowly, and the positions and trajectories are the same each time.