274 lines
9.6 KiB
Scheme
274 lines
9.6 KiB
Scheme
(require scheme/class)
|
|
|
|
(define photon-thresh 0.1)
|
|
|
|
(define (contains? a l)
|
|
(cond
|
|
((null? l) #f)
|
|
((eq? (car l) a) #t)
|
|
(else (contains? a (cdr l)))))
|
|
|
|
(define (remove a l)
|
|
(cond
|
|
((null? l) l)
|
|
((eq? (car l) a) (remove a (cdr l)))
|
|
(else (cons (car l) (remove a (cdr l))))))
|
|
|
|
(define input%
|
|
(class object%
|
|
|
|
(field
|
|
(last-mouse (vector 0 0 0))
|
|
(last-button #f)
|
|
(last-keys '())
|
|
(new-keys '())
|
|
(keys-pressed '())
|
|
(selected 0)
|
|
(zoom -50))
|
|
|
|
(define/public (pre-update)
|
|
(when (and (not last-button) (mouse-button 1))
|
|
(set! selected (select (mouse-x) (mouse-y) 2))))
|
|
|
|
(define/public (update)
|
|
(set! last-button (mouse-button 1))
|
|
(set! new-keys (append (keys-down) '() #;(get-special-keys-pressed)))
|
|
(set! keys-pressed (filter
|
|
(lambda (key)
|
|
(not (contains? key last-keys)))
|
|
new-keys))
|
|
(set! last-keys new-keys)
|
|
(when (key-pressed "-") (set! zoom (* zoom 1.1)))
|
|
(when (key-pressed "=") (set! zoom (* zoom 0.9)))
|
|
(set-camera-transform (mtranslate (vector 0 0 zoom))))
|
|
|
|
(define/public (get-keys-pressed)
|
|
keys-pressed)
|
|
|
|
(define/public (get-selected)
|
|
selected)
|
|
|
|
(define/public (mouse-b n)
|
|
(mouse-button n))
|
|
|
|
(define/public (get-pos-from-mouse)
|
|
(let* ((ndcpos (vector (* (- (/ (mouse-x) (vx (get-screen-size))) 0.5) (* -2 zoom))
|
|
(* (- (- (/ (mouse-y) (vy (get-screen-size))) 0.5)) (* -1.5 zoom)) -10))
|
|
(scrpos (vtransform ndcpos (minverse (get-camera-transform)))))
|
|
scrpos))
|
|
|
|
(define/public (get-mouse-change)
|
|
(let ((r (if last-button (vsub (get-pos-from-mouse) last-mouse)
|
|
(vector 0 0 0))))
|
|
(set! last-mouse (get-pos-from-mouse))
|
|
r))
|
|
|
|
(super-new)))
|
|
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
(define-struct photons (root))
|
|
|
|
(define (build-photons photon-count)
|
|
(with-state
|
|
(hint-depth-sort)
|
|
(texture (load-texture "textures/star.png"))
|
|
(let ((p (build-particles photon-count)))
|
|
(with-primitive p
|
|
(pdata-map!
|
|
(lambda (s)
|
|
(vector 2 2 0))
|
|
"s")
|
|
(pdata-map!
|
|
(lambda (c)
|
|
(vector 1 1 1))
|
|
"c")
|
|
(pdata-map!
|
|
(lambda (p)
|
|
(vector 1 1000 1))
|
|
"p"))
|
|
(make-photons p))))
|
|
|
|
(define (photons-update light)
|
|
(with-primitive (photons-root light)
|
|
(for ((i (in-range 0 30)))
|
|
(let ((p (vector (* (crndf) 30) (* (rndf) 30) 0)))
|
|
(if (> (snoise (* 0.03 (vx p)) (* 0.03 (vy p)) (* 0.1 (time))) photon-thresh)
|
|
(pdata-set! "p" (random (pdata-size)) p)
|
|
(pdata-set! "p" (random (pdata-size)) (vector 0 1000 0)))))))
|
|
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
(define-struct resources ((water #:mutable)))
|
|
|
|
(define (build-resources)
|
|
(make-resources (build-list 5 (lambda (_)
|
|
(with-state
|
|
(translate (vmul (vector (crndf) (- (rndf)) 0) 30))
|
|
(translate (vector 0 -10 10))
|
|
(opacity 0.5)
|
|
(scale (vector 10 10 1))
|
|
(colour (vector 0.5 0.5 1))
|
|
(build-sphere 10 10))))))
|
|
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
(define-struct cell (root
|
|
wall
|
|
(pos #:mutable)
|
|
radius
|
|
thresh
|
|
(dragging #:mutable)
|
|
(connected #:mutable)
|
|
(energy #:mutable)
|
|
type))
|
|
|
|
(define (build-cell pos radius threshold type)
|
|
(with-state
|
|
(push)
|
|
(hint-unlit)
|
|
(translate pos)
|
|
(scale radius)
|
|
(let ((root (build-sphere 7 7)))
|
|
(pop)
|
|
(parent root)
|
|
(scale threshold)
|
|
(opacity 0.3)
|
|
(if (eq? type 'photo)
|
|
(colour (vector 0 1 0))
|
|
(colour (vector 1 0.5 0)))
|
|
(let ((wall (build-sphere 7 7)))
|
|
(make-cell root wall pos radius threshold #f '() 0 type)))))
|
|
|
|
(define (cell-connect! cell other)
|
|
(set-cell-connected! cell (cons other (cell-connected cell)))
|
|
(set-cell-connected! other (cons cell (cell-connected other))))
|
|
|
|
(define (cell-disconnect cell other)
|
|
(set-cell-connected! cell (remove other (cell-connected cell)))
|
|
(set-cell-connected! other (remove cell (cell-connected other))))
|
|
|
|
(define (choose l)
|
|
(list-ref l (random (length l))))
|
|
|
|
(define (cell-divide cell organism)
|
|
(let ((new-cell (build-cell
|
|
(vadd (cell-pos cell) (vmul (srndvec) 3))
|
|
(cell-radius cell) (cell-thresh cell)
|
|
(choose '(photo struct struct struct absorb)))))
|
|
(cell-connect! cell new-cell)
|
|
(set-organism-cells! organism (cons new-cell
|
|
(organism-cells organism)))))
|
|
|
|
(define (cell-update cell input organism photons)
|
|
|
|
(with-primitive (cell-wall cell)
|
|
(if (null? (cell-connected cell))
|
|
(hide 1)
|
|
(hide 0)))
|
|
|
|
(with-primitive (cell-root cell)
|
|
(cond ((eq? (cell-type cell) 'photo)
|
|
(colour (vmul (vector 0.5 1 0.5) (+ 0.5 (cell-energy cell)))))
|
|
((eq? (cell-type cell) 'struct)
|
|
(colour (vmul (vector 1 0.7 0.3) (+ 0.5 (cell-energy cell)))))
|
|
((eq? (cell-type cell) 'absorb)
|
|
(when (> (cell-energy cell) 1)
|
|
(set-cell-energy! cell 0)
|
|
(cell-divide cell organism))
|
|
(colour (vmul (vector 0.5 0.5 1) (+ 0.5 (cell-energy cell))))))
|
|
|
|
|
|
(when (or (eq? (send input get-selected) (cell-wall cell))
|
|
(eq? (send input get-selected) (cell-root cell)))
|
|
(translate (send input get-mouse-change))
|
|
(for-each
|
|
(lambda (other)
|
|
(when (and (not (eq? cell other))
|
|
(not (contains? other (cell-connected cell))))
|
|
|
|
(let ((dist (vdist (cell-pos cell) (cell-pos other))))
|
|
(when (< dist (+ (cell-thresh cell) (cell-thresh other)))
|
|
(cell-connect! other cell)))))
|
|
(organism-cells organism)))
|
|
|
|
|
|
(let ((dir (foldl
|
|
(lambda (other cur)
|
|
(let ((dist (vdist (cell-pos cell) (cell-pos other))))
|
|
(cond
|
|
; inside nucleus
|
|
((< dist (+ (cell-radius cell) (cell-radius other)))
|
|
(vadd cur (vmul (vsub (cell-pos cell) (cell-pos other)) (* 0.1 (/ 1 dist)))))
|
|
((< dist (+ (cell-thresh cell) (cell-thresh other)))
|
|
(vadd cur (vmul (vsub (cell-pos cell) (cell-pos other)) -0.01)))
|
|
(else
|
|
(cell-disconnect cell other)
|
|
cur))))
|
|
(vector 0 0 0)
|
|
(cell-connected cell))))
|
|
(when (eq? (cell-type cell) 'photo)
|
|
(translate (vector (vx dir) (vy dir) 0))))
|
|
|
|
(when (and (eq? (cell-type cell) 'photo)
|
|
(not (null? (cell-connected cell))))
|
|
(with-primitive (photons-root photons)
|
|
(set-cell-energy! cell
|
|
(+ (pdata-fold
|
|
(lambda (p v)
|
|
(if (< (vdist (cell-pos cell) p) (cell-radius cell))
|
|
(+ 0.2 v)
|
|
v))
|
|
0 "p") (cell-energy cell)))))
|
|
|
|
(when (zero? (random 10))
|
|
(for-each
|
|
(lambda (other)
|
|
(when (> (cell-energy other) 0.1)
|
|
(set-cell-energy! cell (+ (cell-energy cell) (* (cell-energy other) 0.49)))
|
|
(set-cell-energy! other (* (cell-energy other) 0.49))))
|
|
(cell-connected cell)))
|
|
|
|
(set-cell-pos! cell (vtransform (vector 0 0 0) (get-transform)))))
|
|
|
|
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
(define-struct organism ((cells #:mutable)))
|
|
|
|
(define (build-organism count)
|
|
(make-organism
|
|
(build-list count
|
|
(lambda (_)
|
|
(build-cell (vmul (vector (crndf) (crndf) 0) 5) 1 2
|
|
(choose '(struct struct struct photo absorb)))))))
|
|
|
|
(define (organism-update organism input photons)
|
|
(for-each
|
|
(lambda (cell)
|
|
(cell-update cell input organism photons))
|
|
(organism-cells organism)))
|
|
|
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
(clear)
|
|
(clear-colour (vector 0.2 0.1 0.1))
|
|
(define organism (build-organism 10))
|
|
(define photons (build-photons 40))
|
|
(define input (make-object input%))
|
|
(define resources (build-resources))
|
|
|
|
(define sky (with-state
|
|
(colour (vector 0.3 0.5 0.2))
|
|
(translate (vector 0 30 -10))
|
|
(scale (vector 150 60 0))
|
|
(build-plane)))
|
|
|
|
(define (update)
|
|
(send input pre-update)
|
|
(organism-update organism input photons)
|
|
(photons-update photons)
|
|
(send input update))
|
|
|
|
(every-frame (update))
|