Skip to content

Instantly share code, notes, and snippets.

@dmirtyisme
Created February 11, 2016 04:46
Show Gist options
  • Save dmirtyisme/f8ebdf96ea9e0cba4ae1 to your computer and use it in GitHub Desktop.
Save dmirtyisme/f8ebdf96ea9e0cba4ae1 to your computer and use it in GitHub Desktop.
what power
<audio controls="controls">
<source src="http://www.dhteumeuleu.com/sound/coldsong.mp3" type="audio/mp3" />
</audio>
~ function() {
'use strict';
function Doll(x, size, stiffness, structure) {
this.x = x;
this.s = size;
this.stiffness = stiffness;
this.points = [];
this.links = [];
this.angles = [];
function Point(doll) {
this.x = doll.x;
this.y = 10;
this.xb = this.x;
this.yb = this.y + 2;
this.w = 0;
this.stiffness = doll.stiffness;
this.mass = 1;
}
Point.prototype.anim = function() {
var vx = (this.x - this.xb) * this.stiffness,
vy = (this.y - this.yb) * this.stiffness;
this.xb = this.x;
this.yb = this.y;
this.x += vx + 0.5 * (Math.random() - 0.5);
this.y += vy + 0.5 * (Math.random() - 0.5);
var dx = this.x - pointer.x,
dy = this.y - pointer.y,
d = Math.sqrt(dx * dx + dy * dy),
w = (pointer.sw + this.w) * 0.5;
if (d < w) {
d = Math.abs(w - d);
var a = Math.atan2(dy, dx);
this.x += d * Math.cos(a);
this.y += d * Math.sin(a);
}
if (this.y < 0) {
this.y = 0;
this.yb = -2;
} else if (this.y > canvas.height) {
this.y = canvas.height;
this.yb = canvas.height + 2;
}
if (this.x < 0) {
this.x = 0;
this.xb = -2;
} else if (this.x > canvas.width) {
this.x = canvas.width;
this.xb = canvas.width + 2;
}
}
function Angle(p1, p2, p3, len1, len2, angle, range, force) {
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
this.len1 = len1;
this.len2 = len2;
this.angle = angle;
this.range = range;
this.force = force || 0.2;
}
Angle.prototype.solve = function() {
var a, b, c, e, m, m1, m2, m3, x1, y1, cos, sin;
a = Math.atan2(this.p2.y - this.p1.y, this.p2.x - this.p1.x);
b = Math.atan2(this.p3.y - this.p2.y, this.p3.x - this.p2.x);
c = this.angle - (b - a);
c = c > Math.PI ? (c - 2 * Math.PI) : (c < -Math.PI ? (c + 2 * Math.PI) : c);
e = (Math.abs(c) > this.range) ? (-Math.sign(c) * this.range + c) * this.force : 0;
m = this.p1.mass + this.p2.mass;
m1 = this.p1.mass / m;
m2 = this.p2.mass / m;
cos = Math.cos(a - e);
sin = Math.sin(a - e);
x1 = this.p1.x + (this.p2.x - this.p1.x) * m2;
y1 = this.p1.y + (this.p2.y - this.p1.y) * m2;
this.p1.x = x1 - cos * this.len1 * m2;
this.p1.y = y1 - sin * this.len1 * m2;
this.p2.x = x1 + cos * this.len1 * m1;
this.p2.y = y1 + sin * this.len1 * m1;
a = Math.atan2(this.p2.y - this.p3.y, this.p2.x - this.p3.x) + e;
m = this.p2.mass + this.p3.mass;
m2 = this.p2.mass / m;
m3 = this.p3.mass / m;
cos = Math.cos(a);
sin = Math.sin(a);
x1 = this.p3.x + (this.p2.x - this.p3.x) * m2;
y1 = this.p3.y + (this.p2.y - this.p3.y) * m2;
this.p3.x = x1 - cos * this.len2 * m2;
this.p3.y = y1 - sin * this.len2 * m2;
this.p2.x = x1 + cos * this.len2 * m3;
this.p2.y = y1 + sin * this.len2 * m3;
};
function Link(doll, link) {
this.length = link.length * doll.s;
this.width = link.width * doll.s;
this.image = new Image();
this.image.src = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/222599/' + link.img;
doll.points[link.p0] = this.p0 = (doll.points[link.p0] ? doll.points[link.p0] : new Point(doll));
doll.points[link.p1] = this.p1 = (doll.points[link.p1] ? doll.points[link.p1] : new Point(doll));
if (this.width > this.p0.w) this.p0.w = this.width;
var mass = link.mass || 1;
if (mass > this.p0.mass) this.p0.mass = mass;
if (mass > this.p1.mass) this.p1.mass = mass;
}
Link.prototype.draw = function() {
var dx = this.p1.x - this.p0.x,
dy = this.p1.y - this.p0.y,
a = Math.atan2(dy, dx);
ctx.save();
ctx.translate(this.p0.x, this.p0.y);
ctx.rotate(a);
ctx.drawImage(this.image, -this.width * 0.15, -this.width * 0.5, this.length + this.width * 0.3, this.width);
ctx.restore();
}
function len(p0, p1) {
for (var i = 0; i < structure.links.length; i++) {
var link = structure.links[i];
if ((link.p0 === p0 && link.p1 === p1) || (link.p0 === p1 && link.p1 === p0)) {
return link.length;
break;
}
}
return 1;
}
for (var i = 0; i < structure.links.length; i++) {
var link = structure.links[i];
this.links.push(new Link(this, link));
}
for (var i = 0; i < structure.constraints.length; i++) {
var constraint = structure.constraints[i];
this.angles.push(
new Angle(
this.points[constraint.p1],
this.points[constraint.p2],
this.points[constraint.p3],
len(constraint.p1, constraint.p2) * size,
len(constraint.p2, constraint.p3) * size,
constraint.angle,
constraint.range,
constraint.force
)
);
}
}
Doll.prototype.anim = function() {
for (var i = 0, o; o = this.angles[i++]; o.solve());
for (var i = 0, o; o = this.points[i++]; o.anim());
for (var i = 0, o; o = this.links[i++]; o.draw());
}
Doll.prototype.collide = function(doll) {
for (var i = 0, o1; o1 = this.points[i++];) {
for (var j = 0, o2; o2 = doll.points[j++];) {
var dx = o1.x - o2.x,
dy = o1.y - o2.y,
d = Math.sqrt(dx * dx + dy * dy),
w = (o1.w + o2.w) * 0.5;
if (d < w) {
d = Math.abs(w - d);
var a = Math.atan2(dy, dx),
vx = d * Math.cos(a) * 0.5,
vy = d * Math.sin(a) * 0.5;
o1.x += vx;
o1.y += vy;
o2.x -= vx;
o2.y -= vy;
}
}
}
}
// main loop
function run() {
requestAnimationFrame(run);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.fillStyle = '#222225';
ctx.arc(pointer.x, pointer.y, pointer.sw / 2, 0, 2 * Math.PI);
ctx.fill();
if (pointer.time -- < 0) {
if (pointer.sw > 1) pointer.sw--;
} else pointer.sw += (canvas.sw - pointer.sw) / 10;
dolls[0].anim();
dolls[1].anim();
dolls[0].collide(dolls[1]);
}
// canvas
var canvas = {
elem: document.createElement('canvas'),
resize: function() {
this.width = this.elem.width = this.elem.offsetWidth;
this.height = this.elem.height = this.elem.offsetHeight;
this.sw = Math.min(this.width, this.height) / 3;
},
init: function() {
var ctx = this.elem.getContext('2d');
document.body.appendChild(this.elem);
window.addEventListener('resize', this.resize.bind(this), false);
this.resize();
return ctx;
}
};
var ctx = canvas.init();
// pointer
var pointer = (function(canvas) {
var pointer = {
x: canvas.width / 2,
y: -500,
sw: 0,
time: 0,
pointer: function(e) {
var touchMode = e.targetTouches,
pointer;
if (touchMode) {
e.preventDefault();
pointer = touchMode[0];
} else pointer = e;
this.x = pointer.clientX;
this.y = pointer.clientY;
this.time = 200;
}
};
window.addEventListener('mousemove', function(e) {
this.pointer(e);
}.bind(pointer), false);
canvas.elem.addEventListener('touchmove', function(e) {
this.pointer(e);
}.bind(pointer), false);
return pointer;
}(canvas));
// init
var dolls = [];
var structure = {
links: [{
p0: 0,
p1: 1,
length: 3,
width: 3,
img: 'rd05.png'
}, {
p0: 1,
p1: 2,
length: 5,
width: 2.5,
img: 'rd09.png'
}, {
p0: 3,
p1: 7,
length: 6,
width: 3.5,
img: 'rd01.png'
}, {
p0: 7,
p1: 8,
length: 7,
width: 5,
img: 'rd06.png'
}, {
p0: 3,
p1: 9,
length: 6,
width: 3.5,
img: 'rd01.png'
}, {
p0: 9,
p1: 10,
length: 7,
width: 5,
img: 'rd06.png',
mass: 10
}, {
p0: 0,
p1: 4,
length: 4,
width: 4.5,
img: 'rd04.png'
}, {
p0: 0,
p1: 3,
length: 9,
width: 5,
img: 'rd08.png'
}, {
p0: 0,
p1: 5,
length: 5,
width: 3,
img: 'rd05.png'
}, {
p0: 5,
p1: 6,
length: 5,
width: 2.5,
img: 'rd07.png'
}],
constraints: [{
p1: 4,
p2: 0,
p3: 3,
angle: 0,
range: 1,
force: 0.2
}, {
p1: 3,
p2: 0,
p3: 1,
angle: Math.PI / 2,
range: Math.PI * 2,
force: 0.2
}, {
p1: 0,
p2: 1,
p3: 2,
angle: -Math.PI / 2,
range: Math.PI / 2,
force: 0.2
}, {
p1: 3,
p2: 0,
p3: 5,
angle: Math.PI / 2,
range: Math.PI * 2,
force: 0.2
}, {
p1: 0,
p2: 5,
p3: 6,
angle: -Math.PI / 2,
range: Math.PI / 2,
force: 0.2
}, {
p1: 0,
p2: 3,
p3: 7,
angle: -Math.PI / 3,
range: Math.PI / 2,
force: 0.2
}, {
p1: 0,
p2: 3,
p3: 9,
angle: -Math.PI / 3,
range: Math.PI / 2,
force: 0.2
}, {
p1: 3,
p2: 7,
p3: 8,
angle: Math.PI / 2,
range: Math.PI / 3,
force: 0.2
}, {
p1: 3,
p2: 9,
p3: 10,
angle: Math.PI / 2,
range: Math.PI / 3,
force: 0.2
}]
};
dolls[0] = new Doll(canvas.width * 0.25, canvas.height / 30, 0.998, structure);
dolls[1] = new Doll(canvas.width * 0.75, canvas.height / 30, 0.998, structure);
run();
}();
html {
overflow: hidden;
touch-action: none;
content-zooming: none;
}
body {
position: absolute;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: #000;
}
canvas {
width: 100%;
height: 100%;
background: #000;
position: absolute;
}
audio {
position: absolute;
z-index: 2;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment