Skip to content

Instantly share code, notes, and snippets.

@selfsame
Last active August 29, 2015 14:14
Show Gist options
  • Save selfsame/4159bf2d30df013ed41d to your computer and use it in GitHub Desktop.
Save selfsame/4159bf2d30df013ed41d to your computer and use it in GitHub Desktop.
(ns snake.core
(:use
[arcadia.core]
[hard.core]
[hard.input]
[hard.tween]))
(declare get-input)
(arcadia.core/defcomponent Pumper []
(Update [this] (get-input)))
(def TIMER (atom 0))
(def A (atom {}))
(def B (atom {}))
(def MAP (atom [
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]))
(defn text [go]
(if-let [T (component go "Text")] (.text T)))
(defn text! [go v]
(if-let [T (component go "Text")] (set! (.text T) v)))
(defn cc-tween [go]
(let [[x y z] (->vec (->v3 go))
start (tween (* x 0.2))
t1 (tween {go {:euler [90 0 0]}} 0.4 :pow2 :+)
t2 (tween {go {:euler [0 90 0]}} 0.4 :pow2 :+)
t3 (tween {go {:euler [0 0 90]}} 0.4 :pow2 :+)]
(link start t1)
(link t1 0.5 t2 0.5 t3 0.5 t1)
(run start)))
(defn direction [k] (get {:u [0 1] :d [0 -1] :l [-1 0] :r [1 0]} k))
(defn make-snake [[x y z] dir path]
(let [me (clone! (resource "snake") [x y z])
offsets (cons [x z] (mapv direction path))
parts
(for [i (range (count offsets))
:let [[px pz] (reduce v+ (take (inc i) offsets))
part (clone! (resource "section") [px 0 pz])]]
(do (parent! part me) part))]
{:go me :x x :z z :parts parts :path path :dir dir}))
(defn animate-part [go loc idx]
(let [delay (tween (* idx 0.04))
t1 (tween {go {:position loc}} 0.2)]
(link delay t1)
(run delay)))
(defn advance-snake [s]
(let [{:keys [:x :z :parts :path :dir]} @s
[dx dz] (v+ [x z] (direction dir))
locs (cons (->v3 [dx 0 dz]) (map ->v3 parts))]
(mapv animate-part parts locs (range (count locs)))
(swap! s conj {:x dx :z dz})))
(defn advance []
(swap! TIMER inc)
(text! (find-name "b-score") (str @TIMER))
(text! (find-name "a-score") (str @TIMER))
(advance-snake A)
(advance-snake B))
(defn make-level []
(if (playing?) (do
(clean-tweens)
(clear-cloned)
(let [title (clone! (resource "snake-title") [5 0 -2])
ccol (objects-named "colcube")
field (clone! (resource "game-map"))
ui (clone! (resource "UI"))
timer (tween {field {}} 0.5 advance)]
(reset! A (make-snake [6 0 3] :r [:l :l :l :u :u :r :r :u]))
(reset! B (make-snake [12 0 3] :u [:d :d :r :r :r :u :r :d]))
(mapv cc-tween ccol)
(mapv #(parent! % field)
(for [y (range (count @MAP))
x (range (count (first @MAP)))
:let [tile (get-in @MAP [y x])]
:when (= 0 tile)]
(clone!
(resource "level-block")
(v* [x -0.6 y] 1))))
(add-component field Pumper)
(link timer timer)
(run timer)))))
(defn reverse? [a b]
(if (= a b) false
(case #{a b} #{:u :d} true #{:l :r} true false)))
(defn steer [S d]
(let [od (:dir @S)
[dx dz] (direction d)]
(if (and (not= d od) (not (reverse? d od)))
(do
(mapv
(fn [go] (run (tween {go {:euler (v* [90 0 90] [dx 0 dz])}} 0.3)))
(objects-named "level-block(Clone)"))
(swap! S conj {:dir d})))))
(defn get-input []
(mapv
(fn [[k d S]]
(if (key-down? k) (steer S d)))
[[:a :l A][:d :r A][:w :u A][:s :d A]
[:left :l B][:right :r B][:up :u B][:down :d B]]))
(make-level)
(defn enter-square [go]
(let [t (hard.tween/tween {go {:local-scale [1.5 1.5 1.5]}} 0.25)]
(hard.tween/run t)))
(defn exit-square [go]
(let [t (hard.tween/tween {go {:local-scale [1 1 1]}} 0.25)]
(hard.tween/run t)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment