Crashcat: موتور فیزیک جاوااسکریپت برای بازیها و شبیهسازیها
خلاصهٔ کاملتر
Crashcat یه کتابخونهی فیزیک جاوااسکریپته که کاملاً با خود JS نوشته شده و نیازی به WebAssembly یا زبان دیگهای نداره. هدفش اینه که به توسعهدهندههای وب قدرت یه موتور فیزیک حرفهای رو بده، بدون اینکه مجبور باشن از اکوسیستم جاوااسکریپت خارج بشن.
از نظر قابلیتها، Crashcat خیلی کامله: شبیهسازی rigid body، پشتیبانی از شکلهای محدب، مشهای مثلثی و شکلهای سفارشی، انواع قیدها مثل hinge، slider، distance، fixed، cone و six-dof، موتورها و فنرها روی قیدها، و تشخیص برخورد پیوسته (CCD) برای اجسام سریع. ضمناً حالت خواب برای rigid bodyهای ساکن و sensor bodyها هم داره که به بهینهسازی کمک میکنن.
یه ویژگی مهمش اینه که tree-shakeable طراحی شده؛ یعنی فقط همون قابلیتهایی که استفاده میکنی وارد bundle نهایی میشن. مثلاً میتونی بهجای registerAll()، فقط شکلها یا قیدهای مورد نیازت رو ثبت کنی.
برای شروع، باید یه دنیای فیزیک بسازی. Crashcat از یه سیستم دو لایهای استفاده میکنه: Broadphase Layers برای عملکرد فضایی (مثلاً "در حال حرکت" و "ساکن") و Object Layers برای کنترل اینکه کدوم اجسام با هم برخورد دارن. این ترکیب هم سرعت پردازش رو بالا میبره، هم کنترل دقیقی روی فیلتر برخوردها میده.
یه مثال ساده برای ساخت دنیا و چند جسم دینامیک اینه:
import { createWorld, createWorldSettings, addBroadphaseLayer, addObjectLayer,
enableCollision, rigidBody, box, MotionType, registerAll, updateWorld } from 'crashcat';
registerAll();
const worldSettings = createWorldSettings();
worldSettings.gravity = [0, -9.81, 0];
const BROADPHASE_LAYER_MOVING = addBroadphaseLayer(worldSettings);
const BROADPHASE_LAYER_NOT_MOVING = addBroadphaseLayer(worldSettings);
const OBJECT_LAYER_MOVING = addObjectLayer(worldSettings, BROADPHASE_LAYER_MOVING);
const OBJECT_LAYER_NOT_MOVING = addObjectLayer(worldSettings, BROADPHASE_LAYER_NOT_MOVING);
enableCollision(worldSettings, OBJECT_LAYER_MOVING, OBJECT_LAYER_NOT_MOVING);
enableCollision(worldSettings, OBJECT_LAYER_MOVING, OBJECT_LAYER_MOVING);
const world = createWorld(worldSettings);بعد از ساخت دنیا، میتونی اجسام ایستا (مثل زمین) و دینامیک (مثل جعبهها) بسازی و شبیهسازی رو قدم به قدم پیش ببری.
برای گامزنی شبیهسازی، دو روش رایج وجود داره. روش اول زمان متغیره (variable timestep) که سادهتره:
let lastTime = performance.now();
const maxDelta = 1 / 30;
function gameLoop() {
const currentTime = performance.now();
const delta = Math.min((currentTime - lastTime) / 1000, maxDelta);
lastTime = currentTime;
updateWorld(world, undefined, delta);
requestAnimationFrame(gameLoop);
}روش دوم استفاده از timestep ثابت با accumulator هست که دقت و determinism بیشتری داره و برای بازیهای حرفهایتر توصیه میشه:
const PHYSICS_DT = 1 / 60;
let accumulator = 0;
let lastTimeFixed = performance.now();
function gameLoopFixed() {
const frameTime = Math.min((performance.now() - lastTimeFixed) / 1000, 0.25);
lastTimeFixed = performance.now();
accumulator += frameTime;
while (accumulator >= PHYSICS_DT) {
updateWorld(world, undefined, PHYSICS_DT);
accumulator -= PHYSICS_DT;
}
requestAnimationFrame(gameLoopFixed);
}Crashcat با هیچ موتور گرافیکی خاصی گره نخورده و میتونی ازش با Three.js، Babylon.js، PlayCanvas یا حتی موتور گرافیکی خودت استفاده کنی. این انعطافپذیری باعث شده که هم برای پروژههای کوچک و هم برای بازیهای جدی مناسب باشه. مستندات کامل API هم روی سایت crashcat.dev/docs در دسترسه.
نکات کلیدی:
- موتور فیزیک خالص جاوااسکریپت، بدون نیاز به WebAssembly
- پشتیبانی از rigid body، CCD، قیدها، فنرها و موتورها
- سیستم لایهبندی Broadphase + Object Layer برای فیلتر برخورد و بهینهسازی
- طراحی tree-shakeable: فقط چیزی که استفاده میکنی bundle میشه
- سازگار با Three.js، Babylon.js، PlayCanvas و هر موتور دلخواهی
- دو روش گامزنی: variable timestep (ساده) و fixed timestep (دقیقتر)




