summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lib/cells.fnl2
-rw-r--r--lib/game.fnl37
-rw-r--r--lib/main.fnl9
-rw-r--r--lib/music-state.fnl1
-rw-r--r--lib/music.fnl83
-rw-r--r--lib/player.fnl4
-rw-r--r--lib/transition.fnl3
7 files changed, 128 insertions, 11 deletions
diff --git a/lib/cells.fnl b/lib/cells.fnl
index e415f21..5cc104e 100644
--- a/lib/cells.fnl
+++ b/lib/cells.fnl
@@ -1,4 +1,5 @@
 (local cell (require :lib.cell))
+(local music-state (require :lib.music-state))
 
 (local neighbors [{:x -1 :y -1}
                   {:x -1 :y 0}
@@ -84,6 +85,7 @@
          nil))
    cell.update
    (fn [self get]
+     (set music-state.fire (math.max music-state.fire self.life))
      (if (> self.life 0.3)
          (setmetatable {:life (* self.life (+ 0.5 (* (math.random 5) 0.1)))} (getmetatable self))
          nil))
diff --git a/lib/game.fnl b/lib/game.fnl
index d07f58c..833de6b 100644
--- a/lib/game.fnl
+++ b/lib/game.fnl
@@ -6,6 +6,7 @@
 (local player (require :lib.player))
 (local transition (require :lib.transition))
 (local fv (require :fennel.view))
+(local music-state (require :lib.music-state))
 
 (fn lerp* [a b c d x]
   (+ c (* (/ (- x a) (- b a)) (- d c))))
@@ -19,6 +20,7 @@
   t)
 
 (fn update [self]
+  (set music-state.screen :game)
   ;; (set ship-pos.x (+ self.ship.x 0.02))
   ;; (set ship-pos.y (+ self.ship.y 0.005))
   (var grid-alive? true)
@@ -26,6 +28,8 @@
 
   (when (= self.tick 0)
     (set grid-alive? false)
+    (set music-state.fire 0)
+    (set music-state.alive 0)
     (for [x 0 (- self.width 1)]
       (for [y 0 (- self.height 1)]
         (fn get [v]
@@ -37,7 +41,8 @@
             (do
               (tset self.grid-alt x y (cell.update (. self.grid x y)
                                                  get))
-              (set grid-alive? true))
+              (set grid-alive? true)
+              (set music-state.alive (+ music-state.alive 1)))
             ;; check for neighbors and then use one at random
             (do
               (var neighbors [])
@@ -88,7 +93,7 @@
                   :death
                   self
                   ((. (getmetatable self) :inner-init)
-                   (getmetatable self) 1 self)
+                   (getmetatable self) (if (> self.level 0) 1 0) self)
                   self.level)
       (not grid-alive?)
       (state.init transition
@@ -204,6 +209,24 @@
              self.max-radius
              (+ self.target-radius 4))))))
 
+(fn make-level [level width height]
+  (if (= level 0)
+      (new-grid width height
+                #(if (or (and (= $2 61) (or (= $1 61) (= $1 62) (= $1 63)))
+                         (and (= $2 62) (= $1 61))
+                         (and (= $2 63) (= $1 62)))
+                     (cell.init cells.life)
+                     nil))
+      true
+      (new-grid width height
+                #(if (= (math.random 6) 1)
+                     (if (> $1 44)
+                         (cell.init cells.life)
+                         (< $1 10)
+                         (cell.init cells.brain)
+                         nil)
+                     nil))))
+
 (fn inner-init [self level past]
   (let [past (or past {})
         width 64
@@ -222,13 +245,7 @@
        :entities (if (= level -1)
                      {}
                      {:player (entity.init player {:x 31.5 :y 31.5})})
-       :grid (new-grid width height #(if (= (math.random 6) 1)
-                                         (if (> $1 44)
-                                             (cell.init cells.life)
-                                             (< $1 10)
-                                             (cell.init cells.brain)
-                                             nil)
-                                         nil))
+       :grid (make-level level width height)
        :grid-alt (new-grid width height #nil)
        }
       self)))
@@ -238,6 +255,6 @@
   (state.init transition
               :menu
               (self.inner-init self -1)
-              (self.inner-init self 1)))
+              (self.inner-init self 0)))
 
 {: inner-init state.draw draw state.init init state.update update state.keypressed keypressed}
