Collision event.x/event.y inconsistent on newly added bodies

I’m working on a basic 2D platform game and I’m finding that randomly when I add new physics bodies (new platforms) the collisions between my character and it will have event.x/event.y relative to the platform instead of relative to the character like the ones I made when creating the scene. (The collision handler belongs to the character, not the platform)

Interestingly, calling removeBody on the character and re-adding it will make it “randomly” happen only about 25% of the time, but if I don’t do that it’s close to 100%. Still – I need it to work the same every time. Any ideas? [import]uid: 119931 topic_id: 28600 reply_id: 328600[/import]

I haven’t encountered this before, it sounds a bit strange - would have a cut down version you could share or a plug and play example? [import]uid: 52491 topic_id: 28600 reply_id: 115392[/import]

yeah, I’m working on a stripped down version to isolate it. I’ll post that when I have it (or the solution, if I come across it first) [import]uid: 119931 topic_id: 28600 reply_id: 115449[/import]

I’ve managed to isolate it – this is just an edited “level1.lua” file from one of the basic collision detection samples.

When the crate first drops and hits the platform, the event.x/y is reported as (45,45), which is relative to the crate which is 90x90. Makes sense, that’s what I would expect. However if you then click the re-add platform button (which destroys and re-adds the platform) and then redrop the crate, the event.x/y will report something like 70.6x-5.99 which can only be relative to the platform. Since the onCollision handler is attached to the crate, I would expect the event.x/y to always be relative to the crate and not change depending on the order the objects are added to the physics engine.

Interestingly, if you keep re-adding the platform and re-dropping the crate, the event.x/y coords seem to cycle between being relative to the crate and relative to the platform.

Is this a bug or am I doing something wrong?

[code]
local widget = require( “widget” );
local storyboard = require( “storyboard” )
local scene = storyboard.newScene()

– include Corona’s “physics” library
local physics = require “physics”
physics.start(); physics.pause()

local crate = false;
local platform = false;
local addbutton = false;
local resetbutton = false;
local platform_def = { x=60, y=400, width=150, height=10, bodyType=“static”, ob_type=“platform” }
– Called when the scene’s view does not exist:
function scene:createScene( event )

platform = createPlatform(platform_def);

– make a crate (off-screen), position it, and rotate slightly
crate = display.newImageRect( “crate.png”, 90, 90 )
crate.x, crate.y = 160, -100
crate.rotation = 0

– add physics to the crate
physics.addBody( crate, { density=1.0, friction=0.2, bounce=0.0 } )
crate.isFixedRotation = true;
crate:addEventListener( “collision”, function(event) onCollision(event); end );
addbutton = widget.newButton{
label=“Re-Add Platform”,
labelColor = { default={0}, over={0} },
width=125, height=40,
left = display.contentWidth - 150,
top = 25,
onRelease = function() platform:removeSelf(); platform=nil; platform = createPlatform(platform_def); return true; end
}
resetbutton = widget.newButton{
label=“Reset Crate”,
labelColor = { default={0}, over={0} },
width=124, height=40,
left = display.contentWidth - 150,
top = 90,
onRelease = function() crate.x,crate.y = 160, -100; return true; end
}
end

function createPlatform(params)

local object = nil;
object = display.newRoundedRect( params.x, params.y, params.width, params.height, 2 );
object.strokeWidth = 1;
object:setFillColor( 100, 100, 100 );
object:setStrokeColor( 0,0,0 );

object.density = params.density or 0;
object.friction = params.friction or 0;
object.bounce = params.bounce or 0;
object.isSensor = params.isSensor or false;
object.bodyType = params.bodyType or “dynamic”;

physics.addBody( object, object.bodyType, {density = object.density, friction = object.friction, bounce = object.bounce, isSensor = object.isSensor}) ;

object.ob_type = params.ob_type or “platform”;

return object;
end

function onCollision(event)

local other = event.other;
if( other.ob_type == “platform” ) then
– hit a platform

if( event.phase == “began” ) then

print("crate/platform collision at location: " … event.x … " x " … event.y );
end
end

end

– Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view

physics.start()

end

– Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view

physics.stop()

end

– If scene’s view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
local group = self.view

package.loaded[physics] = nil
physics = nil
end


