Skip to content

Instantly share code, notes, and snippets.

@aitor
Created June 8, 2012 20:28
Show Gist options
  • Save aitor/2897992 to your computer and use it in GitHub Desktop.
Save aitor/2897992 to your computer and use it in GitHub Desktop.
<html>
<head>
</head>
<body>
<canvas id="c"></canvas>
</body>
<script>
var canvas = document.getElementById('c');
var w = canvas.width = innerWidth;
var h = canvas.height = innerHeight;
var ctx = canvas.getContext('2d');
ctx.translate(w>>1, h>>1);
// vec2
function vec2(x, y) { this.x = x; this.y = y; }
function madd(v, m, a) {
v.x += m*a.x
v.y += m*a.y;
}
function mov(v, a) {
v.x = a.x;
v.y = a.y;
}
function add(a, b) { return new vec2(a.x + b.x, a.y + b.y);}
function mul(a, b) { return new vec2(a*b.x, a*b.y);}
function length(a) { return Math.sqrt(a.x*a.x + a.y*a.y);}
function norm(b) { return mul(1.0/length(b), b) };
function clone(a) { return new vec2(a.x, a.y); }
function v2(x, y) { return new vec2(x, y);}
function rot(v, ang) {
var c = Math.cos(ang);
var s = Math.sin(ang);
return v2(c*v.x - s*v.y, c*v.y + s*v.x);
}
function rndAng() {
var idx = (Math.random()*4)|0;
//return idx*Math.PI/6;
return (idx - 2)*Math.PI/4;
//return ((6*Math.random()-3)|0)*Math.PI/6;
if(Math.random() > 0.5){
return Math.PI/2;
}
return -Math.PI/2;
}
function outside(v) {
return Math.abs(v.x) > (w>>1) || Math.abs(v.y) > (h>>1);
}
// part
function part(start, dir, w, life) {
this.old = clone(start);
this.start = clone(start);
this.dir = dir;
this.dist = length(this.dir);
this.width = w || 60;
this.distance = 0;
this.max_distance = this.width==1?2: this.width*15;
this.life = life;
this.update = function(dt) {
mov(this.old, this.start);
madd(this.start, dt, this.dir);
this.distance += this.dist*dt;
this.life--;
if(this.distance > this.max_distance) {
if(Math.random() < 0.5) {
this.start = add(this.start, mul(-0.2, this.dir));
this.dir = rot(this.dir, rndAng());
} else {
part.add(new part(
clone(this.start),
mul(0.8, rot(this.dir, rndAng())),
Math.max(1,this.width>>1),
(this.life*0.6)|0)
);
}
this.distance = 0;
}
if(outside(this.start) || this.life <= 0) {
part.free(this);
}
}
this.render = function(ctx) {
ctx.beginPath();
ctx.lineWidth = this.width;
var alpha = Math.min(this.width*0.4, 0.8);
ctx.strokeStyle = 'rgba(0, 0, 0, ' + alpha + ')';
ctx.lineCap = 'round';
ctx.moveTo(this.old.x, this.old.y);
ctx.lineTo(this.start.x, this.start.y);
ctx.stroke();
}
}
part.all = [];
part.free = function(p) {
part.all[p.index] = null;
}
part.get_free = function() {
for(var i = 0; i < part.all.length; ++i) {
if(!part.all[i]) return i;
}
return null;
}
part.add = function(p) {
if(part.all.length == 1000) {
var i = part.get_free();
if(i !== null) {
part.all[i] = p;
p.index = i;
}
} else {
p.index = part.all.length;
part.all.push(p);
}
}
for(var i = 0; i < 10; ++i) {
part.add(new part(v2(0, 0), rot(v2(0, 16), rndAng()*3), 25, 800));
}
var frame = function(fn) { setTimeout(fn, 16); }
function loop() {
for(var i = 0; i < part.all.length; ++i) {
var p = part.all[i];
if(p) {
p.update(1);
p.render(ctx);
}
}
frame(loop);
}
frame(loop);
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment