How to trigger this event listener

Hi Dave,

Thanks for the repply.

But how can I make any declared variable a member of the SpriteObject?

I also need to use my declared variable that triggeres an animation (e.g. e:setSequence(“walking”))

local function cowboys (event) local e = Cowboy:new() e.x = 48 e.y = math.random (600,800) e.rotation = 90 physics.addBody (e,"static") local removeE = function () display.remove (e) end transition.to (e,{time = 20000,y = -50,onComplete = removeE}) return e end 

And also on the collision function :

local varE = cowboys() local function onCollisionWithCowboy (self,event) if event.phase == "began" then varE:setSequence ("shooting") varE:play() end end 

And this is the Cowboy.lua fie.:

Cowboy = {} function Cowboy:new() local self = display.newGroup() local sheetData = {width = 70,height = 107,numFrames = 14,sheetContentWidth = 140,sheetContentHeight = 749} local mySheet = graphics.newImageSheet ("cowboy.png",sheetData) local sequenceData ={ {name = "shooting",frames = {9,10,11,12,13,14},time = 1000,loppcount = 1}, {name = "cowboyWalking", start = 1,count = 8,time = 1200,loopcount = 0} } local cowboy = display.newSprite (mySheet,sequenceData) self:insert(cowboy) return self end return Cowboy

Thanks!

The whole trick is how to figure out how to use the :setSequence() method inside those two functions.But how?

Try this:

[lua]

local function cowboys()
    local sp = Cowboy:new()[1]
    sp.x = 48
    sp.y = math.random(600,800)
    sp.rotation = 90
    physics.addBody(sp, “static”)

    local removeE = function()
        display.remove(sp)
    end

    transition.to(sp, {time=20000, y=-50, onComplete=removeE})

    return sp
end

local varE = cowboys()

local function onCollisionWithCowboy(event)
    if event.phase == “began” then
        varE:setSequence(“shooting”)
        varE:play()
    end
end

Runtime:addEventListener(“collision”, onCollisionWithCowboy)
[/lua]

Btw, I’d suggest using a different variable name than “self”, such as:

[lua]Cowboy = {}

function Cowboy:new()
    local grp = display.newGroup()

    local sheetData = {width=70, height=107, numFrames=14, sheetContentWidth=140, sheetContentHeight=749}
    local mySheet = graphics.newImageSheet(“cowboy.png”, sheetData)

    local sequenceData = {
        {name=“shooting”, frames={9,10,11,12,13,14}, time=1000, loopcount=1},
        {name=“cowboyWalking”, start=1, count=8, time=1200, loopcount=0}
    }

    local cowboy = display.newSprite(mySheet, sequenceData)
    grp:insert(cowboy)

    return grp
end

return Cowboy
[/lua]

Hi Dave,

  I tried it and it works only with the first spawned cowboy,and I don’t know why it doesn’t work with the rest of them.Any idea?

Thanks,

Bogdan

Each cowboy object needs to listen to the collision event. So this should do it:

[lua]

local function onCollisionWithCowboy(self, event)
    if event.phase == “began” then
        self:setSequence(“shooting”)
        self:play()
    end
end

local function cowboys()
    local sp = Cowboy:new()[1]
    sp.x = 48
    sp.y = math.random(600,800)
    sp.rotation = 90
    physics.addBody(sp, “static”)

    sp.collision = onCollisionWithCowboy
    sp:addEventListener(“collision”, sp)

    local removeE = function()
        display.remove(sp)
    end

    transition.to(sp, {time=20000, y=-50, onComplete=removeE})

    return sp
end

[/lua]

Thanks mate,but it didn’t worked.

I gues I’ll go ahead and do this the old way,adding each object andtrigger it’s event listeners manually.

I think you have a scoping problem. It’s a bit hard to tell because of the formatting. Your variable ‘crate’ needs to be a member of the object.  ‘crate’ is only in scope on onSpawn(). The crate stuff needs to be member variables - something like this code will create and dispose of it. 

This allows you to write further methods which act on the crate object, so for example you can write something like the Crate:transition() method below.

function Crate:new() self.m\_group = display.newGroup() self.m\_image = display.newImage("Icon.png") self.m\_group:insert(self.m\_image) end function Crate:dispose() self.m\_group:removeSelf() self.m\_group = nil self.m\_image = nil end