– END OF YOUR IMPLEMENTATION

– “createScene” event is dispatched if scene’s view does not exist
scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished
scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched whenever before next scene’s transition begins
scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be
– automatically unloaded in low memory situations, or explicitly via a call to
– storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( “destroyScene”, scene )


return scene
[/code] [import]uid: 119931 topic_id: 28600 reply_id: 116134[/import]

To me this sounds quite a lot like a bug - could you file something with this stripped down sample zipped with any and all assets needed to run it, please? Someone should then be able to confirm. [import]uid: 52491 topic_id: 28600 reply_id: 116210[/import]

Thanks! I’ve submitted it as case #15864 [import]uid: 119931 topic_id: 28600 reply_id: 116255[/import]

How frustrating.

After 4 days I get a response to use event.other.x/y instead – but those aren’t the same. My understanding is that event.x/y are supposed to be the location of the actual collision, which is completely different from event.other.x/y (or self.x/y)

I’m basically trying to determine the hit location on the object but I can’t do that if event.x/y are broken. I realize I can calculate it easily enough for simple shapes – but I shouldn’t have to if event.x/y were working consistently.

Actually, the API docs say event.x/y are supposed to be global coordinates – but that’s never the case in a local collision handler.

-Jeffrey [import]uid: 119931 topic_id: 28600 reply_id: 116785[/import]

Event.x and event.y will return the x and y of the object listening for collision while event.other.x and event.other.y will return x and y of the other object involved in the collision.

If you are trying to get the point the two objects connect I’d suggest calculating this yourself based on the location of each object and their sizes. [import]uid: 52491 topic_id: 28600 reply_id: 116841[/import]

Peach, Yes, it’s looking like I’ll need to calculate it myself, that’s fine. Please just understand my frustrating that what I’m hearing from Corona staff, what I’m reading in the API docs, and what I’m seeing happen are 3 different things. It’s even more frustrating that I provided (what I think to be) a pretty clear example, and I feel like that’s being ignored.

http://docs.coronalabs.com/api/event/collision/x.html
“The x position, in global screen coordinates, that the collision event occurred.”

I realize that’s for a global collision handler – if you can point me towards the local version I’d appreciate it. But to me that’s saying that event.x/y were intended to be the location of the collision, not of either object. If the API docs are right, then the bug is that the hit coordinates aren’t global. If what you’re saying is right then the bug is that event.x/y should match event.other.x/y, which they don’t

The example below is basically what I submitted with the bug report. There are no assets, it should just work with a generic build/config file.

main.lua:

display.setStatusBar( display.HiddenStatusBar )  
  
local widget = require "widget"  
local physics = require "physics"  
  
physics.start(); physics.pause()  
  
local crate = false;  
local platform = false;  
local addbutton = false;  
local resetbutton = false;  
  
-- creates the platform  
function spawnPlatform()  
  
 local object = nil;  
 object = display.newRoundedRect( 60, 400, 150, 10, 2 );  
 object:setFillColor( 100, 100, 100 );  
 object.ob\_type = "platform";  
  
 physics.addBody( object, "static", {density = 0, friction = 0, bounce = 0, isSensor = false}) ;  
  
 return object;   
end  
  
-- the crate's onCollision handler  
function onCollision(event)  
  
 if( event.other.ob\_type == "platform" ) then  
  
 -- the crate hit a platform, what's the hit location?  
 if( event.phase == "began" ) then  
 print("");  
 print("event.x/y: " .. event.x .. " x " .. event.y );  
 print("event.other.x/y: " .. event.other.x .. " x " .. event.other.y );  
 print("platform.x/y: "..platform.x .. " x " .. platform.y );  
 print("crate.x/y: "..crate.x .. " x " .. crate.y )  
 end  
 end  
  
end  
  
-- create a new platform  
platform = spawnPlatform();  
  
-- make the crate  
crate = display.newRect( 80, -100, 90, 90 );  
  
-- add physics to the crate  
physics.addBody( crate, { density=1.0, friction=0.2, bounce=0.0 } )  
crate.isFixedRotation = true;  
crate:addEventListener( "collision", onCollision );  
  
-- make a button that removes and re-adds the platform  
addbutton = widget.newButton{  
 label="Re-Add Platform",  
 width=125, height=40, left = display.contentWidth - 150, top = 25,  
 onRelease = function()   
 platform:removeSelf();   
 platform=nil;   
 platform = spawnPlatform();   
 return true;  
 end  
}  
  
-- make a button that redrops the crate in the same position each time  
resetbutton = widget.newButton{  
 label="Reset Crate",  
 width=124, height=40, left = display.contentWidth - 150, top = 90,  
 onRelease = function()   
 crate.x,crate.y = 160, -100;   
 return true;   
 end  
}  
  
-- start  
physics.start()  
  1. let the crate drop – note the various x/y values in the console
  2. click the “re-add platform” button and then the “reset crate” button – the crate drops again, note the values in the console

event.x/y never match the coordinates of either object. If they are supposed to, that’s fine – but they don’t. They appear to be hit locations relative to one object or the other (which is very cool!) but it’s not consistent as to which they are relative to.

Thanks again [import]uid: 119931 topic_id: 28600 reply_id: 116869[/import]

Hey Jeffrey,

I understand you are frustrated, I’m sorry you feel ignored; I will try and bump this ticket and see if we can get some clarification for you - my understanding was that global collision listener would return the hit location relative to the object1 in the collision, though I’m unsure on inconsistencies there RE obj1/obj2.

Will bring this up in our meeting and see if can get some attention on it.

Peach :slight_smile: [import]uid: 52491 topic_id: 28600 reply_id: 116988[/import]

Thanks, Peach.

The API docs really seem to say event.x/y are global coordinates for a global handler, but I haven’t actually checked to confirm that. All I can say is they are definitely local (relative) coordinates for a local handler, but not always relative to the same object.

At this point I’m calculating the hit location myself since my cases are currently simple ones. But I’m still really interested to see if this can be sorted out since I’ll want to customize the body shapes down the road – and then the hit locations become less trivial to calculate!

Thanks again!
-Jeffrey

[import]uid: 119931 topic_id: 28600 reply_id: 117029[/import]

Bump… same issue:

http://developer.coronalabs.com/forum/2012/10/03/collision-location-appears-incorrect [import]uid: 8271 topic_id: 28600 reply_id: 126238[/import]

Bump… same issue:

http://developer.coronalabs.com/forum/2012/10/03/collision-location-appears-incorrect [import]uid: 8271 topic_id: 28600 reply_id: 126238[/import]

Any news on this one? [import]uid: 169740 topic_id: 28600 reply_id: 128153[/import]

Any news on this one? [import]uid: 169740 topic_id: 28600 reply_id: 128153[/import]

Appears Brent is helping in the other thread, so please post replies there in order to avoid having two simultaneously going - thanks :slight_smile: [import]uid: 52491 topic_id: 28600 reply_id: 128455[/import]

Appears Brent is helping in the other thread, so please post replies there in order to avoid having two simultaneously going - thanks :slight_smile: [import]uid: 52491 topic_id: 28600 reply_id: 128455[/import]

Nothing useful I’m afraid. Someone responded recently to my bug report saying event.object1 and event.object2 tell you which object event x/y are relative to – but those don’t exist in a local collision handler and that’s exactly the problem! Basically I keep saying that the *local* collision event x/y don’t tell you which the coords are relative to, and they keep saying that *global* ones work fine.

So, I don’t think they actually ran the demo I attached. For reference, I got it condensed down to this, which I think is pretty clear that event.x/y are unusable in a local handler – there’s just no way to know which object they will be relative to after a new object is added

-- removed. it looks like the same as what I already posted above

Nothing useful I’m afraid. Someone responded recently to my bug report saying event.object1 and event.object2 tell you which object event x/y are relative to – but those don’t exist in a local collision handler and that’s exactly the problem! Basically I keep saying that the *local* collision event x/y don’t tell you which the coords are relative to, and they keep saying that *global* ones work fine.

So, I don’t think they actually ran the demo I attached. For reference, I got it condensed down to this, which I think is pretty clear that event.x/y are unusable in a local handler – there’s just no way to know which object they will be relative to after a new object is added

-- removed. it looks like the same as what I already posted above