feat(physics): 集成 Rapier2D 物理引擎并修复预览重置问题 (#244)
* feat(physics): 集成 Rapier2D 物理引擎并修复预览重置问题 * fix: 修复 CI 流程并清理代码
This commit is contained in:
213
packages/physics-rapier2d/src/services/Physics2DService.ts
Normal file
213
packages/physics-rapier2d/src/services/Physics2DService.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
5
packages/physics-rapier2d/src/services/index.ts
Normal file
5
packages/physics-rapier2d/src/services/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Physics 2D Services exports
|
||||
*/
|
||||
|
||||
export { Physics2DService } from './Physics2DService';
|
||||
Reference in New Issue
Block a user