JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
class World {
constructor () {
this.canvas = document.getElementById("canvas");
this.ctx = canvas.getContext("2d");
this.h = this.canvas.height = window.innerHeight;
this.w = this.canvas.width = window.innerWidth;
this.ctx.lineWidth = 2;
this.bounce = 0.1;
this.gravity = 0.1;
this.friction = 0.99;
this.points = [];
this.points.push({
x: 100,
y: 100,
oldx: 95,
oldy: 105
});
this.points.push({
x: 100,
y: 200,
oldx: 95,
oldy: 201
});
this.points.push({
x: 200,
y: 100,
oldx: 201,
oldy: 101
});
this.points.push({
x: 200,
y: 200,
oldx: 201,
oldy: 201
});
this.sticks = [];
// Square
this.connectPoints(0, 1);
this.connectPoints(1, 2);
this.connectPoints(2, 3);
this.connectPoints(3, 0);
// Support cross, diagonals
// Try commenting them out
// and see what happens! ;)
this.connectPoints(0, 2);
this.connectPoints(1, 3);
this.onMove = this.onMove.bind(this);
this.canvas.addEventListener("mousemove", this.onMove);
this.canvas.addEventListener("touchmove", this.onMove);
}
connectPoints(index0, index1) {
this.sticks.push({
p0: this.points[index0],
p1: this.points[index1],
length: this.distance(
this.points[index0],
this.points[index1]),
});
}
onMove(e) {
var x = e.touches ? e.touches[0].clientX : e.clientX;
var y = e.touches ? e.touches[0].clientY : e.clientY;
var p0 = { x: x, y: y };
var p1 = this.getClosestPoint(p0);
var dist = this.distance(p0, p1);
if(dist < 55) {
p1.oldx = x;
p1.oldy = y;
}
}
getClosestPoint(p0) {
var index = 0;
this.points.map(p1 => this.distance(p0, p1)).reduce((prev, curr, i) => {
if(curr < prev) {
index = i;
}
return Math.min(curr, prev);
});
return this.points[index];
}
distance(p0, p1) {
var x = p1.x - p0.x;
var y = p1.y - p0.y;
return Math.sqrt(x*x + y*y);
}
update() {
this.ctx.clearRect(0, 0, this.w, this.h);
this.updatePoints();
this.updateSticks();
this.drawSticks();
}
drawSticks() {
this.ctx.beginPath();
this.sticks.forEach(s => {
this.ctx.moveTo(s.p0.x, s.p0.y);
this.ctx.lineTo(s.p1.x, s.p1.y);
});
this.ctx.stroke();
}
updatePoints() {
this.points.forEach(p => {
if(!p.pinned) {
var vx = (p.x - p.oldx) * this.friction;
var vy = (p.y - p.oldy) * this.friction;
p.oldx = p.x;
p.oldy = p.y;
// Ground friction
if(p.y > this.h - this.ctx.lineWidth) {
vx *= 0.5;
}
p.x += vx;
p.y += vy;
p.y += this.gravity;
if(p.x > this.w) {
p.x = this.w;
p.oldx = p.x + vx * this.bounce;
}
if(p.x < 0) {
p.x = 0;
p.oldx = vx * this.bounce;
}
if(p.y > this.h - this.ctx.lineWidth) {
p.y = this.h - this.ctx.lineWidth;
p.oldy = p.y + vy * this.bounce;
}
if(p.y < 0) {
p.y = 0;
p.oldy = vy * this.bounce;
}
}
});
}
updateSticks() {
this.sticks.forEach(s => {
var dx = s.p1.x - s.p0.x;
var dy = s.p1.y - s.p0.y;
var dist = Math.sqrt(dx*dx + dy*dy);
var diff = s.length - dist;
var percent = diff / dist / 2;
var offsetX = dx * percent;
var offsetY = dy * percent;
s.p0.x -= offsetX;
s.p0.y -= offsetY;
s.p1.x += offsetX;
s.p1.y += offsetY;
});
}
}
var world = new World();
function animate() {
world.update();
requestAnimationFrame(animate);
}
animate();