Detect if objects are inside the desired area

Just move Lines 123-131 up to Line 54… first routine inside the checking function. You want the game to check stability every 1 second, so that’s where it should happen.

You’ll also need to move line 98 (local Shapes = {}) somewhere above that check function (maybe even near the very top of your code) because you’ll now be referencing the “Shapes” table in the check function, thus you need its initial declaration somewhere above to prevent a “lookup error”.

Looks like you’re almost there, keep going! :slight_smile:
Brent
[import]uid: 9747 topic_id: 25055 reply_id: 104017[/import]

Hi again

Thank you… but I have a little problem, I get an error saying “no loop to break near ‘end’”, I know this error is caused because there is no loop inside the check function - do I need to move the loop for my Shapes table inside the check function somehow? - if I do so, the game isn’t working - either.

[lua]local function CheckFunction (event)

– This isn’t correct - right?
–[[ for i = 1, #Shapes do
–physics.addBody(Shapes[i], “Dynamic”, { density=0.3, friction=50.6 } )
physics.addBody(Shapes[i], “Dynamic”, { density=10, friction=0.95} )
Shapes[i].linearDamping = 0.4
Shapes[i].angularDamping = 0.6
Shapes[i]:addEventListener( “touch”, dragBody )
Shapes[i].myName = “Shapes” --]]

local thisOne = Shapes[i] --set reference to the current object in loop cycle
local vx, vy = thisOne:getLinearVelocity() --get the linear velocities of that object
local av = thisOne.angularVelocity --get the angular velocity of that object
–check all conditions for “stability”
–adjust these integer values for how “fussy” you want to be… smaller means less movement.
if ( vx > 4 or vx < -4 or vy > 4 or vy < -4 or av > 4 or av < -4 ) then
oneMoving = true

– This break function is causing the error :open_mouth:
break --if any object is “unstable”, break the loop! No reason to continue checking!
end

end

if (boundaryHits == 0 and oneMoving == false )then

print(“Shapes Are Inside The Boundaries”)

end

end

timer.performWithDelay(1000, CheckFunction, 0 )[/lua] [import]uid: 122802 topic_id: 25055 reply_id: 104033[/import]

You still need to loop through all of the shapes.

Add this around Line 12:

local Shapes = Shapes --optimization trick; localize the Shapes table IN the function, to prevent repeated up-value lookup during the loop  
for i = 1, #Shapes do  

You’ll also need another “end” at Line 24 to close the loop. [import]uid: 9747 topic_id: 25055 reply_id: 104036[/import]

Hi Brent

Thank you very very much for all the help, I think I have got it to work now, but sometimes when the shapes are inside the boundaries and seem stable/still, I don’t get the print message “Shapes are inside the boundaries”. Maybe I just need to modify the code a little bit?

Thank you again!

[import]uid: 122802 topic_id: 25055 reply_id: 104423[/import]

You might need to fine-tune the “stability” check values for your game. I gave you the values that I used in my similar scenario, but it might vary for you.

In your check loop (timer), directly BEFORE this line:

if ( vx \> 4 or vx \< -4 or vy \> 4 or vy \< -4 or av \> 4 or av \< -4 ) then

Try printing the values to the terminal/console:

print( vx, vy, av)

Now run your game and watch the terminal display. See what kind of numbers are being output when you personally believe the structure is “stable”. You might want to increase these values (4, -4, etc.)… or decrease for the negative values… to make the check more tolerant and forgiving. The closer you bring these values to 0, the more strict Corona will be on accepting the stability, and it might *never* pass if you make these values too small.

[import]uid: 9747 topic_id: 25055 reply_id: 104452[/import]

Hey IgnisDesign

Thank you for all the help, I appreciate it, it is working very well now :slight_smile:

[import]uid: 122802 topic_id: 25055 reply_id: 104720[/import]

Hi again

I have one little thing I need help to accomplish, related to this. I have added an animation, which is showing up/starting when the shapes are inside the boundaries. What I want to do is if the shapes move out of the boundaries (somehow), the animation should be cancelled and disappear.

This is my code - It almost work, besides that the last if statement does not get triggered.

[lua]local function CheckFunction (event)
if ( boundaryHits == 1) then
Check.isVisible = true

Check:play()
countDown:pause()
Runtime:removeEventListener( “touch”, touchPause )

local Shapes = Shapes ; local oneMoving = false --optimization trick; localize the Shapes table IN the function, to prevent repeated up-value lookup during the loop
for i = 1, #Shapes do

