Although I love dabbling in game creation, I tend to flit across various utilities forgetting much of what I learnt along the way. For example:
PLACE 2,100,100,1
...was that an MPAGD command or Pico8 - and what did that final digit do again?! Well, it was Games Master, and that final digit selects the plane it will operate on. I think.
So this page is just for me. My own little cheat sheet of stuff I'll probably forget.
MPAGD
I'm a paragraph. Click here to add your own text and edit me. It's easy.
Pico8
Circles and Trigonometry
Trigonomentry! Apparently, Pico-8 is not the best place to learn about Trigonometry itself as it deals with it in kind of a funny way. However, in order to plot the points of a circle, you need to:
-
Decide on the size of the Radius.
-
Decide on the size of the Angle (think of a clock face - Angle 0 is at 3, Angle 90 is at 12, Angle 180 is at 9 and Angle 270 is at 6).
-
Decide on the origin where you want the centre of the circle (X,You).
-
To get the X coordinate on the circumference, add Radius * Cos(Angle / 360) to the X origin.
-
To get the Y coordinate on the circumference, add Radius * Sin(Angle / 360) to the Y origin.
You can then cycle through all the angles 0-360 to get your circle.
function _init()
orig_x=63
orig_y=63
radius=30
angle=0
end
function _update()
angle+=5
if angle==360 then stop("done") end
end
function _draw()
pset(orig_x+radius*cos(angle/360),orig_y+radius*sin(angle/360),7)
end



Tables #2
function _init()
init_balls()
end
function _update()
update_balls()
end
function _draw()
cls()
draw_balls()
end
-- user functions --
function init_balls()
ball={}
for f=1,5 do
add(ball,{bx=rnd(120)+4,by=rnd(120)+4,bxx=1,byy=1})
end
end
function update_balls()
for f in all(ball) do
f.bx+=f.bxx
f.by+=f.byy
if f.bx<5 or f.bx>123 then f.bxx=-f.bxx end
if f.by<5 or f.by>123 then f.byy=-f.byy end
end
end
function draw_balls()
for f in all(ball) do
circ(f.bx,f.by,4,7)
end
end


Passing Values to a Function
A value can be passed to a function by placing the appropriate variable inside the function's brackets. These can then be picked up inside the function itself by a new set of variables, also in the brackets, and manipulated.
Depending on the function's ...function(!) it can undertake its own arithmetic and then return TRUE or FALSE. Doing so will bring the function to an abrupt end and return the program to the point where it left.
Therefore, with the appropriate values passed to a function it can become a validation check in its own right, i.e.
IF OVERLAP(PLAYER,SHIP) THEN GAMEOVER=1 END
If the function above returned false, the gameover variable would not be changed.
function _init()
px=10
py=10
ex=64
ey=64
backcol=0
end
function _update()
moveplayer()
if checkcol(px,py) then
backcol=8
else
backcol=0
end
end
Function _draw()
rectfill(0,0,127,127,backcol)
pset(px,py,11)
pset(ex,ey,10)
end
-- user functions --
function moveplayer()
if btn(0) then px-=1 end
if btn(1) then px+=1 end
if btn(2) then py-=1 end
if btn(3) then py+=1 end
end
function checkcol(checkx,checky)
if checkx==ex and checky==ey then return true end
return false
end


State Engine
(or my interpretation anyway)
Main game loops can get cluttered with code once they get to a certain length and extra care has to be taken to make sure your code doesn't interfere with, or affected by, other code within the main game loop. To prevent this, separate the project into game states. That way, a main loop can deal solely with the options or main menu without dealing with the actual gameplay. Within the game itself, it can also help separating game states such a player walking left/right or climbing a ladder.
I guess there are a number of ways to control a state engine, but at my level, assigning simple 1,2,3,etc. values to it suits me just fine for now.
function _init()
gamestate=1
end
function _update()
if gamestate==1 then mainmenu()end
if gamestate==2 then gameloop() end
if gamestate==3 then stop("i'm done!",15,123,7) end
end
function _draw()
end
-- user functions --
function mainmenu()
cls()
rectfill(0,0,127,127,7)
rectfill(3,3,124,124,0)
print("press 'z' to continue",20,60,7)
if btnp(4) then
cls()
gamestate=2
end
end
function gameloop()
line(flr(rnd(120))+3,flr(rnd(118))+5,flr(rnd(120))+3,flr(rnd(118))+5,flr(rnd(16)))
print("press 'x' to end",0,0,7)
if btnp(5) then
gamestate=3
end
end


Tables #1
Okay - I think this is a table (...or is it a list?) - I may have to come back and correct this at a later point when I find out I'm totally wrong!
Defined and populated by assigning values within curly brackets. The total number of values in a table can be returned by using a hash-tag infront of the table name.
When referring to individual values in a table, they are accessed with square brackets [].
(Edit: I realise placing a STOP command within a function like this isn't 'best practice')
function _init()
shoppingbasket(
end
function _update()
end
function _draw()
printlist()
end
-- user functions
function shoppingbasket()
goods={"potatoes","beans","radio times","branston pickle"}
end
function printlist()
for f=1,#goods do
print (goods[f])
end
print("item no.2 is:"..goods[2])
stop("...list finished")
end


For / Next Loops and Concatenate
Fairly straight-forward stuff. Just add the extra value if you want to count every 2, 3,4..etc.
To concatenate strings, use two dots '..' between the strings.


Buttons / Input
function _init()
lastbutton="none"
end
function _update()
if(btn(0)) then lastbutton="left" end
if(btn(1)) then lastbutton="right" end
if(btn(2)) then lastbutton="up" end
if(btn(3)) then lastbutton="down" end
if(btn(4)) then lastbutton="z" end
if(btn(5)) then lastbutton="x" end
end
function _draw()
cls()
print ("last button:"..lastbutton,20,60)
end
In short...
-
BTN(0) - Left
-
BTN(1) - Right
-
BTN(2) - Up
-
BTN(3) - Down
-
BTN(4) - Z
-
BTN(5) - X
-
The code above will check each frame for the current key pressed down causing it to repeat very quickly. To check only once (pressed), use BTNP(#) ...although this does seem to repeat every second or so - I'll look into this later.


Filling those functions
As a quick example of what the functions do, I'm going to place sprite 0 (which is a small 'x' character) in the middle of the screen.
-
FUNCTION _INIT() - Set up the variables of where sprite 0 will be displayed (128 is intentional).
-
FUNCTION _UPDATE() - The current X & Y position are stupid (off the screen) so I'll halve them so the sprite should actually appear where I can see it.
-
FUNCTION _DRAW() - Clear the screen and draw the sprite.
So...
INIT() = set it, UPDATE() = change it, DRAW() = show it.


Function Framework
Pico8 works within the following framework:
-
FUNCTION _INIT() ...called at the start of each game and is used to set up variables, etc.
-
FUNCTION _UPDATE() ...called each game-loop and updates sprites positions, etc. By default runs at 30fps.
-
FUNCTION _DRAW() ...tries to match the game-loop but it will drop frames to keep up if necessary.

Basics first
Pressing escape switches from the command line to the code editor.
I shall add to these as I discover them, but for now the main ones are:
-
HELP
-
SPLORE
-
INSTALL_DEMOS
-
REBOOT
-
MKDIR <dirname>
Once in the code editor window, pressing ALT+CURSORS (left/right) will flip between the different editors. Going left to right they are: boot screen, code editor, sprite editor, map editor, sound fx editor and the music editor."






Games Master
text blah blah