Collision detection scope with multiple lua files.

Hi all,

I'm new to Lua, only started about 4 days ago. I'm not new to programming though.

I've been working on a moderately simple game, of the vertical shooter sort like Galaga etc.

I noticed a strange bug in my code, basically I have several files, main which I use to load up backgrounds/sounds etc which I also wish to use to handle collisions. I also have a file pow which I use to create power ups for use in the game. Currently I'm implementing a speedup power up, simply on collision between the player and the image of the power up.

This is my current code in this class:

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
 
module(..., package.seeall);
function new()                                          
                                require "sprite";
                                local sheetSpeed = sprite.newSpriteSheet( "Media/Images/speedSheet.png", 59,66);
                                local spriteSetSpeed = sprite.newSpriteSet(sheetSpeed, 1, 2); -- two frames.
                                sprite.add( spriteSetSpeed, "flash", 1, 2, 200, 0 ); -- play 2 frames every 500 ms
 
                                local speedUp = sprite.newSprite( spriteSetSpeed );
                                speedUp.myName = "speed";
                                speedUp.x = _W/2; speedUp.y = 0;
                                physics.addBody(speedUp, { isSensor = true });
 
                                speedUp:prepare("flash");
                                speedUp:play();
                                
                                speedUp:setLinearVelocity(0,100);
                                
                                speedUp.collision = speedCollision
                                speedUp:addEventListener( "collision", speedUp );
                        --end
end
 
function speedCollision( self, event ) -- Self is the power up in this case. Other is the player.
                if(event.phase == "began") then
                        if(event.other.myName == "Flyer") then
                                audio.play(power_sound);
                                print( self.myName .. ": collision began with " .. event.other.myName )
                        end
                end
end

Are you using multiple groups?

Thanks for your reply.

I'm not using any groups.

I expect this may be because the speedUp is local - try removing local, test that and let me know results please.

Peach :)

Unfortunately it didn't work. I tested changing it to global late at night last night and I didn't put it back in main so I thought it worked. I tried it again this morning putting it in main and still nothing :(.

Hmmm, I just found something interesting. If I put both the collision handling functions in pow.lua only the speedUp collision works, the collision code between enemies and the player's bullet no longer works. Could the error be something with my enemy bullet collision code?

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
function fire_button:touch(event)
        if(event.phase == "began") then
                image_Select({type = "fire_btn_start"});
                audio.play(bullet_sound);
                player_shot = display.newImage("Media/Images/Player_Bullet.png");
                player_shot.myName = "bullet";
                player_shot:setReferencePoint(display.CenterReferencePoint);
                player_shot.x = plane.x; player_shot.y = plane.y-40; -- Can't use plane.x wonder why?
                physics.addBody(player_shot, { isSensor = true });
                player_shot:setLinearVelocity(0,bullet_speed);
                
                -- Every player bullet gets assigned it's own collision label.
                player_shot.collision = onBulletCollision
                player_shot:addEventListener( "collision", player_shot );
        end
 
function onBulletCollision( self, event )
                if(event.phase == "began") then
                        if(event.other.myName == "met") then -- This stops multiple collisions Without it has collision detected if object off screen also.
                                audio.play(explode_sound);
                                print( self.myName .. ": collision began with " .. event.other.myName )                 -- Collision testing ok.
                                self:removeSelf();                                                                                                                              -- Remove bullet.
                                -- Bug with explosion scope??? Always seen as nil. Doesn't know which explosion instance talking about.
                                xCoord = event.other.x; yCoord = event.other.y;
                                event.other:removeSelf();
                                
                                -- Once enemy is gone, create explosion at coordinate. This happens for every enemy.
                                require "sprite";
                                sheetExplosion = sprite.newSpriteSheet( "Media/Images/explosionSheet.png", 99,119);
                                spriteSetExplosion = sprite.newSpriteSet(sheetExplosion, 1, 3);                                  -- three frames.
                                sprite.add( spriteSetExplosion, "expl", 1, 3, 100,0);                                                    -- play 3 frames once. 0.1s animation.
 
                                explosion = sprite.newSprite( spriteSetExplosion );
                                explosion.x = xCoord; explosion.y = yCoord;
                        
                                explosion:prepare("expl");
                                explosion:play();
                                timer.performWithDelay(100, explody, 1);
                        end
                end
end

Could you return the object so it was local in your main game file, perhaps?

I believe Ghosts VS Monsters may demonstrate that.

Peach :)

Thanks for all your help Peach :)

Unfortunately your suggestion didn't work either. I have many scoping issues in this game. I think I may have to rewrite the game, the functionality is all fine, but I just need to organise it much better and make as much as I can local.

I am surprised to hear that didn't work and yes, the problem seems a little broad - you may want to consider reading this article as you proceed; http://blog.anscamobile.com/2011/09/a-better-approach-to-external-modules/

