summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/draw.js67
-rw-r--r--js/nopaint/index.js165
-rw-r--r--js/util.js3
-rw-r--r--js/vendor/oktween.js167
4 files changed, 401 insertions, 1 deletions
diff --git a/js/draw.js b/js/draw.js
index cedfea2..eb58a27 100644
--- a/js/draw.js
+++ b/js/draw.js
@@ -27,6 +27,72 @@ var draw = (function(){
last_point[1] = point[1]
}
+ function move_toroidal (e, lex, point) {
+ var w = canvas.w, h = canvas.h
+ var src_x_quantile = quantile( last_point[0], w )
+ var src_y_quantile = quantile( last_point[1], h )
+ var dst_x_quantile = quantile( point[0], w )
+ var dst_y_quantile = quantile( point[1], h )
+ var src_x_mod = mod( last_point[0], w )
+ var src_y_mod = mod( last_point[1], h )
+ var dst_x_mod = mod( point[0], w )
+ var dst_y_mod = mod( point[1], h )
+ // if we've moved across the edge of the board, draw two lines
+ if (src_x_quantile != dst_x_quantile || src_y_quantile != dst_y_quantile) {
+ var xa, ya
+ if (src_x_quantile < dst_x_quantile) {
+ xa = [
+ [src_x_mod, dst_x_mod + w],
+ [src_x_mod-w, dst_x_mod],
+ ]
+ }
+ else if (src_x_quantile == dst_x_quantile) {
+ xa = [
+ [src_x_mod, dst_x_mod],
+ [src_x_mod, dst_x_mod],
+ ]
+ }
+ else {
+ xa = [
+ [src_x_mod, dst_x_mod-w],
+ [src_x_mod+w, dst_x_mod],
+ ]
+ }
+
+ if (src_y_quantile < dst_y_quantile) {
+ ya = [
+ [src_y_mod, dst_y_mod + h],
+ [src_y_mod-h, dst_y_mod],
+ ]
+ }
+ else if (src_y_quantile == dst_y_quantile) {
+ ya = [
+ [src_y_mod, dst_y_mod],
+ [src_y_mod, dst_y_mod],
+ ]
+ }
+ else {
+ ya = [
+ [src_y_mod, dst_y_mod-h],
+ [src_y_mod+h, dst_y_mod],
+ ]
+ }
+ line(lex, [ xa[0][0], ya[0][0] ], [ xa[0][1], ya[0][1] ], erasing)
+ line(lex, [ xa[1][0], ya[1][0] ], [ xa[1][1], ya[1][1] ], erasing)
+ }
+ else {
+ var last_point_mod = [], point_mod = []
+ last_point_mod[0] = mod( last_point[0], w )
+ last_point_mod[1] = mod( last_point[1], h )
+ point_mod[0] = mod( point[0], w )
+ point_mod[1] = mod( point[1], h )
+ line(lex, last_point_mod, point_mod, erasing)
+ }
+ last_point[0] = point[0]
+ last_point[1] = point[1]
+ // y = point.y
+ }
+
function point (lex, x, y, erasing) {
stamp (canvas, brush, x, y, erasing)
}
@@ -109,6 +175,7 @@ var draw = (function(){
draw.down = down
draw.set_last_point = set_last_point
draw.move = move
+ draw.move_toroidal = move_toroidal
draw.stamp = stamp
draw.line = line
draw.point = point
diff --git a/js/nopaint/index.js b/js/nopaint/index.js
new file mode 100644
index 0000000..6270503
--- /dev/null
+++ b/js/nopaint/index.js
@@ -0,0 +1,165 @@
+var nopaint = (function(){
+
+ var is_paint = false
+
+ controls.nopaint = {}
+
+ controls.no = new Checkbox (nopaint_no_el)
+ controls.no.use = function(state){
+ this.update(! nopaint.timeout)
+ controls.paint.update(false)
+ undo.undo()
+ nopaint.play()
+ }
+
+ controls.paint = new Checkbox (nopaint_paint_el)
+ controls.paint.use = function(state){
+ controls.no.update(false)
+ nopaint.play()
+ this.update(!! nopaint.timeout)
+ }
+
+ // use own stepwise clock to drive tweens
+ oktween.raf = function(){}
+
+ var nopaint = {}
+ nopaint.delay = 100
+ nopaint.tool = null
+ nopaint.tools = {}
+ nopaint.step = 0
+ nopaint.time = 0
+ nopaint.timeout = false
+ 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.tools[ choice(Object.keys(nopaint.tools)) ]
+ nopaint.tool.start( last_tool )
+ // console.log(nopaint.tool.type)
+ }
+ nopaint.add_tool = function(fn){
+ nopaint.tools[fn.type] = fn
+ }
+
+ var NopaintTool = Model({
+ type: "none",
+ init: function(){},
+ start: function(){},
+ paint: function(t){},
+ finish: function(){},
+ })
+
+ var NopaintBrush = NopaintTool.extend({
+ type: "brush",
+ is_brush: true,
+ init: function(){
+ this.p = {x: 0, y: 0}
+ this.fg = 0
+ this.bg = 1
+ this.char = " "
+ this.tweens = []
+ },
+
+ start: function(last_brush){
+ this.reset( last_brush )
+ this.iterate( last_brush )
+ brush.load( this )
+ brush.generate()
+ 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: function(o,dt){
+ // console.log(o,dt)
+ },
+ finished: function(){
+ this.reorient()
+ }.bind(this)
+ })
+ this.tweens.push(tween)
+ },
+
+
+ })
+
+ var easings = "linear circ_out circ_in circ_in_out quad_in quad_out quad_in_out".split(" ")
+
+ var SolidBrush = NopaintBrush.extend({
+ type: "solid",
+
+ get_next_point: function(){
+ var b = {}
+ b.duration = randrange(1,7)
+ b.easing = choice(easings)
+ b.x = this.p.x + randrange(-10, 10)
+ b.y = this.p.y + randrange(-10, 10)
+ return b
+ },
+
+ recolor: function(){
+ this.fg = this.bg = randint(16)
+ this.char = " "
+ },
+ reset: function(){
+ brush.resize(1,1)
+ },
+ iterate: function( last_brush ){
+ this.reorient( last_brush )
+ this.recolor( last_brush )
+ },
+ update: function(t){
+ }
+ })
+
+ nopaint.add_tool( new SolidBrush )
+
+})()
diff --git a/js/util.js b/js/util.js
index 6d297a1..3775ba0 100644
--- a/js/util.js
+++ b/js/util.js
@@ -56,7 +56,8 @@ function modi(n,m){ return floor(n-(m * floor(n/m))) }
function dist(x0,y0,x1,y1){ return sqrt(pow(x1-x0,2)+pow(y1-y0,2)) }
function angle(x0,y0,x1,y1){ return atan2(y1-y0,x1-x0) }
function avg(m,n,a){ return (m*(a-1)+n)/a }
-function quantize(a,b){ return ~~(a/b)*b }
+function quantize(a,b){ return floor(a/b)*b }
+function quantile(a,b){ return floor(a/b) }
function pixel(x,y){ return 4*(mod(y,actual_h)*actual_w+mod(x,actual_w)) }
function rgbpixel(d,x,y){
diff --git a/js/vendor/oktween.js b/js/vendor/oktween.js
new file mode 100644
index 0000000..41edbb0
--- /dev/null
+++ b/js/vendor/oktween.js
@@ -0,0 +1,167 @@
+/*
+ oktween.add({
+ obj: el.style,
+ units: "px",
+ from: { left: 0 },
+ to: { left: 100 },
+ duration: 1000,
+ easing: oktween.easing.circ_out,
+ update: function(obj){
+ console.log(obj.left)
+ }
+ finished: function(){
+ console.log("done")
+ }
+ })
+*/
+
+var oktween = (function(){
+ var oktween = {}
+ var tweens = oktween.tweens = []
+ var last_t = 0
+ var id = 0
+ oktween.speed = 1
+ oktween.raf = requestAnimationFrame
+ oktween.add = function(tween){
+ tween.id = id++
+ tween.obj = tween.obj || {}
+ if (tween.easing) {
+ if (typeof tween.easing == "string") {
+ tween.easing = oktween.easing[tween.easing]
+ }
+ }
+ else {
+ tween.easing = oktween.easing.linear
+ }
+ if (! ('from' in tween) && ! ('to' in tween)) {
+ tween.keys = []
+ }
+ else if (! ('from' in tween) ) {
+ tween.from = {}
+ tween.keys = Object.keys(tween.to)
+ tween.keys.forEach(function(prop){
+ tween.from[prop] = parseFloat(tween.obj[prop])
+ })
+ }
+ else {
+ tween.keys = Object.keys(tween.from)
+ }
+ tween.delay = tween.delay || 0
+ tween.start = last_t + tween.delay
+ tween.done = false
+ tween.after = tween.after || []
+ tween.then = function(fn){ tween.after.push(fn); return tween }
+ tween.cancel = function(){
+ var index = tweens.indexOf(tween)
+ if (index != -1) tweens.splice(index, 1)
+ tween.obj = null
+ tween.after = null
+ tween.done = null
+ }
+ tween.tick = 0
+ tween.skip = tween.skip || 1
+ tween.dt = 0
+ tweens.push(tween)
+ return tween
+ }
+ oktween.update = function(t) {
+ oktween.raf(oktween.update)
+ last_t = t * oktween.speed
+ if (tweens.length == 0) return
+ var done = false
+ tweens.forEach(function(tween, i){
+ var dt = Math.min(1.0, (t - tween.start) / tween.duration)
+ tween.tick++
+ if (dt < 0 || (dt < 1 && (tween.tick % tween.skip != 0))) return
+ var ddt = tween.dt = tween.easing(dt)
+ tween.keys.forEach(function(prop){
+ val = lerp( ddt, tween.from[prop], tween.to[prop] )
+ if (tween.round) val = Math.round(val)
+ if (tween.units) val = (Math.round(val)) + tween.units
+ tween.obj[prop] = val
+ })
+ tween.update && tween.update(tween.obj, dt)
+ if (dt == 1) {
+ tween.finished && tween.finished(tween)
+ if (tween.after.length) {
+ var twn = tween.after.shift()
+ twn.obj = twn.obj || tween.obj
+ twn.after = tween.after
+ oktween.add(twn)
+ }
+ if (tween.loop) {
+ tween.start = t + tween.delay
+ }
+ else {
+ done = tween.done = true
+ }
+ }
+ })
+ if (done) {
+ tweens = tweens.filter(function(tween){ return ! tween.done })
+ }
+ }
+ function lerp(n,a,b){ return (b-a)*n+a }
+
+ // requestAnimationFrame(oktween.update)
+
+ oktween.easing = {
+ linear: function(t){
+ return t
+ },
+ circ_out: function(t) {
+ return Math.sqrt(1 - (t = t - 1) * t)
+ },
+ circ_in: function(t){
+ return -(Math.sqrt(1 - (t * t)) - 1)
+ },
+ circ_in_out: function(t) {
+ return ((t*=2) < 1) ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1)
+ },
+ quad_in: function(n){
+ return Math.pow(n, 2)
+ },
+ quad_out: function(n){
+ return n * (n - 2) * -1
+ },
+ quad_in_out: function(n){
+ n = n * 2
+ if(n < 1){ return Math.pow(n, 2) / 2 }
+ return -1 * ((--n) * (n - 2) - 1) / 2
+ },
+ cubic_bezier: function (mX1, mY1, mX2, mY2) {
+ function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
+ function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
+ function C(aA1) { return 3.0 * aA1; }
+
+ // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
+ function CalcBezier(aT, aA1, aA2) {
+ return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
+ }
+
+ // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
+ function GetSlope(aT, aA1, aA2) {
+ return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
+ }
+
+ function GetTForX(aX) {
+ // Newton raphson iteration
+ var aGuessT = aX;
+ for (var i = 0; i < 10; ++i) {
+ var currentSlope = GetSlope(aGuessT, mX1, mX2);
+ if (currentSlope == 0.0) return aGuessT;
+ var currentX = CalcBezier(aGuessT, mX1, mX2) - aX;
+ aGuessT -= currentX / currentSlope;
+ }
+ return aGuessT;
+ }
+
+ return function(aX) {
+ if (mX1 == mY1 && mX2 == mY2) return aX; // linear
+ return CalcBezier(aX, mY1, mY2);
+ }
+ }
+ }
+
+ return oktween
+})()