function Crate:transition() transition.to(self.m\_group, { x = 132,y = 412, time = 3000, onComplete = function() self:dispose() }) end

This function works because closures another very important lua context , basically because onComplete is a local function it keeps the scope at the point it was created so ‘self’ maintains the value and disposes the correct crate object.

This allows you to write things like:

local c1 = Crate:new() c1:transition()

Which will create a crate, transition it and then it disposes of itself (via the onComplete) - if you want 38 of them, just do it in a for loop. Whether you keep track of references or not depends on what you are doing.

The important thing is to encapsulate stuff relating to the crate in the crate method, so you have a ‘crate’ object which knows everything about ‘crates’ and has as little knowledge of non-crate things as possible. If you look at a lot of Corona code it is chaos with responsibility for things thrown all over the place, then when things get confusing it breaks because it’s impossible to figure out who is responsible for what.

Now, with regard to listeners and objects. It doesn’t work very well if you do it with functions, but Corona has the ability to apply listeners to objects, by passing the object reference rather than a function. 

So if you put :

c1.m\_group:addEventListener("tap",c1)

when the listener fires it by tapping on c1 doesn’t call a function , because c1 isn’t one - it’s an object, so it calls the object method c1:tap instead.  This is pretty much mandatory for objects, trying to do it with functions is just asking for troubles. I have no idea whether this works for physics listeners because I do not use them.

Hi mate,

 Thanks for the answer.I tried your code and it gives me an error. I put your code in the Crate.lua file and did a for loop so I can have my crate spawned,and here it is.

local function onSpawn (event) for i = 0,0 do local c1 = Crate:new() c1.x = math.random (50,350) c1.y = 400 end end timer.performWithDelay (9000,onSpawn,0)

Untitled-8.jpg

Bogdan,

You need to return Crate like this:

[lua]
– Crate.lua

local Crate = {}

function Crate:new()
    local self = display.newGroup()
    self:insert(display.newImage(“crate.png”))
    return self
end

return Crate

[/lua]

And “static” bodies don’t collide with other static bodies, so you can try “dynamic”:

[lua]
local Crate = require “Crate”

local physics = require “physics”
physics.start()
physics.setGravity(0,0)

local w = display.actualContentWidth
local halfH = display.contentCenterY

local function onSpawn(event)
    local crate = Crate:new()
    physics.addBody(crate, “dynamic”)
    crate.x = math.random(60, w-60) – crate.png is 60x60 pixels
    crate.y = halfH

    local removeCrate = function()
        display.remove(crate)
        crate = nil
    end

    transition.to(crate, { time=5000, x=0, onComplete=removeCrate })
end

timer.performWithDelay(2500, onSpawn, 0)

local function onCollision(event)
    if event.phase==“began” then
        print(“It works!”)
    end
end

Runtime:addEventListener(“collision”, onCollision)

[/lua]

You may want to deal with the crates after they collide (and crate.png can be found at the CoronaSDK/SampleCode/Physics/HelloPhysics folder).

Cheers,

Dave

I use this though there are lots of variations on a theme.

\_G.Base = \_G.Base or { new = function(s,...) local o = { } setmetatable(o,s) s.\_\_index = s o:initialise(...) return o end, initialise = function() end }

Defines a ‘class’ Base which can be extended.

Dave,
Thank you for the answer,but I want the collision event to be triggered by the crate. How can I do that?
Regards,
Bogdan

Did you try the code I posted? The crates are colliding and are triggering the event.

Dave,

  Yes I tried your code,and it works.Thank you :wink:

I haven’t expressed myself correct and didn’t explained you all the problem,I apologize for that.

I want my crate to colide with a laser beam.

The laser beam should colide with the crate and another circle,three diiferent objects.

The laser beam is a dynamic object and the crate and the circle are static objects.

So when the laser beam colides with the crate something should happen (an explosion animation will be triggered)

And when the laser beam colides with the circle,something else should happen (a sound wave will be triggered).

Please note that I use storyboard.

Regards,

Bogdan

local beam = display.newImageRect("Beam.png" ,90,200) physics.addBody (beam,"dynamic")

Hey guys,

 I fixed the collision problem! It was something relative simple.But now I moved from the prototype to the real game,and I am having some problems on loading the sprite sheet.Thank you.

