Overview
This is an overview of the template project located in the folder: ~/template/
Once you understand how the template works you should be ready to examine any of the five game starters.
Project Structure
These are the files and folders in this project and what they do:
~\template\
- Home folder for 'template' projectbuild.settings
- A generic build settings file for this project.config.lua
- A generic config file for the project using 640x960 letterbox scaling.main.lua
- The game's launch file. This is where the game starts.images\
- This folder contains images files (.jpg and .png).Prime.ttf
- A font file used in all examples.sskj.bat
- You can safely ignore this file. I use it during testing to soft-link to my local copy of ssk.ssk2\
- Super Starter Kit 2. If you have not yet copied this folder here yet, please see Quick Start.scripts\
- This folder contains most scripts used in the project.common.lua.lua
- This module contains all of the common/shared settings for the game. +Tip: All other files in the projectrequire()
this module. So, any changes made to it can be seen by all code. i.e. You can use it as a scratch pad if need to.game.lua
- This module contains all of the game logic to run the example.myCC.lua
- A module that creates and configures a collision calculator (external link).factories\
- This folder contains all factory definitions and the factory manager.coin.lua
- Coin pickup factory.coinHUD.lua
- Coin counter interface factory.distanceHUD.lua
- Distance counter interface factory.factoryMgr.lua
- The factory manager module. (See The Factory Concept below.)player.lua
- Player factory. (Note: All game starters customize this factory.)scoreHUD.lua
- Score counter interface factory.segment.lua
- Hallway Segment factory. (See The Hallway below.)
This factory creates hallway segments/triggers whose job it is to create/load new content as the player moves right and triggers a segment sensor.
sounds\
- A folder where sound effect and music files are stored.music\
- Music files.sfx\
- Sound-effect files.
The Factory Concept
This template and all of the starter games use factories to create game objects. In this sense, a factory is a module whose main job is to create a single game object or set of co-related objects. Ex:
- A (pickup) coin.
- A score counter interface.
- A player.
Note: These factories do not strictly conform to the factory design pattern you may be familiar with in OOP languages and other sources. I am using this terms because the factory modules adhere to the broad principle of the pattern: Creating Objects.
Typical Factory Structure
The file containing a factory definition usually has the following structure:
- Header - Copyright info and name of factory.
require()
Statements - modules and libraries used by the factory are required here.- Localizations - In this section, I localize a number of commonly used ssk features.
- Tip: I may not end up using all of these features in the module, but the cost of localization is low and having a standard set of localized features makes for easier coding and duplication later.
- Locals - Next I declare any file-level locals that may be used by the module.
- Ex:
initialized
- Most modules have a flag used to determine if the module has been initialized yet. This is a safety mechanism I use to avoid accidental double initializations.
- Ex:
- Forward Declarations - This is where I declare any functions that may be used by the module, but which I don't expose as public members of the module. +Tip: I rarely use this, but keep a spot for it nonetheless. Again this is about keeping a known structure and enabling easy duplication.
- Factory Module Begins - The module function definitions start here.
- factory.init( params ) - A method do one-time initialization of the factory needs it. Typical things that would be done here are, pre-loading images, defining sprite-sheets, etc.
params
- Optional table of parameters.
- factory.reset( params ) - This function is typically called at the begining of a game (not between levels) to reset the factory module if it is needed.
params
- Optional table of parameters.- Tip: While most factories do not use this,
segment.lua
does.
- factory.new( group, x, y, params ) - This is function responsible for building this factories game object(s).
group
- Display group to insert objects into.x
,y
- x- and y- position to place 'object' at.params
- An optional table of parameters. This is where we pass special data and arguments a factory may need.- Tip: - You don't need to use the values of these arguments in every builder, but by having a minimialistic and yet common
new()
signature we make factories easy to use, easy to write, and easy to understand.
- factory.init( params ) - A method do one-time initialization of the factory needs it. Typical things that would be done here are, pre-loading images, defining sprite-sheets, etc.
return factory
- The last line of every factory module, where we return the factory module reference.
Factories Are Extensible
The above factory definition is pretty basic, but due to the fact that factories are modules, it is easy to extend this concept.
For example, if you include a built-in-editor in your game, it may be useful to add these functions to your factories:
editor_widget()
- A function to create a drag-n-drop widget representing this object type for the ditor.editor_new()
- A function to create the editor instance of this object....
- Whatever else you need.
Example Factory - coin.lua
-- =============================================================
-- Copyright Roaming Gamer, LLC. 2008-2016 (All Rights Reserved)
-- =============================================================
-- Pickup: Coin Factory
-- =============================================================
local common = require "scripts.common"
local myCC = require "scripts.myCC"
local physics = require "physics"
-- =============================================================
-- Localizations
-- =============================================================
-- Commonly used Lua Functions
local getTimer = system.getTimer
local mRand = math.random
local mAbs = math.abs
--
-- Common SSK Display Object Builders
local newCircle = ssk.display.newCircle;local newRect = ssk.display.newRect
local newImageRect = ssk.display.newImageRect;local newSprite = ssk.display.newSprite
local quickLayers = ssk.display.quickLayers
--
-- Common SSK Helper Modules
local easyIFC = ssk.easyIFC;local persist = ssk.persist
--
-- Common SSK Helper Functions
local isValid = display.isValid;local isInBounds = ssk.easyIFC.isInBounds
local normRot = ssk.misc.normRot;local easyAlert = ssk.misc.easyAlert
-- =============================================================
-- Locals
-- =============================================================
local initialized = false
-- =============================================================
-- Forward Declarations
-- =============================================================
-- =============================================================
-- Factory Module Begins
-- =============================================================
local factory = {}
-- ==
-- init() - One-time initialization only.
-- ==
function factory.init( params )
if(initialized) then return end
initialized = true
end
-- ==
-- reset() - Reset any per-game logic/settings.
-- ==
function factory.reset( params )
end
-- ==
-- new() - Create new instance(s) of this factory's object(s).
-- ==
function factory.new( group, x, y, params )
params = params or { width = w/4, debugEn = false }
-- Catch case where we enter, but group was just removed
--
if( not isValid( group ) ) then return end
--
-- Ensure there is a params value 'segmentWidth'
--
params.width = params.width or w/4
--
-- Create a coin
--
local coin = newImageRect( group, x, y, "images/coin.png",
{ size = params.size or 40 },
{ bodyType = "static", isSensor = true,
calculator = myCC, colliderName = "pickup"} )
return coin
end
return factory
Factory Manager
The Factory Manager is the single access point for all factories and is used as follows:
1. Register All Factories
First (usually in main.lua
) we register all factories with the manager like this:
local factoryMgr = require "scripts.factories.factoryMgr"
factoryMgr.register( "segment", "scripts.factories.segment" )
factoryMgr.register( "player", "scripts.factories.player" )
factoryMgr.register( "coin", "scripts.factories.coin" )
factoryMgr.register( "scoreHUD", "scripts.factories.scoreHUD" )
factoryMgr.register( "coinsHUD", "scripts.factories.coinsHUD" )
factoryMgr.register( "distanceHUD", "scripts.factories.distanceHUD" )
2. Initialize Factories
Later (usually in game.lua
) we initialize the factories:
-- Initialize 'segment' factory using special options
factoryMgr.init( "segment", { ceilingPosition = top + 40, floorPosition = bottom - 40 } )
-- Initialize remainder of factories using their default settings.
factoryMgr.init()
3. Call Factory new()
Next (usually in game.lua and other game logic modules) we create game objects using factoryMgr.new()
--
-- Create HUDs
--
factoryMgr.new( "scoreHUD", layers.interfaces, centerX, top + 70 )
factoryMgr.new( "coinsHUD", layers.interfaces, left + 10, top + 70,
{ iconSize = 40, fontSize = 36} )
factoryMgr.new( "distanceHUD", layers.interfaces, right - 10, top + 70, { fontSize = 36 } )
4. Reset Factories
Finally, when we die or reset the game, we typically reset the factories too.
factoryMgr.reset( )
The Hallway
As you will recall from the front page of these docs, the template and all of the starter games in this pack are in a 'world' where the action moves from left-to-right.
The player moves to the right and the world scrolls to the left. While this occors, the player stays in the center of the screen (horizontally) and may move up and down. Finally, as the world scrolls to the left, it brings in new content.
You can think of the world as a big un-ending hallway.
This hallway is made up segments where each segment contains a collide-able trigger object.
When the player moves-right and the world moves left, it (the player) collides with a hallway segment/trigger. This causes a listener to execute. That listener creates the next segment in the hallway including a new trigger. It also dispatches an event onNewSegment
.
onNewSegment
Event
The game logic listens for the event onNewSegment
and creates new content at the position of the just created segment. That new content can be randomly generated, loaded from pre-defined level files, or some combination of both.
Note: All of the game starters in this pack use random generation.
.. and that is pretty much all there is to it. Once you get your head around how this works it is really easy to start making this style of game.
Have Fun!
Template Walkthrough
I will briefly walk through how the template project executes. You should open the script files and follow along to get the most from this part of the docs.
Startup
Please open: build.settings
, config.lua
, main.lua
, then start reading ...
- build.settings and config.lua processed - Corona processes these two files and sets up the environement.
- main.lua - Corona now runs the contents of main.lua
require()
and initialize SSK2require('scripts.common')
- Loads common.lua module into memory.require(...)
- Loads a number of other modules into memory.- Configure and Load Sounds using the SSK2 Sound Manager
- Register all factories using the Factory Manager
- Initialize Game Module.
- Start Game.
- Tip: In the 'Framed' versions of the game starters, we would use composer to load the splash screen here instead. In the framed versions, the game is not started until the game scene loads.
Game Start
Now open: ~/scripts/game.lua
and continue reading...
Once game.start()
is called, things start rolling (locate game.start()
function in game.lua
to follow along).
- Destroy Then Build - The start function calls
destroy()
first. The very first time we start the game, this doesn't do much. The primary reason we do this is to clean up on 2nd, 3rd, ... runs after the player 'dies' and starts over. - Mark game as 'running' - Many parts of the game check the
common.gameIsRunning
flag before doing any work. So, we set it totrue
right away. - Initialize Physics.
- Create a group hierchy using the SSK2 Quick Layers feature. The usual hierarchy looks like this (bottom-to-top)
group
layers
- Group that holds all layers and gives easy access to them.underlay
world
content
player
interfaces
- Create a background image. We're making visually simple games. So we have a visually simple background.
- Create an input handler using the SSK2 Easy Inputs - One Touch Factory.
- One line of code and you've got a whole input handler set up. Booya, SSK2!
- Define a onNewSegment event listener. This piece of code builds our game content as we move to the right.
- The template version is pretty boring. It just drops coins in the hallway. Check out the game starters to see more interesting listeners.
- Define a
onDied
listener. When the player dies, it dispatches this event. We use it to stop the game and clean up.- You can add more code to this in your own games, but I've tried to keep it simple for the purpose of getting you started.
9 Define a
finalize
listener on the layers object. I did this to clean up theonNewSegment
andonDied
listeners. This function is called when thelayers
display group is destroyed. - Tip: Uses SSK2 Runtime improvement
ignoreList()
to do this cleaning.
- You can add more code to this in your own games, but I've tried to keep it simple for the purpose of getting you started.
9 Define a
- Creates a number of beginning segments in our hallway.
- Creates the player.
As soon as the player is created it starts moving and after that everything happens as the results of touch inputs and events. Sweet!
More?
Yes. There is more to it than that, but I'm going to let you dig into each of the script files and modules.
Take it slow and easy.
Make small changes and re-run the template.
You will understand it soon enough.
~ The Roaming Gamer
Copyright © Roaming Gamer, LLC. 2008-2016; All Rights Reserved