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.