Commented source
Questle Run » Devlog
This being a #Pico1k game, here’s the unminified source code with comments so it’s clear what’s what
I might update the game and not update this, who knows
-- create the stars table
★={}
-- all the objects in the game — stars, rings and targets — work the same. this function creates a new object and stores it in 's'
-- "s" is a general variable meaning "whatever object we're doing just now"; having this convention saves us passing parameters back and forth which would have been bad if i'd ended up closer to the 1k limit
function n★()
s={
x=rnd()*128-64,
y=rnd()*128-64,
s=1.0002
}end
-- these two values need initialising for the title screen to work
v=1
u=1
-- everything else happens in this "start game" function
function l()
-- initialise ring
x=100
-- initialise target
y=150
-- initialise player
e=0 --score
v=1 --speed
w=900.001 --timer - we add .01 to this so that it will print "5.001" instead of "5". then we print it really close to the edge of the screen so we can limit it to 1 decimal place without doing any string manipulation
u=1 --base_speed
end
-- this takes the "current" object ('s') and moves it forward in fake-3d space, accounting for steering
function m()
s.x*=s.s
s.y*=s.s
-- v is the player's current speed
s.s+=0.0004*v
-- u is the "base" speed, ie, the speed you'll fall back to after the current boost ends
if btn(⬅️)do s.x+=2.3*u end
if btn(➡️)do s.x-=2.3*u end
if btn(⬆️)do s.y+=2.3*u end
if btn(⬇️)do s.y-=2.3*u end
-- work out how far from the origin we are. we almost never need it, but working it out every time is fewer bytes
d=sqrt(s.x^2+s.y^2)
-- if the value overflows, we'll get zero which means you can hit things by running away from them. if that happens sub in a big number. in theory this means if you hit something exactly it won't count, but that'll never happen
if d==0do d=32000end
end
-- set the current draw colour from s -- you pass in three colours and it picks one based on distance
function c(f,m,l)color(s.s>1.03and l or s.s>1.01and m or f)
end
-- initialise the stars
for i=1,25do
n★()
★[i]=s
end
-- we're doing everything in the update function. we should be using _draw really, that's fewer bytes, but i'm not close enough to the wire to care
function _update()
cls()
-- draw starfield. doing it here means this is shown on the title and game over screens too, which is nice (and free)
for i=1,25do
s=★[i]
m()
if d>64do
n★()
★[i]=s
end
c(7,6,5)
-- note that almost everything is +64 as that's where the origin is. i tried using the camera function to do that globally but that was more bytes because compression is strange
pset(s.x+64,s.y+64)
end
-- x is "how long until a ring appears". it happens that that gets initialised on game start, so before a game starts, it's falsey and we can show the title screen
if not x do
-- ? is shorthand for "print" but compression handles that anyway.
?"questle run",40,40,8
?"targets: +score",10,50,9
?"rings: +time +score +speed",10,60,9
-- "press fire to begin" means everyone knows the fire key before they start, little tutorialising hack for you there, i'm mark brown and welcome to game maker's toolkit
?"press fire to begin",25,100,10
if btnp(🅾️)do l()end
return
end
-- v is your speed, it should reduce if you're going faster than u, your base speed
if v>u do v-=0.1end
-- w is how much time you have left. if it's below 0, show the game over screen
if w<0do
?"game over",50,40,8
?"you scored "..j,40,50,9
-- start is a button they're unlikely to be about to press anyway - using fire here would mean people skipping the game over screen and losing their score (bad experience)
?"press start to try again",20,100,10
if btnp(6)do
l()
-- suppress pause menu
poke(0x5f30,1)
end
return
end
-- only decrement it when actually playing so we don't loop round after 64k frames and start playing some more
w-=1
-- fire lasers
if btn(🅾️)do
-- draw beams
s=12+rnd()*3
for i=0,127,127do
line(i,127,64,64,s)
end
-- make laser noise (the \a command code causes the print statement to make sound instead, in this case one of two high pitched notes at random)
?s>13and"\ag5"or"\af5"
end
-- handle ring
-- rings are spawned when the x timer reaches zero
if x>0then
-- the timer goes down faster when you're moving faster
x-=v
if x<=0do
-- use our "new object" code to create the ring, then store it in r
n★()
r=s
end
else
-- load the ring from "r", move it and draw it
s=r
m()
c(4,9,10)
circ(s.x+64,s.y+64,s.s*750-750)
-- did you fly through the ring
if s.s>1.05do
-- if this is true then the ring has reached us in the z direction
x=150 -- spawn the next ring
if d<38do
v+=5 -- temporary speed boost
e+=10*u -- score
?"\ac3egc4" -- jingle
x=100 -- make next ring come sooner
w+=450/sqrt(u) -- time boost
if w>1800do w=1800end -- not too much tho
u+=.2 -- increase base speed
if u>6do u=6end -- not too much tho
else
?'\ad1.d1' -- if you missed it play the bad noise
end
end
end
-- handle target
-- targets work like rings but the timer is in y and the target is in t
if y>0then
y-=v
if y<=0do
n★()
t=s
end
else
s=t
m()
-- q draws a circle and, if you shot that circle, gives you 5 points (plus speed bonus) and removes the target. shooting the middle circle hits all three so you get 15 points. the target is removed 3 times but who cares, the effect is the same
q(1,13,12,600)
q(5,6,7,400)
q(2,4,8,200)
if s.s>1.05do
-- if you missed it, spawn another and play the bad noise
y=150
?'\ad1.d1'
end
end
-- draw aiming reticule (print a plus sign in the middle of the screen)
?"+",63,62,10
-- print score
j=flr(e)
?j,5,5
-- print timer
?w/30,113,5
end
-- this is the target drawing/shooting function we discussed
function q(f,m,l,r)
c(f,m,l)
circfill(s.x+64,s.y+64,s.s*r-r)
if btn(🅾️) and d<s.s*r-r do
e+=5*u
?'\ai6c' -- this is "play the note C in instrument 6". that instrument is white noise so it sounds a bit like an explosion if you don't pay attention
y=100
end
end
Files
questle.zip Play in browser
2 days ago
Leave a comment
Log in with itch.io to leave a comment.