summaryrefslogtreecommitdiff
path: root/bonnie-bee
diff options
context:
space:
mode:
authorDavid Thompson <dthompson@vistahigherlearning.com>2022-10-12 06:48:14 -0400
committerDavid Thompson <dthompson@vistahigherlearning.com>2022-10-27 13:22:50 -0400
commite287a11c4387382277c31735504fc762c33b4cee (patch)
treeb262dc8de64db21a7d2cb2c980f2be39805d6a34 /bonnie-bee
parentf713890a773a7d6ff666277592eec72f2328a5b6 (diff)
Switch to Catbird engine.
Diffstat (limited to 'bonnie-bee')
-rw-r--r--bonnie-bee/actor.scm11
-rw-r--r--bonnie-bee/assets.scm63
-rw-r--r--bonnie-bee/background.scm10
-rw-r--r--bonnie-bee/boss.scm24
-rw-r--r--bonnie-bee/bullet.scm17
-rw-r--r--bonnie-bee/common.scm22
-rw-r--r--bonnie-bee/flower.scm14
-rw-r--r--bonnie-bee/game.scm791
-rw-r--r--bonnie-bee/moth.scm10
-rw-r--r--bonnie-bee/player.scm31
-rw-r--r--bonnie-bee/pollen.scm4
-rw-r--r--bonnie-bee/popcorn.scm10
-rw-r--r--bonnie-bee/splash.scm105
-rw-r--r--bonnie-bee/turret.scm12
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)))))))