In this three-part series, I will be showing you how to create a game inspired by the popular seventies game, Space Invaders. Along the way, you'll learn about Corona's scene management functionality, timers, moving a character, the built-in physics engine, and how to use modules to emulate classes in the Lua programming language.
1. New Project
Open the Corona Simulator, click New Project, and configure the project as shown below. Select a location to save your project and click OK. This will create a folder with a number of icons and three files that are important to us,main.lua, config.lua, and build.settings. We'll take a look at each file in the next few steps.
2. Build Settings
The build.settings file is responsible for the build time properties of the project. Open this file, remove its contents, and populate it with the following configuration.
01
02
03
04
05
06
07
08
09
10
11
settings =
{
orientation =
{
default="portrait",
supported =
{
"portrait"
},
},
}
In build.settings, we are setting the default orientation and restricting the application to only support a portrait orientation. You can learn which other settings you can include in build.settings by exploring the Corona documentation.
3. Application Configuration
The config.lua file handles the application's configuration. As we did with build.settings, open this file, remove its contents, and add the following configuration.
01
02
03
04
05
06
07
08
09
10
application =
{
content =
{
width = 768,
height = 1024,
scale = "letterbox",
fps = 30,
}
}
This sets the default width and height of the screen, uses letterbox to scale the images, and sets the frame rate to 30. Visit the Corona documentation to learn more about the other properties you can set inconfig.lua.
4. Entry Point
The main.lua file is the file that the application loads first and uses to bootstrap the application. We will be using main.lua to set a few default settings for the application and use the Composer library to load the first screen. If you're not familiar with Corona's Composer library, then I recommend giving the documentation a quick read. In short, Composer is the built-in solution to scene (screen) creation and management in Corona. The library provides developers with an easy way to create and transition between individual scenes. The newer Composer module replaces the older and now deprecated StoryBoard module. A migration guide is available to help convert your old projects over to use Composer.
5. Hide Status Bar
We don't want the status bar showing in our application. Add the following code snippet to main.lua to hide the status bar.
1
display.setStatusBar(display.HiddenStatusBar)
6. Set Default Anchor Points
To set the default anchor or registration points add the following code block to main.lua.
1
2
display.setDefault( "anchorX", 0.5)
display.setDefault( "anchorY", 0.5)
The anchorX and anchorY properties specify where you want the registration point of your display objects to be. Note that the value ranges from 0.0 to 1.0. For example, if you'd want the registration point to be the top left of the display object, then you'd set both properties to 0.0.
7. Seed Random Generator
Our game will be using Lua's math.random function to generate random numbers. To make sure that the numbers are truly random each time the application runs, you must provide a seed value. If you don't provide a seed value, the application will generate the same randomness every time. A good seed value is Lua's os.time function since it will be different each time the application is run. Add the following code snippet to main.lua.
1
math.randomseed( os.time() )
8. Avoiding Globals
When using Corona, and specifically the Lua programming language, one way to have access to variables application-wide is to use globalvariables.The way you declare a global variable is by leaving off the keyword local in front of the variable declaration. For example, the following code block declares two variables. The first one is a local variable that would only be available in the code block it is defined in. The second one is a global variable that is available anywhere in the application.
1
2
local iamalocalvariable = "local"
iamaglobalvariable = "global"
It is generally considered bad practice to use global variables. The most prevalent reason is to avoid naming conflicts, that is, having two variables with the same name. We can solve this problem by using modules. Create a new Lua file, name it gamedata.lua, and add the following code to it.
1
2
M = {}
returnM
We simply create a table and return it. To utilize this, we use Lua's require method. Add the following to main.lua.
1
local gameData = require( "gamedata")
We can then add keys to gameData, which will be the faux global variables. Take a look at the following example.
1
2
3
gameData.invaderNum = 1 -- Used to keep track of the Level we are on
gameData.maxLevels = 3 -- Max number of Levels the game will have
gameData.rowsOfInvaders = 4 -- How many rows of Invaders to create
Whenever we want to access these variables, all we have to do is use the require function to loadgamedata.lua. Every time you load a module using Lua's require function, it adds the moduleto a package.loaded table. If you load a module, the package.loaded table is checked first to see if the module is already loaded. If it is, then it uses the cached module instead of loading it again.
9. Require Composer
Before we can use the Composer module, we must first require it. Add the following to main.lua.
1
local composer = require( "composer")
10. Load the Start Scene
Add the following code snippet to main.lua. This will make the application go to the scene named start, which is also a Lua file, start.lua. You don't need to append the file extension when calling the gotoScene function.
1
composer.gotoScene( "start")
11. Start Scene
Create a new Lua file named start.lua in the project's main directory. This will be a composer file, which means we need to require the Composer module and create a composer scene. Add the following snippet to start.lua.
1
2
3
local composer = require( "composer")
local scene = composer.newScene()
returnscene
The call to newScene makes start.lua part of composer's scene hierarchy. This means that it becomes a screen within the game, which we can call composer methods on. From here on out, the code added to start.lua should be placed above the return statement.
11. Local Variables
The following are the local variables we will need for the start scene.
1
2
3
4
local startButton -- used to start the game
local pulsatingText = require("pulsatingtext") -- A module providing a pulsating text effect
local starFieldGenerator = require("starfieldgenerator") -- A module that generates the starFieldGenerator
local starGenerator -- An instance of the starFieldGenerator
It's important to understand that local variables in the main chunk only get called once, when the scene is loaded for the first time. When navigating through the composer scenes, for example, by invoking methods like gotoScence, the local variables will already be initialized. This is important to remember if you want the local variables to be reinitialized when navigating back to a particular scene. The easiest way to do this is to remove the scene from the composer hierarchy by calling the removeScence method. The next time you navigate to that scene, it will be automatically reloaded. That's the approach we'll be taking in this tutorial. ThepulsatingText and starFieldGenerator are two custom modules we will create to add class-like functionality to the project. Create two new files in your project folder named pulsatingtext.lua and starfieldgenerator.lua.
12. Storyboard Events
If you've taken the time to read the documentation on Composer, which I linked to earlier, you will have noticed the documentation includes a template that contains every possible composer event. The comments are very useful as they indicate which events to leverage for initializing assets, timers, etc. We are interested in the scene:create, scene:show, and scene:hide methods for this tutorial.
This method is called when the scene's view doesn't exist yet. This is where you should initialize the display objects and add them to the scene. The group variable is pointing to self.view, which is a GroupObject for the entire scene. We create the startButton by using the Display object's newImage method, which takes as its parameters the path to the image and the x and y values for the image's position on screen.
Step 2: scene:show
Composer's scene:show method has two phases. The will phase is called when the scene is still off-screen, but is about to come on-screen. The did phase is called when the scene is on-screen. This is where you want to add code to make the scene come alive, start timers, add event listeners, play audio, etc. In this tutorial we are only interested in the did phase. Add the following code snippet to start.lua.
01
02
03
04
05
06
07
08
09
10
functionscene:show( event )
local phase = event.phase
local previousScene = composer.getSceneName( "previous")
if(previousScene~=nil) then
composer.removeScene(previousScene)
end
if( phase == "did") then
startButton:addEventListener("tap",startGame)
end
end
We declare a local variable phase, which we use to check which phase the show method is in. Since we will be coming back to this scene later in the game, we check to see if there is a previous scene and, if so, remove it. We add a tap listener to the startButton that calls the startGame function.
Step 3: scene:hide
Composer's scene:hide method also has two phases. The will phase is called when the scene is on-screen, but is about to go off-screen. Here you will want to stop any timers, remove event listeners, stop audio, etc. The did phase is called once the scene has gone off-screen. In this tutorial, we are only interested in the will phase in which we remove the tap listener from the startButton.
1
2
3
4
5
6
functionscene:hide( event )
local phase = event.phase
if( phase == "will") then
startButton:removeEventListener("tap",startGame)
end
end
16. Start Game
The startGame function is called when the user taps the startButton. In this function, we invoke the gotoScene composer method, which will take us to the gamelevel scene.
1
2
3
functionstartGame()
composer.gotoScene("gamelevel")
end
17. Game Level Scene
Create a new file named gamelevel.lua and add the following code to it. This should look familiar. We are creating a new scene and returning it.
1
2
3
4
local composer = require("composer")
local scene = composer.newScene()
returnscene
18. Add Scene Listeners
We need to add scene listeners for the create, show, and hide methods. Add the following code to start.lua.
1
2
3
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
Advertisement
19. Test Progress
If you test the game now, you should see a black screen with a button you can tap. Tapping the button should take you to the gamelevel scene, which is now just a blank screen.
Conclusion
This brings this part of the series to a close. In the next part, we will start implementing the game's gameplay. Thanks for reading and see you in the second part of this series.
No comments:
Post a Comment