~technomancy/fennel-compendium

b414fef85d75fce99cb9a7e78eab0ef018670562 — Phil Hagelberg 1 year, 3 months ago 1fa7d55
Everything runs except backpackless.
M .gitignore => .gitignore +4 -34
@@ 1,37 1,7 @@
/fennel
/fennel.lua
/fennelview.lua
/fallen/game-over.lua
/fallen/init.lua
/fallen/loader.lua
/fallen/sound.lua
/fallen/action.lua
/fallen/attack-resolution.lua
/fallen/attack.lua
/fallen/bump-plugin.lua
/fallen/ctrl.lua
/fallen/draw.lua
/fallen/editor-ctrl.lua
/fallen/explosion.lua
/fallen/farmer-logic.lua
/fallen/final.lua
/fallen/game.lua
/fallen/knight-logic.lua
/fallen/map.lua
/fallen/mode-intro.lua
/fallen/npc.lua
/fallen/npc1-logic.lua
/fallen/opening.lua
/fallen/pfbs.lua
/fallen/restart.lua
/fallen/robo-satan-logic.lua
/fallen/staging.lua
/fallen/state.lua
/fallen/stones.lua
/fallen/subtile.lua
/fallen/timer.lua
/fallen/ui-hud.lua
/fallen/ui-menu-params.lua
/fallen/ui-text-box.lua
/fallen/ui.lua
/fallen/wrap.lua
/fallen/*.lua
/always-kill-your-heroes/*.lua
/apocalypse-meow/*.lua
/downsheep/*.lua

M Makefile => Makefile +33 -4
@@ 1,6 1,8 @@
lovegames: always-kill-your-heroes apocalypse-meow energize exo-encounter-667 \
	fallen slime-the-world slimers-dungeon backpackless frog-collect-cheese \
	gravity-fall goo-runner tremendous-quest-iv bussard downsheep yahtzee-adventure
all: love tic

love: always-kill-your-heroes apocalypse-meow energize exo-encounter-667 \
	fallen slime-the-world slimers-dungeon frog-collect-cheese gravity-fall \
	goo-runner tremendous-quest-iv bussard downsheep yahtzee-adventure

fennel.lua: ../fennel/fennel.lua ; cp $< $@
fennelview.lua: ../fennel/fennelview.lua ; cp $< $@


@@ 40,31 42,58 @@ yahtzee-adventure/lib/fennel.lua: fennel.lua ; cp $< $@
always-kill-your-heroes: always-kill-your-heroes/lib/fennel.lua \
	always-kill-your-heroes/lib/fennel \
	always-kill-your-heroes/lib/fennelview.lua
	make -C $@ run
apocalypse-meow: apocalypse-meow/lib/fennel.lua \
	apocalypse-meow/lib/fennel \
	apocalypse-meow/lib/fennelview.lua
	make -C $@ run
energize: energize/polywell/lib/fennel.lua \
	energize/polywell/lib/fennel \
	energize/polywell/lib/fennelview.lua
	make -C $@ run
exo-encounter-667: exo-encounter-667/lib/fennel.lua \
	exo-encounter-667/lib/fennel \
	exo-encounter-667/lib/fennelview.lua
	make -C $@ run
fallen: fallen/lib/fennel.lua \
	fallen/lib/fennel \
	fallen/lib/fennelview.lua
	make -C $@ run
slime-the-world: slime-the-world/lib/fennel.lua \
	slime-the-world/lib/fennel \
	slime-the-world/lib/fennelview.lua
	cd $@ && love .
slimers-dungeon: slimers-dungeon/lib/fennel.lua \
	slimers-dungeon/lib/fennel \
	slimers-dungeon/lib/fennelview.lua
	love $@
# TODO: uses git-lfs; assets are missing
backpackless: backpackless/lib/fennel.lua slimers-dungeon/lib/fennelview.lua
	love $@
frog-collect-cheese: frog-collect-cheese/lib/Fennel/fennel.lua
	cd $@ && love .
gravity-fall: gravity-fall/fennel ; make -C gravity-fall
	make -C $@ run
goo-runner: goo-runner/lib/fennel.lua
	cd $@ && love .
tremendous-quest-iv: tremendous-quest-iv/polywell/lib/fennel.lua
	make -C $@ run
bussard: bussard/polywell/lib/fennel.lua
	cd $@ && love .
downsheep: downsheep/lib/fennel.lua
	make -C $@ run
yahtzee-adventure: yahtzee-adventure/lib/fennel.lua
	cd $@ && love .

tic: amethyst.fnl hats.fnl life.fnl mech.fnl robotfindskitten.fnl \
		spilljackers.fnl xeno.fnl

amethyst.fnl: fennel ; tic80 $@
hats.fnl: fennel ; tic80 $@
life.fnl: fennel ; tic80 $@
mech.fnl: fennel ; tic80 $@
robotfindskitten.fnl: fennel ; tic80 $@
spilljackers.fnl: fennel ; tic80 $@
xeno.fnl: fennel ; tic80 $@

.PHONY: lovegames
.PHONY: all love tic

M README.md => README.md +17 -1
@@ 2,4 2,20 @@

A way to see if Fennel changes break things.

Just games so far.
As of 2020 October, this contains every known game written in Fennel.

## Requirements

* [LÖVE](https://love2d.org) version 11.x
* [TIC-80](https://tic80.com) version 0.80

## Running

* Run `make` to every game in a row
* Run `make love` to run all the LÖVE games
* Run `make tic` to run all the TIC-80 games

## Copyright

All games are copyright their respective authors; see the readme or
comment headers.

M amethyst.fnl => amethyst.fnl +1 -1
@@ 7,7 7,7 @@
;; NOTE: This code is minified in order to save space. You
;; can find the full source code on GitHub:
;; https://github.com/stefandevai/amethyst-waters
(macros {:inc (fn [a ?n] `(set ,a (+ ,a (or ,?n 1)))) :dec (fn [a ?n] `(set ,a (- ,a (or ,?n 1)))) :decg (fn [a ?n] `(global ,a (- ,a (or ,?n 1)))) :incg (fn [a ?n] `(global ,a (+ ,a (or ,?n 1))))}) (fn sin [a] (math.sin a)) (fn cos [a] (math.cos a)) (fn pal [i r g b] (if (and (not r) (not g) (not b)) (values (peek (+ 0x3fc0 (* i 3))) (peek (+ 0x3fc0 (* i 3) 1)) (peek (+ 0x3fc0 (* i 3) 2))) (do (var rc r) (var gc g) (var bc b) (when (or (not rc) (< rc 0)) (set rc 0)) (when (or (not gc) (< gc 0)) (set gc 0)) (when (or (not bc) (< bc 0)) (set bc 0)) (when (> rc 255) (set rc 255)) (when (> gc 255) (set gc 255)) (when (> bc 255) (set bc 255)) (poke (+ 0x3fc0 (* i 3) 2) b) (poke (+ 0x3fc0 (* i 3) 1) g) (poke (+ 0x3fc0 (* i 3)) r)))) (fn out-of-bounds? [object] (or (< object.x 0) (< object.y 0) (> (+ object.x object.w) +width+) (> (+ object.y object.h) +height+))) (fn parallax [p0 factor axis] (if (= axis :x) (+ p0 (* *cam*.x factor)) (= axis :y) (+ p0 (* *cam*.y factor)))) (fn loop-spr [id x y w h pfactor ?colorkey ?flip] (spr id (- (% (parallax x pfactor :x) (+ 240 (* w 8))) (* w 8)) (- (% (parallax y pfactor :y) (+ 136 (* h 8))) (* h 8)) (or ?colorkey 0) 1 (or ?flip 0) 0 w h)) (fn r [a b] (math.random a b)) (fn rvalue [l] (. l (r 1 (length l)))) (fn has-element? [l e] (var found false) (each [k v (pairs l)] (when (= v e) (set found true) (lua :break))) found) (fn sign [x] (if (> x 0) 1 (< x 0) -1 0)) (fn bcollides? [a b] (and (< a.x (+ b.x b.w)) (> (+ a.x a.w) b.x) (< a.y (+ b.y b.h)) (> (+ a.y a.h) b.y))) (fn mcollides? [x y w h] (or (> (mget (// (% x 1920) 8) (// y 8)) 127)                        (> (mget (// (+ (% x 1920) (- w 1)) 8) (// y 8)) 127)            (> (mget (// (% x 1920) 8) (// (+ y (- h 1)) 8)) 127)                  (> (mget (// (+ (% x 1920) (- w 1)) 8) (// (+ y (- h 1)) 8)) 127)))    (fn mcollisions [obj] (let [x (- (+ obj.x obj.vx) (math.ceil *cam*.ox)) y (- (+ obj.y obj.vy) *cam*.oy) w obj.w h obj.h] (values (> (mget (// (% x 1920) 8) (// y 8)) 127)                        (> (mget (// (+ (% x 1920) (- w 1)) 8) (// y 8)) 127)            (> (mget (// (% x 1920) 8) (// (+ y (- h 1)) 8)) 127)                  (> (mget (// (+ (% x 1920) (- w 1)) 8) (// (+ y (- h 1)) 8)) 127))))   (fn rcollision [obj] (let [(tl tr bl br) (mcollisions obj)] (local ox (- (+ obj.x obj.vx) (math.ceil *cam*.ox))) (local oy (- (+ obj.y obj.vy) (math.ceil *cam*.oy))) (local ow (- (+ obj.x obj.vx obj.w) (math.ceil *cam*.ox))) (local oh (- (+ obj.y obj.vy obj.h) *cam*.oy)) (var sy 0)  (var ix 0)  (var iy 0)  (var in 0)  (when tl (inc in)) (when tr (inc in)) (when bl (inc in)) (when br (inc in)) (when (and (= in 4) (<= obj.x 1) obj.crush) (obj:crush)) (if (or tr br) (set ix (math.abs (- ow (* 8 (// ow 8))))) (or tl bl) (set ix (math.abs (- ox (* 8 (// (+ ox 8) 8)))))) (if (or br bl) (do (set iy (math.abs (- oh (* (// oh 8) 8)))) (set sy -1)) (or tr tl) (do (set iy (math.abs (- (* (+ (// oy 8) 1) 8) oy))) (set sy 1))) (when (and (= ix 0) (or tl tr bl br)) (set ix 8)) (when (and (= iy 0) (or tl tr bl br)) (set iy 8)) (if (and (or tl tr) (> ix iy)) (set obj.vy (+ obj.vy iy))  (and (or br tr) (> iy ix)) (set obj.vx (- obj.vx ix))  (and (or bl br) (> ix iy)) (set obj.vy (- obj.vy iy))  (and (or tl bl) (> iy ix)) (set obj.vx (+ obj.vx ix))  (and (> in 2) (= iy ix)) (do (set obj.vx 0) (set obj.vy 0))  (and (= iy ix)) (do (set obj.vy (+ obj.vy (* iy sy))))  (do (trace "bad collision") (set obj.vx 0) (set obj.vy 0))))) (fn math.round [n] (math.floor (+ n 0.5))) (fn deepcopy [orig] (var orig-type (type orig)) (var copy nil) (if (= orig-type "table") (do (set copy {}) (each [key value (pairs orig)] (tset copy (deepcopy key) (deepcopy value))) (setmetatable copy (deepcopy (getmetatable orig)))) (set copy orig)) copy) (fn mix [a b t] (+ (* t (- b a)) a)) (fn fract [x] (- x (math.floor x))) (fn dot [a b] (var s 0) (for [i 1 (length a) 1] (set s (+ s (* (. a i) (. b i))))) s) (global seed { :a (r 500 10000) :fx (r 500 10000) :fy (r 500 10000) :px (/ (r -500 500) 1000) :py (/ (r -500 500) 1000)}) (fn pseudor [x y] (fract (* (sin (dot [(+ x seed.px) (+ y seed.py)] [seed.fx seed.fy])) seed.a))) (fn perlin [x y] (mix (mix (pseudor (math.floor x) (math.floor y)) (pseudor (+ (math.floor x) 1) (math.floor y)) (fract x)) (mix (pseudor (math.floor x) (+ (math.floor y))) (pseudor (+ (math.floor x)) (+ (math.floor y))) (fract x)) (fract y))) (fn perlinf [x y] (local iterations 4) (var sum 0) (for [i 0 iterations 1] (set seed.a (+ 500 (* (fract (sin (* (+ i 0.512) 512 725.63))) 1000))) (set sum (+ sum (perlin (* x (+ i 1)) (* y (+ i 1)))))) (/ sum iterations)) (fn init-emitters [] (global *particle* { :x 0 :y 0 :scale 1 :lifetime 0  :sprite 0    :dspl 0  :speed { :x 0 :y 0 } } ) (tset *particle* :update (fn [self] (inc self.x (* self.speed.x *dt*)) (inc self.y (* self.speed.y *dt*)) (spr self.sprite self.x self.y 0 self.scale))) (global *bubble-particle* (deepcopy *particle*)) (tset *bubble-particle* :update (fn [self] (inc self.x (* self.speed.x (sin (+ (* *tick* 0.1) self.dspl)) 3 *dt*)) (inc self.y (* (- self.speed.y *cam*.speedy) *dt*)) (var id 19) (if (< self.lifetime 700) (set id 17) (< self.lifetime 1600) (set id 18)) (loop-spr id self.x self.y 1 1 0.8 15))) (global *pixel-particle* (deepcopy *particle*)) (tset *pixel-particle* :update (fn [self] (var color 11) (if (< self.lifetime 300) (set color 6) (< self.lifetime 600) (set color 8)) (inc self.x (* (- self.speed.x *cam*.speedx) *dt*)) (inc self.y (* (- self.speed.y *cam*.speedy) *dt*)) (pix self.x self.y color))) (global *bexplosion-particle* (deepcopy *particle*)) (tset *bexplosion-particle* :update (fn [self] (var color 11) (if (< self.lifetime 600) (set color 6)) (inc self.x (+ (* (- self.speed.x *cam*.speedx) *dt*) (sin (* 0.4 (+ *tick* self.speed.y))))) (inc self.y (* (+ self.speed.y *cam*.speedy) *dt*)) (pix self.x self.y color))) (global *pexplosion-particle* (deepcopy *particle*)) (tset *pexplosion-particle* :update (fn [self] (var color 11) (if (< self.lifetime 600) (set color 6)) (inc self.x (+ (* (- self.speed.x *cam*.speedx) *dt*) (sin (* 0.4 (+ *tick* self.speed.y))))) (inc self.y (* (+ self.speed.y *cam*.speedy) *dt*)) (pix self.x self.y color))) (global *bcexplosion-particle* (deepcopy *particle*)) (tset *bcexplosion-particle* :update (fn [self] (var color 15) (if (< self.lifetime 200) (set color 6) (< self.lifetime 400) (set color 7) (< self.lifetime 650) (set color 7)) (when (= (% *tick* 4) 0) (dec self.scale 2)) (dec self.x (* *cam*.speedx *dt*)) (circ self.x self.y self.scale color))) (global *cexplosion-particle* (deepcopy *particle*)) (tset *cexplosion-particle* :update (fn [self] (var color 12) (if (< self.lifetime 200) (set color 6) (< self.lifetime 400) (set color 8) (< self.lifetime 650) (set color 11)) (when (= (% *tick* 4) 0) (dec self.scale 2)) (dec self.x (* *cam*.speedx *dt*)) (circ self.x self.y self.scale color))) (global *particle-types* { :bcexplosion *bcexplosion-particle* :bexplosion *bexplosion-particle* :cexplosion *cexplosion-particle* :bubble *bubble-particle* :pixel *pixel-particle* :pexplosion *pexplosion-particle* }) (global *emitters* []) (global *emitter* { :x 0 :y 0  :sprites [ 0 ]  :emition-delay 10  :elapsed-since-emition 0  :pos-range { :xmin 0 :xmax 0 :ymin 0 :ymax 0 }  :speed-range { :xmin -100 :xmax 100 :ymin -100 :ymax 100 }  :scale-range { :min 1 :max 1 }  :lifetime-range { :min 500 :max 1000 }  :type :bubble  :modifier nil  :particle-modifier nil  :num-particles nil  :particles [] })  (tset *emitter* :emit (fn [self ?type] (var particle (deepcopy (. *particle-types* (or ?type self.type)))) (set particle.x (+ self.x (r self.pos-range.xmin self.pos-range.xmax))) (set particle.y (+ self.y (r self.pos-range.ymin self.pos-range.ymax))) (set particle.speed.x (r self.speed-range.xmin self.speed-range.xmax)) (set particle.speed.y (r self.speed-range.ymin self.speed-range.ymax)) (set particle.sprite (. self.sprites (r 1 (length self.sprites)))) (set particle.lifetime (r self.lifetime-range.min self.lifetime-range.max)) (set particle.scale (r self.scale-range.min self.scale-range.max)) (when self.particle-modifier (self:particle-modifier particle)) (table.insert self.particles (+ (length self.particles) 1) particle))) (tset *emitter* :update (fn [self] (if (>= self.elapsed-since-emition self.emition-delay) (do (self:emit) (set self.elapsed-since-emition 0)) (inc self.elapsed-since-emition (* *dt* 1000))) (when self.modifier (self:modifier self)) (each [i particle (ipairs self.particles)] (particle:update) (if (<= particle.lifetime 0) (table.remove self.particles i) (dec particle.lifetime (* *dt* 1000)))))) (tset *emitter* :clear (fn [self] (each [k (pairs self.particles)] (tset self.particles k nil)))) (global *cexplosion-emitter* (deepcopy *emitter*)) (set *cexplosion-emitter*.type :cexplosion) (global *bexplosion-emitter* (deepcopy *emitter*)) (set *bexplosion-emitter*.type :bexplosion) (set *bexplosion-emitter*.num-particles 7) (set *bexplosion-emitter*.lifetime-range { :min 700 :max 1000 }) (set *bexplosion-emitter*.scale-range { :min 3 :max 6 }) (set *bexplosion-emitter*.pos-range { :xmin 0 :xmax 6 :ymin 2 :ymax 8 }) (set *bexplosion-emitter*.speed-range { :xmin -5 :xmax 5 :ymin -50 :ymax -40 }) (tset *bexplosion-emitter* :update (fn [self] (when (> self.num-particles 0) (self:emit) (when (> self.num-particles 4) (self:emit :bcexplosion)) (dec self.num-particles)) (dec self.x (* *cam*.speedx *dt*)) (each [i particle (ipairs self.particles)] (particle:update) (if (<= particle.lifetime 0) (table.remove self.particles i) (dec particle.lifetime (* *dt* 1000)))))) (global *pexplosion-emitter* (deepcopy *emitter*)) (set *pexplosion-emitter*.type :pexplosion) (set *pexplosion-emitter*.num-particles 7) (set *pexplosion-emitter*.lifetime-range { :min 700 :max 1000 }) (set *pexplosion-emitter*.scale-range { :min 3 :max 6 }) (set *pexplosion-emitter*.pos-range { :xmin 0 :xmax 6 :ymin 2 :ymax 8 }) (set *pexplosion-emitter*.speed-range { :xmin -5 :xmax 5 :ymin -50 :ymax -40 }) (tset *pexplosion-emitter* :update (fn [self] (when (> self.num-particles 0) (self:emit) (when (> self.num-particles 4) (self:emit :cexplosion)) (dec self.num-particles)) (dec self.x (* *cam*.speedx *dt*)) (each [i particle (ipairs self.particles)] (particle:update) (if (<= particle.lifetime 0) (table.remove self.particles i) (dec particle.lifetime (* *dt* 1000)))))) (global *bubble-emitter* (deepcopy *emitter*)) (set *bubble-emitter*.emition-delay 300) (set *bubble-emitter*.type :bubble) (set *bubble-emitter*.lifetime-range { :min 3300 :max 3800 }) (set *bubble-emitter*.speed-range { :xmin -30 :xmax 30 :ymin -40 :ymax -20 }) (set *bubble-emitter*.particle-modifier (fn [particle] (set particle.dspl (r 0 100)))) (global *bg-bubbles* (deepcopy *bubble-emitter*)) (set *bg-bubbles*.x 120) (set *bg-bubbles*.y 136) (set *bg-bubbles*.pos-range { :xmin -120 :xmax 120 :ymin 0 :ymax 0 }) (global *motor-emitter* (deepcopy *emitter*)) (set *motor-emitter*.pos-range { :xmin 0 :xmax 0 :ymin 2 :ymax 4 }) (set *motor-emitter*.speed-range { :xmin -50 :xmax -10 :ymin -2 :ymax 2 }) (set *motor-emitter*.type :pixel) (set *motor-emitter*.modifier (fn [emitter] (set emitter.x (+ *player*.x 1)) (set emitter.y (+ *player*.y 2))))) (fn update-emitters [] (each [k emitter (ipairs *emitters*)] (emitter:update) (when (and (<= emitter.num-particles 0) (= (length emitter.particles) 0)) (table.remove *emitters* k)))) (fn init-cave-walls [] (global *pdspl* {:h1 (r 0 1000) :h2 (r 0 1000)}) (global last-h2 0) (global last-h1 0) (global *stalagmites* [136 137 138 139 140 141]) (global *stalagtites* [135 144 145 146 147 148 149 150]) (global ymin 0) (global ymax 5)) (fn pn [y] (math.round (+ ymin (* (perlinf y ymax) (- ymax ymin))))) (fn sn [y] (r ymin ymax)) (fn generate-cave-walls [from to f] (for [i from to 1] (let [h1 (math.min (- 15 last-h2) (f (+ i *pdspl*.h1 *last-block-generated*))) h2 (math.min (- 15 last-h1) (- 14 h1) (f (+ i *pdspl*.h2 *last-block-generated*)))] (global last-h1 h1) (global last-h2 h2) (for [j (- 17 h1) 17 1] (mset i j 128)) (for [j 0 (- h2 1) 1] (mset i j 128))))) (fn clear-map-block [block] (for [i (* block 30) (- (* (+ block 1) 30) 1) 1] (for [j 0  16] (mset i j 0)))) (fn get-surroundings-if-collidable [x y] (let [v (mget x y)] (when (> v 127) (values v                            (mget x (- y 1))             (mget (+ x 1) (- y 1))       (mget (+ x 1) y)             (mget (+ x 1) (+ y 1))       (mget x (+ y 1))             (mget (- x 1) (+ y 1))       (mget (- x 1) y)             (mget (- x 1) (- y 1))))))   (fn decorate-block [from to] (for [j 0 17 1] (for [i from to 1] (let [(v t tr r br b bl l tl) (get-surroundings-if-collidable i j)] (when (= v 128) (if (and (= l t r 0) (> j 0)) (mset i j 136) (and (= r t 0) (> j 0)) (mset i j 134) (and (= l t 0) (> j 0)) (mset i j 133) (and (= t 0) (= l 133) (= r 134) (> j 0)) (mset i j 136) (and (= t 0) (= r 0) (not= l 0) (not= b 0) (> j 0)) (mset i j 156) (and (= t 0) (= l 0) (not= r 0) (not= t 0) (> j 0)) (mset i j 157) (and (= t 0) (not= l 0) (not= r 0) (not= tr 0) (not= tl 0) (> j 0)) (mset i j 142) (and (= t 0) (> j 0)) (mset i j 153) (and (= t 134) (or (= r 0) (= r 134))) (mset i j 150) (and (= t 133) (or (= l 0) (= l 133))) (mset i j 149) (and (= l b r 0) (< j 17)) (mset i j 135) (and (= r b 0) (< j 17)) (mset i j 132) (and (= l b 0) (< j 17)) (mset i j 131) (and (= b 0) (= r 0)) (mset i j 159) (and (= b 0) (= l 0)) (mset i j 158) (and (= b 0) (not= l 0) (not= r 0) (not= br 0) (not= bl 0)) (mset i j 143) (and (= b 0) (< j 17)) (mset i j 152) (= l r 0) (mset i j 151) (or (= r 0) (and (>= r 131) (<= r 136))) (mset i j 155) (or (= l 0) (and (>= l 131) (<= l 136))) (mset i j 154))))))) (fn update-cave-walls [] (local current-block (// (math.abs *cam*.x) 240)) (local from (+ current-block 2)) (when (< *last-block-generated* from) (global n (r 0 100)) (if (and (< ymax 9) (<= n 35)) (incg ymax) (> ymax 2) (decg ymax)) (var noisef sn) (when (= (r 0 1) 0) (set noisef pn)) (global *last-block-generated* from) (when (> from 7) (clear-map-block (% from 8))) (global from-tile (* (% from 8) 30)) (global to-tile (- (* (+ (% from 8) 1) 30) 1)) (generate-cave-walls from-tile to-tile noisef) (if (= (% from 8) 0) (decorate-block 210 239) (decorate-block (- from-tile 30) (- to-tile 30))))) (fn get-next-index [animation-length current-index] (+ 1 (% current-index animation-length))) (fn get-animation-frame [animator] (. (. animator.animations animator.current-animation) animator.current-index)) (fn animate [object] (if (> object.animator.elapsed object.animator.speed) (do (tset object.animator :elapsed 0.0) (tset object.animator :current-index (get-next-index (length (. object.animator.animations object.animator.current-animation)) object.animator.current-index))) (tset object.animator :elapsed (+ object.animator.elapsed (* 1000.0 *dt*))))) (fn init-shots [] (global *basic-shot* { :x 0 :y 0 :w 5 :h 1 :speedx 2 :speedy 0 :damage 2 :spr 261 :rot 0 }) (global *blue-shot* { :x 0 :y 0 :w 8 :h 2 :speedx 8 :speedy 0 :damage 8 :spr 306 :flip 0 :rot 0 :curve 0 }) (tset *basic-shot* :update (fn [self] (inc self.y self.speedy) (inc self.x self.speedx) (out-of-bounds? self))) (tset *basic-shot* :draw (fn [self] (spr self.spr self.x self.y 0 1 0 self.rot))) (tset *blue-shot* :update (fn [self] (dec self.speedy (* self.curve *dt*)) (inc self.x self.speedx) (inc self.y self.speedy) (out-of-bounds? self))) (tset *blue-shot* :draw (fn [self] (spr self.spr self.x self.y 0 1 self.flip self.rot)))) (fn create-shot [type axis] (if (= type :basic-shot) (do (sfx 3 50 -1 3 7) (if (= axis :y) (do (local shot1 (deepcopy *basic-shot*)) (local shot2 (deepcopy *basic-shot*)) (set shot1.speedy shot1.speedx) (set shot1.rot 1) (set shot1.speedx 0) (set shot2.speedy (- 0 shot2.speedx)) (set shot2.rot 1) (set shot2.flip 1) (set shot2.speedx 0) [shot1 shot2]) (deepcopy *basic-shot*))) (= type :blue-shot) (do (sfx 3 20 -1 3 8 3) (if (= axis :y) (do (local shot1 (deepcopy *blue-shot*)) (local shot2 (deepcopy *blue-shot*)) (set shot1.speedy shot1.speedx) (set shot1.rot 1) (set shot1.speedx 0) (set shot2.speedy (- 0 shot2.speedx)) (set shot2.rot 3) (set shot2.flip 1) (set shot2.speedx 0) [shot1 shot2]) (deepcopy *blue-shot*))) (and (= type :triple-shot) (= axis :x)) (do (sfx 7 30 -1 3 8 3) (local shot1 (deepcopy *blue-shot*)) (set shot1.speedy 2) (set shot1.curve 2) (set shot1.spr 307) (set shot1.flip 2) (set shot1.damage 2) (local shot2 (deepcopy *blue-shot*)) (local shot3 (deepcopy *blue-shot*)) (set shot3.speedy -2) (set shot3.curve -2) (set shot3.spr 307) [shot1 shot2 shot3]))) (fn init-player [] (init-shots) (fn get-available-shots [] (local available-shots [ :basic-shot ]) (when (= (pmem 2) 1) (table.insert available-shots (+ (length available-shots) 1) :blue-shot)) (when (= (pmem 3) 1) (table.insert available-shots (+ (length available-shots) 1) :triple-shot)) available-shots) (global *player* { :x 32 :y 68 :w 8   :h 8 :vx 0  :vy 0 :shots [] :health 100 :state :none :hurt-timer 0 :points 0 :available-shots (get-available-shots) :current-shot :basic-shot :emitter (deepcopy *motor-emitter*) }) (set *player*.current-shot (. *player*.available-shots (length *player*.available-shots))) (tset *player* :animator { :current-animation :moving :current-index 1 :elapsed 0 :speed 100 }) (if (= *player*.current-shot :basic-shot) (set *player*.target-points 15) (= *player*.current-shot :blue-shot) (set *player*.target-points 50) (= *player*.current-shot :triple-shot) (set *player*.target-points 0)) (tset *player* :change-outfit (fn [self shot] (if (= shot :basic-shot) (do (set self.animator.animations { :moving [ 257 258 259 260 ] :hurt [ 257 256 258 256 259 256 260 256 ] })) (= shot :blue-shot) (do (set self.animator.animations { :moving [ 400 401 402 403 ] :hurt [ 400 256 401 256 402 256 403 256 ] })) (= shot :triple-shot) (do (set self.animator.animations { :moving [ 432 433 434 435 ] :hurt [ 432 256 433 256 434 256 435 256 ] }))))) (*player*:change-outfit *player*.current-shot) (tset *player* :update (fn [self] (if (= self.state :hurt) (do (when (< self.hurt-timer 0) (do (set self.state :none) (set self.animator.current-animation :moving))) (dec self.hurt-timer))) (set self.vx 0) (set self.vy 0) (when (btn 2) (set self.vx -1)) (when (btn 3) (set self.vx 1)) (when (btn 1) (set self.vy 1)) (when (btn 0) (set self.vy -1)) (var fx (- (+ self.x self.vx) (math.ceil *cam*.x))) (var fy (- (+ self.y self.vy) *cam*.y)) (var ni 0)  (while (and (< ni 5) (mcollides? fx fy self.w self.h)) (rcollision self) (set ni (+ ni 1)) (set fx (- (+ self.x self.vx) (math.ceil *cam*.x))) (set fy (- (+ self.y self.vy) *cam*.y))) (if (and (btnp 4 10 10) (not (btn 5))) (self:shoot :x) (btnp 5 10 10) (self:shoot :y)) (if (btnp 6) (set self.current-shot (self:change-shot :p)) (btnp 7) (set self.current-shot (self:change-shot :n))) (set self.x (+ self.x self.vx)) (set self.y (+ self.y self.vy)) (if (> (+ self.x self.w) +width+) (set self.x (- +width+ self.w)) (< self.x 0) (set self.x 0)) (if (> (+ self.y self.h) +height+) (set self.y (- +height+ self.h)) (< self.y 0) (set self.y 0)))) (set *player*.change-shot (fn [self dir] (var changed-shot self.current-shot) (each [k v (ipairs self.available-shots)] (when (= v self.current-shot) (sfx 5 30 -1 3 8 3) (set changed-shot (if (= dir :n) (. self.available-shots (+ (% k (length self.available-shots)) 1)) (= dir :p) (. self.available-shots (if (= k 1) (length self.available-shots) (- k 1))))))) (self:change-outfit changed-shot) changed-shot)) (tset *player* :draw (fn [self] (each [index shot (pairs self.shots)] (let [should-delete? (shot:update)] (shot:draw) (when should-delete? (table.remove self.shots index)))) (when (not (= self.state :dead)) (self.emitter:update) (animate self) (spr (get-animation-frame self.animator) self.x self.y 0)))) (fn store-shot [shot] (set shot.x *player*.x) (set shot.y (+ *player*.y 4 (r -2 2))) (table.insert *player*.shots (+ (length *player*.shots) 1) shot)) (tset *player* :shoot (fn [self axis] (let [shot-obj (create-shot self.current-shot axis)] (when shot-obj (if (> (length shot-obj) 1) (each [i shot (pairs shot-obj)] (store-shot shot)) (store-shot shot-obj)))))) (tset *player* :hurt (fn [self damage] (when (and (not= self.state :hurt) (not= *game-state* "game-over")) (dec self.health (math.max 1 (r (- damage 5) damage))) (if (<= self.health 0) (do (global *time-elapsed* 0) (set self.state :dead) (local emitter (deepcopy *pexplosion-emitter*)) (set emitter.x self.x) (set emitter.y self.y) (set emitter.num-particles 17) (set emitter.lifetime-range { :min 800 :max 1200 }) (set emitter.scale-range { :min 6 :max 9 }) (set emitter.pos-range { :xmin 0 :xmax 16 :ymin 2 :ymax 18 }) (table.insert *emitters* emitter) (sfx 4 30 -1 3 15 -1) (set *cam*.speedx 0) (music 1) (global *game-state* "game-over")) (do (sfx 4 60 -1 3 88) (global *shake* 18) (set self.animator.current-animation :hurt) (set self.state :hurt) (set self.hurt-timer 90)))))) (tset *player* :crush (fn [self] (self:hurt 105)))) (fn destroy-shot [index] (table.remove *player*.shots index)) (fn init-goods [] (global goods [])) (fn spawn-good [type x y] (let [good { :x (r (- (math.round x) 10) (+ (math.round x) 10)) :y (r (- (math.round y) 10) (+ (math.round y) 10)) :w 8 :h 8 :collected? false :type type :rfactor (r 0 100)}]  (when (= type :amethyst) (set good.animator { :current-animation :shining :current-index 1 :elapsed 0 :speed 60 :animations { :shining [ 277 277 277 277 277 277 277 277 277 288 289 290 291 278 ] } })) (table.insert goods (+ (length goods) 1) good))) (fn spawn-goods [x y points] (local rn (r 0 100)) (when (and (< rn 30) (< *player*.health 100)) (spawn-good :life x y)) (for [i 0 (r 0 points) 1] (spawn-good :amethyst x y))) (fn update-goods [] (each [index good (pairs goods)] (dec good.x (* *cam*.speedx *dt*)) (match good.type :amethyst (do (animate good) (spr (get-animation-frame good.animator) good.x (+ good.y (* (sin (* (+ *tick* good.rfactor) 0.05)) 2)) 0)) :life (spr 387 good.x (+ good.y (* (sin (* (+ *tick* good.rfactor) 0.05)) 2)) 0)) (when (bcollides? *player* good) (set good.collected? true) (match good.type :amethyst (do (sfx 5 70 -1 3 8 3) (inc *player*.points)) :life (do (sfx 8 64 -1 3 8 -2) (inc *player*.health (math.min 20 (- 100 *player*.health)))))) (when (or (< (+ good.x good.w) 0) good.collected?) (table.remove goods index)))) (fn spawn-enemy [type ?x ?y] (let [enemy (if (= type :simple-fish) (deepcopy *simple-fish*) (= type :ghost-fish) (deepcopy *ghost-fish*) (= type :stronger-fish) (deepcopy *stronger-fish*) (= type :shooter-fish) (deepcopy *shooter-fish*) (= type :energy-ball) (deepcopy *energy-ball*) (= type :follower) (deepcopy *follower*) (= type :anglerfish) (deepcopy *anglerfish*) (= type :snake) (deepcopy *snake*) (= type :snail) (deepcopy *snail*) (= type :easy-snail) (deepcopy *easy-snail*) (= type :guard) (deepcopy *guard*))] (tset enemy :type type) (tset enemy :x (or ?x (+ +width+ 8.0))) (tset enemy :y (or ?y (r 0 (- +height+ enemy.h)))) (table.insert *enemy-pool* enemy) enemy)) (fn init-enemies [] (global *enemy-types* [ :simple-fish :stronger-fish ]) (global *enemy* { :w 8 :h 8 :speedx 50 :speedy 0 :damage 2.0 :health 2.0 :points 1 :emitter :pexplosion :flicker 0 :no-flicker false }) (set *enemy*.animator { :current-animation :moving :current-index 1 :elapsed 0 :speed 150 :animations { :moving nil }}) (set *enemy*.update (fn [self] (inc self.y (* self.speedy *dt*)) (dec self.x (* self.speedx *dt*)))) (set *enemy*.draw (fn [self] (animate self) (if (and (> self.flicker 0) (< (% *tick* 5) 3)) (do (dec self.flicker)) (spr (get-animation-frame self.animator) self.x self.y 0)))) (global *simple-fish* (deepcopy *enemy*)) (set *simple-fish*.w 7) (set *simple-fish*.h 3) (set *simple-fish*.animator.animations.moving [ 292 293 294 293 292 295 296 295 ]) (set *simple-fish*.update (fn [self] (dec self.x (* (+ self.speedx *cam*.speedx) *dt*)) (inc self.y (* 0.2 (sin (* 0.05 (+ *tick* self.y))))))) (global *ghost-fish* (deepcopy *simple-fish*)) (set *ghost-fish*.damage 5) (set *ghost-fish*.animator.animations.moving [ 377 378 379 378 377 380 381 380 ]) (global *stronger-fish* (deepcopy *enemy*)) (set *stronger-fish*.speedx 30) (set *stronger-fish*.damage 5) (set *stronger-fish*.health 4) (set *stronger-fish*.points 1) (set *stronger-fish*.update (fn [self] (dec self.x (* (+ self.speedx *cam*.speedx) *dt*)) (inc self.y (* 0.5 (sin (* 0.05 (+ *tick* self.y))))))) (set *stronger-fish*.animator.animations.moving [ 273 274 275 276 275 274 ]) (global *shooter-fish* (deepcopy *stronger-fish*)) (set *shooter-fish*.speedx 20) (set *shooter-fish*.health 24) (set *shooter-fish*.damage 15) (set *shooter-fish*.animator.animations.moving [ 269 270 271 285 271 270 ]) (set *shooter-fish*.update (fn [self] (when (= (% (+ *tick* 40) 40) 0) (var ball (spawn-enemy :energy-ball self.x self.y)) (set ball.animator.animations.moving [ 264 308 309 308 ]) (set ball.animator.speed 50) (set ball.damage 20) (set ball.w 3) (set ball.h 3) (set ball.speedx (+ *cam*.speedx 80))) (dec self.x (* (+ self.speedx *cam*.speedx) *dt*)) (inc self.y (* 0.5 (sin (* 0.05 (+ *tick* self.y))))))) (global *energy-ball* (deepcopy *enemy*)) (set *energy-ball*.animator.animations.moving [ 265 323 324 ]) (set *energy-ball*.points 0) (set *energy-ball*.health 9999) (set *energy-ball*.speedx 130) (set *energy-ball*.damage 20) (set *energy-ball*.no-flicker true) (global *follower* (deepcopy *energy-ball*)) (set *follower*.speedx 200) (set *follower*.update (fn [self] (if (and (< self.y *player*.y) (> self.x *player*.x)) (set self.speedy 35) (and (> self.y *player*.y) (> self.x *player*.x)) (set self.speedy -35)) (inc self.y (* self.speedy *dt*)) (dec self.x (* self.speedx *dt*)))) (global *anglerfish* (deepcopy *enemy*)) (set *anglerfish*.w 32) (set *anglerfish*.h 32) (set *anglerfish*.points 100) (set *anglerfish*.damage 40) (set *anglerfish*.health 2000) (set *anglerfish*.shake true) (set *anglerfish*.boss? true) (set *anglerfish*.state :arriving) (set *anglerfish*.next-state :centering) (set *anglerfish*.tick 0) (set *anglerfish*.reposition-flag false) (set *anglerfish*.cattack nil) (set *anglerfish*.aframe 0) (set *anglerfish*.asfactor 1) (set *anglerfish*.attack-types [ :follow :energy :straight :pacifist ]) (set *anglerfish*.animator { :current-animation :moving :current-index 1 :elapsed 0 :speed 150 :animations { :moving [ 300 312 448 420 448 312 ] :attack [ 160 164 160 168 ] }}) (set *anglerfish*.draw (fn [self] (animate self) (if (and (> self.flicker 0) (< (% self.tick 5) 3)) (do (dec self.flicker)) (spr (get-animation-frame self.animator) self.x self.y 0 1 0 0 4 4)))) (set *anglerfish*.move (fn [self] (inc self.y (- (* 1.5 (sin (* 0.04 (+ self.tick 39)))) 0.0)))) (set *anglerfish*.finish-attack (fn [self] (set self.aframe 0) (set self.tick 0) (set self.cattack nil) (set self.reposition-flag false) (set self.state :centering) (set self.next-state :moving))) (set *anglerfish*.attack (fn [self] (when (not self.cattack) (set self.cattack (. self.attack-types (r 1 (length self.attack-types))))) (if (and (not self.reposition-flag) (or (= self.cattack :straight) (= self.cattack :follow))) (if (< self.y (- *player*.y 1)) (inc self.y (* 50 *dt*)) (> self.y (+ *player*.y 1)) (dec self.y (* 50 *dt*)) (set self.reposition-flag true)) (= self.cattack :follow) (do (when (= (% self.tick 100) 0) (spawn-enemy :follower self.x self.y) (set self.reposition-flag false)) (when (= (% self.tick 600) 0) (self:finish-attack))) (= self.cattack :straight) (do (when (= (% self.tick 150) 0) (global *shake* 0) (set self.reposition-flag false)) (when (= (% self.tick 3) 0) (local ball (spawn-enemy :energy-ball self.x self.y)) (set ball.speedx 500)) (global *shake* 5) (when (= (% self.tick 500) 0) (self:finish-attack))) (= self.cattack :energy) (do (self:move) (when (= (% self.tick (math.round (* 15 self.asfactor))) 0) (sfx 3 20 -1 3 8 3) (spawn-enemy :energy-ball self.x (+ self.y (/ self.h 2)))) (when (= (% self.tick 500) 0) (self:finish-attack))) (= self.cattack :pacifist) (self:finish-attack)))) (set *anglerfish*.update (fn [self] (inc self.tick) (when (not= self.state :arriving) (global *boss-life* (math.max 0 self.health))) (when (and (< self.health 1000) (> self.asfactor 0.5)) (set self.asfactor 0.8)) (if (= self.state :arriving) (if (< self.tick 200) (when (> *cam*.speedx 15) (set *cam*.speedx 15)) (do (when (< *cam*.speedx 50) (set *cam*.speedx 50)) (when (< self.x 200) (set self.state :centering) (set self.next-state :moving)) (dec self.x (* 60 *dt*)))) (= self.state :attack) (do (when (not (= self.animator.current-animation :attack)) (set self.animator.current-animation :attack)) (when (= (% self.tick 30) 0) (local emitter (deepcopy *bexplosion-emitter*)) (set emitter.x (+ self.x 9)) (set emitter.y (+ self.y 12)) (table.insert *emitters* emitter)) (self:attack)) (= self.state :centering) (do (if (< (+ self.y (/ self.h 2)) 65) (inc self.y (* 40 *dt*)) (> (+ self.y (/ self.h 2)) 71) (dec self.y (* 40 *dt*)) (do (set self.tick 0) (set self.state self.next-state)))) (= self.state :moving) (do (when (not (= self.animator.current-animation :moving)) (set self.animator.current-animation :moving)) (when (= (% self.tick 15) 0)  (local rn (r 0 100)) (when (< rn 40) (local enemy (spawn-enemy :stronger-fish self.x (+ self.y 16))) (set enemy.health 16))) (when (= (% self.tick 400) 0) (self:finish-attack) (set self.state :centering) (set self.next-state :attack)) (self:move))))) (global *snake* (deepcopy *enemy*)) (set *snake*.length 30) (set *snake*.animator.animations.moving [ 368 374 371 374 ]) (set *snake*.animator.speedx 100) (set *snake*.speedx 100) (set *snake*.health 100) (set *snake*.damage 30) (set *snake*.draw (fn [self] (var bindex 1)  (local aindex (if (< (% *tick* 32) 8) 0 (< (% *tick* 32) 16) 2 (< (% *tick* 32) 24) 1 2))  (spr (+ 368 aindex) self.x self.y 0) (for [i 1 self.length 1] (spr (+ 371 aindex) (+ self.x (* bindex 8)) self.y 0) (inc bindex)) (spr (+ 374 aindex) (+ self.x (* bindex 8)) self.y 0))) (set *snake*.update (fn [self] (when (< self.w (* (+ self.length 2) 8)) (set self.w (* (+ self.length 2) 8))) (dec self.x (* (+ self.speedx *cam*.speedx) *dt*)))) (global *snail* (deepcopy *enemy*)) (set *snail*.animator.animations.moving [ 266 ]) (set *snail*.health 12) (set *snail*.damage 40) (set *snail*.draw (fn [self] (animate self) (spr (get-animation-frame self.animator) self.x self.y 0 1 0 0 1 2))) (set *snail*.update (fn [self] (when ( = (% (+ *tick* (math.round self.y)) 70) 0) (var ball (spawn-enemy :energy-ball self.x self.y)) (set ball.animator.animations.moving [ 264 308 309 308 ]) (set ball.animator.speed 50) (set ball.damage 20) (set ball.w 3) (set ball.h 3) (set ball.speedx (- self.x *player*.x)) (set ball.speedy (- *player*.y self.y))) (dec self.x (* *cam*.speedx *dt*)))) (global *easy-snail* (deepcopy *snail*)) (set *easy-snail*.animator.animations.moving [ 338 ]) (set *easy-snail*.health 12) (set *easy-snail*.damage 30) (set *easy-snail*.update (fn [self] (when ( = (% (+ *tick* (math.round self.y)) 70) 0) (var ball (spawn-enemy :energy-ball self.x self.y)) (set ball.animator.animations.moving [ 264 308 309 308 ]) (set ball.animator.speed 50) (set ball.damage 20) (set ball.w 3) (set ball.h 3) (set ball.speedx *cam*.speedx) (set ball.speedy -40)) (dec self.x (* *cam*.speedx *dt*)))) (global *guard* (deepcopy *enemy*)) (set *guard*.animator.animations.moving [ 304 ]) (set *guard*.health 10) (set *guard*.tick 0) (set *guard*.update (fn [self] (inc self.tick) (when ( = (% self.tick 60) 0) (var ball (spawn-enemy :energy-ball self.x self.y)) (set ball.animator.animations.moving [ 264 308 309 308 ]) (set ball.animator.speed 50) (set ball.damage 7) (set ball.w 3) (set ball.h 3) (set ball.speedx (+ *cam*.speedx 20))) (set self.y (+ 68 (* 50 (sin (* 0.03 *tick*))))) (dec self.x (* *cam*.speedx *dt*)))) (global *enemy-pool* [])) (fn spawn-snail [?enemy] (when (< ymax 9) (local camtile (% (math.abs (math.round (// *cam*.x 8))) 240)) (var found-tile false) (for [i (+ camtile 30) (+ camtile 60) 1] (for [j 10 16 1] (when (and (> (mget i j) 127) (= (mget i (- j 1)) 0) (not= i *last-snail-x*)) (spawn-enemy (or ?enemy :snail) (- (* (- i camtile -1) 8) (% (math.abs *cam*.x) 8)) (+ (* (- j 1) 8) 4)) (global *last-snail-x* i) (set found-tile true) (lua :break))) (when found-tile (lua :break))))) (fn destroy-enemy [index] (table.remove *enemy-pool* index)) (fn update-enemies [] (each [index enemy (pairs *enemy-pool*)] (enemy:update) (enemy:draw) (when (bcollides? *player* enemy) (*player*:hurt enemy.damage)) (each [shot-index shot (pairs *player*.shots)] (when (bcollides? shot enemy) (dec enemy.health shot.damage) (when (and (> enemy.health 0) (not enemy.no-flicker)) (set enemy.flicker 18) (sfx 4 33 4 3 6)) (destroy-shot shot-index) (when (and enemy.shake (= *shake* 0)) (global *shake* 5)))) (when (or (< (+ enemy.x enemy.w) -8.0) (> enemy.x 480) (< enemy.y -200) (> enemy.y (+ +height+ 200)) (<= enemy.health 0)) (when (<= enemy.health 0) (when enemy.boss? (global *boss-killed* true)) (sfx 4 12 -1 3 6) (local emitter (match enemy.emitter :pexplosion (deepcopy *pexplosion-emitter*) :cexplosion (deepcopy *cexplosion-emitter*))) (set emitter.x enemy.x) (set emitter.y enemy.y) (table.insert *emitters* emitter) (spawn-goods (math.max enemy.x 60) (+ enemy.y (/ enemy.h 2)) enemy.points)) (destroy-enemy index)))) (fn init-enemy-spawners [] (global *spawners* {}) (global *active-spawners* 0) (global *spawner* { :enemy :simple-fish :delay 30 :duration 5 :finished false }) (global *last-snail-x* 0) (set *spawner*.update (fn [self ?delay ?x ?y ?enemy] (when (= (% *tick* (or ?delay self.delay)) 0) (spawn-enemy (or ?enemy self.enemy) ?x ?y)) (if (< self.duration 0) (set self.finished true) (dec self.duration *dt*)))) (global *fish-spawner* (deepcopy *spawner*)) (global *ghost-fish-spawner* (deepcopy *spawner*)) (set *ghost-fish-spawner*.enemy :ghost-fish) (global *stronger-fish-spawner* (deepcopy *fish-spawner*)) (set *stronger-fish-spawner*.enemy :stronger-fish) (set *stronger-fish-spawner*.delay 55) (global *snail-spawner* (deepcopy *spawner*)) (set *snail-spawner*.enemy :snail) (set *snail-spawner*.delay 250) (set *snail-spawner*.duration 15) (set *snail-spawner*.update (fn [self ?delay] (when (= (% *tick* (or delay self.delay)) 0) (spawn-snail self.enemy)) (if (< self.duration 0) (set self.finished true) (dec self.duration *dt*)))) (global *easy-snail-spawner* (deepcopy *snail-spawner*)) (set *easy-snail-spawner*.enemy :easy-snail) (global *shooter-fish-spawner* (deepcopy *spawner*)) (set *shooter-fish-spawner*.enemy :shooter-fish) (set *shooter-fish-spawner*.delay 180) (global *snake-spawner* (deepcopy *spawner*)) (set *snake-spawner*.enemy :snake) (set *snake-spawner*.delay 180) (global *guard-spawner* (deepcopy *spawner*)) (set *guard-spawner*.enemy :guard) (set *guard-spawner*.update (fn [self] (when (= (% *tick* 150) 0) (spawn-enemy :guard) (set self.finished true)))) (global *easy-spawners* [ :fish :stronger-fish :guard :easy-snail ]) (global *medium-spawners* [ :guard :snail :snake :shooter-fish :ghost-fish ]) (global *wave-counter* 0)) (fn camr [from to] (and (> *cam*.x to) (< *cam*.x from))) (fn get-spawner [type] (match type :fish (deepcopy *fish-spawner*) :ghost-fish (deepcopy *ghost-fish-spawner*) :stronger-fish (deepcopy *stronger-fish-spawner*) :shooter-fish (deepcopy *shooter-fish-spawner*) :snake (deepcopy *snake-spawner*) :guard (deepcopy *guard-spawner*) :easy-snail (deepcopy *easy-snail-spawner*) :snail (deepcopy *snail-spawner*))) (fn add-spawner [spawners] (local spw (. spawners (r 1 (length spawners)))) (when (= (. *spawners* spw) nil) (incg *active-spawners*) (tset *spawners* spw (get-spawner spw)))) (fn update-enemy-spawners [] (when (and (< *cam*.speedx *cam*.max-speed) (= (% *tick* 400) 0)) (inc *cam*.speedx)) (if (= *enemy-wave* :easy-wave) (do (when (< *active-spawners* 2) (add-spawner *easy-spawners*)) (each [k spawner (pairs *spawners*)] (spawner:update) (when spawner.finished (decg *active-spawners*) (tset *spawners* k nil))) (when (< *cam*.x -2000) (global *enemy-wave* :medium-wave))) (= *enemy-wave* :medium-wave) (do (when (< *active-spawners* 2) (add-spawner *medium-spawners*)) (each [k spawner (pairs *spawners*)] (spawner:update) (when spawner.finished (decg *active-spawners*) (tset *spawners* k nil))) (when (< *cam*.x -4000) (each [k spawner (pairs *spawners*)] (decg *active-spawners*) (tset *spawners* k nil)) (global *enemy-wave* :boss-wave))) (= *enemy-wave* :boss-wave) (do (if *boss-killed* (do (global *enemy-wave* :none) (global *time-elapsed* 0) (global *game-state* "win")) (> *cam*.x -4600) (do (when (> *cam*.speedx 20) (set *cam*.speedx 20)) (when (< *active-spawners* 2) (add-spawner [:fish :stronger-fish])) (each [k spawner (pairs *spawners*)] (spawner:update) (when spawner.finished (decg *active-spawners*) (tset *spawners* k nil)))) (<= (length *enemy-pool*) 0) (spawn-enemy :anglerfish))) (= *enemy-wave* :first-wave) (do (when (and (< *cam*.x -100) (= (% *tick* 200) 0)) (incg *wave-counter* 9)) (if (and (< *cam*.x -30) (> *cam*.x -100)) (*fish-spawner*:update 80 nil (+ 68 (r -40 40))) (and (< *cam*.x -100) (> *cam*.x -700)) (do (*fish-spawner*:update (- 100 *wave-counter*)) (*fish-spawner*:update (- 120 *wave-counter*) nil nil :stronger-fish)) (< *cam*.x -700) (do (global *wave-counter* 0) (global *enemy-wave* :easy-wave)))))) (fn draw-cave-bg [pfactor] (if (> map-offset-y 0) (do (spr 11 230 (+ map-offset-y 120) 0 1 0 0 2 4) (spr 8 180 (+ map-offset-y 40) 0 1 0 0 1 2) (spr 11 100 (+ map-offset-y 70) 0 1 0 0 5 5) (spr 9 50 (+ map-offset-y 100) 0 1 0 0 4 4) (spr 8 100 (+ map-offset-y 110) 0 1 0 0 1 2) (spr 9 190 (+ map-offset-y 100) 0 1 0 0 7 5) (spr 8 140 (+ map-offset-y 100) 0 1 0 0 1 2) (spr 11 280 (+ map-offset-y 70) 0 1 0 0 5 5) (spr 9 120 (+ map-offset-y 68) 0 1 0 0 2 3)) (do (loop-spr 11 230 120 2 4 pfactor) (loop-spr 8 180 40 1 2 pfactor) (loop-spr 11 100 70 5 5 pfactor) (loop-spr 9 50 100 4 4 pfactor) (loop-spr 8 100 110 1 2 pfactor) (loop-spr 9 190 100 7 5 pfactor) (loop-spr 8 140 100 1 2 pfactor) (loop-spr 11 280 70 5 5 pfactor) (loop-spr 9 120 68 2 3 pfactor)))) (fn draw-algae [pfactor] (local positions [ 0 15 32 39 47 56 62 79 83 98 107 113 125 132 147 153 165 169 177 182 189 198 213 224 232 240  ]) (local sprites [ 51 54 51 52 52 53 54 51 54 53 51 53 51 53 54 52 54 52 51 53 54 52 54 51 52 54 ]) (for [i 1 26 1] (local pos (. positions i)) (if (> map-offset-y 0) (spr (. sprites i) pos (+ 136 (% pos 8) map-offset-y) 0 1 (% pos 2) 0 1 5) (loop-spr (. sprites i) pos (+ 136 (% pos 8)) 1 5 pfactor 0 (% pos 2))))) (fn draw-bg [] (draw-cave-bg 0.1) (draw-algae 0.6) (*bg-bubbles*:update)) (fn draw-healthbar [x y n] (spr 387 x (+ y 3) 0) (spr 384 (+ x 3) y 0 1 0 0 2 1) (for [i 2 5 1] (spr 385 (+ x (* 8 i) 3) y 0 1 0 0 1 1)) (spr 385 (+ x 42 3) y 0 1 0 0 2 1) (spr 384 (+ x 3) (+ y 5) 0 1 2 0 2 1) (for [i 2 5 1] (spr 385 (+ x (* 8 i) 3) (+ y 5) 0 1 2 0 1 1)) (spr 385 (+ x 42 3) (+ y 5) 0 1 2 0 2 1) (when (> n 0) (var fill-color 1) (when (< n 10) (set fill-color 9)) (for [j y (+ y 4) 1] (for [i (+ x 3) (+ x 3 n -1) 1] (pix (+ i 4) (+ j 4) fill-color))))) (fn draw-shot-icons [x y] (if (= *player*.current-shot :basic-shot) (spr 388 x y 0) (spr 395 x y 0)) (if (has-element? *player*.available-shots :blue-shot) (if (= *player*.current-shot :blue-shot) (spr 389 (+ x 8) y 0) (spr 396 (+ x 8) y 0)) (spr 392 (+ x 8) y 0)) (if (has-element? *player*.available-shots :triple-shot) (if (= *player*.current-shot :triple-shot) (spr 390 (+ x 16) y 0) (spr 397 (+ x 16) y 0)) (spr 393 (+ x 16) y 0))) (fn draw-boss-healthbar [x y] (when (and (> *boss-life* 0) (not *boss-killed*)) (spr 407 x (+ y 2) 0) (spr 404 (+ x 3) y 0 1 0 0 2 1) (for [i 2 27 1] (spr 405 (+ x (* 8 i) 3) y 0 1 0 0 1 1)) (spr 406 (+ x (* 28 8) 2) y 0 1 0 0 1 1) (spr 404 (+ x 3) (+ y 3) 0 1 2 0 2 1) (for [i 2 27 1] (spr 405 (+ x (* 8 i) 3) (+ y 3) 0 1 2 0 1 1)) (spr 406 (+ x (* 28 8) 2) (+ y 3) 0 1 2 0 1 1) (when (> *boss-life* 0) (var fill-color 7) (for [j y (+ y 2) 1] (for [i (+ x 3) (+ x 3 (math.round (/ *boss-life* 8.968609)) -1) 1] (pix (+ i 4) (+ j 4) fill-color)))))) (fn draw-hud [] (spr 277 5 13 0) (if (> *player*.target-points 0) (print (.. *player*.points (.. "/" *player*.target-points)) 15 13 12) (print *player*.points 15 13 12)) (draw-healthbar 5 0 (// *player*.health 2)) (draw-shot-icons 65 3) (draw-boss-healthbar 5 (- 136 10))) (fn draw-game [] (cls) (local txcam (// (math.abs *cam*.x) 8)) (local tycam (// (math.abs *cam*.y) 8)) (map txcam tycam 31 18 (- 0 (% (math.abs *cam*.x) 8)) (- 0 (% (math.abs *cam*.y) 8)) 0) (update-goods) (*player*:draw) (update-enemies) (update-emitters) (draw-hud)) (fn update-camera [] (set *cam*.ox (- *cam*.ox (* *cam*.speedx *dt*))) (set *cam*.x (+ *cam*.ox *cam*.offsetx)) (set *cam*.y (+ *cam*.oy *cam*.offsety))) (fn update-game [] (when (not= map-offset-y 0) (global map-offset-y 0)) (update-camera) (update-cave-walls) (when (> *shake* 0) (set *cam*.offsetx (r -2 2)) (set *cam*.offsety (r -2 2)) (poke 0x3FF9 (r 0 1)) (poke (+ 0x3FF9 1) (r 0 1)) (decg *shake*) (when (= *shake* 0) (memset 0x3FF9 0 2) (set *cam*.offsety 0) (set *cam*.offsetx 0))) (*player*:update) (update-enemy-spawners)) (global *icosahedron* []) (global *t-icosahedron* []) (fn minz [t] (math.min (. (. t 1) 3) (. (. t 2) 3) (. (. t 3) 3))) (fn sum-tri [t] (+ (. (. t 1) 3) (. (. t 2) 3) (. (. t 3) 3))) (global +fov+ 120) (fn compute-icosahedron-vertices [radius] (local hangle (* (/ math.pi 180) 72)) (local vangle (math.atan (/ 1 2))) (local vertices []) (var i1 0) (var i2 0) (var z 0) (var xy 0) (var hangle1 (- (/ -3.141592 2) (/ hangle 2))) (var hangle2 (/ -3.141592 2)) (tset vertices 0 0) (tset vertices 1 radius) (tset vertices 2 0) (for [i 1 5 1] (set i1 (* i 3)) (set i2 (* (+ i 5) 3)) (set z (* radius (sin vangle))) (set xy (* radius (cos vangle))) (tset vertices i1 (* xy (cos hangle1))) (tset vertices i2 (* xy (cos hangle2))) (tset vertices (+ i1 1) z) (tset vertices (+ i2 1) (- 0 z)) (tset vertices (+ i1 2) (* xy (sin hangle1))) (tset vertices (+ i2 2) (* xy (sin hangle2))) (inc hangle1 hangle) (inc hangle2 hangle)) (set i1 (* 11 3)) (tset vertices i1 0) (tset vertices (+ i1 1) (- 0 radius)) (tset vertices (+ i1 2) 0) vertices) (fn getv3 [arr i] (local v []) (tset v 1 (. arr i)) (tset v 2 (. arr (+ i 1))) (tset v 3 (. arr (+ i 2))) v) (fn convert-3d-2d [ox oy oz] (local v []) (tset v 0 (+ (* ox (/ +fov+ (+ oz 20))) (/ +width+ 2))) (tset v 1 (+ (* oy (/ +fov+ (+ oz 20))) (/ +height+ 2))) v) (fn draw-tri [vertices color] (local xo (/ +width+ 2)) (local yo (/ +height+ 2)) (local v1-3d (. vertices 1)) (local v2-3d (. vertices 2)) (local v3-3d (. vertices 3)) (local v1 (. vertices 1)) (local v2 (. vertices 2)) (local v3 (. vertices 3)) (tri (+ (. v1 1) xo) (+ (. v1 2) yo) (+ (. v2 1) xo) (+ (. v2 2) yo) (+ (. v3 1) xo) (+ (. v3 2) yo) color)) (fn build-icosahedron-triangles [] (local tmp-verts (compute-icosahedron-vertices 40)) (var v0 []) (var v1 []) (var v2 []) (var v3 []) (var v4 []) (var v11 []) (var index 0) (set v0 (getv3 tmp-verts 0)) (set v11 (getv3 tmp-verts (* 11 3))) (for [i 1 5 1] (set v1 (getv3 tmp-verts (* i 3))) (if (< i 5) (set v2 (getv3 tmp-verts (* (+ i 1) 3))) (set v2 (getv3 tmp-verts 3))) (set v3 (getv3 tmp-verts (* (+ i 5) 3))) (if (< i 5) (set v4 (getv3 tmp-verts (* (+ i 6) 3))) (set v4 (getv3 tmp-verts (* 6 3)))) (table.insert *icosahedron* [v0 v1 v2 index]) (table.insert *icosahedron* [v1 v3 v2 (+ index 1)]) (table.insert *icosahedron* [v2 v3 v4 (+ index 2)]) (table.insert *icosahedron* [v3 v11 v4 (+ index 3)]) (inc index 4))) (fn sort-icosahedron [] (table.sort *t-icosahedron* (fn [a b] (if (< (minz b) (minz a)) true (> (minz b) (minz a)) false (if (< (sum-tri b) (sum-tri a)) true false))))) (fn rotate-point [point g b a] (local px (. point 1)) (local py (. point 2)) (local pz (. point 3)) (local newpoint [(+ (* px (cos a) (cos b)) (* py (- (* (cos a) (sin b) (sin g)) (* (sin a) (cos g)))) (* pz (+ (* (cos a) (sin b) (cos g)) (* (sin a) (sin g))))) (+ (* px (* (sin a) (cos b))) (* py (+ (* (sin a) (sin b) (sin g)) (* (cos a) (cos g)))) (* pz (- (* (sin a) (sin b) (cos g)) (* (cos a) (sin g))))) (+ (* px (- 0 (sin b))) (* py (cos b) (sin g)) (* pz (cos b) (cos g)))]) newpoint) (fn rotate-icosahedron [x y z] (each [i triangle (pairs *icosahedron*)] (var new-triangle []) (for [j 1 3 1] (table.insert new-triangle (rotate-point (. triangle j) x y z))) (table.insert new-triangle (. triangle 4)) (tset *t-icosahedron* i new-triangle))) (fn translate-point [point x y z] (local px (. point 1)) (local py (. point 2)) (local pz (. point 3)) (local newpoint [(+ px x) (+ py y) (+ pz z)]) newpoint) (fn translate-icosahedron [x y z] (each [i triangle (pairs *icosahedron*)] (var new-triangle []) (for [j 1 3 1] (table.insert new-triangle (translate-point (. triangle j) x y z))) (table.insert new-triangle (. triangle 4)) (tset *t-icosahedron* i new-triangle))) (fn transform-icosahedron [r t] (each [i triangle (pairs *icosahedron*)] (var new-triangle []) (for [j 1 3 1] (table.insert new-triangle (translate-point (rotate-point (. triangle j) r.x r.y r.z) t.x t.y t.z))) (table.insert new-triangle (. triangle 4)) (tset *t-icosahedron* i new-triangle))) (fn get-tri-color [triangle] (local p1 (. triangle 1)) (local p2 (. triangle 2)) (local p3 (. triangle 3)) (if (and (< (math.min (. p1 1) (. p2 1) (. p3 1)) 0) (< (math.max (. p1 2) (. p2 2) (. p3 2)) 20)) 0)) (fn draw-icosahedron [] (for [index 1 (length *t-icosahedron*) 1] (local triangle (. *t-icosahedron* index)) (local color-id (% (. triangle 4) 5)) (var color 7) (match color-id 0 (set color 8) 1 (set color 14) 2 (set color 15) 3 (set color 0)) (draw-tri triangle color))) (fn init-icosahedron [] (build-icosahedron-triangles) (sort-icosahedron) (global *t-icosahedron* (deepcopy *icosahedron*))) (fn ico-r [offset] (- 0xff (math.abs (math.round (* 150 (sin (* (+ *tick* offset) 0.01))))))) (fn ico-g [offset] (+ 0x00 (math.abs (math.round (* 50 (sin (* (+ *tick* offset) 0.07))))))) (fn ico-b [offset] (- 0x88 (math.abs (math.round (* 50 (sin (* (+ *tick* offset) 0.07))))))) (fn ico-pal [i offset] (pal i (ico-r offset) (ico-g offset) (ico-b offset))) (fn update-icosahedron [?offset-y] (ico-pal 7 0) (ico-pal 0 100) (ico-pal 15 200) (ico-pal 8 50) (ico-pal 14 150) (pal 6 (- 0x2a (math.abs (math.round (* 16 (sin (* *tick* 0.01)))))) (- 0x37 (math.abs (math.round (* 27 (sin (* *tick* 0.01)))))) (- 0x58 (math.abs (math.round (* 55 (sin (* *tick* 0.01))))))) (transform-icosahedron { :x (* (/ math.pi 4) *elapsed*) :y (* (/ math.pi 2) *elapsed*) :z 0 } { :x 0 :y (- (* 3 (sin (* *tick* 0.05))) (or ?offset-y 0)) :z 0 }) (sort-icosahedron)) (fn ease-in-back [x] (- (* 2.70158 x x x) (* 1.70158 x x))) (fn ease-in-out-cubic [x] (if (< x 0.5) (* 4 x x x) (- 1 (/ (math.pow (+ (* -2 x) 2) 3) 2)))) (fn update-menu [] (cls 5) (*bg-bubbles*:update) (print "AMETHYST WATERS" (* 4 8) (* 3 8) 12 true 2) (print "AMETHYST WATERS" (- (* 4 8) 1) (* 3 8) 12 true 2) (print "AMETHYST WATERS" (* 4 8) (- (* 3 8) 1) 12 true 2) (local acc (math.round (ease-in-out-cubic (* 5 *elapsed*)))) (if (< acc 230) (pal 12 (+ 0x0c acc) (+ 0x0c acc) (+ 0x10 acc)) (pal 12 0xf2 0xf4 0xf6)) (update-icosahedron) (draw-icosahedron) (when (< (% *tick* 60) 30) (print "- Press Z to play the game -" (* 6 8) (+ (* 12 8) 6) 12)) (when (btnp 4) (sfx 5 55 -1 3 6 -2) (global *time-elapsed* -1.0) (pal 12 0xf2 0xf4 0xf6) (set *player*.x -10) (global *initial-time* (time)) (global *game-state* "t-menu-game"))) (fn t-menu-game [] (cls 5) (global map-offset-y 196) (var particle-speed 0) (var title-speed 0) (var ico-speed 0) (var message-speed 0) (var message-delay 15) (when (> *time-elapsed* 0.0) (global map-offset-y (- 236 (* 180 (ease-in-back (* 0.5 *time-elapsed*))))) (when (< map-offset-y 0) (global map-offset-y 0)) (set particle-speed (* 8 (ease-in-back (* 0.5 *time-elapsed*)))) (set title-speed (* 200 (ease-in-back (* 0.5 *time-elapsed*)))) (set ico-speed (* 260 (ease-in-back (* 0.5 *time-elapsed*)))) (set message-speed (* 300 (ease-in-back (* 0.5 *time-elapsed*)))) (set message-delay 10)) (rect 0 map-offset-y 240 136 0) (draw-bg) (*bg-bubbles*:update) (when (> map-offset-y 0) (each [k part (pairs *bg-bubbles*.particles)] (dec part.y particle-speed))) (print "AMETHYST WATERS" (* 4 8) (- (* 3 8) title-speed) 12 true 2) (print "AMETHYST WATERS" (- (* 4 8) 1) (- (* 3 8) title-speed) 12 true 2) (print "AMETHYST WATERS" (* 4 8) (- (* 3 8) 1 title-speed) 12 true 2) (update-icosahedron ico-speed) (draw-icosahedron) (when (< (% *tick* message-delay) 10) (print "- Press Z to play the game -" (* 6 8) (- (+ (* 12 8) 6) message-speed) 12)) (local txcam (// (math.abs *cam*.x) 8)) (local tycam (// (math.abs *cam*.y) 8)) (when (< map-offset-y 138) (pal 0 0x14 0x14 0x28) (pal 7 0x8e 0x2e 0x91) (pal 8 0x3c 0x40 0x55) (pal 14 0x20 0x18 0x34) (pal 15 0xf6 0x61 0xba) (pal 6 0x20 0x2d 0x51)) (if (<= map-offset-y 0) (do (set *bg-bubbles*.emition-delay 1000) (set *player*.y 68) (if (>= *player*.x 32) (do (music 0) (global *game-state* "game")) (inc *player*.x (* 60 *dt*)))) (do (set *player*.y (+ 68 map-offset-y)))) (update-emitters)) (fn init [] (init-emitters) (init-icosahedron) (music 1) (init-player) (init-cave-walls) (init-enemies) (init-enemy-spawners) (init-goods) (poke 0x03FF8 5) (global +width+ 240.0) (global +height+ 136.0) (global *dt* 0.0) (global *previous-time* (time)) (global *tick* 0) (global *t-tick* 0) (global *elapsed* 0) (global *time-elapsed* 0) (global *cam* { :x 0 :y 0 :ox 0 :oy 0 :speedx 20 :speedy 0 :max-speed 200 :offsetx 0 :offsety 0 }) (global *last-block-generated* 0) (global *max-wall-y* 6) (for [i 0 13 1] (mset i 0 152) (mset i 16 153)) (generate-cave-walls 14 59 pn) (decorate-block 14 59) (global map-offset-y 196) (global *shake* 0) (global *enemy-wave* :first-wave) (global *boss-life* -1) (global *boss-killed* false) (global *music-playing* true) (global highscore-flag false) (global *game-state* "menu")) (fn update-win-screen [] (cls 5) (when (not *music-playing*) (global *music-playing* true) (music 1)) (local title-string "YOU WON!!!") (local width (print title-string 0 -16 12 true 2)) (print title-string (// (- 240 width) 2) (* 2 8) 12 true 2) (print title-string (- (// (- 240 width) 2) 1) (* 2 8) 12 true 2) (print title-string (// (- 240 width) 2) (- (* 2 8) 1) 12 true 2) (local middle-text ["You explored the Amethyst Waters." (.. "And look! You collected " *player*.points " amethysts!")]) (for [i 1 (length middle-text) 1] (local width (print (. middle-text i) 0 -16)) (print (. middle-text i) (// (- 240 width) 2) (+ 60 (* 8 (- (* i 1.5) 1))) 15)) (local bottom-string "Press Z to go back to the title screen.") (local width (print bottom-string 0 -16 12)) (print "Press Z to go back to the title screen" (// (- 240 width) 2) (+ (* 13 8) 6) 12) (when (btnp 4) (global *icosahedron* []) (global *t-icosahedron* []) (init-icosahedron) (for [i 0 7] (clear-map-block i)) (init) (global *initial-time* (time)) (global *game-state* "menu"))) (fn update-game-over [] (if (< *time-elapsed* 2) (draw-bg) (do (cls 5) (local title-string "YOU CRASHED") (print title-string (- 256 (* (length title-string) 16)) (* 2 8) 12 true 2) (print title-string (- (- 256 (* (length title-string) 16)) 1) (* 2 8) 12 true 2) (print title-string (- 256 (* (length title-string) 16)) (- (* 2 8) 1) 12 true 2) (spr 288 32 21 0) (print (.. "x " *player*.points) 42 21 12) (var middle-text []) (var icon nil) (var padding 0) (if (and (= *player*.target-points 15) (>= *player*.points 15)) (do (when (not= (pmem 2) 1) (pmem 2 1)) (set icon 389) (set middle-text [ "YOU UNLOCKED A NEW WEAPON!" "Press A or S to change weapons." ])) (and (= *player*.target-points 50) (>= *player*.points 20)) (do (when (not= (pmem 3) 1) (pmem 3 1)) (set icon 390) (set middle-text [ "YOU UNLOCKED A NEW WEAPON!" "Press A or S to change weapons." ])) (< *player*.points *player*.target-points) (set middle-text [(.. "Get " *player*.target-points " amethysts") "to unlock your next weapon!"]) (set middle-text ["You have superpowers!!"])) (when icon (spr icon 114 44 0 2) (set padding 8)) (for [i 1 (length middle-text) 1] (local width (print (. middle-text i) 0 -16)) (print (. middle-text i) (// (- 240 width) 2) (+ 60 padding (* 8 (- i 1))) 15)) (print "Press Z to test your skills again!" 32 (+ (* 13 8) 6) 12) (when (btnp 4) (for [i 0 7] (clear-map-block i)) (init) (music 0) (global *initial-time* (time)) (global *game-state* "game"))))) (global TIC  (fn [] (global *dt* (/ (- (time) *previous-time*) 1000.0)) (global *previous-time* (time)) (incg *time-elapsed* *dt*) (incg *tick*) (incg *elapsed* *dt*) (if (= *game-state* "game") (do (update-game) (draw-bg)) (= *game-state* "menu") (update-menu) (= *game-state* "t-menu-game") (t-menu-game) (= *game-state* "win") (if (< *time-elapsed* 10) (do (when (> *cam*.speedx 10) (set *cam*.speedx 10)) (if *music-playing* (global *music-playing* false) (music)) (when (= (% *tick* 45) 0) (sfx 9 (r 20 30) -1 0 10 0) (local emitter (deepcopy *pexplosion-emitter*)) (set emitter.x (r 10 230)) (set emitter.y (r 10 126)) (set emitter.scale-range { :min 10 :max 40 }) (table.insert *emitters* emitter)) (draw-bg) (update-game)) (update-win-screen)) (= *game-state* "game-over") (update-game-over)))) (global OVR (fn [] (if (= *game-state* "game") (draw-game) (or (and (= *game-state* "game-over") (< *time-elapsed* 2)) (and (= *game-state* "win") (< *time-elapsed* 10))) (draw-game) (= *game-state* "t-menu-game") (do (if (<= map-offset-y 0) (map txcam tycam 31 18 (- 0 (% (math.abs *cam*.x) 8)) 0 0) (map txcam tycam 31 18 (- 0 (% (math.abs *cam*.x) 8)) map-offset-y 0)) (*player*:draw))))) (global scanline (fn [row] (if (= *game-state* "game") (poke 0x3ff9 (* (sin (+ (/ (time) 200) (/ row 5))) 2.2)) (or (and (= *game-state* "game-over") (< *time-elapsed* 2)) (and (= *game-state* "win") (< *time-elapsed* 10)) (and (= *game-state* "t-menu-game") (< map-offset-y 138))) (poke 0x3ff9 (* (sin (+ (/ (time) 200) (/ row 5))) 2.2))))) (init) 
(macros {:inc (fn [a ?n] `(set ,a (+ ,a (or ,?n 1)))) :dec (fn [a ?n] `(set ,a (- ,a (or ,?n 1)))) :decg (fn [a ?n] `(global ,a (- ,a (or ,?n 1)))) :incg (fn [a ?n] `(global ,a (+ ,a (or ,?n 1))))}) (fn sin [a] (math.sin a)) (fn cos [a] (math.cos a)) (fn pal [i r g b] (if (and (not r) (not g) (not b)) (values (peek (+ 0x3fc0 (* i 3))) (peek (+ 0x3fc0 (* i 3) 1)) (peek (+ 0x3fc0 (* i 3) 2))) (do (var rc r) (var gc g) (var bc b) (when (or (not rc) (< rc 0)) (set rc 0)) (when (or (not gc) (< gc 0)) (set gc 0)) (when (or (not bc) (< bc 0)) (set bc 0)) (when (> rc 255) (set rc 255)) (when (> gc 255) (set gc 255)) (when (> bc 255) (set bc 255)) (poke (+ 0x3fc0 (* i 3) 2) b) (poke (+ 0x3fc0 (* i 3) 1) g) (poke (+ 0x3fc0 (* i 3)) r)))) (fn out-of-bounds? [object] (or (< object.x 0) (< object.y 0) (> (+ object.x object.w) +width+) (> (+ object.y object.h) +height+))) (fn parallax [p0 factor axis] (if (= axis :x) (+ p0 (* *cam*.x factor)) (= axis :y) (+ p0 (* *cam*.y factor)))) (fn loop-spr [id x y w h pfactor ?colorkey ?flip] (spr id (- (% (parallax x pfactor :x) (+ 240 (* w 8))) (* w 8)) (- (% (parallax y pfactor :y) (+ 136 (* h 8))) (* h 8)) (or ?colorkey 0) 1 (or ?flip 0) 0 w h)) (fn r [a b] (math.random a b)) (fn rvalue [l] (. l (r 1 (length l)))) (fn has-element? [l e] (var found false) (each [k v (pairs l)] (when (= v e) (set found true) (lua :break))) found) (fn sign [x] (if (> x 0) 1 (< x 0) -1 0)) (fn bcollides? [a b] (and (< a.x (+ b.x b.w)) (> (+ a.x a.w) b.x) (< a.y (+ b.y b.h)) (> (+ a.y a.h) b.y))) (fn mcollides? [x y w h] (or (> (mget (// (% x 1920) 8) (// y 8)) 127)                        (> (mget (// (+ (% x 1920) (- w 1)) 8) (// y 8)) 127)            (> (mget (// (% x 1920) 8) (// (+ y (- h 1)) 8)) 127)                  (> (mget (// (+ (% x 1920) (- w 1)) 8) (// (+ y (- h 1)) 8)) 127)))    (fn mcollisions [obj] (let [x (- (+ obj.x obj.vx) (math.ceil *cam*.ox)) y (- (+ obj.y obj.vy) *cam*.oy) w obj.w h obj.h] (values (> (mget (// (% x 1920) 8) (// y 8)) 127)                        (> (mget (// (+ (% x 1920) (- w 1)) 8) (// y 8)) 127)            (> (mget (// (% x 1920) 8) (// (+ y (- h 1)) 8)) 127)                  (> (mget (// (+ (% x 1920) (- w 1)) 8) (// (+ y (- h 1)) 8)) 127))))   (fn rcollision [obj] (let [(tl tr bl br) (mcollisions obj)] (local ox (- (+ obj.x obj.vx) (math.ceil *cam*.ox))) (local oy (- (+ obj.y obj.vy) (math.ceil *cam*.oy))) (local ow (- (+ obj.x obj.vx obj.w) (math.ceil *cam*.ox))) (local oh (- (+ obj.y obj.vy obj.h) *cam*.oy)) (var sy 0)  (var ix 0)  (var iy 0)  (var in 0)  (when tl (inc in)) (when tr (inc in)) (when bl (inc in)) (when br (inc in)) (when (and (= in 4) (<= obj.x 1) obj.crush) (obj:crush)) (if (or tr br) (set ix (math.abs (- ow (* 8 (// ow 8))))) (or tl bl) (set ix (math.abs (- ox (* 8 (// (+ ox 8) 8)))))) (if (or br bl) (do (set iy (math.abs (- oh (* (// oh 8) 8)))) (set sy -1)) (or tr tl) (do (set iy (math.abs (- (* (+ (// oy 8) 1) 8) oy))) (set sy 1))) (when (and (= ix 0) (or tl tr bl br)) (set ix 8)) (when (and (= iy 0) (or tl tr bl br)) (set iy 8)) (if (and (or tl tr) (> ix iy)) (set obj.vy (+ obj.vy iy))  (and (or br tr) (> iy ix)) (set obj.vx (- obj.vx ix))  (and (or bl br) (> ix iy)) (set obj.vy (- obj.vy iy))  (and (or tl bl) (> iy ix)) (set obj.vx (+ obj.vx ix))  (and (> in 2) (= iy ix)) (do (set obj.vx 0) (set obj.vy 0))  (and (= iy ix)) (do (set obj.vy (+ obj.vy (* iy sy))))  (do (trace "bad collision") (set obj.vx 0) (set obj.vy 0))))) (fn math.round [n] (math.floor (+ n 0.5))) (fn deepcopy [orig] (var orig-type (type orig)) (var copy nil) (if (= orig-type "table") (do (set copy {}) (each [key value (pairs orig)] (tset copy (deepcopy key) (deepcopy value))) (setmetatable copy (deepcopy (getmetatable orig)))) (set copy orig)) copy) (fn mix [a b t] (+ (* t (- b a)) a)) (fn fract [x] (- x (math.floor x))) (fn dot [a b] (var s 0) (for [i 1 (length a) 1] (set s (+ s (* (. a i) (. b i))))) s) (global seed { :a (r 500 10000) :fx (r 500 10000) :fy (r 500 10000) :px (/ (r -500 500) 1000) :py (/ (r -500 500) 1000)}) (fn pseudor [x y] (fract (* (sin (dot [(+ x seed.px) (+ y seed.py)] [seed.fx seed.fy])) seed.a))) (fn perlin [x y] (mix (mix (pseudor (math.floor x) (math.floor y)) (pseudor (+ (math.floor x) 1) (math.floor y)) (fract x)) (mix (pseudor (math.floor x) (+ (math.floor y))) (pseudor (+ (math.floor x)) (+ (math.floor y))) (fract x)) (fract y))) (fn perlinf [x y] (local iterations 4) (var sum 0) (for [i 0 iterations 1] (set seed.a (+ 500 (* (fract (sin (* (+ i 0.512) 512 725.63))) 1000))) (set sum (+ sum (perlin (* x (+ i 1)) (* y (+ i 1)))))) (/ sum iterations)) (fn init-emitters [] (global *particle* { :x 0 :y 0 :scale 1 :lifetime 0  :sprite 0    :dspl 0  :speed { :x 0 :y 0 } } ) (tset *particle* :update (fn [self] (inc self.x (* self.speed.x *dt*)) (inc self.y (* self.speed.y *dt*)) (spr self.sprite self.x self.y 0 self.scale))) (global *bubble-particle* (deepcopy *particle*)) (tset *bubble-particle* :update (fn [self] (inc self.x (* self.speed.x (sin (+ (* *tick* 0.1) self.dspl)) 3 *dt*)) (inc self.y (* (- self.speed.y *cam*.speedy) *dt*)) (var id 19) (if (< self.lifetime 700) (set id 17) (< self.lifetime 1600) (set id 18)) (loop-spr id self.x self.y 1 1 0.8 15))) (global *pixel-particle* (deepcopy *particle*)) (tset *pixel-particle* :update (fn [self] (var color 11) (if (< self.lifetime 300) (set color 6) (< self.lifetime 600) (set color 8)) (inc self.x (* (- self.speed.x *cam*.speedx) *dt*)) (inc self.y (* (- self.speed.y *cam*.speedy) *dt*)) (pix self.x self.y color))) (global *bexplosion-particle* (deepcopy *particle*)) (tset *bexplosion-particle* :update (fn [self] (var color 11) (if (< self.lifetime 600) (set color 6)) (inc self.x (+ (* (- self.speed.x *cam*.speedx) *dt*) (sin (* 0.4 (+ *tick* self.speed.y))))) (inc self.y (* (+ self.speed.y *cam*.speedy) *dt*)) (pix self.x self.y color))) (global *pexplosion-particle* (deepcopy *particle*)) (tset *pexplosion-particle* :update (fn [self] (var color 11) (if (< self.lifetime 600) (set color 6)) (inc self.x (+ (* (- self.speed.x *cam*.speedx) *dt*) (sin (* 0.4 (+ *tick* self.speed.y))))) (inc self.y (* (+ self.speed.y *cam*.speedy) *dt*)) (pix self.x self.y color))) (global *bcexplosion-particle* (deepcopy *particle*)) (tset *bcexplosion-particle* :update (fn [self] (var color 15) (if (< self.lifetime 200) (set color 6) (< self.lifetime 400) (set color 7) (< self.lifetime 650) (set color 7)) (when (= (% *tick* 4) 0) (dec self.scale 2)) (dec self.x (* *cam*.speedx *dt*)) (circ self.x self.y self.scale color))) (global *cexplosion-particle* (deepcopy *particle*)) (tset *cexplosion-particle* :update (fn [self] (var color 12) (if (< self.lifetime 200) (set color 6) (< self.lifetime 400) (set color 8) (< self.lifetime 650) (set color 11)) (when (= (% *tick* 4) 0) (dec self.scale 2)) (dec self.x (* *cam*.speedx *dt*)) (circ self.x self.y self.scale color))) (global *particle-types* { :bcexplosion *bcexplosion-particle* :bexplosion *bexplosion-particle* :cexplosion *cexplosion-particle* :bubble *bubble-particle* :pixel *pixel-particle* :pexplosion *pexplosion-particle* }) (global *emitters* []) (global *emitter* { :x 0 :y 0  :sprites [ 0 ]  :emition-delay 10  :elapsed-since-emition 0  :pos-range { :xmin 0 :xmax 0 :ymin 0 :ymax 0 }  :speed-range { :xmin -100 :xmax 100 :ymin -100 :ymax 100 }  :scale-range { :min 1 :max 1 }  :lifetime-range { :min 500 :max 1000 }  :type :bubble  :modifier nil  :particle-modifier nil  :num-particles nil  :particles [] })  (tset *emitter* :emit (fn [self ?type] (var particle (deepcopy (. *particle-types* (or ?type self.type)))) (set particle.x (+ self.x (r self.pos-range.xmin self.pos-range.xmax))) (set particle.y (+ self.y (r self.pos-range.ymin self.pos-range.ymax))) (set particle.speed.x (r self.speed-range.xmin self.speed-range.xmax)) (set particle.speed.y (r self.speed-range.ymin self.speed-range.ymax)) (set particle.sprite (. self.sprites (r 1 (length self.sprites)))) (set particle.lifetime (r self.lifetime-range.min self.lifetime-range.max)) (set particle.scale (r self.scale-range.min self.scale-range.max)) (when self.particle-modifier (self:particle-modifier particle)) (table.insert self.particles (+ (length self.particles) 1) particle))) (tset *emitter* :update (fn [self] (if (>= self.elapsed-since-emition self.emition-delay) (do (self:emit) (set self.elapsed-since-emition 0)) (inc self.elapsed-since-emition (* *dt* 1000))) (when self.modifier (self:modifier self)) (each [i particle (ipairs self.particles)] (particle:update) (if (<= particle.lifetime 0) (table.remove self.particles i) (dec particle.lifetime (* *dt* 1000)))))) (tset *emitter* :clear (fn [self] (each [k (pairs self.particles)] (tset self.particles k nil)))) (global *cexplosion-emitter* (deepcopy *emitter*)) (set *cexplosion-emitter*.type :cexplosion) (global *bexplosion-emitter* (deepcopy *emitter*)) (set *bexplosion-emitter*.type :bexplosion) (set *bexplosion-emitter*.num-particles 7) (set *bexplosion-emitter*.lifetime-range { :min 700 :max 1000 }) (set *bexplosion-emitter*.scale-range { :min 3 :max 6 }) (set *bexplosion-emitter*.pos-range { :xmin 0 :xmax 6 :ymin 2 :ymax 8 }) (set *bexplosion-emitter*.speed-range { :xmin -5 :xmax 5 :ymin -50 :ymax -40 }) (tset *bexplosion-emitter* :update (fn [self] (when (> self.num-particles 0) (self:emit) (when (> self.num-particles 4) (self:emit :bcexplosion)) (dec self.num-particles)) (dec self.x (* *cam*.speedx *dt*)) (each [i particle (ipairs self.particles)] (particle:update) (if (<= particle.lifetime 0) (table.remove self.particles i) (dec particle.lifetime (* *dt* 1000)))))) (global *pexplosion-emitter* (deepcopy *emitter*)) (set *pexplosion-emitter*.type :pexplosion) (set *pexplosion-emitter*.num-particles 7) (set *pexplosion-emitter*.lifetime-range { :min 700 :max 1000 }) (set *pexplosion-emitter*.scale-range { :min 3 :max 6 }) (set *pexplosion-emitter*.pos-range { :xmin 0 :xmax 6 :ymin 2 :ymax 8 }) (set *pexplosion-emitter*.speed-range { :xmin -5 :xmax 5 :ymin -50 :ymax -40 }) (tset *pexplosion-emitter* :update (fn [self] (when (> self.num-particles 0) (self:emit) (when (> self.num-particles 4) (self:emit :cexplosion)) (dec self.num-particles)) (dec self.x (* *cam*.speedx *dt*)) (each [i particle (ipairs self.particles)] (particle:update) (if (<= particle.lifetime 0) (table.remove self.particles i) (dec particle.lifetime (* *dt* 1000)))))) (global *bubble-emitter* (deepcopy *emitter*)) (set *bubble-emitter*.emition-delay 300) (set *bubble-emitter*.type :bubble) (set *bubble-emitter*.lifetime-range { :min 3300 :max 3800 }) (set *bubble-emitter*.speed-range { :xmin -30 :xmax 30 :ymin -40 :ymax -20 }) (set *bubble-emitter*.particle-modifier (fn [particle] (set particle.dspl (r 0 100)))) (global *bg-bubbles* (deepcopy *bubble-emitter*)) (set *bg-bubbles*.x 120) (set *bg-bubbles*.y 136) (set *bg-bubbles*.pos-range { :xmin -120 :xmax 120 :ymin 0 :ymax 0 }) (global *motor-emitter* (deepcopy *emitter*)) (set *motor-emitter*.pos-range { :xmin 0 :xmax 0 :ymin 2 :ymax 4 }) (set *motor-emitter*.speed-range { :xmin -50 :xmax -10 :ymin -2 :ymax 2 }) (set *motor-emitter*.type :pixel) (set *motor-emitter*.modifier (fn [emitter] (set emitter.x (+ *player*.x 1)) (set emitter.y (+ *player*.y 2))))) (fn update-emitters [] (each [k emitter (ipairs *emitters*)] (emitter:update) (when (and (<= emitter.num-particles 0) (= (length emitter.particles) 0)) (table.remove *emitters* k)))) (fn init-cave-walls [] (global *pdspl* {:h1 (r 0 1000) :h2 (r 0 1000)}) (global last-h2 0) (global last-h1 0) (global *stalagmites* [136 137 138 139 140 141]) (global *stalagtites* [135 144 145 146 147 148 149 150]) (global ymin 0) (global ymax 5)) (fn pn [y] (math.round (+ ymin (* (perlinf y ymax) (- ymax ymin))))) (fn sn [y] (r ymin ymax)) (fn generate-cave-walls [from to f] (for [i from to 1] (let [h1 (math.min (- 15 last-h2) (f (+ i *pdspl*.h1 *last-block-generated*))) h2 (math.min (- 15 last-h1) (- 14 h1) (f (+ i *pdspl*.h2 *last-block-generated*)))] (global last-h1 h1) (global last-h2 h2) (for [j (- 17 h1) 17 1] (mset i j 128)) (for [j 0 (- h2 1) 1] (mset i j 128))))) (fn clear-map-block [block] (for [i (* block 30) (- (* (+ block 1) 30) 1) 1] (for [j 0  16] (mset i j 0)))) (fn get-surroundings-if-collidable [x y] (let [v (mget x y)] (when (> v 127) (values v                            (mget x (- y 1))             (mget (+ x 1) (- y 1))       (mget (+ x 1) y)             (mget (+ x 1) (+ y 1))       (mget x (+ y 1))             (mget (- x 1) (+ y 1))       (mget (- x 1) y)             (mget (- x 1) (- y 1))))))   (fn decorate-block [from to] (for [j 0 17 1] (for [i from to 1] (let [(v t tr r br b bl l tl) (get-surroundings-if-collidable i j)] (when (= v 128) (if (and (= l t r 0) (> j 0)) (mset i j 136) (and (= r t 0) (> j 0)) (mset i j 134) (and (= l t 0) (> j 0)) (mset i j 133) (and (= t 0) (= l 133) (= r 134) (> j 0)) (mset i j 136) (and (= t 0) (= r 0) (not= l 0) (not= b 0) (> j 0)) (mset i j 156) (and (= t 0) (= l 0) (not= r 0) (not= t 0) (> j 0)) (mset i j 157) (and (= t 0) (not= l 0) (not= r 0) (not= tr 0) (not= tl 0) (> j 0)) (mset i j 142) (and (= t 0) (> j 0)) (mset i j 153) (and (= t 134) (or (= r 0) (= r 134))) (mset i j 150) (and (= t 133) (or (= l 0) (= l 133))) (mset i j 149) (and (= l b r 0) (< j 17)) (mset i j 135) (and (= r b 0) (< j 17)) (mset i j 132) (and (= l b 0) (< j 17)) (mset i j 131) (and (= b 0) (= r 0)) (mset i j 159) (and (= b 0) (= l 0)) (mset i j 158) (and (= b 0) (not= l 0) (not= r 0) (not= br 0) (not= bl 0)) (mset i j 143) (and (= b 0) (< j 17)) (mset i j 152) (= l r 0) (mset i j 151) (or (= r 0) (and (>= r 131) (<= r 136))) (mset i j 155) (or (= l 0) (and (>= l 131) (<= l 136))) (mset i j 154))))))) (fn update-cave-walls [] (local current-block (// (math.abs *cam*.x) 240)) (local from (+ current-block 2)) (when (< *last-block-generated* from) (global n (r 0 100)) (if (and (< ymax 9) (<= n 35)) (incg ymax) (> ymax 2) (decg ymax)) (var noisef sn) (when (= (r 0 1) 0) (set noisef pn)) (global *last-block-generated* from) (when (> from 7) (clear-map-block (% from 8))) (global from-tile (* (% from 8) 30)) (global to-tile (- (* (+ (% from 8) 1) 30) 1)) (generate-cave-walls from-tile to-tile noisef) (if (= (% from 8) 0) (decorate-block 210 239) (decorate-block (- from-tile 30) (- to-tile 30))))) (fn get-next-index [animation-length current-index] (+ 1 (% current-index animation-length))) (fn get-animation-frame [animator] (. (. animator.animations animator.current-animation) animator.current-index)) (fn animate [object] (if (> object.animator.elapsed object.animator.speed) (do (tset object.animator :elapsed 0.0) (tset object.animator :current-index (get-next-index (length (. object.animator.animations object.animator.current-animation)) object.animator.current-index))) (tset object.animator :elapsed (+ object.animator.elapsed (* 1000.0 *dt*))))) (fn init-shots [] (global *basic-shot* { :x 0 :y 0 :w 5 :h 1 :speedx 2 :speedy 0 :damage 2 :spr 261 :rot 0 }) (global *blue-shot* { :x 0 :y 0 :w 8 :h 2 :speedx 8 :speedy 0 :damage 8 :spr 306 :flip 0 :rot 0 :curve 0 }) (tset *basic-shot* :update (fn [self] (inc self.y self.speedy) (inc self.x self.speedx) (out-of-bounds? self))) (tset *basic-shot* :draw (fn [self] (spr self.spr self.x self.y 0 1 0 self.rot))) (tset *blue-shot* :update (fn [self] (dec self.speedy (* self.curve *dt*)) (inc self.x self.speedx) (inc self.y self.speedy) (out-of-bounds? self))) (tset *blue-shot* :draw (fn [self] (spr self.spr self.x self.y 0 1 self.flip self.rot)))) (fn create-shot [type axis] (if (= type :basic-shot) (do (sfx 3 50 -1 3 7) (if (= axis :y) (do (local shot1 (deepcopy *basic-shot*)) (local shot2 (deepcopy *basic-shot*)) (set shot1.speedy shot1.speedx) (set shot1.rot 1) (set shot1.speedx 0) (set shot2.speedy (- 0 shot2.speedx)) (set shot2.rot 1) (set shot2.flip 1) (set shot2.speedx 0) [shot1 shot2]) (deepcopy *basic-shot*))) (= type :blue-shot) (do (sfx 3 20 -1 3 8 3) (if (= axis :y) (do (local shot1 (deepcopy *blue-shot*)) (local shot2 (deepcopy *blue-shot*)) (set shot1.speedy shot1.speedx) (set shot1.rot 1) (set shot1.speedx 0) (set shot2.speedy (- 0 shot2.speedx)) (set shot2.rot 3) (set shot2.flip 1) (set shot2.speedx 0) [shot1 shot2]) (deepcopy *blue-shot*))) (and (= type :triple-shot) (= axis :x)) (do (sfx 7 30 -1 3 8 3) (local shot1 (deepcopy *blue-shot*)) (set shot1.speedy 2) (set shot1.curve 2) (set shot1.spr 307) (set shot1.flip 2) (set shot1.damage 2) (local shot2 (deepcopy *blue-shot*)) (local shot3 (deepcopy *blue-shot*)) (set shot3.speedy -2) (set shot3.curve -2) (set shot3.spr 307) [shot1 shot2 shot3]))) (fn init-player [] (init-shots) (fn get-available-shots [] (local available-shots [ :basic-shot ]) (when (= (pmem 2) 1) (table.insert available-shots (+ (length available-shots) 1) :blue-shot)) (when (= (pmem 3) 1) (table.insert available-shots (+ (length available-shots) 1) :triple-shot)) available-shots) (global *player* { :x 32 :y 68 :w 8   :h 8 :vx 0  :vy 0 :shots [] :health 100 :state :none :hurt-timer 0 :points 0 :available-shots (get-available-shots) :current-shot :basic-shot :emitter (deepcopy *motor-emitter*) }) (set *player*.current-shot (. *player*.available-shots (length *player*.available-shots))) (tset *player* :animator { :current-animation :moving :current-index 1 :elapsed 0 :speed 100 }) (if (= *player*.current-shot :basic-shot) (set *player*.target-points 15) (= *player*.current-shot :blue-shot) (set *player*.target-points 50) (= *player*.current-shot :triple-shot) (set *player*.target-points 0)) (tset *player* :change-outfit (fn [self shot] (if (= shot :basic-shot) (do (set self.animator.animations { :moving [ 257 258 259 260 ] :hurt [ 257 256 258 256 259 256 260 256 ] })) (= shot :blue-shot) (do (set self.animator.animations { :moving [ 400 401 402 403 ] :hurt [ 400 256 401 256 402 256 403 256 ] })) (= shot :triple-shot) (do (set self.animator.animations { :moving [ 432 433 434 435 ] :hurt [ 432 256 433 256 434 256 435 256 ] }))))) (*player*.change-outfit *player* *player*.current-shot) (tset *player* :update (fn [self] (if (= self.state :hurt) (do (when (< self.hurt-timer 0) (do (set self.state :none) (set self.animator.current-animation :moving))) (dec self.hurt-timer))) (set self.vx 0) (set self.vy 0) (when (btn 2) (set self.vx -1)) (when (btn 3) (set self.vx 1)) (when (btn 1) (set self.vy 1)) (when (btn 0) (set self.vy -1)) (var fx (- (+ self.x self.vx) (math.ceil *cam*.x))) (var fy (- (+ self.y self.vy) *cam*.y)) (var ni 0)  (while (and (< ni 5) (mcollides? fx fy self.w self.h)) (rcollision self) (set ni (+ ni 1)) (set fx (- (+ self.x self.vx) (math.ceil *cam*.x))) (set fy (- (+ self.y self.vy) *cam*.y))) (if (and (btnp 4 10 10) (not (btn 5))) (self:shoot :x) (btnp 5 10 10) (self:shoot :y)) (if (btnp 6) (set self.current-shot (self:change-shot :p)) (btnp 7) (set self.current-shot (self:change-shot :n))) (set self.x (+ self.x self.vx)) (set self.y (+ self.y self.vy)) (if (> (+ self.x self.w) +width+) (set self.x (- +width+ self.w)) (< self.x 0) (set self.x 0)) (if (> (+ self.y self.h) +height+) (set self.y (- +height+ self.h)) (< self.y 0) (set self.y 0)))) (set *player*.change-shot (fn [self dir] (var changed-shot self.current-shot) (each [k v (ipairs self.available-shots)] (when (= v self.current-shot) (sfx 5 30 -1 3 8 3) (set changed-shot (if (= dir :n) (. self.available-shots (+ (% k (length self.available-shots)) 1)) (= dir :p) (. self.available-shots (if (= k 1) (length self.available-shots) (- k 1))))))) (self:change-outfit changed-shot) changed-shot)) (tset *player* :draw (fn [self] (each [index shot (pairs self.shots)] (let [should-delete? (shot:update)] (shot:draw) (when should-delete? (table.remove self.shots index)))) (when (not (= self.state :dead)) (self.emitter:update) (animate self) (spr (get-animation-frame self.animator) self.x self.y 0)))) (fn store-shot [shot] (set shot.x *player*.x) (set shot.y (+ *player*.y 4 (r -2 2))) (table.insert *player*.shots (+ (length *player*.shots) 1) shot)) (tset *player* :shoot (fn [self axis] (let [shot-obj (create-shot self.current-shot axis)] (when shot-obj (if (> (length shot-obj) 1) (each [i shot (pairs shot-obj)] (store-shot shot)) (store-shot shot-obj)))))) (tset *player* :hurt (fn [self damage] (when (and (not= self.state :hurt) (not= *game-state* "game-over")) (dec self.health (math.max 1 (r (- damage 5) damage))) (if (<= self.health 0) (do (global *time-elapsed* 0) (set self.state :dead) (local emitter (deepcopy *pexplosion-emitter*)) (set emitter.x self.x) (set emitter.y self.y) (set emitter.num-particles 17) (set emitter.lifetime-range { :min 800 :max 1200 }) (set emitter.scale-range { :min 6 :max 9 }) (set emitter.pos-range { :xmin 0 :xmax 16 :ymin 2 :ymax 18 }) (table.insert *emitters* emitter) (sfx 4 30 -1 3 15 -1) (set *cam*.speedx 0) (music 1) (global *game-state* "game-over")) (do (sfx 4 60 -1 3 88) (global *shake* 18) (set self.animator.current-animation :hurt) (set self.state :hurt) (set self.hurt-timer 90)))))) (tset *player* :crush (fn [self] (self:hurt 105)))) (fn destroy-shot [index] (table.remove *player*.shots index)) (fn init-goods [] (global goods [])) (fn spawn-good [type x y] (let [good { :x (r (- (math.round x) 10) (+ (math.round x) 10)) :y (r (- (math.round y) 10) (+ (math.round y) 10)) :w 8 :h 8 :collected? false :type type :rfactor (r 0 100)}]  (when (= type :amethyst) (set good.animator { :current-animation :shining :current-index 1 :elapsed 0 :speed 60 :animations { :shining [ 277 277 277 277 277 277 277 277 277 288 289 290 291 278 ] } })) (table.insert goods (+ (length goods) 1) good))) (fn spawn-goods [x y points] (local rn (r 0 100)) (when (and (< rn 30) (< *player*.health 100)) (spawn-good :life x y)) (for [i 0 (r 0 points) 1] (spawn-good :amethyst x y))) (fn update-goods [] (each [index good (pairs goods)] (dec good.x (* *cam*.speedx *dt*)) (match good.type :amethyst (do (animate good) (spr (get-animation-frame good.animator) good.x (+ good.y (* (sin (* (+ *tick* good.rfactor) 0.05)) 2)) 0)) :life (spr 387 good.x (+ good.y (* (sin (* (+ *tick* good.rfactor) 0.05)) 2)) 0)) (when (bcollides? *player* good) (set good.collected? true) (match good.type :amethyst (do (sfx 5 70 -1 3 8 3) (inc *player*.points)) :life (do (sfx 8 64 -1 3 8 -2) (inc *player*.health (math.min 20 (- 100 *player*.health)))))) (when (or (< (+ good.x good.w) 0) good.collected?) (table.remove goods index)))) (fn spawn-enemy [type ?x ?y] (let [enemy (if (= type :simple-fish) (deepcopy *simple-fish*) (= type :ghost-fish) (deepcopy *ghost-fish*) (= type :stronger-fish) (deepcopy *stronger-fish*) (= type :shooter-fish) (deepcopy *shooter-fish*) (= type :energy-ball) (deepcopy *energy-ball*) (= type :follower) (deepcopy *follower*) (= type :anglerfish) (deepcopy *anglerfish*) (= type :snake) (deepcopy *snake*) (= type :snail) (deepcopy *snail*) (= type :easy-snail) (deepcopy *easy-snail*) (= type :guard) (deepcopy *guard*))] (tset enemy :type type) (tset enemy :x (or ?x (+ +width+ 8.0))) (tset enemy :y (or ?y (r 0 (- +height+ enemy.h)))) (table.insert *enemy-pool* enemy) enemy)) (fn init-enemies [] (global *enemy-types* [ :simple-fish :stronger-fish ]) (global *enemy* { :w 8 :h 8 :speedx 50 :speedy 0 :damage 2.0 :health 2.0 :points 1 :emitter :pexplosion :flicker 0 :no-flicker false }) (set *enemy*.animator { :current-animation :moving :current-index 1 :elapsed 0 :speed 150 :animations { :moving nil }}) (set *enemy*.update (fn [self] (inc self.y (* self.speedy *dt*)) (dec self.x (* self.speedx *dt*)))) (set *enemy*.draw (fn [self] (animate self) (if (and (> self.flicker 0) (< (% *tick* 5) 3)) (do (dec self.flicker)) (spr (get-animation-frame self.animator) self.x self.y 0)))) (global *simple-fish* (deepcopy *enemy*)) (set *simple-fish*.w 7) (set *simple-fish*.h 3) (set *simple-fish*.animator.animations.moving [ 292 293 294 293 292 295 296 295 ]) (set *simple-fish*.update (fn [self] (dec self.x (* (+ self.speedx *cam*.speedx) *dt*)) (inc self.y (* 0.2 (sin (* 0.05 (+ *tick* self.y))))))) (global *ghost-fish* (deepcopy *simple-fish*)) (set *ghost-fish*.damage 5) (set *ghost-fish*.animator.animations.moving [ 377 378 379 378 377 380 381 380 ]) (global *stronger-fish* (deepcopy *enemy*)) (set *stronger-fish*.speedx 30) (set *stronger-fish*.damage 5) (set *stronger-fish*.health 4) (set *stronger-fish*.points 1) (set *stronger-fish*.update (fn [self] (dec self.x (* (+ self.speedx *cam*.speedx) *dt*)) (inc self.y (* 0.5 (sin (* 0.05 (+ *tick* self.y))))))) (set *stronger-fish*.animator.animations.moving [ 273 274 275 276 275 274 ]) (global *shooter-fish* (deepcopy *stronger-fish*)) (set *shooter-fish*.speedx 20) (set *shooter-fish*.health 24) (set *shooter-fish*.damage 15) (set *shooter-fish*.animator.animations.moving [ 269 270 271 285 271 270 ]) (set *shooter-fish*.update (fn [self] (when (= (% (+ *tick* 40) 40) 0) (var ball (spawn-enemy :energy-ball self.x self.y)) (set ball.animator.animations.moving [ 264 308 309 308 ]) (set ball.animator.speed 50) (set ball.damage 20) (set ball.w 3) (set ball.h 3) (set ball.speedx (+ *cam*.speedx 80))) (dec self.x (* (+ self.speedx *cam*.speedx) *dt*)) (inc self.y (* 0.5 (sin (* 0.05 (+ *tick* self.y))))))) (global *energy-ball* (deepcopy *enemy*)) (set *energy-ball*.animator.animations.moving [ 265 323 324 ]) (set *energy-ball*.points 0) (set *energy-ball*.health 9999) (set *energy-ball*.speedx 130) (set *energy-ball*.damage 20) (set *energy-ball*.no-flicker true) (global *follower* (deepcopy *energy-ball*)) (set *follower*.speedx 200) (set *follower*.update (fn [self] (if (and (< self.y *player*.y) (> self.x *player*.x)) (set self.speedy 35) (and (> self.y *player*.y) (> self.x *player*.x)) (set self.speedy -35)) (inc self.y (* self.speedy *dt*)) (dec self.x (* self.speedx *dt*)))) (global *anglerfish* (deepcopy *enemy*)) (set *anglerfish*.w 32) (set *anglerfish*.h 32) (set *anglerfish*.points 100) (set *anglerfish*.damage 40) (set *anglerfish*.health 2000) (set *anglerfish*.shake true) (set *anglerfish*.boss? true) (set *anglerfish*.state :arriving) (set *anglerfish*.next-state :centering) (set *anglerfish*.tick 0) (set *anglerfish*.reposition-flag false) (set *anglerfish*.cattack nil) (set *anglerfish*.aframe 0) (set *anglerfish*.asfactor 1) (set *anglerfish*.attack-types [ :follow :energy :straight :pacifist ]) (set *anglerfish*.animator { :current-animation :moving :current-index 1 :elapsed 0 :speed 150 :animations { :moving [ 300 312 448 420 448 312 ] :attack [ 160 164 160 168 ] }}) (set *anglerfish*.draw (fn [self] (animate self) (if (and (> self.flicker 0) (< (% self.tick 5) 3)) (do (dec self.flicker)) (spr (get-animation-frame self.animator) self.x self.y 0 1 0 0 4 4)))) (set *anglerfish*.move (fn [self] (inc self.y (- (* 1.5 (sin (* 0.04 (+ self.tick 39)))) 0.0)))) (set *anglerfish*.finish-attack (fn [self] (set self.aframe 0) (set self.tick 0) (set self.cattack nil) (set self.reposition-flag false) (set self.state :centering) (set self.next-state :moving))) (set *anglerfish*.attack (fn [self] (when (not self.cattack) (set self.cattack (. self.attack-types (r 1 (length self.attack-types))))) (if (and (not self.reposition-flag) (or (= self.cattack :straight) (= self.cattack :follow))) (if (< self.y (- *player*.y 1)) (inc self.y (* 50 *dt*)) (> self.y (+ *player*.y 1)) (dec self.y (* 50 *dt*)) (set self.reposition-flag true)) (= self.cattack :follow) (do (when (= (% self.tick 100) 0) (spawn-enemy :follower self.x self.y) (set self.reposition-flag false)) (when (= (% self.tick 600) 0) (self:finish-attack))) (= self.cattack :straight) (do (when (= (% self.tick 150) 0) (global *shake* 0) (set self.reposition-flag false)) (when (= (% self.tick 3) 0) (local ball (spawn-enemy :energy-ball self.x self.y)) (set ball.speedx 500)) (global *shake* 5) (when (= (% self.tick 500) 0) (self:finish-attack))) (= self.cattack :energy) (do (self:move) (when (= (% self.tick (math.round (* 15 self.asfactor))) 0) (sfx 3 20 -1 3 8 3) (spawn-enemy :energy-ball self.x (+ self.y (/ self.h 2)))) (when (= (% self.tick 500) 0) (self:finish-attack))) (= self.cattack :pacifist) (self:finish-attack)))) (set *anglerfish*.update (fn [self] (inc self.tick) (when (not= self.state :arriving) (global *boss-life* (math.max 0 self.health))) (when (and (< self.health 1000) (> self.asfactor 0.5)) (set self.asfactor 0.8)) (if (= self.state :arriving) (if (< self.tick 200) (when (> *cam*.speedx 15) (set *cam*.speedx 15)) (do (when (< *cam*.speedx 50) (set *cam*.speedx 50)) (when (< self.x 200) (set self.state :centering) (set self.next-state :moving)) (dec self.x (* 60 *dt*)))) (= self.state :attack) (do (when (not (= self.animator.current-animation :attack)) (set self.animator.current-animation :attack)) (when (= (% self.tick 30) 0) (local emitter (deepcopy *bexplosion-emitter*)) (set emitter.x (+ self.x 9)) (set emitter.y (+ self.y 12)) (table.insert *emitters* emitter)) (self:attack)) (= self.state :centering) (do (if (< (+ self.y (/ self.h 2)) 65) (inc self.y (* 40 *dt*)) (> (+ self.y (/ self.h 2)) 71) (dec self.y (* 40 *dt*)) (do (set self.tick 0) (set self.state self.next-state)))) (= self.state :moving) (do (when (not (= self.animator.current-animation :moving)) (set self.animator.current-animation :moving)) (when (= (% self.tick 15) 0)  (local rn (r 0 100)) (when (< rn 40) (local enemy (spawn-enemy :stronger-fish self.x (+ self.y 16))) (set enemy.health 16))) (when (= (% self.tick 400) 0) (self:finish-attack) (set self.state :centering) (set self.next-state :attack)) (self:move))))) (global *snake* (deepcopy *enemy*)) (set *snake*.length 30) (set *snake*.animator.animations.moving [ 368 374 371 374 ]) (set *snake*.animator.speedx 100) (set *snake*.speedx 100) (set *snake*.health 100) (set *snake*.damage 30) (set *snake*.draw (fn [self] (var bindex 1)  (local aindex (if (< (% *tick* 32) 8) 0 (< (% *tick* 32) 16) 2 (< (% *tick* 32) 24) 1 2))  (spr (+ 368 aindex) self.x self.y 0) (for [i 1 self.length 1] (spr (+ 371 aindex) (+ self.x (* bindex 8)) self.y 0) (inc bindex)) (spr (+ 374 aindex) (+ self.x (* bindex 8)) self.y 0))) (set *snake*.update (fn [self] (when (< self.w (* (+ self.length 2) 8)) (set self.w (* (+ self.length 2) 8))) (dec self.x (* (+ self.speedx *cam*.speedx) *dt*)))) (global *snail* (deepcopy *enemy*)) (set *snail*.animator.animations.moving [ 266 ]) (set *snail*.health 12) (set *snail*.damage 40) (set *snail*.draw (fn [self] (animate self) (spr (get-animation-frame self.animator) self.x self.y 0 1 0 0 1 2))) (set *snail*.update (fn [self] (when ( = (% (+ *tick* (math.round self.y)) 70) 0) (var ball (spawn-enemy :energy-ball self.x self.y)) (set ball.animator.animations.moving [ 264 308 309 308 ]) (set ball.animator.speed 50) (set ball.damage 20) (set ball.w 3) (set ball.h 3) (set ball.speedx (- self.x *player*.x)) (set ball.speedy (- *player*.y self.y))) (dec self.x (* *cam*.speedx *dt*)))) (global *easy-snail* (deepcopy *snail*)) (set *easy-snail*.animator.animations.moving [ 338 ]) (set *easy-snail*.health 12) (set *easy-snail*.damage 30) (set *easy-snail*.update (fn [self] (when ( = (% (+ *tick* (math.round self.y)) 70) 0) (var ball (spawn-enemy :energy-ball self.x self.y)) (set ball.animator.animations.moving [ 264 308 309 308 ]) (set ball.animator.speed 50) (set ball.damage 20) (set ball.w 3) (set ball.h 3) (set ball.speedx *cam*.speedx) (set ball.speedy -40)) (dec self.x (* *cam*.speedx *dt*)))) (global *guard* (deepcopy *enemy*)) (set *guard*.animator.animations.moving [ 304 ]) (set *guard*.health 10) (set *guard*.tick 0) (set *guard*.update (fn [self] (inc self.tick) (when ( = (% self.tick 60) 0) (var ball (spawn-enemy :energy-ball self.x self.y)) (set ball.animator.animations.moving [ 264 308 309 308 ]) (set ball.animator.speed 50) (set ball.damage 7) (set ball.w 3) (set ball.h 3) (set ball.speedx (+ *cam*.speedx 20))) (set self.y (+ 68 (* 50 (sin (* 0.03 *tick*))))) (dec self.x (* *cam*.speedx *dt*)))) (global *enemy-pool* [])) (fn spawn-snail [?enemy] (when (< ymax 9) (local camtile (% (math.abs (math.round (// *cam*.x 8))) 240)) (var found-tile false) (for [i (+ camtile 30) (+ camtile 60) 1] (for [j 10 16 1] (when (and (> (mget i j) 127) (= (mget i (- j 1)) 0) (not= i *last-snail-x*)) (spawn-enemy (or ?enemy :snail) (- (* (- i camtile -1) 8) (% (math.abs *cam*.x) 8)) (+ (* (- j 1) 8) 4)) (global *last-snail-x* i) (set found-tile true) (lua :break))) (when found-tile (lua :break))))) (fn destroy-enemy [index] (table.remove *enemy-pool* index)) (fn update-enemies [] (each [index enemy (pairs *enemy-pool*)] (enemy:update) (enemy:draw) (when (bcollides? *player* enemy) (*player*:hurt enemy.damage)) (each [shot-index shot (pairs *player*.shots)] (when (bcollides? shot enemy) (dec enemy.health shot.damage) (when (and (> enemy.health 0) (not enemy.no-flicker)) (set enemy.flicker 18) (sfx 4 33 4 3 6)) (destroy-shot shot-index) (when (and enemy.shake (= *shake* 0)) (global *shake* 5)))) (when (or (< (+ enemy.x enemy.w) -8.0) (> enemy.x 480) (< enemy.y -200) (> enemy.y (+ +height+ 200)) (<= enemy.health 0)) (when (<= enemy.health 0) (when enemy.boss? (global *boss-killed* true)) (sfx 4 12 -1 3 6) (local emitter (match enemy.emitter :pexplosion (deepcopy *pexplosion-emitter*) :cexplosion (deepcopy *cexplosion-emitter*))) (set emitter.x enemy.x) (set emitter.y enemy.y) (table.insert *emitters* emitter) (spawn-goods (math.max enemy.x 60) (+ enemy.y (/ enemy.h 2)) enemy.points)) (destroy-enemy index)))) (fn init-enemy-spawners [] (global *spawners* {}) (global *active-spawners* 0) (global *spawner* { :enemy :simple-fish :delay 30 :duration 5 :finished false }) (global *last-snail-x* 0) (set *spawner*.update (fn [self ?delay ?x ?y ?enemy] (when (= (% *tick* (or ?delay self.delay)) 0) (spawn-enemy (or ?enemy self.enemy) ?x ?y)) (if (< self.duration 0) (set self.finished true) (dec self.duration *dt*)))) (global *fish-spawner* (deepcopy *spawner*)) (global *ghost-fish-spawner* (deepcopy *spawner*)) (set *ghost-fish-spawner*.enemy :ghost-fish) (global *stronger-fish-spawner* (deepcopy *fish-spawner*)) (set *stronger-fish-spawner*.enemy :stronger-fish) (set *stronger-fish-spawner*.delay 55) (global *snail-spawner* (deepcopy *spawner*)) (set *snail-spawner*.enemy :snail) (set *snail-spawner*.delay 250) (set *snail-spawner*.duration 15) (set *snail-spawner*.update (fn [self ?delay] (when (= (% *tick* (or delay self.delay)) 0) (spawn-snail self.enemy)) (if (< self.duration 0) (set self.finished true) (dec self.duration *dt*)))) (global *easy-snail-spawner* (deepcopy *snail-spawner*)) (set *easy-snail-spawner*.enemy :easy-snail) (global *shooter-fish-spawner* (deepcopy *spawner*)) (set *shooter-fish-spawner*.enemy :shooter-fish) (set *shooter-fish-spawner*.delay 180) (global *snake-spawner* (deepcopy *spawner*)) (set *snake-spawner*.enemy :snake) (set *snake-spawner*.delay 180) (global *guard-spawner* (deepcopy *spawner*)) (set *guard-spawner*.enemy :guard) (set *guard-spawner*.update (fn [self] (when (= (% *tick* 150) 0) (spawn-enemy :guard) (set self.finished true)))) (global *easy-spawners* [ :fish :stronger-fish :guard :easy-snail ]) (global *medium-spawners* [ :guard :snail :snake :shooter-fish :ghost-fish ]) (global *wave-counter* 0)) (fn camr [from to] (and (> *cam*.x to) (< *cam*.x from))) (fn get-spawner [type] (match type :fish (deepcopy *fish-spawner*) :ghost-fish (deepcopy *ghost-fish-spawner*) :stronger-fish (deepcopy *stronger-fish-spawner*) :shooter-fish (deepcopy *shooter-fish-spawner*) :snake (deepcopy *snake-spawner*) :guard (deepcopy *guard-spawner*) :easy-snail (deepcopy *easy-snail-spawner*) :snail (deepcopy *snail-spawner*))) (fn add-spawner [spawners] (local spw (. spawners (r 1 (length spawners)))) (when (= (. *spawners* spw) nil) (incg *active-spawners*) (tset *spawners* spw (get-spawner spw)))) (fn update-enemy-spawners [] (when (and (< *cam*.speedx *cam*.max-speed) (= (% *tick* 400) 0)) (inc *cam*.speedx)) (if (= *enemy-wave* :easy-wave) (do (when (< *active-spawners* 2) (add-spawner *easy-spawners*)) (each [k spawner (pairs *spawners*)] (spawner:update) (when spawner.finished (decg *active-spawners*) (tset *spawners* k nil))) (when (< *cam*.x -2000) (global *enemy-wave* :medium-wave))) (= *enemy-wave* :medium-wave) (do (when (< *active-spawners* 2) (add-spawner *medium-spawners*)) (each [k spawner (pairs *spawners*)] (spawner:update) (when spawner.finished (decg *active-spawners*) (tset *spawners* k nil))) (when (< *cam*.x -4000) (each [k spawner (pairs *spawners*)] (decg *active-spawners*) (tset *spawners* k nil)) (global *enemy-wave* :boss-wave))) (= *enemy-wave* :boss-wave) (do (if *boss-killed* (do (global *enemy-wave* :none) (global *time-elapsed* 0) (global *game-state* "win")) (> *cam*.x -4600) (do (when (> *cam*.speedx 20) (set *cam*.speedx 20)) (when (< *active-spawners* 2) (add-spawner [:fish :stronger-fish])) (each [k spawner (pairs *spawners*)] (spawner:update) (when spawner.finished (decg *active-spawners*) (tset *spawners* k nil)))) (<= (length *enemy-pool*) 0) (spawn-enemy :anglerfish))) (= *enemy-wave* :first-wave) (do (when (and (< *cam*.x -100) (= (% *tick* 200) 0)) (incg *wave-counter* 9)) (if (and (< *cam*.x -30) (> *cam*.x -100)) (*fish-spawner*:update 80 nil (+ 68 (r -40 40))) (and (< *cam*.x -100) (> *cam*.x -700)) (do (*fish-spawner*:update (- 100 *wave-counter*)) (*fish-spawner*:update (- 120 *wave-counter*) nil nil :stronger-fish)) (< *cam*.x -700) (do (global *wave-counter* 0) (global *enemy-wave* :easy-wave)))))) (fn draw-cave-bg [pfactor] (if (> map-offset-y 0) (do (spr 11 230 (+ map-offset-y 120) 0 1 0 0 2 4) (spr 8 180 (+ map-offset-y 40) 0 1 0 0 1 2) (spr 11 100 (+ map-offset-y 70) 0 1 0 0 5 5) (spr 9 50 (+ map-offset-y 100) 0 1 0 0 4 4) (spr 8 100 (+ map-offset-y 110) 0 1 0 0 1 2) (spr 9 190 (+ map-offset-y 100) 0 1 0 0 7 5) (spr 8 140 (+ map-offset-y 100) 0 1 0 0 1 2) (spr 11 280 (+ map-offset-y 70) 0 1 0 0 5 5) (spr 9 120 (+ map-offset-y 68) 0 1 0 0 2 3)) (do (loop-spr 11 230 120 2 4 pfactor) (loop-spr 8 180 40 1 2 pfactor) (loop-spr 11 100 70 5 5 pfactor) (loop-spr 9 50 100 4 4 pfactor) (loop-spr 8 100 110 1 2 pfactor) (loop-spr 9 190 100 7 5 pfactor) (loop-spr 8 140 100 1 2 pfactor) (loop-spr 11 280 70 5 5 pfactor) (loop-spr 9 120 68 2 3 pfactor)))) (fn draw-algae [pfactor] (local positions [ 0 15 32 39 47 56 62 79 83 98 107 113 125 132 147 153 165 169 177 182 189 198 213 224 232 240  ]) (local sprites [ 51 54 51 52 52 53 54 51 54 53 51 53 51 53 54 52 54 52 51 53 54 52 54 51 52 54 ]) (for [i 1 26 1] (local pos (. positions i)) (if (> map-offset-y 0) (spr (. sprites i) pos (+ 136 (% pos 8) map-offset-y) 0 1 (% pos 2) 0 1 5) (loop-spr (. sprites i) pos (+ 136 (% pos 8)) 1 5 pfactor 0 (% pos 2))))) (fn draw-bg [] (draw-cave-bg 0.1) (draw-algae 0.6) (*bg-bubbles*:update)) (fn draw-healthbar [x y n] (spr 387 x (+ y 3) 0) (spr 384 (+ x 3) y 0 1 0 0 2 1) (for [i 2 5 1] (spr 385 (+ x (* 8 i) 3) y 0 1 0 0 1 1)) (spr 385 (+ x 42 3) y 0 1 0 0 2 1) (spr 384 (+ x 3) (+ y 5) 0 1 2 0 2 1) (for [i 2 5 1] (spr 385 (+ x (* 8 i) 3) (+ y 5) 0 1 2 0 1 1)) (spr 385 (+ x 42 3) (+ y 5) 0 1 2 0 2 1) (when (> n 0) (var fill-color 1) (when (< n 10) (set fill-color 9)) (for [j y (+ y 4) 1] (for [i (+ x 3) (+ x 3 n -1) 1] (pix (+ i 4) (+ j 4) fill-color))))) (fn draw-shot-icons [x y] (if (= *player*.current-shot :basic-shot) (spr 388 x y 0) (spr 395 x y 0)) (if (has-element? *player*.available-shots :blue-shot) (if (= *player*.current-shot :blue-shot) (spr 389 (+ x 8) y 0) (spr 396 (+ x 8) y 0)) (spr 392 (+ x 8) y 0)) (if (has-element? *player*.available-shots :triple-shot) (if (= *player*.current-shot :triple-shot) (spr 390 (+ x 16) y 0) (spr 397 (+ x 16) y 0)) (spr 393 (+ x 16) y 0))) (fn draw-boss-healthbar [x y] (when (and (> *boss-life* 0) (not *boss-killed*)) (spr 407 x (+ y 2) 0) (spr 404 (+ x 3) y 0 1 0 0 2 1) (for [i 2 27 1] (spr 405 (+ x (* 8 i) 3) y 0 1 0 0 1 1)) (spr 406 (+ x (* 28 8) 2) y 0 1 0 0 1 1) (spr 404 (+ x 3) (+ y 3) 0 1 2 0 2 1) (for [i 2 27 1] (spr 405 (+ x (* 8 i) 3) (+ y 3) 0 1 2 0 1 1)) (spr 406 (+ x (* 28 8) 2) (+ y 3) 0 1 2 0 1 1) (when (> *boss-life* 0) (var fill-color 7) (for [j y (+ y 2) 1] (for [i (+ x 3) (+ x 3 (math.round (/ *boss-life* 8.968609)) -1) 1] (pix (+ i 4) (+ j 4) fill-color)))))) (fn draw-hud [] (spr 277 5 13 0) (if (> *player*.target-points 0) (print (.. *player*.points (.. "/" *player*.target-points)) 15 13 12) (print *player*.points 15 13 12)) (draw-healthbar 5 0 (// *player*.health 2)) (draw-shot-icons 65 3) (draw-boss-healthbar 5 (- 136 10))) (fn draw-game [] (cls) (local txcam (// (math.abs *cam*.x) 8)) (local tycam (// (math.abs *cam*.y) 8)) (map txcam tycam 31 18 (- 0 (% (math.abs *cam*.x) 8)) (- 0 (% (math.abs *cam*.y) 8)) 0) (update-goods) (*player*:draw) (update-enemies) (update-emitters) (draw-hud)) (fn update-camera [] (set *cam*.ox (- *cam*.ox (* *cam*.speedx *dt*))) (set *cam*.x (+ *cam*.ox *cam*.offsetx)) (set *cam*.y (+ *cam*.oy *cam*.offsety))) (fn update-game [] (when (not= map-offset-y 0) (global map-offset-y 0)) (update-camera) (update-cave-walls) (when (> *shake* 0) (set *cam*.offsetx (r -2 2)) (set *cam*.offsety (r -2 2)) (poke 0x3FF9 (r 0 1)) (poke (+ 0x3FF9 1) (r 0 1)) (decg *shake*) (when (= *shake* 0) (memset 0x3FF9 0 2) (set *cam*.offsety 0) (set *cam*.offsetx 0))) (*player*:update) (update-enemy-spawners)) (global *icosahedron* []) (global *t-icosahedron* []) (fn minz [t] (math.min (. (. t 1) 3) (. (. t 2) 3) (. (. t 3) 3))) (fn sum-tri [t] (+ (. (. t 1) 3) (. (. t 2) 3) (. (. t 3) 3))) (global +fov+ 120) (fn compute-icosahedron-vertices [radius] (local hangle (* (/ math.pi 180) 72)) (local vangle (math.atan (/ 1 2))) (local vertices []) (var i1 0) (var i2 0) (var z 0) (var xy 0) (var hangle1 (- (/ -3.141592 2) (/ hangle 2))) (var hangle2 (/ -3.141592 2)) (tset vertices 0 0) (tset vertices 1 radius) (tset vertices 2 0) (for [i 1 5 1] (set i1 (* i 3)) (set i2 (* (+ i 5) 3)) (set z (* radius (sin vangle))) (set xy (* radius (cos vangle))) (tset vertices i1 (* xy (cos hangle1))) (tset vertices i2 (* xy (cos hangle2))) (tset vertices (+ i1 1) z) (tset vertices (+ i2 1) (- 0 z)) (tset vertices (+ i1 2) (* xy (sin hangle1))) (tset vertices (+ i2 2) (* xy (sin hangle2))) (inc hangle1 hangle) (inc hangle2 hangle)) (set i1 (* 11 3)) (tset vertices i1 0) (tset vertices (+ i1 1) (- 0 radius)) (tset vertices (+ i1 2) 0) vertices) (fn getv3 [arr i] (local v []) (tset v 1 (. arr i)) (tset v 2 (. arr (+ i 1))) (tset v 3 (. arr (+ i 2))) v) (fn convert-3d-2d [ox oy oz] (local v []) (tset v 0 (+ (* ox (/ +fov+ (+ oz 20))) (/ +width+ 2))) (tset v 1 (+ (* oy (/ +fov+ (+ oz 20))) (/ +height+ 2))) v) (fn draw-tri [vertices color] (local xo (/ +width+ 2)) (local yo (/ +height+ 2)) (local v1-3d (. vertices 1)) (local v2-3d (. vertices 2)) (local v3-3d (. vertices 3)) (local v1 (. vertices 1)) (local v2 (. vertices 2)) (local v3 (. vertices 3)) (tri (+ (. v1 1) xo) (+ (. v1 2) yo) (+ (. v2 1) xo) (+ (. v2 2) yo) (+ (. v3 1) xo) (+ (. v3 2) yo) color)) (fn build-icosahedron-triangles [] (local tmp-verts (compute-icosahedron-vertices 40)) (var v0 []) (var v1 []) (var v2 []) (var v3 []) (var v4 []) (var v11 []) (var index 0) (set v0 (getv3 tmp-verts 0)) (set v11 (getv3 tmp-verts (* 11 3))) (for [i 1 5 1] (set v1 (getv3 tmp-verts (* i 3))) (if (< i 5) (set v2 (getv3 tmp-verts (* (+ i 1) 3))) (set v2 (getv3 tmp-verts 3))) (set v3 (getv3 tmp-verts (* (+ i 5) 3))) (if (< i 5) (set v4 (getv3 tmp-verts (* (+ i 6) 3))) (set v4 (getv3 tmp-verts (* 6 3)))) (table.insert *icosahedron* [v0 v1 v2 index]) (table.insert *icosahedron* [v1 v3 v2 (+ index 1)]) (table.insert *icosahedron* [v2 v3 v4 (+ index 2)]) (table.insert *icosahedron* [v3 v11 v4 (+ index 3)]) (inc index 4))) (fn sort-icosahedron [] (table.sort *t-icosahedron* (fn [a b] (if (< (minz b) (minz a)) true (> (minz b) (minz a)) false (if (< (sum-tri b) (sum-tri a)) true false))))) (fn rotate-point [point g b a] (local px (. point 1)) (local py (. point 2)) (local pz (. point 3)) (local newpoint [(+ (* px (cos a) (cos b)) (* py (- (* (cos a) (sin b) (sin g)) (* (sin a) (cos g)))) (* pz (+ (* (cos a) (sin b) (cos g)) (* (sin a) (sin g))))) (+ (* px (* (sin a) (cos b))) (* py (+ (* (sin a) (sin b) (sin g)) (* (cos a) (cos g)))) (* pz (- (* (sin a) (sin b) (cos g)) (* (cos a) (sin g))))) (+ (* px (- 0 (sin b))) (* py (cos b) (sin g)) (* pz (cos b) (cos g)))]) newpoint) (fn rotate-icosahedron [x y z] (each [i triangle (pairs *icosahedron*)] (var new-triangle []) (for [j 1 3 1] (table.insert new-triangle (rotate-point (. triangle j) x y z))) (table.insert new-triangle (. triangle 4)) (tset *t-icosahedron* i new-triangle))) (fn translate-point [point x y z] (local px (. point 1)) (local py (. point 2)) (local pz (. point 3)) (local newpoint [(+ px x) (+ py y) (+ pz z)]) newpoint) (fn translate-icosahedron [x y z] (each [i triangle (pairs *icosahedron*)] (var new-triangle []) (for [j 1 3 1] (table.insert new-triangle (translate-point (. triangle j) x y z))) (table.insert new-triangle (. triangle 4)) (tset *t-icosahedron* i new-triangle))) (fn transform-icosahedron [r t] (each [i triangle (pairs *icosahedron*)] (var new-triangle []) (for [j 1 3 1] (table.insert new-triangle (translate-point (rotate-point (. triangle j) r.x r.y r.z) t.x t.y t.z))) (table.insert new-triangle (. triangle 4)) (tset *t-icosahedron* i new-triangle))) (fn get-tri-color [triangle] (local p1 (. triangle 1)) (local p2 (. triangle 2)) (local p3 (. triangle 3)) (if (and (< (math.min (. p1 1) (. p2 1) (. p3 1)) 0) (< (math.max (. p1 2) (. p2 2) (. p3 2)) 20)) 0)) (fn draw-icosahedron [] (for [index 1 (length *t-icosahedron*) 1] (local triangle (. *t-icosahedron* index)) (local color-id (% (. triangle 4) 5)) (var color 7) (match color-id 0 (set color 8) 1 (set color 14) 2 (set color 15) 3 (set color 0)) (draw-tri triangle color))) (fn init-icosahedron [] (build-icosahedron-triangles) (sort-icosahedron) (global *t-icosahedron* (deepcopy *icosahedron*))) (fn ico-r [offset] (- 0xff (math.abs (math.round (* 150 (sin (* (+ *tick* offset) 0.01))))))) (fn ico-g [offset] (+ 0x00 (math.abs (math.round (* 50 (sin (* (+ *tick* offset) 0.07))))))) (fn ico-b [offset] (- 0x88 (math.abs (math.round (* 50 (sin (* (+ *tick* offset) 0.07))))))) (fn ico-pal [i offset] (pal i (ico-r offset) (ico-g offset) (ico-b offset))) (fn update-icosahedron [?offset-y] (ico-pal 7 0) (ico-pal 0 100) (ico-pal 15 200) (ico-pal 8 50) (ico-pal 14 150) (pal 6 (- 0x2a (math.abs (math.round (* 16 (sin (* *tick* 0.01)))))) (- 0x37 (math.abs (math.round (* 27 (sin (* *tick* 0.01)))))) (- 0x58 (math.abs (math.round (* 55 (sin (* *tick* 0.01))))))) (transform-icosahedron { :x (* (/ math.pi 4) *elapsed*) :y (* (/ math.pi 2) *elapsed*) :z 0 } { :x 0 :y (- (* 3 (sin (* *tick* 0.05))) (or ?offset-y 0)) :z 0 }) (sort-icosahedron)) (fn ease-in-back [x] (- (* 2.70158 x x x) (* 1.70158 x x))) (fn ease-in-out-cubic [x] (if (< x 0.5) (* 4 x x x) (- 1 (/ (math.pow (+ (* -2 x) 2) 3) 2)))) (fn update-menu [] (cls 5) (*bg-bubbles*:update) (print "AMETHYST WATERS" (* 4 8) (* 3 8) 12 true 2) (print "AMETHYST WATERS" (- (* 4 8) 1) (* 3 8) 12 true 2) (print "AMETHYST WATERS" (* 4 8) (- (* 3 8) 1) 12 true 2) (local acc (math.round (ease-in-out-cubic (* 5 *elapsed*)))) (if (< acc 230) (pal 12 (+ 0x0c acc) (+ 0x0c acc) (+ 0x10 acc)) (pal 12 0xf2 0xf4 0xf6)) (update-icosahedron) (draw-icosahedron) (when (< (% *tick* 60) 30) (print "- Press Z to play the game -" (* 6 8) (+ (* 12 8) 6) 12)) (when (btnp 4) (sfx 5 55 -1 3 6 -2) (global *time-elapsed* -1.0) (pal 12 0xf2 0xf4 0xf6) (set *player*.x -10) (global *initial-time* (time)) (global *game-state* "t-menu-game"))) (fn t-menu-game [] (cls 5) (global map-offset-y 196) (var particle-speed 0) (var title-speed 0) (var ico-speed 0) (var message-speed 0) (var message-delay 15) (when (> *time-elapsed* 0.0) (global map-offset-y (- 236 (* 180 (ease-in-back (* 0.5 *time-elapsed*))))) (when (< map-offset-y 0) (global map-offset-y 0)) (set particle-speed (* 8 (ease-in-back (* 0.5 *time-elapsed*)))) (set title-speed (* 200 (ease-in-back (* 0.5 *time-elapsed*)))) (set ico-speed (* 260 (ease-in-back (* 0.5 *time-elapsed*)))) (set message-speed (* 300 (ease-in-back (* 0.5 *time-elapsed*)))) (set message-delay 10)) (rect 0 map-offset-y 240 136 0) (draw-bg) (*bg-bubbles*:update) (when (> map-offset-y 0) (each [k part (pairs *bg-bubbles*.particles)] (dec part.y particle-speed))) (print "AMETHYST WATERS" (* 4 8) (- (* 3 8) title-speed) 12 true 2) (print "AMETHYST WATERS" (- (* 4 8) 1) (- (* 3 8) title-speed) 12 true 2) (print "AMETHYST WATERS" (* 4 8) (- (* 3 8) 1 title-speed) 12 true 2) (update-icosahedron ico-speed) (draw-icosahedron) (when (< (% *tick* message-delay) 10) (print "- Press Z to play the game -" (* 6 8) (- (+ (* 12 8) 6) message-speed) 12)) (local txcam (// (math.abs *cam*.x) 8)) (local tycam (// (math.abs *cam*.y) 8)) (when (< map-offset-y 138) (pal 0 0x14 0x14 0x28) (pal 7 0x8e 0x2e 0x91) (pal 8 0x3c 0x40 0x55) (pal 14 0x20 0x18 0x34) (pal 15 0xf6 0x61 0xba) (pal 6 0x20 0x2d 0x51)) (if (<= map-offset-y 0) (do (set *bg-bubbles*.emition-delay 1000) (set *player*.y 68) (if (>= *player*.x 32) (do (music 0) (global *game-state* "game")) (inc *player*.x (* 60 *dt*)))) (do (set *player*.y (+ 68 map-offset-y)))) (update-emitters)) (fn init [] (init-emitters) (init-icosahedron) (music 1) (init-player) (init-cave-walls) (init-enemies) (init-enemy-spawners) (init-goods) (poke 0x03FF8 5) (global +width+ 240.0) (global +height+ 136.0) (global *dt* 0.0) (global *previous-time* (time)) (global *tick* 0) (global *t-tick* 0) (global *elapsed* 0) (global *time-elapsed* 0) (global *cam* { :x 0 :y 0 :ox 0 :oy 0 :speedx 20 :speedy 0 :max-speed 200 :offsetx 0 :offsety 0 }) (global *last-block-generated* 0) (global *max-wall-y* 6) (for [i 0 13 1] (mset i 0 152) (mset i 16 153)) (generate-cave-walls 14 59 pn) (decorate-block 14 59) (global map-offset-y 196) (global *shake* 0) (global *enemy-wave* :first-wave) (global *boss-life* -1) (global *boss-killed* false) (global *music-playing* true) (global highscore-flag false) (global *game-state* "menu")) (fn update-win-screen [] (cls 5) (when (not *music-playing*) (global *music-playing* true) (music 1)) (local title-string "YOU WON!!!") (local width (print title-string 0 -16 12 true 2)) (print title-string (// (- 240 width) 2) (* 2 8) 12 true 2) (print title-string (- (// (- 240 width) 2) 1) (* 2 8) 12 true 2) (print title-string (// (- 240 width) 2) (- (* 2 8) 1) 12 true 2) (local middle-text ["You explored the Amethyst Waters." (.. "And look! You collected " *player*.points " amethysts!")]) (for [i 1 (length middle-text) 1] (local width (print (. middle-text i) 0 -16)) (print (. middle-text i) (// (- 240 width) 2) (+ 60 (* 8 (- (* i 1.5) 1))) 15)) (local bottom-string "Press Z to go back to the title screen.") (local width (print bottom-string 0 -16 12)) (print "Press Z to go back to the title screen" (// (- 240 width) 2) (+ (* 13 8) 6) 12) (when (btnp 4) (global *icosahedron* []) (global *t-icosahedron* []) (init-icosahedron) (for [i 0 7] (clear-map-block i)) (init) (global *initial-time* (time)) (global *game-state* "menu"))) (fn update-game-over [] (if (< *time-elapsed* 2) (draw-bg) (do (cls 5) (local title-string "YOU CRASHED") (print title-string (- 256 (* (length title-string) 16)) (* 2 8) 12 true 2) (print title-string (- (- 256 (* (length title-string) 16)) 1) (* 2 8) 12 true 2) (print title-string (- 256 (* (length title-string) 16)) (- (* 2 8) 1) 12 true 2) (spr 288 32 21 0) (print (.. "x " *player*.points) 42 21 12) (var middle-text []) (var icon nil) (var padding 0) (if (and (= *player*.target-points 15) (>= *player*.points 15)) (do (when (not= (pmem 2) 1) (pmem 2 1)) (set icon 389) (set middle-text [ "YOU UNLOCKED A NEW WEAPON!" "Press A or S to change weapons." ])) (and (= *player*.target-points 50) (>= *player*.points 20)) (do (when (not= (pmem 3) 1) (pmem 3 1)) (set icon 390) (set middle-text [ "YOU UNLOCKED A NEW WEAPON!" "Press A or S to change weapons." ])) (< *player*.points *player*.target-points) (set middle-text [(.. "Get " *player*.target-points " amethysts") "to unlock your next weapon!"]) (set middle-text ["You have superpowers!!"])) (when icon (spr icon 114 44 0 2) (set padding 8)) (for [i 1 (length middle-text) 1] (local width (print (. middle-text i) 0 -16)) (print (. middle-text i) (// (- 240 width) 2) (+ 60 padding (* 8 (- i 1))) 15)) (print "Press Z to test your skills again!" 32 (+ (* 13 8) 6) 12) (when (btnp 4) (for [i 0 7] (clear-map-block i)) (init) (music 0) (global *initial-time* (time)) (global *game-state* "game"))))) (global TIC  (fn [] (global *dt* (/ (- (time) *previous-time*) 1000.0)) (global *previous-time* (time)) (incg *time-elapsed* *dt*) (incg *tick*) (incg *elapsed* *dt*) (if (= *game-state* "game") (do (update-game) (draw-bg)) (= *game-state* "menu") (update-menu) (= *game-state* "t-menu-game") (t-menu-game) (= *game-state* "win") (if (< *time-elapsed* 10) (do (when (> *cam*.speedx 10) (set *cam*.speedx 10)) (if *music-playing* (global *music-playing* false) (music)) (when (= (% *tick* 45) 0) (sfx 9 (r 20 30) -1 0 10 0) (local emitter (deepcopy *pexplosion-emitter*)) (set emitter.x (r 10 230)) (set emitter.y (r 10 126)) (set emitter.scale-range { :min 10 :max 40 }) (table.insert *emitters* emitter)) (draw-bg) (update-game)) (update-win-screen)) (= *game-state* "game-over") (update-game-over)))) (global OVR (fn [] (if (= *game-state* "game") (draw-game) (or (and (= *game-state* "game-over") (< *time-elapsed* 2)) (and (= *game-state* "win") (< *time-elapsed* 10))) (draw-game) (= *game-state* "t-menu-game") (do (if (<= map-offset-y 0) (map txcam tycam 31 18 (- 0 (% (math.abs *cam*.x) 8)) 0 0) (map txcam tycam 31 18 (- 0 (% (math.abs *cam*.x) 8)) map-offset-y 0)) (*player*:draw))))) (global scanline (fn [row] (if (= *game-state* "game") (poke 0x3ff9 (* (sin (+ (/ (time) 200) (/ row 5))) 2.2)) (or (and (= *game-state* "game-over") (< *time-elapsed* 2)) (and (= *game-state* "win") (< *time-elapsed* 10)) (and (= *game-state* "t-menu-game") (< map-offset-y 138))) (poke 0x3ff9 (* (sin (+ (/ (time) 200) (/ row 5))) 2.2))))) (init) 
;; <TILES>
;; 008:000000000000000000000000e0ee00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
;; 009:000000000000000000000000e0ee00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

M apocalypse-meow/conf.lua => apocalypse-meow/conf.lua +1 -1
@@ 13,6 13,6 @@ love.conf = function(t)
   t.window.fullscreentype = "desktop" -- exclusive
   t.window.fullscreen = false
   t.window.display = 2
   t.version = "11.3"
   -- t.version = "11.3"
   t.gammacorrect = true
end

M downsheep/conf.lua => downsheep/conf.lua +1 -1
@@ 11,6 11,6 @@ love.conf = function(t)
   t.window.borderless= false
   t.window.fullscreentype = "desktop" -- exclusive
   t.window.fullscreen = false
   t.version = "11.3"
   -- t.version = "11.3"
   t.gammacorrect = true
end

M goo-runner/mode-play.fnl => goo-runner/mode-play.fnl +2 -2
@@ 33,7 33,7 @@
    (: blob.centerBody :setLinearDamping 1)
    blob))

(local (player-layer, player-layer-index) (utils.get-layer map "player"))
(local (player-layer player-layer-index) (utils.get-layer map "player"))
(local player-start (-> (. player-layer "objects")
                        (lume.match (fn [o] (= o.type "player")))))



@@ 106,7 106,7 @@
(fn camera-follow-blob [blob zoom-scale]
  (let [points (: blob :getPoints)
        (x y) (: blob.centerBody :getPosition)
        (win-width, win-height) (: love.window :getMode)]
        (win-width win-height) (: love.window :getMode)]
    (set camera.tx (- x (/ win-width 2 zoom-scale)))
    (set camera.ty (- y (/ win-height 2 zoom-scale)))))


M goo-runner/wrap.fnl => goo-runner/wrap.fnl +1 -1
@@ 32,7 32,7 @@
  (love.graphics.setColor 1 1 1)
  (love.graphics.draw canvas 0 0 0 scale scale))

(fn love.update[dt]
(fn love.update [dt]
  (when mode.update
    (mode.update dt set-mode scale)))


M gravity-fall/Makefile => gravity-fall/Makefile +2 -0
@@ 2,3 2,5 @@ default : main.lua util.lua starfield.lua ship.lua level.lua planet.lua hud.lua 

%.lua : %.fnl
	./fennel --compile $< > $@

run: ; love .

M slime-the-world/main.lua => slime-the-world/main.lua +2 -1
@@ 1,6 1,7 @@
-- bootstrap the compiler
fennel = require("lib.fennel")
table.insert(package.loaders, fennel.make_searcher({correlate=true}))
table.insert(package.loaders, fennel.make_searcher({correlate=true,
                                                    allowedGlobals=false}))
pp = function(x) print(require("lib.fennelview")(x)) end
lume = require("lib.lume")


M slimers-dungeon/game.fnl => slimers-dungeon/game.fnl +26 -26
@@ 47,12 47,12 @@
(var player-win nil)
(var id 0)

(defn  get-id []
(fn  get-id []
  (set id (+ id 1))
  id)

;; 4,3
(defn love.load []
(fn love.load []
  (set camera (gamera.new 0 0 2000 2000))
  (: camera :setWorld 0 0 2000 2000)
  (: camera :setWindow 0 0 1024 768)


@@ 88,14 88,14 @@
  (set enemy.image (love.graphics.newImage "assets/slime.png"))  
  (: enemy.image :setFilter "nearest" "nearest")
  (set enemy.grid (anim8.newGrid 8 8 (: enemy.image :getWidth)  (: enemy.image :getHeight)  ))
  (set enemy.animation (anim8.newAnimation (: enemy.grid :getFrames '1-5' 1) 0.1))
  (set enemy.animation (anim8.newAnimation (: enemy.grid :getFrames "1-5" 1) 0.1))

  
  (set player.grid (anim8.newGrid 7 16 (: player.image :getWidth) (: player.image :getHeight)))
  (set player.right-animation (anim8.newAnimation (: player.grid :getFrames '1-3' 1) 0.1 ))
  (set player.right-animation (anim8.newAnimation (: player.grid :getFrames "1-3" 1) 0.1 ))
  (set player.left-animation  (: (: player.right-animation :clone) :flipH ))
  (set player.up-animation  (anim8.newAnimation (: player.grid :getFrames '1-3' 2) 0.1 ))
  (set player.down-animation  (anim8.newAnimation (: player.grid :getFrames '1-3' 3) 0.1 ))
  (set player.up-animation  (anim8.newAnimation (: player.grid :getFrames "1-3" 2) 0.1 ))
  (set player.down-animation  (anim8.newAnimation (: player.grid :getFrames "1-3" 3) 0.1 ))

  
  (set  music  (love.audio.newSource "assets/music.wav" "static"))


@@ 120,7 120,7 @@
(var spawned-roomi 1)
(var spawned-roomj 1)
;; ------------ Enemy control ------------------------------------------
(defn remove-enemies []
(fn remove-enemies []
  (when (> (# enemy-list) 0)
    (let [len (# enemy-list)]
      (for [i 1 len] (let [en (. enemy-list i)]


@@ 130,15 130,15 @@
    (set enemy-list []))
  )

(defn spawn [en]
(fn spawn [en]
 (let [layer (: map :addCustomLayer "enemy")]
    (set layer.sprites [en]))
 (if (not (: world :hasItem en))
       (: world :add en en.x en.y en.width en.height)
  (set [en.x en.y] [(: world :move en x y)]))
  (set [en.x en.y] [(: world :move en en.x en.y)]))
  (table.insert enemy-list en))

(defn spawn-enemies []
(fn spawn-enemies []
;  (print "BEFORE: roomi: " roomi  "sroomi: " spawned-roomi  "roomj: " roomj "spawned-roomj: " spawned-roomj)

  (when (or (~= roomi spawned-roomi) (~= roomj spawned-roomj))    


@@ 159,7 159,7 @@
  ;(print "AFTER: roomi: " roomi  "sroomi: " spawned-roomi  "roomj: " roomj "spawned-roomj: " spawned-roomj)
  ))

(defn draw-enemies []
(fn draw-enemies []
  (when (> (# enemy-list) 0)
    (let [len (# enemy-list)]
      (for [i 1 len]


@@ 170,7 170,7 @@
(var ecols nil)
(var elen nil)

(defn update-enemies [dt]
(fn update-enemies [dt]
    (when (> (# enemy-list) 0)
    (let [len (# enemy-list)]
      (for [i 1 len]


@@ 196,7 196,7 @@

;;------------ BULLET CONTROL  ------------------------------------------

(defn shoot []
(fn shoot []

  (set bullet.shotting true)
  (: shoot-sound :play)


@@ 217,11 217,11 @@
       (: world :add bullet bullet.x bullet.y bullet.width bullet.height)  
  (let [layer (: map :addCustomLayer "bullet")]
    (set layer.sprites [bullet]))
  (set [bullet.x bullet.y] [(: world :move bullet x y)])
  (set [bullet.x bullet.y] [(: world :move bullet bullet.x bullet.y)])
  (set can-shoot nil)))
  

(defn damage-enemy [en]
(fn damage-enemy [en]
;  (print "enemy damaged")
;  (pp en)
  (when (and (= en.type "enemy") (~= en.health nil) )


@@ 233,7 233,7 @@
         ;(pp e)
         ))))))

(defn update-bullet[dt]
(fn update-bullet [dt]
 ;  (pp bullet)
  (var cols nil)
  (var len 0)


@@ 258,7 258,7 @@
          ))))))
;;------------------- Room update ------------------
(var key-pressed nil)
(defn update-level [dt]
(fn update-level [dt]
 (set key-pressed nil)
 (local cons nil)
 (local len nil) 


@@ 287,27 287,27 @@
(var deltay 120)
(var camera-speed 10)
 
(defn move-camera-right [dt]
(fn move-camera-right [dt]
  (: camera :setPosition   (+ camera.x room-w ) camera.y)
  (set roomi (+ roomi 1))
  (set game-state "cameraIDLE"))

(defn move-camera-left [dt]
(fn move-camera-left [dt]
  (: camera :setPosition   (- camera.x room-w) camera.y)
  (set roomi (- roomi 1))
  (set game-state "cameraIDLE"))

(defn move-camera-up [dt]
(fn move-camera-up [dt]
  (: camera :setPosition    camera.x (- camera.y room-h))
  (set roomj (- roomj 1))
  (set game-state "cameraIDLE"))

(defn move-camera-down [dt]
(fn move-camera-down [dt]
  (set roomj (+ roomj 1))
  (: camera :setPosition    camera.x (+ camera.y  room-h))
  (set game-state "cameraIDLE"))

(defn update-dy []
(fn update-dy []
  (when  (~=  camera.y  last-camera-y)
          (set camera-dy (* (- roomj 1)  (- (- camera.y last-camera-y))))
          (when (> camera-dy  0)   (set camera-dy (- camera-dy)))


@@ 316,7 316,7 @@
            (set camera-dy 0))
            (spawn-enemies)))

(defn update-dx []
(fn update-dx []
  (when  (~=  camera.x  last-camera-x)
          (set camera-dx (* (- roomi 1)  (- (- camera.x last-camera-x))))
          (when (> camera-dx  0)   (set camera-dx (- camera-dx)))


@@ 326,7 326,7 @@
            (spawn-enemies)))
;;-----------------------------------------------------------------  

(defn love.update [dt]
(fn love.update [dt]
;  (print player.x player.y)
  (update-dy)
  (update-dx)


@@ 353,7 353,7 @@
  )
;; -----------------------------

(defn love.draw []
(fn love.draw []
  (var rotation 0)
  (chain.draw (fn []
                (: camera :draw


@@ 396,4 396,4 @@
  
  (love.graphics.setColor 1 1 1))))))

(defn love.keypressed [key] (when (= key "escape") (love.event.quit)))
(fn love.keypressed [key] (when (= key "escape") (love.event.quit)))

M spilljackers.fnl => spilljackers.fnl +1 -1
@@ 1291,7 1291,7 @@
      (init-tile cx cy (mget cx cy)))))

(when (not _G.state)
  (modes.start-mission 4)
  (modes.start-mission 1)
  (modes.activate-chat))
(set _G.state s)


M yahtzee-adventure/conf.lua => yahtzee-adventure/conf.lua +1 -1
@@ 1,3 1,3 @@
function love.conf(t)
    t.version = "11.3"
    -- t.version = "11.3"
end