Time for action – adding a main menu

We will create the frontend of our game by introducing the game title and the Play and Options buttons that will transition throughout different scenes in the application with ease.

  1. Create a new file called mainmenu.lua and import Composer and the UI modules, the composer.newScene() function, and the variables for timer and audio:
    local composer = require( "composer" )
    local scene = Composer.newScene()
    
    local ui = require("ui")
    
    local btnAnim
    
    local btnSound = audio.loadSound( "btnSound.wav" )
  2. Create the create() event. Add in the composer.removeScene( "maingame" ) and composer.removeScene( "options" ) lines, which will remove the "maingame" and "options" scenes. You can remove "maingame" after the player has transitioned from the main game screen and is sent to the main menu screen. You can remove "options" after the player has transitioned from the options screen and is sent to the main menu screen:
    -- Called when the scene's view does not exist:
    function scene:create( event )
      local sceneGroup = self.view
    
      -- completely remove maingame and options
      composer.removeScene( "maingame" )
      composer.removeScene( "options" )
    
      print( "\nmainmenu: create event" )
    end
  3. Add in the show() event and the backgroundImage display object;
    -- Called immediately after scene has moved onscreen:
    function scene:show( event )
      local sceneGroup = self.view
    
      print( "mainmenu: show event" )
    
      local backgroundImage = display.newImageRect( "mainMenuBG.png", 480, 320 )
      backgroundImage.x = 240; backgroundImage.y = 160
      sceneGroup:insert( backgroundImage )
  4. Introduce the playBtn display object and create a function called onPlayTouch(event) that uses composer.gotoScene() to change the scene to "loadgame". Use the "fade" effect to change scenes:
      local playBtn
    
      local onPlayTouch = function( event )
        if event.phase == "release" then
    
          audio.play( btnSound )
          composer.gotoScene( "loadgame", "fade", 300  )
    
        end
      end
    
      playBtn = ui.newButton{
        defaultSrc = "playbtn.png",
        defaultX = 100,
        defaultY = 100,
        overSrc = "playbtn-over.png",
        overX = 100,
        overY = 100,
        onEvent = onPlayTouch,
        id = "PlayButton",
        text = "",
        font = "Helvetica",
        textColor = { 255, 255, 255, 255 },
        size = 16,
        emboss = false
      }
    
      playBtn.x = 240; playBtn.y = 440
        sceneGroup:insert( playBtn )
  5. Transition the playBtn display object to y = 260 in 500 milliseconds using the easing.inOutExpo transition. Have it initialized through btnAnim:
    btnAnim = transition.to( playBtn, { time=1000, y=260, transition=easing.inOutExpo } )
  6. Introduce the optBtn display object and create a function called onOptionsTouch(event). Use composer.gotoScene() to transition the scene to "options" using the "crossFade" effect:
    local optBtn
    
      local onOptionsTouch = function( event )
        if event.phase == "release" then
    
          audio.play( btnSound )
          composer.gotoScene( "options", "crossFade", 300)
    
        end
      end
    
      optBtn = ui.newButton{
        defaultSrc = "optbtn.png",
        defaultX = 60,
        defaultY = 60,
        overSrc = "optbtn-over.png",
        overX = 60,
        overY = 60,
        onEvent = onOptionsTouch,
        id = "OptionsButton",
        text = "",
        font = "Helvetica",
        textColor = { 255, 255, 255, 255 },
        size = 16,
        emboss = false
      }
      optBtn.x = 430; optBtn.y = 440
      sceneGroup:insert( optBtn )
  7. Transition the optBtn display object to y = 280 in 500 milliseconds using the easing.inOutExpo transition. Have it initialized through btnAnim. Close the scene:show( event ) function with end:
      btnAnim = transition.to( optBtn, { time=1000, y=280, transition=easing.inOutExpo } )
    
    end
  8. Create the hide() event and cancel the btnAnim transition. Also, create the destroy() event:
    -- Called when scene is about to move offscreen:
    function scene:hide()
    
      if btnAnim then transition.cancel( btnAnim ); end
    
      print( "mainmenu: hide event" )
    
    end
    
    -- Called prior to the removal of scene's "view" (display group)
    function scene:destroy( event )
    
      print( "destroying mainmenu's view" )
    end
  9. Add the event listeners for all the scene events and for return scene. Save and close your file:
    -- "create" event is dispatched if scene's view does not exist
    scene:addEventListener( "create", scene )
    
    -- "show" event is dispatched whenever scene transition has finished
    scene:addEventListener( "show", scene )
    
    -- "hide" event is dispatched before next scene's transition begins
    scene:addEventListener( "hide", scene )
    
    -- "destroy" event is dispatched before view is unloaded, which can be
    scene:addEventListener( "destroy", scene )
    
    return scene
    Time for action – adding a main menu

On the main menu screen, we added an image that displayed the game title and the Play and Options buttons. The Options button is still not functional at this time. The onPlayTouch() function transitions the scene to "loadgame". This will change scenes to loadgame.lua. The Play button is placed at x = 240; y = 440, (middle and offscreen). When the scene loads, playBtn transitions to y = 260, so it pops up from the bottom of the screen in 1000 milliseconds.

The Options button does a similar thing. The optBtn object is placed to the right of the stage and pops up at y = 280 in 500 milliseconds.

The btnAnim transition is cancelled by transition.cancel( btnAnim ) through the scene:hide() function. It is important to clean timers, transitions, and event listeners every time you change scenes so that potential memory leaks do not occur while in the application.