summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/cells.fnl25
-rw-r--r--lib/entity.fnl12
-rw-r--r--lib/game.fnl81
-rw-r--r--lib/main.fnl10
-rw-r--r--lib/player.fnl39
-rw-r--r--lib/vec.fnl27
6 files changed, 163 insertions, 31 deletions
diff --git a/lib/cells.fnl b/lib/cells.fnl
index dde8372..3a43010 100644
--- a/lib/cells.fnl
+++ b/lib/cells.fnl
@@ -63,4 +63,27 @@
         [0.2 0.2 0.3])
    })
 
-{: life : brain}
+(local boom
+  {cell.init
+   (fn [self]
+     (setmetatable {:life 1} self))
+   cell.birth
+   (fn [self get]
+     (if (and (> self.life 0.08)
+              (> (neighbors> get (* (if (> self.life 0.9) 0.3 0.1) (math.random 7))) 0))
+         (do
+           (setmetatable {:life (* self.life 0.8)} (getmetatable self)))
+         nil))
+   cell.update
+   (fn [self get]
+     (if (> self.life 0.3)
+         (setmetatable {:life (* self.life (+ 0.5 (* (math.random 5) 0.1)))} (getmetatable self))
+         nil))
+   cell.aliveness
+   #$.life
+   cell.color
+   #[(+ 0.4 (* 0.6 $.life))
+     (math.max 0 (- 0.8 (* 0.9 (- 1 $.life))))
+     (+ 0.1 )]})
+
+{: life : brain : boom}
diff --git a/lib/entity.fnl b/lib/entity.fnl
new file mode 100644
index 0000000..2032e65
--- /dev/null
+++ b/lib/entity.fnl
@@ -0,0 +1,12 @@
+(local proto (require :lib.proto))
+
+{:init (proto.table-method :entity.init)
+ :position (proto.table-value :entity.position)
+ :velocity (proto.table-value :entity.velocity)
+ ;; [self game {: up : down : left : right}]
+ :steer (proto.meta-method :entity.velocity)
+ ;; [self game]
+ ;; screen origin at center of entity, 1 = 1 pixel (for now)
+ :draw (proto.meta-method :entity.draw)
+ ;; [self game pos]
+ :collide (proto.meta-method-opt :entity.collide)}
diff --git a/lib/game.fnl b/lib/game.fnl
index 01f882d..b75a254 100644
--- a/lib/game.fnl
+++ b/lib/game.fnl
@@ -1,19 +1,14 @@
 (local state (require :lib.state))
 (local cell (require :lib.cell))
 (local cells (require :lib.cells))
+(local vec (require :lib.vec))
+(local entity (require :lib.entity))
+(local player (require :lib.player))
 (local fv (require :fennel.view))
 
 (fn lerp* [a b c d x]
   (+ c (* (/ (- x a) (- b a)) (- d c))))
 
-(fn vec-sub [a b]
-  {:x (- a.x b.x)
-   :y (- a.y b.y)})
-
-(fn vec-lerp* [a b c d x]
-  {:x (lerp* a.x b.x c.x d.x x.x)
-    :y (lerp* a.y b.y c.y d.y x.y)})
-
 (fn new-grid [w h f]
   (var t {})
   (for [x 0 (- w 1)]
@@ -23,8 +18,8 @@
   t)
 
 (fn update [self]
-  (set self.ship.x (+ self.ship.x 0.02))
-  (set self.ship.y (+ self.ship.y 0.005))
+  ;; (set ship-pos.x (+ self.ship.x 0.02))
+  ;; (set ship-pos.y (+ self.ship.y 0.005))
   (set self.radius (lerp* 0 1 self.radius self.target-radius 0.3))
   (when (= self.tick 0)
     (for [x 0 (- self.width 1)]
@@ -48,15 +43,37 @@
                         (cell.birth (. neighbors (math.random (length neighbors))) get))
                   (tset self.grid-alt x y nil))))))
     (set (self.grid self.grid-alt) (values self.grid-alt self.grid)))
