Complex Bodies Collision and Image switching

I have declared the following variables for multi-element bodies png files in corona all are physics bodies

local h2 = h2.png complex body composed of element1, element2 and element3
h2.myName = “h”

local h1 = h1.png complex body composed of element1 and element2
h1.myName = “h”

local h0 = h0.png body composed of element1 only
h0.myName = “h”

local m2 = m2.png complex body composed of element1, element2 and element3
m2.myName = “m”

local m1 = m1.png complex body composed of element1 and element2
m1.myName = “m”

local m0 = m0.png body composed of element1 only
m0.myName = “m”

I need to setup some collision with image switching
( x,y coordinates of previous images will be recorded and assign to new image )

element1 in all cases refers to circle or rect depending on image
element2 and element3 whichever on presents in an image refers to a line
only element1 coming into contact with element2 or element3 triggers a collision

if element1 of h2 collides with element2 or element3 of m2 then m2 becomes m1
if element1 of h1 collides with element2 or element3 of m2 then m2 becomes m1
if element1 of m1 collides with element2 or element3 of h2 then h2 becomes h1
if element1 of m2 collides with element2 or element3 of h2 then h2 becomes h1

if element1 of h2 collides with element2 of m1 then m1 becomes m0
if element1 of h1 collides with element2 of m1 then m1 becomes m0
if element1 of m2 collides with element2 of h1 then h1 becomes h0
if element1 of m1 collides with element2 of h1 then h1 becomes h0

The collision is not giving any result on screen nothing happens here is the code below,

Is it possible to declare h0, h1, m0 and m1 without displaying the image first because
they should only appear after a collision but I think I need to declare them first since
they have different shapes from m2 and h2

[lua]local physics = require( “physics”)
physics.start()
physics.setDrawMode( “hybrid” )
display.setStatusBar (display.HiddenStatusBar)

–in this example h2 is a rectangle with 2 obliques lines on top, left line is hh1, right line is hh2
–Format is x, y , x , y , x, y , x , y
local rect = {-35, -71.5 , 39, -71.5 , 39.5, -31 , -36, -29.5}
local hh1 = { -22, -71.5 , -56.5, -121 , -55, -125.5 , -14, -71.5 }
local hh2 = { 52, -126.5 , 54.5, -122 , 26.5, -72 , 21, -71.5 }

– m2 is a cricle with 2 obliques lines on top, left line is mh1, right line is mh2
local circle = { 10, -65.5 , 26, -58.5 , 36.5, -48 , 42.5, -34 , 42.5, -16 , 26, 8.5 , -22, -58.5 , -6, -65.5 }
local mh1 = { -72.5, -126 , -24.5, -57 , -29.5, -55 , -78, -123.5 , -78.5, -128 }
local mh2 = { 96.5, -124 , 38, -47.5 , 33, -52.5 , 89.5, -124 , 95, -127.5 }
local h0 = display.newImage(“h0.png”)
h0.x = 70 h0.y = 320
h0.myName = “h”
physics.addBody(h0, “static”,
{ density=10.0, friction=0.6, bounce=0.5, shape=rect})

local h1 = display.newImage(“h1.png”, 50, 62)
h1.x = 240 h1.y = 320
h1.myName = “h”
physics.addBody(h1, “static”,
{ density=10.0, friction=0.6, bounce=0.5, shape=rect},
{ density=10.0, friction=0.6, bounce=0.5, shape=hh1}
)

local h2 = display.newImage(“h2.png”, 50, 62)
h2.x = 410 h2.y = 320
h2.myName = “h”
h2.isHero = true
physics.addBody(h2, “static”,
{ density=10.0, friction=0.6, bounce=0.5, shape=rect},
{ density=10.0, friction=0.6, bounce=0.5, shape=hh1},
{ density=10.0, friction=0.6, bounce=0.5, shape=hh2}
)

local m0 = display.newImage(“m0.png”, 50, 62)
m0.x = 70 m0.y = 160
m0.myName = “m”
physics.addBody(m0, “static”,
{ density=10.0, friction=0.6, bounce=0.5, shape=circle})

local m1 = display.newImage(“m1.png”, 50, 62)
m1.x = 220 m1.y = 160
m1.myName = “m”
physics.addBody(m1, “static”,
{ density=10.0, friction=0.6, bounce=0.5, shape=circle},
{ density=10.0, friction=0.6, bounce=0.5, shape=mh1}
)

