Assignment 00 - Individual - Lua Introduction (part 0)
Comments, Variables, Flow Control — Due: 2019.06.18 1:00PM
In this assignment, you will begin to learn how to code in PICO-8. PICO-8 uses Lua 5.2 as it's programming language, but there are a few differences (not covered in this course).
Useful
After running PICO-8, toggle between the console and the editors by pressing the ESC key.
You can execute commands immediately using the console.
You can run the code that is typed in the editor by typing run in the console or by pressing CTRL+R.
Requirements
- Read the following sections of the Learn PICO-8 Guide located in the Resources section below.
- Section 0, Comments
- Section 1, Variables and Flow Control
- Answer the Questions below.
- You will not turn in your answers, but there might be a quiz over them.
- Solve the Problems addressed below.
- Write all of you code in the PICO-8 code editor, not in the console.
- Save your solution as a PNG cartridge called
a00_lua.p8.png.- IMPORTANT: Use
save a00_lua.p8.png, notexport a00_lua.png - The former creates a cartridge; the latter exports the sprite sheet.
- IMPORTANT: Use
- Submit your PNG cartridge to the course Canvas page.
Resources
The PICO-8 program below computes the factorial of a number. You may copy the source by pressing the COPY button in the top-right corner, and then paste it into your PICO-8 editor with CTRL+V.
-- defines a factorial function
function fact (n)
if n == 0 then
return 1
else
return n * fact(n - 1)
end
end
-- print factorial of number 5
print("factorial(5) = "..fact(5))
Below is a modified version of the Learning Lua in 15 Minutes | Tyley Neylon. I have modified it to include the quirks of PICO-8's Lua implementation.
--[[
welcome to the learn pico-8 guide!
pico-8 is a fantasy console for making, sharing, and
playing tiny games and other computer programs. when you
turn it on, the machine greets you with a shell for
typing in lua programs and provides simple built-in tools
for creating sprites, maps, and sounds
the harsh limitations of pico-8 are carefully chosen to be fun
to work with, encourage small but expressive designs and
hopefully to give pico-8 cartridges their own particular
look and feel.
keys
alt+enter toggle fullscreen
alt+f4 quit
ctrl+r reload/run/restart cart
ctrl+s quick-save
ctrl+m mute / unmute
arrows+zx player 1 controls
sdfe+tab,q player 2 controls
enter/p pause game
specs
display 128x128 pixels fixed 16 color pal
input 6 btn controller
cart size 32k
sound 4 channel, 64 editable blerps
code lua (max 8192 tokens of code)
sprites single bank of 128 8x8 sprites (+128 shared)
map 128x32 8b cels (+128x32 shared)
an important note:
pico-8 uses portions of lua 5.2 under the hood. so, if
you know lua, you can easily learn pico-8. however, there
are a few differences that will make standard lua code
not work in pico-8. i will try to note these.
a less important note:
pico-8 is a constrained fantasy console. one of the
constraints is that there is no case (no upper or lower
case of a). also, the editor can only show 32 characters.
i have written this document to fit these constraints, so
that you can copy-paste the document into the pico-8
editor and run it.
--]]
------------------------------------------------------------
-- Section 0. comments
------------------------------------------------------------
-- two dashes start a one-line comment.
--[[
adding two ['s and ]'s makes
it a multi-line comment.
--]]
------------------------------------------------------------
-- Section 1. variables and flow control
------------------------------------------------------------
num = 42
-- all numbers are 32b fixed-point floats. this
-- means that there are 16bits for storing the integer,
-- and 16bits for storing the decimal portion. numbers
-- can store any value between -32768.0 and 32767.99999,
-- inclusive. if you try to store numbers outside that
-- range, the value will wrap around (modulus).
s = 'walternate' -- immutable strings like python.
t = "double-quotes are fine"
u = [[ double brackets
start and end
multi-line strings.]]
t = nil -- undefines t; lua has garbage collection.
-- blocks are denoted with keywords like do/end:
while num < 50 do
-- the following two lines both increment num by 1
num = num + 1
num += 1
end
-- if clauses:
if num > 40 then
print('over 40')
elseif s ~= 'walternate' then
-- ~= is not equals. can use != instead.
print('not over 40')
elseif s == "foo bar" then
-- equality check is == like python; ok for strs.
else
-- variables are global by default.
thisisglobal = 5
-- line (below) is a local variable. local vars
-- exist only within the chunk they are defined.
local line = 'bar'
-- string concatenation uses the .. operator:
print('foo ' .. line)
end
-- line is no longer defined
-- undefined variables return nil. this is not an error:
foo = anunknownvariable
-- now, foo == nil.
aboolval = false
-- only nil and false are falsy; 0 and '' are true!
if not aboolval then
print('twas false')
end
-- 'or' and 'and' are short-circuited. this is similar
-- to the a?b:c operator in c/js:
ans = aboolval and 'y' or 'n'
-- now, ans == 'n'
karlsum = 0
for i = 1, 100 do
-- range includes both ends.
karlsum = karlsum + i
end
-- use "100, 1, -1" as the range to count down:
fredsum = 0
for j = 100, 1, -1 do
fredsum = fredsum + j
end
-- in general, the range is begin, end[, step].
-- another loop construct:
repeat
print('back to the future!')
num = num - 1
until num == 0
------------------------------------------------------------
-- Section 2. functions
------------------------------------------------------------
function fib(n)
if n < 2 then return 1 end
return fib(n - 2) + fib(n - 1)
end
-- closures and anonymous functions are ok:
function adder(x)
-- the returned function is created when adder is
-- called, and remembers the value of x:
return function (y)
return x + y
end
end
a1 = adder(9)
a2 = adder(36)
print(a1(16)) --> 25
print(a2(64)) --> 100
-- returns, func calls, and assignments all work with
-- lists that may be mismatched in length. unmatched
-- receivers are nil; unmatched senders are discarded.
x, y, z = 1, 2, 3, 4
-- now x == 1, y == 2, z == 3, and 4 is thrown away.
function bar(a, b, c)
print(a.." "..b.." "..c)
return 4, 8, 15, 16, 23, 42
end
x, y = bar('zaphod')
-- prints "zaphod nil nil" now x == 4, y == 8,
-- values 15..42 are discarded.
-- functions are first-class, may be local/global. these
-- are the same:
function f(x) return x * x end
f = function (x)
return x * x
end
-- and so are these:
local function g(x)
return sin(x)
end
local g; g = function (x)
return sin(x)
end
-- the 'local g' decl makes g-self-references ok.
-- in pico-8, trig functions such as sin, cos, and atan2
-- work in [0,1] range, *not* in radians or degrees! also,
-- sin is inverted! both of these points deviate from
-- lua and other standard languages.
-- calls with one string param don't need parens:
print 'hello' -- works fine.
------------------------------------------------------------
-- Section 3. tables
------------------------------------------------------------
-- tables are lua's only compound data structure;
-- they are associative arrays. similar to php arrays or js
-- objects, they are hash-lookup dicts that can also
-- be used as lists.
-- using tables as dictionaries / maps:
-- dict literals have string keys by default:
t = {
key1 = 'val1',
key2 = false
}
-- string keys can use js-like dot notation:
print(t.key1) -- prints 'val1'
t.newkey = {} -- adds a new key/val pair
t.key2 = nil -- removes key2 from the t
-- literal notation for any (non-nil) value as key:
u = {
['@!#'] = 'qbert',
[{}] = 1729, -- new dict, object as key
[6.28] = 'tau'
}
print(u[6.28]) -- prints "tau"
-- key matching is basically by value for numbers and
-- strings, but by identity for tables.
a = u['@!#'] -- now a = 'qbert'
b = u[{}] -- we might expect
-- 1729, but it's nil: b = nil since the lookup fails. it
-- fails because the key we used is not the same object
-- as the one used to store the original value. so strings
-- and numbers are more portable keys.
-- a one-table-param function call needs no parens:
function h(x) print(x.key1) end
h{key1 = 'sonmi~451'} -- prints 'sonmi~451'.
-- table iteration.
for key, val in pairs(u) do
print(key.." "..val)
end
-- using tables as lists / arrays:
-- list literals implicitly set up int keys:
v = {
'value1',
'value2',
1.21,
'gigawatts'
}
for i = 1, #v do
-- #v is the size of v for lists.
print(v[i])
end
-- important: indices start at 1!! so crazy!
-- a 'list' is not a real type. v is just a table with
-- consecutive integer keys, treated as a list.
------------------------------------------------------------
-- Section 4. pico-8 functions
------------------------------------------------------------
--[[
pico-8 has many built-in fns defined for drawing, playing
sounds or music, or for manipulating memory.
also, there are a few special functions that you will define
to make your game work.
--]]
print('hello world')
rectfill(80,80,120,120,12)
circfill(70,90,20,14)
for i=1,4 do print(i) end
-- rectfill function draws a filled rectangle. the
-- parameters are:
-- rectfill x0 y0 x1 y1 [col]
-- the col param is optional.
-- circfill draws a filled circle. the parameters are:
-- circfill x y r [col]
-- technically, print has parameters that allow you to
-- print text anywhere on the screen.
-- print str [x y [col]]
-- color indices:
-- 0 black 1 dark blue
-- 2 dark purple 3 dark green
-- 4 brown 5 dark gray
-- 6 light gray 7 white
-- 8 red 9 orange
-- 10 yellow 11 green
-- 12 blue 13 indigo
-- 14 pink 15 peach
btn_0 = btn(0, 0)
print(btn_0)
-- btn function returns boolean indicating if a given button
-- for a given player is being pressed.
-- btn [i [p]]
-- i: [0,5]: left, right, up, down, button_o, button_x
-- p: [0,7]: player index
-- if no params are supplied, btn returns a bitfield of
-- all 12 button states for plr 0 & 1.
greatr = max(1, 3)
lesser = min(1, 3)
middle = mid(1, 5, 3)
floor = flr(4.1)
ceiling = ceil(4.1)
-- other useful math functions
-- cos, sin, atan2 (remember, these work in [0,1] range!)
-- sqrt, abs, rnd, srand
-- convert str->num or val->str
anumber = tonum('2.7')
astring = tostr(2.7)
bstring = tostr(true)
cstring = tostr(nil)
-- finally, pico-8 calls fns with special names when the
-- cart is ran.
function _init()
-- this function is called
-- once at program startup.
-- place all initialization
-- code in here.
end
function _update()
-- this function is called
-- at 30fps while the
-- program is running.
-- place code to update the
-- game's state in here.
end
function _draw()
-- this function is called
-- once per visible frame.
-- place code to draw the
-- game in here.
end
------------------------------------------------------------
-- Section 5. references
------------------------------------------------------------
--[[
this is a modification of the:
learning lua in 15 minutes, by tyler neylon.
http://tylerneylon.com/a/learn-lua/
i have modified it to include the quirks of pico-8's lua
implementation.
other great resources:
https://www.lexaloffle.com/pico-8.php?page=manual
http://pico-8.wikia.com/wiki/lua
https://github.com/felipebueno/awesome-pico-8
https://www.lexaloffle.com/bbs/?tid=28207
https://neko250.github.io/pico8-api/
--]]
Questions
- What do each of the following mean in PICO-8?
----[[--]]
- Which of the following strings are valid PICO-8 identifiers?
____ENDENDUNTIL?NILNULLONE-STEP
- What does
x += 1do? What doesy = y + 1do? - What are the different ways you can write a loop? How are they different?
- What is the difference between
=,==,~=, and!=? - How do you write a conditional (if)? What does
elseifmean? - When it comes to strings, what is the difference between a single quote (
') and a double quote (")? For example,'foo'and"foo". - What does
foo = nildo?
Problems
-
Write working PICO-8 code that performs the following assigning, summing, concatenating, and printing
- Assign your current age to variable called
AGE - Assign
10to a variable calledPLUS - Print out
MY AGE ISfollowed by the value store inAGE- Note: all of this text should be printed on a single line!
- For example:
MY AGE IS 59
- Print out
BUT IN xx YEARS, I WILL BE xxbut usePLUSand the sum ofPLUSandAGEwhere appropriate- Note: all of this text should be printed on a single line!
- For example:
BUT IN 10 YEARS, I WILL BE 69
- Store your first (given) name to the variable
FNAME - Store your last (family) name to the variable
LNAME - Print out
MY NAME ISfollowed by the values stored inFNAMEandLNAME
- Assign your current age to variable called
-
Write working PICO-8 code that performs the following iteration
- Using a
FORloop, print outHELLO, WORLDexactly 10 times - Using a
FORloop, print out the sum of the values of numbers between 5 and 15, inclusively.
- Using a
-
Write working PICO-8 code that performs the following
- Copy and paste the factorial function (Resources section above) into your PICO-8 source.
- What happens if you call
factwith a negative number? (ex:fact(-42)) - Modify the example to avoid this problem by having the function return
nilwhen the parameter is negative.- Note:
fact(0)should still return1, notnil!
- Note:
- Demonstrate you have done this correctly by printing out the result of
fact(-42)andfact(5)
The output after completing each step above should look like the following screenshot (assuming you are Roberto Ierusalimschy, the creator of the Lua programming language).

Deliverable
Create a PNG cartridge for your solution called a00_lua.p8.png, and submit it to the course Canvas page.
Grading Rubric
| 3pts | Variables are used correctly for age and name |
| 3pts | For-loops are correct |
| 3pts | Factorial function is correctly modified |
| 3pts | Submitted PNG cartridge |