你需要实现 EventScheduler 类,这是粒子碰撞模拟器的核心算法模块,负责管理和调度所有碰撞事件。
算法原理:事件驱动模拟
传统的物理模拟使用固定时间步长(如每秒60帧),但这会导致碰撞检测不精确。事件驱动模拟采用完全不同的思路:
- 预测所有可能的碰撞事件及其发生时间
- 将事件放入优先级队列(按时间排序)
- 跳转到下一个事件的时间点,精确处理碰撞
- 碰撞后重新预测受影响粒子的未来碰撞
这种方法能够精确模拟物理过程,无论粒子速度多快都不会"穿透"。
EventScheduler 接口
class EventScheduler {
constructor() // 初始化事件调度器,创建优先级队列
clear(): void // 清空事件队列
peekNextValidEvent(particles: Particle[]): CollisionEvent | null
// 获取下一个有效事件(不移除),需过滤过时事件
processNextValidEvent(particles: Particle[]): CollisionEvent | null
// 处理并移除下一个有效事件
predictCollisionsForParticle(particle, allParticles, container, currentTime): void
// 为单个粒子预测所有碰撞事件并加入队列
predictAllCollisions(particles, container, currentTime): void
// 预测所有粒子的碰撞事件
}可用的工具类
PriorityQueue - 优先级队列
new PriorityQueue((a, b) => a.time - b.time)
queue.push(event) // 插入
queue.peek() // 查看顶部
queue.pop() // 移除顶部
queue.isEmpty() // 是否为空PhysicsCalculator - 物理计算工具
// 计算两个粒子的碰撞时间
PhysicsCalculator.calculateParticleCollisionTime(p1, p2)
// 计算粒子与墙壁的碰撞时间
PhysicsCalculator.calculateWallCollisionTime(particle, container)
// 返回: { time: number, wall?: 'top'|'bottom'|'left'|'right' }数据类型
interface Particle {
id: number;
x: number, y: number; // 位置
vx: number, vy: number; // 速度
radius: number, mass: number;
collisionCount: number; // 碰撞计数
}
interface CollisionEvent {
time: number; // 碰撞时间
type: 'particle' | 'wall';
particleA: number; // 粒子A的ID
particleB?: number; // 粒子B的ID
wall?: 'top'|'bottom'|'left'|'right';
countA: number; // 粒子A的碰撞计数
countB?: number; // 粒子B的碰撞计数
}提交代码后,点击"生成粒子"和"开始模拟"按钮测试你的实现。