Weird code behavior.. Please help

Hey all,

I am currently making a game where you move a ball by tilting your device and you must make the ball land on a certain platform. Once there is contact between the 2 objects, the platform teleports to a random position on screen and the ball bounces so you must make it land on the platform again, and again. You gain one point when colliding with the platform and you lose when the ball falls to the ground. Here is the actual level scene code (called “level1”) (I know the code is too long but please bear with me)

local composer = require( "composer" ) local scene = composer.newScene() local physics = require "physics" physics.start( ) function scene:create( event ) local sceneGroup = self.view end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is still off screen and is about to move on screen elseif phase == "did" then -- Called when the scene is now on screen -- -- INSERT code here to make the scene come alive -- e.g. start timers, begin animation, play audio, etc. local score = 0 local scoreText = display.newText( "Score: " .. score, 40, 0, native.systemFontBold, 20 ) scoreText:setFillColor( 1, 1, 1 ) local function platformCollision(self, event) if event.phase == "ended" then if event.target.type == "platform" and event.other.type == "ball" then timer.performWithDelay(1, function() self.x = math.random( 0, 300 ) self.y = math.random( 50, 300 ) self:setFillColor( math.random(0,1), math.random(0,1), math.random(0,1) ) end ) media.playSound( "jump.wav" ) end end end local function limitCollision(self, event) if event.phase == "ended" then if event.target.type == "limit" and event.other.type == "ball" then self:removeSelf( ) self = nil native.showAlert( "", "You scored " .. score .. " !" ) composer.removeScene( "level1", false ) composer.gotoScene( "menu", "fade", 500 ) end end end function GlobalCollision(event) if event.phase == "began" then if event.object1.type == "platform" and event.object2.type == "ball" then score = score + 1 scoreText.text = "Score: " .. score end end end local ball = display.newCircle( 100, 10, 10 ) ball.type = "ball" ball:setFillColor( 1,1,1 ) physics.addBody( ball, "dynamic", { bounce = 1 } ) local platform = display.newRect( 100, 100, 50, 5 ) physics.addBody( platform, "static" ) platform.type = "platform" platform.collision = platformCollision platform.strokeWidth = 1 local limit = display.newRect( display.actualContentWidth/2, display.actualContentHeight-150, display.actualContentWidth\*3 , 10 ) limit:setFillColor( 0,0,0 ) physics.addBody( limit, "static") limit.type = "limit" limit.collision = limitCollision local exit = display.newImage( "exxit.png", 160, 460 ) local function onAccelerate(event) ball.x = ball.x + event.xGravity \* 90 end local function exitf() native.showAlert( "", "You scored " .. score .. " !" ) composer.removeScene( "level1", false ) composer.gotoScene( "menu", "fade", 500 ) return true end exit:addEventListener( "touch", exitf ) limit:addEventListener( "collision", limit ) platform:addEventListener( "collision", platform ) Runtime:addEventListener( "collision", GlobalCollision ) Runtime:addEventListener("accelerometer", onAccelerate) sceneGroup:insert(platform) sceneGroup:insert(scoreText) sceneGroup:insert(ball) sceneGroup:insert(limit) sceneGroup:insert(exit) end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if event.phase == "will" then -- Called when the scene is on screen and is about to move off screen -- -- INSERT code here to pause the scene -- e.g. stop timers, stop animation, unload sounds, etc.) elseif phase == "did" then -- Called when the scene is now off screen platform:removeSelf( ) platform = nil end end function scene:destroy( event ) -- Called prior to the removal of scene's "view" (sceneGroup) -- -- INSERT code here to cleanup the scene -- e.g. remove display objects, remove touch listeners, save state, etc. local sceneGroup = self.view end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) ----------------------------------------------------------------------------------------- return scene

I tested the game on my Android and discovered quite a weird behavior:

When playing the game, the score stays 0 when colliding, when I lose, the game returns to menu but when I tap “Play” again and replay the level, the ball bounces without colliding with the actual platform, it seems like it is bouncing on invisible platforms. And the more I restart the level (without quitting the app) the more frequent the “invisible platforms”. What’s funny is that the score actually goes up when the ball collides with an “invisible plarform” but remains the same when colliding with the actual platform.

I seriously need someone to help me

Thank you :slight_smile:

Have you tried to add 

physics.setDrawMode( "hybrid" )

 That will show all the physics body’s that are being added…

And here’s your code … i cut it down a bit but it should work like before…

