Skip to content

Instantly share code, notes, and snippets.

@shakesoda
Last active August 29, 2015 14:24
Show Gist options
  • Save shakesoda/963c88d4fda251b75322 to your computer and use it in GitHub Desktop.
Save shakesoda/963c88d4fda251b75322 to your computer and use it in GitHub Desktop.

Creating a new Screen

Defining metrics

Screens need to be defined in a theme's metrics file to be available. At a minimum you must define a screen's name, class, next and previous screen. Different screen classes need different things to work, here is a basic ScreenAttract:

; Screen name
[ScreenExample]
; The screen Class used by the Engine, which defines the basic behavior of it.
Class="ScreenAttract"
; Fallback from which the game should fill in missing rules
Fallback="ScreenAttract"

; When the user goes back, go here
PrevScreen="ScreenTitleMenu"
; When the screen cycles to next, go here
NextScreen="ScreenTitleMenu"
; When the user presses Start, go here
StartScreen="ScreenTitleMenu"

; Force a silent 5 second timer
ForceTimer=true
TimerSeconds=5
TimerMetricsGroup="MenuTimerNoSound"
TimerOnCommand=visible,false

; Do not play music
PlayMusic=false

Many more options are available, and you can follow the Fallback rules to see what all is defined in fallback and default to find most of them.

Note that metrics can also be requested by Lua scripts, so not everything you encounter is part of the engine.

BGAnimation layers and where to put the files

Every theme has a BGAnimation folder which provides all the scripted visuals. There are various layers available for different purposes, most commonly you will use background and decorations.

The following layers are children of the Screen and are different only in drawing order:

  • background - the bottom most layer
  • underlay - above background, but below decorations
  • overlay - the top layer, below only overlay screens.

As they are children of the screen, input will be locked until the initial commands are finished.

The decorations layer is special in that it is not a direct child of the screen. Due to this, the screen will not lock input from its animations not does it receive screen messages (e.g. Code messages).

The following are used during transitions:

  • in - When a screen first loads
  • out - Before a screen exits to the next screen
  • cancel - When the user presses back.

For example, the background for ScreenTitleMenu would be ScreenTitleMenu background and could either be a folder or a Lua file. If you use a folder, you should place the code in a file called default.lua i.e. ScreenTitleMenu background/default.lua. Different BGAnimation layers do not all need to be the same type of file, it is perfectly fine to mix folders and Lua files. If you would like to refer to an existing BGAnimation, you can use a .redir file.

When loading files from Lua script, they will always be loaded from the folder which contains the script. You may access files from Graphics, Sounds or any other theme-level folder using THEME:GetPathG, THEME:GetPathS, etc.

For example, LoadActor(THEME:GetPathG("", "platinum")) would look for a file named platinum in Graphics/, which can be a Sprite, Lua file or any other file type SM understands.

Writing the code

Method 1: Lua style

This is the "right" way to do it, which most anyone who can read Lua should understand with little explanation.

local t = Def.ActorFrame {}

local a = LoadFont("Common", "Normal")
a.Text = "Hello, World!"
function a:InitCommand()
    self:spin()
    self:xy(50, 50)
end
table.insert(t, f)

return t

Method 2: Shorthand

This method is a bit more concise, but relies on table concat (..) and the fact that versions of the game return self from every actor command.

local t = Def.ActorFrame {}

t[#t+1] = LoadFont("Common", "Normal") .. {
    Text = "Foo",
    InitCommand = function(self)
        self:spin()
            :xy(50, 50)
    end
}
t[#t+1] = LoadFont("Common", "Normal") .. {
    Text = "Bar",
    InitCommand = function(self)
        self:spin()
    end
}

return t

Method 3: Legacy style

This should only be used when converting old code, as it relies on the "cmd" macro which expands things into functions automatically. This is baffling to most Lua programmers, which is why its use is discouraged.

return Def.ActorFrame {
    LoadActor("Foo") .. {
        InitCommand = cmd(spin;xy,SCREEN_CENTER_X,SCREEN_CENTER_Y)
    },
    LoadFont("Common", "Normal") .. {
        Text = "Hello, World!",
        InitCommand = cmd(rainbow;xy,SCREEN_CENTER_X,SCREEN_CENTER_Y-150)
    }
}

Scripts can be written any way you want as long as they are valid Lua (read the manual!) and an Actor or ActorFrame is returned.

Lua.xml is a more-or-less complete function reference which can be found at Docs/Luadoc/Lua.xml in the game data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment