This is what I hope will be a fairly easy to follow tutorial for those of you who need some help learning how to use “scenes” or “screens” in your apps.
*Full credit for the director file goes to Ricardo Rauber – I could never have come up with this, I only want to help others learn how to use it.
Download the project file here.
(Keep in mind that if you are planning on compiling this for your device you’ll need to add an Icon.png and Default.png image to the folder.)
Alright, let’s get started!
Step One: In your project file (this is a NEW project, not the one you downloaded above) you will want to copy across four files, these are build.settings, config.lua, director.lua and main.lua.
Step Two: Create the first scene/screen that people will see when they open up your app, in my case I always call this “menu.lua”. Don’t worry about adding anything to it yet, just make the file.
Step Three: Open the main.lua file that you copied into your project in step one and look for this line;
1 2 3 4 5 6 7 8 9 10 11 | local function main() -- Adds main function mainGroup:insert(director.directorView) -- Adds the group from director director:changeScene("menu") -- Change the scene, no effects return true end |
Here you are going to replace “menu” with the name of your initial screen, for example if you have called your file home.lua you will change “menu” to “home” – note, we do not include “.lua” here.
Step Four: Open the file you created before, menu or home or what have you, and insert the following code (this should be the only text in the file at this stage):
1 2 3 4 5 6 7 8 9 | module(..., package.seeall) function new() local localGroup = display.newGroup() ------------------------------------------------------------------------------ -- YOUR CODE WILL GO HERE ------------------------------------------------------------------------------ return localGroup end |
Step Five: Write your code here as you normally would, inserting images and arranging them, with one additional step now present; for every image, you must add this line;
1 2 3 4 | local redbutton = display.newImage ("redbutton.png") redbutton.x = 160 redbutton.y = 100 localGroup:insert(redbutton) |
This is very important, if you forget to add this line to any image, including your background, the project will not function as intended. If you can see it, you add the line. Every time.
Step Six: Now you’ve got your initial screen/scene setup, you will want to add a button which will go to a new one; that’s the point of using director, right? Right.
First, we need a file to change to – for me, I created red.lua.
In every file you create you will use the code above that you pasted into your menu.lua or home.lua file, placing your code in between the red lines and using the line of code discussed for every single image.
Step Seven: To demonstrate how to change from your menu.lua or home.lua to red.lua I will create a function for one of my buttons, as used in the example. In this case my button is redbutton and when it is touched I want to change to the scene I’ve created called red.lua
1 2 3 4 5 | local function pressRed (event) if event.phase == "ended" then director:changeScene ("red") end end |
Now, when you press your button it will change from your initial screen/scene to red.lua
And that’s it!
By looking at the example you will see it in action if you don’t want to create a simple project yourself to test with; provided you always put each files code in between the red lines and remember to add every image to your localGroup then it will function beautifully and be one of the most useful things you ever learn.
From time to time when your code has errors, terminal may indicate that some of these are in director.lua – this is not the case. If you read through the errors you will note at least one is in your own file; once this is remedied the errors supposedly relating to director.lua will disappear; so do not be alarmed.
If you have questions, ask me. I’m committed to helping others learn Corona as I learn myself
Be sure to add me on Facebook and follow me on Twitter if you have it; although I’m currently posting in the Corona forums when I update the site I don’t intend to do so forever. Plus, Facebook is an easy way to quickly reach me if you need a hand!
Stay tuned, I hope to post an OpenFeint example soon as requested by a couple of you.
Peach Pellen ![]()