local composer = require( "composer" ) local scene = composer.newScene() local physics = require "physics" physics.start( ) function scene:create( event ) local sceneGroup = self.view end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "did" then local score = 0 local scoreText = display.newText( "Score: " .. score, 40, 0, native.systemFontBold, 20 ) scoreText:setFillColor( 1, 1, 1 ) local function platformCollision(self, event) if event.phase == "ended" then if event.target.type == "platform" and event.other.type == "ball" then timer.performWithDelay(1, function() self.x = math.random( 0, 300 ) self.y = math.random( 50, 300 ) self:setFillColor( math.random(0,1), math.random(0,1), math.random(0,1) ) end ) media.playSound( "jump.wav" ) end end end local function limitCollision(self, event) if event.phase == "ended" then if event.target.type == "limit" and event.other.type == "ball" then self:removeSelf( ) self = nil native.showAlert( "", "You scored " .. score .. " !" ) composer.removeScene( "level1", false ) composer.gotoScene( "menu", "fade", 500 ) end end end function GlobalCollision(event) if event.phase == "began" then if event.object1.type == "platform" and event.object2.type == "ball" then score = score + 1 scoreText.text = "Score: " .. score end end end local ball = display.newCircle( 100, 10, 10 ) ball.type = "ball" ball:setFillColor( 1,1,1 ) physics.addBody( ball, "dynamic", { bounce = 1 } ) local platform = display.newRect( 100, 100, 50, 5 ) physics.addBody( platform, "static" ) platform.type = "platform" platform.collision = platformCollision platform.strokeWidth = 1 local limit = display.newRect( display.actualContentWidth/2, display.actualContentHeight-150, display.actualContentWidth\*3 , 10 ) limit:setFillColor( 0,0,0 ) physics.addBody( limit, "static") limit.type = "limit" limit.collision = limitCollision local exit = display.newImage( "exxit.png", 160, 460 ) local function onAccelerate(event) ball.x = ball.x + event.xGravity \* 90 end local function exitf() native.showAlert( "", "You scored " .. score .. " !" ) composer.removeScene( "level1", false ) composer.gotoScene( "menu", "fade", 500 ) return true end exit:addEventListener( "touch", exitf ) limit:addEventListener( "collision", limit ) platform:addEventListener( "collision", platform ) Runtime:addEventListener( "collision", GlobalCollision ) Runtime:addEventListener("accelerometer", onAccelerate) sceneGroup:insert(platform) sceneGroup:insert(scoreText) sceneGroup:insert(ball) sceneGroup:insert(limit) sceneGroup:insert(exit) end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if phase == "did" then -- Called when the scene is now off screen platform:removeSelf( ) platform = nil end end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) return scene

I haven’t looked over your code much but i dont see where you remove your eventListeners and timers and stuff…

You will have to manually remove listeners and times and stuff like that…

Good Luck!

I see… Can you explain how to remove event listeners or at least give me a link explaining how to ? And where should I delete them ? In the scene:hide() function “did” phase ?

Thank you for your effort :slight_smile:

This is just an example but you do this…

Runtime:removeEventListener("accelerometer", onAccelerate)

All you change is “add” to “remove” and put it in a function like this 

local function removeThings() Runtime:removeEventListener("accelerometer", onAccelerate) --Next listener --next --next end removeThings()

And you can do it in your show scene like this.

 function removeThings() Runtime:removeEventListener("accelerometer", onAccelerate) --Next listener --next --next end local function exitf() removeThings() native.showAlert( "", "You scored " .. score .. " !" ) composer.removeScene( "level1", false ) composer.gotoScene( "menu", "fade", 500 ) return true end

Good luck!

The idea of removing them in the scene:show() function somewhat confuses me.

Can I remove them in the scene:hide() function  :huh: ?

Yes, I believe you can…l I have never tried it but i’m pretty sure you can… 

Mate you are a life saver. :)  Thank you for assisting me 

It didn’t work man :frowning:

