PIGSCRIPT

.pig v3 — the LuckyPurplePig language, now in 3D
EDITOR
1

        
      

PIGSCRIPT in 60 seconds

Variables

let x = 5
const NAME = "pig"   // can't be reassigned
x += 1

Types

num str bool nil array map fn — check with type(v)

Control flow

if x > 3 { print("big") } else if x == 3 { print("three") } else { print("small") }
while x > 0 { x -= 1 }
for i in 0..10 { print(i) }      // range: 0..10 = [0..9]
for ch in "hello" { print(ch) }  // strings + arrays + map keys iterate
break  continue

Functions & closures

fn add(a, b) { return a + b }
let twice = fn(f, v) { return f(f(v)) }
fn counter() { let n = 0  return fn() { n += 1 return n } }

Arrays & maps

let a = [1, 2, 3]
push(a, 4)  pop(a)  a[0]  a[-1]  len(a)  slice(a, 1, 3)
let m = { name: "pig", hp: 100 }
m.hp -= 10   m["name"]   keys(m)   contains(m, "hp")

Logic

and  or  not     ==  !=  <  >  <=  >=

String interpolation v2

let name = "pig"
print("hello {upper(name)}, 2+2 = {2 + 2}")   // any expr inside {}
// literal brace: "\{"

Builtins

print len push pop keys str num type floor ceil round abs sqrt sin cos min max random() random(n) random(a,b) upper lower split join slice contains

New in v2

math: tan atan2(y,x) pow(a,b) pi() clamp(v,lo,hi) lerp(a,b,t) dist(x1,y1,x2,y2)

arrays: sort(a) sort(a, keyfn) reverse(a) insert(a,i,v) remove(a,i) find(a,v) map(a,f) filter(a,f) reduce(a,f,init)

strings: trim replace(s,from,to) repeat(s,n) char(n) code(s)

storage (persists across runs & reloads — high scores!):

save("best", 42)
let b = load("best")     // nil if never saved

New in v3 3D + juice

// ternary + two-variable for loops
let label = hp > 50 ? "fine" : "ouch"
for i, v in ["a", "b"] { print(i, v) }   // 0 a / 1 b
for k, v in { hp: 9 } { print(k, v) }    // hp 9

3D engine (software rendered, y is up):

cam(x, y, z, yaw, pitch)     // place the camera
cube(x, y, z, size, "#7dffa8")  // queue a cube (corner at x,y,z)
render3d()                   // draw the queue: shaded, sorted, fogged
fov(90)  fog("#1a2340", 34)  // tune lens + fog color/distance
let d = look()               // [dx,dy,dz] camera forward vector

game feel:

sprite(x, y, ["..PP..", ".PPPP."], { P: "#ff7ad9" }, 3)  // pixel art from strings
particle(x, y, vx, vy, life, "#ffd97a", size)  // auto-updated + faded for you
camera(x, y)      // 2D scroll offset (clear() re-applies it)
shake(8)          // screen shake, decays on its own
glow(x, y, r, "#ff7ad9")  // radial light
melody("c4 e4 g4 c5 r g4 c5", 180, "square")  // note sequencer, r = rest

Game loop

onframe(fn(dt) {          // called ~60x per second, dt = seconds since last frame
  clear("#000")
  // ...update + draw your game here
})
stop()                     // ends the loop

Input & sound

keydown("left")   // held?   names: left right up down space a-z
keyhit("space")   // pressed this frame? (edge-triggered)
mousex()  mousey()  mousedown()
sound(440, 0.1)   // beep: frequency, seconds
time()            // seconds since program start

Canvas

clear("#000")
rect(x, y, w, h, "#ff7ad9")
circle(x, y, r, "#7dffa8")
line(x1, y1, x2, y2, "#fff", width)
text("hi", x, y, "#fff", size)
// v2:
poly([[x,y], [x,y], ...], "#b07aff")   // filled polygon
ellipse(x, y, rx, ry, "#ff7ad9")
arc(x, y, r, a1, a2, "#ffd97a", width) // angles in radians
box(x, y, w, h, "#7dffa8", linewidth)  // outline rect
alpha(0.5)                             // transparency (clear() resets it)
width()  height()                      // 480, 270

Click anywhere outside to close.