Spawn a new Object and move it cross the screen.

Hi! I’m new to corona and programming in general. I’ve been working on a simple project and come across this road block.

I’m trying to spawn an object and move it across the screen from
X coordinate 480 —> X coordinate 0. A new object will spawn every 3 seconds and when one object moves pass X coordinate -50 then I want to remove it from the system, but I still want the others to be displayed and moved on the screen.
I don’t know how to setup the “function” to remove the object when it moves pass X coordinate -50.

I have tried a few methods, but they usually ended up removing all the objects.

One last issue with my codes. When the second object spawn, the first object stop moving and so forth. I highly appreciate any suggestions and helps anyone can provide me.
Long story short. Here are my noob codes:

[lua]-- display object and setup movement
local levelObject = function ()
local smallobject

smallobject = display.newImageRect(“smallobject.png”, 100, 51.5)
physics.addBody(smallobject, “dynamic”, {density = 1, friction =
0,bounce = 0 })
smallobject.x = 550
smallobject.y = math.random(50, 120)

levelGroup:insert(smallobject)
gameGroup:insert(levelGroup)

local function moveObject()
local speed = 1
smallobject.x = smallobject.x - speed
end

Runtime:addEventListener(“enterFrame”, moveObject)
end

– spawn object

local objectSpawner = function( event )

levelObject()

end

timer.performWithDelay(3000, objectSpawner, 10)

Runtime:addEventListener( “enterFrame”, objectSpawner )

[import]uid: 12455 topic_id: 4995 reply_id: 304995[/import]

here is another option… possibly it is more efficient because you’re not creating a separate killMe function for each dude instance (if you had lots of dudes and a bigger killMe function, in the original version you’d have more memory used up by each dude I think because each would have the killMe function attached to their table… I’m not sure but I think this is the case)

[lua]local function killMe(dudeToKill)
– transition.to passes the object as the onComplete parameter
dudeToKill:removeSelf()
end
local function makeDude()
local dude = display.newImageRect(“10.png”, 100, 100)
dude.x, dude.y = math.random(200, 300), math.random(50, 350)
transition.to(dude, {time=(dude.x-50)*30, x=50, onComplete=killMe})
end

timer.performWithDelay(500, makeDude, 10)[/lua] [import]uid: 6645 topic_id: 4995 reply_id: 16648[/import]

Wow, I didn’t know transition.to passes the object when it calls the onComplete function. Nice one, jmp909! :slight_smile:
[import]uid: 9659 topic_id: 4995 reply_id: 16653[/import]

I have two solutions for you.

The first method uses a table to track each sprite created. Each enterFrame event, it loops through the table and deletes the ones that passed x=50.

local dudes = {}  
  
