Mekersa - Create 2D Mobile Games With Corona SDK - 2015
Mekersa - Create 2D Mobile Games With Corona SDK - 2015
GAMES WITH
CORONA SDK
CREATE 2D MOBILE
GAMES WITH
CORONA SDK
DAVID MEKERSA
First published 2015
by Focal Press
70 Blanchard Road, Suite 402, Burlington, MA 01803
Focal Press is an imprint of the Taylor & Francis Group, an informa business
The right of David Mekersa to be identified as the author of this work has been
asserted by him in accordance with sections 77 and 78 of the Copyright, Designs
and Patents Act 1988.
All rights reserved. No part of this book may be reprinted or reproduced or uti-
lised in any form or by any electronic, mechanical, or other means, now known or
hereafter invented, including photocopying and recording, or in any information
storage or retrieval system, without permission in writing from the publishers.
Notices
Knowledge and best practice in this field are constantly changing. As new
research and experience broaden our understanding, changes in research
methods, professional practices, or medical treatment may become necessary.
Practitioners and researchers must always rely on their own experience and
knowledge in evaluating and using any information, methods, compounds,
or experiments described herein. In using such information or methods they
should be mindful of their own safety and the safety of others, including parties
for whom they have a professional responsibility.
Acknowledgments ix
Part 1: Lua 3
Get Prepared 7
Functions 17
Part 2: Display 43
Texts 47
Images 53
Shapes 57
Part 3: Move 67
Debug 163
Deploy 169
Index 187
This page intentionally left blank
Acknowledgments
x Acknowledgments
• JavaScript
• BlitzBasic
• Monkey X Basic
• Lua (for Löve 2D and Corona SDK)
• C Sharp
More than 10 different languages and almost 20 if we include the
different implementations (Borland Pascal and Delphi, for example, use
the same language but must be learned individually).
After so much practice, I had built my own personal way to learn, which
I’m going to share with you.
For this particular Game Jam, I decided to learn Löve (a 2D frame-
work based on Lua). I knew the Lua language already, so it only took
me few hours to be able to understand the framework and create a game
prototype.
I had learned Lua using Corona SDK a few months before, and I just
needed one day to learn the language plus the basics of the Framework
and some advanced features!
Think it’s impressive? You can do the same.
You just have to learn less and build a minimal toolkit. Let me explain!
Learn Less
This is a simple method based on common sense.
Learn only the basics, then start a real project.
The basics are:
• Minimum skeleton / minimal game engine
• How to run / test the code
• Variables, functions, classes and other language fundamentals
• Lists and/or arrays
• Display an image and make it move
• . . . That’s all!
Depending on your skill level, mastering the basics of a programming
language associated with its framework will take you between two hours
and one day.
At this stage, you’re not an expert, and it’s not enough for the entire
project you’re going to work on . . . No problem! Start the project now!
You’ll learn any additional concepts only when you’ll need to use them.
Why is this method good for you?
xii Acknowledgments
1) It avoids learning useless stuff. Why learn this advanced API if you
won’t need it for your first project? You don’t have to be an expert;
you just need to know enough to produce something right now!
2) It keeps your motivation high with fast results and many small,
early successes.
It might not sound like much, yet with this minimal toolkit you can
create some great classics: Pac-Man, Space Invaders, Tetris, Mario Bros.,
Street Fighter, Puzzle Bobble, Zelda, and many more!
In this book, I will teach you to create any kind of game with Corona
SDK by following this method.
In addition to the lesson, each chapter will provide tips and links that
take the concept even further.
It’s time to make stuff !
This page intentionally left blank
Part 1
Lua
Moon
Lua means “moon” in Portuguese. It’s pronounced “loo-ah” and not
“L.U.A.” It was created in Brazil in 1993 and is now available for a wide
variety of systems.
Corona SDK uses Lua as its programming language. Because
Lua is very easy to learn, it has allowed Corona SDK to become
one of the most accessible tools to create mobile games and
applications.
result = LookFor("butter")
If result == false then
MoveToStore()
Buy("margarine")
GotoHome()
End
UseButter()
It’s not terribly realistic, but it’ll help you to understand what a script-
ing language is.
Comments
Sometimes you’ll need to explain something in your code that isn’t
part of the code itself. For example, leaving a note to yourself about
Lua 5
-- Here is a comment
--[[
Here is a long comment.
It’s amazing how this comment is long!
--]]
Traces
On many occasions, you’ll need to display something that’s not for your
users, but only for you. A kind of “I was here!” to check if your code is
doing what you expect. (Yes, the code isn’t always obedient!)
Here is how to display a trace:
This instruction will display “David was here!” in the console when
this instruction is executed.
The console is a kind of ticker that’s essential to your survival.
TOP TIP: Traces are the best and simplest way to discover bugs
and fix them. It’s like having a spy in your code! You’ll learn more
about traces in the chapter addressing debugging.
That’s All
That’s enough to start. Let’s now look at Lua in detail!
Get Prepared
8 Lua
We all love action. So, before we learn anything, let’s install Corona
SDK! You’ll then be ready to enter the code from the examples and test
them.
You’re done!
Experiment
In the next chapter, I’ll teach you Lua.
Lua is the scripting language, not the SDK. It’s quite independent
from Corona SDK, but a good way to learn is to experiment with the
examples and lessons through Corona SDK. This way, you’ll become
familiar with the Corona SDK tools.
How do you begin experimenting with Lua code?
Sublime Text will open a new file, main.lua, with just few comments
in it:
Keep this open and jump to the next chapter. You’re ready to learn
Lua!
Variables, Tables, and
Expressions
12 Lua
title = "Rocky"
This gives a string the name “title” and assigns it “Rocky” as a value.
Please note that strings are between quotation marks.
Numbers are expressed in the same way, except that the value does
not use quotation marks:
lives = 3
started = true
IMPORTANT: The variable name has to start with a letter, and can
contain letters and numbers, with no spaces.
Lives = 3
lives = 3
Variables, Tables, and Expressions 13
Got it?
Please note that there is a special type to define the lack of value: nil.
myVariable = nil
Tables
To store more complex data, like a player, you’ll use tables. Think of a
table as a magic box. You give it a name, and then you put stuff inside.
Here is an example of a table:
MyPlayer = {}
MyPlayer.Energy = 100
MyPlayer.x = 50
MyPlayer.y = 20
Expressions
Expressions will be absolutely everywhere in your code. However, I
won’t dig too deeply into expressions because I prefer practice rather
than theory. Here are some basics to understand what they are.
According to Wikipedia:
+ (addition)
– (subtraction)
* (multiplication)
/ (division)
myResult = 1 + 12
Expressions are nothing without statements, but we’ll save these for later.
Practice!
In your main.lua file (refer to “Get Prepared” in the previous chapter),
enter some expressions to experiment with variables in Lua. Just type in
this code:
-- Complex values
MyPlayer = {}
MyPlayer.Energy = 100
MyPlayer.x = 50
MyPlayer.y = 20
Syntax error
.../main.lua:23: unexpected symbol near ')'
This means that the error is somewhere in line 23, and that something
is wrong near the last parenthesis. Most of the time, the error is quite
obvious.
Did you find the error? There is an unexpected comma before the sec-
ond parenthesis. You’ll learn some great tips and strategies for debug-
ging your code in Part 5, but at this stage, being able to understand how
to find and fix an error is enough.
Experiment by trying out your own variables and tracing their values,
then head to the next chapter!
TO GO FURTHER . . .
You can read everything about variables, tables, and expressions in the
official Lua documentation. Follow the link:
Tables:
www.lua.org/pil/2.5.html
Expressions:
www.lua.org/pil/3.html
Functions
18 Lua
Shot = function ()
Energy = Energy - 10
End
Function Shot()
Energy = Energy - 10
End
The above two examples are of the same code, with two different
syntaxes. The first version is the legacy way, and demonstrates that a
function is like any other value. The second is a syntax shortcut.
I prefer the second example. Why? Because most programming
languages use this kind of syntax, and it’s easier to remember. I use this
syntax in this book, but you can use either one.
A Function as a Task
This kind of function is autonomous. Let’s say it’s just performing a task,
and that’s it. For example, imagine that we need to reset several variables
when a game session starts:
Function ResetGame()
Score = 0
Level = 1
Energy = 100
End
The variables Score, Level, and Energy exist outside of the function and
are modified by the function. The function will then be “called” like this:
Functions 19
NOTE: In Lua, you can cut a line of code into chunks if needed, like I
did in this example. Just insert a few blank lines.
20 Lua
Look at the function call and how it receives the parameters. Now,
here’s how to call the function in your games:
foeDistance = getDistance(hero,foe)
print(foeDistance)
That’s it. It’s clean and readable, and you can call getDistance any time
you need.
Functions in a Table
You can store a function in a variable. Let’s enhance our Energy variable
with a function to decrease it:
Energy = {}
Energy.level = 100
function Energy.Decrease(p)
Energy.level = Energy.level - p
end
Energy.Decrease(10)
print(Energy.level)
Experiment
Create a new project with Corona Simulator called “TestFunctions” and
type this code:
object1 = {}
object1.x = 50
object1.y = 50
object2 = {}
object2.x = 100
object2.y = 100
TO GO FURTHER . . .
You can read everything about Lua functions in the official Lua docu-
mentation here:
www.lua.org/pil/5.html
This page intentionally left blank
Control Structure
Statements
24 Lua
Conditional Statements
This is the basic control statement, and the most used: If . . . Then . . .
Else.
With this amazing “if ” statement, you’re able to execute some code
only if a certain condition is verified. I always use this example:
If it rains, take an umbrella.
In Lua and in a “game coding” situation, it looks like this:
This means that if the distance between the hero and the foe is less
than 100, the trace “Alert” is displayed.
Here is the same example with an “else” statement added, and more
than one line of code:
Loop Statements
For
Let’s start with my favorite: For.
The “for” loop is used to repeat a group of statements (lines of code) a
specified number of times.
The “for” loop increases (or decreases) a variable at each step.
Here is an example:
for count=1,10 do
print(count)
end
for count=10,0,-1 do
print(count)
end
While
The second loop statement you’ll have to use is “while.” It will repeat a
group of statements (lines of code) until a condition becomes true. It’s
quite simple to use. Here is an example:
Global Scope
A global variable exists in your code and can be used right after being
declared. For example, the variable global_variable declared in main.lua:
global_variable = "hello"
You can then use and modify global_variable anywhere in your code,
including other Lua files.
It’s great to use global variables, but it’s dirty too . . . The main reason
is the readability and reliability of your code. Using too many global
variables will lead to bugs and hassles like “Where was this initialized?”,
“Where was this variable modified?”, or “I’m bored! I’m going to bed
right now!”
Control Structure Statements 27
Local Scope
A local variable is known only in the block where it is declared. A block
is a statement (most of the time ending with “end”), a function, or a Lua
file. To declare a variable or a function as local, just add local before its
name:
local x = 100
Here is an illustration:
If you type and execute this example, you’ll find message to be nil (or
undeclared) outside of the control statement “if energy . . .”
TIP: Use a local variable anytime you know that the variable won’t
be used later in your code. It will avoid cluttering the memory with
unused values or creating unexpected side effects, such as accidentally
using a global variable initialized somewhere else in your code!
TOP TIP: If you declare a global variable, it’s great to use uppercase
names. This makes your code highly readable, and enables you to
guess which variable is global. Example: DEFAULT_ENERGY = 1000.
It’s great, as well, to declare global variables at the top of your Lua files,
so you can easily find where they are initialized.
28 Lua
Experiment
Write a simple “for” loop, increasing a counter from 1 to 100. Then, in
this loop, use an “if ” statement to display (then “print” the result):
• “I’m a kid” if the counter is less than 15
• “I’m young” if the counter is between 30 and 59
• “I’m wise” if the counter is between 60 and 79
• “I ask for respect” for values between 80 and 100
TO GO FURTHER . . .
There is another loop statement called “repeat . . . until,” but you won’t
have any difficulty understanding how it works. The “while” statement is
more readable from my point of view.
You can read everything about Lua control structures in the official
Lua documentation. Follow the link:
www.lua.org/pil/4.3.html
Arrays and Lists
30 Lua
In your games, you’ll have to deal with a bunch of items, bullets, ene-
mies, obstacles, and so forth. To store this kind of data in memory, you
will use arrays or lists. You’ll use an array when the number of items
is known. Some examples are months, fixed gameplay elements, and
inventory items. You’ll use a list when the number of items is unknown
and fluctuating (e.g., bullets, flying saucers, and other funny things a
video game contains).
Arrays
Create an Array
In Lua, an array is nothing more than a table (see the chapter “Variables,
Tables, and Expressions”).
myShips = {}
Then, in the table, we insert data indexed with an integer like this:
myShips[1] = "Alpha"
myShips[2] = "Omega"
myShips[3] = "Delta"
myShips[1] = {}
myShips[1].name = "Alpha"
myShips[1].shield = 400
Browse an Array
Now we need to go through our array. You learned the “for” loop few
pages earlier, so . . . Just iterate with an integer like this:
Arrays and Lists 31
for i=1,3 do
print(myShips[i])
end
size = #myShips
for i=1,#myShips do
print(myShips[i])
end
If you try to access an element outside of the array, you’ll get nil as the
value.
Lists
Create a List
A list is an array, but I prefer to explain the concept separately because
if you have used another programming language, you may be used to
seeing the both concepts as different.
With Lua, just consider a list as an advanced approach to creating
arrays. With a list you can insert and remove items in an arbitrary order.
myList = {}
table.insert(myList, myElement)
table.insert(myList, 1, myElement)
32 Lua
myStarList = {}
for i=1,10 do
local myStar = {}
myStar.index = i
table.insert(myStarList, myStar)
end
Browse a List
It’s not the easy part. There are several ways to browse a list. Let me
show you a generic way (the one I use in my games and apps).
for i in pairs(myStarList) do
print(myStarList[i].index)
end
It is, from my point of view, the most readable way to browse a list.
table.remove(myStarList, 1)
Experiment
Type and execute this code. Observe the behavior of the array and try to
add and remove items of your own.
Arrays and Lists 33
myShips = {}
myShips[1] = "Alpha"
myShips[2] = "Omega"
myShips[3] = "Delta"
-- remove Alpha
table.remove(myShips, 2)
TO GO FURTHER . . .
You can read everything about Lua tables as arrays and lists here:
http://lua-users.org/wiki/TablesTutorial
This page intentionally left blank
Object-Oriented
Programming With Lua
36 Lua
WARNING: The goal here is not to make you a Lua expert, but
rather a game programmer. So I’ll use some special features of Lua here
without explaining them in great detail. The bottom line is that you’ll
still be able to create and use objects in your game.
This can be reused and adapted according to your needs. To use this in
your code, you just have to rename it and add your properties and functions:
OOShip = {}
local mt = {__index = OOShip}
return OOShip
To create a Ship object in your code, you just need few lines of code:
File: main.lua (or any other Lua file from your game)
ship = require("OOShip")
ship1:PrintName()
ship2:PrintName()
Some Explanations
The first line is creating an empty table called OOShip (for Object-Oriented
Ship):
OOShip = {}
The next line is preparing a special table, with an entry called __index,
which is an internal Lua field:
function OOShip.new(pName)
local new_instance = {}
new_instance.name = pName
return setmetatable(new_instance,mt)
end
function OOShip:PrintName()
print(self.name)
end
Please note the use of the colon (:) instead of the period (.)! It’s a
special way to declare a function in Lua. It means that the function will
receive a special and hidden parameter called self. This self parameter
Object-Oriented Programming with Lua 39
will contain the instance of the object (with its attached properties and
functions). Using the colon is a shortcut to avoid passing/receiving the
self parameter.
Here, the function is using the traditional period:
function OOShip.PrintName(self)
print(self.name)
end
It’s the same function, but you can see the hidden parameter.
Experiment
Use the OOShip class sample to create a Hero class. Add 2 properties,
x and y, as its coordinates. Then, add a method “MoveTo” receiving two
parameters, px and py, and replace its coordinates with the received one.
Here’s how your player class Hero.lua should look:
Hero = {}
local mt = {__index = Hero}
function Hero:MoveTo(px,py)
self.x = px
self.y = py
end
return Hero
hero = require("Hero")
myHero:MoveTo(50,50)
TO GO FURTHER . . .
Here are some official links for Object-Oriented Programming with Lua:
http://lua-users.org/wiki/TablesTutorial
http://lua-users.org/wiki/MetamethodsTutorial
However, in this chapter you already have the most you’ll ever need to
create a game using some OOP!
This page intentionally left blank
Part 2
Display
Introduction
How was your journey in the Lua world? I’m sure you did not under-
stand everything, and it’s normal. One of my suggestions is to learn
the basics and then practice, looking back at the previous lesson when
needed.
In this part you’ll start to use your knowledge (Lua programming) to
display text, shapes, and images. In other words, to give life to your code!
44 Display
Display Objects
To display something you will create display objects. Anything that
appears on your screen is a display object: a shape, an image, a button,
and so forth.
Display 45
Hey! You’re going to display your first object on the device screen: a text!
This line of code creates a text object at the position 100 (x) and
200 (y) using the system font, with a height of 20 pixels.
display.setDefault("anchorX", 0)
display.newText("I'm on the left. . .", 0, 50,
native.systemFont, 20)
display.setDefault("anchorX", 0.5)
Note that we need to revert the anchor back to its default behavior
(center) after the text is created. Otherwise, the objects created after-
wards will be left aligned, which is not the default behavior.
Regarding Fonts
There are two variants of the system font:
• native.systemFont
• native.systemFontBold
You can use custom fonts or use the available fonts on the device. It’s
out of our scope, but take a look at “To Go Further . . .” below for some
tips.
Text 49
options =
{
text = "Hello world! This is my first
multiline text. Made with Corona SDK. . .",
x = display.contentCenterX,
y = display.contentCenterY,
width = 300,
50 Display
font = native.systemFont,
align = "center",
fontSize = 25
}
The align property is only available with the advanced syntax and sup-
ports the following values : left (default), right, or center.
Practice
Experiment with the different behaviors of the text objects. Try to align
texts on the right, on the left, or even on the bottom of the screen using
anchorY and the display.contentHeight property.
TO GO FURTHER . . .
If you want to use custom fonts, I recommend this official FAQ:
http://coronalabs.com/blog/2013/01/16/faq-wednesday-custom-fonts/
For anchor points, refer to this official guide:
http://docs.coronalabs.com/guide/graphics/transform-anchor.html
This page intentionally left blank
Images
54 Display
Now we’re ready to draw basic shapes. We’re going to learn how to
display images like backgrounds, grounds, and crates. Then we’ll create
and display sprites.
An image is a picture, and most of the time contained in a file called a
jpeg or a png. A sprite is one or several animated sequences of images. It
is used in video games to display characters, animations, and so on. The
main advantage of sprites is that all the images can be gathered in one
big picture called the image sheet. There’s a lot to learn here, but it’s fun!
What Is an Image?
At the beginning of this chapter, I mentioned jpeg and png. How are
they different? You just have to remember this:
• a jpeg is a rectangular picture, with no transparent parts.
• a png is a picture with transparent parts, so it allows nonrectangu-
lar images.
PRO TIP: While jpeg files tend to be lighter than png, I always use jpeg
when I don’t need transparent parts in the asset.
Standard Image
A standard image is displayed using a single line of code:
It’s important to understand that once the image has been displayed,
it will remain on the screen forever until you remove it. It’s a display
object, and this is how Corona SDK deals with those. In some other
low-level programming languages, we have to redraw the image over
and over again on every frame. Thankfully, that’s not the case with
Corona SDK. Good news, right?
Dynamic Images
Standard Image and Device Resolution
A standard image (created with newImage) will not have the same
rendering depending on which device it is displayed on. For exam-
ple, the image will be crisp on an iPad with Retina display, but just
so-so on an old iPhone 4. You’ll say to yourself, why not provide only
high-definition images? Because you will force Corona to scale down
Images 55
local myImageDynamic =
display.newImageRect("chicken.png",
132, 153)
application = {
content = {
width = 320*2,
height = 480*2,
scale = "letterBox",
fps = 30,
imageSuffix = {
["@2x"] = 2,
}
},
}
Standard: chicken.png
High-definition: chicken@2x.png
56 Display
It’s a lot to digest, I know, but you have to master this part to be able
to create apps that render best on devices of all sizes.
I will teach you everything in detail in the chapter “The Screen Jun-
gles.” Keep cool until then; you have more to learn.
TO GO FURTHER . . .
You can find everything about standard images objects here:
http://docs.coronalabs.com/api/library/display/newImage.html
And regarding dynamic images with imageRect:
http://docs.coronalabs.com/api/library/display/newImageRect.html
But do not forget to look at the project configuration guide:
http://docs.coronalabs.com/guide/basics/configSettings/index.html
Shapes
58 Display
Circle
local head = display.newCircle(160, 100, 50)
Rectangle
To illustrate a rectangle, let’s add a chest to the head:
Here is a nice chest . . . for a stick figure wearing an ugly green shirt.
I like it!
Lines
We’ll use lines to add some arms to our stick figure:
arm1.strokeWidth = 10
arm2.strokeWidth = 10
It’s done!
60 Display
An Underlined Title
Draw a label, then add a line between it. Simple!
-- An underlined title
options =
{
text = "My underlined title",
x = display.contentCenterX,
y = 150,
font = native.systemFont,
fontSize = 25
}
local myTitle2 = display.newText(options)
A Squared Title
The classic squared label using just few lines of code!
-- A squared title
options =
{
text = "I'm in a frame!",
x = display.contentCenterX,
y = 250,
font = native.systemFont,
fontSize = 25
}
local myTitle3 = display.newText(options)
64 Display
-- The square
local padding = 5
local title3Square = display.newRect(
myTitle3.x, myTitle3.y,
myTitle3.width + padding, myTitle3.height
+ padding)
-- To be a square, the rect needs a stroke and a
transparent fill
title3Square.strokeWidth = 1
title3Square:setFillColor(0, 0)
title3Square:setStrokeColor(.6, .6, .8)
TO GO FURTHER . . .
You can find everything about shape objects in the official Shapes guide
from Corona Labs:
http://docs.coronalabs.com/guide/graphics/path.html
Regarding the text object, look at the newtext API documentation:
http://docs.coronalabs.com/api/library/display/newText.html
This page intentionally left blank
Part 3
Move
Reverse Transition
In our first example, we moved our ball from its current position to
another one. We can also do the opposite and move our ball from one
position to the current one. Here is how:
As you can see, we animated the alpha from 0 to the current value,
which is 1 by default. The other, less direct way to do this is with
transition.to:
box.alpha = 0
Smooth Transitions
Now that we know how to animate some properties, let’s add
some fun.
In our example, the properties (x, y, rotation, alpha) were animated
linearly. Adding an easing method to the transition allows us to add
some nonlinear movements like bounce effect, acceleration, decelera-
tion, and so forth. There are dozens of easing methods!
Here is an outExpo effect giving the illusion that the circle lands
smoothly in its final position:
And to add a funny bounce effect, just change the transition to:
onComplete
A transition would not be so powerful without the ability to trigger a
function when the transition is over. There are several ways to do this;
here are my favorites:
• Chain transitions, like bounces back and forth
• Displaying something when a transition is over
• Playing a sound when a transition is over
72 Move
function ballDown()
transition.to(ball, { y = 200, time=1000,
transition = easing.inQuad,
onComplete = ballUp })
end
function ballUp(ball)
transition.to(ball, { y = 100, time=1000,
transition = easing.outQuad,
onComplete = ballDown })
end
ballDown()
Read the code carefully. There are two functions, one of the falling
ball, the other moving it back to its upper position. Each one is calling
the other when the transition is over using onComplete. We then just
have to create the ball and make it fall by calling ballDown once!
This other example displays a text (using a fade-in transition!) when a
circle reaches its final position:
function boxDone()
transition.to(boxText, { alpha = 1, time =
500 })
end
boxText.alpha = 0
TOP TIP: With Lua you’re able to declare the function on the fly,
inside the transition call! Here is how:
transition.to(box,
{ y = 400, time = 2000, transition =
easing.outExpo,
onComplete = function()
transition.to(boxText, { alpha
= 1, time = 500 })
end
})
Convenient Methods
If you want, you can use some convenient methods provided by Corona
SDK. Some of them are useless like moveTo or scaleTo, but the others
allow you to focus on the effect, not the properties to animate.
Here are these methods, each one provided as an example:
transition.blink()
transition.dissolve()
74 Move
transition.fadeIn()
transition.fadeOut()
transition.moveBy()
transition.moveTo()
transition.scaleBy()
transition.scaleTo()
Practice
Be sure to experiment with transitions to create some nice and fun
effects. As another exercise, revisit the chapter on images and animate
an image instead of circle and rectangles.
Do you remember the familiar game with a plumber jumping every-
where? Remember the rotating coins? Achieve this effect with what you
have learned! Here are some clues:
• Animate the xScale back and forth.
• Use onComplete to chain xScale transitions.
Remember the game with the flapping bird? You can make the pipe
move from right to left using a transition too. Let’s do it!
TO GO FURTHER . . .
Here are some useful links from the official documentation:
First, the starting point, everything about the transition library:
http://docs.coronalabs.com/api/library/transition/index.html
Then, the reference guide for the easing functions, with visuals:
http://docs.coronalabs.com/api/library/easing/index.html
Move Objects Around
the Screen
The Interactive Way
76 Move
It’s moving? Now let’s add some interactivity with user inputs. This sec-
tion will teach you how to move objects in response to taps and finger
movements on the screen.
A user input can take various forms: a single tap, a tap followed by a
move, or a device movement like a shake.
Each time the user interacts with the device, an event is sent to your
code. To react to this event, you need to “catch” it. We can catch an
event by “listening” to it with an event listener.
function onBtn(event)
print("Tap on Left")
end
myBtn:addEventListener("tap", onBtn)
What about adding a nice effect on the circle using our new transition
expertise? Add this code in the OnBtn function:
Got it? This single line of code will make our circle bounce when
tapped!
myObject:setFillColor(255)
function onTouch(event)
print(event.phase)
return true
end
myObject:addEventListener("touch", onTouch)
PRO TIP: For cleaner code, you should attach your listener function
to the display object itself. Here is how:
function myObject:touch(event)
print(event.phase)
return true
end
myObject:addEventListener("touch", myObject)
78 Move
display.getCurrentStage()
Then we’ll need to set a flag to true to know if the user is currently
dragging the object or not. It’s quite easy: we’ll set this flag to true on the
began phase, and set it to false on the ended phase. The rest of the time,
if we get a moved on the object, we’ll know if we need to drag it or not!
Here is the full code:
function myObject:touch(event)
if event.phase == "began" then
display.getCurrentStage():
Move Objects the Interactive Way 79
setFocus(self)
self.isDrag = true
self.initX = self.x
self.initY = self.y
return true
end
myObject:addEventListener("touch", myObject)
Amazing!
If you’re not sure that you understand the purpose of the isDrag flag,
try not to use it (comment the lines involving it with two hyphens:
“--”), and then drag your finger (actually, from the Corona Simulator,
the mouse with the left button pressed) from the outside of the square,
and then move on it. The square gets some touch events (with “moved”
phases) that it should ignore, and goes crazy!
PRO TIP: To understand a code from another coder, the best way
is to play with it by commenting on the parts that you don’t under-
stand the need for. Next, run the code and see what bugs result. Then,
change some values and look at the impact. By doing it this way, you’ll
be more comfortable with the code.
80 Move
Practice
I challenge you to combine these last two lessons. Let’s add two circle
buttons to the very last example (the “drag the square”). One of these
circle buttons will make the square move to the left of the screen using a
transition, and the other to the right.
Ready? Go!
Move Objects Around
the Screen
Frame by Frame
82 Move
It’s sometime necessary to move objects across the screen with full control.
Transitions are great, but they aren’t the answer for everything. I’ll teach you
how to perform a code of your own every time the system displays a frame
on the screen. This will give you full control over movements on the screen.
Keep in mind, however, that performing a code 60 times per second is
bad for the app’s performance. So, any time you can use a simple event
or a transition instead, your app will thank you.
What Is a Frame?
While it’s not obvious when using an advanced SDK like Corona SDK,
every system is refreshing its display many times per second—around
60! A refresh is called a frame. Perhaps you’ve seen the acronym FPS
somewhere? It means frame per second, which is the “frame rate.” Most
game coders will target a 60 FPS frame rate for a perfectly smooth game.
Please note that you can get the current frame rate by calling display.
fps; for example:
If you perform too many things in your code, or if your game displays
a lot of moving objects at the same time, the frame rate can be impacted,
and your game will slow down.
It’s also important to know that Corona SDK apps run with a limit of
30 FPS by default. To change this, you need to add/modify a line in the
file called config.lua. To run your app at 60 FPS, change the fps value to
60 by doing this:
application = {
content = {
width = 320,
height = 480,
scale = "letterBox",
fps = 60,
},
}
Runtime:addEventListener("enterFrame",
myListener)
Here it is! Here we just created a circle shape and we moved it around
the screen by changing its x and y properties. By default, we increased
both x and y, making the ball follow a diagonal. Then, when the ball
reached an edge, we reversed the move.
84 Move
You can resolve this issue by calculating the time elapsed since the last
frame. (The value you’ll get is called the “delta time,” or “delta” by coding
insiders). If the device runs slowly, this delta will be higher, so the trick
is to multiply all the values you use to change positions with this delta:
Practice
Here’s a simple exercise: Add a third ball that moves only vertically,
starting at the center of the screen.
Another one, tougher this time: Create a star field using the List
lesson you just learned. Create a bunch of dots using a small circle, store
them in a list, make them move from one side of the screen to another
frame by frame, then translate the ones moving outside of the screen to
the opposite!
TO GO FURTHER . . .
A tutorial about the EnterFrame event:
http://coronalabs.com/blog/2012/02/21/understanding-coronas-
enterframe-event/
The EnterFrame event documentation:
http://docs.coronalabs.com/api/event/enterFrame/index.html
This page intentionally left blank
Make Them Fall
The Physics Engine
88 Move
There’s a smart way to deal with object movements, which is to let the
engine do the job for you! If your game idea fits with it, the physics
engine will do a lot of the heavy lifting.
The physics engine adds life to your game objects by giving them
weight and consistency, which allows objects to fall, bounce, and collide.
Games like Angry Birds are great examples of the physics engine doing
its job.
Type this code into your editor, run it, and look at how the ball is
falling and bouncing, where your code is not doing anything!
Let me explain the code:
NOTE: Corona SDK uses the Box2D engine, which is one of the most
popular in the game coding world. Thousands of games are imple-
menting it. Corona SDK lets you use it with some degree of simplicity,
but remember that this engine is huge (and very powerful too). I’m
providing enough guidance here for you to get started.
Rectangular Body
By default, the body is rectangular and the body boundaries will snap to
the rectangular boundaries of the display object.
90 Move
Circular Body
Just add radius=r to the table, where r is the radius of the object. This is
the ball example.
Complex Body
Corona SDK allows bodies to have very complex shapes, even multi-art
bodies, but it’s beyond the scope of this book. That said, if your object
has a nonrectangular and noncircular shape, the simplest way is to
use the outline feature (which is limited to Pro and Enterprise Corona
users). Here is an example:
physics = require("physics")
physics.setDrawMode("hybrid")
physics.start()
Then, let’s create a function to create a new ball. We’ll color it ran-
domly and give it a small velocity so that not all the balls fall vertically.
This will create a nice fountain effect:
Make Them Fall 91
function newBall()
local ball = display.newCircle(display.
contentCenterX+math.random(-10,10), 100, 20)
ball:setFillColor(math.random(), math.
random(), math.random())
ball.rotation = math.random(0,360)
physics.addBody(ball, "dynamic", { radius
= 20, density=1.0, friction=0.3, bounce=0.5 })
ball:setLinearVelocity(math.random
(-50,50), 0)
end
92 Move
Now, the ground! Because I do not want the balls to fall out of the
screen, we’ll create two tilted and static grounds, to simulate a kind of pit:
Enjoy!
Runtime:addEventListener("collision",
onCollision)
For the balls, we’ll use a global counter called ballNumber to number
the balls.
Here is the full code:
physics = require("physics")
physics.setDrawMode("hybrid")
physics.start()
local ballNumber = 0
function newBall()
local ball = display.newCircle(display.
contentCenterX+math.random(-10,10), 100, 20)
ball:setFillColor(math.random(), math.
random(), math.random())
ball.rotation = math.random(0,360)
physics.addBody(ball, "dynamic", { radius
= 20, density=1.0, friction=0.3, bounce=0.5 })
ball:setLinearVelocity(math
random(-50,50), 0)
ball.myName="ball #"..ballNumber
ballNumber = ballNumber + 1
end
94 Move
TO GO FURTHER . . .
Look deeply in the Corona SDK documentation and samples to master
the physics engine. Here are some useful links.
Make Them Fall 95
A game is not a game if nothing collides, but not all games need physics!
The physics engine offers the simplest way to deal with collisions; however,
adding a body to an object makes it fall on the screen. Funny, but useless!
print("Collision occurs")
end
end
Runtime:addEventListener("collision",
onCollision)
physics = require("physics")
physics.start()
physics.setGravity(0,0)
math.random())
physics.addBody(ball1, "dynamic",
{ isSensor=true, radius = 20 })
ball1.xMove = math.random(1,5)
ball1.yMove = math.random(1,5)
ball1.x = previousXball1
end
if ball1.y <= 0 or ball1.y >= display.
contentHeight then
ball1.yMove = 0 - ball1.yMove
ball1.y = previousYball1
end
if ball2.x <= 0 or ball2.x >= display.
contentWidth then
ball2.xMove = 0 - ball2.xMove
ball2.x = previousXball2
end
if ball2.y <= 0 or ball2.y >= display.
contentHeight then
ball2.yMove = 0 - ball2.yMove
ball2.y = previousYball2
end
end
Runtime:addEventListener("collision",
onCollision)
Runtime:addEventListener("enterFrame",
myListener)
As you can see, we are randomly changing the colors of the circles
when they collide.
In this lesson, we managed to detect a collision between 2 graphical
objects without using any strange code. Nice!
Make Them Collide But Not Fall 101
Now we can see, in the console, the names of our balls when they
collide. This isn’t very useful as there are only two objects on the screen.
Let’s add a wall. Input this code after the creation of the 2 balls:
Practice
You now have enough knowledge to create a basic Space Invaders–type
game!
Create a basic game with:
• A ship at the bottom of the screen, with 3 buttons to move it from
left to right and fire a bullet.
• Some aliens on the top (no need to make them move at this stage).
• Code (using the tap event) that assigns actions to the 3 buttons:
• 1 left button: to decrease the x position of the ship
• 1 right button: to increase the x position of the ship
• 1 fire button: to create a bullet (can be a small circle) that moves
from the ship position to the top of the screen using a transition
(or frame by frame if you prefer)
• Adding a collision event to detect a collision between a bullet and
an alien, making the alien disappear!
Ready? Go!
Make Them Collide But Not Fall 103
TO GO FURTHER . . .
You can go deeper with collisions; this was just an introduction that
covered the basics.
Here is an official guide regarding collision detection:
http://docs.coronalabs.com/guide/physics/collisionDetection/
This page intentionally left blank
Animate Images
With Sprites
106 Move
KEY POINT: Sprite images are stored in image sheets. An image sheet
combines numerous small images into a larger image. It allows storing
many images in one, creating frame-by-frame animations, and reducing
processing time.
Image Sheets
To build an image sheet, you have two options:
KEY POINT: There are several tools available for building image
sheets, so feel free to choose your favorite.
My favorite is Texture Packer. It is available for Mac and Windows:
www.codeandweb.com/texturepacker/coronasdk
Consider paying for tools like these . . . they are definitely worth it!
Using a tool is fast and user friendly. It does a lot of the work for you,
supports multiple sizes for the different resolutions, and arranges the
images in the sheet to reduce its size. The bad news: these tools are not
free. However, I would consider them must-haves.
Animate Images With Sprites 107
From the code side it’s quite simple, as you just have to describe the
size of the sprite and the number of frames:
local options =
{
width = 174,
height = 160,
numFrames = 4
}
108 Move
Now, here is the code to use the generated image sheet in your code:
If you created the sprite sheet with a tool, the process is slightly
different:
local sequenceData2 =
{
name="fly",
frames={sheetInfo:getFrameIndex
("blitzsubspeed1"),
sheetInfo:getFrameIndex
("blitzsubspeed2"),
sheetInfo:getFrameIndex
("blitzsubspeed3"),
sheetInfo:getFrameIndex
("blitzsubspeed4")},
time=250,
loopCount = 0,
loopDirection = "bounce"
}
TO GO FURTHER . . .
CoronaLabs provides a detailed guide for sprite sheets here:
http://docs.coronalabs.com/guide/media/imageSheets/index.html
Introduction
In this section, you’ll learn to add “must have” features to your games:
• Organize your games in screens
• Add sounds and advanced input
• Save and restore game data
The road to creating a great, complete game is almost over!
114 Advanced Features
function scene:create(event)
function onTouchText(event)
print("Text was touched!")
end
mytitle:addEventListener("tap", onTouchText)
end
scene:addEventListener("create", scene)
return scene
116 Advanced Features
Run the project and touch the text. Ok, nothing happens . . . but it’s
not finished! You have to understand what we did first. The “scene.lua”
file is creating and returning a new scene. It’s a kind of object that will
then be used by gotoScene.
So, we first create a new scene:
function scene:create(event)
...
NOTE: If you‘re not familiar with this kind of function, take a look at
the chapter “Object-Oriented Programming With Lua.”
...
local mytitle = display.newText(self.view, ...
Note how the label is added to a view using the optional parent
parameter from newText.
Yes, a Composer scene is a display group! The Composer library cre-
ates the group when the scene is created, so you don’t have to deal with
its creation. However, you do have to add all the display objects that you
create to the scene view. This view is accessible in the view property of
the scene. Just use “self.view” in any scene function to access it.
The following code is just adding a tap event to the label. Refer to the
chapter “Moving Objects Around the Screen: The Interactive Way” if
you missed something.
Finally, we link the scene:create function to the create event that will
be raised by the scene:
scene:addEventListener("create", scene)
Advanced Features 117
You can now guess the plan: go to scene 2 from scene 1 and . . . go to
scene 1 from scene 2! Let’s add the “go to” stuff to our code now.
In “scene1.lua,” just change the onTouchText function to match this:
function onTouchText(event)
composer.gotoScene("scene2")
end
And in “scene2.lua”:
function onTouchText(event)
composer.gotoScene("scene1")
end
Run your code. You can now jump from one scene to another!
scene:show()
118 Advanced Features
This event is raised after the create event, when the scene will be
shown. It’s the best place to add some effects to the display objects (such
as fade-in or transitions).
scene:hide()
This event is raised when the scene is hidden because another scene is
opening.
scene:destroy()
function scene:show(event)
if (event.phase == "will") then
-- Your code here, executed before
the scene is shown
elseif (event.phase == "did") then
-- Your code here, executed after
the scene is shown
end
end
scene:addEventListener("show", scene)
Practice
Now, it’s quite easy to add the show event to our scene. Do not forget the
addEventListener at the end!
Then, make the title fade in when the scene is displayed.
The idea is simple:
• Make the title become invisible (alpha=0) before the scene is displayed.
• Transition the title alpha to 1 when the scene is displayed.
Advanced Features 119
TO GO FURTHER . . .
You can find a scene template in the official Composer documentation:
http://docs.coronalabs.com/api/library/composer/index.html
A full guide provides in-depth details here:
http://docs.coronalabs.com/guide/system/composer/index.html
This page intentionally left blank
Add Sounds and Music
122 Advanced Features
What Is a Sound?
In the game programmer universe, a sound is a file containing some
sound data. Corona supports a few different sound file formats, but to
have a fully cross-platform game, please use only MP3 and WAV.
A WAV sound is heavy; an MP3 sound is light.
You get the point: MP3 is the better sound format for your games.
On the tool side, there is one must-have: Audacity. This is an audio
editor that’s useful for cutting, converting, or tweaking your sounds. It is
available for both Windows and Mac, and you can download it for free
here:
http://audacity.sourceforge.net/
Create a Sound
The purest way to get sound effects is to create them yourself! You can
record some sounds, or create your sounds using tools, but that’s out of
our scope here.
However, if you want to create some fun arcade sounds, use SFRX by
Tomas Pettersson:
www.drpetter.se/project_sfxr.html
This tool will help you create random arcade sounds with just a few
mouse clicks.
Regular sounds are loaded in their entirety. It’s the best way to incor-
porate event sounds.
Load and play a regular sound:
In the example, the load and loadStream are receiving the name of the
sound file, and return a handle (or “channel number” in some docu-
mentation). You then just have to pass this handle to audio.play.
TIP: Load your sounds beforehand; for example, during the scene
creation.
Loop a Sound
audio.play(myGameMusic, { loops= -1})
or
local options = {
loops = -1
}
audio.play(myGameMusic, options)
124 Advanced Features
audio.resume(myGameMusic)
audio.setVolume(0.5)
audio.setVolume(0.75, { channel=myGameMusic })
Practice
You are on vacation, no need to practice today!
TO GO FURTHER . . .
You can find the entire audio library API in the official documentation:
http://docs.coronalabs.com/api/library/audio/index.html
And an official guide here:
http://docs.coronalabs.com/guide/media/audioSystem/index.html
Menu and User Interface
126 Advanced Features
What do you think of what you have learned so far? You have learned
everything you need to create your own games by displaying things,
make them move, and making noise . . . but now you need to learn how
to put it all into a nice box!
The box is the User Interface (UI), also known as the Head Up Dis-
play (HUD) by the pros. The main part of this HUD is the game menu.
All the remaining screens will be similar.
I’m going to show you how to create a nice animated menu. Here is
our objective, with around 80 lines of code:
You can create this nice menu with just 80 lines of code.
Menu and User Interface 127
NOTE: You can use your own graphic assets, but for the example I
used some of my own, inspired by my game Chicken Deep. You can
download these assets from the book companion and use them for
testing purposes.
Also note that this example is for a smartphone, not for an iPad. To
understand the specifics of iPad programming, please refer to the next
chapter.
application = {
content = {
width = 320,
height = 480,
scale = "letterBox",
fps = 60,
imageSuffix = {
["@2x"] = 2,
}
},
}
-- From main.lua
local composer = require("composer")
composer.gotoScene("menu", "fade")
Now, create the menu.lua scene and modify the create function to
match this:
-- Main background
local background = display.newImageRect(view,
"background.jpg", 320, 568)
background.x = display.contentCenterX
background.y = display.contentCenterY
iPhone 4 screen, the 4-inch iPhone 5 screen, and the recent iPhone 6
and iPhone 6 plus screen ratio.
-- Game Logo
menuLogo = display.newImageRect(view, "logo.
png", 252, 124)
menuLogo.x = display.contentCenterX
menuLogo.y = 130
menuOverlay = display.newImageRect(view,
"overlay.png", 320, 180)
menuOverlay.anchorY = 1
menuOverlay.x = display.contentCenterX
menuOverlay.y = display.actualContentHeight +
display.screenOriginY
Note how the overlay and the button are displayed relative to the
bottom of screen. We use here the display.screenOriginY value provided
by Corona SDK. In our example, this value is 0 if we run the app on an
iPhone 4 and 44 on an iPhone 5. Indeed, the iPhone 5 is 88 pixels higher
than the iPhone 4 (44 is half of 88).
Add Interactivity
We now have to react when the play button is pressed. You know how:
function onPlay(event)
composer.gotoScene("gameplay", options)
end
menuButton:addEventListener("tap", onPlay)
This code will open the gameplay scene when the button is tapped.
For the example, you have to create a gameplay.lua scene.
function scene:show(event)
if (event.phase == "will") then
print("will")
menuOverlay.isVisible = false
menuButton.isVisible = false
menuFish.x = display.
actualContentWidth + menuFish.width
...
...
elseif (event.phase == "did") then
print("did")
menuOverlay.isVisible = true
132 Advanced Features
Despite the large amount of code, it’s not a big deal. We’re using the
transitions to make the animation, using the onComplete callback to
chain the animation:
• The overlay is slid from the bottom of the screen, and then the
button is displayed when the transition is completed.
• The fish are moved from the right to the left with a nice effect, then
moved back to the right when they are out of the screen.
Practice
Download the full sample from the book companion website, then
analyze the code to see how it works. Look how I made the fish swim by
chaining transitions.
Menu and User Interface 133
I passed a parameter from the menu to the gameplay scene using the
params property:
local options =
{
effect = "fade",
time = 300,
params = {
sampleParam = "I was here!"
}
}
composer.gotoScene("gameplay", options)
function scene:show(event)
if (event.phase == "will") then
print("will")
myTitle.alpha = 0
print("Get a parameter:",event.
params.sampleParam)
...
TO GO FURTHER . . .
Read carefully the documentation regarding newImageRect to get more
detail about the dynamic content scaling:
http://docs.coronalabs.com/api/library/display/newImageRect.html
Some more information regarding the iPad and the Retina display:
http://coronalabs.com/blog/2012/03/22/developing-for-ipad-retina-
display/
This page intentionally left blank
The Screen Jungles
136 Advanced Features
application = {
content = {
width = 320,
height = 480,
scale = "letterBox",
fps = 60,
imageSuffix = {
["@2x"] = 2,
}
},
}
The width and the height are defining the content area. This content
area represents the virtual size of the app you are creating. It’s virtual,
because the actual device resolution will differ most of the time. Corona
will then use the scale factor, defined by scale, to adjust the content area
size and the aspect ratio to match the actual device size.
The Screen Jungles 137
Now that you know the three possible values, forget the last two, and
use only letterBox.
imageSuffix = {
["@2x"] = 2,
}
-- main.lua
display.setStatusBar(display.HiddenStatusBar)
background = display.newImageRect("360x570bg.
jpg", 360, 570)
background.x = display.contentCenterX
background.y = display.contentCenterY
print("display.screenOriginX", display.
screenOriginX)
print("display.screenOriginY", display.
screenOriginY)
print("display.actualContentWidth", display.
actualContentWidth)
print("display.actualContentHeight", display.
actualContentHeight)
print("display.contentWidth", display.
contentWidth)
print("display.contentHeight", display.
contentHeight)
Run this code, and look at your traces. The code is displaying all the
key values from the display API.
140 Advanced Features
Now, imagine you want to display a red square at 10 pixels from the
left side of your screen. Add these lines:
Run your code and play with the “Window/View as” menu. Try the
iPad, the iPhone 5, the Kindle Fire, and other platforms. Look how the
values differ and how your background is cropped, or not.
Is your red square at 10 pixels from the left side on every device? No.
This is because when the screen aspect ratio is different than your con-
tent area aspect ratio, some parts of the screen are cropped, and others
are added with blank (actually black) content.
You can fix the issue by using the display.screenOriginX (or display.
screenOriginY) property:
Fixed! But you need to apply this to any display object you need to
align with the borders. It’s tedious and it’s a source of bugs. The sample
“ScreenJungle” shows you how to adjust the position to display objects
on all four sides.
Now comes the magical config.lua . . .
The Screen Jungles 141
imageSuffix = {
["@2x"] = 1.3,
},
},
}
TO GO FURTHER . . .
Corona SDK official documentation for the project configuration:
http://docs.coronalabs.com/guide/basics/configSettings/index.html
The tutorial from which I took the magical config.lua, including some
explanation on how it happens:
http://coronalabs.com/blog/2013/09/10/modernizing-the-config-lua/
Save and Restore Data
144 Advanced Features
gamedata = {}
gamedata.player = {}
gamedata.player.live = 3
gamedata.player.shield = 100
{"player":{"live":3,"shield":100}}
{
"player":
{
"live":3,
"shield":100
}
}
Now that you’re convinced, here is the developer kit to use JSON in
your Corona SDK games!
Save and Restore Data 145
ships = {}
ships[1] = {}
ships[1].name = "Alpha Centauri"
ships[1].shield = 100
ships[2] = {}
ships[2].name = "Cygnus"
ships[2].shield = 150
ships[3] = {}
ships[3].name = "Taurus"
ships[3].shield = 200
encoded = json.encode(ships)
print(encoded)
The encoded table (in JSON format) is then displayed in the console.
Just copy and paste the text in a text editor. The result is:
[{"name":"Alpha Centauri","shield":100},
{"name":"Cygnus","shield":150},
{"name":"Taurus","shield":200}]
146 Advanced Features
To read this data in your game, just use these lines of code:
shipsData = {}
jsonContent = jsonFile("ships.json",system.
ResourceDirectory)
shipsData = json.decode(jsonContent)
We first declare a small function jsonFile able to read a text file and
return its content in a string. Then we use this function to read our
JSON file in the resource directory. The resource directory is the folder
where the game files are stored (just put files beside your Lua files so
they will be installed in the resource directory).
Once we have the file content in a string (jsonContent in the example),
we just have to decode it to get a Lua table containing the data!
Let’s display the data we just read:
for i in pairs(shipsData) do
print(shipsData[i].name,shipsData[i]
.shield)
end
NOTE: We just used here what we learned in the chapter “Arrays and
Lists” to browse the array.
Save and Restore Data 147
saveToFile("gamedata.json", system.DocumentsDi-
rectory, encoded)
TO GO FURTHER . . .
All you need to know about the Resource Directory:
http://docs.coronalabs.com/api/library/system/ResourceDirectory.html
And for the Documents Directory:
http://docs.coronalabs.com/api/library/system/DocumentsDirectory.html
And all about the JSON API from Corona SDK:
http://docs.coronalabs.com/api/library/json/index.html
Part 5
To the Stores
NOTE: I do not cover subscription purchases here; these are too far
from the game universe.
Before proposing IAP in your game, you need to set up the products
in the developer’s portals. Each product has an identifier (ID) that you
then use in your code. The standard is to use the “reverse domain name”
system:
com.yourcompany.yourgame.yourproduct
To set up your respective developer’s account, follow the updated
processes from the CoronaLabs documentation:
iOS:
http://docs.coronalabs.com/daily/guide/monetization/IAP/index.html#setupios
Google Play:
http://docs.coronalabs.com/daily/guide/monetization/IAP/index.html#goo-
gle-play-setup
You will then use the store API from Corona SDK through three main
API calls:
• store.init()
• store.purchase()
• store.restore()
I definitely encourage you to learn from the Corona Labs documen-
tation and to experiment. I cannot show you everything here, but I’ve
given you the fundamentals.
Here are some useful code snippets for reference:
152 To the Stores
function transactionCallback(event)
-- Transaction successful
-- Transaction restored
-- Transaction cancelled
-- Transaction failed
else
end
store.finishTransaction(transaction)
end
RESTORED TRANSACTION
transaction.originalReceipt Same as the receipt, but for the original
purchase.
transaction.originalIdentifier Same as the identifier, but for the
original purchase.
transaction.originalDate Same as the date, but for the original
purchase.
FAILED TRANSACTION
transaction.errorType The type of error that occurred when the
state is “failed” (a string).
transaction.errorString A more descriptive error message of what
went wrong in the “failed” case.
All these values are related to the vendor, and you should read the
official documentation from them to get more details:
For iOS:
https://developer.apple.com/library/mac/documentation/NetworkingInternet/
Conceptual/StoreKitGuide/Introduction.html
For Google Play:
http://developer.android.com/guide/market/billing/billing_admin.html
Make a Purchase
store.purchase(productList)
store.purchase({"com.yourcompany.yourgame.
yourproduct"})
Restore a Purchase
store.restore()
IMPORTANT: From the Android side, do not forget to add the per-
missions in the build.settings file:
android =
{
usesPermissions =
{
"android.permission.INTERNET",
"com.android.vending.BILLING",
"com.android.vending.CHECK_LICENSE",
},
},
ads.init()
NOTE: How you will set up then initialize the ad network will depend
on the partner. I won’t cover all the partners here; please refer to the
Corona SDK documentation.
To the Stores 155
ads.show()
ads.hide()
There are also other ad network partners that are not part of the ads
API. For instance, the Chartboost community provides an open source
plugin on their official site: https://help.chartboost.com/documentation/
open-source-sdks#corona. So, be aware and keep up with the Corona
Labs forums.
Expect to spend a lot of effort finding players, as making money with
ads requires A LOT of active players!
Then, you just have to collect the money!
TO GO FURTHER . . .
Corona Labs provides a complete guide for In-App Purchases:
http://docs.coronalabs.com/daily/guide/monetization/IAP/index.html
And a tutorial:
http://coronalabs.com/blog/2013/09/03/tutorial-understanding-in-app-
purchases/
Do not forget the store API documentation to get detailed samples for
each function:
http://docs.coronalabs.com/api/library/store/index.html
As the rules are changing often, you should always refer to the official
Corona SDK documentation regarding topics linked to the Apple and
Google stores.
Regarding In-App Advertising, here is the complete list of the
supported networks and how to implement them:
http://docs.coronalabs.com/api/library/ads/index.html
This page intentionally left blank
Test and Debug
158 To the Stores
physics.starte()
instead of:
physics.start()
Programming bugs can be tricky to fix, and so I’ll spend more time
talking about them here.
• The first word of variables and functions is lowercase, and all fol-
lowing words start with capital letters: myFunction, thisIsAVariable-
Name.
• Apply Hungarian Notation, which consists of starting the
name with a letter describing its type: bStarted (Boolean), nLife
(numeric), sName (string), fAngle (float), tPlayer (table), and so on.
• Do not introduce useless empty lines.
• Use comments to organize your code (different parts, phases,
behavior, objectives, etc.), and comment to explain something, not
simply repeat what your code is doing.
• Be homogenous.
• Delete commented/deactivated code.
Even if your code seems perfect, you have to treat it with suspicion. If
your code is as perfect as you think, there should be no bugs. Yet, there
are some. Admit it.
It’s not a treasure; it’s just some lines of code! Put some traces in it,
and admire the disaster . . . Most of the time, the bugs are in the places
you don’t expect. Be your own worst enemy: do not trust your code!
Use Traces
Following the previous advice, the use of traces will show you the real
behavior of your code, not the one you imagined.
Sometimes, the good result you get with your code is a coincidence:
the code is not always executed as you think, yet you get the result you
expected, because of an unexpected side effect from another line of
code!
Do the Monkey
Run your app and test it. Everything OK? Now, think of yourself
like a monkey in the zoo. Test it again, but instead of testing like a
well-behaved child, just tap everywhere like mad and . . . it’s a miracle;
you found a bug!
Display this version number somewhere in your app (in the credit
scene, for instance). It’s VERY useful: when a bug is reported, you will
easily know the version of your app in which the bug appeared!
1) Deactivate all the useless code around the part you suspect (even if
your app is then partially unusable).
2) Run your code and notice that the bug is not triggered.
3) Activate a small part of the deactivated code, and run it again.
4) Proceed until the bug returns; you now know where it is hiding!
If this method does not work, consider adding dirty and temporary
traces in your code: trace the suspected (and the less suspected) values,
trace all the function calls, and so forth. Be patient.
-- Trace a string
print("My string contains", str)
Now, you have to use _print(. . . instead of print(…, and your traces
won’t be computed if you set the DEBUG variable to false. Example:
TO GO FURTHER . . .
Corona Labs has a simple tutorial about basic testing and debugging:
http://coronalabs.com/blog/2013/07/09/tutorial-basic-debugging/
Debug
164 To the Stores
Now that you’ve tested your game, I will teach you everything about
debugging.
adb logcat
Note that you may have to put your device into “developer mode.”
Do an Internet search for “android activate developer mode” to find
instructions, which will depend on your device and version of Android.
Debug 167
TO GO FURTHER . . .
Apple explains everything about testing on a device here:
https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/
AppDistributionGuide/Introduction/Introduction.html
Corona Labs has published a simple tutorial about basic testing:
http://coronalabs.com/blog/2013/07/09/tutorial-basic-debugging/
The complete building guides from Corona Labs are here:
http://docs.coronalabs.com/guide/index.html#building-and-distribution
This page intentionally left blank
Deploy
170 To the Stores
The Holy Grail—and the most annoying and confusing part! Thanks to
Corona SDK, however, deploying a game is greatly simplified.
The main thing to know is that, independently of the build/signing
process, which I will explain, most of the deployment process will be
different depending on the operating system (iOS or Android), the
devices targeted (iPhone, iPad, Android, Kindle Fire, OUYA, etc.) and
the store you want your game to be sold in. This deployment process
can often evolve. That’s why I will give you the fundamentals to make
you autonomous and responsive, and then I’ll provide you all the links
to the official and updated processes.
Developer Accounts
For both iOS and Android you need a developer account.
For iOS you need an Apple ID, then register here:
https://developer.apple.com/devcenter/ios/
The current price is $99 per year.
For Android, you must sign up for a Google account, then create your
Google Play developer account here:
https://play.google.com/apps/publish/signup/
The current price is $25. This is a one time registration fee.
NOTE: Take a breath, and begin the process by following the link
above, and you’ll slowly become more familiar with the App Store.
Corona Labs servers will compile and deliver the app to you in a short
time. You’ll then obtain a file with the extension .app. Keep it safe!
Version name: A version name for your app. Use clear names, like
“beta1” for beta versions.
Package: The package name. The traditional Java scheme is to
use the reverse-domain format like com.yourcompany.yourapp.
Choose it carefully.
Minimum SDK version: Select the latest version.
Target app store: Select the store you’re targeting. Google Play is
the official store for Android phones and devices.
Keystore: Choose Debug to build for testing. Otherwise, you
should create a Keystore to deploy for the stores. See “To Go
Further . . .” below.
Key alias: Choose “androiddebugkey” to build for testing. Other-
wise choose the alias of your app, the one you created in the
Keystore.
Save to folder: This is where to save the .app file, which is what
you’ll distribute!
4) Click Build!
Corona Labs servers will compile and deliver the app to you in a short
time. You’ll then obtain a file with the extension .apk. Keep it safe!
PRO TIP: Target Android first. It’s the shorter way and it allows reach-
ing real players in a timely manner. The iOS publishing process is boring
and long, so when you start it you’ll be prepared with an improved app,
thanks to the Android players.
TO GO FURTHER . . .
There are a lot of reference materials, forums, and guides on the Inter-
net. However, the Corona Labs website remains the best place to go.
Regarding the project settings:
http://docs.coronalabs.com/guide/distribution/buildSettings/index.html
Regarding building for iOS and Android:
http://coronalabs.com/resources/tutorials/building-and-distribution/
For the Android Keystore, the process is here:
http://docs.coronalabs.com/guide/distribution/androidBuild/index.
html#signrelease
The official signing documentation for Android:
http://developer.android.com/tools/publishing/app-signing.html
Finally, there are the official guides from Apple regarding the App Store:
https://developer.apple.com/appstore/index.html
This page intentionally left blank
More With Corona SDK?
178 To the Stores
So, you think it’s over? Not at all! Corona SDK is an amazing and
powerful tool that’s growing every month. In this next-to-last chapter,
I’d like to provide an overview of what you can still do to improve your
creations, and some links to get even more out of these features.
local options = {
-- 140 characters only
message = "I’m reading an amazing book and
now I’m a game coder!"
}
native.showPopup("twitter", options)
local options =
{
to = "",
subject = "This is the subject",
More With Corona SDK? 179
Note how I included some extra lines using escape codes (\n). These
two characters will then be replaced in the message by an extra line.
And now, let’s publish a message on the Facebook wall of the player:
local fbCommand
local facebook = require("facebook")
function fbListener(event)
print("event.name", event.name)
print("event.type:", event.type)
print("isError: " .. tostring(event.isError))
print("didComplete: " .. tostring(event.
didComplete))
if ("session" == event.type)then
if fbCommand == POST_MSG then
local options = {
name = "Message name",
description = "I’m reading an
amazing book and now I’m a game coder!",
listener = fbListener,
link = "http://www.focalpress.com/"
}
facebook.showDialog("feed", options)
fbCommand = nil
end
elseif ("request" == event.type)then
-- event.response is a JSON object from
the FB server
local response = event.response
180 To the Stores
if (not event.isError)then
response = json.decode(event.response)
print(response)
fbCommand = POST_MSG
facebook.login(appId, fbListener,
{"publish_actions"})
IMPORTANT: Facebook API needs some setup before you can use it,
so please consult the official documentation to make sure you don’t
miss anything:
http://docs.coronalabs.com/api/library/facebook/index.html
For getting friends, you can also look at this official tutorial:
http://coronalabs.com/blog/2014/01/14/tutorial-getting-
facebook-friends-the-easy-way/
You’re done!
You’ve reached the end of the road, and a brand new landscape has
been revealed.
However, before leaving you alone I’d like to provide you with 13 tips
to help you learn and create quickly:
1—Familiarize Yourself
Read books and tutorials, open sample projects, play with the code, and
try to understand it. You won’t understand every line, but I have found
it takes two days to begin to learn a new programming language. At this
point, start coding!
3—Make Decisions
What is your game about? Try to sketch it on paper and divide it into
chunks. I like to use wireframe templates. Start simple, create a menu
scene and a gameplay scene, and use the storyboard functions of Corona.
4—Think Simple
You’ll add a new scene when you need it. Don’t try to plan everything,
because you don’t really know how your game will look before the first
prototype—and even then you won’t be sure!
5—Limit Yourself
Decide how many weeks you’ll work on the game. The schedule will
decide the features, not the other way around! Check your progress
every week and make smart decisions.
7—Prototype
Aim to prototype the gameplay in a minimum amount of time; just a
few hours should be enough. If the prototype isn’t great, try to enhance
it. If you can’t, go to sleep and try again the next day.
9—Integrate
When you have something playable (and demonstrable to your
spouse . . .), it’s time to integrate real art, music, and sounds. But don’t
be naïve—your game will change, up until the final version you submit
to the App Store. Your inner artist needs to be aware of that.
10—Play!
Play your game at every stage. A lot.
11—Plan
Divide your process into 4 steps:
• Alpha (playable, with lot of bugs and missing features)
• Beta (few bugs, feature complete)
• Final Beta (only your spouse can ask for some changes . . .)
• Release Candidate (this is the one!)
13—Take a Break
You have to stop coding at some point and decide on the release
candidate.
That’s it!
Thanks for reading this book. I hope you found some help and sup-
port for your game project. Do not forget to visit my book companion
web site: www.create2Dmobilegames.com.
This page intentionally left blank
Index
188 Index
advanced features 113–48; add sounds debug 163–7; Android device 166; iOS
and music 121–4; menu and user device 166; step by step 164; see also
interface 125–33; save and restore test and debug
data 143–7; screen jungles 135–42 deploy 169–75; Android deployment
advertisement banners 154–5 specifics 171; build for Android
anchor points 48, 51 173–4; build for iOS 171–3; devel-
Apple Retina 127 oper accounts 170; iOS deployment
Apple simulator 173 specifics 170; to the stores 174–5
arrays 30–1; browse an array 30–1; developer accounts 170
create an array 30; see also lists display 43–64; fonts 48; images 53–6;
introduction 43–5; multiline text
Boolean values 12, 14 49–51; position 48; properties 45;
Box2D engine 89 shapes 57–64; texts 48–51
“break” statement 26 Documents Directory 147
bugs: pro advice to isolate bugs 161;
programming 158; pro tips to avoid easing method 71
bugs 159–61; syntax 158; see also economics 149–54; charging for your
debug; test and debug game 150; include advertisement
banners 154–5; include paid content
Chicken Deep 127, 184 150–4; make money with your
collision detection 92–4, 103 games 150
combining shapes with text 60–4; energy 15, 18, 20
squared title 63–4; title with a EnterFrame event 84–4, 85
background 60–2; underlined event listener 76–85; tap event 76;
title 63 touch event 76–7; touch event to
comments 4–5, 10, 158, 159 drag an object on the screen 78–9
Composer 114–19; change the current expressions 13–15
scene 117–18; create and open a
scene 115–16 Facebook 179–80
config.lua file 55, 82, 128, 136, 137, “fly” 107, 109
140, 141 fonts 48, 50, 62, 63; custom 51
content area 55, 136, 137, 140, 141 “for” 25, 28, 30
control structure statements: break frame 82–5; EnterFrame event 82–3;
statements 26; conditional state- moving a ball every frame 83–4;
ments 24–5; loop statements 25–6; warning 85–6
variable scope 26–7 functions: example 18; getting parame-
coordinate 44 ters and returning a value 19–20; in
Corona Cards 181 a table 20; as a task 18–19
Corona Debugger 164
Corona Editor 10, 11, 164 Google 19, 170, 184; free tools 166;
Corona Enterprise 96, 181 Play 151, 152, 153, 170, 174, 175;
Corona Simulator 9, 79, 136, 137, 158, stores 155
164–5, 172, 173; TestFunctions 20 Graphics 2.0 181
Index 189