var nopaint = (function(){ var is_paint = false controls.no = new Tool (nopaint_no_el) controls.no.use = function(state){ undo.undo() controls.paint.focus() } controls.paint = new Tool (nopaint_paint_el) controls.paint.use = function(state){ nopaint.play() nopaint_pause_el.classList.toggle("hidden", false) } controls.nopaint_pause = new Tool (nopaint_pause_el) controls.nopaint_pause.use = function(state){ nopaint.pause() nopaint_pause_el.classList.toggle("hidden", true) } // use own stepwise clock to drive tweens oktween.raf = function(){} var nopaint = {} nopaint.delay = 100 nopaint.tool = null nopaint.tools = {} nopaint.keys = [] nopaint.weights = [] nopaint.step = 0 nopaint.time = 0 nopaint.timeout = false nopaint.toggle = function(state){ var state = typeof state == "boolean" ? state : nopaint_rapper.classList.contains("hidden") nopaint_rapper.classList.toggle("hidden", ! state) nopaint_pause_el.classList.toggle("hidden", true) document.body.classList.toggle("nopaint", state) return state } nopaint.undo = function(){ undo.undo() } nopaint.pause = function(){ clearTimeout(nopaint.timeout) nopaint.timeout = 0 nopaint.step = 0 } nopaint.play = function(){ nopaint.pause() nopaint.switch_tool() nopaint.go() } nopaint.go = function(){ nopaint.timeout = setTimeout(nopaint.go, nopaint.delay) oktween.update(nopaint.time) nopaint.tool.paint( nopaint.step ) nopaint.time += 1 nopaint.step += 1 } nopaint.switch_tool = function(){ undo.new() last_tool = nopaint.tool last_tool && last_tool.finish() nopaint.tool = nopaint.get_random_tool() nopaint.tool.start( last_tool ) console.log(nopaint.tool.type) } nopaint.add_tool = function(fn){ nopaint.tools[fn.type] = fn } nopaint.get_random_tool = function(){ var n = rand( nopaint.sum ) for (var i = 0, _len = nopaint.weights.length; i < _len; i++) { if (n < nopaint.weights[i]) { return nopaint.tools[ nopaint.keys[i] ] } } return nopaint.tools[ choice(nopaint.keys) ] } nopaint.regenerate_weights = function(){ nopaint.sum = 0 nopaint.weights = [] nopaint.keys = Object.keys( nopaint.tools ).sort(function(a,b){ return b-a }) nopaint.keys.forEach(function(key){ nopaint.sum += nopaint.tools[key].opt.weight nopaint.weights.push( nopaint.sum ) }) } /* Base models for brushes */ var NopaintTool = Model({ type: "none", init: function(opt){ this.opt = opt || {} }, start: function(){}, paint: function(t){}, update: function(t){}, finish: function(){}, }) var NopaintBrush = NopaintTool.extend({ type: "brush", is_brush: true, init: function(opt){ this.opt = opt || {} this.opt.max_radius = this.opt.max_radius || 10 this.p = {x: randint(canvas.w), y: randint(canvas.h)} this.fg = 0 this.bg = 1 this.char = " " this.tweens = [] }, start: function(last_brush){ this.reset( last_brush ) this.regenerate() draw.down({}, null, [this.p.x, this.p.y]) }, paint: function(t){ this.update(t) draw.move_toroidal({}, null, [this.p.x, this.p.y]) }, finish: function(){ this.tweens.forEach(function(t){ t.cancel() }) this.tweens = [] }, reorient: function(last_brush){ var a = {}, b if (last_brush) { this.p.x = a.x = randint(canvas.w) this.p.y = a.y = randint(canvas.h) } else { a.x = this.p.x a.y = this.p.y } b = this.get_next_point() var tween = oktween.add({ obj: this.p, from: a, to: b, duration: b.duration, easing: b.easing, update: b.update, finished: function(){ this.iterate() this.regenerate() }.bind(this) }) this.tweens.push(tween) }, get_next_point: function(){ var radius = randrange(2, this.opt.max_radius) var b = {} b.duration = randrange(1, 7) b.easing = choice(easings) b.x = this.p.x + randrange(-radius, radius) b.y = this.p.y + randrange(-radius, radius) return b }, iterate: function( last_brush ){ this.reorient( last_brush ) }, regenerate: function(){ brush.load( this ) brush.generate() }, }) var easings = "linear circ_out circ_in circ_in_out quad_in quad_out quad_in_out".split(" ") /* Standard brushes */ var SolidBrush = NopaintBrush.extend({ type: "solid", recolor: function(){ this.fg = this.bg = randint(16) this.char = " " }, resize: function(m,n){ m = m || 3 n = n || 0 var bw = xrandrange(5, 0, m) + n brush.resize( round(bw * randrange(0.9, 1.8)) || 1, round(bw) || 1 ) }, reset: function( last_brush ){ this.opt.max_radius = randrange(5,20) this.resize() this.reorient( last_brush ) this.recolor( last_brush ) this.regenerate() }, iterate: function( last_brush ){ this.resize() this.reorient( last_brush ) }, }) var EraseBrush = SolidBrush.extend({ type: "random", iterate: function( last_brush ){ this.bg = 0 this.char = " " this.random() }, }) var RandomBrush = SolidBrush.extend({ type: "random", iterate: function( last_brush ){ this.reorient( last_brush ) this.recolor( last_brush ) }, }) var HueBrush = SolidBrush.extend({ type: "hue", recolor: function(){ this.fg = this.bg = rand_hue() this.char = " " }, }) var LetterBrush = SolidBrush.extend({ type: "letter", chars: unicode.block('Basic Latin', 32), recolor: function(){ this.fg = rand_hue() this.bg = rand_hue() this.char = choice(this.chars) }, }) var RandomLetterBrush = LetterBrush.extend({ type: "random-letter", iterate: function(){ if (Math.random() < 0.01) { this.fg += 1 } if (Math.random() < 0.05) { var n = this.fg this.fg = this.bg this.bg = n } if (Math.random() < 0.7) { this.char = choice(this.chars) } this.regenerate() this.__iterate() }, update: function(){ if (Math.random() < 0.3) { this.char = choice(this.chars) } this.regenerate() }, }) var CloneBrush = SolidBrush.extend({ type: "clone", reset: function( last_brush ){ this.opt.max_radius = randrange(5,20) this.reorient( last_brush ) this.__resize(4,2) this.clone_region() }, clone_region: function(){ var x = randrange(0, canvas.w - brush.w) var y = randrange(0, canvas.h - brush.h) blit.copy_from(canvas, brush, floor(x-brush.w/2), floor(y-brush.h/2)) brush.mask(brush) }, regenerate: function(){}, resize: function(){}, }) var StarsTool = NopaintBrush.extend({ type: "stars", chars: "....,,'''*", start: function(last_brush){ this.reorient( last_brush ) }, paint: function(t){ if (Math.random() < 0.5) { var lex = canvas.get(this.p.x, this.p.y) lex.fg = rand_hue() lex.bg = colors.black lex.char = choice(this.chars) lex.build() } }, }) /* Fill tool */ var FillTool = NopaintTool.extend({ type: "fill", rate: 25, start: function(){ this.fill() }, paint: function(t){ if ((t % this.rate) == this.rate-1) { this.fill() } }, recolor: function(){ this.fg = this.bg = randint(16) this.char = " " this.opacity = 1 }, fill: function(){ var x = randint(canvas.w) var y = randint(canvas.h) this.recolor() draw.fill(this, x, y) } }) var FillLetterTool = FillTool.extend({ type: "fill-letter", rate: 25, chars: unicode.block('Basic Latin', 32), recolor: function(){ this.fg = randint(16) this.bg = randint(16) this.char = choice(this.chars) this.opacity = 1 }, }) nopaint.add_tool( new SolidBrush({ weight: 3 }) ) nopaint.add_tool( new EraseBrush({ weight: 5 }) ) nopaint.add_tool( new RandomBrush({ weight: 4 }) ) nopaint.add_tool( new HueBrush({ weight: 6 }) ) nopaint.add_tool( new LetterBrush({ weight: 4 }) ) nopaint.add_tool( new RandomLetterBrush({ weight: 14 }) ) nopaint.add_tool( new CloneBrush({ weight: 8 }) ) nopaint.add_tool( new FillTool({ weight: 4 }) ) nopaint.add_tool( new FillLetterTool({ weight: 6 }) ) nopaint.add_tool( new StarsTool({ weight: 6 }) ) nopaint.regenerate_weights() nopaint.toggle(true) return nopaint })()