feat(physics): 集成 Rapier2D 物理引擎并修复预览重置问题 (#244)

* feat(physics): 集成 Rapier2D 物理引擎并修复预览重置问题

* fix: 修复 CI 流程并清理代码
This commit is contained in:
YHH
2025-11-28 10:32:28 +08:00
committed by GitHub
parent cabb625a17
commit 673f5e5855
56 changed files with 4934 additions and 218 deletions

View File

@@ -0,0 +1,213 @@
/**
* Physics2DService
* 2D 物理服务
*
* 提供全局物理配置和实用方法
*/
import type { IService } from '@esengine/ecs-framework';
import type { Vector2, Physics2DConfig, RaycastHit2D, OverlapResult2D } from '../types/Physics2DTypes';
import { DEFAULT_PHYSICS_CONFIG, CollisionLayer2D } from '../types/Physics2DTypes';
import type { Physics2DSystem } from '../systems/Physics2DSystem';
/**
* 2D 物理服务
*
* 提供场景级别的物理配置和全局查询方法。
* 作为服务注册到 ServiceContainer 中。
*
* @example
* ```typescript
* // 从服务容器获取
* const physicsService = scene.services.resolve(Physics2DService);
*
* // 使用射线检测
* const hit = physicsService.raycast(origin, direction, 100);
* if (hit) {
* console.log('Hit entity:', hit.entityId);
* }
* ```
*/
export class Physics2DService implements IService {
private _config: Physics2DConfig = { ...DEFAULT_PHYSICS_CONFIG };
private _physicsSystem: Physics2DSystem | null = null;
/**
* 设置物理系统引用
* @internal
*/
public setPhysicsSystem(system: Physics2DSystem): void {
this._physicsSystem = system;
}
/**
* 获取物理系统
*/
public getPhysicsSystem(): Physics2DSystem | null {
return this._physicsSystem;
}
// ==================== 配置 ====================
/**
* 获取物理配置
*/
public getConfig(): Readonly<Physics2DConfig> {
return this._config;
}
/**
* 设置重力
*/
public setGravity(gravity: Vector2): void {
this._config.gravity = { ...gravity };
this._physicsSystem?.setGravity(gravity);
}
/**
* 获取重力
*/
public getGravity(): Vector2 {
return this._physicsSystem?.getGravity() ?? { ...this._config.gravity };
}
/**
* 设置时间步长
*/
public setTimestep(timestep: number): void {
this._config.timestep = timestep;
}
/**
* 获取时间步长
*/
public getTimestep(): number {
return this._config.timestep;
}
// ==================== 查询 ====================
/**
* 射线检测(第一个命中)
* @param origin 起点
* @param direction 方向(归一化)
* @param maxDistance 最大距离
* @param collisionMask 碰撞掩码(默认所有层)
*/
public raycast(
origin: Vector2,
direction: Vector2,
maxDistance: number,
collisionMask: number = CollisionLayer2D.All
): RaycastHit2D | null {
return this._physicsSystem?.raycast(origin, direction, maxDistance, collisionMask) ?? null;
}
/**
* 射线检测(所有命中)
* @param origin 起点
* @param direction 方向(归一化)
* @param maxDistance 最大距离
* @param collisionMask 碰撞掩码(默认所有层)
*/
public raycastAll(
origin: Vector2,
direction: Vector2,
maxDistance: number,
collisionMask: number = CollisionLayer2D.All
): RaycastHit2D[] {
return this._physicsSystem?.raycastAll(origin, direction, maxDistance, collisionMask) ?? [];
}
/**
* 点重叠检测
* @param point 检测点
* @param collisionMask 碰撞掩码
*/
public overlapPoint(point: Vector2, collisionMask: number = CollisionLayer2D.All): OverlapResult2D {
return this._physicsSystem?.overlapPoint(point, collisionMask) ?? { entityIds: [], colliderHandles: [] };
}
/**
* 圆形重叠检测
* @param center 圆心
* @param radius 半径
* @param collisionMask 碰撞掩码
*/
public overlapCircle(
center: Vector2,
radius: number,
collisionMask: number = CollisionLayer2D.All
): OverlapResult2D {
return this._physicsSystem?.overlapCircle(center, radius, collisionMask) ?? { entityIds: [], colliderHandles: [] };
}
/**
* 矩形重叠检测
* @param center 中心点
* @param halfExtents 半宽高
* @param rotation 旋转角度
* @param collisionMask 碰撞掩码
*/
public overlapBox(
center: Vector2,
halfExtents: Vector2,
rotation: number = 0,
collisionMask: number = CollisionLayer2D.All
): OverlapResult2D {
return (
this._physicsSystem?.overlapBox(center, halfExtents, rotation, collisionMask) ?? {
entityIds: [],
colliderHandles: []
}
);
}
// ==================== 工具方法 ====================
/**
* 归一化向量
*/
public normalize(v: Vector2): Vector2 {
const length = Math.sqrt(v.x * v.x + v.y * v.y);
if (length === 0) return { x: 0, y: 0 };
return { x: v.x / length, y: v.y / length };
}
/**
* 计算两点之间的距离
*/
public distance(a: Vector2, b: Vector2): number {
const dx = b.x - a.x;
const dy = b.y - a.y;
return Math.sqrt(dx * dx + dy * dy);
}
/**
* 计算向量长度
*/
public magnitude(v: Vector2): number {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
/**
* 向量点积
*/
public dot(a: Vector2, b: Vector2): number {
return a.x * b.x + a.y * b.y;
}
/**
* 向量叉积返回标量2D 特有)
*/
public cross(a: Vector2, b: Vector2): number {
return a.x * b.y - a.y * b.x;
}
/**
* 释放资源
*/
public dispose(): void {
this._physicsSystem = null;
}
}

View File

@@ -0,0 +1,5 @@
/**
* Physics 2D Services exports
*/
export { Physics2DService } from './Physics2DService';