Playing with a circular particle system based on a water simulation, done using Fluxus (http://pawfal.org/fluxus). Energy is tranferred between adjacent toads, so after time they start to bounce back and forth chaotically.
Code:
; a simple script that looks like it could be made into a
; water simulation of some kind
(clear)
(require fluxus-016/shapes)
(hint-ignore-depth)
; dimensions of the circles
(define elems 20)
; angle between each element
(define elem-angle (/ 3.14156 elems))
; simulation constants
(define max-dist 10)
(define max-dist-sq (* max-dist max-dist))
(define min-dist 4)
(define min-dist-sq (* min-dist min-dist))
(define max-vel-mag 0.1)
; stops the simulation going out of control
(define max-vel (vmul (vector (cos elem-angle) (sin elem-angle) 0) max-vel-mag))
(define max-vel-sq (vdist-sq max-vel (vector 0 0 0)))
(define trans 0.008) ; the amount the energy transmitted to
; the neighboring vertex
; feedback velocity per frame
(define feedback 0.1)
; complexity of initial positions (sin peaks, basically)
(define complexity 4)
; make a list of points in a circle
(define circle-points (build-circle-points elems 1))
(define tex (load-texture "/Users/evan/cvs/newflx/fluxus/textures/whitetoady.png"))
(define s (build-particles elems))
(with-primitive s
(pdata-add "vel" "v")
(pdata-add "v0" "v")
(pdata-add "p0" "v")
(pdata-index-map!
(lambda (i p)
(list-ref circle-points i))
"p")
; copy default pos at radius 1
(pdata-copy "p" "p0")
; scale circle radius
(pdata-index-map!
(lambda (i p)
; (vmul p (+ (* (* 0.5 (+ 1 (sin (* 3.4156 (/ i elems)))))
; (- max-dist min-dist)) min-dist)))
(vmul p (* (* 0.5 (+ 1 (sin (* complexity (* 3.4156 (/ i elems)))))) max-dist)))
"p")
; start off the simulation with random point distances
; (pdata-index-map!
; (lambda (i p)
; (vadd p (vmul p (* (* max-dist 0.4) (crndf)) )))
; "p")
(pdata-index-map!
(lambda (i vel p)
(vmul p (/ max-dist 10)))
"vel" "p")
; store initial velocity
(pdata-copy "vel" "v0")
; start off the simulation with random colours
(pdata-map!
(lambda (c)
(rndvec))
"c")
; start off the simulation with random colours
(pdata-map!
(lambda (s)
(vector 2 2 0.6))
"s")
)
(define (simulate n)
(cond [(< n 0) 0]
[else
(let* [(result (pdata-get "vel" n))
(p (pdata-get "p" n))
(p-sq (vdist-sq p (vector 0 0 0)))]
(cond [(> p-sq max-dist-sq)
; (display "max")(newline)
; we are above "sea level" head down
(pdata-set "vel" n (vmul (pdata-ref "vel" n) -0.9))
; (pdata-set "vel" n (vmul (pdata-ref "v0" n) -1))
(pdata-set "p" n (vmul (pdata-ref "p0" n) max-dist))
]
[(< p-sq min-dist-sq)
; (display "mIN")(newline)
; we are below "sea level" head up
; (pdata-set "vel" n (pdata-ref "v0" n))
(pdata-set "vel" n (vmul (pdata-ref "vel" n) -0.9))
(pdata-set "p" n (vmul (pdata-ref "p0" n) min-dist))
]
[else
(let [(pv (* (vdist (pdata-get "vel" (- n 1)) (vector 0 0 0)) trans))
(nv (* (vdist (pdata-get "vel" (+ n 1)) (vector 0 0 0)) trans))]
; mix in the surrounding verts to transmit energy around
(set! result (vadd result
(vmul result pv)))
(set! result (vadd result
(vmul result nv)))
; add the result to the existing velocity
(pdata-set "vel" n (vadd (pdata-get "vel" n) (vmul result feedback)))
;(pdata-set "vel" n (vadd (pdata-get "vel" n) result))
)
]
)
(let* [
(v (pdata-get "vel" n))
(v0 (pdata-get "v0" n))
(vmax (vmul v0 max-vel-mag))
(v-sq (vdist-sq v (vector 0 0 0)))]
; clamp the velocity - this stops the
; simulation going too fast and blowing up
(cond [(> v-sq max-vel-sq)
; divide by mag to get sign, mult by max-vel
(pdata-set "vel" n (vmul (vmul v (/ 1 (vmag v))) max-vel-mag))
]
)
)
)
(simulate (- n 1))
]
)
)
(define (render)
(set! feedback (* 0.4 0.5 (+ 1 (sin (* 0.3 (time))))))
(with-primitive s
(rotate (vector 0 0 2))
(texture tex)
(simulate (pdata-size))
(pdata-op "+" "p" "vel")
; (recalc-normals 1)
)
)
(every-frame (render))