In our game we need to remove object when it stops but there are many objects in the screen at the same time? So how can we solve this problem?
Thanks for your time.
In our game we need to remove object when it stops but there are many objects in the screen at the same time? So how can we solve this problem?
Thanks for your time.
Assuming you’re using physics, and assuming ‘stopped means moving at a rate nearly zero’:
(May contain typos)
local function onEnterFrame( self, event ) local vx,vy = self:getLinearVelocity() if( ( vx^2 + vy^2 ) \<= self.minRate2 ) then Runtime:removeEventListener( "enterFrame", self ) display.remove(self) end end local function myDummyObjectBuilder( x, y, vx, vy, minRate ) local obj = display.newCirle( x, y, 10 ) physics.addBody( obj ) obj:setLinearVelocity( vx, vy ) obj.minRate2 = minRate ^ 2 obj.linearDamping = 1 obj.enterFrame = onEnterFrame Runtime:addEventListener( "enterFrame", obj ) return obj end myDummyObjectBuilder( 200, 10, 100, 0, 1 ) myDummyObjectBuilder( 200, 20, 90, 0, 1 ) myDummyObjectBuilder( 200, 30, -50, 0, 5 )
Warning, in games with physics, stopped generally ~= 0 velocity.
i.e. Treat a very small velocity as stopped or your stopped algorithm/detector will fail.
**CORRECTED TYPOS IN CODE ABOVE**
Thank you that was really helpful!
Hi Riku,
the method of roaming impose as much Runtime/enterFrame as objects in your screen.
With 500 objects, that can be lag.
I prefer to have only one Runtime listener that check into a table, but there are a slightly time lag due to the time for the " for loop " to browse the big table.
When the speed is under the minRate, I remove the object from the table first, and from display next.
local tab={} tab.enterFrame=function(self,event) if #self==0 then Runtime:removeEventListener( "enterFrame", self ) self.enterFrame=nil return end for k=#self,1,-1 do local o=self[k] local vx,vy = o:getLinearVelocity() if( ( vx\*vx + vy\*vy ) \<= o.minRate2 ) then table.remove( self,k ) display.remove(o) end end end Runtime:addEventListener( "enterFrame", tab ) -- local function myDummyObjectBuilder( x, y, vx, vy, minRate ) local obj = display.newCircle( x, y, 10 ) physics.addBody( obj ) obj:setLinearVelocity( vx, vy ) obj.minRate2 = minRate\*minRate obj.linearDamping = 1 tab[1+#tab]=obj return obj end physics.setGravity(0,0) for k=1,500 do local x,y,vx,vy=math.random(w),math.random(h),math.random(-100,100),math.random(-100,100) myDummyObjectBuilder(x,y,vx,vy,1) end
Lag & enterFrame Listeners
@yvandotet, Do you have metrics to support the idea that it will ‘lag’ with 500 objects?
I ask because I disagree and have tested this before. 500 enterFrame listeners will not cause lag. The listener call mechanism is quite efficient. In fact, in testing on devices I’ve had as many as 10,000 active enterFrame listeners w/ no
FPS impact.
I would expect this to be a little lower however with the call to getLinearVelocity() but I think that call will dominate the equation.
Code Efficiency
The primary cause of lag is usually expensive calculations which is why, in this case, I used the squared-length trick, thus avoiding the costly square root calculation for true length.
Nonethless
Having said all that, @riku.kukkonen what @yvandotet says is right in that a single event listener will cumulatively be faster than multiple.
Using one over using multiple is a design decision usually based on:
I would say, go with a single one if all you’re doing is this work. However, if your enterFrame listener starts to get bigger and bigger to contain unique work per object (work that doesn’t apply to all objects), then you’d be better off with listeners attached to the objects themselves.
Thanks for the help.
I test the both method on the simulator and on my device (huawei y6), and it’s often 3 times longer if I give a runtime to each objects.
With 1000 balls, it’s like 25 seconds vs 8 seconds.
Code Efficiency
The primary cause of lag is usually expensive calculations which is why, in this case, I used the squared-length trick, thus avoiding the costly square root calculation for true length.
Nice, it’s a programmer’s trick that I don’t know. Thanks lol.
@riku.kukonen
After posting I realized we could make this much faster by skipping the getLinearVelocity() call entirely.
Instead measure change in position from frame to frame.
The following is a combination of this idea and @yvandotet’s single listener approach.
local minDist = 1 local tab={} tab.enterFrame=function(self,event) if #self==0 then Runtime:removeEventListener( "enterFrame", self ) self.enterFrame=nil return end for k=#self,1,-1 do local o=self[k] local dx = o.x - o.lx local dy = o.y - o.ly o.lx = o.x o.ly = o.y if( ( dx\*dx + dy\*dy ) \<= o.minDist ) then table.remove( self,k ) display.remove(o) end end end Runtime:addEventListener( "enterFrame", tab ) -- local function myDummyObjectBuilder( x, y, vx, vy, minRate ) local obj = display.newCircle( x, y, 10 ) physics.addBody( obj ) obj:setLinearVelocity( vx, vy ) obj.minDist = minDist obj.lx = obj.x obj.ly = obj.y obj.linearDamping = 1 tab[#tab+1]=obj return obj end physics.setGravity(0,0) for k=1,500 do local x,y,vx,vy=math.random(w),math.random(h),math.random(-100,100),math.random(-100,100) myDummyObjectBuilder(x,y,vx,vy,1) end
The biggest performance gains come with precalculation always. Never do something per frame when you can do it once!
interesting topic, very helpful. good stuff.
any idea the best way to check if a physics object is stationary when standing on a moving platform, such as an elevator ?
so the platform (floor object) is always moving about the screen (up,down, left, right…), and the check is to determine if the physics object (player) is stationary or moving about (walking, jumping upon … etc) relative to the moving platform.
cheers in advance for any advice.
Hi. You should probably start a new post and refer back to this one if you think it is relevant.
Adding a new question to an existing/idle thread is seen as ‘thread hijacking’ and won’t get you good answers.
no worries, I sorted it
Assuming you’re using physics, and assuming ‘stopped means moving at a rate nearly zero’:
(May contain typos)
local function onEnterFrame( self, event ) local vx,vy = self:getLinearVelocity() if( ( vx^2 + vy^2 ) \<= self.minRate2 ) then Runtime:removeEventListener( "enterFrame", self ) display.remove(self) end end local function myDummyObjectBuilder( x, y, vx, vy, minRate ) local obj = display.newCirle( x, y, 10 ) physics.addBody( obj ) obj:setLinearVelocity( vx, vy ) obj.minRate2 = minRate ^ 2 obj.linearDamping = 1 obj.enterFrame = onEnterFrame Runtime:addEventListener( "enterFrame", obj ) return obj end myDummyObjectBuilder( 200, 10, 100, 0, 1 ) myDummyObjectBuilder( 200, 20, 90, 0, 1 ) myDummyObjectBuilder( 200, 30, -50, 0, 5 )
Warning, in games with physics, stopped generally ~= 0 velocity.
i.e. Treat a very small velocity as stopped or your stopped algorithm/detector will fail.
**CORRECTED TYPOS IN CODE ABOVE**
Thank you that was really helpful!
Hi Riku,
the method of roaming impose as much Runtime/enterFrame as objects in your screen.
With 500 objects, that can be lag.
I prefer to have only one Runtime listener that check into a table, but there are a slightly time lag due to the time for the " for loop " to browse the big table.
When the speed is under the minRate, I remove the object from the table first, and from display next.
local tab={} tab.enterFrame=function(self,event) if #self==0 then Runtime:removeEventListener( "enterFrame", self ) self.enterFrame=nil return end for k=#self,1,-1 do local o=self[k] local vx,vy = o:getLinearVelocity() if( ( vx\*vx + vy\*vy ) \<= o.minRate2 ) then table.remove( self,k ) display.remove(o) end end end Runtime:addEventListener( "enterFrame", tab ) -- local function myDummyObjectBuilder( x, y, vx, vy, minRate ) local obj = display.newCircle( x, y, 10 ) physics.addBody( obj ) obj:setLinearVelocity( vx, vy ) obj.minRate2 = minRate\*minRate obj.linearDamping = 1 tab[1+#tab]=obj return obj end physics.setGravity(0,0) for k=1,500 do local x,y,vx,vy=math.random(w),math.random(h),math.random(-100,100),math.random(-100,100) myDummyObjectBuilder(x,y,vx,vy,1) end
Lag & enterFrame Listeners
@yvandotet, Do you have metrics to support the idea that it will ‘lag’ with 500 objects?
I ask because I disagree and have tested this before. 500 enterFrame listeners will not cause lag. The listener call mechanism is quite efficient. In fact, in testing on devices I’ve had as many as 10,000 active enterFrame listeners w/ no
FPS impact.
I would expect this to be a little lower however with the call to getLinearVelocity() but I think that call will dominate the equation.
Code Efficiency
The primary cause of lag is usually expensive calculations which is why, in this case, I used the squared-length trick, thus avoiding the costly square root calculation for true length.
Nonethless
Having said all that, @riku.kukkonen what @yvandotet says is right in that a single event listener will cumulatively be faster than multiple.
Using one over using multiple is a design decision usually based on:
I would say, go with a single one if all you’re doing is this work. However, if your enterFrame listener starts to get bigger and bigger to contain unique work per object (work that doesn’t apply to all objects), then you’d be better off with listeners attached to the objects themselves.