Scenes issue-Corona

So I’ve bee creating a simon-says type game for a school assessment and came across an issue when incorporating the game into scenes. I currently have a menu scene, highscores scene and game scene in which the transition between the menu and highscores works fine. However, when trying to leave the game scene to go to the menu scene, none of the images/sprites on the screen are removed. I’m not sure why this is occurring and would like some help. Here is the code:

local composer = require( "composer")

local scene = composer.newScene() – create scene


– Code outside of the scene event functions below will only be executed ONCE unless
– the scene is removed entirely (not recycled) via “composer.removeScene()”


display.setStatusBar(display.HiddenStatusBar) – Hide status bar

–Setting up variables
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local w = display.contentWidth
local h = display.contentHeight
local fullw = display.actualContentWidth
local fullh = display.actualContentHeight
local left = centerX - fullw/2
local right = left + fullw
local top = centerY - fullh/2
local bottom = top + fullh

local wait = false
local playerTurn = false

local maxSequenceLength = 0
local sequenceLength = 0
local currentSequence = {} – A table for the sequence that the computer generates, which increases every turn
local playerSequence = {} – A table which records the player presses.

local squares = {}

–Setting the colors for when the squares are pressed
local activeColor = {}
activeColor[1] = { 1, 0, 0 }
activeColor[2] = {0.25, 1, 0.25}
activeColor[3] = {0.25, 1, 1}
activeColor[4] = {1, 1, 0}

local inactiveColor = {}
inactiveColor[1] = {0.78, 0, 0}
inactiveColor[2] = {0, 0.78, 0}
inactiveColor[3] = {0, 0.5, 0.78}
inactiveColor[4] = {0.78, 0.78, 0}

–Positioning the squares
local squareOffsets = {}
squareOffsets[1] = { x = -200, y = -75 }
squareOffsets[2] = { x = -75, y = -75 }
squareOffsets[3] = { x = -200, y = 50 }
squareOffsets[4] = { x = -75, y = 50 }

– Loading Sounds
local squareSounds = {}
squareSounds[1] = audio.loadSound( “sounds/redSound.wav” )
squareSounds[2] = audio.loadSound( “sounds/blueSound.wav”)
squareSounds[3] = audio.loadSound( “sounds/greenSound.wav”)
squareSounds[4] = audio.loadSound( “sounds/yellowSound.wav”)

local failSound = audio.loadSound( “sounds/failSound.wav”)

–Labels
local playButton
local playButtonText
local sequenceText
local maxSequenceText
local badLuck
local menuButton
local menuButtonText
local tmp

–Function declerations
local drawSquares
local squarePress

local playSequence

local onSquareTouch
local onPlay_RepeatSquare

–Definitions/Functions--------------------------------------------------------------------------------------------------------------

– Function for lighting or un-lighting the squares
local function squarePress (num, inactive)

local inactive = inactive or false

if(inactive) then
	squares[num]:setFillColor( unpack( inactiveColor[num]))
	squares[num].fill.effect = "filter.none"
else
	squares[num]:setFillColor( unpack( activeColor[num]))
	squares[num].fill.effect = "filter.dissolve"
	squares[num].fill.effect.threshold = 0.4
	audio.play( squareSounds[num])
end

end

– Function for checking the players presses versus the correct sequence---------------------------------------------------------------
local function isCorrectSequence()

for i = 1, #playedSequence do
	print(currentSequence[i], playedSequence[i]) --This prints the correct choice in the sequence compared to the players choice
	if (currentSequence[i] ~= playedSequence[i]) then
		return false
	end
end

return true

end

– Function for setting up the sequence-----------------------------------------------------------------------------------------
local function playSequence ( generate )
local generate = generate or false