local m2 = display.newImage(“m2.png”, 50, 62)
m2.x = 360 m2.y = 160
m2.myName = “m”
physics.addBody(m2, “static”,
{ density=10.0, friction=0.6, bounce=0.5, shape=circle},
{ density=10.0, friction=0.6, bounce=0.5, shape=mh1},
{ density=10.0, friction=0.6, bounce=0.5, shape=mh2}
)

–if element1 of h2 collides with element2 or element3 of m2 then m2 becomes m1
function handleCollision(event)
if (((event.object1 == h2.rect) and (event.object2 == m2.mh1)) or ((event.object2 == h2.rect) and (event.object1 == m2.mh2))) then
m2 = display.newImage(“m1.png”, m2.x, m2.y)
end
end
Runtime:addEventListener(“collision”, handleCollision) [import]uid: 43696 topic_id: 9493 reply_id: 309493[/import]

Hi there,

Is this routine producing absolutely NO collision detection at all? Or is it something more complex regarding the shapes, image switching, or other?

I see you’re using a “Global collision listener” as documented in the Corona docs. I think I tried using these in the beginning, but I couldn’t get it to work properly. So, I switched over to “Local collision listeners”. These work perfectly for me, and I like the structure of local collisions versus global… just a personal preference. I prefer having a local listener assigned to the object(s) I need to sense collision, versus a global “when anything touches anything else” kind of setup.

Also, the documentation isn’t necessarily clear about this, but you do not need to assign a local listener to EVERY physical object in your scene… that would be really tedious! In my game, I have just 1 local listener assigned: to my “Player” object. When it collides with some other physical object, this registers a hit: “Player” is the “self” parameter of the resulting function, and “event.other” indicates the object it collided with.

For clarity, I then assign local variables at the start of the collision handler function:

local srcObj = self ; local dstObj = event.other

You can probably figure out the rest on your own. If you are still having trouble, let me know and I can copy some code examples from my game.

Search for the topic here (it’s directly below the Global listener description):
http://developer.anscamobile.com/content/game-edition-collision-detection

Hopefully this helps!

Brent Sorrentino
Ignis Design [import]uid: 9747 topic_id: 9493 reply_id: 34769[/import]

Hey Brent

Well in my case my “Player” object is -h- and has h0, h1 and h2 each with specific properties and you can only have one on screen at once either h1 or h2
-m- is for the monster h1, h2 each with specific properties you can have as many of each on screen at once

I used the global listener below and it reported the element involved in the collision as I wanted and switched the image but once h1.png appear it does not have any property just an image on screen how do I make it take the physics properties I defined for h1 at the beginning.
Does it have to do with the “myName” or the way I defined the variables

Also when I have one h1 and one h2 on screen for testing purposes every time a collision happened between h1 and an object of type -m- involving the right elements, h2 changes too although it was not involved in the collision

What will be the best way to get this done using a local collision? At the start there will be one h2 onscreen and a few m2, once the correct collision between h2 and an m2 occurs:
the h2 should either become h1 and have all the properties defined for it above or the m2 involved should become m1 will all its properties the others m2 onscreen not involved in the collision should stay m2 ( I included the one I used below too )

[lua]local function onGlobalCollision( event )
if ( event.phase == “began” ) then

print( “Global report: " … event.object1.myName … " & " … event.object2.myName … " collision began” )

elseif ( event.phase == “ended” ) then

print( “Global report: " … event.object1.myName … " & " … event.object2.myName … " collision ended” )

end

print( "**** " … event.element1 … " – " … event.element2)
if ( ( event.element1 == 2 ) or ( event.element1 == 3 ) ) then
local tempX = h2.x local tempY = h2.y
h2:removeSelf()
h2 = display.newImage(“h1.png”)
h2.x = tempX h2.y = tempY
end
end
Runtime:addEventListener( “collision”, onGlobalCollision )

–I also tried this local listener but it does not return the elements involved

local function onLocalCollision( self, event )
local h2 = Self
local m2 = event.other
if ( event.phase == “began” ) then

print( self.myName … ": collision began with " … event.other.myName )

elseif ( event.phase == “ended” ) then

print( self.myName … ": collision ended with " … event.other.myName )

print( "**** " … event.selfElement … " – " … event.otherElement)

end
end

h2.collision = onLocalCollision
h2:addEventListener( “collision”, h2 )
m2.collision = onLocalCollision
m2:addEventListener( “collision”, m2) [import]uid: 43696 topic_id: 9493 reply_id: 34792[/import]

