Today I am starting my first pixelart challenge.

Tree!

Just trying recursive branching

var times = 0, tree = function(layer, x, y, direction){ if(layer <= 0) return; var wind = cos(times/10*layer)/3, i = 0, cs = cos(direction), sn = sin(direction); point(x,y, 0xff0000); for(; i< 5; i++){ point(x + cs*i,y+ sn*i, 0xff0000); } tree(layer - 1, x + cs*i,y + sn*i, direction - 0.5+wind); tree(layer - 1, x + cs*i,y + sn*i, direction + 0.5+wind); }, update = function(dt, t) { clear(); times = t*10; tree(5, w/2, h-3, Math.PI/2*3); };

Dithering!

Let's make a simple dither algorithm. It would be useful for drawing lots of things in pixelart style.

First approach was too naive. It worked, but looks artificial.

var sum = 0, dither = function(amount, filledColor, notEnoughColor) { sum += amount; // if colour storage is filled — return filled color if(sum >= 1){ sum %= 1; return filledColor; } return notEnoughColor; }, x, y; for(x = 0; x < w; x++){ for(y = 0; y < h; y++){ point( x, y, dither(x/w, 0xFF0000, 0x000000) ); } }

Mouse

Previous dither function is not so bad when it is used with custom angles.

Added move function that calls each time when mouse is moved over canvas.

var sum = 0, dither = function(amount, filledColor, notEnoughColor) { sum += amount; // if colour storage is filled — return filled color if(sum >= 1){ sum %= 1; return filledColor; } return notEnoughColor; }, x, y; move = function() { var angle = new Point(w/2, h/2).sub(mouse).getAngle(), si = sin(angle), cs = cos(angle); for(x = 0; x < w; x++){ for(y = 0; y < h; y++){ point( x, y, dither( bound( (cs*(x-w/2)+si*(y-h/2)+h/2)/h ), 0xFF0000, 0x000000) ); } } }

Dither 2.0

Would use a simple hashing approach. Added another collector, so it would feel more randomized.

var sum = 0, kc = 0, dither = function(amount, filledColor, notEnoughColor) { kc = ((kc+1)*1.4 + 1) % 17; sum += amount; if(kc%3<1)sum+=amount if(sum >= 1){ sum %= 1; return filledColor; } return notEnoughColor; }, x, y; for(x = 0; x < w; x++){ for(y = 0; y < h; y++){ point( x, y, dither(x/w, 0xFF0000, 0x000000) ); } }

With mouse move

var sum = 0, kc = 0, dither = function(amount, filledColor, notEnoughColor) { kc = ((kc+1)*1.4 + 1) % 17; sum += amount; if(kc%3<1)sum+=amount if(sum >= 1){ sum %= 1; return filledColor; } return notEnoughColor; }, x, y; // reset collectors dither.reset = function() { kc = 0; return sum = 0; }; move = function() { dither.reset(); var angle = new Point(w/2, h/2).sub(mouse).getAngle(), si = sin(angle), cs = cos(angle); for(x = 0; x < w; x++){ for(y = 0; y < h; y++){ point( x, y, dither( bound( (cs*(x-w/2)+si*(y-h/2)+h/2)/h ), 0xFF0000, 0x000000) ); } } }

Sky!

Now I am ready to draw the sky

var sky = px.createLayer(1), center = new Point(w/2,h), x, y; for(x = 0; x < w; x++) for(y = 0; y < h; y++) sky.point( x, y, dither( center.distance(new Point(x,y))/200, 0x000000, 0x201050 )); var stars = []; for(x = 0; x < 30; x++){ var star = new Point(rand(w), rand(h)); star.animation = rand(300); star.color =[0x75F3FF,0xFEFFB7,0xACFF7C][rand(3)] stars.push(star); } var starsLayer = px.createLayer(2); var tick = 0; var randomMeteor = function() { var angle = rand(720)/720*Math.PI*2; var meteor = new Point(0, w).rotate(angle); meteor.mass = rand(1000)/1500+0.1; meteor.direction = angle + Math.PI+ rand(1000)/200; meteor.speed = rand(100)+500; meteor.color =[0xFFFC07,0xFFFFFF,0xFFA8BB][rand(3)] return meteor; } var meteors = []; for(x = 0; x < 1; x++){ meteors.push(randomMeteor()); } update = function(dt, t){ tick++; starsLayer.clear(); dither.reset(); stars.forEach(function(star) { var animate = sin(star.animation + t/20)+1; starsLayer.point(star.x, star.y, dither(animate, star.color, alpha )); }); meteors.forEach(function(meteor, i) { var normal = new Point(0,1).rotate(meteor.direction); meteor.mass-=dt; if(meteor.mass<0){ meteors[i] = randomMeteor(); }else{ for(var k = 0, _k = meteor.speed*dt; k < _k; k++){ meteor.add(normal); starsLayer.point(meteor.x+w/2, meteor.y+h/2, meteor.color); } } }) }

This is it. It is a simple sky, but tools are working and I am ready to begin my challenge!