Text Adventure Storyboard issues

Hi everyone,

I am working on my very first project in LUA (or any other language for that matter) and decided to make a very linear text based adventure for android. I am having an issue with scrollviews in storyboard. The first scene loads fine, but when i use a button to move to the second scene, all of the text for the first scene is still in the background and can still be moved independently of the new scene. I took the example from the sample app for reference and have just added to it.


– scene1.lua


local widget = require( “widget” )

local storyboard = require( “storyboard” )

local scene = storyboard.newScene()


– 

–    NOTE:

–    

–    Code outside of listener functions (below) will only be executed once,

–    unless storyboard.removeScene() is called.

– 



– BEGINNING OF YOUR IMPLEMENTATION


– Called when the scene’s view does not exist:

function scene:createScene( event )

    local group = self.view

local function scrollListener( event )

   local phase = event.phase

   print( phase )

   local direction = event.direction

   – If the scrollView has reached it’s scroll limit

   if ( event.limitReached ) then

      if ( “up” == direction ) then

         print( “Reached Top Limit” )

      elseif ( “down” == direction ) then

         print( “Reached Bottom Limit” )

      elseif ( “left” == direction ) then

         print( “Reached Left Limit” )

      elseif ( “right” == direction ) then

         print( “Reached Right Limit” )

      end

   end

   return true

end

local scrollView = widget.newScrollView

{

   left = 0,

   top = 20,

   width = display.contentWidth,

   height = display.contentHeight,

   scrollWidth = 465,

   scrollHeight = 670,

   friction = 0.972,

   listener = scrollListener,

   

   backgroundColor = {0,0,0}

   

}

–Create a large text string

local thisText = “SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…SCENE ONE TESTING SCROLLING…” 

–Create a text object containing the large text string and insert it into the scrollView

local sceneObject = display.newText( thisText, 0,20, 250,1000, “Times New Roman”, 20)

sceneObject:setTextColor( 255,255,255 ) 

sceneObject:setReferencePoint( display.TopCenterReferencePoint )

sceneObject.x = display.contentCenterX

scrollView:insert( sceneObject )

local option1 = widget.newButton

    {

        width = display.contentWidth,

        height = 59,

        label = “SCENE2”,

    onRelease = goBack,

        onPress = function()

 storyboard.gotoScene( “scene2”,“fade”,400 );end,

    }

    option1.x = display.contentWidth - option1.width/2

    option1.y = sceneObject.contentHeight - option1.height/2

    scrollView:insert( option1 )

  

  local option2 = widget.newButton

    {

        width = display.contentWidth,

        height = 59,

        label = “YOU DIE HAHA”,

        onRelease = goBack,

    }

    option2.x = display.contentWidth - option2.width/2

    option2.y = sceneObject.contentHeight + option1.height - option2.height/2

    scrollView:insert( option2 )

    -----------------------------------------------------------------------------

        

    –    CREATE display objects and add them to ‘group’ here.

    –    Example use-case: Restore ‘group’ from previously saved state.

    

    -----------------------------------------------------------------------------

    

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.)

    

    -----------------------------------------------------------------------------

    

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.)

    

    -----------------------------------------------------------------------------

    

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

in your createScene code you’ll need to add the scrollview to the scene’s group:

group:insert(scrollView)

would that be instead of self.view?

No, like this:  