diff --git a/lib/main.fnl b/lib/main.fnl
index 4a4de12..e88f704 100644
--- a/lib/main.fnl
+++ b/lib/main.fnl
@@ -2,6 +2,7 @@
 (local proto (require :lib.proto))
 (local state (require :lib.state))
 (local game (require :lib.game))
+(local music (require :lib.music))
 (local font (require :lib.font))
 (local profi (require :vendor.ProFi))
 (local profi? false)
@@ -12,6 +13,7 @@
 ;; TODO: ^
 (local hotswap-modules
   [:lib.player
+   :lib.music
    :lib.translation
    :lib.bullet
    :lib.cells
@@ -23,6 +25,7 @@
 ;; oh thats why it doesnt work lmao
 
 (fn love.load []
+  (music.load)
   (when profi?
     (profi:start)
     (set love.frame 0))
@@ -39,7 +42,7 @@
                 (love.graphics.print (.. "draw: \n" x))))
   (love.graphics.reset)
   ;; (love.graphics.setFont font.small)
-  (love.graphics.print (love.timer.getFPS))
+  ;; (love.graphics.print (love.timer.getFPS))
   ;; (love.graphics.print :soko font.big 100 100)
   (when true ;; debug stuff
     (love.graphics.print (table.concat
@@ -53,6 +56,7 @@
           (set v.ticks (- v.ticks 1))))))
 
 (fn love.update []
+  (music.pre-update)
   (when profi?
     (profi:startHooks)
     (set love.frame (+ love.frame 1))
@@ -69,10 +73,13 @@
                 (table.insert messages
                               {:ticks 1
                                :msg (.. "update: \n" x)})))
