Problem with timer.performWithDelay().

In my game I am working on, I recently cleaned up a lot of my code, but all the functionality should remain the same, just performance is improved. A strange error has appeared this time. Basically when a collision occurs between a bullet and an enemy, I remove the bullet, get the (x,y) coords of the enemy, remove the enemy, then I load up an explosion animation at those (x,y) coords I stored in variables.
The animation lasts for 0.1s so what I did was inside the collision code, I used a timer, to wait 0.1s and then remove the explosion from memory so it is seen.
The collision works fine, but the timer doesn't wait 0.1s and then call the function asked, it acts instantaneously.

I'll show the code here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
local function explody(exp,shExp)
        print( "in explody" );
        exp:removeSelf();
        exp = nil;
        -- These two lines free texture from memory.
        shExp:dispose();
        shExp = nil;
end
 
 
function onBulletCollision( self, event )
                if(event.phase == "began") then
                        -- Use an elseif here, so it hits the enemy OR it goes off screen for a second and is removed. Don't want to be able to shoot enemies off screen.
                        -- Could use another if here if have different types of enemies.
                        -- To free up memory. Remove bullet when off screen.
                        if(event.other.myName == "met") then
                                print( self.myName .. ": collision began with " .. event.other.myName );                        -- Collision testing ok. (Remove on release).
                                self:removeSelf();                                                                                                                                      -- Remove self (bullet).
                                self = nil;                                                                                                                                                     -- Extra cautious.
                                
                                xCoord = event.other.x; yCoord = event.other.y;                                                                         -- Get coordinates of meteor.
                                event.other:removeSelf();                                                                                                                       -- Remove the meteor from memory.
                                event.other = nil;
                                print( xCoord .. " " .. yCoord );                                                                                                       -- Check ok. (Remove on release).
                                
                                -- Once enemy is gone, create explosion at coordinate. This happens for every enemy.
                                require "sprite";
                                local sheetExplosion = sprite.newSpriteSheet( "Media/Images/explosionSheet.png", 99,119);
                                local spriteSetExplosion = sprite.newSpriteSet(sheetExplosion, 1, 3);                           -- three frames.
                                sprite.add( spriteSetExplosion, "expl", 1, 3, 100,0);                                                           -- play 3 frames once. 0.1s animation.
 
                                local explosion = sprite.newSprite( spriteSetExplosion );                                                       -- Load explosion image.
                                explosion.x = xCoord; explosion.y = yCoord;                                                                                     -- Position at the (x,y) coordinates of meteor.
                        
                                explosion:prepare("expl");                                                                                                                      -- Load animation.
                                explosion:play();                                                                                                                                       -- Play animation.
                                timer.performWithDelay(100, explody(explosion,sheetExplosion), 1);                                                                              -- Give object time to animate. Pass newly created explosion object to explody function.
                        end
                        else if(event.other.myName == "ceiling") then
                                print( self.myName .. ": collision began with " .. event.other.myName );                        -- Collision testing ok.
                                self:removeSelf();
                                self = nil;
                        end
                end
end

Have you set it on a longer timer to check to see if it's not just your computer rushing through the timer?

Yes I have tried setting it to a longer time for that purpose, but it still appears to call the function instantaneously. I've commented out the timer code to check that the explosion animation loads correctly and it does, the problem has to do with the timer, I have no idea what is going on.

Thanks for your input though.

The formatting of your nested if statements is strange, try cleaning that up, the issue may be coming from that.

I have changed it to the following, but still no change.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function onBulletCollision( self, event )
                if(event.phase == "began") then
                        -- Use an elseif here, so it hits the enemy OR it goes off screen for a second and is removed. Don't want to be able to shoot enemies off screen.
                        -- Could use another if here if have different types of enemies.
                        -- To free up memory. Remove bullet when off screen.
                        if(event.other.myName == "met") then
                                print( self.myName .. ": collision began with " .. event.other.myName );                        -- Collision testing ok. (Remove on release).
                                self:removeSelf();                                                                                                                                      -- Remove self (bullet).
                                self = nil;                                                                                                                                                     -- Extra cautious.
                                
                                xCoord = event.other.x; yCoord = event.other.y;                                                                         -- Get coordinates of meteor.
                                event.other:removeSelf();                                                                                                                       -- Remove the meteor from memory.
                                event.other = nil;
                                print( xCoord .. " " .. yCoord );                                                                                                       -- Check ok. (Remove on release).
                                
                                -- Once enemy is gone, create explosion at coordinate. This happens for every enemy.
                                require "sprite";
                                local sheetExplosion = sprite.newSpriteSheet( "Media/Images/explosionSheet.png", 99,119);
                                local spriteSetExplosion = sprite.newSpriteSet(sheetExplosion, 1, 3);                           -- three frames.
                                sprite.add( spriteSetExplosion, "expl", 1, 3, 100,0);                                                           -- play 3 frames once. 0.1s animation.
 
                                local explosion = sprite.newSprite( spriteSetExplosion );                                                       -- Load explosion image.
                                explosion.x = xCoord; explosion.y = yCoord;                                                                                     -- Position at the (x,y) coordinates of meteor.
                        
                                explosion:prepare("expl");                                                                                                                      -- Load animation.
                                explosion:play();                                                                                                                                       -- Play animation.
                                timer.performWithDelay(1000, explody(explosion,sheetExplosion), 1);                                                                             -- Give object time to animate. Pass newly created explosion object to explody function.
                        elseif(event.other.myName == "ceiling") then
                                print( self.myName .. ": collision began with " .. event.other.myName );                        -- Collision testing ok.
                                self:removeSelf();
                                self = nil;
                        end
                end
end

1
timer.performWithDelay(1000, explody(explosion,sheetExplosion), 1)

lordmooch may be onto something, try adjusting your function call.

Before I read loordmooch's post, after playing around with the code for a while, I discovered that the problem had to do with the function call. I was just about to post that but, I just saw his reply, thanks for that, your right.

But now I'm wondering how I pass parameters to the function if I only pass it's name? Is there a way to do that? or will I just have to call another function inside that function where I can then pass parameters too?

However, the problem with the method I suggested is that I have to make some variables I'm using global, I want to avoid doing that.

Edit:
I solved this by declaring the variables as local at the top of the file, so it's local scope isn't to the function. All is working now :)

You both were a great help in solving this, thanks for everything !

views:2233 update:2012/2/9 11:37:26
corona forums © 2003-2011