How To Make a Simple Game with Moai
This is a tutorial for beginner Moak SDK developers, you’ll learn how to create a new animal-feeding game for iOS from scratch. With Moai, you don’t need to fear being locked in to one platform — you can let everyone enjoy the fruits of your labors! By .
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How To Make a Simple Game with Moai
55 mins
- What is Moai?
- Getting Started
- Ready Player One — Getting Your Project Ready
- What’s Invisible and Smells Like Carrots? — Adding Sprites to the Game
- Fast Food — Setting Object Position and Movement
- Cats and Dogs and Bunnies, Oh My! — Adding Characters to the Game
- Feeding the Hordes — Adding Interaction to the Game
- Picky Eaters — Adding Drag and Drop Logic to the Game
- Meow, Bark, Squeak — Adding Sound to your Game
- You’ve Been Fed, Now Shoo! – Removing Sprites
- Won’t These Animals Ever Stop Eating? — Displaying the Score On-Screen
- Taking this Dog and Pony Show On the Road — The Mobile Version
- Where to Go From Here?
Ready Player One — Getting Your Project Ready
For the game you’re making in this tutorial, I’ve created a starter project for you. It doesn’t contain any code yet, but it contains all of the files and sounds you’ll need for the game, as well as a nice directory structure.
So Download the starter project and unpack it. Inside you’ll find a project folder named AnimalFeeding. As well, you’ll find a set of image and audio assets along with the main.lua file, which will contain the main game code. The structure is shown below:
Fire up your text editor of choice and open up main.lua.
Whoa — it’s empty! That will get you nowhere fast! First, you’ll need to display a window on the screen. Every visual application needs a window (or a view in iOS) to display your work.
Paste the following code into the main.lua:
----------------------------------------------------------------
-- screen (window) initialization
----------------------------------------------------------------
-- 1.
local STAGE_WIDTH = 960
local STAGE_HEIGHT = 640
local SCREEN_WIDTH = 960
local SCREEN_HEIGHT = 640
print ( "System: ", MOAIEnvironment.osBrand )
print ( "Resolution: " .. SCREEN_WIDTH .. "x" .. SCREEN_HEIGHT )
-- 2.
MOAISim.openWindow ( "Animal Feeding", SCREEN_WIDTH, SCREEN_HEIGHT ) -- window/device size
-- 3.
local viewport = MOAIViewport.new ()
viewport:setSize ( SCREEN_WIDTH, SCREEN_HEIGHT ) -- window/device size
viewport:setScale ( STAGE_WIDTH, STAGE_HEIGHT ) -- size of the "app"
-- 4.
local layer = MOAILayer2D.new ()
layer:setViewport ( viewport )
layer:setClearColor (0.53, 0.53, 0.53, 1)
-- 5.
local partition = MOAIPartition.new ()
layer:setPartition ( partition )
-- 6.
MOAIRenderMgr.setRenderTable ( { layer } )
Here’s a quick rundown of the code above, comment by comment:
- Set some local constants (stage and screen width and height) and print them out to the console. If you’re new to Lua, keep in mind that the local keyword gives the variable limited rather than global scope. In this app the scope doesn’t really matter, but it’s a good practice to limit the number of global variables floating around.
- Open the window, name it “Animal Feeding” and set width and height to the previously defined 960 and 640.
- Create the viewport, which is what allows you to “look” at the scene. The viewport size refers to the actual display size, while the scale defines the coordinates. In this case, the size and scale are the same. If you have a Retina display, you might set the size to 960×640 but the scale to 480×320.
- Create a layer, which is sort of like the “root” view or window. A layer needs to be viewed through a viewport, so the viewport from step #3 is linked to the layer. The “clear color” is the background color of the layer, which is set to a nice grey (RGB 0.53, 0.53, 0.53)
- A partition is used to catch user interactions, such as clicks and touch events. This will come in use later when you add the interactive bits.
- Finally, the Moai Render Manager is set up to handle rendering on the newly created layer.
To run the code, open up a Terminal window and navigate to the folder containing main.lua.
Build and run your code with this command:
$ moai main.lua
You’ll see the following stunning window:
Success! A nice blank grey window. You should also notice the output of the two print statements in the terminal:
System: OSX Resolution: 960x640
Now that the window is set up, it’s time to add something more interesting to it.
What’s Invisible and Smells Like Carrots? — Adding Sprites to the Game
You’ll need to add a few things to liven up this game. Start by adding some sprites.
Add this code to the bottom of main.lua:
local quad = MOAIGfxQuad2D.new ()
quad:setTexture ( "gfx/carrot.png" )
quad:setRect ( -84/2, -98/2, 84/2, 98/2 )
local prop = MOAIProp2D.new()
prop:setDeck ( quad )
layer:insertProp ( prop )
A “quad” is a rectangle — hence the name “quad” — that can hold a texture image. Think of it as an abstract object, much like a class definition.
A “prop” is what might be called a “sprite” in another framework. It is something that is displayed on-screen. If a quad is comparable to a class, then a prop is like a practical, usable instance of that class.
With this setup, you could load a texture into a quad, and then use it multiple times in many props. You can read more about the distinction between the two on the Moai wiki.
Run your project, and now you are rewarded with a mighty-looking carrot in the center of the screen!