-    ;; TODO
-  (set self.tick (% (+ self.tick 1) self.rate)))
+  (set self.tick (% (+ self.tick 1) self.rate))
+  ;; player steering
+  (when self.entities.player
+    (entity.steer self.entities.player
+                  self
+                  :player
+                  {:up (love.keyboard.isDown :up)
+                   :right (love.keyboard.isDown :right)
+                   :left (love.keyboard.isDown :left)}))
+  ;; entities
+  (each [id e (pairs self.entities)]
+    (tset e entity.position (vec.wrap
+                              (vec.add (entity.position e) (entity.velocity e))
+                              {:x self.width :y self.height}))
+    (let [x (math.floor (. e entity.position :x))
+          y (math.floor (. e entity.position :y))
+          t (. self.grid x y)]
+      (when t
+        (entity.collide e self id x y)))
+    )
+  )
 
 (fn id [x] x)
 
 (fn draw [self]
   (local (width height) (love.graphics.getDimensions))
   ;; (love.graphics.scale width height)
-  (let [camera-size (math.min width height)
+  (let [ship-pos (if self.entities.player
+                     (entity.position self.entities.player)
+                     self.ship-pos)
+        camera-size (math.min width height)
         radius-x (* self.radius (/ width camera-size))
         radius-y (* self.radius (/ height camera-size))
         clipped-x (math.min radius-x self.max-radius)
@@ -64,18 +81,20 @@
         display-a {:x (* width (- 1 (/ clipped-x radius-x)) 0.5)
                    :y (* height (- 1 (/ clipped-y radius-y)) 0.5)}
         display-b {:x (- width display-a.x) :y (- height display-a.y)}
-        display-size (vec-sub display-b display-a)
-        camera-a {:x (- self.ship.x clipped-x)
-                  :y (- self.ship.y clipped-y)}
-        camera-b {:x (+ self.ship.x clipped-x)
-                  :y (+ self.ship.y clipped-y)}
-        cell-box (vec-lerp* {:x 0 :y 0}
+        display-size (vec.sub display-b display-a)
+        camera-a {:x (- ship-pos.x clipped-x)
+                  :y (- ship-pos.y clipped-y)}
+        camera-b {:x (+ ship-pos.x clipped-x)
+                  :y (+ ship-pos.y clipped-y)}
+        cell-box (vec.lerp {:x 0 :y 0}
                             {:x (* 2 clipped-x)
                              :y (* 2 clipped-y)}
                             ;; TODO: this is wrong
                             {:x 0 :y 0}
                             display-size
                             {:x 1 :y 1})]
+    ;; TODO: this is ugly and weird
+    (set self.ship-pos ship-pos)
     (love.graphics.setScissor (- display-a.x 1) (- display-a.y 1)
                               (- display-b.x display-a.x -2)
                               (- display-b.y display-a.y -2))
@@ -91,12 +110,12 @@
     (love.graphics.clear)
     (for [x (math.floor camera-a.x) (math.floor camera-b.x)]
       (for [y (math.floor camera-a.y) (math.floor camera-b.y)]
-        (let [vec {:x (% x self.width) :y (% y self.height)}
-              render-a (vec-lerp* camera-a camera-b display-a display-b
+        (let [pos {:x (% x self.width) :y (% y self.height)}
+              render-a (vec.lerp camera-a camera-b display-a display-b
                                   {: x : y})
-              render-b (vec-lerp* camera-a camera-b display-a display-b
+              render-b (vec.lerp camera-a camera-b display-a display-b
                                   {:x (+ x 1) :y (+ y 1)})
-              the (. self.grid vec.x vec.y)
+              the (. self.grid pos.x pos.y)
               color (and the (cell.color the))]
           (when color
             (love.graphics.setColor (unpack color))
@@ -106,6 +125,15 @@
                                      (id cell-box.x)
                                      (id cell-box.y))))))
     ;; draw other stuff
+    (each [id v (pairs self.entities)]
+      (love.graphics.push)
+      (let [pos (entity.position v)
+            render-pos (vec.lerp camera-a camera-b display-a display-b pos)]
+        (love.graphics.translate render-pos.x render-pos.y)
+        (love.graphics.scale cell-box.x
+                             cell-box.y))
+      (entity.draw v self id)
+      (love.graphics.pop))
     ))
     ;; (love.graphics.setLineWidth 0.1)
     ;; (love.graphics.line 0 0 0.3 0.3)
@@ -142,10 +170,13 @@
      :min-radius 16
      :tick 0
      :rate 6
+     :entities {:player (entity.init player {:x 32 :y 32})}
      :grid (new-grid width height #(if (= (math.random 6) 1)
-                                (if (< $1 52)
+                                (if (> $1 34)
                                     (cell.init cells.life)
-                                    (cell.init cells.brain))
+                                    (< $1 00)
+                                    (cell.init cells.brain)
+                                    nil)
                                 nil))
      :grid-alt (new-grid width height #nil)
      }
diff --git a/lib/main.fnl b/lib/main.fnl
index 03383ad..8e4908a 100644
--- a/lib/main.fnl
+++ b/lib/main.fnl
@@ -10,7 +10,8 @@
 ;; i'm not sure if it'd be worth it (it'd require those dependency loops maybe)
 ;; TODO: ^
 (local hotswap-modules
-  [:lib.cells
+  [:lib.player
+   :lib.cells
    :lib.game
    :lib.main])
 
@@ -19,11 +20,11 @@
 
 (fn love.load []
   (when profi?
-    (profi:start))
-  (set love.frame 0)
+    (profi:start)
+    (set love.frame 0))
   (love.keyboard.setKeyRepeat true)
   (global the-state (state.init game))
-  (global messages {})
+  (global messages (or messages {}))
   (print "a"))
 
 (fn love.draw []
@@ -46,7 +47,6 @@
           (table.remove messages i)
           (set v.ticks (- v.ticks 1))))))
 
-;; TODO: we need a better way to display errors at runtime for updates too
 (fn love.update []
   (when profi?
     (profi:startHooks)
diff --git a/lib/player.fnl b/lib/player.fnl
new file mode 100644
index 0000000..0633727
--- /dev/null
+++ b/lib/player.fnl
@@ -0,0 +1,39 @@
+(local entity (require :lib.entity))
+(local vec (require :lib.vec))
+(local cell (require :lib.cell))
+(local cells (require :lib.cells))
+
+(fn init [self pos]
+  (setmetatable {entity.position pos
+                 entity.velocity {:x 0 :y 0}
+                 :target-spin 0
+                 :direction 0}
+                self))
+
+(fn steer [self game id controls]
+  ;; TODO: smooth turning
+  (when controls.left
+    (set self.target-spin (- self.target-spin 0.15)))
+    ;; (set self.direction (% (- self.direction 0.1) (* math.pi 2)))
+  (when controls.right
+    (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))
+  (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)))))))
+
+(fn draw [self game id]
+  (love.graphics.setColor 1 1 1)
+  (love.graphics.rotate self.direction)
+  (love.graphics.polygon :fill -0.6 -0.4 0.6 0 -0.6 0.4))
+
+(fn collide [self game id x y]
+  (print "ow!")
+  (tset game.entities id nil)
+  (tset game.grid x y (cell.init cells.boom)))
+
+{entity.init init entity.steer steer entity.draw draw entity.collide collide}
diff --git a/lib/vec.fnl b/lib/vec.fnl
new file mode 100644
index 0000000..cce9627
--- /dev/null
+++ b/lib/vec.fnl
@@ -0,0 +1,27 @@
+(fn ilerp* [a b c d x]
+  (+ c (* (/ (- x a) (- b a)) (- d c))))
+
+(fn add [a b]
+  {:x (+ a.x b.x)
+   :y (+ a.y b.y)})
+
+(fn sub [a b]
+  {:x (- a.x b.x)
+   :y (- a.y b.y)})
+
+(fn mul [v n]
+  {:x (* v.x n)
+   :y (* v.y n)})
+
+(fn mag [v]
+  (math.sqrt (+ (* v.x v.x) (* v.y v.y))))
+
+(fn wrap [a b]
+  {:x (% a.x b.x)
+   :y (% a.y b.y)})
+
+(fn lerp [a b c d x]
+  {:x (ilerp* a.x b.x c.x d.x x.x)
+   :y (ilerp* a.y b.y c.y d.y x.y)})
+
+{: lerp : add : sub : mul : mag : wrap}