Zero Overhead Game Development

Overview

The aim of this package is to remove accidental complexity from the game development process. We therefore always choose simplicity and consistency over features. The users of this package will include young programmers learning their first language, maybe moving up from Scratch. While we aim to support reasonably sophisticated 2D games, our first priority will remain learners, and their teachers.

Examples

The best way to learn how to use this package is by looking at code. There are some simple examples in the example subdirectory. More comprehensive examples are listed in the GZExamples repository. The example source code can also be viewed as part of this documentation – see the menu on the left.

Running games

Games created using GameZero are .jl files that live in any directory. To play the games, start the Julia REPL and:

pkg> add GameZero

pkg> add Colors

julia> using GameZero

julia> rungame("C:\\path\\to\\game\\Spaceship\\Spaceship.jl")

Assets

Each game, and its assets, are stored in a separate directory. Within this directory, there is a .jl file, which stores the game code. As well as this, there are three subfolders for sounds, images, and music. The games are executed using the rungame function provided by the Game Zero package, meaning that games do not have to be Julia packages or modules, making it much simpler. An empty file also counts as a valid game.

Initialising a screen

To initalise a screen, all that is needed to define a set of three global variables:

HEIGHT
WIDTH
BACKGROUND

All of these are optional, and if not specified, will default to 400x400, and a white background. HEIGHT and WIDTH should be integers, and BACKGROUND should be set to a Colorant object from Colors

Actors

Game objects on-screen are represented as Actors which have several associated attributes. Using Actors, you can change position, change the image and check for collisions. However, not all moving parts need to be Actors as those without a specific image can be defined as a Circle or a Rect, which have the same associated attributes (apart from image). Actors are usually the primary game objects that you move around.

a = Actor(image.png, xpos, ypos)

Rects, circles, and lines

GameZero.jl also includes basic geometric shapes. Rects, Circles and Lines can be used to do everything an Actor can, having the same attributes (apart from image).

r = Rect(xpos, ypos, width, height)
c = Circle(xpos, ypos, radius)
l = Line(xpos1, ypos1, xpos2, ypos2)

Drawing in-game objects

To draw an in-game object, the draw function is used, which takes the object (Actor, Line, Rect or Circle) and renders it on-screen at its current position. If taking a shape (i.e. not an Actor), the draw function can also take a colorant object from Colors.jl. This is done inside the draw game loop function (see Draw and update methods).

Moving objects

All objects have many attributes to define position. The corners — topleft, topright, bottomleft, and bottomright — are tuples (x and y coordinates). The sides — top, bottom, left and right — read either the x or y coordinate (top and bottom are x, left and right are y). These position attributes can be used either to read position or to set position. In addition, objects also have an x and y attribute which are anchored to the top left of the objects. Finally, the position attribute is a synomym for topleft

Draw and update methods

You write a game by defining your own draw and update methods. These functions are run by the game engine automatically every frame, meaning developers do not have to define their own event loop. The update function is used to change game state and attributes of the Actors and the draw function renders on-screen objects.

The draw method can be defined to take zero or one argument. If present, the single argument is the Game object. In other words, define one of

function draw() .... end

or

function draw(g::Game) .... end

The update method can be defined to take zero, one or two arguments. The first argument is the Game object, and the second argument is the the time step from the previous frame.

function update() .... end

function update(g::Game) .... end

function update(g::Game, dt) .... end

Keyboard inputs

To take an instantaneous input, define the on_key_down() in your game. This function can take upto three postional arguments: The Game object, the key and the keymod. You can define the function with zero, one, two or three arguments, depending on which values you need. However, since the arguments are positional, the order matters.

In other words, you can define one of:

function on_key_down() .... end

function on_key_down(g) .... end

function on_key_down(g, key) .... end

function on_key_down(g, key, keymod) .... end

For a constant input, such as for movement, you can check for keypress within the update function, via the keyboard attribute of the game object (g.keyboard).

Mouse input

Mouse movement can be tracked defining the on_mouse_move function in your game. The inputs to the function should be the Game object, and the mouse position as a tuple of numbers. For mouse clicks, use the on_mouse_down function, which takes as input the Game object, position, and the button.

function on_mouse_move(g::Game, pos) .... end

function on_mouse_down(g::Game, pos, button) .... end

Playing sounds

To play sound effects, you can call the play_sound function. To play music on a loop, call the play_music function. Both these functions can take .wav, .mp3 and .ogg files.

Timers

To set a timer in a normal program, sleep would be used. However, in this instance, this would cause the whole game to pause for that amount of time. Therefore, to avoid having to use a complicated @async loop, you can use the function schedule_once, which takes a function and a time in seconds, and sets the function to run after that amount of time.

Animation

To animate an actor, the image is changed several times as seen in the loop below. Better animation is most likely coming very soon.

function shoot_animation()
    global shoot_frame
    if shoot_frame < 16
        space_pod.image = "space_pod_shoot" * string(shoot_frame) * ".png"
        shoot_frame += 1
        schedule_once(shoot_animation, 1/16)
    else
        space_pod.image = "space_pod.png"
    end
end