I wrote the function in the scene:hide() “did” phase but It didn’t work :-(((

my guess is it didn’t work because scope is not seeing it.

–SonicX278

I read about scope and solved the issue about the score text not updating properly :slight_smile:

However I’m still stuggling with the invisible platforms :frowning:

And something confuses me, is it better to declare display objects in the scene:create() or scene:show() function ? Same question about functions and event listeners.

And how could I remove objects and their listeners if they are local variables not available in all code functions ?

I’m sorry if my questions are obvious, but I’m trying so hard to figure out a solution !

Hello, I’m out of state so in on my phone so here is the best I can answer you with.

You have to put your display objects into scene show after the did phase and add then to the self.view(aka sceneGroup). Try adding hybrid mode to the physics and see if objects are being randomly added.

To remove an object you do

display.remove(objectName)

To remove a listener you do

Runtime/orObject:removeEventListener( “listenerType”, function )

–SonicX278

So should I remove the objects/listeners in which scene event ?

In the did phase of scene show

So you make a function and then call it when you are changing scenes …

Local function removeThings()
Display.remove
Listener remove
End

And then you call it with

removeThings()

Good luck!

so for example: if I press the exit button an exit function is executed and within this function, removeThings() is called ?

Exactly! But make sure scope sees the function being called… If it doesn’t then make it global… But try to stay away from globals…

IT FINALLY WORKED !!! I had to declare the display objects as global variables and made a function removing all display objects and only the Runtime event listener. Thank you very much !! 

This issue has been solved. However, there is not a “one-post solution” but rather a serie of questions and answers.

Have you tried to add 

physics.setDrawMode( "hybrid" )

 That will show all the physics body’s that are being added…

And here’s your code … i cut it down a bit but it should work like before…

local composer = require( "composer" ) local scene = composer.newScene() local physics = require "physics" physics.start( ) function scene:create( event ) local sceneGroup = self.view end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "did" then local score = 0 local scoreText = display.newText( "Score: " .. score, 40, 0, native.systemFontBold, 20 ) scoreText:setFillColor( 1, 1, 1 ) local function platformCollision(self, event) if event.phase == "ended" then if event.target.type == "platform" and event.other.type == "ball" then timer.performWithDelay(1, function() self.x = math.random( 0, 300 ) self.y = math.random( 50, 300 ) self:setFillColor( math.random(0,1), math.random(0,1), math.random(0,1) ) end ) media.playSound( "jump.wav" ) end end end local function limitCollision(self, event) if event.phase == "ended" then if event.target.type == "limit" and event.other.type == "ball" then self:removeSelf( ) self = nil native.showAlert( "", "You scored " .. score .. " !" ) composer.removeScene( "level1", false ) composer.gotoScene( "menu", "fade", 500 ) end end end function GlobalCollision(event) if event.phase == "began" then if event.object1.type == "platform" and event.object2.type == "ball" then score = score + 1 scoreText.text = "Score: " .. score end end end local ball = display.newCircle( 100, 10, 10 ) ball.type = "ball" ball:setFillColor( 1,1,1 ) physics.addBody( ball, "dynamic", { bounce = 1 } ) local platform = display.newRect( 100, 100, 50, 5 ) physics.addBody( platform, "static" ) platform.type = "platform" platform.collision = platformCollision platform.strokeWidth = 1 local limit = display.newRect( display.actualContentWidth/2, display.actualContentHeight-150, display.actualContentWidth\*3 , 10 ) limit:setFillColor( 0,0,0 ) physics.addBody( limit, "static") limit.type = "limit" limit.collision = limitCollision local exit = display.newImage( "exxit.png", 160, 460 ) local function onAccelerate(event) ball.x = ball.x + event.xGravity \* 90 end local function exitf() native.showAlert( "", "You scored " .. score .. " !" ) composer.removeScene( "level1", false ) composer.gotoScene( "menu", "fade", 500 ) return true end exit:addEventListener( "touch", exitf ) limit:addEventListener( "collision", limit ) platform:addEventListener( "collision", platform ) Runtime:addEventListener( "collision", GlobalCollision ) Runtime:addEventListener("accelerometer", onAccelerate) sceneGroup:insert(platform) sceneGroup:insert(scoreText) sceneGroup:insert(ball) sceneGroup:insert(limit) sceneGroup:insert(exit) end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if phase == "did" then -- Called when the scene is now off screen platform:removeSelf( ) platform = nil end end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) return scene

I haven’t looked over your code much but i dont see where you remove your eventListeners and timers and stuff…

You will have to manually remove listeners and times and stuff like that…

Good Luck!

I see… Can you explain how to remove event listeners or at least give me a link explaining how to ? And where should I delete them ? In the scene:hide() function “did” phase ?

Thank you for your effort :slight_smile:

This is just an example but you do this…

Runtime:removeEventListener("accelerometer", onAccelerate)

All you change is “add” to “remove” and put it in a function like this 

local function removeThings() Runtime:removeEventListener("accelerometer", onAccelerate) --Next listener --next --next end removeThings()

And you can do it in your show scene like this.

 function removeThings() Runtime:removeEventListener("accelerometer", onAccelerate) --Next listener --next --next end local function exitf() removeThings() native.showAlert( "", "You scored " .. score .. " !" ) composer.removeScene( "level1", false ) composer.gotoScene( "menu", "fade", 500 ) return true end

Good luck!