local function makeDude()   
 local dude = display.newImageRect("10.png", 100, 100)  
 dude.x, dude.y = math.random(200, 300), math.random(50, 350)  
 dudes[#dudes+1] = dude  
end  
  
local function listener(event)  
 for i, v in pairs(dudes) do  
 if dudes[i].x \< 50 then  
 dudes[i]:removeSelf()  
 dudes[i] = nil  
 else  
 local speed = 1  
 dudes[i].x = dudes[i].x - speed  
 end  
 end  
end  
  
timer.performWithDelay(500, makeDude, 10)  
  
Runtime:addEventListener("enterFrame", listener)  

The second method is much smaller because it uses transition.to()

local function makeDude()  
 local dude = display.newImageRect("10.png", 100, 100)  
 dude.x, dude.y = math.random(200, 300), math.random(50, 350)  
 local function killMe()  
 dude:removeSelf()  
 end  
 transition.to(dude, {time=(dude.x-50)\*30, x=50, onComplete=killMe})  
end  
  
timer.performWithDelay(500, makeDude, 10)  

I had to calculate the time in transition.to() based on the distance from x=50 at sprite creation time. Also, you have to put killMe() inside makeDude() so it still has a reference to the “dude” object for the dude:removeSelf() call.

Hope that helps!

EDIT: Fixed typo in last paragraph.
[import]uid: 9659 topic_id: 4995 reply_id: 16617[/import]

Meh, I just realized I could have coded the pairs() loop in my first example a little better by using the 2nd value returned by pairs():

local function listener(event)  
 for i, dude in pairs(dudes) do  
 if dude.x \< 50 then  
 dude:removeSelf()  
 dudes[i] = nil  
 else  
 local speed = 1  
 dude.x = dude.x - speed  
 end  
 end  
end  

That saves a tiny fraction of time, and cleans up the code a bit.

You still need to use dudes[i] when you’re setting an item in the table to nil, though. If you said “dude=nil” you’d be clearing the local reference, not the item in the table.
[import]uid: 9659 topic_id: 4995 reply_id: 16666[/import]

Thank you for your helps, guys.

I tried both methods. The transition method worked great.

For some reasons, the
[lua]for i, v in pairs(table) do [/lua] is not working for me.
I don’t know what I did wrong, but whenever a new object spawn, the
“moving speed” of the new and old objects are increased.

[import]uid: 12455 topic_id: 4995 reply_id: 20100[/import]

How can I remove the transition.to if dude is removed in a collision before
It reaches x=50? I’m getting and error saying attempt to perform
removeSelf a nil value. [import]uid: 12455 topic_id: 4995 reply_id: 20227[/import]

transition.cancel()
http://developer.anscamobile.com/reference/index/transitioncancel
[import]uid: 9659 topic_id: 4995 reply_id: 20230[/import]

i tried using the transition.cancel, but it didn’t work.

if the flyingobject is removed with a collision before the transition is completed, then it gives me an error saying attempt to call method ‘removeSelf’ a ‘nil value’. Basically, the onComplete transition will try to remove the flyingobject again from my understanding.

how to solve this issue? or should i just setup an invisible wall to remove the flyingobject on collision as it was done by another developer?

Please help someone, I’ve been stuck on this one for days…LOL
here’s an
example of my code:
Note: I did not include the cannonball code in this example.

[lua]local flyingobject

local removeflyingObject = function (obj)

obj:removeSelf()
end

local createflyingObject = function ()
flyingobject = display.newImageRect(“flyingobject.png”, 50, 50)
flyingobject.x = 560
flyingobject.y = math.random(50, 120)
flyingobject.objectName = “flyingobject”
physics.addBody(flyingobject, “static”, {density = 1})

transition.to(flyingobject, {time=(flyingobject.x-200)*30, x=50, onComplete=removeflyingObject})

localGroup:insert(flyingobject)
end

local onCollision = function (self, event)
if event.phase == “began” then
if event.other == “flyingobject” then
transition.cancel(flyingobject)
event.other:removeSelf()
event.other = nil
self:removeSelf()
self = nil
end
end
end

local firstSpawn = timer.performWithDelay(1, createflyingObject, 1)
local secondSpawn = timer.performWithDelay(2500, createflyingObject, 3) [import]uid: 12455 topic_id: 4995 reply_id: 20327[/import]

  1. you’re trying to create multiple flying objects but using only 1 overall flyingobject variable. make flyingobject local to your spawn function and if you need access to it outside of the spawn function, add it to an array that is defined outside of your spawn function

eg

[lua]local flyingobjects = {}

local function spawn()
local flyingobject = display.newImage(“ufo.png”)

– use object’s table address as an array index,
– so you can remove it easily later
local id = tostring(flyingobject) – eg “9A0BD13”
flyingobjects[id] = flyingobject
end[/lua]

dont forget to remove the object from the array when it is destroyed.

  1. it should be
    [lua]if(event.other.objectName==“flyingobject”)[/lua]

  2. if another operation can remove the object, eg collision then you need to check if the object is nil (ie already removed) before attempting another operation on it

  3. you need to call transition.cancel on the transition reference, not the object as detailed here: http://developer.anscamobile.com/reference/index/transitioncancel

eg [lua]flyingObject.myTransition=transition.to(flyingobject, {time=(flyingobject.x-200)*30, x=50, onComplete=removeflyingObject})[/lua]

then

[lua]transition.cancel(event.other.myTransition)[/lua] [import]uid: 6645 topic_id: 4995 reply_id: 20329[/import]

Thank Thank Thank JMP909. You solved my life long struggle…LOL. I didn’t use the table, but the flyingObject.myTransition = transition.to
works perfect.

I’ll post the result later today.

This worked for me. Any errors?

[lua]greendragon = sprite.newSpriteSheetFromData ( “greendragon.png”, require(“greendragon”).getSpriteSheetData() )
greendragonSet = sprite.newSpriteSet( greendragon, 1, 4 )
sprite.add( greendragonSet, “greendragon”, 1, 4, 1000, 0 )

–**************************************************************************************************
local removedragon = function (self)
self:removeSelf()
self = nil
end

local createDragons = function()
local greendragonInstance = sprite.newSprite(greendragonSet)
greendragonInstance.x = 490
greendragonInstance.y = mRand(50, 120)
greendragonInstance.objectName = “greendragonInstance”
greendragonInstance.isVisible = true

greendragonInstance.myTransition = transition.to(greendragonInstance, {time=(greendragonInstance.x-200)*30, x=50, onComplete=removedragon})

physics.addBody(greendragonInstance, “static”, { density = 0, friction = 0, bounce = 0 })

levelGroup:insert(greendragonInstance)
gameGroup:insert(levelGroup)

greendragonInstance:prepare(“greendragon”)
greendragonInstance:play()

end
–===================== Move Dragon ===================================================

local firstspawnerTimer = timer.performWithDelay(1, createDragons, 1)
local spawndragonTimer = timer.performWithDelay(2500, createDragons, 5)
local thirdspawnerTimer = timer.performWithDelay(4000, createDragons, 5)

local onDragonCollision = function ( self, event )

if event.phase == “began” then

if event.other.objectName == “greendragonInstance” then
transition.cancel(event.other.myTransition)
event.other:removeSelf()
event.other = nil
self:removeSelf()
self = nil
end
end
end [import]uid: 12455 topic_id: 4995 reply_id: 20397[/import]

seems like i can use the transition.to method, but not the table{} method. For some reasons, I can’t seem to get it right.

What I want to do:

  1. spawn multiple objects from the same source.
  2. move it across the screen.
  3. whichever object gets hit by cannonball then remove that object.
  4. if object reaches the other side of the screen, the remove object also.

Issue i’m having:

  1. if one of the object is hit by a cannonball, all the others are removed along with it. However, when the object reaches the other side, it gets remove just fine, individually.

many thanks to all your helps in advance.

[lua]local flyingobjects = {}

local onFlyingCollision = function (self, event)
if event.phase == “began” then
if event.other.objectName == “flyingobject” then

event.other:removeSelf()
end
end
end

local createFlyingObject = function ()
local flyingobject = display.newImageRect(“watever.png”, 50, 50)
physics.addBody(flyingobject, “static”)
flyingobject.x = 490
flyingobject.y = math.random(100,120)
flyingobject.objectName = “flyingobject”

flyingobjects[#flyingobjects + 1] = flyingobject
end

local spawnTimer = timer.performWithDelay(1000, createFlyingObject, 4)

local flyingEnterFrame = function ()

for k = #flyingobjects, 1, -1 do

local theY = flyingobjects[k].y + math.sin(flyingobjects[k].x/40)*2
if flyingobjects[k].x < 50 then
flyingobjects[k]:removeSelf()
table.remove(flyingobjects, k)

else
flyingobjects[k].x = flyingobjects[k].x - dx
flyingobjects[k].y = theY

end
end

Runtime:addEventListener(“enterFrame”, flyingEnterFrame)
[import]uid: 12455 topic_id: 4995 reply_id: 21447[/import]

you havent posted your collision setup so dont know. you’ve only posted the actual collision function, not how it is called [import]uid: 6645 topic_id: 4995 reply_id: 21619[/import]

this is what I have:

when the collision occurs, the other spawned flyingobject stop moving.

What did I do wrong?

[lua]local flyingobjects = {}

local onFlyingCollision = function (self, event)
if event.phase == “began” then
if event.other.objectName == “flyingobject” then
self:removeSelf()
event.other:removeSelf()
end
end
end

– asumming I have the cannonball code here
cannonball.collision = onFlyingCollision
cannonball:addEventListener(“collision”, cannonball)

local createFlyingObject = function ()
local flyingobject = display.newImageRect(“watever.png”, 50, 50)
physics.addBody(flyingobject, “static”)
flyingobject.x = 490
flyingobject.y = math.random(100,120)
flyingobject.objectName = “flyingobject”

flyingobjects[#flyingobjects + 1] = flyingobject
end

local spawnTimer = timer.performWithDelay(1000, createFlyingObject, 4)

– i modified the enterframe code a little bit, but
– still get the same issue.

local flyingEnterFrame = function ()

for k, v in pairs (flyingobjects) do

local theY = flyingobjects[k].y + math.sin(flyingobjects[k].x/40)*2
if flyingobjects[k].x < 50 then
flyingobjects[k]:removeSelf()
table.remove(flyingobjects, k)

else
flyingobjects[k].x = flyingobjects[k].x - dx
flyingobjects[k].y = theY

end
end
end

Runtime:addEventListener(“enterFrame”, flyingEnterFrame)
Edit:
Nevermind, I solved it. If anyone is carious about the code, let me know and I’ll post it here.
[import]uid: 12455 topic_id: 4995 reply_id: 21788[/import]

yellowbanner
Can you please share the code, I am having a similar problem.
instead of removing one object after collision, the entire spawned object from the same source are removed [import]uid: 40990 topic_id: 4995 reply_id: 25020[/import]

I would also love to see all the code! Thanks a lot! [import]uid: 9968 topic_id: 4995 reply_id: 26043[/import]

when you remove elements from your table like that the value for the next k no-longer refers to the item it would have referred to before, since you’ve shifted all the elements by removing 1 in the middle

try this ( at http://www.lua.org/cgi-bin/demo )

[lua]local flyingobjects = {}
flyingobjects[#flyingobjects+1] = “one”
flyingobjects[#flyingobjects+1] = “two”
flyingobjects[#flyingobjects+1] = “three”
flyingobjects[#flyingobjects+1] = “four”
flyingobjects[#flyingobjects+1] = “five”

for k, v in pairs (flyingobjects) do
print(k,v)
if(v==“one”) then
print("found one at "…k)
table.remove(flyingobjects,k)
elseif(v==“two”) then
print("found two at "…k)
table.remove(flyingobjects,k)
elseif(v==“three”) then
print("found three at "…k)
table.remove(flyingobjects,k)
elseif(v==“four”) then
print("found four at "…k)
table.remove(flyingobjects,k)
end
end

print("—")

for k, v in pairs (flyingobjects) do
print(k,v)
end[/lua]

you get this:

[lua]1 one
found one at 1
2 three
found three at 2
3 five

1 two
2 four
3 five[/lua]

you need to loop over your table backwards so that when you remove an item none of the others are shifted

this is documented here:
http://developer.anscamobile.com/content/application-programming-guide-graphics-and-drawing#Common_Pitfalls

[import]uid: 6645 topic_id: 4995 reply_id: 26046[/import]

Jmp909, what if i have 10,000 spawned objects? do i need 10,000 if statements [import]uid: 40990 topic_id: 4995 reply_id: 26124[/import]

err no… that was just an example to explain what was wrong with the table.remove code above [import]uid: 6645 topic_id: 4995 reply_id: 26125[/import]

I’m sorry to post to old topic. I’m facing the same issue. teex84, can you share the code? Thank you.

Steve [import]uid: 84159 topic_id: 4995 reply_id: 52508[/import]