ballz.js/ball.js

108 lines
3.3 KiB
JavaScript
Raw Normal View History

2019-04-06 17:19:26 +00:00
class Ball {
constructor(game, cx, cy, v, dir) {
this.game = game;
this.id = this.game.balls.length;
this.cx = cx;
this.cy = cy;
this.vx = v * Math.cos(dir);
this.vy = v * Math.sin(dir);
this.collide = true;
}
update(stepCount = 10) {
if (!this.game.isMoving)
return;
for (let i = 0; i < stepCount; i++) {
this.cx += this.vx / stepCount;
this.cy -= this.vy / stepCount;
if (this.cx - this.game.ballRadius <= 0 || this.cx + this.game.ballRadius >= this.game.canvas.width) {
this.vx *= -1;
}
if (this.cy - this.game.ballRadius <= 0) {
this.vy *= -1;
}
if (this.cy >= this.game.originY && this.vy < 0) {
this.vy = 0;
this.cy = this.game.originY;
if (this.game.newOriginX === null || this.cx === this.game.newOriginX) {
this.game.newOriginX = this.cx;
this.vy = 0;
this.remove();
} else {
this.vx = (this.game.newOriginX - this.cx) / 60 * 2;
setTimeout(() => {
this.vx = 0;
this.remove();
}, 500);
}
}
if (this.collide) {
this.game.rects.forEach(rect => {
this.checkHitRect(rect);
});
this.game.powerUps.forEach(powerUp => {
this.checkHitPowerUp(powerUp);
});
}
}
}
remove() {
this.game.balls.splice(this.game.balls.findIndex(ball => ball === this), 1);
if (this.game.isMoving && this.game.balls.length === 0) {
this.game.roundOver();
}
}
checkHitRect(rect) {
const closestX = Math.clamp(this.cx, rect.x, rect.x + this.game.rectSize);
const closestY = Math.clamp(this.cy, rect.y, rect.y + this.game.rectSize);
const distX = this.cx - closestX;
const distY = this.cy - closestY;
const distSquared = (distX ** 2) + (distY ** 2);
if (distSquared < this.game.ballRadius ** 2) {
const collBottom = rect.y + this.game.rectSize - (this.cy - this.game.ballRadius);
const collTop = (this.cy + this.game.ballRadius) - rect.y;
const collLeft = (this.cx + this.game.ballRadius) - rect.x;
const collRight = rect.x + this.game.rectSize - (this.cx - this.game.ballRadius);
if ((collTop <= collLeft && collTop <= collRight) || (collBottom <= collLeft && collBottom <= collRight)) {
this.vy *= -1;
} else {
this.vx *= -1;
}
rect.hit(this);
}
}
checkHitPowerUp(powerUp) {
const distX = this.cx - powerUp.cx;
const distY = this.cy - powerUp.cy;
const distSquared = (distX ** 2) + (distY ** 2);
if (distSquared < (this.game.ballRadius + this.game.powerUpRadius) ** 2) {
powerUp.hit();
}
}
draw() {
this.game.ctx.fillStyle = '#fff';
this.game.ctx.beginPath();
this.game.ctx.arc(this.cx, this.cy, this.game.ballRadius, 0, 2 * Math.PI);
this.game.ctx.fill();
}
}