Tower Defense type game: spawning and moving enemies

Hi guys this is my first post on the forums now that I have been developing with Corona for about a month and loving it!

I have learned a great deal so I decided to try my hand at developing a tower defense game. I have a very basic map and have created an enemy tank object that goes through the path at a certain speed that I set. My problem comes when I try to create several instances of the enemy object with delay of about 1 second between each “spawn” and make each still follow the path. I have done a lot of research and am at a loss on how to fix this:( Here is my code with only one enemy tank that goes through the course without fail. Any help would be greatly appreciated!!

Map: The red dots are used as guidance pints for the tanks.



[code]
-----------------------------------------------------------------------------------------

– level1.lua

-----------------------------------------------------------------------------------------

local storyboard = require( “storyboard” )
local scene = storyboard.newScene()

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

--------------------------------------------

– forward declarations and other locals
local screenW, screenH, halfW, halfH = display.contentWidth, display.contentHeight, display.contentWidth0.5, display.contentHeight0.5

-----------------------------------------------------------------------------------------
– BEGINNING OF YOUR IMPLEMENTATION

– NOTE: Code outside of listener functions (below) will only be executed once,
– unless storyboard.removeScene() is called.

-----------------------------------------------------------------------------------------

– Called when the scene’s view does not exist:
function scene:createScene( event )
local group = self.view

pointersGroup = display.newGroup()
mapGroup = display.newGroup()

map = display.newImage( “map.png” )
map:setReferencePoint(display.TopLeftReferencePoint)
map.x = 0
map.y = 0

spawner = display.newImage(“pointer.png”)
spawner:setReferencePoint(display.CenterReferencePoint)
spawner.y = 200
spawner.x = -100

pointer1 = display.newImage(“pointer.png”)
pointer1:setReferencePoint(display.CenterReferencePoint)
pointer1.x = 280
pointer1.y = 200

pointer2 = display.newImage(“pointer.png”)
pointer2:setReferencePoint(display.CenterReferencePoint)
pointer2.x = 280
pointer2.y = 360

pointer3 = display.newImage(“pointer.png”)
pointer3:setReferencePoint(display.CenterReferencePoint)
pointer3.x = 520
pointer3.y = 360

pointer4 = display.newImage(“pointer.png”)
pointer4:setReferencePoint(display.CenterReferencePoint)
pointer4.x = 520
pointer4.y = 120

tank = display.newImage(“tank.png”)
tank:setReferencePoint(display.CenterReferencePoint)
tank.x = spawner.x
tank.y = spawner.y
tank.rotation = 90

– all display objects must be inserted into group

pointersGroup:insert( spawner )
pointersGroup:insert( pointer1 )
pointersGroup:insert( pointer2 )
pointersGroup:insert( pointer3 )
pointersGroup:insert( pointer4 )
mapGroup:insert( map )
mapGroup:insert( tank )
group:insert( mapGroup )
group:insert( pointersGroup )

end

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

function moveTank ()
local speed = 10

if(tank.x < pointer1.x)then
tank.x = tank.x + speed
end
if(tank.x == pointer1.x and tank.y >= pointer1.y)then
tank.rotation = 180
tank.y = tank.y + speed
end
if(tank.y == pointer2.y and tank.x >= pointer2.x)then
tank.rotation = 90
tank.x = tank.x + speed
end
if(tank.x == pointer3.x and tank.y <= pointer3.y)then
tank.rotation = 0
tank.y = tank.y - speed
end
if(tank.x >= pointer4.x and tank.y == pointer4.y)then
tank.rotation = 90
tank.x = tank.x + speed
end
end
timer.performWithDelay(10, moveTank, 0)

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 [import]uid: 118482 topic_id: 26218 reply_id: 326218[/import]

Take a look here: http://developer.anscamobile.com/code/pathfinding-demo. That is probably the best, most efficient way to go for a game like yours. [import]uid: 63320 topic_id: 26218 reply_id: 106319[/import]

Yes I’ve seen it and it’s a good method for complex maps, but mine is very very simple so I think using the “pointer” objects is better for this example.

The problem happens though when I try to spawn multiple instances of the “tank” object and make each one follow the path according to its own personal location. I feel like the problem is because once i make several instances of the object, I cannot identify each instance individually and therefor my movement script fails. I know I could make several tank objects manually, but that is ineffective when trying to make an endless “wave” based game. Instead I want to build an algorithm that spawns a certain number of tanks depending on which “wave” it is.

Could anyone help please? [import]uid: 118482 topic_id: 26218 reply_id: 106334[/import]

Just my quick thoughts on this to hopefully get you started.

First, try to check out the forums here for discussions about OOP (object oriented) because I believe that is the way to go. Making each of your tanks a separate object, you can control individually. Although Lua is supposedly not a true OOP, there is some varied opinions out there on how to make it OOP. I think OOP is the best way to go, it is just a little more complicated to setup initially. But if this is going to be very basic and simple, not a lot of sprites and upgrades etc… it should work just as well maybe to keep it simple and make all in one file. Create a ‘table’ of tank images, instead of going OOP. In a very broad sense, the table substitutes for what oop would refer to as a class, and each tank element of the table is like an object of the class. In any case, you can control each of these tanks individually.
In this scene level1.lua, at the top somewhere, create a table

local tanks = {}

just below that create a variable to track the tanks set in motion

local tankCnt = 0

just below it create a timer value to check against spawnTime in the game loop that will pace the spawning of the tanks
(research to see which timer method you like the most)
Then, in enterScene function load the table with your tanks…
for i = 1, 5 do
table.insert(display.newImage(“tank.png”)
– set each tank position somewhere off the screen. (same position to start is okay)
– add these values to each image
tanks[i].isAlive = true
tanks[i].isMoving = false – set to false until timer is checked in game loop and sets it true
end

Just above the CreateScene function add a gameLoop function
local function gameLoop(event)
– this will work as long as there are not a lot of sprites to check on
– once it gets to heavy, the loop will end before all items are checked
– there are much better ways to do this, but this is just a quick simple way
– so you can see the spawning work and each tank move individually

– first check to see if timer has passed whatever time you want as a spawning time
– if it has, use tankCnt variable to call the proper tank object from the
– tanks table, to set it in motion
if timer > spawnTime then
tankCnt = tankCnt + 1
– add some code her to make sure to reset tankCnt, or end the wave, or end the level
– etc… so the code does not try to call tanks outside he limits of the table size
tanks[tankCnt].isMoving = true
end
for i = 1, #tanks do
if tanks[i].isAlive and tanks[i].isMoving then
– update tanks movement
– each tank will have started spawn time later then the tank before it
– so as you update each here they should drove along in a uniform line
end
end

end

in enterScene function
add this code : Runtime:addEventListener(“enterFrame”, gameLoop)

in exitScene function
* be sure to clear the tanks table of all it’s elements (research on best/correct method to do that)
add this code : Runtime:removeEventListener(“enterFrame”, gameLoop)

** there are better ways, and certainly cleaner ways, but hopefully this will help you out getting to figure things out.

I hope this helps! [import]uid: 148857 topic_id: 26218 reply_id: 106346[/import]

Thanks for the help, it seems like a good idea. I have one question though. When I insert the tank images into the table, when I need to add motion to them to move them through the map, how do I refer to and distinguish between each individual image? Sorry if this is a noob question, I am not good with tables! :0 [import]uid: 118482 topic_id: 26218 reply_id: 106359[/import]

Each tank will be an element of the table… each tank created can be accessed by

tanks[1] –
tanks[2] – second tank
tanks[3] – third tank

tanks[1].x = tanks[1].x + 10 – moves 1st tank in the table 10 pixels to the right
tanks[7].y = tanks[7].y + 5 – moves the 7th tank in the table 5 pixels down

In example I sent, when the tanks table was created, each element was created as a display image.
During the loop where they are created, they each were assigned the same image file ‘tank.png’. So they wall will be individual objects, just using a copy of the same image file. So they all look exactly alike, but they are all individual objects to be controlled.

Instead of using a loop, to insert each tank element into the table, I could have inserted them line by line and gave each of them a different look(a different image file):

table.insert(tanks, display.newImage(“blueTank.png”)
table.insert(tanks, display.newImage(“redTank.png”)
table.insert(tanks, display.newImage(“greenTank.png”)

tanks[1] now is a blue tank
tanks[2] now is a red tank
instead of them all being the same look

* in my example i sent in first reply, where the table.insert statement is listed, I forgot one thing

– incorrect
for i = 1, 5 do
table.insert(display.newImage(“tank.png”)
end

i forgot to note the name of the table to insert the image into, and there needs to be a closing bracket ‘)’ for the table.insert statement. It should be this instead:

–correct
for i = 1, 5 do
table.insert( tanks, display.newImage(“tank.png”))
end
[import]uid: 148857 topic_id: 26218 reply_id: 106385[/import]

Ey thanks a lot for the explanation. Now I was wondering if it was possible to make a universal function which could govern the movement of each tank. Without having to make a function by hand for each tank. It would be good if I could have a function generator or a universal function for an “endless” game mode [import]uid: 118482 topic_id: 26218 reply_id: 106464[/import]

It is best to follow the pop style of coding, so if you get a chance do some research in the forums and you can learn a lot from those post.

I assume you mean by ‘universal function for an endless game mode’ just a game loop that continues to loop as long as game is active?

the clear simple way to do that is :

– here is your endless loop
local function gameLoop(event)

– the Runtime Event listener, below, will automatically call this function as soon as you
– enterScene here, and quit calling it as soon as you call Runtime to remove the listener
– you should be sure to remove the listener on exitScene

– you can check in this function that is constantly being called, for a flag/variable to
– see if all the tanks in a wave have been killed or all have reached then end of the path
– and also check if the player’s life is zero(which would end the game in defeat)
– you can do many other things here, but keep in mind you only have a fraction of a second
– before this function gets called again automatically … but again, as this is a very simple
– game and handling a few sprites should be okay in this loop

end

– this calls the gameLoop function every frame
Runtime:addEventListener(“enterFrame”, gameLoop)
* I would code this in your enterScene function

Runtime:removeEventListener(“enterFrame”, gameLoop)
* and I would code this in the exitScene function
you CAN have one function to handle all the tanks as such:

the best way, especially since these tanks are displayObjects(images), is to assign event listeners to them and set it up to share the same event function. I think there are a couple of ways to setup the event listener. You would be best to check the api and/or the tutorials on events to get a good understanding.
That is where you will find the best answer for this specific question.
Good Luck!
[import]uid: 148857 topic_id: 26218 reply_id: 106550[/import]

Don’t use table insert, its flawed by design.

Do this instead

[code]
Then, in enterScene function load the table with your tanks…
for i = 1, 5 do
table[i] = “tank”
– set each tank position somewhere off the screen. (same position to start is okay)
– add these values to each image
tanks[i].isAlive = true
tanks[i].isMoving = false – set to false until timer is checked in game loop and sets it true
end [import]uid: 84637 topic_id: 26218 reply_id: 106581[/import]

Hi Danny,

“Don’t use table insert, its flawed by design.”

Could you please tell us why is it flawed? In this case, shouldn’t it be somehow deprecated?
Thanks!

Cleverson Schmidt [import]uid: 79136 topic_id: 26218 reply_id: 106586[/import]

more of a personal opinion. (also table.insert is pure lua, if you want to voice your opinion on it the place to do so is the lua mailing list (corona simply uses it)

For instance take this example

  
local myTable = {}  
  
table.insert(myTable, 1, 20)  
table.insert(myTable, 1, 20)  
  
print(#myTable) -- prints 2, even though you specified to put the items at position 1 in the table.  
  
----- as opposed to  
  
local myTable = {}  
  
myTable[1] = 20  
myTable[1] = 20  
  
print(#myTable) -- prints 1  
  
-------------  

The problem with the above example is that table.insert will shuffle things around a table, if a position already is filled it will simply push it to a new position, this can make tracking where things are in a table difficult [import]uid: 84637 topic_id: 26218 reply_id: 106587[/import]

Guys thanks for all the help but I think I’m doing a terrible job of getting my point across. If I make all these tank objects(more depending on the level) how can i make a single function that defines their movement and NOT have to make a function for each individual tank? [import]uid: 118482 topic_id: 26218 reply_id: 106683[/import]

local tanks = {}
local tankCnt = 0
local tickCnt = 0
local TOTAL_TANKS = 5

– outside all the storyboard functions
local function moveTank(aTank)
– you can move the tank, as well as other actions here for each
– tank as it’s reference is sent in as a parameter
if aTank.isAlive then
aTank.x = aTank.x + 10
aTank.y = aTank.y + 1
end
end
– IN enterScene FUNCTION, load up the tanks table
for i = 1, TOTAL_TANKS do
– create 5 tanks, place them off screen, set their status to isAlive and not isMoving
table.insert(tanks, display.newImage(“tank.png” , -50, -50))
tanks[i].isAlive = true
tanks[i].isMoving = false
end

local function gameLoop(event)

– normally should not have loops inside the game loop, because
– if there is too much going on during each frame call it can cause issues
– but for moving only 5 tanks, this is how you can do it.
– each tank will call the same function above (moveTank)

– have a variable that you would check here, to see if ‘so many ticks or seconds’
– has passed, and if so, set the isMoving to true for the next tank … will just use
– a simple incremented variable ‘tickCnt’
if tickCnt > 1000 and tankCnt <= TOAL_TANKS then
– set the next tank in motion
tanks[tankCnt].isMoving = true
tankCnt = tankCnt + 1
– reset the tickCnt
tickCnt = 0
end
tickCnt = tickCnt + 1
for i = 1, 5 do
if tanks[i].isMoving and tanks[i].isAlive then
– sending in reference to each tank, to the moveTank function
moveTank(tanks[i])
end
end

end

Runtime:addEventListener(“enterFrame”, gameLoop)
** in the exitScene function
be sure to remove the event listener and clear the tanks table
again, oop is a better way ‘IMO’, as well as there is better ways to code it even in this style, but this hopefully will help you get an understanding of one simple way to do it. It is very simple and very quick and dirty.

[import]uid: 148857 topic_id: 26218 reply_id: 106691[/import]

Thanks sooooo much for your help!!! I modified this code a bit by adding some timers to regulate the tickCnt variable and other minor modification and it works perfectly!! I didn’t know how to reference those functions to each of the tank objects but now I do. Thanks so much. Do you know any good reads to read about this “referencing” thing? [import]uid: 118482 topic_id: 26218 reply_id: 106722[/import]

here is a good link, that has many tutorials on all aspects of corona
http://www.learningcorona.com/

there all in one place, so it makes it easy just go from one link to another picking up bits of info from each. I really believe, this is the best way to learn it, but it means taking time to type and go thru some of the basic tutorials(and then experimenting with them). I have spent a lot of time doing that to teach myself the little I know so far!
as far as lua, I have never read any books on it, just taught myself from searching on the internet for whatever articles and tutorials I could find, and I still have a lot to learn about it. I just don’t have the links.

I think there has to be a good ‘basic’ lua book on amazon or at the local bookstore.

Good luck! [import]uid: 148857 topic_id: 26218 reply_id: 106794[/import]

Hey,

I have been working on a tower defense game/engine for awhile now and I have had a lot of the same problems you are having.

For the longest time I couldn’t get the enemies to spawn right/not on top of each other. My solution was to just simply spawn all of them at once(when the map loads) and either on the side of or in front/behind of the first waypoint and make them invisible. Then, when they hit the start or the first waypoint, they would become visible. It worked great and if you set your movement right you won’t have to worry about spawn timers, they all should turn on at the same rate as the others. [import]uid: 23649 topic_id: 26218 reply_id: 106961[/import]

Thanks for all the help guys. I’m at the point where I am working on how to remove the tanks when they are off screen or “dead.” I added some physics sensor bodies for something I will be using them for which slightly complicates things. I am having trouble removing only the body of a tank that is off screen. With this code below, once one tank is off screen, the boides of all the tanks get removed which is an issue. This is going to become even more important when the tanks start getting shot. I am trying to figure out how to detect specifically which tank is off screen or at 0 health and remove him. anybody have any ideas?

[code]


– level1.lua


local storyboard = require( “storyboard” )
local scene = storyboard.newScene()

– include Corona’s “physics” library
local physics = require “physics”
physics.start()
physics.setGravity( 0, 0)
physics.setDrawMode(“hybrid”)

– forward declarations and other locals
local screenW, screenH, halfW, halfH = display.contentWidth, display.contentHeight, display.contentWidth*0.5, display.contentHeight*0.5

local tanks = {}
local tickCnt = 0
local TOTAL_TANKS = 5
local tankCnt = 1

function AddCommas( number, maxPos )

local s = tostring( number )
local len = string.len( s )

if len > maxPos then
– Add comma to the string
local s2 = string.sub( s, -maxPos )
local s1 = string.sub( s, 1, len - maxPos )
s = (s1 … “,” … s2)
end

maxPos = maxPos - 3 – next comma position

if maxPos > 0 then
return AddCommas( s, maxPos )
else
return s
end

end

function tickCntFunct()
if tickCnt <= 2000 then
tickCnt = tickCnt + 25
print(“tick count”, tickCnt)
else
tickCnt = 0
end
end
timer.performWithDelay(10, tickCntFunct, 0)

function moveTank(aTank)
– you can move the tank, as well as other actions here for each
– tank as it’s reference is sent in as a parameter
local mSpeed = 150
rSpeed = 6

if aTank.isAlive == true then
print("aTank.x = ", aTank.x)
print("aTank.y = ", aTank.y)
print("tank rotation = ", aTank.rotation)

local disP1 = math.sqrt((math.abs(aTank.x - pointer1.x))^2 + (math.abs(aTank.y - pointer1.y))^2)
local disP2 = math.sqrt((math.abs(aTank.x - pointer2.x))^2 + (math.abs(aTank.y - pointer2.y))^2)
local disP3 = math.sqrt((math.abs(aTank.x - pointer3.x))^2 + (math.abs(aTank.y - pointer3.y))^2)
local disP4 = math.sqrt((math.abs(aTank.x - pointer4.x))^2 + (math.abs(aTank.y - pointer4.y))^2)

if aTank.x < 0 then
aTank.rotation = 90
aTank:setLinearVelocity( mSpeed, 0)
end
if aTank.rotation < 180 and disP1 < 1 then
aTank:setLinearVelocity( 0, 0)
aTank.rotation = aTank.rotation + rSpeed
end
if aTank.rotation >= 180 and disP1 < 1 then
aTank.rotation = 180
aTank:setLinearVelocity( 0, mSpeed)
end
if aTank.rotation > 90 and disP2 < 1 then
aTank:setLinearVelocity( 0, 0)
aTank.rotation = aTank.rotation - rSpeed
end
if aTank.rotation <= 90 and disP2 < 1 then
aTank.rotation = 90
aTank:setLinearVelocity( mSpeed, 0)
end
if aTank.rotation > 0 and disP3 < 1 then
aTank:setLinearVelocity( 0, 0)
aTank.rotation = aTank.rotation - rSpeed
end
if aTank.rotation <= 0 and disP3 < 1 then
aTank.rotation = 0
aTank:setLinearVelocity( 0, -1*mSpeed)
end
if aTank.rotation < 90 and disP4 < 1 then
aTank:setLinearVelocity( 0, 0)
aTank.rotation = aTank.rotation + rSpeed
end
if aTank.rotation >= 90 and disP4 < 1 then
aTank.rotation = 90
aTank:setLinearVelocity( mSpeed, 0)
end
if aTank.x > screenW + 40 then
aTank.x = screenW + 41
end
end
end
timer.performWithDelay(1, moveTank, 0)


– BEGINNING OF YOUR IMPLEMENTATION

– NOTE: Code outside of listener functions (below) will only be executed once,
– unless storyboard.removeScene() is called.


– Called when the scene’s view does not exist:
function scene:createScene( event )
local group = self.view

pointersGroup = display.newGroup()
mapGroup = display.newGroup()

– create a grey rectangle as the backdrop
map = display.newImage( “map1.png” )
map:setReferencePoint(display.TopLeftReferencePoint)
map.x = 0
map.y = 0

spawner = display.newImage(“pointer.png”)
spawner:setReferencePoint(display.CenterReferencePoint)
spawner.y = 210
spawner.x = -40

pointer1 = display.newImage(“pointer.png”)
pointer1:setReferencePoint(display.CenterReferencePoint)
pointer1.x = 210
pointer1.y = 210

pointer2 = display.newImage(“pointer.png”)
pointer2:setReferencePoint(display.CenterReferencePoint)
pointer2.x = 210
pointer2.y = 390

pointer3 = display.newImage(“pointer.png”)
pointer3:setReferencePoint(display.CenterReferencePoint)
pointer3.x = 510
pointer3.y = 390

pointer4 = display.newImage(“pointer.png”)
pointer4:setReferencePoint(display.CenterReferencePoint)
pointer4.x = 510
pointer4.y = 90

– all display objects must be inserted into group

pointersGroup:insert( spawner )
pointersGroup:insert( pointer1 )
pointersGroup:insert( pointer2 )
pointersGroup:insert( pointer3 )
pointersGroup:insert( pointer4 )
mapGroup:insert( map )
group:insert( pointersGroup )
group:insert( mapGroup )

end

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

for i = 1, TOTAL_TANKS do
– create 5 tanks, place them off screen, set their status to isAlive and not isMoving
table.insert(tanks, display.newImage(“tank.png”))
print("memory (all spawned): “, AddCommas( system.getInfo(“textureMemoryUsed”), 9 ) … " bytes” )
tanks[i]:setReferencePoint(display.CenterReferencePoint)
tanks[i]:scale(0.75, 0.75)
tanks[i].x = spawner.x
tanks[i].y = spawner.y
tanks[i].isAlive = true
tanks[i].isMoving = false
end

local function gameLoop(event)

– normally should not have loops inside the game loop, because
– if there is too much going on during each frame call it can cause issues
– but for moving only 5 tanks, this is how you can do it.
– each tank will call the same function above (moveTank)

– have a variable that you would check here, to see if ‘so many ticks or seconds’
– has passed, and if so, set the isMoving to true for the next tank … will just use
– a simple incremented variable ‘tickCnt’

if tickCnt > 2000 and tankCnt <= TOTAL_TANKS then
physics.addBody( tanks[tankCnt], { isSensor = true } )
tanks[tankCnt].isMoving = true
print("tankCnt= ", tankCnt)
tankCnt = tankCnt + 1
print("memory (moving): “, AddCommas( system.getInfo(“textureMemoryUsed”), 9 ) … " bytes” )
end

for i=1, TOTAL_TANKS do
if tanks[i].isMoving and tanks[i].isAlive then
moveTank(tanks[i])
end
end
end

Runtime:addEventListener(“enterFrame”, gameLoop)

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 [import]uid: 118482 topic_id: 26218 reply_id: 107798[/import]

Why not use transition.to()? Create each straight line segment as a simple transition. Use a delay in each transition to separate each motion in time. Here’s a snippet of code from a project I was working on.

This function creates a sprite and moves it on a pattern similar to what you have in your map. Each alien keeps an array of transitions, so that if it is removed the transitions can be canceled. When the last transition is completed the sprites call an onComplete functions that removes them, i have omitted this here.

[lua]local function make_alien()
local alien

if #alien_hoard_array > 0 then
local f = alien_hoard_array[1]
table.remove( alien_hoard_array, 1 )
alien = sprite.newSprite( alien_set )
alien.currentFrame = f
else
print( “game over” )
return
end

alien.x = 32
alien.y = -32
local transition_time = math.random( 5000, 10000 )

local transitions = {}
table.insert( transitions, transition.to( alien, {y=50, time=1000} ) )
table.insert( transitions, transition.to( alien, {x=288, time=1200, delay=1000} ) )
table.insert( transitions, transition.to( alien, {y=150, time=1000, delay=2200} ) )
table.insert( transitions, transition.to( alien, {x=32, time=1200, delay=3200} ) )
table.insert( transitions, transition.to( alien, {y=end_y, time=1400, delay=4400, onComplete=alien_complete} ) )

alien.transitions = transitions
table.insert( alien_array, alien )

alien.bomb_timer = timer.performWithDelay( bomb_delay, create_timer_callback( alien ), -1 )

end

local alien_timer = timer.performWithDelay( 1000, make_alien, -1 )[/lua]

This has room for improvement. The times and distances moved could be calculated in pixels per frame to give the sprites a constant rate of movement for each transition. [import]uid: 98652 topic_id: 26218 reply_id: 107819[/import]

hhmm looks interesting but I’m not seeing how I could implement that into what i’m trying to do. Since i am using tables to make my tanks, I will need to somehow be able to detect specifically which tank is off the screen. If i plug in a “aTank:removeSelf()” in the moveTank function then it takes the physics bodies off of all tanks once only one has moved off screen. That’s why I’m looking for a way to detect specifically which tank (ex: tanks[1] or tanks[2]) is off screen.

I decided to try adding a wall about 200 pixels to the right off the screen and try to detect collision when a tank hits it, detect which tank it is, and remove its display and physics body. However again, I have no clue how to detect the specific tank number. Help?
[import]uid: 118482 topic_id: 26218 reply_id: 107831[/import]

Not sure what you are describing. If you’re making tanks in advance and holding them off screen, add the transitions to a tank when a tank needs to move onto the screen.

Or, if the tanks need to move on at specific intervals, use delay in the transitions to determine when each tank begins moving onto the screen.

Not sure how all of the tanks would lose physics if you removed one tank. The transition onComplete sends a reference to the object. So you should know which object completes a transition. If your objects are in a table you can use table.indexOf( t, obj ) to find it. [import]uid: 98652 topic_id: 26218 reply_id: 107836[/import]