Hi kofmes,

Just to simplify this discussion back to the core issue… are you trying to completely *change* physics bodies of objects upon collision? Or do you just want to switch the images or other variable traits (i.e. life, damage, etc.) associated with these objects? Sorry if I didn’t pick up on the core issue you’re struggling with; sometimes I read too much into the technical code aspects. :slight_smile:

If you’re trying to outright change physics bodies, i.e. change a body from “triangle” to “pentagon” upon collision, Corona doesn’t really allow that. I think this might have been discussed in other threads recently, so search around for it.

If this is your goal, there might be a monkey-wrench solution. You could probably delete the current physics body entirely, then assign a new one afterward, in a called function. But I have not tested this so I can’t vouch for it.

Let me know what you turn up in some forum searches and maybe I can advise further…

Brent
[import]uid: 9747 topic_id: 9493 reply_id: 34796[/import]

http://www.vimeo.com/19213301
this is a video of the Corona made game ROBOT 99 it kind of illustrate it.
When the simple robot falls to the ground it is rolled of screen,
when a touch event is registered on the simple robot during its fall it now has a parachute it could seem like a simple image switch but when the robot with parachute hits the bottom unlike the simple robot it shoots back up in the the air which leads me to believe it’s not a simple image switch but a completely new object that was introduced by the touch event

Let’s take the two objects below the only difference is hh2 as a 3rd element,
it’s just a rectangle with lines sticking out h2 has 2 lines and h1 has a single line
hh1 and hh2 are just line and rect is a rectangle
when a collision occurs on one of h2’s lines, the h2 object is removed and replaced by h1 with it’s image and all its properties as defined below so not just a simple image change. It can be considered a damage because of the missing element but the goal is to make the change of object and keep playing with h1
[lua]local h1 = display.newImage(“h1.png”, 50, 62)
h1.x = 240 h1.y = 320
h1.myName = “h”
physics.addBody(h1, “static”,
{ density=10.0, friction=0.6, bounce=0.5, shape=rect},
{ density=10.0, friction=0.6, bounce=0.5, shape=hh1}
)

local h2 = display.newImage(“h2.png”, 50, 62)
h2.x = 410 h2.y = 320
h2.myName = “h”
physics.addBody(h2, “static”,
{ density=10.0, friction=0.6, bounce=0.5, shape=rect},
{ density=10.0, friction=0.6, bounce=0.5, shape=hh1},
{ density=10.0, friction=0.6, bounce=0.5, shape=hh2}
) [import]uid: 43696 topic_id: 9493 reply_id: 34798[/import]

In this case, I would suggest you experiment with deleting the current physics body and then re-assigning it in the next game cycle (which happens almost instantaneously, 33 milliseconds or something which wouldn’t be noticed by the player).
[import]uid: 9747 topic_id: 9493 reply_id: 34840[/import]

I am completely deleting the object then recreating it with a new image the code does not go past the print statement the simulator crashes so I get a new image without any physics property

I dont get a message concerning an error in my .lua code but this

Applications/CoronaSDK/Corona Terminal: line 9: 63407 Bus error
“$path/Corona Simulator.app/Contents/MacOS/Corona Simulator” $* logout

On the other hand when using a local listener with event.selfElement and event.otherElement it does not return the index number of the elements involved in the collision as expected while the global listener event.element1 and event.element2 return the right body element index number thus initiating the image switch

[lua]local function onGlobalCollision( event )
if ( event.phase == “began” ) then
print( “Global report: " … event.object1.myName … " & " … event.object2.myName … " collision began” )
elseif ( event.phase == “ended” ) then
print( “Global report: " … event.object1.myName … " & " … event.object2.myName … " collision ended” )
end
print( "**** " … event.element1 … " – " … event.element2)
if ( ( event.element1 == 1 ) and ( event.element2 == 1 ) or ( event.element1 == 2 ) and ( event.element2 == 1 ) or
( event.element1 == 6 ) and ( event.element2 == 1 ) ) then
local tempX = obj.x local tempY = obj.y

display.remove(obj)
obj = display.newImage(“Fly2x.png”)
obj.x = tempX obj.y = tempY
print (“here i am”)
physics.addBody(obj, physicsData:get(“Fly2x”)) – using physics editor for the data
–but still crashes when doing the regular way
end
end

Runtime:addEventListener( “collision”, onGlobalCollision ) [import]uid: 43696 topic_id: 9493 reply_id: 35153[/import]

