From one spritesheet to another and delete the first one?

Hi!
I have a spritesheet (para_glide.png) that moves from top to bottom. Before it reaches ground it calls function paraLanding to start another spritesheet (para_land.png). But how do I remove the first spritesheet (para_glide.png)?

local function spawnPara()  
  
-- paraLanding  
 local function paraLanding(event)  
  
 local sheet = sprite.newSpriteSheet( "images/enemies/para\_land.png", 261, 240 )  
  
 thetime = 400  
  
 local spriteSet = sprite.newSpriteSet(sheet, 1, 7)  
 sprite.add( spriteSet, "paraLanding", 1, 9, 400, 1 )   
  
 paraChuter = sprite.newSprite( spriteSet )  
 paraChuter.x = event.x  
 paraChuter.y = event.y  
  
 paraChuter.xScale = -0.5  
 paraChuter.yScale = 0.5  
  
 paraChuter:prepare("paraLanding")  
 paraChuter:play()  
  
 transition.to( paraChuter, { time=thetime, alpha=1, y=paraChuter.y+20 } )  
  
 end   
-- paraChuter  
 local sheet = sprite.newSpriteSheet( "images/enemies/para\_glide.png", 261, 240 )  
  
 thetime = math.random(5000, 7000)  
  
 local spriteSet = sprite.newSpriteSet(sheet, 1, 7)  
 sprite.add( spriteSet, "paraChuter", 1, 31, 400, 1 )   
  
 paraChuter = sprite.newSprite( spriteSet )  
 paraChuter.x = copter.x-35  
 paraChuter.y = copter.y  
  
 randDir = math.random(1, 2)  
  
 paraChuter.xScale = -0.5  
 paraChuter.yScale = 0.5  
  
 paraChuter:prepare("paraChuter")  
 paraChuter:play()  
  
 paraChuter.name = "paraChuter"  
  
 pentagonShape = { 2, 17 , -12, 39 , -13, 16 , -9, -1 }  
  
 physics.addBody(paraChuter, "kinematic", {bounce = 0, shape=pentagonShape})  
  
 -- Before ground, call function paraLanding  
 transition.to( paraChuter, { time=thetime, alpha=1, x=copter.x-60, y=245, onComplete = paraLanding } )  
  
  
end  

Best regards,
joelwe [import]uid: 54640 topic_id: 10149 reply_id: 310149[/import]

Hey there,

Is it possible for you to simply use removeSelf() on the the first sprite immediately prior to creating the second?

I’d use a single sprite and just change what sequence was playing, if that interests you there’s plenty of info in the sprite APIs :slight_smile:

Peach [import]uid: 52491 topic_id: 10149 reply_id: 37102[/import]

Hi Peach and thank you for your reply!
The thing is that I have a hero that can shoot down para_glide.png, but not para_land.png. So if I shoot the parachuter when he is in the air it calls oncollision and table.insert(toRemove,event.other) to remove the paraChuter.

for i = 1, #toRemove do toRemove[i].parent:remove(toRemove[i]) toRemove[i] = nil end

But when this happens, the para_land.png still fires up, and I don’t know how to avoid that.

So, you’re saying that I should have all the sprites (para_glide and para_land) on one spritesheet? Would this help me regarding this new info?

Best regards,
joelwe [import]uid: 54640 topic_id: 10149 reply_id: 37121[/import]

Can you be a little more specific?

I’m a tad confused as to what your game looks like - I was imagining a HERO para moving down a level, then he changed to land.

I understand the glider is shot and then the land spawns; but what do you mean when you say it still “fires”? Are we talking about an event firing for the lander that should only fire for the glider, or actual shooting?

Sorry, it’s just a tad hard to envision. [import]uid: 52491 topic_id: 10149 reply_id: 37135[/import]

Okey, now I’m being over clear, so bear with me:

I’ve got a hero that shoot at enemies (parachuter in this case). The parachuter jumps from a helicopter (now shown below). He transition down to the ground, and when onComplete the para_glide.png-sprite is supposed to disappear and the para_land.png-sprite to show up.

Gliding (para_glide.png):
http://imageshack.us/photo/my-images/861/glide.png/

Landing (para_land.png):
http://imageshack.us/photo/my-images/42/landp.png

But if the hero hit the parachuter, he dies (table.insert(toRemove,event.other)), and the para_land.png-sprite should not be called.
http://imageshack.us/photo/my-images/850/deadm.png

So what I’m asking is; how can I remove the first sprite when the second is supposed to be shown (onComplete) and how can I cancel the transition if the parachuter is killed?

And there’s not just one parachuter, they come all the time in a gameloop.

Best regards,
joelwe [import]uid: 54640 topic_id: 10149 reply_id: 37143[/import]

This is still a little hard to picture but from the sounds of things canceling the transition would be best.

To cancel a transition you need to give it a name; have you done that? Eg; mytrans = transition.to (yourcodehere) [import]uid: 52491 topic_id: 10149 reply_id: 37264[/import]

Hi!
This is a gif-animation how my game works:

http://postimage.org/image/2jj4adrgk/