-- -- scene1.lua -- ---------------------------------------------------------------------------------- local widget = require( "widget" ) local storyboard = require( "storyboard" ) local scene = storyboard.newScene() ---------------------------------------------------------------------------------- -- -- NOTE: -- -- Code outside of listener functions (below) will only be executed once, -- unless storyboard.removeScene() is called. -- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -- BEGINNING OF YOUR IMPLEMENTATION --------------------------------------------------------------------------------- -- Called when the scene's view does not exist: function scene:createScene( event ) local group = self.view local function scrollListener( event ) local phase = event.phase print( phase ) local direction = event.direction -- If the scrollView has reached it's scroll limit if ( event.limitReached ) then if ( "up" == direction ) then print( "Reached Top Limit" ) elseif ( "down" == direction ) then print( "Reached Bottom Limit" ) elseif ( "left" == direction ) then print( "Reached Left Limit" ) elseif ( "right" == direction ) then print( "Reached Right Limit" ) end end return true end local scrollView = widget.newScrollView { left = 0, top = 20, width = display.contentWidth, height = display.contentHeight, scrollWidth = 465, scrollHeight = 670, friction = 0.972, listener = scrollListener, backgroundColor = {0,0,0} } --Create a large text string local thisText = "SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING.....SCENE ONE TESTING SCROLLING....." --Create a text object containing the large text string and insert it into the scrollView local sceneObject = display.newText( thisText, 0,20, 250,1000, "Times New Roman", 20) sceneObject:setTextColor( 255,255,255 ) sceneObject:setReferencePoint( display.TopCenterReferencePoint ) sceneObject.x = display.contentCenterX scrollView:insert( sceneObject ) local option1 = widget.newButton { width = display.contentWidth, height = 59, label = "SCENE2", onRelease = goBack, onPress = function() storyboard.gotoScene( "scene2","fade",400 );end, } option1.x = display.contentWidth - option1.width/2 option1.y = sceneObject.contentHeight - option1.height/2 scrollView:insert( option1 ) local option2 = widget.newButton { width = display.contentWidth, height = 59, label = "YOU DIE HAHA", onRelease = goBack, } option2.x = display.contentWidth - option2.width/2 option2.y = sceneObject.contentHeight + option1.height - option2.height/2 scrollView:insert( option2 ) group:insert(scrollView) ----------------------------------------------------------------------------- -- CREATE display objects and add them to 'group' here. -- Example use-case: Restore 'group' from previously saved state. ----------------------------------------------------------------------------- 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.) ----------------------------------------------------------------------------- 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.) ----------------------------------------------------------------------------- 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

Awesome that seems to have worked - it did create a second problem though. In my main.lua i have 3 buttons, one of which is supposed to start scene1. it now does that, but the buttons from main stay on the screen

local storyboard = require “storyboard”

local widget = require “widget”

– load first scene

local option1 = widget.newButton

    {

    top = 280,

        width = display.contentWidth,

        height = 59,

        label = “Start Game”,

    onRelease = goBack,

        onPress = function() storyboard.gotoScene( “scene1”,“fade”,400 ); end,

    }

  

  – other options

  

  local option2 = widget.newButton

    {

    top = 340,

        width = display.contentWidth,

        height = 59,

        label = “Help”,

    onRelease = goBack,

  }

  

  local option3 = widget.newButton

    {

    top = 400,

        width = display.contentWidth,

        height = 59,

        label = “Quit”,

    onRelease = goBack,

    }

Well, really there are a couple ways to fix it.  But since you are using storyboard then you should stick with the storyboard way:

This should be your button screen code:

-- -- -- ---------------------------------------------------------------------------------- local widget = require( "widget" ) local storyboard = require( "storyboard" ) local scene = storyboard.newScene() ---------------------------------------------------------------------------------- -- -- NOTE: -- -- Code outside of listener functions (below) will only be executed once, -- unless storyboard.removeScene() is called. -- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -- BEGINNING OF YOUR IMPLEMENTATION --------------------------------------------------------------------------------- -- Called when the scene's view does not exist: function scene:createScene( event ) local group = self.view ----------------------------------------------------------------------------- -- CREATE display objects and add them to 'group' here. -- Example use-case: Restore 'group' from previously saved state. ----------------------------------------------------------------------------- -- load first scene local option1 = widget.newButton { top = 280, width = display.contentWidth, height = 59, label = "Start Game", onRelease = goBack, onPress = function() storyboard.gotoScene( "scene1","fade",400 ); end, } group:insert(option1) -- other options local option2 = widget.newButton { top = 340, width = display.contentWidth, height = 59, label = "Help", onRelease = goBack, } group:insert(option2) local option3 = widget.newButton { top = 400, width = display.contentWidth, height = 59, label = "Quit", onRelease = goBack, } group:insert(option3) 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.) ----------------------------------------------------------------------------- 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.) ----------------------------------------------------------------------------- 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

Also, I would really suggest you read up on some storyboard tutorials so you can understand more about how it works.  Notice that I am adding all of the display objects (anything that gets displayed on the screen) to ‘group’.  Anything that you add to ‘group’ will automatically be handled by storyboard.

I’ve been reading them and I am starting to understand - Thank you. 

One thing im having trouble with is keeping static variables across all scenes.(health mana etc)

Here’s what I have right now in main.lua - Should I be using a storyboard on this page as well if my goal is to display variables across all of the scenes?

I tried what you posted last time and it gave me an error when I included the variables at the bottom


– main.lua


– require controller module

local storyboard = require “storyboard”

local widget = require “widget”

– load first scene

local option1 = widget.newButton

    {

    top = 280,

        width = display.contentWidth,

        height = 59,

        label = “Start Game”,

    onRelease = goBack,

        onPress = function() storyboard.gotoScene( “scene1”,“fade”,400 ); end,

    }

  

  – other options

  

  local option2 = widget.newButton

    {

    top = 340,

        width = display.contentWidth,

        height = 59,

        label = “Help”,

    onRelease = goBack,

  }

  

  local option3 = widget.newButton

    {

    top = 400,

        width = display.contentWidth,

        height = 59,

        label = “Quit”,

    onRelease = goBack,

    }

  

– Display objects added below will not respond to storyboard transitions

health = 100

mana = 10

morale = 10

gold = 0

titleBar = display.newRect( 0, -100, display.contentWidth, 120 )

titleBar:setFillColor( titleGradient )

healthObject = display.newText ("Health: " … health ,20, 0, “Times New Roman”, 10)

healthObject:setTextColor(255,0,0)

manaObject = display.newText ("Mana: " … mana ,95, 0, “Times New Roman”, 10)

manaObject:setTextColor(0,0,255)

moraleObject = display.newText ("Morale: " … morale ,170, 0, “Times New Roman”, 10)

moraleObject:setTextColor(0,255,0)

goldObject = display.newText ("Gold: " … gold ,245, 0, “Times New Roman”, 10)

goldObject:setTextColor(215,200,0)

Personally, I like to keep main.lua to a bare minimum.  This is an example of what pretty much all of my project’s main.lua looks like:

display.setStatusBar(display.HiddenStatusBar) local storyboard = require( "storyboard" ) storyboard.gotoScene("menu")

This isn’t a requirement, it’s just my personal preference.  Then in “menu.lua” is where I would have my main menu buttons, etc.  

Can you post the code you used that gave you an error?  Note you really shouldn’t be adding anything below the “return scene” line in the storyboard scenes.  

Also, generally you want to avoid using globals.  All of your variables at the bottom are global.  Sure, this makes it easy to access, but by the time you finish your project there might be a performance impact.  When you say you need variables to access throughout each scene, you must consider a couple things first.  Will you need these “variables” to persist once the user leaves the app and opens it again at a later time?  If so, that changes things.  

It may have been because I had variables below return scene. I would prefer to do something like you said having the menu in a separate .lua file - but I can’t find a better way to keep health mana gold and morale displaying constantly at the top (except in the menu)

Trying to recreate that error but I can’t seem to. I pasted exactly what you had and all of the buttons disappeared.

I also tried this

display.setStatusBar(display.HiddenStatusBar)
local storyboard = require( “storyboard” )

storyboard.gotoScene(“menu”)

and I got this error:

attempt to concatenate sceneName a nil value 

That is your main.lua?  Do you also have a menu.lua in the project folder?

Yes I do also have a menu.lua 

Can you post menu.lua as well

Yes, this is what I have in menu.lua currently

– require controller module

local storyboard = require “storyboard”

local widget = require “widget”

– load first scene

local option1 = widget.newButton

    {

    top = 280,

        width = display.contentWidth,

        height = 59,

        label = “Start Game”,

    onRelease = goBack,

        onPress = function() storyboard.gotoScene( “scene1”,“fade”,400 ); end,

      

    }

  

  – other options

  

  local option2 = widget.newButton

    {

    top = 340,

        width = display.contentWidth,

        height = 59,

        label = “Help”,

    onRelease = goBack,

  }

  

  local option3 = widget.newButton

    {

    top = 400,

        width = display.contentWidth,

        height = 59,

        label = “Quit”,

    onRelease = goBack,

    }

  

The code I posted before (button code) is what you should be using

Okay i changed the menu.lua and also changed main to include 

display.setStatusBar(display.HiddenStatusBar)
local storyboard = require( “storyboard” )

storyboard.gotoScene(“menu”)

and the buttons disappear now as they should. Is there an easy way to explain why what I had before did not work?

Basically it is because in main.lua you called storyboard.gotoScene(“menu”), which makes it expect a storyboard scene.  But with your original menu.lua code it actually wasn’t a storyboard scene because of the missing code (primarily the local scene = storyboard.newScene() and return scene).  You can’t use storyboard.gotoScene if you are not going to an actual storyboard scene.  

That makes perfect sense. Thanks so much for all of your help :slight_smile: You don’t have to keep answering my questions at all, but I do have one more…

Everything is working how I want it to now with the exception of the fact that my variables are also showing on the top of the menu screen. I want them to show up on the top of every screen EXCEPT the menu screen.


– main.lua


– require controller module

local storyboard = require “storyboard”

local widget = require “widget”

local variables = require “variables”

– load first scene

display.setStatusBar(display.HiddenStatusBar)

storyboard.gotoScene(“menu”)

– Display objects added below will not respond to storyboard transitions

titleBar = display.newRect( 0, -100, display.contentWidth, 120 )

titleBar:setFillColor( titleGradient )

healthObject = display.newText ("Health: " … health ,20, 0, “Times New Roman”, 10)

healthObject:setTextColor(255,0,0)

manaObject = display.newText ("Mana: " … mana ,95, 0, “Times New Roman”, 10)

manaObject:setTextColor(0,0,255)

moraleObject = display.newText ("Morale: " … morale ,170, 0, “Times New Roman”, 10)

moraleObject:setTextColor(0,255,0)

goldObject = display.newText ("Gold: " … gold ,245, 0, “Times New Roman”, 10)

goldObject:setTextColor(215,200,0)

So again, when you create display objects and you don’t insert them into ‘group’, then storyboard does not manage these display objects, you must manually manage them yourself.  

If I were you I would create these display objects in every scene you want them in and let storyboard handle them, instead of only creating them once and leaving them there.  

Side note, save the code below to a file and use it every time you create a new scene (aka page) in your app.  This is basically the main things you need to create a storyboard scene.

-- blankscene.lua local storyboard = require( "storyboard" ) local scene = storyboard.newScene() ---------------------------------------------------------------------------------- -- -- NOTE: -- -- Code outside of listener functions (below) will only be executed once, -- unless storyboard.removeScene() is called. -- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -- BEGINNING OF YOUR IMPLEMENTATION --------------------------------------------------------------------------------- -- Called when the scene's view does not exist: function scene:createScene( event ) local group = self.view ----------------------------------------------------------------------------- -- CREATE display objects and add them to 'group' here. -- Example use-case: Restore 'group' from previously saved state. ----------------------------------------------------------------------------- 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.) ----------------------------------------------------------------------------- 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.) ----------------------------------------------------------------------------- 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