I’m pretty sure the cause of your first problem (crash) is that you can’t remove and add a new physics body in the same step (game cycle). You need to let Corona “handle” the first body then move to the next.

So, you’ll need to call your swap (new body) in another function (or in the same, but triggered by a timer of 33 or 50 or 100 milliseconds). This should allow Corona to safely delete the first body and then assign the next.

As for your local vs. global collision issue, did you follow the example in the Corona documentation exactly? If you’re using “event.selfElement” and “event.otherElement”, those are not the correct terms: I think “self” is the first parameter of the on-collide function (whatever you name it) and “event.other” is the other parameter you’ll need.

Can you post some of your code using the local collision method vs. global?

Brent [import]uid: 9747 topic_id: 9493 reply_id: 35159[/import]

here is the local collision. So I created a swap function do I put display.remove(obj) in it or outside before the function call in the if statement and how do I call it with a delay or keep it the same but triggered by a delay
[lua]local function onLocalCollision( self, event )
local obj = Self
local m2 = event.other

if ( event.phase == “began” ) then
print( self.myName … ": collision began with " … event.other.myName )
elseif ( event.phase == “ended” ) then
print( self.myName … ": collision ended with " … event.other.myName )
print( "**** " … event.SelfElement … " – " … event.otherElement)
end
end

obj.collision = onLocalCollision
obj:addEventListener( “collision”, obj )
m2.collision = onLocalCollision
m2:addEventListener( “collision”, m2 )

local swap = function()
display.remove(obj)
obj = display.newImage(“Fly2x.png”)
obj.x = tempX obj.y = tempY
print (“here i am”)
physics.addBody(obj, physicsData:get(“Fly2x”))
end [import]uid: 43696 topic_id: 9493 reply_id: 35197[/import]

A few quick comments:

  1. You capitalized “Self” in line 2; Lua is case-sensitive, so make it lowercase.

  2. The “swap” function must be *above* the collision function by standard Lua structure; you’ll get a “stack traceback” error if you try to call a local function from another local function and the one being called is below the one calling it. Does that make any sense? :stuck_out_tongue:

  3. The deletion of the first body should happen within the FIRST function (the collision function). The addition of the new body must happen in the swap function. Call it using a standard timer (timer.performWithDelay()) right after the first body is deleted.

Please post how this progress/changes goes… [import]uid: 9747 topic_id: 9493 reply_id: 35235[/import]

Hey Brent
This works it switch the image with all the physics properties
The only problem now is still with the local listener even by changing to lowercase i still dont the get the right number as the global i get some negative/positive numbers very high any idea what can generate them?
[lua]local tempX; local tempY;

local swap = function()
obj = display.newImage(“boyFly@2x.png”)
obj.x = tempX obj.y = tempY
physics.addBody(obj, physicsData:get(“boyFly@2x”))
end

local function onGlobalCollision( event )
if ( event.phase == “began” ) then
print( “Global report: " … event.object1.myName … " & " … event.object2.myName … " collision began” )
elseif ( event.phase == “ended” ) then
print( “Global report: " … event.object1.myName … " & " … event.object2.myName … " collision ended” )
end
print( "**** " … event.element1 … " – " … event.element2)
if ( ( event.element1 == 1 ) and ( event.element2 == 1 ) or ( event.element1 == 2 ) and ( event.element2 == 1 ) or
( event.element1 == 6 ) and ( event.element2 == 1 ) ) then
tempX = obj.x; tempY = obj.y
display.remove(obj)
timer.performWithDelay(10, swap)
end
end
Runtime:addEventListener( “collision”, onGlobalCollision ) [import]uid: 43696 topic_id: 9493 reply_id: 35251[/import]

I’m a bit lost again… did you decide to use a global listener method, or a local listener? Which one is working and which one isn’t? Which one is generating the odd numbers? Can you post that specific chunk of code? [import]uid: 9747 topic_id: 9493 reply_id: 35269[/import]

could someone answer this issue on collisions and arrays?

http://developer.anscamobile.com/forum/2011/05/03/collision [import]uid: 54001 topic_id: 9493 reply_id: 35276[/import]

I am trying to get both to work the previous code is for the global listener and it works
the local listener is the one generating the odd numbers instead of elements number
here is the code for the local
[lua]------
local function onLocalCollision( self, event )
local obj = Self
local m2 = event.other
if ( event.phase == “began” ) then
print( self.myName … ": collision began with " … event.other.myName )
elseif ( event.phase == “ended” ) then
print( self.myName … ": collision ended with " … event.other.myName )
print( "**** " … event.selfElement … " – " … event.otherElement)
end
end

