Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

How to trigger this event listener
Started by bogdanmocanu2 Oct 23 2014 10:12 AM

- - - - -
25 replies to this topic
[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

Hey guys,

 

  I am trying to get my collision event to be triggered by the local variable crate,but I cannot find a way.So please help me.Thank you.

Also if I create another local function and place my crate variable in there,the transition doesn't work,I tried and it gives me an error when I try to triger the collision event using that function.

 

My Main.lua file :

require ("Crate")

local physics = require ("physics")
physics.start()
physics.setGravity (0,0)

local function onSpawn (event)
for i = 0,0 do 
local crate = Crate:new()
physics.addBody (crate,"static")
crate.x = math.random (50,300)
crate.y = 450

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

cIntro = transition.to (crate,{time = 20000,x = 0,onComplete = removeCrate})
end 
end 
timer.performWithDelay (9000,onSpawn,0)

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


Runtime:addEventListener ("collision",onCollision)

And here is the Crate.lua file :

Crate = {}

function Crate:new()
  local self = display.newGroup()
  self:insert(display.newImage("Icon.png"))
  
  return self
end

The tutorial I followed: http://lazywombat.co.uk/object-oriented-programming-in-corona-sdk-part-1-basics/



[TOPIC: post.html]
#2

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

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.



[TOPIC: post.html]
#3

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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



[TOPIC: post.html]
#4

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

Bogdan,

 

You need to return Crate like this:

 

-- Crate.lua
 
local Crate = {}
 
function Crate:new()
    local self = display.newGroup()
    self:insert(display.newImage("crate.png"))
    return self
end
 
return Crate

 

And "static" bodies don't collide with other static bodies, so you can try "dynamic":

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)

 

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

 



[TOPIC: post.html]
#5

paulscottrobson

[GLOBAL: userInfoPane.html]
paulscottrobson
  • Contributor

  • 456 posts
  • Corona SDK

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.



[TOPIC: post.html]
#6

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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

[TOPIC: post.html]
#7

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

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



[TOPIC: post.html]
#8

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

Dave,

 

  Yes I tried your code,and it works.Thank you ;)

 

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")


[TOPIC: post.html]
#9

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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



[TOPIC: post.html]
#10

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

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

 

-- 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



[TOPIC: post.html]
#11

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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)


[TOPIC: post.html]
#12

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

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:

 

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()

 

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

 

local function newCow()
    return cow:new()
end
timer.performWithDelay (2000, newCow, 0)



[TOPIC: post.html]
#13

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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:

 

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()

 

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

 

local function newCow()
    return cow:new()
end
timer.performWithDelay (2000, newCow, 0)

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?



[TOPIC: post.html]
#14

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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)


[TOPIC: post.html]
#15

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

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



[TOPIC: post.html]
#16

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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

Hey Dave,

 

  I fixed the collision problem.The laser beam is a dynamic object and the cows are static objects.The cow is a sprite object declared in another file.

But how do I get the cow to trigger the collision event? 

I can do this in two ways:

1. Declaring the cow as a global variable,,if I choose this option how can I make my for loop to work?

2. declaring in in a local function,as a local variable,but if I choose the second option it will give me a nil value when I call the seSequence method.

Thank you!

local beam = display.newImageRect("Beam.png" ,90,200)
beam.rotation = 90
beam.isVisible = false
physics.addBody (beam,"dynamic")
beam.gravityScale = 0
beam.isSensor = true
beam:setLinearVelocity (0,0)

-- This is the first method that I used.

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)


[TOPIC: post.html]
#17

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

Return the cow:

 

local function cows (event)
    local c = Cow:new()
    c.x = 100
    c.y = math.random (0,display.contentHeight)
    physics.addBody (c,"static")
    return c
end

 

And add this to test:

 

local beam = display.newImageRect("Beam.png" ,90,200)
beam.rotation = 90
beam.isVisible = false
physics.addBody(beam,"dynamic")
beam.gravityScale = 0
beam.isSensor = true
beam:setLinearVelocity(0,0)
beam.x, beam.y = display.contentWidth,500
 
local function fireLaser(event)
    beam.isVisible = true
    beam:setLinearVelocity(-2000,0)
end
 
Runtime:addEventListener("touch", fireLaser)

 

Touch the screen when there's a cow at the same height (500) as the laser to see if it works.

 

BTW, I'm not sure why you have a loop like this: 

for i = 0,0 do

 

Dave



[TOPIC: post.html]
#18

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

Hi Dave,

 

  I have a different function that activates the beam and the only way this can work is via the collision event.I also tried non physics collision with no luck.

 

 

If I create a global variable for example :

var = cows()

and then to run the collision event:

var.collision = onCollision
Runtime:addeventListener ("collision",onCollision)

Hope this will help me.I'll come back with an update.

Thank you,

Bogdan



[TOPIC: post.html]
#19

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

Return the cow:

 

local function cows (event)
    local c = Cow:new()
    c.x = 100
    c.y = math.random (0,display.contentHeight)
    physics.addBody (c,"static")
    return c
end

 

And add this to test:

 

local beam = display.newImageRect("Beam.png" ,90,200)
beam.rotation = 90
beam.isVisible = false
physics.addBody(beam,"dynamic")
beam.gravityScale = 0
beam.isSensor = true
beam:setLinearVelocity(0,0)
beam.x, beam.y = display.contentWidth,500
 
local function fireLaser(event)
    beam.isVisible = true
    beam:setLinearVelocity(-2000,0)
end
 
Runtime:addEventListener("touch", fireLaser)

 

Touch the screen when there's a cow at the same height (500) as the laser to see if it works.

 

BTW, I'm not sure why you have a loop like this: 

for i = 0,0 do

 

Dave

UPDATE

 

I manage to fix the collision problem.Thank you for the help.

But still having this issue.

And you can find the setSequence method in cowboys function and onCollisionWithCowboy function.

Thank you!

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


local function cowboySpawning (event)
for i = 0,0 do 
cowboys()
end 
end 


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

 

Untitled-10.jpg



[TOPIC: post.html]
#20

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

As I mentioned before: setSequence() is a method of the SpriteObject.

 

And it looks like e is not a SpriteObject from this statement:

 

local e = Cowboy:new()



[TOPIC: post.html]
#21

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

As I mentioned before: setSequence() is a method of the SpriteObject.

 

And it looks like e is not a SpriteObject from this statement:

 

local e = Cowboy:new()

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!



[TOPIC: post.html]
#22

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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



[TOPIC: post.html]
#23

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

Try this:

 

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)

 

Btw, I'd suggest using a different variable name than "self", such as:

 

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



[TOPIC: post.html]
#24

bogdanmocanu2

[GLOBAL: userInfoPane.html]
bogdanmocanu2
  • Contributor

  • 124 posts
  • Corona SDK

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



[TOPIC: post.html]
#25

Quantumwave

[GLOBAL: userInfoPane.html]
Quantumwave
  • Contributor

  • 113 posts
  • Corona SDK

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

 

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




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]