Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Dodge ’Em Up

In this chapter we’ll make a very simple game where you move a square around the screen and dodge circles that fly at you. We’ll cover all of the basics of making a game with Usagi and then package up our game to share it with others.

Now that you’ve got Usagi is installed, you’ll have the usagi command available. Go ahead and open your text editor. Many code editors include a way to open a terminal/shell within it. If you’re using a text editor that doesn’t, then launch your terminal or Command Prompt or PowerShell separately. Run usagi init hello_usagi. This will create a folder called hello_usagi with a bunch of different files in them. The most important one is main.lua, which is the primary entrypoint for your game. It’s where you’ll start out coding.

meta/usagi.lua is a file that helps your text editor know what functions and variables are available from Usagi. You don’t edit this file, it’s read-only and to help improve your experience writing code.

In your terminal, run usagi dev hello_usagi. You’ll see a window pop up that draws some text on the screen.

(TODO: show screenshot)

Then in your text editor, open main.lua. You’ll see this:

function _config()
  return { name = "Game", game_id = "com.usagiengine.YOURGAMENAME" }
end

function _init()
  -- Live reload preserves globals across saved edits but resets locals.
  -- Stash mutable game state in a capitalized global like `State` so it
  -- survives reloads; F5 calls _init again to reset.
  State = {}
end

function _update(dt)
end

function _draw(dt)
  gfx.clear(gfx.COLOR_BLACK)
  gfx.text("Hello, Usagi!", 10, 10, gfx.COLOR_WHITE)
end

If this is your first time seeing code, congratulations! This is Lua. functions are reusable pieces of code that can be called to make whatever code is contained within the function and end run. We’ll dive more into functions soon. But let’s walk through the code a bit more first.

_config() is a place where you can set your game’s name and game_id. The game_id is used for putting your game’s save data in the proper location on your players’ computers. Don’t worry about this too much yet.

_init() is a function that gets run when your game starts (and when you press F5 or Ctrl+R). It’s a good place to set up data once.

Then _update(dt) and _draw(dt) are sort of siblings. They get called 60 times per second, over and over again, automatically by Usagi. This is called the game loop. Games run rapidly so that movement is smooth and the game can react quickly to player input. Each iteration through the loop is called a frame, similar to how each image in a movie is a frame. Movies are often 24 frames per second (FPS), whereas games are often 60 FPS. The _update function is where you check for player input, have entities in your game react to what’s happening, and simulate the game. There’s nothing there yet, but there will be soon. The _draw function is where you can show text, draw hapes, or put your game’s art on the screen.

dt is short for delta-time and it’s passed into _update and _draw automatically by the game engine. We’ll cover it more in depth in a future chapter. For now, it’s unused and not something to worry about.

gfx.clear(gfx.COLOR_BLACK) clears the screen so that all that’s shown is a black rectangle. Each frame we clears the screen so that what was drawn on the last frame doesn’t reappear. Try changing gfx.COLOR_BLACK to gfx.COLOR_RED. The background of your game instantly updates from black to red.

The next line gfx.text("Hello, Usagi!", 10, 10, gfx.COLOR_WHITE) is what draws the message on the screen.

_update and _draw are functions we define ourselves, which Usagi looks for and calls. gfx.clear and gfx.text are functions that Usagi provides, which we call. Calling a function makes that code run. so gfx.text draws text to the screen. It knows which text to draw, where to place it, and what color to make it by passing in arguments. Arguments are comma-separated values that correspond to the parameter list of the function. gfx.text expects the text message to show, the x coordinate, the y coordinate, and the color of the text as its arguments.

Try changing a few aspects of gfx.text and see what happens. Update the message, change the 10s, and use a different color.

Next, copy that line of code and paste it below. Draw a different message to the screen in a different position. And don’t forget to save your main.lua file.

You’re coding! And Usagi is live updating, giving you instant feedback to your changes.

Normally, in most game engines, you’d need to change your code, save it, and run a command to start the game again. With Usagi, you just change it and save it and see your changes.

(TODO: explain the coordinate system + image)

The x and y parameters of the gfx.text function are the pixel coordinates on our screen of where to place the upper-left corner of the text. The upper-left corner of our game is the 0 x position and the 0 y position. If you increase the x value, the text will move to the right. If you increase the y value, it will move down.

By default, Usagi games are 320 pixels wide and 180 pixels tall. If you set the x position of your text to 400, it won’t be visible in your game.

Greeting

Let’s write our own function. It’s a great way to learn how functions work. Rather than just greeting Usagi, let’s make it easy to say hello to any given name.

At the bottom of main.lua, add the following code:

function greet(name)
  return "Hello, " .. name .. "!"
end

Then, in _draw:

gfx.text(greet("Alucard"), 10, 10, gfx.COLOR_WHITE)

Try changing the name. What our updated gfx.text is doing is calling our new greet function. We pass in the name we want to greet, wrapped quotations (note: these are not curly quotes, those are for writing, not coding). When you wrap characters in quotations, this is called a string and it is not evaluated as code. It’s instead data that we can use in our code. The return keyword in our function is what our function spits back to wherever calls it. In our case, it passes the returned value into gfx.text. It draws "Hello, Alucard!" on the screen. The .. (two periods) is Lua’s syntax for how to combine strings. It squishes together "Hello, ", our name we pass in, and "!" into a new string.

Add some other greetings to try our your new function.

While we’re not going to use this in our game yet, functions can take numbers and return them as well. Here’s a simple function for adding two numbers:

function add(a, b)
  return a + b
end

Moving a Square

(TODO: drawing shapes) (TODO: player input) (TODO: State)

Spawning Circles

Hit Detection

Game Over

Sharing Our Game

(TODO: usagi export)