import Matter from 'matter-js'; import type { LeviarObject } from './LeviarObject.js'; /** * matter-js 기반 물리 엔진 래퍼. * attribute.physics = 'dynamic' | 'static' 인 LeviarObject를 등록하고 매 프레임 시뮬레이션을 수행합니다. */ export declare class PhysicsEngine { readonly engine: Matter.Engine; private bodyMap; private objMap; private prevTime; /** syncObjectSizes에서 크기 변경 감지용 - border/margin 제외한 순수 w, h */ private lastSizeMap; /** Z 또는 레이어 ID → 양수 그룹 번호 매핑 (1-based). 같은 그룹 = 충돌, 다른 그룹 = 차단 */ private zGroupMap; private nextZGroup; constructor(); /** * LeviarObject를 물리 바디로 등록합니다. * attribute.physics에 따라 dynamic / static 바디를 생성합니다. */ addBody(obj: LeviarObject, w: number, h: number): void; /** * 물리 바디의 크기를 재계산하여 재생성합니다. * 현재 위치, 속도, 각도를 유지합니다. * w, h는 style.width * scale, style.height * scale 기준 (margin/border 미포함) */ updateBodySize(obj: LeviarObject, w: number, h: number): void; /** * LeviarObject._renderedSize 기반으로 물리 바디 크기를 동기화합니다. * dirty + 디바운스(개혁) 또는 스로틄(강제) 조건 달성 시에만 크기를 재확인합니다. */ syncObjectSizes(objects: Iterable): void; /** * LeviarObject의 물리 바디를 제거합니다. */ removeBody(obj: LeviarObject): void; /** * 특정 오브젝트에 힘을 적용합니다. */ applyForce(obj: LeviarObject, force: { x: number; y: number; }): void; /** * 특정 오브젝트의 속도를 설정합니다. */ setVelocity(obj: LeviarObject, velocity: { x: number; y: number; }): void; /** * 물리 시뮬레이션을 진행하고, 바디 위치를 LeviarObject에 동기화합니다. * @param timestamp requestAnimationFrame의 타임스탬프 */ step(timestamp: number): void; private getFlatAncestor; /** * 매 step 전, 오브젝트가 속한 레이어 또는 Z 좌표를 기반으로 collisionFilter.group을 동적으로 갱신합니다. * - 같은 레이어/Z → 같은 category 비트 → 충돌 허용 * - 다른 레이어/Z → 다른 category 비트 → 충돌 차단 * - 사용자가 attr.collisionGroup을 명시한 경우 Z/레이어 로직을 건너뜁니다. */ private updateZCollisionFilters; /** * matter-js 바디의 위치/회전을 LeviarObject.transform에 반영합니다. */ private syncToObjects; }