--add another level to the sequence
if( generate ) then
	currentSequence[#currentSequence+1] = math.random(1,4)

	sequenceLength = sequenceLength + 1
	sequenceText.text = "Level: " .. sequenceLength
end

--Display the sequence back to the player
for i = 1, #currentSequence do
	timer.performWithDelay( 750 * i, 
		function()
			squarePress( currentSequence[i] )
		end
	)
	timer.performWithDelay( 750 * i + 400, 
		function()
			squarePress( currentSequence[i], true )
		end
	)
end

--Wait until the sequence is played then allow the player to touch the squares 
	timer.performWithDelay( 750 * #currentSequence + 400, 
		function()
			wait = false
			playersTurn = true 
			playedSequence = {}
		end
	)
end

– on square touch is an event listener for the colored squares------------------------------------------------------------------
local function onSquareTouch( event )
local phase = event.phase
local target = event.target

-- Ignore the touches if not the players turn 
if ( not playersTurn ) then
	return true
end

--Highlight the button when pressed
if (event.phase == "began") then 
	squarePress( target.myNum )
	display.getCurrentStage():setFocus(event.target)

-- Un-highlight the button and check the sequence as compared to the player so far and release focus
elseif(event.phase == "ended") then
	squarePress( target.myNum, true )
	display.getCurrentStage():setFocus(nil)

	--Add a new key to "played sequence"
	playedSequence[#playedSequence+1] = target.myNum

	-- If the played sequence and the current sequence are the same length do one final check then generate a new sequence 
	if(#playedSequence == #currentSequence) then

		--If it is right
		if( isCorrectSequence() ) then
			pleaseWait = true
			playersTurn = false 
			timer.performWithDelay( 500, function() playSequence( true ) end )

			if(maxSequenceLength < sequenceLength) then
				maxSequenceLength = sequenceLength 
				maxSequenceText.text = "Highscore: " .. maxSequenceLength
			end

			--If last choice was wrong
		else
			currentSequence = {}
			playersTurn = false 
			wait = true 
			badLuck = display.newText( "Bad Luck", 160, 75, native.systemFont, 48)
			audio.play(failSound)
			timer.performWithDelay( 2000,
				function()
					display.remove( badLuck )
					badLuck = nil
					playButtonText.text = "Play Game"
					wait = false
					composer.setVariable( "finalScore", score )
				end
			)

		end

		--Test what has been pressed so far
	elseif( not isCorrectSequence()) then
		currentSequence = {}
		playersTurn = false
		wait = true
		badLuck = display.newText( "Bad Luck", 160, 75, native.systemFont, 48)
		audio.play(failSound)
		timer.performWithDelay( 2000,
			function()
				display.remove( badLuck )
				badLuck = nil
				playButtonText.text = "Play Game"
				wait = false 
				composer.setVariable( "finalScore", score )
			end
		)
	end
end
return true 

end

– This is the event handler for the play game/repeat button-----------------------------------------------------------------
local function onPlay_RepeatSquare( event )
local phase = event.phase
local target = event.target
local label = target.label

--Dont do anything if the wait variable is true 
	if( wait ) then
		return true 
	end

	--Brighten up on touch
	if(event.phase == "began") then
		target:setFillColor( 0.25, 0.25, 0.25, 1)
		display.getCurrentStage():setFocus(event.target)

	--At the end of the touch, un highlight the button and either start the game or repeat sequence
elseif(event.phase == "ended") then
	target:setFillColor( 0.5, 0.5, 0.5, 1 )
	display.getCurrentStage():setFocus(nil)

	--If the button label is "play game" then start game
	if(label.text == "Play Game") then
		label.text = "Repeat"
		wait = true 
		sequenceLength = 0
		timer.performWithDelay( 1000, function() playSequence( true )end) --Generate sequence

		--Otherwise repeat current sequence
	else
		playSequence()
	end

	wait = true
	playersTurn = false
end
return true

end

– Function to go to menu
local function gotoMenu( event)

-- Dont do anything if wait variable is true
	if( wait ) then
		return true
	end

	if(event.phase == "began") then
		composer.gotoScene("menu", {time = 800, effect = "crossFade"})
	end

end

–drawSquares function draws the squares-----------------------------------------------------------------------------------
local function drawSquares()

local tmp

local xOffset = 140

-- Display Squares (white square is colored and placed in a table)
local placement = { 0, 90, 270, 180 }
for i = 1, 4 do
	tmp = display.newImageRect( "images/white.png", 100, 100)
	tmp.x = centerX + squareOffsets[i].x + xOffset
	tmp.y = centerY + squareOffsets[i].y
	tmp:setFillColor( unpack( inactiveColor[i]))


	tmp.placement = placement[i]

	tmp.myNum = i

	tmp:addEventListener( "touch", onSquareTouch )


	squares[i] = tmp

end

end

–scene event functions

--Create()
function scene:create(event)

	local sceneGroup = self.view

--Add a title
local simonSaysText = display.newText("Simon Squares", 0, 0, native.systemFont, 36)
simonSaysText.x = left + 160
simonSaysText.y = top + 100
simonSaysText:setFillColor( 100, 0, 0)


--Add a play again button

playButton = display.newRect( 0, 0, 240, 60 )
playButton.x = 162
playButton.y = bottom - 75
playButton:setStrokeColor( 0.25, 0.25, 0.25, 1 )
playButton:setFillColor( 0.5, 0.5, 0.5, 1 )
playButton.strokeWidth = 3
playButton:addEventListener( "touch", onPlay_RepeatSquare ) --Listener for playButton

--Text for playButton
playButtonText = display.newText( "Play Game", 0, 0, native.systemFont, 36)
playButtonText.x = playButton.x
playButtonText.y = playButton.y
playButtonText:setFillColor(0,0,0)
playButton.label = playButtonText

--Add a menu button
menuButton = display.newRect( 0, 0, 240, 60)
menuButton.x = left + 160
menuButton.y = top + 100
menuButton:setStrokeColor( 0.25, 0.25, 0.25, 1)
menuButton:setFillColor( 0.5, 0.5, 0.5, 1)
menuButton.strokeWidth = 3
menuButton:addEventListener( "touch", gotoMenu)

--Text for menu button
menuButtonText = display.newText( "Menu", 0, 0, native.systemFont, 36)
menuButtonText.x = menuButton.x
menuButtonText.y = menuButton.y
menuButtonText:setFillColor( 0, 0, 0)
menuButton.label = menuButtonText

--Sequence Labels
sequenceText = display.newText( "Level: 0", 0, 0, native.systemFont, 48)
sequenceText.anchorX = 1
sequenceText.x = left + 240
sequenceText.y = top + 500

maxSequenceText = display.newText( "Highscore: 0", 0, 0, native.systemFont, 36)
maxSequenceText.anchorX = 1
maxSequenceText.x = left + 260
maxSequenceText.y = top + 550



--Run listener

drawSquares()

end

–show()
function scene:show(event)

local sceneGroup = self.view
local phase = event.phase

if ( phase == "will" ) then


elseif ( phase == "did") then
	
end

end

– hide()
function scene:hide(event)

local sceneGroup = self.view
local phase = event.phase

if ( phase == "will") then
	--Code runs here when scene is on screen but about to go off

elseif ( phase == "did") then
	--Code runs here after scene goes entirely off screen
	Runtime:removeEventListener( "touch", onSquareTouch)
	composer.removeScene("game")
end

end

–destroy()
function scene:destroy(event)

local sceneGroup = self.view

end

– Scene event function listeners
scene:addEventListener(“create”, scene)
scene:addEventListener(“show”, scene)
scene:addEventListener(“hide”, scene)
scene:addEventListener(“destroy”, scene)

return scene


Any help would be much appreciated thanks :slight_smile:

If you want composer to manage your display objects, then you need to add said display objects to the sceneGroup.

See https://docs.coronalabs.com/guide/system/composer/index.html.

1 Like

I didn’t run your code. But just glancing at it shows you do not add you visual items to the ‘sceneGroup’ and therefore are not a part of your scene. So when you go to another scene those visual items don’t get destroyed with your older scene. Simple add ‘sceneGroup’ as the first variable to display items you creat. For example:
playButtonText = display.newText( sceneGroup, “Play Game”, 0, 0, native.systemFont, 36)
and:
menuButton = display.newRect( sceneGroup, 0, 0, 240, 60)

Hope this helps

1 Like