| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- import { BALL_RADIUS, BALL_COLOR } from '../constants.js';
- /**
- * Ball - 小球实体
- * 由玩家发射,碰撞方块和边缘时反弹
- */
- export class Ball {
- /**
- * @param {number} x - 初始 x 坐标
- * @param {number} y - 初始 y 坐标
- * @param {number} [radius=BALL_RADIUS] - 半径
- * @param {string} [color=BALL_COLOR] - 颜色
- */
- constructor(x, y, radius = BALL_RADIUS, color = BALL_COLOR) {
- this.x = x;
- this.y = y;
- this.radius = radius;
- this.color = color;
- this.vx = 0;
- this.vy = 0;
- this.active = true;
- }
- /**
- * 每帧更新位置(子步移动,fraction 为 0~1 的比例)
- * 处理左/右/顶部边缘反弹,底部停止
- * @param {number} _deltaTime - 未使用,保留接口兼容
- * @param {number} boardWidth - 面板宽度
- * @param {number} boardHeight - 面板高度
- * @param {number} [fraction=1] - 移动比例(用于子步进防穿透)
- */
- update(_deltaTime, boardWidth, boardHeight, fraction = 1) {
- if (!this.active) return;
- // 移动 fraction 比例的距离
- this.x += this.vx * fraction;
- this.y += this.vy * fraction;
- // 左侧边缘反弹
- if (this.x - this.radius <= 0) {
- this.x = this.radius;
- this.reflect('x');
- }
- // 右侧边缘反弹
- if (this.x + this.radius >= boardWidth) {
- this.x = boardWidth - this.radius;
- this.reflect('x');
- }
- // 顶部边缘反弹
- if (this.y - this.radius <= 0) {
- this.y = this.radius;
- this.reflect('y');
- }
- // 底部:停止运动
- if (this.isAtBottom(boardHeight)) {
- this.y = boardHeight - this.radius;
- this.active = false;
- }
- }
- /**
- * 反射:反转指定轴的速度分量
- * @param {'x'|'y'} axis - 'x' 反转 vx,'y' 反转 vy
- */
- reflect(axis) {
- if (axis === 'x') {
- this.vx = -this.vx;
- } else if (axis === 'y') {
- this.vy = -this.vy;
- }
- }
- /**
- * 判断球是否到达底部
- * @param {number} boardHeight - 面板高度
- * @returns {boolean}
- */
- isAtBottom(boardHeight) {
- return this.y + this.radius >= boardHeight;
- }
- /**
- * 获取碰撞矩形(AABB)
- * @returns {{ x: number, y: number, width: number, height: number }}
- */
- getRect() {
- const diameter = this.radius * 2;
- return {
- x: this.x - this.radius,
- y: this.y - this.radius,
- width: diameter,
- height: diameter
- };
- }
- }
|