In this tutorial I added a few new lines of code to my Rolly Bear World project. The events which needed happen when a user completes a level is still missing at this point. When Rolly Bear gets successfully launched and bounced to the treasure chest, the chest should open and a trophy should be rewarded to the user. Next, an overlay should be displayed to navigate the user either back to the level selection screen or to the next level of the game.
See screenshots:
After being almost 4 weeks in Thailand we did the notorious border crossing between Thailand and Cambodia at Poipet. The complete journey from Bangkok to Siem Reap took us overland about 10 hours. 4 hours were just dealing with customs and border control in Cambodia. Besides paying off a corrupt police officer for 100 Baht (about 3 USD), we didn’t fall for much of the scams going on at the border. I honestly have never seen so many dollar bills disappear in foreign passports to bring the total time of 4 hours back to a few minutes. Because my of proud against corruption we ended up waiting 4 hours at the border. In Siemp Reap we did the usual stuff visiting Angkor Wat and Pub street, which is in one word amazing! But one day we urged to do something else and we rented some motorbikes (125 CC Honda Dreams) and explored the country sides of Cambodia, including a peak into a magic mushroom farm.
Back to Corona SDK :). Open your level01.lua file and create a global variable currentLevel = 1, we will use this variable later to pass on to the overlay so we can determine what the next level is that need to be showed to the user (which is currentLevel + 1).
Put in you level01.lua a global variable:
local currentLevel = 1
Now we first want to determine when a user wins the game. In Rolly Bear World this happens when Rolly Bear gets to the treasure chest. In Corona SDK, we can determine this with a collision event. We already developed this for the game over part of Rolly Bear. Click here if you missed this tutorial. Now we need to extend this collision function when RollyBear gets into collision with the treasure chest (a.k.a. winning the level!)
Note that a few things need to happen when this collision occurs:
- We remove the runtime listener onCollision and set the alpha level of Rolly Bear to 0.
- We replace the closed chest with an image of an open chest.
- We transition a heart (trophy) from the middle of the chest toward the center of the screen.
- We make the trophy a bit larger with xScale and yScale.
- Finally we show an overlay that mentions that the level has been completed.
function onCollision(event) --- events which happen when rollbear collides with the treasure chest if (event.object1.myName=="chestClosed" and event.object2.myName=="rollybear") then print ("Yes! found the treasure") Runtime:removeEventListener("collision", onCollision) display.remove (chestClosed) local chestopen = display.newImage("images/chestopen.png") chestopen.x = chestClosed.x chestopen.y = chestClosed.y group:insert(chestopen) trophy:toFront() local function trophyEffect (event) local function showOverlayNext() transition.to( trophy, {time=600, alpha=0} ) storyboard.showOverlay( "gamecompleteoverlay" ,{effect = "fade" , params ={curLevel = currentLevel}, isModal = true} ) end local function enlargeTrophy() transition.to( trophy, {time=500, xScale = 2.0, yScale = 2.0, onComplete=showOverlayNext} ) end timer.performWithDelay ( 100, enlargeTrophy ) end transition.to( trophy, {time=500, x = centerX, y = centerY, onComplete=trophyEffect} ) rollybear.alpha = 0 end --- events which happen when Rollbear collides to become GameOver if(event.object1.myName=="rightwall" and event.object2.myName=="rollybear") or (event.object1.myName=="leftwall" and event.object2.myName=="rollybear") or (event.object1.myName=="topwall" and event.object2.myName=="rollybear") or (event.object1.myName=="bottomwall" and event.object2.myName=="rollybear") or (event.object1.myName=="floor" and event.object2.myName=="rollybear") then Runtime:removeEventListener("collision", onCollision) rollybear.alpha = 0 storyboard.showOverlay( "gameoveroverlay" ,{effect = "fade" , params ={curLevel = currentLevel}, isModal = true} ) --storyboard.showOverlay( "gameoveroverlay" ,{effect = "fade" , params ={levelNum = "level01"}, isModal = true} ) end end Runtime:addEventListener("collision", onCollision)
As you can see we pass into the overlay the currentLevel variable, so that the overlay is aware of which level calls this overlay (line 15).
This is the parameter in the storyboard.showOverlay, which passes the currentLevel variable:
params ={curLevel = currentLevel}
Now create a new .lua file and call it “gamecompleteoverlay.lua” This .lua file has the layout and functionality of the level complete overlay.
In this file we have the black rectangle to make sure that the user first deals with the overlay before continuing with the game. In case you missed this discussion please visit my previous post. (line 28 – 33).
Next is the overlay itself which is a wooden sign with two button: A “Next level” and a “back to level selection” button. These are the variables called levelBtn and nextlevelBtn and both listen to the function: btnTap through an eventlistener.
The gotoScene function in btnTap take as parameter “event.target.destination” which is defined for each of the buttons. Lets start with the easiest one the levelsBtn.
levelBtn.destination = "levels"
When the levelBtn is clicked this destination parameter takes the user directly to levels.lua. As the destination is passed on in the btnTap function as event.target.destination. Corona SDK knows that “levels” means open the “levels.lua” file in the project folder of the game.
For the nextlevelBtn we need to have some more information. We want to reuse this code across all levels, therefore, we need to know what the currentLevel is before we can decide which new level (file) we need to load through the btnTap function (line 43)
In the definition of the nextlevelBtn we get the params = event.params (this holds the currentLevel variable), we already passed this into the gamecompleteoverlay.lua by defining it in the show.Overlay when a collision happened in levels01.lua (line 15). We then increment this with 1 and store it in a variable called nextLevel (line 51)
We need the incremented nextLevel variable to set the destination of the nextlevelBtn and set it to a string value. In case level01 is completed the currentLevel variable 1 is passed on and incremented with 1 (1+1 = 2) and is set as level02 in the nextlevelBtn.destination ( “level”..tostring(nextLevel)) and consequently passed on in the tapBtn function (line 52 and 54). A very important note is that all your level files should have the same convention: level01.lua, level02.lua, level03.lua etc.
-- Rolly Bear World Project by Christian Peeters -- See all tutorial @christian.peeters.com local storyboard = require( "storyboard" ) local scene = storyboard.newScene() local physics = require("physics") local level01 = require("level01") -- local forward references should go here -- local function btnTap(event) event.target.xScale = 0.95 event.target.yScale =0.95 storyboard.gotoScene (event.target.destination, {effect = "fade"} ) return true end function catchBackgroundOverlay(event) return true end -- Called when the scene's view does not exist: function scene:createScene( event ) local group = self.view local backgroundOverlay = display.newRect (group, leftScrn-1000, topScrn-1000, withScrn+1000, heightScrn+1000) backgroundOverlay:setFillColor( black ) backgroundOverlay.alpha = 0.6 backgroundOverlay.isHitTestable = true backgroundOverlay:addEventListener ("tap", catchBackgroundOverlay) backgroundOverlay:addEventListener ("touch", catchBackgroundOverlay) local overlay = display.newImageRect ("images/overlay_complete.png", 400 , 250) overlay.x = centerX overlay.y = centerY group:insert (overlay) local levelBtn = display.newImageRect ("images/levelBtn.png", 112, 116 ) levelBtn.x = centerX + overlay.width / 4 levelBtn.y = centerY + overlay.height/2.2 levelBtn.destination = "levels" levelBtn:addEventListener("tap", btnTap) group:insert(levelBtn) local nextlevelBtn = display.newImageRect ("images/nextlevelBtn.png" ,112, 116) nextlevelBtn.x = centerX - overlay.width / 4 nextlevelBtn.y = centerY + overlay.height/2.2 params = event.params nextLevel = params.curLevel + 1 nextlevelBtn.destination = "level"..tostring(nextLevel) print(nextlevelBtn.destination) nextlevelBtn:addEventListener ("tap", btnTap) group:insert (nextlevelBtn) end -- Called immediately after scene has moved onscreen: function scene:enterScene( event ) local group = self.view -- INSERT code here (e.g. start timers, load audio, start listeners, etc.) end -- Called when scene is about to move offscreen: function scene:exitScene( event ) local group = self.view -- INSERT code here (e.g. stop timers, remove listeners, unload sounds, etc.) -- Remove listeners attached to the Runtime, timers, transitions, audio tracks end -- Called prior to the removal of scene's "view" (display group) function scene:destroyScene( event ) local group = self.view -- INSERT code here (e.g. remove listeners, widgets, save state, etc.) -- Remove listeners attached to the Runtime, timers, transitions, audio tracks end --------------------------------------------------------------------------------- -- END OF YOUR IMPLEMENTATION --------------------------------------------------------------------------------- -- "createScene" event is dispatched if scene's view does not exist scene:addEventListener( "createScene", scene ) -- "enterScene" event is dispatched whenever scene transition has finished scene:addEventListener( "enterScene", scene ) -- "exitScene" event is dispatched before next scene's transition begins scene:addEventListener( "exitScene", scene ) -- "destroyScene" event is dispatched before view is unloaded, which can be -- automatically unloaded in low memory situations, or explicitly via a call to -- storyboard.purgeScene() or storyboard.removeScene(). scene:addEventListener( "destroyScene", scene ) --------------------------------------------------------------------------------- return scene