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))