_G.score2 still prints 10 in level2 in the debugger. there were some initial issues copying and pasting your quotation marks, but I fixed themt. I’m at a loss, but thanks so much for your valiant efforts.
p.s., what time is it there? it’s 5:28 am in Chicago. I can’t sleep until I get this scoring to carry.
Give me 5 minutes and I’ll post something for you to try.
PS – 10:45pm but I work all night
no worries… fellow vampire ;-[
Obviously folder must have director in it and main.lua file set up for director, which should go to menu.lua.
Use this code in menu.lua
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
-- Main function - MUST return a display.newGroup()
function new()
local localGroup = display.newGroup()
--------------------------------------------------------------------
--------------------------------------------------------------------
--Background
local bg = display.newRect( 0, 0, 320, 480 )
bg:setFillColor(20, 200, 255)
localGroup:insert( bg )
--Score
_G.score = 0
--Score Text
local scoreText = display.newText("score: ".._G.score, 200, 5, native.systemFont, 16)
scoreText:setTextColor(0, 0, 0)
localGroup:insert( scoreText )
--Add to score, update text when background is tapped
local function upScore ()
_G.score = _G.score + 1
scoreText.text = "score: ".._G.score
end
bg:addEventListener("tap", upScore)
--Button to change scene
local nextBtn = display.newRect( 200, 400, 60, 20 )
localGroup:insert( nextBtn )
--Scene change function
local function changeScene()
director:changeScene("level1")
end
nextBtn:addEventListener("tap", changeScene)
--------------------------------------------------------------------
-- MUST return a display.newGroup()
return localGroup
end
And this exact code in level1.lua;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-- Main function - MUST return a display.newGroup()
function new()
local localGroup = display.newGroup()
--------------------------------------------------------------------
--------------------------------------------------------------------
--Background
local bg = display.newRect( 0, 0, 320, 480 )
bg:setFillColor(255, 200, 25)
localGroup:insert( bg )
--Score Text
local scoreText = display.newText("score: ".._G.score, 200, 5, native.systemFont, 16)
scoreText:setTextColor(0, 0, 0)
localGroup:insert( scoreText )
--------------------------------------------------------------------
-- MUST return a display.newGroup()
return localGroup
end
Run that. Should persist through scenes and give you a good idea of how it should be done ;-[
got this error:
Runtime error
/Volumes/TBO/Space Nuts/director.lua:440: ERROR: table expected. If this is a function call, you might have used ‘.’ instead of ‘:’
stack traceback:
[C]: ?
[C]: in function ‘insert’
/Volumes/TBO/Space Nuts/director.lua:440: in function ‘_listener’
?: in function
?: in function
———————–
Director ERROR: Failed to load module ‘menu’ – Please check if the file exists and it is correct.
———————–
I’m going to be banging my face itno the keyboard in a minute–more out of sleepiness than frustration. got to climb back into the coffin for now. :-] thanks. you’re absolutely mah’velous!
I’m not sure why you’re getting that error – I’m going to email you this thing as a zip for when you wake up
what a beautiful way to start the day!!!!
I will apply this to my game immediately, if not sooner…
thanks, Peach! you’re a gem…
Not a problem Mike – glad I could help improve your morning
Hi
I followed this tutorial and it worked great. I created a basic ball bouncing within the ‘red.lua’ file so when I push the button it loads that, it works fine, however when I hit the ‘back’ button it does what it should and takes me back to the main menu but it keeps the ball bouncing and showing too lol. I’ve not changed any of the code for the buttons or the director file so not really sure whats happening?
Thanks for any help
worked like a charm. brilliant! you should share this in a tutorial perhaps so others could be as happy as I am right now. it would make a wonderful companion piece to this one.
I believe you are not adding your ball to the local group – check to see you have;
Thanks Mike
hi peach, glad I have your approval on the name
. I have new ideas of things that could solve the proplem i’m having with director. *insert that “ohhhhh” moment here* haha. however, i’ve been away from my pc for a few days.. more on a personal note, I have a 17 month old little that’s in the hospital for her second time in two weeks. she is improving though and if all goes well we should be heading home tomorrow. I hope this isnt too forward, but I do enjoy the chats and am very thankful for all the help that yourself and the community has offered. do you have an easier way of maintaing contact? I feel kinda bad for weighing your site down with so many comments.
I did follow you on twitter, so I suppose that would be a bit easier to maintain contact, unless of course you had yahoo messeger or something of the sort. anyhow, I’ll keep you updated on the progress of my director issues and other app news. here’s my yahoo im address. rave_master_apollo@yahoo.com do stay in touch and keep me posted on how your apps are going. oh, and last thing.. I was quite pleased to see that there was a meetup pretty close to home. I was in the hospital at the time, and did not get to make it. hopefully i’ll get to check some of them one day. okay, enough from me. i’ll update you when I get to try this new idea.
Hey Joey,
I am very sorry to hear about your kid; I hope she is OK and home by now.
I am certainly happy to maintain contact via email or an instant messenger, although I haven’t used YM in about 7 years
Will shoot you an email now so you have my address and we’ll touch base again soon.
hi peach, I got your email and replied. thank you for your concern.
Hi Peach,
Thanks for the great walkthroughs. One quick question though I can’t figure out how to add an Icon.png and Default.png image to my projects folder. Any help will be greatly appreciated. Thanks.
Hey Sammy, you just drop the Default.png image and Icon.png image into your project folder; is that what you’re asking?
Exactly, but where can I find the two .pngs to drop them into my folder. I can’t find them in the project that you provided to download at the top of the page. Do you know where I can find the files to drag them into my project?
At the top of the page? Where are you looking for them? You just drop them into a folder like you do when moving anything else on your computer.
Are you using any third party software?
All i am doing is using the Corona software to view my work and I am going around to websites self teaching myself to code. I use TextWrangler to code.
And I don’t know where to find the Default.png image and Icon.png to drop them into my folder. Because in your Project File Example its not in the folder to drop over into my project. Do I need to make them? If so how?
OH I understand, haha, sorry!
You make Default.png and Icon.png. They’re YOUR Icon and YOUR Splash screen
Then just drop them in the folder and they will work.
What program do you normally use to make images in? You would use that. Default.png should be the size of your screen (iPhone is 320 wide x 480 high) and the icon should be 57×57, assuming it is an iPhone app.
Make sense?
Thanks for your help. I use photoshop elements to create my own backgrounds and icon. So would I just make a background in the dimensions of the ipod and name it Default.png and the same for the icon. If so what would I make the icon button look like? Also what is a Splash Screen? Thanks for your help again.
Hi Peach,
I’m a fan of you & your tutorials
I’ve tried to use these codes in my game but there’s a problem. Let me explain:
I have a game with a character on stage, setflag of its existence.
IE:
local Player1Exist = false
Inside the game I will spawn it for the first time, and setting the Player1Exist = true.
If the player1 fall off the into the water in the game, I will use player1.removeSelf() to remove it, set Player1Exist = false again. And after 10seconds, player1 will re-spawn.
I have a joystick controlling the player movement. It’s a simple joystick which I found from Ansca Mobile forum. During runtime, if Player1Exist = true, then I will set the joystick to be able to control player1 movement (I applied Player1:applyForce method for motion control). During Player1Exist = false, I will have to remove the functions of the joystick. (If not, error will comes out if I touch the joystick when the player1 is not on the stage).
After playing for 30seconds, the game will calculate the player’s point. If point < 100, then it will jump to youLose.lua, else, it will jump to youWin.lua.
I used your tutorial here and set all these codes into singlePlayer.lua and simulated it.
Everything goes fine until 30seconds reached, it jumped to the correct scene. But there's error popping out indicating that the player1:applyForce is a nil value.
I used Runtime onEnterFrame in the singlePLayer.lua to keep detecting the player1's existence, continuously removing and adding the joystick function to the player1.
I notice that when the scene jumped to youLose.lua or youWin.lua, the singlePlayer.lua's onEnterFrame function is still running.
Pls help to make it stop running when the scene has already changed.
No worries.
Splash screen is what Default.png is – it shows when your app is loading at the start
You would indeed do that – make the Default.png the screen size and name it Default.png.
Make the icon 57×57 and name it Icon.png and then put both into the project folder.
What you make the icon look like is up to you, it’s your icon
Hey Shao, thank you for the kind words.
For your problem you need to remove the Runtime listener, like so;
That assumes it is on enterFrame – but just the same way you added it, your remove it in the line above director:changeScene()
Does this make sense?
That makes perfect sense! Thanks PP!
Not only must remove listener, but all the timers which have looping-called-functions which spans more than 30seconds must be removed too. My codes work perfectly.
Thanks again.
Exactly – I’m very pleased to hear you have this working. Good job!
Hi Peach, Just a rather basic question here about using Director.
You state that every image has to be added to localGroup. Can I assume that you can have sub-groups that are added to localGroup, and the the images only have to be added to the relevant sub-group?
(I think that makes sense).
Cheers
Hey Chris, yes, that works fine – I actually do it in my Boggle video
Hi Peach,
Do you prefer director to storyboard? I switched not long ago.
Best,
Mike Kelly
That’s a tough question but I suppose right now the answer is yes, I do prefer Director. That is namely because I’m set in my ways and have been using Director for over a year and also in part because I haven’t had any spare time to really get familiar with Storyboard. (The last two months for some reason have just been so busy; I keep meaning to email you to ask how your class is going but every time I start to write I get a phone call or someone grabs me on Skype >.< ‘)
You get a chance please do write me and let me know
The class will be going a lot better once the Corona Level Editor breaks out of Alpha testing and gets to us. Any insider info on when that might be? ;-p
If you really want insider info get Carlos all hopped up on coffee – it’s the only way
Hi!…I can get a scene transition like going from page in a book?
Hey Daniel,
At present no I don’t believe so but it’s something we’re hoping will be available very soon.
Hi Peach,
Do you have an email address I would be able to contact you on at all? I’m having some issues with images clearing when switching scenes and I’ve tried many different ways of grouping them but I seem to be getting some strange results and was wondering if you would be able to lend some advise?
Thanks a lot
Alex
Hey Alex,
I do – it’s on my contact/hire page: http://techority.com/hire-me/ (as you can see it’s an image not a link as I want to stay off spam lists
)
That said I’m generally very busy so while I do my best you may actually get a faster reply posting in the Ansca/Corona forum. (Which I also answer several times a day.)
Hi there again
I’ve been working on this menu for switching between scenes using the director class and I’m having a problem with the switching. I’m also using some of the sample code to create my moving background.
When I run my program the menu animates and works ok but when I click game I get the error “lua:183: attempt to perform arithmetic on field ‘x’
This is the code I’m using:
module(…, package.seeall)
function new()
local localGroup = display.newGroup()
_W = display.contentWidth
_H = display.contentHeight
– The sky image as background
local sky = display.newImage( “Images/skyBG.png” )
localGroup:insert (sky)
local logo = display.newImage (“Images/logoImage.png”)
localGroup:insert(logo)
logo.x = _W/2
logo.y = 50
logo.xScale = 0.6
logo.yScale = 0.7
local playButton = display.newImage (“Images/playButton.png”)
localGroup:insert(playButton)
playButton.x = _W/2
playButton.y = 130
playButton.xScale = 0.6
playButton.yScale = 0.6
local instButton = display.newImage (“Images/instructionsButton.png”)
localGroup:insert(instButton)
instButton.x = _W/2
instButton.y = 180
instButton.xScale = 0.6
instButton.yScale = 0.6
local quitButton = display.newImage (“Images/exitButton.png”)
localGroup:insert(quitButton)
quitButton.x = _W/2
quitButton.y = 230
quitButton.xScale = 0.6
quitButton.yScale = 0.6
– Code required for a moving background
require “sprite”
display.setStatusBar( display.HiddenStatusBar )
local baseline = 280
– Series of cloud images
local tree = {}
tree[1] = display.newImage( “Images/cloud1.png” )
tree[1].xScale = 1; tree[1].yScale = 1
tree[1]:setReferencePoint( display.BottomCenterReferencePoint )
tree[1].x = 20; tree[1].y = 180
tree[1].dx = 0.2
tree[2] = display.newImage( “Images/cloud2.png” )
tree[2].xScale = 0.6; tree[2].yScale = 0.6
tree[2]:setReferencePoint( display.BottomCenterReferencePoint )
tree[2].x = 450; tree[2].y = 125
tree[2].dx = 0.2
tree[3] = display.newImage( “Images/cloud3.png” )
tree[3].xScale = 0.6; tree[3].yScale = 0.8
tree[3]:setReferencePoint( display.BottomCenterReferencePoint )
tree[3].x = 600; tree[3].y = baseline
tree[3].dx = 0.3
tree[4] = display.newImage( “Images/cloud4.png” )
tree[4].xScale = 0.7; tree[4].yScale = 0.7
tree[4]:setReferencePoint( display.BottomCenterReferencePoint )
tree[4].x = 230; tree[4].y = 220
tree[4].dx = 0.4
tree[5] = display.newImage( “Images/cloud5.png” )
tree[5].xScale = 0.8; tree[5].yScale = 0.8
tree[5]:setReferencePoint( display.BottomCenterReferencePoint )
tree[5].x = 300; tree[5].y = 120
tree[5].dx = 0.3
tree[6] = display.newImage( “Images/cloud6.png” )
tree[6].xScale = 0.8; tree[5].yScale = 0.8
tree[6]:setReferencePoint( display.BottomCenterReferencePoint )
tree[6].x = 320; tree[6].y = 300
tree[6].dx = 0.3
tree[7] = display.newImage( “Images/cloud7.png” )
tree[7].xScale = 0.8; tree[7].yScale = 0.8
tree[7]:setReferencePoint( display.BottomCenterReferencePoint )
tree[7].x = 580; tree[7].y = baseline
tree[7].dx = 0.5
for i=1,#tree do
localGroup:insert(tree[i])
end
local bar1 = display.newImage( “Images/baseLine.png” )
–localGroup:insert(bar1)
bar1:setReferencePoint( display.CenterLeftReferencePoint )
bar1.x = 0
bar1.alpha = 0
bar1.y = baseline – 0.1
local bar2 = display.newImage( “Images/baseLine.png” )
–localGroup:insert(bar2)
bar2:setReferencePoint( display.CenterLeftReferencePoint )
bar2.x = 480
bar2.alpha = 0
bar2.y = baseline – 0.1
local function playButtonEvent (event)
if event.phase == “ended” then
director:changeScene (“game”)
end
end
playButton:addEventListener (“touch”, playButtonEvent)
local function instButtonEvent (event)
if event.phase == “ended” then
director:changeScene (“instructions”)
end
end
instButton:addEventListener (“touch”, instButtonEvent)
local function quitButtonEvent (event)
if event.phase == “ended” then
director:changeScene (“exit”)
end
end
quitButton:addEventListener (“touch”, quitButtonEvent)
local tPrevious = system.getTimer()
local function move(event)
local tDelta = event.time – tPrevious
tPrevious = event.time
local xOffset = ( 0.1 * tDelta )
bar1.x = bar1.x – xOffset
bar2.x = bar2.x – xOffset
if (bar1.x + bar1.contentWidth) < 0 then
bar1:translate( 480 * 2, 0)
end
if (bar2.x + bar2.contentWidth) < 0 then
bar2:translate( 480 * 2, 0)
end
local i
for i = 1, #tree, 1 do
tree[i].x = tree[i].x – tree[i].dx * tDelta * 0.05
if (tree[i].x + tree[i].contentWidth) < 0 then
tree[i]:translate( 480 + tree[i].contentWidth * 2, 0 )
end
end
end
Runtime:addEventListener( "enterFrame", move )
——————————————————————————
——————————————————————————
return localGroup
end
I think this is something to do with the timer to move everything and it not ending when the scene is switched however I'm a but puzzled on where to end it and what code I use?
Sorry for the long post and thanks for any help!
Hey Alex,
I actually replied to your forum thread on this; it’s because you have not removed the Runtime listener. I gave you the code to remove it specifically in the forum