+  (music.update)
   (when profi?
     (profi:stopHooks)))
 
 (fn love.keypressed [key scancode repeat]
+  (when (and (= key "f") (not repeat))
+    (love.window.setFullscreen (not (love.window.getFullscreen))))
   (match (pcall #(state.keypressed the-state key scancode repeat))
     (true x) nil
     (false x) (do
diff --git a/lib/music-state.fnl b/lib/music-state.fnl
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/lib/music-state.fnl
@@ -0,0 +1 @@
+{}
diff --git a/lib/music.fnl b/lib/music.fnl
new file mode 100644
index 0000000..434855b
--- /dev/null
+++ b/lib/music.fnl
@@ -0,0 +1,83 @@
+(local s (require :lib.music-state))
+
+(local sample-rate 8000)
+(local bit-depth 8)
+(local channels 2)
+(local buffers 4)
+(local buffer-size 256)
+
+(fn osc [n freq]
+  (tset s.voices n (% (+ (. s.voices n) (/ freq sample-rate)) 1))
+  (if (= s.screen :game)
+      (math.max -1 (math.min 1 (* (math.sin (* math.pi 2 (. s.voices n))) 2)))
+      (math.max -1 (math.min 1 (* (math.sin (* math.pi 2 (math.min 0.3 (. s.voices n)))) 1)))))
+
+(fn fill [buffer n]
+  (set s.alive* (+ s.alive* (* 0.03 (- s.alive s.alive*))))
+  (when (= (math.random 0 30) 0)
+    ;; (print s.t)
+    (local index (math.random 3 31))
+    (tset s.rhythms index (math.random 3 8))
+    (tset s.freqs index (* (. s.freqs (- index 1))
+                           (. [1 1.2 1.2 1.2 1.5 1.5 1.2 (/ 4 3) 1.75 2]
+                              (math.random 10)))))
+  (for [x 0 (- n 1)]
+    (for [side 1 2]
+      (var total 0)
+      (for [z 0 15]
+        (local vn (+ (* z 2) side -1))
+        (set total
+             (+ total
+                (* (osc vn (* (math.max 0.6 (or s.speed 0)) (/ 0.6) (. s.freqs vn)))
+                   (if (< vn (+ (/ s.alive* 23) 1)) 1 0)
+                   0.04
+                   (math.max 0
+                             (- 1 (* 0.00005
+                                     (% (- s.t (* vn 1600))
+                                        (* (. s.rhythms vn) 1600)))))))))
+      (set total (+ total
+                    (* 0.3
+                       (+ s.fire
+                          (if s.forward 0.3 0)
+                          (if (and s.shot-age (> s.shot-age 0)) 0.4 0))
+                       (^ (- (math.random) 0.5) 2))))
+      (buffer:setSample x side total))
+    (set s.t (+ s.t 1))))
+
+(fn load []
+  (set s.t 0)
+  (set s.alive* 0)
+  (set s.ring {})
+  (set s.ring-index 1)
+  (set s.voices (do (var t []) (for [i 0 31] (tset t i 0)) t))
+  (set s.freqs (do (var t [])
+                 (for [i 0 31]
+                   (tset t i (* 110 (^ 1.2 (math.floor (/ i 2))))))
+                 t))
+  (set s.rhythms (do (var t [])
+                   (for [i 0 31] (tset t i (if (< i 2) 8 (< i 4) 6
+                                               (+ (/ i 2) 8))))
+                   t))
+  (set s.volumes (do (var t []) (for [i 0 31]
+                                  (tset t i (if (< i 6) 1 0))) t))
+  (set s.source (love.audio.newQueueableSource
+                  sample-rate
+                  bit-depth
+                  channels
+                  buffers))
+  (for [i 1 buffers]
+    (tset s.ring i (love.sound.newSoundData buffer-size sample-rate bit-depth channels))))
+
+(fn pre-update []
+  )
+
+(fn update []
+  (when (not (s.source:isPlaying))
+    (s.source:play))
+  (while (> (s.source:getFreeBufferCount) 0)
+    (fill (. s.ring s.ring-index) buffer-size)
+    (do)
+    (s.source:queue (. s.ring s.ring-index))
+    (set s.ring-index (+ (% s.ring-index buffers) 1))))
+
+{: load : update : pre-update}
diff --git a/lib/player.fnl b/lib/player.fnl
index 4693d2e..d40e980 100644
--- a/lib/player.fnl
+++ b/lib/player.fnl
@@ -3,6 +3,7 @@
 (local cell (require :lib.cell))
 (local cells (require :lib.cells))
 (local bullet (require :lib.bullet))
+(local music-state (require :lib.music-state))
 
 (fn init [self pos]
   (setmetatable {entity.position pos
@@ -15,6 +16,7 @@
 (fn steer [self game id controls]
   (when (> self.shot-age 0)
     (set self.shot-age (- self.shot-age 1)))
+  (set music-state.shot-age self.shot-age)
   ;; TODO: smooth turning
   (when controls.left
     (set self.target-spin (- self.target-spin 0.15)))
@@ -23,12 +25,14 @@
     (set self.target-spin (+ self.target-spin 0.15)))
   (set self.direction (% (+ self.direction (* self.target-spin 0.1)) (* math.pi 2)))
   (set self.target-spin (* self.target-spin 0.9))
+  (set music-state.forward controls.up)
   (when controls.up
     (local v (entity.velocity self))
     (set v.x (+ v.x (* (math.cos self.direction) 0.02)))
     (set v.y (+ v.y (* (math.sin self.direction) 0.02)))
     (when (> (vec.mag v) 0.8)
       (tset self entity.velocity (vec.mul v (/ 0.8 (vec.mag v))))))
+  (set music-state.speed (vec.mag (. self entity.velocity)))
   (when (and controls.shoot (= self.shot-age 0))
     (set self.shot-age 10)
     (local v (entity.velocity self))
diff --git a/lib/transition.fnl b/lib/transition.fnl
index 096de9e..e62dcb8 100644
--- a/lib/transition.fnl
+++ b/lib/transition.fnl
@@ -1,6 +1,7 @@
 (local state (require :lib.state))
 (local font (require :lib.font))
 (local translation (require :lib.translation))
+(local music-state (require :lib.music-state))
 
 (fn draw [self]
   (local (width height) (love.graphics.getDimensions))
@@ -34,6 +35,8 @@
   ;; TODO: actually update in case it returns something else
   (when (not= self.type :pause)
     (state.update self.present-state))
+  (when (= self.type :pause)
+    (set music-state.screen :pause))
   (set self.age (math.min 40 (+ self.age 1)))
   (if self.transition
       self.future-state