Note that the default position of your graphics is smack dab in the center of the screen.
Coordinates in a typical Moai application are a bit different than what you’re used to in Cocos2D or Corona SDK applications. The (0, 0) point is at the center of the window! Positive X values are to the right side and negative to the left; positive Y values are up and negative on the bottom, as shown in the image below:
You’re likely thinking “That’s a heck of a lot of code to display a single sprite! Do I really need to type all that code for every graphic on my screen?”
It probably makes sense to set up a reusable function that will do all the graphics housekeeping for your game. The average game will probably have many sprites, so you’ll want to make creating a sprite nice and easy to save you coding time.
Replace the last bit of code you pasted in (from “local quad = “MOAIGfxQuad2D.new ()” down to “layer:insertProp ( prop )”) with the following:
----------------------------------------------------------------
-- Textures and sprites creation
----------------------------------------------------------------
local textureCache = {}
local function textureFromCache ( name, width, height )
if textureCache [ name ] == nil then
textureCache[name] = MOAIGfxQuad2D.new ()
textureCache[name]:setTexture ( name )
textureCache[name]:setRect ( -width/2, -height/2, width/2, height/2 )
end
return textureCache [ name ]
end
local function newSprite ( filename, width, height )
if width == nil or height == nil then
-- read width/height from the image
local img = MOAIImage.new ()
img:load ( filename )
width, height = img:getSize ()
img = nil
end
local gfxQuad = textureFromCache ( filename, width, height )
local prop = MOAIProp2D.new ()
prop:setDeck ( gfxQuad )
prop.filename = filename
return prop
end
In the code above, newSprite() takes a filename as an argument with optional width and height of the image. If the width and height aren’t passed in as arguments, the function will figure out the image dimensions once it’s been loaded.
The textureCache object is used by newSprite() to represent the graphics object to display on-screen. As well, setDeck is a Lua hashtable, comparable to an NSDictionary that will hold each texture as it’s loaded. Since textures will be reused a lot, this will help speed things up.
Finally, newSprite sets the filename property of the object and returns the newly created sprite to the caller for later reference.
Now you’re able create a sprite with a single line of code! However, you’ll still need three lines total to add and position the sprite on the layer.
Paste in these lines at the bottom of main.lua:
local sp1 = newSprite ( "gfx/carrot.png", 84, 98 ) -- here we supply width and height
sp1:setLoc( -100, -230 ) -- set location - we move the sprite to the left and down
layer:insertProp ( sp1 )
local sp2 = newSprite ( "gfx/bone.png" ) -- no width and height supplied, it will be read from the file size
sp2:setLoc ( 100, -230 ) -- move to the right and down
layer:insertProp ( sp2 )
Run your app, and now your screen should look like the image below:
You could of course have a super-function that (in addition to loading the image) also sets the position and adds it to a layer. However, in this tutorial, you’ll keep things simple and depend on newSprite() to only load the image and handle the caching.
Now that you have an easy way to throw images up on the screen, it’s time to get those images moving around!
First, remove those six lines that you just pasted in main.lua; you’ll be adding a more generic spawnFoodObject() method in the next section that will make your life a little easier.