It shows when an enemy survives the hero’s bullets and land on the ground, and it shows when the hero hit the enemy and the enemy dies.

Yes, I’ve given the transition a name, but where should I cancel it? In the collision function? Wouldn’t this affect the other parachuters?

That’s the first problem; how I should cancel the transition if the hero kills the enemy.

The second problem is how I should remove the first sprite (para_glide.png) and replace it with the other sprite (para_land.png). As for now, the first sprite isn’t removed, although the second one appears.

Best regards,
joelwe [import]uid: 54640 topic_id: 10149 reply_id: 37276[/import]

Hey Joelwe,

You’d want to cancel the collision for that para only, yes. You should look into assigning the para’s different names if you are canceling multiple transitions and not just one.

Alternatively, if the transition is on a timer, you could also simply have it trigger on collision with the ground instead, that way you needn’t worry about canceling it on removal.

I would still change what sprite sequence is being played rather than using removeSelf, however if you want to remove the glider and add the lander, use the gliders x and y to spawn the lander then in the next line remove the glider.

Peach :slight_smile: [import]uid: 52491 topic_id: 10149 reply_id: 37428[/import]

I will elaborate Peach’s suggestion which IMO is much better than removing and adding object.

You can put your enemy sprites in one file itself.

so lets say you have spritesheet1 (png file) which has “falling” animation frames. and spritesheet2 (again png file) which as “landed” animation frames.

you can put all these frames in single big spritesheet so that you get something like below

frame 1 to frame k --> falling animation
frame k+1 to frame n —> exploding animation
frame n+1 to frame p —> landing anmiation
you can set up different animation sequences using following command

sprite.add( spriteSet, “falling”, startFrame, frameCount, time, [loopCount])
Now you create only 1 sprite object using following command

si = sprite.newSprite( spriteSet )

and add your physics logic to this object.

you can animate this object using any of the animation sequences you defined before using following two commands

si:prepare([sequence])
si:play()
so basically in your bullet collision event handler you can do

enemy:prepare(“die”)
enemy:play()
on landing collision handler you do

enemy:prepare(“landed”)
enemy:play()
Hope you get the point. [import]uid: 48521 topic_id: 10149 reply_id: 37442[/import]

Thanks guys for your replies! This is essential for my game, if I get this working I think I’m done with 50% of the project.

I have no chance to try this today, but I’ll do it tomorrow and come back with results! But it seems logic the way you’ve explained things.

Thanks again!

Best regards,
joelwe [import]uid: 54640 topic_id: 10149 reply_id: 37447[/import]

@chinmay - Great info; thanks for taking the time to share it. I certainly agree that this is a much better method than removing the object.

@joelwe - Best of luck to you, I hope tomorrow is a productive and successful day for you!

Peach :slight_smile: [import]uid: 52491 topic_id: 10149 reply_id: 37586[/import]

Good that you got what you wanted… but somehow I don’t like this part…
[lua] self:removeSelf() – You remove object here.

local sheet = sprite.newSpriteSheet( “images/enemies/para_land.png”, 261, 240 )

local spriteSet = sprite.newSpriteSet(sheet, 1, 7)
sprite.add( spriteSet, “paraland”, 1, 9, 400, 1 )

paraLander = sprite.newSprite( spriteSet )
paraLander.x = self.x – And still access it here…
paraLander.y = self.y – Something’s not right.[/lua]

I suggest you check for memory leaks. [import]uid: 48521 topic_id: 10149 reply_id: 37877[/import]

self:removeSelf() -- You remove object here. removes paraGlider from the gameloop? Then I create a new object called paraLander, with a new sprite.

One more question though: How should I do if I want 4 parachuters jumping at the same time? Do I have to multiply this code by 4? [import]uid: 54640 topic_id: 10149 reply_id: 37892[/import]

I was referring to “self” object.

If you remove it using self:removeSelf() how are you still able to access self.x ? [import]uid: 48521 topic_id: 10149 reply_id: 37893[/import]

Ooops! Just moved the text down a bit! :slight_smile: Thanks! [import]uid: 54640 topic_id: 10149 reply_id: 37895[/import]

YAY! I finally got it to work! For now, I haven’t used a big sprite, but I’ll fix it later.

What I’ve done:

I changed the paraglider’s physics to “dynamic” and gave it a collision listener. When the paraglider hits the ground (just an invisible line) it calls onCollision function.

It then remove itself and creates a new object, called paraLander. paraLander transition down a bit, then onComplete it calls soldierFrag. soldierFrag is a animation where the soldier throws a grenade (goFrag). When it is done, it calls soldierRun. soldierRun then transition out of the screen and removes itself.

Now, if I kill the the paraglider it dies and no new transitions begins, just as I wanted.

I don’t know how good this code is though and how different it is from what you guys described, but it works! :wink:

Thank you again Seth and cinmay! :smiley:

function onCollision(self, event)  
if (self.name == "paraGlider" and event.other.name == "ground") then  
  