obj.collision = onLocalCollision
obj:addEventListener( “collision”, obj )
m2.collision = onLocalCollision
m2:addEventListener( “collision”, m2 ) [import]uid: 43696 topic_id: 9493 reply_id: 35306[/import]

See my comments below; hopefully this will help. I sense that you’re very close to figuring this all out, it’s just some tiny aspect that is wrong/missing. :slight_smile:

[code]
local function onLocalCollision( self, event )
local obj = self --made lowercase
local m2 = event.other
if ( event.phase == “began” ) then
print( obj.myName … ": collision began with " … m2.myName )
–“obj” is now “self” (defined above), so no need to use “self” now
–“m2” is now “event.other” so no need to use “event.other” now
–I assume “myName” is defined as a parameter for each object when you first declare them?
elseif ( event.phase == “ended” ) then
print( obj.myName … ": collision ended with " … m2.myName )
print( "**** " … event.selfElement … " – " … event.otherElement)
–what is “event.selfElement”? This might be the cause or your weird positive/negative
–numbers. “event” is like the Corona “handler” for this collision. If you want the OBJECT
–involved in the collision, you use “event.other” or rather “m2” since you defined
–those as the same. Likewise with “event.otherElement”; neither of these are native
–Corona parameters that I know of, so you must have tried to define them elsewhere, but
–they are not called correctly here.
end
end

obj.collision = onLocalCollision
obj:addEventListener( “collision”, obj )
m2.collision = onLocalCollision
m2:addEventListener( “collision”, m2 )
[/code] [import]uid: 9747 topic_id: 9493 reply_id: 35320[/import]

I found event.selfElement and event.otherElement on the link you gave me the first time
http://developer.anscamobile.com/content/game-edition-collision-detection
I am working with complex bodies (multi elements bodies) in my collision.
Those two when it comes to complex bodies involved in a collision
returns the element involved for each body and for my collision I need specific elements colliding between obj(player) and m2(monster) in order to trigger the swap function
and myName is defined as parameter for each object and the myName name is displayed by the print statement in the terminal.

If I have different type of object (monsters, platform, ground) that the player collides with each triggering a different reaction do I write a collision function for the player and each one of the other type of objects? [import]uid: 43696 topic_id: 9493 reply_id: 35325[/import]

I see now where you’re getting “selfElement” and “otherElement”. I haven’t used this part-specific attribute before, sorry.

According to the documentation for local listeners:
As above, these values will be 1 in the case of single-element bodies, and in multi-element bodies will range from 1 to the total number of elements in the body, numbered by the order in which the elements were added to the body.

Are you getting recognizable values returned from your collisions? For example, when “Player” collides with “part 2” of monster, “otherElement” sends back “2” to your collision function?

For your last question, you definitely *don’t* need to write a new collision function for different types of objects. That would be very tedious. :slight_smile: You just need to filter the returned collision data properly and use if-then statements depending on what you want to do next.
[import]uid: 9747 topic_id: 9493 reply_id: 35330[/import]

It returns no recognizable values I get some high numbers sometimes in the 100’s even negative,
but when I use event.element1 and event.element2 in the global collision code posted before as mentioned on the same page it does return the right numbers. [import]uid: 43696 topic_id: 9493 reply_id: 35355[/import]

In this case, I would suggest you use the global collision routine… unless it was causing some other problem way up in this thread that I forgot about. Obviously, both are legit ways to handle collisions; I just use local listeners in my game and they work perfectly. But my collision handling is more simple than yours. :wink:

If you get this step working, remember that you’ll have to deal with collision groups and filters next. I wrote a very detailed post about this issue which many developers have found useful. Here’s the link:

http://developer.anscamobile.com/forum/2010/10/25/collision-filters-helper-chart [import]uid: 9747 topic_id: 9493 reply_id: 35412[/import]

It seems like there’s a bug, at least in the non-daily build I’m using. I’m seeing it for both global and local events. On the began phase everything works fine as the docs say it should.

On the ended phase (and the postCollision event) however:
event.x has the event.selfElement/event.element1 value.
event.y has the event.otherElement/event.element2 value.

event.selfElement/event.element1 has a the integer rounded event.x value
event.otherElement /event.element2 has a the integer rounded event.y value [import]uid: 56009 topic_id: 9493 reply_id: 35443[/import]