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:

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:

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:

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:

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

  1. build.settings and config.lua processed - Corona processes these two files and sets up the environement.
  2. main.lua - Corona now runs the contents of main.lua
    • require() and initialize SSK2
    • require('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
  3. Initialize Game Module.
  4. 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).

  1. 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.
  2. Mark game as 'running' - Many parts of the game check the common.gameIsRunning flag before doing any work. So, we set it to true right away.
  3. Initialize Physics.
  4. 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
  5. Create a background image. We're making visually simple games. So we have a visually simple background.
  6. 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!
  7. 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.
  8. 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 the onNewSegment and onDied listeners. This function is called when the layers display group is destroyed.
    • Tip: Uses SSK2 Runtime improvement ignoreList() to do this cleaning.
  9. Creates a number of beginning segments in our hallway.
  10. 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

RoamingGamer Copyright © Roaming Gamer, LLC. 2008-2016; All Rights Reserved