-- soldierRun   
---- Enemy soldier starts running  
  
 local function soldierRun()  
  
 soldierFrags:removeSelf()   
  
 local sheet = sprite.newSpriteSheet( "images/enemies/soldier\_run.png", 130, 120 )  
  
 thetime = 8000  
  
 local spriteSet = sprite.newSpriteSet(sheet, 1, 7)  
 sprite.add( spriteSet, "soldierRuns", 1, 12, 100, 0 )   
  
 local soldierRuns = sprite.newSprite( spriteSet )  
 soldierRuns.x = soldierFrags.x  
 soldierRuns.y = soldierFrags.y  
 soldierRuns.xScale = 0.5  
 soldierRuns.yScale = 0.5  
 soldierRuns:prepare("soldierRuns")  
 soldierRuns:play()  
  
 transition.to( soldierRuns, { time=thetime, alpha=1, x=-20, onComplete = function(self) self.parent:remove(self); self = nil; end } )  
 end  
  
-- soldierFrag  
---- Enemy soldier throws frag  
  
 local function soldierFrag()  
  
 paraLander:removeSelf()  
 print("soldierFrag")  
 local sheet = sprite.newSpriteSheet( "images/enemies/soldier\_frag.png", 130, 120 )  
  
 thetime = 2000  
  
 local spriteSet = sprite.newSpriteSet(sheet, 1, 7)  
 sprite.add( spriteSet, "soldierFrags", 1, 68, 100, 1 )   
  
 soldierFrags = sprite.newSprite( spriteSet )  
 soldierFrags.x = paraLander.x-15  
 soldierFrags.y = paraLander.y+20  
 soldierFrags.xScale = 0.5  
 soldierFrags.yScale = 0.5  
 soldierFrags:prepare("soldierFrags")  
 soldierFrags:play()  
  
-- goFrag  
---- Frags explodes  
  
 function goFrag()  
 local sheet = sprite.newSpriteSheet( "images/explosions/frag.png", 260, 283 )  
 thetime = 2000  
  
 local spriteSet = sprite.newSpriteSet(sheet, 1, 5)  
 sprite.add( spriteSet, "frag", 1, 40, 100, 1 )   
  
 -- Sets random throw hit  
 stringX = math.random(100, 150)  
 stringY = math.random(10, 20)  
  
 local throwFrag = sprite.newSprite( spriteSet )  
 throwFrag.x = soldierFrags.x-stringX  
 throwFrag.y = soldierFrags.y-stringY  
 throwFrag.xScale = 0.5  
 throwFrag.yScale = 0.5  
 throwFrag:prepare("frag")  
 throwFrag:play()  
  
 timer.performWithDelay( 1, healthP, 1)  
 end  
  
 timer.performWithDelay( 2000, goFrag, 1)  
  
 transition.to( soldierFrags, { time=thetime, alpha=1, onComplete = soldierRun } )  
  
 end  
  
-- paraLander  
---- Parachuter lands  
  
 local sheet = sprite.newSpriteSheet( "images/enemies/para\_land.png", 261, 240 )  
  
 local spriteSet = sprite.newSpriteSet(sheet, 1, 7)  
 sprite.add( spriteSet, "paraland", 1, 9, 400, 1 )  
  
  
 paraLander = sprite.newSprite( spriteSet )  
 paraLander.x = self.x  
 paraLander.y = self.y  
 paraLander.xScale = -0.5  
 paraLander.yScale = 0.5  
  
 self:removeSelf()  
  
 randDir = math.random(1, 2)  
  
 paraLander:prepare("paraland")  
 paraLander:play()  
  
 transition.to( paraLander, { time=600, alpha=1, y=270, onComplete = soldierFrag})  
  
 end  
end  

[code]
local function gameLoop(event)
if event.time - timeLastCopter >= math.random(4000, 5000) then

– Copter code…

– spawnPara
– paraGlider
– Parachuters, 20% chance no chuter
randParaX = math.random(1, 5)

if randParaX > 1 then

local function spawnPara()

local sheet = sprite.newSpriteSheet( “images/enemies/para_glide.png”, 261, 240 )

thetime = math.random(5000, 7000)

local spriteSet = sprite.newSpriteSet(sheet, 1, 7)
sprite.add( spriteSet, “paraglide”, 1, 31, 400, 1 )

paraGlider = sprite.newSprite( spriteSet )
paraGlider.x = copter.x-35
paraGlider.y = copter.y

randDir = math.random(1, 2)

paraGlider.xScale = -0.5
paraGlider.yScale = 0.5

paraGlider:prepare(“paraglide”)
paraGlider:play()

paraGlider.name = “paraGlider”

pentagonShape = { 2, 17 , -12, 39 , -13, 16 , -9, -1 }

physics.addBody(paraGlider, {bounce = 0, shape=pentagonShape})
paraGlider.isFixedRotation = true

paraGlider.collision = onCollision
paraGlider:addEventListener(“collision”, paraGlider)

paraGlider.linearDamping = 5

gameLayer:insert(paraGlider)
end

– Spawns random 1-4, with 500 delay
randPara = math.random(1, 1)

timer.performWithDelay( 500, spawnPara, randPara)

end
[/code] [import]uid: 54640 topic_id: 10149 reply_id: 37785[/import]