
This figure shows the architecture of an application created with Scrupp. The whole development happens on the right side using Lua.
At the beginning, Scrupp tries to run a Lua file which is chosen depending on the command line arguments.
$ scrupp
In this case Scrupp tries to open the file main.lua
in the directory where the Scrupp executable is located. This
directory will also be the working directory of the script.
However, it is not possible to give extra arguments to the Lua
file, yet.
$ scrupp -e <Lua file> arg1 arg2 ...
Scrupp adds the directory that contains the Lua file to the search path. Every attempt to open a file (images, sounds, music, fonts, other Lua files) will result in a search for it in this directory. In case the file is not found there it will be searched in the directory of the executable. After that the Lua file is executed. Now it is possible to give extra arguments to the Lua file.
$ scrupp <directory> arg1 arg2 ...
The directory is added to the search path and set as the
working directory. Every file access results in a search in
this directory at first. Only if it is not found there the
file will be searched in the directory of the executable.
Then Scrupp tries to execute main.lua which
should be located inside this directory. Now it is possible
to give extra arguments to the
Lua file.
$ scrupp <zip archive> arg1 arg2 ...
The archive is added to the search path. The directory
containing the archive becomes the working directory. Every
file access results in a search in this archive at first. The
directory of the executable is searched after that. Then Scrupp
tries to execute main.lua which should be located
inside this archive. It is possible to give extra
arguments to the Lua file.
Before running the Lua file, Scrupp collects all command line
arguments in the global table arg. The name of the
chosen Lua file, directory or archive becomes the element at index
0 in that table. Additional arguments are stored in index 1, 2 and
so on. Any arguments before this name (name of the executable, the
options) go to negative indices. The script can access these
arguments by using arg[1], arg[2], etc. or the vararg
expression '...'.
-- print the name of the script
print("name of the script:", arg[0])
-- print the number of arguments to the script
print("number of arguments:", select('#', ...) )
-- print all arguments
print("arguments:",...)
-- this prints the first argument
print("Argument 1: ", arg[1] or "none")
-- exiting Scrupp
game.exit()
Just save this example code in a file called
argtest.lua and run
$ scrupp -e argtest.lua arg1 arg2
This can be done with every example from the manual. To get started have a look at the General Functions, save the example in a file and run this file with Scrupp.
At the beginning, Scrupp runs a Lua file which is chosen depending on the command line arguments. Read "Getting Started" for details. This file can run other Lua files, load any media type, define functions and so on. It has to define a table with the name 'main' which contains the callbacks.
game.init("Callback Test", 600, 400, 32, false)
image = game.addImage(<image file>)
main = {
render = function(dt)
image:render(mouse.getX(), mouse.getY())
end,
mousepressed = function(x, y, button)
print(button .." button pressed at "..x..", "..y)
end,
mousereleased = function(x, y, button)
print(button .." button released at "..x..", "..y)
end,
keypressed = function(k)
if k == key.ESCAPE then
game.exit()
end
print("key with keycode " .. k .. " pressed")
end,
keyreleased = function(k)
print("key with keycode " .. k .. " released")
end
}
game.init("Draw Test - Click to test!", 600, 400, 32, false)
-- prepare one table for big white pixels
pixels = { antialiasing = false, size = 20, pixellist = true }
-- prepare one table for red connected lines
lines = { color = {255,0,0}, antialiasing = true, connect = true }
main = {
render = function(dt)
game.draw(lines)
game.draw(pixels)
end,
mousepressed = function(x, y, button)
-- add the point where the mouse was pressed to the list of pixels
pixels[#pixels+1] = x
pixels[#pixels+1] = y
-- add the point to the list of lines, too
lines[#lines+1] = x
lines[#lines+1] = y
end
}
game.init("Image Test", 600, 400, 32, false)
-- load an image file
image = game.addImage(<image file>)
-- get the dimension of the image
width = image:getWidth()
height = image:getHeight()
-- this has the same result:
width, height = image:getSize()
if width > game.getWindowWidth() or height > game.getWindowHeight() then
print("Please choose an image with smaller dimensions.")
game.exit()
end
-- calculate the x- and y-coordinate of the image
x = (game.getWindowWidth()-width)/2
y = (game.getWindowHeight()-height)/2
main = {
render = function(dt)
-- get the position of the mouse pointer
mx, my = mouse:getPos()
-- set the image alpha depending on the x-coordinate of the
-- mouse pointer
image:setAlpha(mx/game.getWindowWidth()*200+50)
-- if you click with the left mouse button,
-- only a part of the image is rendered
if mouse.isDown("left") then
image:render{
mx, my,
rect = { mx-x, my-y, width/2, height/2 }
}
-- otherwise the whole image is rendered
else
image:render(x,y)
end
end
}
game.init("Font Test", 600, 400, 32, false)
-- load a font
font = game.addFont("fonts/Vera.ttf", 20)
-- get the recommended line height in pixel
lineSkip = font:getLineSkip()
-- get the text size of a sample text
w, h = font:getTextSize("Hello World")
-- define a color (opaque blue)
cBlue = {0, 0, 255, 255}
-- the transparency defaults to 255 (opaque), so this is the same:
cBlue = {0, 0, 255}
-- generate an image containing some text using the default color
image_1 = font:generateImage("Hello World")
-- generate an image using the defined color cBlue
-- -- because font:generateImage() gets only one parameter and this is a table
-- -- we can omit the parenthesises and just use the curly brackets of the table
-- -- constructor
image_2 = font:generateImage{"Hello World", color = cBlue}
-- this has the same result:
image_2 = font:generateImage{"Hello World", color = {0, 0, 255}}
main = {
render = function(dt)
-- render the already loaded images:
image_1:render(100,50)
image_2:render(100 + w, 50 + lineSkip)
-- render some text using font:print():
font:print(100, 50 + 2*lineSkip, "Hello World")
font:print{100 + w, 50 + 3*lineSkip, "Hello World", color = cBlue}
end
}
The sound support is implemented using SDL_mixer.
Note: If you load a sound and play it multiple times in parallel all sound manipulating methods will affect every instance of this sound!
game.init("Sound Test", 600, 400, 32, false)
-- load a sound file
sound = game.addSound(<sound file>)
main = {
-- empty render function
render = function(dt)
end,
-- play the sound every time a mouse button is pressed
mousepressed = function(x, y, button)
sound:play()
end
}
The music support is implemented using SDL_mixer.
Scrupp supports only one music file playing at a time. Because of that there is only one method for a music object: play. All the other music manipulating functions are independant from a special music object. They change whatever music file is playing at the moment.
id3convert -s -2 <mp3 file>
game.init("Music Test", 600, 400, 32, false)
-- load some music
music = game.addMusic(<music file>)
-- start music
music:play()
main = {
-- empty render function
render = function(dt)
end
}
game.init("Mouse Test", 600, 400, 32, false)
cursor = game.addImage(<path to cursor image>)
main = {
render = function(dt)
if mouse.isDown("left") then
cursor:render(mouse.getX(), mouse.getY())
--or: cursor:render(mouse:getPos())
end
end,
mousepressed = function(x, y, button)
print(button .." button pressed at "..x..", "..y)
end,
mousereleased = function(x, y, button)
print(button .." button released at "..x..", "..y)
end
}
The first table shows virtual key constants. These keys do not exist. You should not try to use them with the callbacks because they will never occur. Instead of e.g. key.SHIFT, test for key.LSHIFT or key.RSHIFT
They should be used with key.isDown() to test for some special keys which happen to be twice on a standard keyboard. key.isDown(key.SHIFT) will return true if either of the two shift keys is pressed.
| key.SHIFT | either of the shift keys |
| key.CTRL | either of the ctrl keys |
| key.ALT | either of the alt keys |
| key.META | either of the meta keys |
| key.SUPER | either of the windows keys |
The following table shows all key constants usable with Scrupp.
| key.BACKSPACE | '\b' | backspace |
| key.TAB | '\t' | tab |
| key.CLEAR | clear | |
| key.RETURN | '\r' | return |
| key.PAUSE | pause | |
| key.ESCAPE | '^[' | escape |
| key.SPACE | ' ' | space |
| key.EXCLAIM | '!' | exclaim |
| key.QUOTEDBL | '"' | quotedbl |
| key.HASH | '#' | hash |
| key.DOLLAR | '$' | dollar |
| key.AMPERSAND | '&' | ampersand |
| key.QUOTE | ''' | quote |
| key.LEFTPAREN | '(' | left parenthesis |
| key.RIGHTPAREN | ')' | right parenthesis |
| key.ASTERISK | '*' | asterisk |
| key.PLUS | '+' | plus sign |
| key.COMMA | ',' | comma |
| key.MINUS | '-' | minus sign |
| key.PERIOD | '.' | period |
| key.SLASH | '/' | forward slash |
| key.0 | '0' | 0 |
| key.1 | '1' | 1 |
| key.2 | '2' | 2 |
| key.3 | '3' | 3 |
| key.4 | '4' | 4 |
| key.5 | '5' | 5 |
| key.6 | '6' | 6 |
| key.7 | '7' | 7 |
| key.8 | '8' | 8 |
| key.9 | '9' | 9 |
| key.COLON | ':' | colon |
| key.SEMICOLON | ';' | semicolon |
| key.LESS | '<' | less-than sign |
| key.EQUALS | '=' | equals sign |
| key.GREATER | '>' | greater-than sign |
| key.QUESTION | '?' | question mark |
| key.AT | '@' | at |
| key.LEFTBRACKET | '[' | left bracket |
| key.BACKSLASH | '\' | backslash |
| key.RIGHTBRACKET | ']' | right bracket |
| key.CARET | '^' | caret |
| key.UNDERSCORE | '_' | underscore |
| key.BACKQUOTE | '`' | grave |
| key.a | 'a' | a |
| key.b | 'b' | b |
| key.c | 'c' | c |
| key.d | 'd' | d |
| key.e | 'e' | e |
| key.f | 'f' | f |
| key.g | 'g' | g |
| key.h | 'h' | h |
| key.i | 'i' | i |
| key.j | 'j' | j |
| key.k | 'k' | k |
| key.l | 'l' | l |
| key.m | 'm' | m |
| key.n | 'n' | n |
| key.o | 'o' | o |
| key.p | 'p' | p |
| key.q | 'q' | q |
| key.r | 'r' | r |
| key.s | 's' | s |
| key.t | 't' | t |
| key.u | 'u' | u |
| key.v | 'v' | v |
| key.w | 'w' | w |
| key.x | 'x' | x |
| key.y | 'y' | y |
| key.z | 'z' | z |
| key.DELETE | '^?' | delete |
| key.KP0 | keypad 0 | |
| key.KP1 | keypad 1 | |
| key.KP2 | keypad 2 | |
| key.KP3 | keypad 3 | |
| key.KP4 | keypad 4 | |
| key.KP5 | keypad 5 | |
| key.KP6 | keypad 6 | |
| key.KP7 | keypad 7 | |
| key.KP8 | keypad 8 | |
| key.KP9 | keypad 9 | |
| key.KP_PERIOD | '.' | keypad period |
| key.KP_DIVIDE | '/' | keypad divide |
| key.KP_MULTIPLY | '*' | keypad multiply |
| key.KP_MINUS | '-' | keypad minus |
| key.KP_PLUS | '+' | keypad plus |
| key.KP_ENTER | '\r' | keypad enter |
| key.KP_EQUALS | '=' | keypad equals |
| key.UP | up arrow | |
| key.DOWN | down arrow | |
| key.RIGHT | right arrow | |
| key.LEFT | left arrow | |
| key.INSERT | insert | |
| key.HOME | home | |
| key.END | end | |
| key.PAGEUP | page up | |
| key.PAGEDOWN | page down | |
| key.F1 | F1 | |
| key.F2 | F2 | |
| key.F3 | F3 | |
| key.F4 | F4 | |
| key.F5 | F5 | |
| key.F6 | F6 | |
| key.F7 | F7 | |
| key.F8 | F8 | |
| key.F9 | F9 | |
| key.F10 | F10 | |
| key.F11 | F11 | |
| key.F12 | F12 | |
| key.F13 | F13 | |
| key.F14 | F14 | |
| key.F15 | F15 | |
| key.NUMLOCK | numlock | |
| key.CAPSLOCK | capslock | |
| key.SCROLLOCK | scrollock | |
| key.RSHIFT | right shift | |
| key.LSHIFT | left shift | |
| key.RCTRL | right ctrl | |
| key.LCTRL | left ctrl | |
| key.RALT | right alt | |
| key.LALT | left alt | |
| key.RMETA | right meta | |
| key.LMETA | left meta | |
| key.LSUPER | left windows key | |
| key.RSUPER | right windows key | |
| key.MODE | mode shift | |
| key.HELP | help | |
| key.PRINT | print-screen | |
| key.SYSREQ | SysRq | |
| key.BREAK | break | |
| key.MENU | menu | |
| key.POWER | power | |
| key.EURO | euro |
The source of this table is the SDL man page for SDLKey.
game.init("Keyboard Test", 600, 400, 32, false)
main = {
render = function(dt)
-- we need at least an empty render function
end,
keypressed = function(k)
-- check if a valid letter key is pressed;
-- string.byte is a Lua function that returns
-- the ASCII value of a char
if k>=string.byte('a') and k<=string.byte('z') then
-- if a letter key is pressed, then the argument k
-- is a number (the ASCII code);
-- string.char is a Lua function that returns
-- the char of such a code
local ch = string.char(k)
-- check whether any of the two shift keys is pressed
if key.isDown(key.SHIFT) then
-- make the letter uppercase
ch = string.upper(ch)
end
-- print the letter of the key;
-- string.char is a Lua function that returns
-- the char of a ASCII value
print(ch .. " pressed")
end
-- the escape key exits the demo
if k == key.ESCAPE then
game.exit()
end
end,
keyreleased = function(k)
print("key released")
end
}
