diff options
Diffstat (limited to 'bonnie-bee')
-rw-r--r-- | bonnie-bee/actor.scm | 11 | ||||
-rw-r--r-- | bonnie-bee/assets.scm | 63 | ||||
-rw-r--r-- | bonnie-bee/background.scm | 10 | ||||
-rw-r--r-- | bonnie-bee/boss.scm | 24 | ||||
-rw-r--r-- | bonnie-bee/bullet.scm | 17 | ||||
-rw-r--r-- | bonnie-bee/common.scm | 22 | ||||
-rw-r--r-- | bonnie-bee/flower.scm | 14 | ||||
-rw-r--r-- | bonnie-bee/game.scm | 791 | ||||
-rw-r--r-- | bonnie-bee/moth.scm | 10 | ||||
-rw-r--r-- | bonnie-bee/player.scm | 31 | ||||
-rw-r--r-- | bonnie-bee/pollen.scm | 4 | ||||
-rw-r--r-- | bonnie-bee/popcorn.scm | 10 | ||||
-rw-r--r-- | bonnie-bee/splash.scm | 105 | ||||
-rw-r--r-- | bonnie-bee/turret.scm | 12 |
14 files changed, 637 insertions, 487 deletions
diff --git a/bonnie-bee/actor.scm b/bonnie-bee/actor.scm index 8aec98a..3d693dd 100644 --- a/bonnie-bee/actor.scm +++ b/bonnie-bee/actor.scm @@ -6,9 +6,10 @@ #:use-module (chickadee math rect) #:use-module (chickadee math vector) #:use-module (oop goops) - #:use-module (starling asset) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird asset) + #:use-module (catbird node) + #:use-module (catbird node-2d) + #:use-module (catbird scene) #:export (<actor> velocity hitbox @@ -107,7 +108,7 @@ (refresh-world-hitbox actor) (collision-check actor) (add-to-quadtree actor) - (dirty! actor))))) + (expire-local-matrix actor))))) (define-method (dead? (actor <actor>)) #f) @@ -138,7 +139,7 @@ (define-method (damage (d <damageable>) x) (set! (health d) (max (- (health d) x) 0)) (unless (dead? d) - (audio-play (asset-ref enemy-hit-sound) #:volume 0.25))) + (audio-play (artifact enemy-hit-sound) #:volume 0.25))) (define-method (on-death (d <damageable>)) #t) diff --git a/bonnie-bee/assets.scm b/bonnie-bee/assets.scm index 3dc35cc..a6c2358 100644 --- a/bonnie-bee/assets.scm +++ b/bonnie-bee/assets.scm @@ -1,8 +1,8 @@ (define-module (bonnie-bee assets) #:use-module (chickadee audio) - #:use-module (chickadee graphics font) + #:use-module (chickadee graphics text) #:use-module (chickadee graphics texture) - #:use-module (starling asset) + #:use-module (catbird asset) #:export (monogram-font background-image particle-image @@ -33,28 +33,37 @@ (let ((prefix (or (getenv "BONNIE_BEE_DATADIR") (getcwd)))) (string-append prefix "/" file-name))) -(define-asset monogram-font (load-font (scope-datadir "assets/fonts/monogram_extended.ttf") 12)) -(define-asset background-image (load-image (scope-datadir "assets/images/background.png"))) -(define-asset particle-image (load-image (scope-datadir "assets/images/particle.png"))) -(define-asset darkness-image (load-image (scope-datadir "assets/images/darkness.png"))) -(define-asset lightness-image (load-image (scope-datadir "assets/images/lightness.png"))) -(define-asset chickadee-image (load-image (scope-datadir "assets/images/chickadee.png"))) -(define-asset bee-atlas (load-tileset (scope-datadir "assets/images/bee.png") 32 32)) -(define-asset bullet-atlas (load-tileset (scope-datadir "assets/images/bullets.png") 16 16)) -(define-asset flower-atlas (load-tileset (scope-datadir "assets/images/flower.png") 64 64)) -(define-asset popcorn-atlas (load-tileset (scope-datadir "assets/images/popcorn.png") 32 32)) -(define-asset turret-atlas (load-tileset (scope-datadir "assets/images/turret.png") 64 64)) -(define-asset moth-atlas (load-tileset (scope-datadir "assets/images/moth.png") 64 64)) -(define-asset beetle-atlas (load-tileset (scope-datadir "assets/images/beetle.png") 128 64)) -(define-asset explosion-sound (load-audio (scope-datadir "assets/sounds/explosion.wav"))) -(define-asset pickup-sound (load-audio (scope-datadir "assets/sounds/pickup.wav"))) -(define-asset enemy-shoot-sound (load-audio (scope-datadir "assets/sounds/enemy-shoot.wav"))) -(define-asset enemy-hit-sound (load-audio (scope-datadir "assets/sounds/enemy-hit.wav"))) -(define-asset player-death-sound (load-audio (scope-datadir "assets/sounds/player-death.wav"))) -(define-asset player-shoot-sound (load-audio (scope-datadir "assets/sounds/player-shoot.wav"))) -(define-asset player-bomb-sound (load-audio (scope-datadir "assets/sounds/player-bomb.wav"))) -(define-asset pollen-release-sound (load-audio (scope-datadir "assets/sounds/pollen-release.wav"))) -(define-asset hehehe-sound (load-audio (scope-datadir "assets/sounds/hehehe.wav"))) -(define-asset alarm-sound (load-audio (scope-datadir "assets/sounds/alarm.wav"))) -(define-asset intro-music (load-audio (scope-datadir "assets/sounds/intro.ogg") #:mode 'stream)) -(define-asset main-music (load-audio (scope-datadir "assets/sounds/main.ogg") #:mode 'stream)) +(define (font-file file-name) + (scope-datadir (string-append "assets/fonts/" file-name))) + +(define (image-file file-name) + (scope-datadir (string-append "assets/images/" file-name))) + +(define (audio-file file-name) + (scope-datadir (string-append "assets/sounds/" file-name))) + +(define-font monogram-font (font-file "monogram_extended.ttf") 12) +(define-image background-image (image-file "background.png")) +(define-image particle-image (image-file "particle.png")) +(define-image darkness-image (image-file "darkness.png")) +(define-image lightness-image (image-file "lightness.png")) +(define-image chickadee-image (image-file "chickadee.png")) +(define-tileset bee-atlas (image-file "bee.png") 32 32) +(define-tileset bullet-atlas (image-file "bullets.png") 16 16) +(define-tileset flower-atlas (image-file "flower.png") 64 64) +(define-tileset popcorn-atlas (image-file "popcorn.png") 32 32) +(define-tileset turret-atlas (image-file "turret.png") 64 64) +(define-tileset moth-atlas (image-file "moth.png") 64 64) +(define-tileset beetle-atlas (image-file "beetle.png") 128 64) +(define-audio explosion-sound (audio-file "explosion.wav")) +(define-audio pickup-sound (audio-file "pickup.wav")) +(define-audio enemy-shoot-sound (audio-file "enemy-shoot.wav")) +(define-audio enemy-hit-sound (audio-file "enemy-hit.wav")) +(define-audio player-death-sound (audio-file "player-death.wav")) +(define-audio player-shoot-sound (audio-file "player-shoot.wav")) +(define-audio player-bomb-sound (audio-file "player-bomb.wav")) +(define-audio pollen-release-sound (audio-file "pollen-release.wav")) +(define-audio hehehe-sound (audio-file "hehehe.wav")) +(define-audio alarm-sound (audio-file "alarm.wav")) +(define-audio intro-music (audio-file "intro.ogg") #:mode 'stream) +(define-audio main-music (audio-file "main.ogg") #:mode 'stream) diff --git a/bonnie-bee/background.scm b/bonnie-bee/background.scm index f374556..9434993 100644 --- a/bonnie-bee/background.scm +++ b/bonnie-bee/background.scm @@ -11,8 +11,8 @@ #:use-module (chickadee scripting) #:use-module (chickadee utils) #:use-module (oop goops) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (<background> scroll-y)) @@ -94,6 +94,12 @@ void main (void) { (geometry #:getter geometry #:init-thunk make-background-geometry) (mvp-matrix #:getter mvp-matrix #:init-thunk make-identity-matrix4)) +(define-method (default-width (background <background>)) + (texture-width (texture background))) + +(define-method (default-height (background <background>)) + (texture-height (texture background))) + (define-method (render (background <background>) alpha) (let ((mvp (mvp-matrix background)) (t (texture background))) diff --git a/bonnie-bee/boss.scm b/bonnie-bee/boss.scm index e312d4e..7788f31 100644 --- a/bonnie-bee/boss.scm +++ b/bonnie-bee/boss.scm @@ -11,9 +11,9 @@ #:use-module (chickadee scripting) #:use-module (chickadee utils) #:use-module (oop goops) - #:use-module (starling asset) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird asset) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (<boss>)) (define-class <boss> (<grounded> <damageable> <actor>) @@ -33,7 +33,7 @@ (let loop ((i 0)) (when (< i n) (let ((theta (+ (* (/ tau n) i) offset))) - (add-bullet (bullets (parent boss)) + (add-bullet (& (parent boss) bullets) type (position boss) (vec2 (* (cos theta) speed) @@ -41,7 +41,7 @@ (loop (+ i 1)))))) (define (random-shot speed) (let ((theta (* (- pi) (random:uniform)))) - (add-bullet (bullets (parent boss)) + (add-bullet (& (parent boss) bullets) medium-enemy-bullet (position boss) (vec2 (* (cos theta) speed) @@ -53,9 +53,9 @@ (let ((big-speed 2.0) (little-speed 1.0)) (while (> (health boss) 800) - (let ((d (direction-to boss (player (parent boss))))) - (audio-play (asset-ref enemy-shoot-sound)) - (add-bullet (bullets (parent boss)) + (let ((d (direction-to boss (& (parent boss) player)))) + (audio-play (artifact enemy-shoot-sound)) + (add-bullet (& (parent boss) bullets) large-enemy-bullet (position boss) (vec2* d big-speed)) @@ -67,7 +67,7 @@ (sleep 2.5) (let loop ((theta 0.0)) (unless (<= (health boss) 400) - (audio-play (asset-ref enemy-shoot-sound)) + (audio-play (artifact enemy-shoot-sound)) (repeat 2 (random-shot 0.5)) (circle-shot 2 theta 1.5 large-enemy-bullet) (circle-shot 6 (- theta) 1.0 medium-enemy-bullet) @@ -75,7 +75,7 @@ (loop (+ theta (/ pi 17.1))))) (sleep 2.5) (let loop ((theta 0.0)) - (audio-play (asset-ref enemy-shoot-sound)) + (audio-play (artifact enemy-shoot-sound)) (circle-shot 10 (* theta 2.0) 1.5 large-enemy-bullet) (circle-shot 4 (- theta) 1.0 medium-enemy-bullet) (sleep (* (current-timestep) 10)) @@ -95,6 +95,6 @@ (else #f))) (define-method (on-death (boss <boss>)) - (audio-play (asset-ref explosion-sound)) - (add-particle-emitter (particles (particles (parent boss))) + (audio-play (artifact explosion-sound)) + (add-particle-emitter (particles (& (parent boss) particles)) (make-particle-emitter (world-hitbox boss) 20 30))) diff --git a/bonnie-bee/bullet.scm b/bonnie-bee/bullet.scm index 4f79792..5342271 100644 --- a/bonnie-bee/bullet.scm +++ b/bonnie-bee/bullet.scm @@ -1,6 +1,7 @@ (define-module (bonnie-bee bullet) #:use-module (bonnie-bee actor) #:use-module (bonnie-bee assets) + #:use-module (bonnie-bee common) #:use-module (chickadee data quadtree) #:use-module (chickadee graphics sprite) #:use-module (chickadee graphics texture) @@ -10,9 +11,9 @@ #:use-module (chickadee utils) #:use-module (oop goops) #:use-module (srfi srfi-9) - #:use-module (starling asset) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird asset) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (<bullet-type> player-bullet? player-primary-bullet? @@ -37,7 +38,7 @@ (hitbox #:getter hitbox #:init-keyword #:hitbox)) (define (bullet-texture bullet) - (texture-atlas-ref (asset-ref bullet-atlas) + (texture-atlas-ref (artifact bullet-atlas) (atlas-index (type bullet)))) (define player-primary-bullet @@ -68,7 +69,7 @@ (define (make-bullet-sprite-batch) (make-sprite-batch (texture-parent - (texture-atlas-ref (asset-ref bullet-atlas) 0)))) + (texture-atlas-ref (artifact bullet-atlas) 0)))) (define (make-vector* size proc) (let ((v (make-vector size))) @@ -104,6 +105,12 @@ (set! (hitboxes bullets) (make-vector* %max-bullets make-null-rect)) (set! (regions bullets) (make-vector* %max-bullets make-null-rect))) +(define-method (default-width (bullets <bullets>)) + %game-width) + +(define-method (default-height (bullets <bullets>)) + %game-height) + (define-method (clear-bullets (bullets <bullets>)) (set! (num-bullets bullets) 0)) diff --git a/bonnie-bee/common.scm b/bonnie-bee/common.scm index 885ab33..6ff21c6 100644 --- a/bonnie-bee/common.scm +++ b/bonnie-bee/common.scm @@ -6,9 +6,9 @@ #:use-module (chickadee math vector) #:use-module (chickadee scripting) #:use-module (oop goops) - #:use-module (starling scene) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird scene) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (%window-width %window-height %game-width @@ -23,17 +23,17 @@ (define %game-width 320) (define %game-height 240) -(define-method (set-cameras! (scene <scene-2d>)) - (set! (cameras scene) - (list (make <camera-2d> - #:resolution (vec2 %game-width %game-height) - #:viewport (make-viewport 0 0 %window-width %window-height - #:clear-color black))))) +;; (define-method (set-cameras! (scene <scene-2d>)) +;; (set! (cameras scene) +;; (list (make <camera-2d> +;; #:resolution (vec2 %game-width %game-height) +;; #:viewport (make-viewport 0 0 %window-width %window-height +;; #:clear-color black))))) (define (steps n) (* n (current-timestep))) -(define-method (fade-in (scene <scene-2d>) duration) +(define-method (fade-in (scene <scene>) duration) (let ((bg (make <sprite> #:rank 999 #:texture darkness-image))) @@ -43,7 +43,7 @@ (set! (tint bg) (transparency a)))) (detach bg))) -(define-method (fade-out (scene <scene-2d>) duration) +(define-method (fade-out (scene <scene>) duration) (let ((bg (make <sprite> #:rank 999 #:texture darkness-image))) diff --git a/bonnie-bee/flower.scm b/bonnie-bee/flower.scm index 5e9eb12..6646ecc 100644 --- a/bonnie-bee/flower.scm +++ b/bonnie-bee/flower.scm @@ -10,9 +10,9 @@ #:use-module (chickadee scripting) #:use-module (chickadee utils) #:use-module (oop goops) - #:use-module (starling asset) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird asset) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (<flower> pollen-enabled? enable-pollen! @@ -66,12 +66,12 @@ (let ((p (position flower))) (if (pollen-enabled?) (begin - (audio-play (asset-ref pollen-release-sound)) + (audio-play (artifact pollen-release-sound)) (for-range ((i 16)) (let ((theta (- (* (- (random:uniform) 0.5) (/ pi 3.0)) (/ pi 2.0))) (speed (+ (* (random:uniform) 1.0) 1.0))) - (add-bullet (bullets (parent flower)) + (add-bullet (& (parent flower) bullets) pollen-pickup p (vec2 (* (cos theta) speed) (* (sin theta) speed))))) @@ -81,7 +81,7 @@ #:position (position flower) #:hitbox (make-rect -1.0 -1.0 2.0 2.0)))) (begin - (audio-play (asset-ref explosion-sound)) - (add-particle-emitter (particles (particles (parent flower))) + (audio-play (artifact explosion-sound)) + (add-particle-emitter (particles (& (parent flower) particles)) (make-particle-emitter (make-rect (vec2-x p) (vec2-y p) 1.0 1.0) 10 5)))))) diff --git a/bonnie-bee/game.scm b/bonnie-bee/game.scm index 18b177b..40d5cb6 100644 --- a/bonnie-bee/game.scm +++ b/bonnie-bee/game.scm @@ -20,12 +20,20 @@ #:use-module (chickadee math vector) #:use-module (chickadee scripting) #:use-module (oop goops) - #:use-module (starling asset) - #:use-module (starling kernel) - #:use-module (starling node) - #:use-module (starling node-2d) - #:use-module (starling scene) - #:export (<game>)) + #:use-module (catbird) + #:use-module (catbird asset) + #:use-module (catbird kernel) + #:use-module (catbird observer) + #:use-module (catbird mode) + #:use-module (catbird node) + #:use-module (catbird node-2d) + #:use-module (catbird scene) + #:export (make-game-scene)) + + +;;; +;;; Shadow label +;;; (define %text-color (rgb #xfee761)) @@ -37,7 +45,7 @@ (make <label> #:name 'shadow #:position (vec2 0.0 1.0) - #:font (font label) + #:font (slot-ref label 'font) #:text (text label) #:color (color label))) (set! (color label) black)) @@ -46,79 +54,83 @@ (next-method) (case slot-name ((text) - (set! (text (& label shadow)) new))) ) + (set! (text (& label shadow)) new)))) -(define %game-bounds (make-rect 0.0 0.0 %game-width %game-height)) + +;;; +;;; Heads-up display +;;; -(define-class <game> (<scene-2d>) - (state #:accessor state #:init-value 'play) - (quadtree #:getter quadtree #:init-form (make-quadtree %game-bounds)) - (scroll-speed #:getter scroll-speed #:init-value 0.0) +(define-class <hud> (<node-2d>) (last-lives #:accessor last-lives #:init-value 0) (last-pollen #:accessor last-pollen #:init-value 0) - (last-score #:accessor last-score #:init-value 0) - (music-source #:getter music-source #:init-form (make-source #:loop? #t))) - -(define-method (change-scroll-speed (game <game>) speed) - (slot-set! game 'scroll-speed speed)) - -(define-method (spawn (game <game>) (actor <actor>)) - (set! (quadtree actor) (quadtree game)) - (quadtree-insert! (quadtree game) (world-hitbox actor) actor) - (attach-to game actor)) - -(define-method (player (game <game>)) - (& game player)) - -(define-method (bullets (game <game>)) - (& game bullets)) - -(define-method (particles (game <game>)) - (& game particles)) + (last-score #:accessor last-score #:init-value 0)) -(define-method (on-boot (game <game>)) - (set! *random-state* (random-state-from-platform)) - (set-cameras! game) - (attach-to game - (make <background> - #:name 'background - #:texture background-image) - (make <particles> - #:name 'particles - #:particles (make-particles 2048 - #:texture (asset-ref particle-image) - #:end-color (make-color 1.0 1.0 1.0 0.0))) - (make <bullets> - #:name 'bullets - #:rank 4 - #:quadtree (quadtree game)) +(define-method (on-boot (hud <hud>)) + (attach-to hud (make <shadow-label> - #:name 'hud-lives - #:rank 5 + #:name 'lives #:position (vec2 2.0 2.0) #:font monogram-font #:text "lives 0" #:color %text-color) (make <shadow-label> - #:name 'hud-pollen - #:rank 5 + #:name 'pollen #:position (vec2 (/ %game-width 2.0) 2.0) #:font monogram-font #:text "pollen 0" #:align 'center #:color %text-color) (make <shadow-label> - #:name 'hud-score - #:rank 5 + #:name 'score #:position (vec2 (- %game-width 2.0) 2.0) #:font monogram-font #:text "score 0" #:align 'right #:color %text-color))) -(define-method (play-music (game <game>) music-asset) - (set-source-audio! (music-source game) (asset-ref music-asset)) - (source-play (music-source game))) +(define-method (update (hud <hud>) dt) + (let ((p (& (parent hud) player))) + (when (not (= (last-lives hud) (lives p))) + (set! (text (& hud lives)) + (string-append "lives " (number->string (lives p))))) + (when (not (= (last-pollen hud) (pollen p))) + (let ((n (pollen p))) + (set! (text (& hud pollen)) + (string-append "pollen " + (if (= n %max-pollen) "MAX" (number->string n)))))) + (when (not (= (last-score hud) (score p))) + (set! (text (& hud score)) + (string-append "score " (number->string (score p))))) + (set! (last-lives hud) (lives p)) + (set! (last-pollen hud) (pollen p)) + (set! (last-score hud) (score p)))) + + +;;; +;;; Game scene +;;; + +(define %game-bounds (make-rect 0.0 0.0 %game-width %game-height)) +(define %default-player-position (vec2 (/ %game-width 2.0) 20.0)) + +(define-class <game-scene> (<scene>) + (quadtree #:getter quadtree #:init-form (make-quadtree %game-bounds)) + (scroll-speed #:getter scroll-speed #:init-value 0.0) + (music-source #:getter music-source #:init-form (make-source #:loop? #t)) + (intro-script #:accessor intro-script #:init-value #f)) + +(define-method (change-scroll-speed (scene <game-scene>) speed) + (slot-set! scene 'scroll-speed speed)) + +(define-method (spawn (scene <game-scene>) (actor <actor>)) + (set! (quadtree actor) (quadtree scene)) + (quadtree-insert! (quadtree scene) (world-hitbox actor) actor) + (attach-to scene actor)) + +(define-method (play-music (scene <game-scene>) music-asset) + (set-source-audio! (music-source scene) (artifact music-asset)) + (source-play (music-source scene))) (define* (make-turret p #:key (interval 0.5) (speed 1.0)) (let ((turret (make <turret> @@ -130,11 +142,11 @@ (run-script turret (sleep (steps 1)) (forever - (let ((theta (+ (angle-to turret (player (parent turret))) + (let ((theta (+ (angle-to turret (& (parent turret) player)) (* (- (* (random:uniform) 2.0) 1.0) 0.2))) (speed 1.5)) - (audio-play (asset-ref enemy-shoot-sound)) - (add-bullet (bullets (parent turret)) + (audio-play (artifact enemy-shoot-sound)) + (add-bullet (& (parent turret) bullets) medium-enemy-bullet (position turret) (vec2 (* (cos theta) speed) @@ -168,11 +180,14 @@ #:health 20 #:points 1000)) -(define-method (change-state (game <game>) new-state) - (set! (state game) new-state)) +(define-method (skip-intro (scene <game-scene>)) + (teleport (& scene player) + (vec2-x %default-player-position) + (vec2-y %default-player-position)) + (cancel-script (intro-script scene))) -(define-method (run-level (game <game>)) - (define (tutorial message key) +(define-method (run-level (scene <game-scene>)) + (define (tutorial message continue?) (let ((l (make <shadow-label> #:name 'tutorial #:rank 5 @@ -181,160 +196,196 @@ #:text message #:align 'center #:color %text-color))) - (attach-to game l) - (if key - (wait-until (key-pressed? key)) + (attach-to scene l) + (if continue? + (begin + (wait-until (continue?)) + (sleep 1.0)) (sleep 2.0)) (detach l))) - (run-script game - (fade-in game 1.0)) - (run-script game - (unless (getenv "SKIP_INTRO") - ;; Intro - (let ((popcorn (make-popcorn (vec2 (/ %game-width 2.0) (+ %game-height 16.0)))) - (bullet-speed 5.0) - (flower-1 (make-flower (vec2 194.0 210.0))) - (flower-2 (make-flower (vec2 50.0 206.0))) - (flower-3 (make-flower (vec2 280.0 201.0))) - (flower-4 (make-flower (vec2 121.0 197.0))) - (flower-5 (make-flower (vec2 58.0 134.0))) - (flower-6 (make-flower (vec2 145.0 135.0))) - (flower-7 (make-flower (vec2 220.0 151.0))) - (flower-8 (make-flower (vec2 290.0 129.0)))) - (define (shoot-at flower) - (add-bullet (bullets game) - medium-enemy-bullet - (position popcorn) - (vec2* (direction-to popcorn flower) bullet-speed))) - (change-state game 'intro) - (spawn game flower-1) - (spawn game flower-2) - (spawn game flower-3) - (spawn game flower-4) - (spawn game flower-5) - (spawn game flower-6) - (spawn game flower-7) - (spawn game flower-8) - (spawn game (make-flower (vec2 194.0 95.0))) - (spawn game (make-flower (vec2 102.0 82.0))) - (spawn game (make-flower (vec2 247.0 45.0))) - (spawn game (make-flower (vec2 159.0 40.0))) - (spawn game (make-flower (vec2 73.0 28.0))) - (teleport (player game) 159.0 40.0) - (play-music game intro-music) - (sleep 1.0) - (audio-play (asset-ref pollen-release-sound)) - (sleep 0.6) - (move-to (player game) 247.0 45.0 1.0) - (sleep 0.2) - (audio-play (asset-ref pollen-release-sound)) - (sleep 0.6) - (move-to (player game) 102.0 76.0 1.0) - (sleep 0.2) - (audio-play (asset-ref pollen-release-sound)) - (sleep 2.0) - (run-script game - (tween 1.0 1.0 0.0 - (lambda (volume) - (set-source-volume! (music-source game) volume)))) - (source-stop (music-source game)) - (spawn game popcorn) - (change-velocity popcorn 0.0 -1.0) - (tween 2.4 -1.0 0.0 - (lambda (dy) - (change-velocity popcorn 0.0 dy))) - (shoot-at flower-1) - (sleep 0.3) - (shoot-at flower-2) - (sleep 0.3) - (shoot-at flower-3) - (sleep 0.3) - (shoot-at flower-4) - (sleep 0.3) - (shoot-at flower-8) - (sleep 0.3) - (shoot-at flower-7) - (sleep 0.3) - (shoot-at flower-6) - (sleep 0.3) - (shoot-at flower-5) - (sleep 1.0) - (audio-play (asset-ref hehehe-sound)) - (sleep 1.0) - (tween 0.5 0.0 1.5 - (lambda (dy) - (change-velocity popcorn 0.0 dy))) - (sleep 1.0))) + (run-script scene + (fade-in scene 1.0)) + (run-script scene + (set! (scoring-enabled? (& scene player)) #f) + (set! (intro-script scene) + (run-script scene + ;; Intro + (let ((popcorn (make-popcorn (vec2 (/ %game-width 2.0) (+ %game-height 16.0)))) + (bullet-speed 5.0) + (flower-1 (make-flower (vec2 194.0 210.0))) + (flower-2 (make-flower (vec2 50.0 206.0))) + (flower-3 (make-flower (vec2 280.0 201.0))) + (flower-4 (make-flower (vec2 121.0 197.0))) + (flower-5 (make-flower (vec2 58.0 134.0))) + (flower-6 (make-flower (vec2 145.0 135.0))) + (flower-7 (make-flower (vec2 220.0 151.0))) + (flower-8 (make-flower (vec2 290.0 129.0)))) + (define (shoot-at flower) + (add-bullet (& scene bullets) + medium-enemy-bullet + (position popcorn) + (vec2* (direction-to popcorn flower) bullet-speed))) + (spawn scene flower-1) + (spawn scene flower-2) + (spawn scene flower-3) + (spawn scene flower-4) + (spawn scene flower-5) + (spawn scene flower-6) + (spawn scene flower-7) + (spawn scene flower-8) + (spawn scene (make-flower (vec2 194.0 95.0))) + (spawn scene (make-flower (vec2 102.0 82.0))) + (spawn scene (make-flower (vec2 247.0 45.0))) + (spawn scene (make-flower (vec2 159.0 40.0))) + (spawn scene (make-flower (vec2 73.0 28.0))) + (teleport (& scene player) 159.0 40.0) + (play-music scene intro-music) + (sleep 1.0) + (audio-play (artifact pollen-release-sound)) + (sleep 0.6) + (move-to (& scene player) 247.0 45.0 1.0) + (sleep 0.2) + (audio-play (artifact pollen-release-sound)) + (sleep 0.6) + (move-to (& scene player) 102.0 76.0 1.0) + (sleep 0.2) + (audio-play (artifact pollen-release-sound)) + (sleep 2.0) + (run-script scene + (tween 1.0 1.0 0.0 + (lambda (volume) + (set-source-volume! (music-source scene) volume)))) + (source-stop (music-source scene)) + (spawn scene popcorn) + (change-velocity popcorn 0.0 -1.0) + (tween 2.4 -1.0 0.0 + (lambda (dy) + (change-velocity popcorn 0.0 dy))) + (shoot-at flower-1) + (sleep 0.3) + (shoot-at flower-2) + (sleep 0.3) + (shoot-at flower-3) + (sleep 0.3) + (shoot-at flower-4) + (sleep 0.3) + (shoot-at flower-8) + (sleep 0.3) + (shoot-at flower-7) + (sleep 0.3) + (shoot-at flower-6) + (sleep 0.3) + (shoot-at flower-5) + (sleep 1.0) + (audio-play (artifact hehehe-sound)) + (sleep 1.0) + (tween 0.5 0.0 1.5 + (lambda (dy) + (change-velocity popcorn 0.0 dy))) + (sleep 1.0) + (enable-pollen!) + (replace-major-mode scene (make <play-mode>)) + (play-music scene main-music) + (set-source-volume! (music-source scene) 1.0) + ;; Tutorial + (tutorial "move with ARROW keys or controller DPAD" + (lambda () + (moving? (& scene player)))) + (tutorial "press Z key or A button to shoot" + (lambda () + (shoot? (& scene player)))) + (sleep 2.0) + (tutorial "shoot FLOWERS and collect POLLEN for special power" #f) + (tutorial "press X key or B button to unleash stored power" + (lambda () + (let ((p (& scene player))) + (or (bombing? p) + ;; Ensure bomb can be used to avoid a soft lock. + (begin + (unless (= (pollen p) %max-pollen) + (set! (pollen p) %max-pollen)) + #f))))) + (tutorial "godspeed you, little bee!" #f)))) + (join (intro-script scene)) + (set! (intro-script scene) #f) + ;; The intro and tutorial sequence set up a bunch of state, but if + ;; the player skips it, we need to set it up here. Each of the + ;; following operations may be no-ops, depending on how far into + ;; the intro the player was before they skipped it. (enable-pollen!) - (change-state game 'play) - (play-music game main-music) - (set-source-volume! (music-source game) 1.0) - (unless (getenv "SKIP_TUTORIAL") - ;; Tutorial - (tutorial "move with ARROW keys" #f) - (tutorial "press Z to shoot" 'z) - (sleep 2.0) - (tutorial "shoot FLOWERS and collect POLLEN for special power" #f) - (tutorial "press X to unleash stored power" 'x) - (tutorial "godspeed you, little bee!" #f)) - (change-scroll-speed game 15.0) + (unless (is-a? (major-mode scene) <play-mode>) + (replace-major-mode scene (make <play-mode>))) + (play-music scene main-music) + (set-source-volume! (music-source scene) 1.0) + (set! (pollen (& scene player)) 0) + (and=> (& scene tutorial) detach) + (clear-bullets (& scene bullets)) + (for-each-child (lambda (child) + (when (and (is-a? child <actor>) + (not (is-a? child <player>))) + (detach child))) + scene) + ;; Start the game + (set! (scoring-enabled? (& scene player)) #t) + (change-scroll-speed scene 15.0) + (sleep 1.0) ;; Wave 1 (define* (popcorn-line n spawn-point velocity delay #:optional script) (let loop ((i 0)) (when (< i n) (let ((popcorn (make-popcorn (vec2-copy spawn-point) velocity))) - (spawn game popcorn) + (spawn scene popcorn) (when script (run-script popcorn (script popcorn)))) (sleep delay) (loop (+ i 1))))) (define (spawn-flower x) - (spawn game (make-flower (vec2 x (+ %game-height 32.0))))) + (spawn scene (make-flower (vec2 x (+ %game-height 32.0))))) (unless (getenv "SKIP_WAVE1") - (spawn game (make-flower (vec2 (- %game-width 64.0) (+ %game-height 32.0)))) + (spawn scene (make-flower (vec2 (- %game-width 64.0) (+ %game-height 32.0)))) (popcorn-line 5 (vec2 64.0 (+ %game-height 16.0)) (vec2 0.0 -2.0) 0.2) (sleep 0.5) (popcorn-line 5 (vec2 (- %game-width 64.0) (+ %game-height 16.0)) (vec2 0.0 -2.0) 0.2) (sleep 0.5) - (spawn game (make-flower (vec2 64.0 (+ %game-height 32.0)))) + (spawn scene (make-flower (vec2 64.0 (+ %game-height 32.0)))) (popcorn-line 5 (vec2 (/ %game-width 2.0) (+ %game-height 16.0)) (vec2 0.0 -2.0) 0.2) (sleep 1.0) - (run-script game + (run-script scene (popcorn-line 10 (vec2 -16.0 220.0) (vec2 3.0 -0.5) 0.2)) (popcorn-line 10 (vec2 (+ %game-width 16.0) 200.0) (vec2 -3.0 -0.5) 0.2) - (spawn game (make-flower (vec2 (/ %game-width 2.0) (+ %game-height 32.0)))) + (spawn scene (make-flower (vec2 (/ %game-width 2.0) (+ %game-height 32.0)))) (sleep 1.0) - (run-script game + (run-script scene (popcorn-line 30 (vec2 -16.0 220.0) (vec2 2.0 -2.0) 0.2)) - (run-script game + (run-script scene (popcorn-line 30 (vec2 (+ %game-width 16.0) 220.0) (vec2 -2.0 -2.0) 0.2)) - (spawn game (make-flower (vec2 128.0 (+ %game-height 32.0)))) + (spawn scene (make-flower (vec2 128.0 (+ %game-height 32.0)))) (sleep 2.0) - (run-script game + (run-script scene (popcorn-line 20 (vec2 -16.0 20.0) (vec2 2.0 2.0) 0.2)) - (spawn game (make-flower (vec2 256.0 (+ %game-height 32.0)))) + (spawn scene (make-flower (vec2 256.0 (+ %game-height 32.0)))) (popcorn-line 20 (vec2 (+ %game-width 16.0) 20.0) (vec2 -2.0 2.0) 0.2) (sleep 3.0)) ;; Wave 2 (define (spawn-turret x) - (spawn game (make-turret (vec2 x (+ %game-height 32.0))))) + (spawn scene (make-turret (vec2 x (+ %game-height 32.0))))) (define (shoot-down enemy) (sleep 0.2) (repeat 10 - (add-bullet (bullets game) - medium-enemy-bullet - (position enemy) - (vec2 0.0 -2.0)) - (sleep 0.1))) + (add-bullet (& scene bullets) + medium-enemy-bullet + (position enemy) + (vec2 0.0 -2.0)) + (sleep 0.1))) (unless (getenv "SKIP_WAVE2") (popcorn-line 10 (vec2 (+ %game-width 16.0) 200.0) (vec2 -3.0 -0.5) 0.2) @@ -409,7 +460,7 @@ (popcorn-line 10 (vec2 (+ %game-width 16.0) 200.0) (vec2 -3.0 -0.5) 0.2) (sleep 1.0) - (run-script game + (run-script scene (spawn-turret (* %game-width 0.25)) (sleep 2.0) (spawn-turret (* %game-width 0.75)) @@ -425,14 +476,14 @@ (- (random:uniform) 0.5))) (+ %game-height 16.0)) (vec2 0.0 -2.0)))) - (spawn game popcorn) + (spawn scene popcorn) (run-script popcorn (sleep 0.5) (tween 0.5 -2.0 0.0 (lambda (dy) (change-velocity popcorn 0.0 dy))) (let ((d (vec2-normalize - (vec2- (vec2+ (position (player game)) (vec2 0.0 16.0)) + (vec2- (vec2+ (position (& scene player)) (vec2 0.0 16.0)) (position popcorn))))) (tween 0.5 0.0 4.0 (lambda (speed) @@ -442,7 +493,7 @@ ;; Wave 3 (define (spawn-moth p) (let ((moth (make-moth p))) - (spawn game moth) + (spawn scene moth) (run-script moth (sleep 0.2) (tween 1.0 -2.0 0.0 @@ -456,11 +507,11 @@ (n 9) (arc-step (/ (- arc-end arc-start) n)) (speed 1.9)) - (audio-play (asset-ref enemy-shoot-sound)) + (audio-play (artifact enemy-shoot-sound)) (let arc-loop ((j 0)) (when (< j n) (let ((theta (+ arc-start (* j arc-step)))) - (add-bullet (bullets game) + (add-bullet (& scene bullets) medium-enemy-bullet (position moth) (vec2 (* (cos theta) speed) @@ -507,11 +558,11 @@ (sleep 7.0)) ;; Boss (unless (getenv "SKIP_BOSS") - (run-script game + (run-script scene (repeat 8 - (audio-play (asset-ref alarm-sound)) + (audio-play (artifact alarm-sound)) (sleep 1.0))) - (run-script game + (run-script scene (let ((warning (make <shadow-label> #:name 'warning #:rank 9 @@ -520,11 +571,11 @@ #:text "WARNING!! BIG OL' BAD THING AHEAD!" #:align 'center #:color %text-color))) - (attach-to game warning) + (attach-to scene warning) (blink warning 15 0.25) (detach warning))) (sleep 7.0) - (spawn game (make <boss> + (spawn scene (make <boss> #:name 'boss #:rank 2 #:position (vec2 (/ %game-width 2.0) @@ -535,49 +586,65 @@ (sleep 4.5) (tween 1.0 15.0 0.0 (lambda (speed) - (change-scroll-speed game speed))) - (wait-until (dead? (& game boss))) - (clear-bullets (bullets game))) + (change-scroll-speed scene speed))) + (wait-until (dead? (& scene boss))) + (clear-bullets (& scene bullets))) ;; Victory! - (set! (invincible? (player game)) #t) - (add-to-score (player game) (* (lives (player game)) 50000)) - (game-complete game))) + (set! (invincible? (& scene player)) #t) + (add-to-score (& scene player) (* (lives (& scene player)) 50000)) + (game-complete scene))) -(define-method (reset-game (game <game>)) - (stop-scripts game) +(define-method (reset-game (scene <game-scene>)) + (stop-scripts scene) (disable-pollen!) - (change-scroll-speed game 0.0) - (clear-bullets (bullets game)) - (quadtree-clear! (quadtree game)) - (show (& game hud-lives)) - (show (& game hud-pollen)) + (change-scroll-speed scene 0.0) + (clear-bullets (& scene bullets)) + (quadtree-clear! (quadtree scene)) + (show (& scene hud lives)) + (show (& scene hud pollen)) (for-each-child (lambda (child) (when (or (is-a? child <actor>) (memq (name child) '(game-over game-complete tutorial warning))) (detach child))) - game) - (spawn game + scene) + (spawn scene (make <player> #:name 'player #:rank 3 - #:position (vec2 (/ %game-width 2.0) 20.0) + #:position (vec2-copy %default-player-position) #:hitbox (make-rect -0.5 -0.5 1.0 1.0))) - (run-level game)) + (run-level scene)) -(define-method (on-enter (game <game>)) - (reset-game game)) +(define-method (on-boot (scene <game-scene>)) + (attach-to scene + (make <background> + #:name 'background + #:texture background-image) + (make <particles> + #:name 'particles + #:particles (make-particles 2048 + #:texture (artifact particle-image) + #:end-color (make-color 1.0 1.0 1.0 0.0))) + (make <bullets> + #:name 'bullets + #:rank 4 + #:quadtree (quadtree scene)) + (make <hud> + #:name 'hud + #:rank 5))) -(define-method (game-complete (game <game>)) - (hide (& game hud-pollen)) +(define-method (game-complete (scene <game-scene>)) + (set! (scoring-enabled? (& scene player)) #f) + (hide (& scene hud pollen)) (tween 1.0 1.0 0.0 (lambda (volume) - (set-source-volume! (music-source game) volume))) - (source-stop (music-source game)) - (play-music game intro-music) - (set-source-volume! (music-source game) 1.0) - (change-state game 'pre-game-complete) - (let ((p (player game))) + (set-source-volume! (music-source scene) volume))) + (source-stop (music-source scene)) + (play-music scene intro-music) + (set-source-volume! (music-source scene) 1.0) + (replace-major-mode scene (make <nothing-mode>)) + (let ((p (& scene player))) (stop-scripts p) (set! (shoot? p) #f) (set! (move-left? p) #f) @@ -585,20 +652,20 @@ (set! (move-down? p) #f) (set! (move-up? p) #f)) (sleep 1.0) - (audio-play (asset-ref pickup-sound)) - (spawn game (make-flower (vec2 (/ %game-width 4) 160.0))) + (audio-play (artifact pickup-sound)) + (spawn scene (make-flower (vec2 (/ %game-width 4) 160.0))) (sleep 1.0) - (audio-play (asset-ref pickup-sound)) - (spawn game (make-flower (vec2 (/ %game-width 2) 160.0))) + (audio-play (artifact pickup-sound)) + (spawn scene (make-flower (vec2 (/ %game-width 2) 160.0))) (sleep 1.0) - (audio-play (asset-ref pickup-sound)) - (spawn game (make-flower (vec2 (- %game-width (/ %game-width 4)) 160.0))) + (audio-play (artifact pickup-sound)) + (spawn scene (make-flower (vec2 (- %game-width (/ %game-width 4)) 160.0))) (sleep 1.0) - (change-state game 'game-complete) + (replace-major-mode scene (make <game-complete-mode>)) (let ((group (make <node-2d> #:name 'game-complete #:rank 5))) - (attach-to game group) + (attach-to scene group) (attach-to group (make <shadow-label> #:position (vec2 (/ %game-width 2.0) (/ %game-height 2.0)) @@ -609,22 +676,23 @@ (make <shadow-label> #:position (vec2 (/ %game-width 2.0) (- (/ %game-height 2.0) 20.0)) #:font monogram-font - #:text "press ENTER to play again" + #:text "press ENTER key or START button to play again" #:align 'center #:color %text-color))) (forever - (add-bullet (bullets game) + (add-bullet (& scene bullets) pollen-pickup (vec2 (random %game-width) (+ %game-height 0.0)) (vec2 0.0 (- (+ (random:uniform) 0.5)))) (sleep 0.1))) -(define-method (game-over (game <game>)) - (hide (& game hud-lives)) - (hide (& game hud-pollen)) - (change-state game 'game-over) - (stop-scripts game) - (let ((p (player game))) +(define-method (game-over (scene <game-scene>)) + (set! (scoring-enabled? (& scene player)) #f) + (hide (& scene hud lives)) + (hide (& scene hud pollen)) + (replace-major-mode scene (make <game-over-mode>)) + (stop-scripts scene) + (let ((p (& scene player))) (stop-scripts p) (hide p) (set! (shoot? p) #f) @@ -632,14 +700,14 @@ (set! (move-right? p) #f) (set! (move-down? p) #f) (set! (move-up? p) #f)) - (run-script game - (tween 1.0 (scroll-speed game) 0.0 + (run-script scene + (tween 1.0 (scroll-speed scene) 0.0 (lambda (speed) - (change-scroll-speed game speed)))) + (change-scroll-speed scene speed)))) (let ((group (make <node-2d> #:name 'game-over #:rank 5))) - (attach-to game group) + (attach-to scene group) (attach-to group (make <shadow-label> #:position (vec2 (/ %game-width 2.0) (/ %game-height 2.0)) @@ -650,21 +718,21 @@ (make <shadow-label> #:position (vec2 (/ %game-width 2.0) (- (/ %game-height 2.0) 20.0)) #:font monogram-font - #:text "press ENTER to try again" + #:text "press ENTER key or START button to try again" #:align 'center #:color %text-color)))) -(define-method (toggle-pause (game <game>)) - (if (paused? game) +(define-method (toggle-pause (scene <game-scene>)) + (if (paused? scene) (begin - (detach (& game pause-overlay)) - (source-play (music-source game)) - (resume game)) + (detach (& scene pause-overlay)) + (source-play (music-source scene)) + (resume scene)) (let ((overlay (make <node-2d> #:name 'pause-overlay #:rank 99))) - (pause game) - (source-pause (music-source game)) + (pause scene) + (source-pause (music-source scene)) (attach-to overlay (make <sprite> #:texture darkness-image @@ -676,110 +744,145 @@ #:align 'center #:vertical-align 'center #:color %text-color)) - (attach-to game overlay)))) + (attach-to scene overlay)))) -(define-method (play-again (game <game>)) - (change-state game 'play-again) - (run-script game +(define-method (play-again (scene <game-scene>)) + (replace-major-mode scene (make <nothing-mode>)) + (run-script scene (tween 0.5 1.0 0.0 (lambda (volume) - (set-source-volume! (music-source game) volume))) - (source-stop (music-source game)) - (set-source-volume! (music-source game) 1.0)) - (run-script game - (fade-out game 1.0) - (reset-game game))) - -(define-method (close-game (game <game>)) - (pop-scene (current-kernel))) - -(define-method (on-quit (game <game>)) - (close-game game)) - -(define-method (on-key-press (game <game>) key modifiers repeat?) - (case (state game) - ((play) - (case key - ((left) - (set! (move-left? (player game)) #t)) - ((right) - (set! (move-right? (player game)) #t)) - ((down) - (set! (move-down? (player game)) #t)) - ((up) - (set! (move-up? (player game)) #t)) - ((z) - (set! (shoot? (player game)) #t)) - ((x) - (bomb (player game))) - ((escape) - (close-game game)) - ((return) - (toggle-pause game)))) - ((intro) - (case key - ((escape) - (close-game game)) - ((return) - (toggle-pause game)))) - ((game-over game-complete) - (case key - ((escape) - (close-game game)) - ((return) - (play-again game)))))) - -(define-method (on-key-release (game <game>) key modifiers) - (case (state game) - ((play) - (case key - ((left) - (set! (move-left? (player game)) #f)) - ((right) - (set! (move-right? (player game)) #f)) - ((down) - (set! (move-down? (player game)) #f)) - ((up) - (set! (move-up? (player game)) #f)) - ((z) - (set! (shoot? (player game)) #f)))))) - -(define-method (update (game <game>) dt) + (set-source-volume! (music-source scene) volume))) + (source-stop (music-source scene)) + (set-source-volume! (music-source scene) 1.0)) + (run-script scene + (fade-out scene 1.0) + (replace-major-mode scene (make <intro-mode>)))) + +(define-method (clean-up-actors (scene <game-scene>)) + (let ((p (& scene player))) + ;; This probably shouldn't be here, but it is. + (shoot-maybe p (& scene bullets)) + ;; Remove dead actors and actors that have gone too far off + ;; screen. + (for-each-child (lambda (child) + (cond + ((dead? child) + (on-death child) + (quadtree-delete! (quadtree scene) + (world-hitbox child) + child) + (add-to-score (& scene player) (points child)) + (detach child)) + ((out-of-bounds? child) + (quadtree-delete! (quadtree scene) + (world-hitbox child) + child) + (detach child)))) + scene) + (when (= (lives p) 0) ; bummer + (game-over scene)))) + +(define-method (update (scene <game-scene>) dt) (next-method) - (let ((bg (& game background))) - (set! (scroll-y bg) (+ (scroll-y bg) (* (scroll-speed game) dt)))) - (case (state game) - ((intro play) - (let ((p (player game))) - (when (not (= (last-lives game) (lives p))) - (set! (text (& game hud-lives)) - (string-append "lives " (number->string (lives p)))) - (when (= (lives p) 0) - (game-over game))) - (when (not (= (last-pollen game) (pollen p))) - (let ((n (pollen p))) - (set! (text (& game hud-pollen)) - (string-append "pollen " - (if (= n %max-pollen) "MAX" (number->string n)))))) - (when (not (= (last-score game) (score p))) - (set! (text (& game hud-score)) - (string-append "score " (number->string (score p))))) - (set! (last-lives game) (lives p)) - (set! (last-pollen game) (pollen p)) - (set! (last-score game) (score p)) - (shoot-maybe p (bullets game)) - (for-each-child (lambda (child) - (cond - ((dead? child) - (on-death child) - (quadtree-delete! (quadtree game) - (world-hitbox child) - child) - (add-to-score (player game) (points child)) - (detach child)) - ((out-of-bounds? child) - (quadtree-delete! (quadtree game) - (world-hitbox child) - child) - (detach child)))) - game))))) + (let ((bg (& scene background))) + (set! (scroll-y bg) (+ (scroll-y bg) (* (scroll-speed scene) dt))))) + + +;;; +;;; Modes +;;; + +(define-method (close-game (mode <major-mode>)) + (exit-catbird)) + +(define-method (pause-game (mode <major-mode>)) + (toggle-pause (parent mode))) + +(define-method (skip-intro (mode <major-mode>)) + (skip-intro (parent mode))) + +(define-class <intro-mode> (<major-mode>)) + +(define-method (on-enter (mode <intro-mode>)) + (reset-game (parent mode))) + +(define-method (update (mode <intro-mode>) dt) + (clean-up-actors (parent mode))) + +(bind-input <intro-mode> (key-press 'escape) close-game) +(bind-input <intro-mode> (key-press 'return) skip-intro) +(bind-input <intro-mode> (controller-press '0 'back) close-game) +(bind-input <intro-mode> (controller-press '0 'start) skip-intro) + +(define-class <play-mode> (<major-mode>)) + +(define-method (update (mode <play-mode>) dt) + (clean-up-actors (parent mode))) + +(define (move-command accessor value) + (lambda (mode) + (set! (accessor (& (parent mode) player)) value))) + +(define-method (player-shoot (mode <play-mode>)) + (set! (shoot? (& (parent mode) player)) #t)) + +(define-method (player-stop-shooting (mode <play-mode>)) + (set! (shoot? (& (parent mode) player)) #f)) + +(define-method (player-bomb (mode <play-mode>)) + (bomb (& (parent mode) player))) + +(define-method (skip-intro-or-pause-game (mode <play-mode>)) + (let ((scene (parent mode))) + (if (intro-script scene) + (skip-intro scene) + (toggle-pause scene)))) + +(bind-input <play-mode> (key-press 'left) (move-command move-left? #t)) +(bind-input <play-mode> (key-press 'right) (move-command move-right? #t)) +(bind-input <play-mode> (key-press 'down) (move-command move-down? #t)) +(bind-input <play-mode> (key-press 'up) (move-command move-up? #t)) +(bind-input <play-mode> (key-release 'left) (move-command move-left? #f)) +(bind-input <play-mode> (key-release 'right) (move-command move-right? #f)) +(bind-input <play-mode> (key-release 'down) (move-command move-down? #f)) +(bind-input <play-mode> (key-release 'up) (move-command move-up? #f)) +(bind-input <play-mode> (key-press 'z) player-shoot) +(bind-input <play-mode> (key-release 'z) player-stop-shooting) +(bind-input <play-mode> (key-press 'x) player-bomb) +(bind-input <play-mode> (key-press 'escape) close-game) +(bind-input <play-mode> (key-press 'return) skip-intro-or-pause-game) +(bind-input <play-mode> (controller-press 0 'dpad-left) (move-command move-left? #t)) +(bind-input <play-mode> (controller-press 0 'dpad-right) (move-command move-right? #t)) +(bind-input <play-mode> (controller-press 0 'dpad-down) (move-command move-down? #t)) +(bind-input <play-mode> (controller-press 0 'dpad-up) (move-command move-up? #t)) +(bind-input <play-mode> (controller-release 0 'dpad-left) (move-command move-left? #f)) +(bind-input <play-mode> (controller-release 0 'dpad-right) (move-command move-right? #f)) +(bind-input <play-mode> (controller-release 0 'dpad-down) (move-command move-down? #f)) +(bind-input <play-mode> (controller-release 0 'dpad-up) (move-command move-up? #f)) +(bind-input <play-mode> (controller-press 0 'a) player-shoot) +(bind-input <play-mode> (controller-release 0 'a) player-stop-shooting) +(bind-input <play-mode> (controller-press 0 'b) player-bomb) +(bind-input <play-mode> (controller-press 0 'back) close-game) +(bind-input <play-mode> (controller-press 0 'start) skip-intro-or-pause-game) + +(define-class <game-over-mode> (<major-mode>)) + +(define-method (play-game-again (mode <major-mode>)) + (play-again (parent mode))) + +(bind-input <game-over-mode> (key-press 'escape) close-game) +(bind-input <game-over-mode> (key-press 'return) play-game-again) +(bind-input <game-over-mode> (controller-press 0 'back) close-game) +(bind-input <game-over-mode> (controller-press 0 'start) play-game-again) + +(define-class <game-complete-mode> (<major-mode>)) + +(bind-input <game-complete-mode> (key-press 'escape) close-game) +(bind-input <game-complete-mode> (key-press 'return) play-game-again) +(bind-input <game-complete-mode> (controller-press 0 'back) close-game) +(bind-input <game-complete-mode> (controller-press 0 'start) play-game-again) + +(define (make-game-scene) + (let ((scene (make <game-scene>))) + (replace-major-mode scene (make <intro-mode>)) + scene)) diff --git a/bonnie-bee/moth.scm b/bonnie-bee/moth.scm index bcd165b..ac0aa6a 100644 --- a/bonnie-bee/moth.scm +++ b/bonnie-bee/moth.scm @@ -10,9 +10,9 @@ #:use-module (chickadee scripting) #:use-module (chickadee utils) #:use-module (oop goops) - #:use-module (starling asset) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird asset) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (<moth>)) (define-class <moth> (<damageable> <actor>)) @@ -38,8 +38,8 @@ (else #f))) (define-method (on-death (moth <moth>)) - (audio-play (asset-ref explosion-sound)) + (audio-play (artifact explosion-sound)) (let ((p (position moth))) - (add-particle-emitter (particles (particles (parent moth))) + (add-particle-emitter (particles (& (parent moth) particles)) (make-particle-emitter (make-rect (vec2-x p) (vec2-y p) 1.0 1.0) 4 3)))) diff --git a/bonnie-bee/player.scm b/bonnie-bee/player.scm index 1a524e7..09770a0 100644 --- a/bonnie-bee/player.scm +++ b/bonnie-bee/player.scm @@ -11,17 +11,20 @@ #:use-module (chickadee math vector) #:use-module (chickadee scripting) #:use-module (oop goops) - #:use-module (starling asset) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird asset) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (%max-pollen <player> move-left? move-right? move-down? move-up? + moving? shoot? invincible? + bombing? + scoring-enabled? speed lives pollen @@ -45,8 +48,15 @@ (invincible? #:accessor invincible? #:init-value #f) (pollen #:accessor pollen #:init-value 0) (score #:accessor score #:init-value 0) + (scoring-enabled? #:accessor scoring-enabled? #:init-value #f) (bombing? #:accessor bombing? #:init-value #f)) +(define-method (moving? (player <player>)) + (or (move-left? player) + (move-right? player) + (move-down? player) + (move-up? player))) + (define-method (on-boot (player <player>)) (attach-to player (make <animated-sprite> @@ -116,8 +126,8 @@ (set! (lives player) (max (- (lives player) 1) 0)) (set! (pollen player) 0) (set! (invincible? player) #t) - (audio-play (asset-ref player-death-sound)) - (add-particle-emitter (particles (particles (parent player))) + (audio-play (artifact player-death-sound)) + (add-particle-emitter (particles (& (parent player) particles)) (make-particle-emitter (world-hitbox player) 10 5)) (run-script player @@ -127,7 +137,7 @@ (define-method (on-collide (player <player>) (bullet <bullet>)) (cond ((eq? (type bullet) pollen-pickup) - (audio-play (asset-ref pickup-sound) #:volume 0.3) + (audio-play (artifact pickup-sound) #:volume 0.3) (kill-bullet bullet) (add-to-score player 5) (set! (pollen player) (min (+ (pollen player) 1) %max-pollen)) @@ -159,7 +169,7 @@ (shot-interval player))) (let ((p (position player))) (set! (last-shot player) (agenda-time)) - (audio-play (asset-ref player-shoot-sound) #:volume 0.2) + (audio-play (artifact player-shoot-sound) #:volume 0.2) (add-bullet bullets player-primary-bullet (vec2 (vec2-x p) (+ (vec2-y p) 14.0)) @@ -174,14 +184,14 @@ (radius 16.0) (speed 5.0) (p (position player)) - (bullets (bullets (parent player)))) + (bullets (& (parent player) bullets))) (add-to-score player (expt 5 times)) (set! (bombing? player) #t) (set! (pollen player) 0) (set! (invincible? player) #t) (let loop ((i 0)) (when (< i times) - (audio-play (asset-ref player-bomb-sound)) + (audio-play (artifact player-bomb-sound)) (let shot-loop ((j 0)) (when (< j num-bullets) (let ((theta (* j theta-step))) @@ -198,4 +208,5 @@ (set! (bombing? player) #f))))) (define-method (add-to-score (player <player>) points) - (set! (score player) (+ (score player) points))) + (when (scoring-enabled? player) + (set! (score player) (+ (score player) points)))) diff --git a/bonnie-bee/pollen.scm b/bonnie-bee/pollen.scm index 97aaf0e..941fa77 100644 --- a/bonnie-bee/pollen.scm +++ b/bonnie-bee/pollen.scm @@ -4,8 +4,8 @@ #:use-module (chickadee math rect) #:use-module (chickadee math vector) #:use-module (oop goops) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (<pollen>)) (define-class <pollen> (<actor>)) diff --git a/bonnie-bee/popcorn.scm b/bonnie-bee/popcorn.scm index 594e88c..1fde520 100644 --- a/bonnie-bee/popcorn.scm +++ b/bonnie-bee/popcorn.scm @@ -10,9 +10,9 @@ #:use-module (chickadee scripting) #:use-module (chickadee utils) #:use-module (oop goops) - #:use-module (starling asset) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird asset) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (<popcorn>)) (define-class <popcorn> (<damageable> <actor>)) @@ -35,8 +35,8 @@ #f)) (define-method (on-death (popcorn <popcorn>)) - (audio-play (asset-ref explosion-sound)) + (audio-play (artifact explosion-sound)) (let ((p (position popcorn))) - (add-particle-emitter (particles (particles (parent popcorn))) + (add-particle-emitter (particles (& (parent popcorn) particles)) (make-particle-emitter (make-rect (vec2-x p) (vec2-y p) 1.0 1.0) 4 3)))) diff --git a/bonnie-bee/splash.scm b/bonnie-bee/splash.scm index 7059f91..09fcb47 100644 --- a/bonnie-bee/splash.scm +++ b/bonnie-bee/splash.scm @@ -6,56 +6,69 @@ #:use-module (chickadee math vector) #:use-module (chickadee scripting) #:use-module (oop goops) - #:use-module (starling kernel) - #:use-module (starling node) - #:use-module (starling node-2d) - #:use-module (starling scene) + #:use-module (catbird) + #:use-module (catbird camera) + #:use-module (catbird kernel) + #:use-module (catbird mode) + #:use-module (catbird node) + #:use-module (catbird node-2d) + #:use-module (catbird region) + #:use-module (catbird scene) #:export (launch-game)) -(define-class <splash> (<scene-2d>)) +(define-class <splash-mode> (<major-mode>)) (define %text-color (rgb #x181425)) -(define-method (on-boot (splash <splash>)) - (set-cameras! splash) - (attach-to splash - (make <sprite> - #:texture lightness-image) - (make <sprite> - #:texture chickadee-image - #:position (vec2 (/ %game-width 2.0) - (/ %game-height 2.0)) - #:origin (vec2 8.0 8.0) - #:scale (vec2 4.0 4.0)) - (make <label> - #:rank 1 - #:position (vec2 (/ %game-width 2.0) 70.5) - #:font monogram-font - #:color %text-color - #:align 'center - #:vertical-align 'center - #:text "Made with Chickadee") - (make <label> - #:rank 1 - #:position (vec2 (/ %game-width 2.0) 50.5) - #:font monogram-font - #:color %text-color - #:align 'center - #:vertical-align 'center - #:text "https://dthompson.us/projects/chickadee.html"))) - -(define-method (on-enter (splash <splash>)) - (run-script splash - (unless (getenv "SKIP_SPLASH") - (fade-in splash 1.0) - (sleep 1.0) - (fade-out splash 1.0)) - (replace-scene (current-kernel) (make <game>)))) +(define-method (on-enter (mode <splash-mode>)) + (let ((scene (parent mode))) + (attach-to scene + (make <sprite> + #:texture lightness-image) + (make <sprite> + #:texture chickadee-image + #:position (vec2 (/ %game-width 2.0) + (/ %game-height 2.0)) + #:origin (vec2 8.0 8.0) + #:scale (vec2 4.0 4.0)) + (make <label> + #:rank 1 + #:position (vec2 (/ %game-width 2.0) 70.5) + #:font monogram-font + #:color %text-color + #:align 'center + #:vertical-align 'center + #:text "Made with Chickadee") + (make <label> + #:rank 1 + #:position (vec2 (/ %game-width 2.0) 50.5) + #:font monogram-font + #:color %text-color + #:align 'center + #:vertical-align 'center + #:text "https://dthompson.us/projects/chickadee.html")) + (run-script scene + (unless (getenv "SKIP_SPLASH") + (fade-in scene 1.0) + (sleep 1.0) + (fade-out scene 1.0)) + (let ((new-scene (make <scene>)) + (region (car (all-regions)))) + (replace-scene region (make-game-scene)))))) (define (launch-game) - (boot-kernel (make <kernel> - #:window-config (make <window-config> - #:title "Bonnie Bee and the Pesticidal Tendencies - Autumn Lisp Game Jam 2021" - #:width %window-width - #:height %window-height)) - (lambda () (make <splash>)))) + (set! *random-state* (random-state-from-platform)) + (run-catbird + (lambda () + (let ((region (create-full-region)) + (scene (make <scene>))) + (take-controller-focus 0 region) + (replace-scene region scene) + (replace-major-mode scene (make <splash-mode>)) + (set! (camera region) + (make <camera-2d> + #:width %game-width + #:height %game-height)))) + #:width %window-width + #:height %window-height + #:title "Bonnie Bee and the Pesticidal Tendencies")) diff --git a/bonnie-bee/turret.scm b/bonnie-bee/turret.scm index 5aae796..61a075c 100644 --- a/bonnie-bee/turret.scm +++ b/bonnie-bee/turret.scm @@ -10,9 +10,9 @@ #:use-module (chickadee scripting) #:use-module (chickadee utils) #:use-module (oop goops) - #:use-module (starling asset) - #:use-module (starling node) - #:use-module (starling node-2d) + #:use-module (catbird asset) + #:use-module (catbird node) + #:use-module (catbird node-2d) #:export (<turret>)) (define-class <turret> (<grounded> <damageable> <actor>)) @@ -38,15 +38,15 @@ (else #f))) (define-method (on-death (turret <turret>)) - (audio-play (asset-ref explosion-sound)) + (audio-play (artifact explosion-sound)) (let ((p (position turret))) - (add-particle-emitter (particles (particles (parent turret))) + (add-particle-emitter (particles (& (parent turret) particles)) (make-particle-emitter (make-rect (vec2-x p) (vec2-y p) 1.0 1.0) 10 3)) (for-range ((i 8)) (let ((theta (- (* (random:uniform) (/ pi -2.0)) (/ pi 4.0))) (speed (+ (* (random:uniform) 1.0) 1.0))) - (add-bullet (bullets (parent turret)) + (add-bullet (& (parent turret) bullets) medium-enemy-bullet p (vec2 (* (cos theta) speed) (* (sin theta) speed))))))) |