cow = {} function cow:new() local self = display.newGroup() self:insert ( local sheetData = {width = 100,height = 100,numFrames = 14,sheetContentWidth = 200,sheetContentHeight = 700} local mySheet = graphics.newImageSheet ("cow.png",sheetData) local sequenceData = {{name = "cowOne2",start = 1,count = 8,time = 1000,loopcount = 0}, {name = "cowBeaming",frames = {9,10,11,12,13,14},time = 1000,loopcount = 0}} local cowOne = display.newSprite (mySheet,sequenceData) ) return self end 

Untitled-9.jpg

You can’t insert statements into a group. Try something like this:

[lua]
– cow.lua

local cow = {}

function cow:new()
    local self = display.newGroup()

    local sheetData = { width=100, height=100, numFrames=14, sheetContentWidth=200, sheetContentHeight=700 }
    local mySheet = graphics.newImageSheet(“cow.png”, sheetData)
    local sequenceData = {{ name=“cowOne2”, start=1, count=8, time=1000, loopcount=0 },

      { name=“cowBeaming”, frames={9,10,11,12,13,14}, time=1000, loopcount=0 }}
 

    self:insert(display.newSprite(mySheet, sequenceData))

    return self
end

[/lua]

Hi Dave,

Thanks it worked,but now I have another two issues.

  1. I have an error that say “attempted to call method “setSequence” a nil value”

  2. How can I start the function (with the timer) in order that my for loop would work,I tried with a touch event and it worked,but with the timer.performWithDelay,I can’t get it to work,why?

Thank you very much!

-- cow.lua file local cow = {} function cow:new() for i = 1,2 do local self = display.newGroup() local sheetData = { width=100, height=100, numFrames=14, sheetContentWidth=200, sheetContentHeight=700 } local mySheet = graphics.newImageSheet("cow.png", sheetData) local sequenceData = {{ name="cowOne2", start=1, count=8, time = 1000, loopcount = 0 }, { name="cowBeaming", frames={9,10,11,12,13,14}, time=1000, loopcount = 0 }} self:insert(display.newSprite(mySheet, sequenceData)) self.x = 38 self.y = math.random (0,500) self.rotation = 90 self:setSequence ("cowOne2") self:play() physics.addBody (self,"static") self.gravityScale = 0 self.isSensor = true self:setLinearVelocity (0,0) local removeCow = function () display.remove (self) self = nil end transition.to (self,{time = 10000,y = 10,onComplete = removeCow }) return self end end timer.performWithDelay (2000,cow:new(),0)

setSequence() is a method of the SpriteObject, and ‘self’ in your code is a display group; that’s why it’s nil.

Please refer to: http://docs.coronalabs.com/api/type/SpriteObject/setSequence.html

I haven’t tested the following, but try changing the code like this:

[lua]local cowOne = display.newSprite (mySheet,sequenceData)
self:insert(cowOne)

self.x = 38
self.y = math.random (0,500)
self.rotation = 90
cowOne:setSequence (“cowOne2”)
cowOne:play()[/lua]

And for the 2nd issue, would the following work?

[lua]local function newCow()
    return cow:new()
end

timer.performWithDelay (2000, newCow, 0)[/lua]

Hi Dave,

  Thank you very much it worked! But for some wierd reasons I don’t know why the collision event doesn’t work with all the spawned objects.It works only with one cow,but the rest of the spawned cows it doesn’t. Any ideas?

UPDATE:

I manage to fix the collision,butI have a doubt on how to get my collision event to be triggered by the cow.

In my game there will be a cow and a cowboy,and when the laser beam hits the cow an animation should start and when the laser beam hits the cowboy a different animation should start.

Thanks

local function cows (event) local c = Cow:new() c.x = 100 c.y = math.random (0,500) physics.addBody (c,"static") end local function spawning (event) for i = 0,0 do cows() end end local function onCol (event) if event.phase == "began" then print ("works") end end timer.performWithDelay (10000,spawning,0) Runtime:addEventListener ("collision",onCol)

From the code you provided, I can’t tell how your cowboy and laser are set up. Because you are only creating static bodies here, collision won’t happen between them as mentioned previously.

You may want to familiar yourself with this: http://docs.coronalabs.com/guide/physics/collisionDetection/index.html

Dave