Part of the ‘Project Nightjar’ camouflage work I’m doing for the Sensory Ecology group at Exeter University is to design citizen science games we can build to do some research. One plan is to create lots of patterns in the browser that we can run perceptual models on for different predator animals, and use an online game to compare them with human perception.
A nice aspect of this is that it’s easy to artistically control the patterns by changing the starting images, for example much more naturalistic patterns would result from noisier, less geometric base images and more earthy colours. This way we can have different ‘themes’ for levels in a game, for example.
I’m using the scheme compiler I wrote for planet fluxus to do this, and building trees that look like this:
'("op" "lighter" ("op" "source-in" ("op" "source-out" ("terminal" (124 57 0 1) "stripe-6") ("terminal" (42 23 0 1) "dots-6")) ("op" "copy" ("terminal" (36 47 0 1) "stripe-7") ("terminal" (8 90 1.5705 1) "red"))) ("terminal" (108 69 0 1) "green"))
Ops are the blend mode operations, and terminals are images, which include translation and scale (not currently used). The egg trees get drawn with the function below, which shows the curious hybrid mix of HTML5 canvas and Scheme I’m using these days (and some people may find offensive :) Next up is to actually do the genetic programming part, so mutating and doing crossover on the trees.
(define (draw-egg ctx x y program) (if (eq? (program-type program) "terminal") (begin (set! ctx.fillStyle (ctx.createPattern (find-image (terminal-image program) image-lib) "repeat")) ;; centre the rotation (ctx.translate 64 64) (ctx.rotate (transform-rotate (terminal-transform program))) (ctx.translate -64 -64) ;; make the pattern translate by moving, ;; drawing then moving back (ctx.translate (transform-x (terminal-transform program)) (transform-y (terminal-transform program))) (ctx.fillRect (- 0 (transform-x (terminal-transform program))) (- 0 (transform-y (terminal-transform program))) (* 127 2) (* 127 2)) (ctx.translate (- 0 (transform-x (terminal-transform program))) (- 0 (transform-y (terminal-transform program))))) (begin ;; slightly overzealous context saving/restoring (ctx.save) ;; set the composite operation (set! ctx.globalCompositeOperation (operator-type program)) (ctx.save) (draw-egg ctx x y (operator-operand-a program)) (ctx.restore) (ctx.save) (draw-egg ctx x y (operator-operand-b program)) (ctx.restore) (ctx.restore))))