Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Q: Physics eventlisteners on sprites? — Gideros Forum

Q: Physics eventlisteners on sprites?

GhandoGhando Member
edited January 2012 in General questions
So I've been playing with the "Collision Detection" project using physics for collisions but having movement of objects using Gtween. The following works and in the console I can see the begin/pre/post/end events getting called.
_H = application:getDeviceHeight()
_W = application:getDeviceWidth()
 
require "box2d"
 
b2.setScale(10)
 
local sky = Bitmap.new(Texture.new("sky.png"))
stage:addChild(sky)
 
local grass = Bitmap.new(Texture.new("grass.png"))
grass:setY(400)
stage:addChild(grass)
 
local world = b2.World.new(0, 0, true)
 
local function onBeginContact(event)
	-- you can get the fixtures and bodies in this contact like:
	local fixtureA = event.fixtureA
	local fixtureB = event.fixtureB
	local bodyA = fixtureA:getBody()
	local bodyB = fixtureB:getBody()
 
	print("begin contact: "..bodyA.name.." "..bodyB.name)
end
 
local function onEndContact(event)
	-- you can get the fixtures and bodies in this contact like:
	local fixtureA = event.fixtureA
	local fixtureB = event.fixtureB
	local bodyA = fixtureA:getBody()
	local bodyB = fixtureB:getBody()
 
	print("end contact: "..bodyA.name.." "..bodyB.name)
end
 
local function onPreSolve(event)
	-- you can get the fixtures and bodies in this contact like:
	local fixtureA = event.fixtureA
	local fixtureB = event.fixtureB
	local bodyA = fixtureA:getBody()
	local bodyB = fixtureB:getBody()
 
	print("pre solve: "..bodyA.name.." "..bodyB.name)
end
 
local function onPostSolve(event)
	-- you can get the fixtures and bodies in this contact like:
	local fixtureA = event.fixtureA
	local fixtureB = event.fixtureB
	local bodyA = fixtureA:getBody()
	local bodyB = fixtureB:getBody()
 
	print("post solve: "..bodyA.name.." "..bodyB.name)
end
 
-- this is the list of physical entities
local actors = {}
 
local function createBox(x, y, name, image)
	local body = world:createBody{type = b2.DYNAMIC_BODY, position = {x = x, y = y}}
 
	body.name = name
 
	local shape = b2.PolygonShape.new()
	shape:setAsBox(40, 40)
	body:createFixture{shape = shape, density = 1, restitution = 0.2, friction = 0.3}
 
	local sprite = Bitmap.new(Texture.new(image))
	sprite:setAnchorPoint(0.5, 0.5)
	sprite:setPosition(x, y)
	sprite.body = body
	stage:addChild(sprite)
 
	actors[#actors + 1] = sprite
end
 
local ground = world:createBody({})
 
ground.name = "ground"
 
local shape = b2.EdgeShape.new(-200, 400, 520, 400)
ground:createFixture({shape = shape, density = 0})
 
 
createBox(_W/2, 300, "box1", "box.png")
createBox(0, 300, "box2", "green-box.png")
 
world:addEventListener(Event.BEGIN_CONTACT, onBeginContact)
world:addEventListener(Event.END_CONTACT, onEndContact)
world:addEventListener(Event.PRE_SOLVE, onPreSolve)
world:addEventListener(Event.POST_SOLVE, onPostSolve)
 
local function onEnterFrame()
	world:step(1/60, 8, 3)
 
	for i=1, #actors do
		local sprite = actors[i]
		local body = sprite.body
		-- inverted from the original example. In this case, body sets its position based on the sprite position
		body:setPosition(sprite:getPosition())
	end
end
 
stage:addEventListener(Event.ENTER_FRAME, onEnterFrame)
 
actors[2].tween = GTween.new(actors[2], 2, {x=_W})
However, when I move the eventlisteners from the world object to the crates I no longer see any output in the console - its the same code as above except world:addEventListener(Event.BEGIN_CONTACT, onBeginContact) becomes actors[1]:addEventListener(Event.BEGIN_CONTACT, onBeginContact), actors[2]:addEventListener(...) etc etc.

Obviously I'm doing something wrong - any ideas what?
And a follow-up question: what's the forum code to use to make the above example format properly?
Tagged:

Comments

  • To answer your follow-up question .... you can use: <pre lang="lua"> code goes here </pre>

    An example:
     
    _H = application:getDeviceHeight()
    _W = application:getDeviceWidth()
     
    require "box2d"
     
    b2.setScale(10)
     
    local sky = Bitmap.new(Texture.new("sky.png"))
    stage:addChild(sky)
     
    local grass = Bitmap.new(Texture.new("grass.png"))
    grass:setY(400)
    stage:addChild(grass)
  • Thanks @ndoss
    Have updated the post and now its much more readable!
  • My guess is that a sprite has no event listeners of these types.
  • Cheers, looks like you're right:
    http://giderosmobile.com/documentation/reference_manual_2011.9.html#Sprite

    Hmmm, so instead of having each object listening for a collision I should:
    1. add the collisions event listeners to the world
    2. When a collision does occur the world can then work out the bodies from the fixtures
    3. Work out what Sprite is connected to the body (???)
    4. Call a function on that Sprite so it can do it's magic

    Am I overthinking this? And if not, any ideas on how to accomplish step 3?
  • MikeHartMikeHart Guru
    edited January 2012
    Not at all, that is the fun of finding a solution. And the solution is very simple (but not tested).

    Answer to question 3:

    Just store the sprite into the body too.
    body.xSprite = sprite
  • Heh, it's so obvious once you take a step back but I was so focused on the sprite being the "parent" object that I couldn't see it.

    Thanks MikeHart!
Sign In or Register to comment.