Sorry I couldn't give you a simple answer :(

Thanks for that link Peach, I have reprogrammed my game using that method of external modules. Unfortunately the error must not be related to that because I have ended up with the exact same error :(.

I will elaborate more this time. I don't think it is because multiple collision per file are not allowed, because I tested using 2 collisions in a file and it worked fine, something else is going on here.

In main I wish for the following collision handling functions to be used: (I will post my entire main file as I suspect there is something wrong in there somewhere).

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
--                                                      Shooter Engine 1.0.
--                                                      If an object is not defined when it is called, a nil error will occur.
--                                                      Don't want anything global - creates scope issues.
-- Touch listeners and collision listeners (I think) get removed auto, only enterFrames don't.
-- *************************
-- Private part of module.
-- *************************
 
--                                                      Use this to access other modules.
local Player = require("Player");
local Enemy = require("Enemy");
local Pow = require("Pow");
 
--                                                      Local Constants
local _H = display.contentHeight;
local _W = display.contentWidth;
 
--                                                      Local Variables
local xCoord;                                                                                                                                                                   -- Used to position explosion.
local yCoord;                                                                                                                                                                   -- Used to position explosion.
local explosion;                                                                                                                                                                -- Solve timer parameter issue.
local sheetExplosion;                                                                                                                                                   -- Solve timer parameter issue.
--                                                      Enable Physics Engine.
physics = require("physics");
physics.start();
physics.setGravity(0,0);                                                                                                                                                -- Eliminate gravity.
 
--                                                      Background music to be loaded.
local soundtrack = audio.loadStream("Media/Sound/Background_Music.aiff");
 
--                                                      Background images to be loaded.
--                                      Used to remove bullets off stage.
local ceiling = display.newRect(0,0,_W,1);                                                                                                              -- position top left, _W is display width 20 is height.
ceiling:setReferencePoint(display.CenterReferencePoint);                                                                                -- center ref pt is important with physics.
ceiling.x = _W/2; ceiling.y = -30;
ceiling.isHitTestable = true;
ceiling.isVisible = false;
ceiling.myName = "ceiling";
physics.addBody(ceiling, { isSensor = true });
 
--                                                      Play music when app is launched.
audio.play(soundtrack, {loops=-1}); -- Loops infinite times (-1).
audio.setVolume(1.0, { channel=1 } );                                                                                                                   -- Use to adjust background sound volume. 
 
--                                                      Load background image here.
 
 
--                                                      Instantiate Player.
local hero = Player.new();                                                                                                                              -- Call new function in player.lua.
Player.start_Playing();                                                                                                                                 -- Call start_Playing function in player.lua
Enemy.new(100,0,0,100);
Enemy.new(300,0,0,100);
Pow.new();
 
--                                                      Instantiate Enemies.
 
local function explody()
        print( "in explody" );
        explosion:removeSelf();
        explosion = nil;
        -- These two lines free texture from memory.
        sheetExplosion:dispose();
        sheetExplosion = nil;
end
 
 
-- *************************
-- Public part of module.
-- *************************
 
--                                                      Put collision stuff here.
 
 
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;                                                                                                                              -- Removing this allows us to go into other if statement.
                                print( xCoord .. " " .. yCoord );                                                                                                       -- Check ok. (Remove on release).
                                
                                -- Once enemy is gone, create explosion at coordinate. This happens for every enemy.
                                require "sprite";
                                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.
 
                                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, 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
 
function onPlaneCollision( self, event )
        if(event.phase == "began") then
                if(event.other.myName == "met") then
                        print( self.myName .. ": collision began with " .. event.other.myName );
                end
        end
end
 
function speedCollision( self, event )
        if(event.phase == "began") then
                if(event.other.myName == "Hero") then
                        print( self.myName .. ": collision began with " .. event.other.myName );
                end
        end
end

I would suggest perhaps uploading your project and posting a link and hoping someone has the free time to look at it, or if it is a matter of urgency using premium support; http://www.anscamobile.com/corona/support/

This is just because the above will take a fair chunk of time to go through.

Alternatively you could try to make a new project, a mini one, to try and isolate the problem further. (This is often my first course of action in these situations.)

Hi Peach, you make a good point.

Here is my game here, this will be much easier to read. It's not too urgent, I'll try making my game by spreading the collisions over a few files to avoid this issue. This issue won't stop me from making the game, but I really want to learn from it.

Below is the link for my game:

http://uploading.com/files/4948m315/Game1_11.zip/

Thanks in advance anyone who takes the time to look at it, it's not a massive game at the moment, it is just under 400 lines, I've tried to make it as easy to follow as possible.

views:2764 update:2012/2/8 8:46:10
corona forums © 2003-2011