# 实践-弹弹球
# 预览效果
刷新网页重新开始动画
# 实现一个二维向量类
export function Vector2(x, y) {
this.x = x;
this.y = y;
}
Vector2.prototype = {
// 复制
copy: function () {
return new Vector2(this.x, this.y);
},
// 取模
length: function () {
return Math.sqrt(this.x * this.x + this.y * this.y);
},
// 平方和
sqrLength: function () {
return this.x * this.x + this.y * this.y;
},
// 方向矢量(单位矢量)
normalize: function () {
var inv = 1 / this.length();
return new Vector2(this.x * inv, this.y * inv);
},
// 取反
negate: function () {
return new Vector2(-this.x, -this.y);
},
// 加法
add: function (v) {
return new Vector2(this.x + v.x, this.y + v.y);
},
// 减法
subtract: function (v) {
return new Vector2(this.x - v.x, this.y - v.y);
},
// 数乘
multiply: function (f) {
return new Vector2(this.x * f, this.y * f);
},
// 除法
divide: function (f) {
var invf = 1 / f;
return new Vector2(this.x * invf, this.y * invf);
},
// 点乘
dot: function (v) {
return this.x * v.x + this.y * v.y;
},
// 投影
projection: function (v) {}
};
# 实现一个球类
export function Ball(color, mass, pos, vel, acc) {
this.color = color;
this.mass = mass;
this.r = Math.cbrt(mass);
this.pos = pos;
this.vel = vel;
this.acc = acc;
}
// 小球绘制方法 传入canvas上下文
Ball.prototype.draw = function (ctx) {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.pos.x, this.pos.y, this.r, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
};
// 小球运动方法 与其他球以及墙壁交互 并且传入canvas上下文
Ball.prototype.move = function (ball, container) {
// 位置
this.pos = this.pos.add(this.vel);
// 速度
this.vel = this.vel.add(this.acc);
// 边界检测
// 撞击左右墙壁 速度反向并且衰减1%
if (
this.pos.x < container.left + this.r ||
this.pos.x > container.right - this.r
) {
this.vel.x *= -0.99;
}
// 撞击上下墙壁 速度反向并且衰减1%
if (
this.pos.y < container.top + this.r ||
this.pos.y > container.bottom - this.r
) {
this.vel.y *= -0.99;
}
// 小球之间的撞击
if (isBallHit(this, ball)) {
// console.log('碰撞了');
// 假设为完全弹性碰撞
let v10 = this.vel.copy();
let v20 = ball.vel.copy();
this.vel = v10
.multiply(this.mass - ball.mass)
.add(v20.multiply(2 * ball.mass))
.divide(this.mass + ball.mass);
ball.vel = v20
.multiply(ball.mass - this.mass)
.add(v10.multiply(2 * this.mass))
.divide(this.mass + ball.mass);
}
};
# 实现一个墙壁类
export function Container(left, right, top, bottom) {
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
this.width = this.right - this.left;
this.height = this.bottom - this.top;
}
Container.prototype.draw = function (ctx) {
ctx.strokeRect(this.left, this.top, this.width, this.height);
};