local thisOne = Shapes[i] --set reference to the current object in loop cycle
local vx, vy = thisOne:getLinearVelocity() --get the linear velocities of that object
local av = thisOne.angularVelocity --get the angular velocity of that object
–check all conditions for “stability”
–adjust these integer values for how “fussy” you want to be… smaller means less movement.
print( vx, vy, av)
if ( vx > 4 or vx < -4 or vy > 4 or vy < -4 or av > 4 or av < -4 ) then
oneMoving = true
break --if any object is “unstable”, break the loop! No reason to continue checking!
end

end

else

Check.isVisible = false

Check:pause()

countDown:resume()

if ( oneMoving == false and Check.currentFrame == 4 ) then

print(“Level Complete”)

end

end

end
local Checktimer = timer.performWithDelay(1000, CheckFunction, 0 )[/lua]

I hope you know what I mean - thank you for the help in advance - much appreciated. [import]uid: 122802 topic_id: 25055 reply_id: 107274[/import]

Is your “check” animation a looping one? If so, the issue is probably that it doesn’t always stop/pause on frame #4. Maybe it stops/pauses on #3, thus your “if” statement fails. A better idea might be to check the “isPlaying” flag, and carefully ensure that the animation starts and stops when necessary.

Brent Sorrentino
[import]uid: 9747 topic_id: 25055 reply_id: 107331[/import]

Hi Brent

Thank you for your quick response. I don’t think that it is the animation/sprite, which is causing the issue, it is more likely the “else statement” after the code which check for stability. Because if I remove it, the app works like it should, but if the code is there - the last if statement does not get triggered. It is pretty weird :open_mouth:

Thank you for your help in advance. [import]uid: 122802 topic_id: 25055 reply_id: 107354[/import]

Hi again

Is it possible to stop the check timer when the figure has been built? So I can call a stageclear function where it checks if the shapes are moving, without it calling the function multiple times because of the timer?

Thank you in advance :slight_smile: [import]uid: 122802 topic_id: 25055 reply_id: 108694[/import]

Absolutely! In fact, you MUST stop that timer, or it’ll cause all kinds of problems (errors) and clog itself in memory.

What you need to do, first, is declare the variable as an up-reference at the very top of your code. Something as simple as:

local checkTimer --no need to define it, just create a reference to it  

Then lower down, when you set this as an actual timer, of course just say:

--do not RE-declare it like you have it now:  
local checkTimer = timer.performWithDelay(1000, CheckFunction, 0 )  
--INSTEAD, just do this:  
checkTimer = timer.performWithDelay(1000, CheckFunction, 0 )  

Finally, when the shapes are checked as valid and within the bounds, and you wish to proceed, write this line:

timer.cancel( checkTimer )

Note that you can (and probably should) pause and resume this timer if your game has a pause feature. Same basic concept:

timer.pause( checkTimer )  
timer.resume( checkTimer )  

Brent Sorrentino
Ignis Design [import]uid: 9747 topic_id: 25055 reply_id: 108705[/import]

Not sure why you are working with the physics for it.
If there is only one possible solution to where each shape must go, why not just check against that?
EG If a square must be at location 100, 50, then while you are moving it, or more likely when you stop moving it, just do a simple distance check, IE:

local dX = shape.x - destination.x
local dY = shape.y - destination.y
local snapDistance = 10
local distance = dX * dX + dY * dY
if distance < snapDistance * snapDistance then print( “this is where it should be!”)
else print( “not even close you loser!”) ; end

If a given shape can go in more than one place, or multiple shapes, then you’d need to modify the code accordingly, but it seems to be a very trivial problem to actually solve in straight code. If objects can rotate then you’d simply also include that into the ‘correct position?’ test. [import]uid: 46639 topic_id: 25055 reply_id: 109166[/import]

Hi rakoonic

Thank you for your input. Can you maybe give mé some plug and play code, sample code, so I can try it out and see if it is working better?

Btw. Thank you Brent, I appreciate the help.
[import]uid: 122802 topic_id: 25055 reply_id: 109399[/import]

Good to hear it’s working. Are you considering, however, abandoning the physics approach? Is there some other problem with that approach? It seems that you’ve come a long way with this method…

Brent
[import]uid: 9747 topic_id: 25055 reply_id: 109403[/import]

Hi Brent

No I am not considering to abandon the physics method, it is working very well. I just wanted to see a sample for the other approach in order to learn.

Thank you. [import]uid: 122802 topic_id: 25055 reply_id: 109451[/import]

Check out Rob Miracle’s page:

http://omnigeek.robmiracle.com/2011/12/14/collision-detection-without-physics/ [import]uid: 40033 topic_id: 25055 reply_id: 109482[/import]

Had a quick look at that page and it makes a few basic errors and inefficiencies in the routines.
Optimising stuff isn’t really a big deal (since the code still works) so the square root thing for example (as mentioned in the first comment) isn’t a big deal, but when it comes to multiple collisions and what-not you’d need to know a few things, such as:

  1. Iterate through the table of objects backwards. This lets you delete objects without screwing up the loop.

  2. If you have 10 objects and need to check against all the others, it isn’t 10 x 10 checks, because you can ignore all previous collisions (so it works out a bit quicker). In fact your loops would look something like this:

for i = #objects, 2, -1 do
local firstObject = objects[i]
for j = (i - 1), 1, -1 do
local secondObject = objects[j]
– Check for a collision between firstObject and secondObject and react accordingly
end
end

The savings are significant. If you have 10 objects, checking all VS all is 100 checks (technically 90 - would you really attempt to collide an object with itself? :), but doing it this way it is only 55, almost half the code. [import]uid: 46639 topic_id: 25055 reply_id: 109496[/import]

Excellent! Significant savings = very good! :wink: [import]uid: 40033 topic_id: 25055 reply_id: 109497[/import]

Hi

Thank you for all the help related to this. I just have have problem, I need to get solved.

In my check function (the function which detects if the shapes are in the right place) I have some if statements and then I have added an else statement. But if I this else statement is there, the last if statement does not get triggered. What have I done wrong? and is it possible to get it to work properly? :smiley:
[lua]local function CheckFunction (event)
if ( boundaryHits == 0) then

Check.isVisible = true
Check:play()
gameClock:pause()
Runtime:removeEventListener( “touch”, touchPause )

local Shapes = Shapes ; local oneMoving = false --optimization trick; localize the Shapes table IN the function, to prevent repeated up-value lookup during the loop
for i = 1, #Shapes do
local thisOne = Shapes[i] --set reference to the current object in loop cycle
local vx, vy = thisOne:getLinearVelocity() --get the linear velocities of that object
local av = thisOne.angularVelocity --get the angular velocity of that object
–check all conditions for “stability”
–adjust these integer values for how “fussy” you want to be… smaller means less movement.
print( vx, vy, av)
if ( vx > 4 or vx < -4 or vy > 4 or vy < -4 or av > 4 or av < -4 ) then
oneMoving = true
break --if any object is “unstable”, break the loop! No reason to continue checking!
end

end

else
–stop check animation if the shapes are unstable or if the shapes are not inside the boundaries

Check.isVisible = false
Check:pause()
gameClock:resume()
Runtime:addEventListener( “touch”, touchPause )

if ( oneMoving == false ) then

print(“Level Complete”)

timer.cancel( Checktimer )
print(“Checktimer Cancel”)

doGameCompleted()
end
end
end [/lua]

Thank you in advance!

[import]uid: 122802 topic_id: 25055 reply_id: 112792[/import]

Hi again,

This appears to basically be a logic flow error (where you’re placing the if-then statements). You basically need to use the “oneMoving” variable as a means to test if something is “wrong”, i.e. the structure is unstable or whatever. Try the code below… I’ve sort of re-indented the if-then blocks so it’s easier to understand where each on resides in the logic flow.

[code]
local function CheckFunction (event)

if ( boundaryHits == 0) then

Check.isVisible = true
Check:play()
gameClock:pause()
Runtime:removeEventListener( “touch”, touchPause )

local Shapes = Shapes ; local oneMoving = false
for i = 1, #Shapes do
local thisOne = Shapes[i]
local vx, vy = thisOne:getLinearVelocity()
local av = thisOne.angularVelocity
–check all conditions for “stability”
–print( vx, vy, av)
if ( vx > 4 or vx < -4 or vy > 4 or vy < -4 or av > 4 or av < -4 ) then
oneMoving = true
break --if any object is “unstable”, break the loop! No reason to continue checking!
end
end

if ( oneMoving == false ) then

print(“Level Complete”)
timer.cancel( Checktimer )
print(“Checktimer Cancel”)
doGameCompleted()

else --oneMoving is “true” so the structure isn’t stable!

Check.isVisible = false
Check:pause()
timer.cancel( Checktimer )
gameClock:resume()
Runtime:addEventListener( “touch”, touchPause )

end

end

end
[/code] [import]uid: 9747 topic_id: 25055 reply_id: 112819[/import]