Skip to content

Instantly share code, notes, and snippets.

@selfsame
Last active August 29, 2015 14:14
Show Gist options
  • Save selfsame/2ffa721f656a04e81665 to your computer and use it in GitHub Desktop.
Save selfsame/2ffa721f656a04e81665 to your computer and use it in GitHub Desktop.
flock.clj
(ns flock
(:use hard.core hard.input hard.spatial)
(:import [UnityEngine]))
(declare pump initial make-boid)
(def FLOCKS (atom {}))
(def HASH (bucket-hash 10))
(arcadia.core/defcomponent Boid
[^Vector3 heading ^float idle ^Boolean debug]
(Awake [this]
(set! (.idle this) (float (* (rand) 1.5))))
(Start [this]
(initial this))
(Update [this]
(pump this)))
(arcadia.core/defcomponent Flock
[^Int32 size
^GameObject species
^float max-speed
^float turn-speed
^float distance
^float rule-center
^float rule-heading
^float rule-seperate
^Boolean debug]
(Start [this]
(swap! FLOCKS #(conj %
{(.gameObject this)
(mapv
(fn [_] (make-boid (.gameObject this) (.species this)))
(range (int (.size this))))})))
(Update [this]))
(defn rand-in [lb ub] (+ lb (* (rand) (- ub lb))))
(defn- median [group f]
(let [combined (reduce #(v+ %1 (f %2)) [0 0 0] group)]
(vdiv combined (count group))))
(defn center [group] (median group ->v3))
(defn alignment [group] (median group #(->v3 (.forward (.transform %)))))
(defn separate [group])
(defn rand-v3 [sc]
(let [nsc (* sc -1)]
[(rand-in nsc sc)(rand-in nsc sc)(rand-in nsc sc)]))
(defn make-boid [parent species]
(let [me (clone! species)]
(position! me (rand-v3 20))
(rotate! me (rand-v3 360))
(.AddComponent me Boid)
(parent! me parent) me))
(defn initial [bcomp] (store (.gameObject bcomp) HASH))
(defn simmer [me other]
(let [vv (->v3 (v- (->v3 other) me))]
{:h (.forward (.transform other)) :v vv :d (.magnitude vv)}))
(defn n-n [gob sep]
(let [me (vec3 gob)
others (bucket-others gob HASH)
data (mapv #(simmer me %) others)
combined (reduce
(fn [res next]
(let [d (- (:d next) sep)]
{:h (v+ (:h res) (v* (:h next) (:d next)))
:v (v+ (:v res) (v* (:v next) d))}))
{:h [0 0 0] :v [0 0 0]}
data)]
(conj combined {:count (count others)})))
(defn pump [bcomp]
(let [gob (.gameObject bcomp)
delta (UnityEngine.Time/deltaTime)
me (->v3 gob)
flock (parent-component gob Flock)
forward (.forward (.transform gob))
speed (.max-speed flock)
idle (.idle bcomp)
ready (< idle 0.0)]
(when ready
(let [data (n-n gob (.distance flock))
num (inc (:count data))
r1 (.rule-center flock)
r2 (.rule-heading flock)
r3 (.rule-seperate flock)
rule1 (.normalized (->v3 (vdiv (:v data) num)))
rule2 (.normalized (->v3 (vdiv (:h data) num)))
heading (.normalized (->v3 (v+ (v* rule1 r1) (v* rule2 r2))))]
(set! (.heading bcomp) heading)
(store gob HASH)))
(if ready
(set! (.idle bcomp) (float (+ 0.2 (* (rand) 0.4))))
(set! (.idle bcomp) (float (- idle delta))))
(.LookAt
(.transform gob)
(Vector3/Lerp
(->v3 (v+ me forward))
(->v3 (v+ me (.heading bcomp))) (* delta (.turn-speed flock))))
(position! gob (v+ me (v* forward (* speed delta 8))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment