變遷:從 Box2D 移植到 TypeScript 引擎的完整技術脈絡)
游戲開發(fā)【免費下載鏈接】planck.js2D JavaScript Physics Engine項目地址https://gitcode.com/gh_mirrors/pl/planck.js點擊查看免費下載planck.js 是一個以 TypeScript/JavaScript 實現(xiàn)的 2D 物理引擎MIT 協(xié)議源自 Box2D 的跨平臺 HTML5 游戲開發(fā)移植。本文以倉庫根目錄的 CHANGES.md 變更記錄為主線逐版還原 0.1 → 0.2 → 1.0.0 → 1.1.0 的演進脈絡并結(jié)合 src、vite.config.mts 等源碼證據(jù)解讀每一次重構(gòu)背后的設計動機與 API 遷移方式幫助讀者理解當前引擎的模塊結(jié)構(gòu)、事件系統(tǒng)與命名規(guī)范并掌握從舊版 API 升級到新版的關鍵對照。版本演進總覽當前倉庫 package.json 版本為 1.5.0而 CHANGES.md 記錄了從早期移植到現(xiàn)代化重構(gòu)的四個關鍵階段版本核心變化性質(zhì)0.1目錄重排、類合并、標志位改布爾字段、事件系統(tǒng)引入大范圍架構(gòu)重構(gòu)0.2TypeScript 定義加入、向量組合運算 API 重命名、關節(jié)構(gòu)造器清理API 命名規(guī)范化1.0.0全量 TypeScript 遷移、性能優(yōu)化語言與運行時升級1.1.0Vite 構(gòu)建遷移工程化升級從變更記錄看planck.js 的演進方向非常清晰先是內(nèi)部架構(gòu)去 Box2D 化0.1再是公開 API 規(guī)范化0.2隨后是類型系統(tǒng)與構(gòu)建工具鏈的現(xiàn)代化1.0.0 / 1.1.0。0.1架構(gòu)重構(gòu)——從忠實移植到JavaScript 原生0.1 是信息量最大的一次版本幾乎重寫了整個引擎的組織方式。以下按主題分組解讀。目錄結(jié)構(gòu)與文件組織source code directory layout changed, classes moved around!從當前倉庫的目錄布局可以反推這次調(diào)整的結(jié)果物理與碰撞基礎類型集中在 src/commonVec2、Vec3、Mat22、Mat33、Rot、Transform、Sweep、Jacobian等碰撞算法集中在 src/collisionAABB、BroadPhase、DynamicTree、Distance、Manifold、Shape、TimeOfImpact形狀實現(xiàn)在 src/collision/shapeCircleShape、EdgeShape、PolygonShape、ChainShape、BoxShape及各Collide*配對碰撞函數(shù)動力學與求解器集中在 src/dynamicsBody、Fixture、Contact、Joint、World、Solver關節(jié)實現(xiàn)位于 src/dynamics/joint。b2Class renamed to Class早期版本中所有類都繼承自一個b2Class基類0.1 起統(tǒng)一改名為Class。當前源碼中已完全搜不到b2Class或GrowableStack的痕跡說明這兩項已徹底移除。Dumping is removed, Drawing is moved to testbed序列化/反序列化能力被拆分場景dump功能被移除繪圖相關能力移入 testbed即planck-with-testbed構(gòu)建產(chǎn)物見 vite.config.mts 的buildTestbed分支。這也解釋了package.json中./with-testbed導出子路徑的存在——核心引擎與可視化測試臺被明確解耦。GrowableStack replaced with native array, Timer is changedBox2D 風格的自增長棧數(shù)據(jù)結(jié)構(gòu)被原生數(shù)組取代計時器改為基于Date.now()的輕量實現(xiàn)見 src/util/Timer.tsnow()直接返回Date.now()diff(time)計算差值。數(shù)學與幾何 API 拆分Math is changed and splitVec2.Min/Max renamed to Vec2.Upper/Lower and several other methods added數(shù)學工具被拆分到多個文件Vec2、Vec3、Mat22、Mat33、Rot、Transform、Sweep等見 src/common同時Vec2.Min/Max更名為Vec2.Upper/Lower并補充了若干新方法。當前 Vec2.ts 中可以看到大量以matrix.*前綴出現(xiàn)的內(nèi)部向量運算輔助以及setVec2、add、setCombine、addCombine、subCombine、setMul、addMul、subMul等方法見 Vec2.ts。TestOverlap moved from Collision to DistancetestOverlap從 Collision 模塊移入 Distance 模塊當前位于 src/collision/Distance.ts它通過設置input.useRadii true調(diào)用Distance算法計算兩形狀最近距離并以output.distance 10.0 * EPSILON判定是否重疊。同時 Distance.ts 保留了 legacy 導出Distance.testOverlap、Distance.Input、Distance.Output、Distance.Proxy、Distance.Cache方便舊代碼平滑遷移Distance.ts。Distance method, DistanceInput/Output and SimplexCache merged into a stateful Distance class原獨立的Distance函數(shù)、DistanceInput、DistanceOutput、SimplexCache被合并進一個有狀態(tài)的 Distance 模塊。當前 Distance.ts 中DistanceInput、DistanceOutput、SimplexCache仍作為獨立類存在分別見 Distance.ts、Distance.ts、Distance.ts但Distance本體變成了可復用的函數(shù)式接口配合模塊級復用對象simplex、output、cache等減少 GC 壓力內(nèi)部統(tǒng)計stats.gjkCalls、stats.gjkIters也可用于基準測試Distance.ts。Shape.computeDistanceProxy is added形狀基類Shape新增抽象方法computeDistanceProxysrc/collision/Shape.ts各形狀CircleShape、EdgeShape、PolygonShape、ChainShape分別實現(xiàn)為 GJK 距離算法提供支持點查詢代理。Distance內(nèi)部通過shape.computeDistanceProxy(this, index)裝載代理Distance.ts。接觸與碰撞架構(gòu)合并Contact and Collide classes merged, Contact registration/creation is changedContactSolver/VelocityConstraint/PositionConstraint merged with ContactContactManager/ContactListener merged into World (and Contact)這三條變更合起來看原先分散的碰撞、求解、管理職責被壓縮。當前 src/dynamics/Contact.ts 一個文件內(nèi)同時包含VelocityConstraintPoint、速度約束求解initVelocityConstraint、solveVelocityConstraint與位置約束求解solvePositionConstraint、solvePositionConstraintTOI即舊版ContactSolver/VelocityConstraint/PositionConstraint的邏輯已被合并進 Contact 類。而ContactManager/ContactListener的職責則并入 src/dynamics/World.ts 與 Contact。Manifold files is added, WorldManifold.Initialize moved to Manifold.getWorldManifold新增獨立的 src/collision/Manifold.ts原WorldManifold.Initialize變?yōu)镸anifold.getWorldManifold。該方法接收世界變換與形狀半徑將局部流形換算為世界坐標下的法線、接觸點與分離距離見 Manifold.ts并處理e_circles、e_faceA、e_faceB三種流形類型。Manifold.ts 還靜態(tài)導出clipSegmentToLine、ClipVertex、getPointStates、PointStateManifold.ts。ContactFilter.ShouldCollide moved to Fixture?碰撞過濾判定下沉到 Fixture 層與 Fixture 的過濾數(shù)據(jù)group、categoryBits、maskBits耦合更緊密。碰撞配對階段仍由 BroadPhase 的updatePairs驅(qū)動src/collision/BroadPhase.ts測試見 src/test/Collision.test.ts。求解流程重組Island/World.Solve/SolveTOI moved to new SolverPosition/Velocity correction objects assigned to owner bodies孤島Island管理與世界級求解含 TOI 連續(xù)碰撞求解被移入新的 src/dynamics/Solver.ts其中定義TimeStep、ContactImpulse等求解輸入輸出類型位置/速度矯正對象則歸屬到各自的 Body 上消除了大量臨時對象傳遞。二進制標志位 → 布爾字段binary flags changes to boolean fields (awakeFlag, autoSleepFlag, bulletFlag, fixedRotationFlag, activeFlag, enabledFlag, islandFlag, touchingFlag, filterFlag, bulletHitFlag, toiFlag, clearForces, newFixture, locked)這是最影響內(nèi)部實現(xiàn)的一處改動原本用單個整數(shù)按位存儲的十幾個狀態(tài)標志全部改為獨立的布爾字段。好處是代碼可讀性與調(diào)試友好度大幅提升代價是需要逐一核對語義遷移。以 src/dynamics/Body.ts 為例當前可見m_bulletFlag、m_autoSleepFlag、m_awakeFlag、m_activeFlag、m_fixedRotationFlag等字段并通過isBullet/setBulletBody.ts、isSleepingAllowed/setSleepingAllowedBody.ts、isAwake/setAwakeBody.ts、isActive/setActiveBody.ts、isFixedRotation/setFixedRotationBody.ts成對暴露。字符串類型系統(tǒng)Body.Is[Type]/Set[Type] addedShape, Body and Joint string types (circle, dynamic, mouse-joint, etc.)引擎從數(shù)值枚舉走向字符串類型標識這是一次面向開發(fā)者的重大 API 變更形狀類型ShapeType circle | edge | polygon | chainsrc/collision/Shape.tsgetType()返回對應字符串剛體類型BodyType static | kinematic | dynamicsrc/dynamics/Body.ts并同時保留Body.STATIC/KINEMATIC/DYNAMIC靜態(tài)常量與setStatic/setDynamic/setKinematic/setType/getType系列方法Body.ts關節(jié)類型DistanceJoint、FrictionJoint、GearJoint、MotorJoint、MouseJoint、PrismaticJoint、PulleyJoint、RevoluteJoint、RopeJoint、WeldJoint、WheelJoint各自定義static TYPE如distance-jointDistanceJoint.ts、mouse-jointMouseJoint.ts、wheel-jointWheelJoint.ts等Joint.getType()返回該字符串Joint.ts。字符串類型的價值在于序列化、調(diào)試輸出、以及testbed的 UI 展示關節(jié)樣式匹配、形狀渲染分支都可以直接以可讀字符串為鍵無需維護枚舉 ? 字符串的映射表。測試中可直接斷言b1.getFixtureList().getType() circlesrc/test/Basic.test.ts。世界監(jiān)聽器 → 事件系統(tǒng)World listeners changed to events: PostSolve, PreSolve, EndContact, BeginContact, SayGoodby to post-solve, pre-solve, end-contact, begin-contact, remove-body, remove-joint, remove-fixture這是 0.1 中最具代表性的公開 API 變更從接口式監(jiān)聽器轉(zhuǎn)向事件發(fā)布/訂閱。當前World以on(name, listener)/off(name, listener)/publish(name, ...)三件套實現(xiàn)事件機制src/dynamics/World.ts支持的事件包括事件名回調(diào)參數(shù)觸發(fā)時機begin-contact(contact)兩個 fixture 開始接觸World.tsend-contact(contact)兩個 fixture 停止接觸World.tspre-solve(contact, oldManifold)接觸更新后、進入求解器前可修改流形或禁用接觸World.tspost-solve(contact, impulse)求解完成后用于讀取沖量World.tsremove-body/remove-joint/remove-fixture(body)/(joint)/(fixture)對應實體被顯式或隱式移除時World.ts此外還擴展了add-body、add-joint、add-fixture三個新增事件World.ts。事件發(fā)布點在 Contact 與 World 內(nèi)部如beginContact/endContact/preSolve/postSolve均通過this.publish(...)觸發(fā)World.ts。官方文檔注明這些回調(diào)中不能創(chuàng)建/銷毀世界實體World.ts且同一時間步內(nèi)同一接觸可能收到多次回調(diào)?;卣{(diào)類 → 函數(shù)Callbacks classes changed to functions: DynamicTree.query DynamicTree.rayCast BroadPhase.updatePairs BroadPhase.rayCast BroadPhase.query World.queryAAB World.rayCastBox2D 中以回調(diào)對象 虛方法實現(xiàn)查詢的方式被替換為純函數(shù)回調(diào)DynamicTree.query(aabb, callback)與DynamicTree.rayCast(input, callback)src/collision/DynamicTree.tsBroadPhase.query、BroadPhase.rayCast、BroadPhase.updatePairs(addPairCallback)src/collision/BroadPhase.tsWorld.queryAABB(aabb, callback)src/dynamics/World.ts與World.rayCast(point1, point2, callback)World.ts回調(diào)返回false可提前終止 AABB 查詢rayCast 回調(diào)返回數(shù)值可控制射線maxFraction的收縮。0.2API 命名規(guī)范化與 TypeScript 定義向量組合運算重命名wSet/wAdd/wSub(a, v, b, w) replaced with combine/setCombine/addCombine/subCombine(a, v, b, w)wSet/wAdd/wSub(a, v) replaced with mul/setMul/addMul/subMul(a, v)Vec2的加權(quán)賦值方法從帶w前綴的模糊命名改為語義明確的組合運算命名。舊方法在 Vec2.ts 中仍保留但標記deprecated并內(nèi)部委托給新方法wSet(a, v, b, w)→setCombine(a, v, b, w)語義為this a*v b*wwSet(a, v)→setMul(a, v)語義為this a*vVec2.tswAdd→addCombine/addMul語義為this a*v ( b*w)Vec2.tswSub→subCombine/subMul語義為this - a*v ( b*w)Vec2.ts。注意setCombine的注釋特別說明this可能即是w// this may be w因此實現(xiàn)先計算局部變量再賦值避免別名沖突——這是向量庫常見的坑。此外Vec2.combine(a, v, b, w)靜態(tài)方法也基于setCombine實現(xiàn)Vec2.ts。關節(jié)構(gòu)造器清理Joints constructors cleanupTypeScript definitions added各關節(jié)構(gòu)造器從需要顯式傳入大量參數(shù)改為統(tǒng)一的definition 對象 可選 bodyA/bodyB風格例如 Joint.ts 支持兩種構(gòu)造形式new Joint(def)或new Joint(def, bodyA, bodyB)其中bodyA可從def.bodyA解出。這一約定配合0.2引入的 TypeScript 定義文件讓關節(jié)創(chuàng)建更類型安全、更易讀。1.0.0全量 TypeScript 遷移與性能優(yōu)化Typescript migrationPerformance improvements1.0.0 將引擎主體含測試從 JavaScript 全面遷移到 TypeScript。當前倉庫結(jié)構(gòu)可見完整證據(jù)源碼全部為.ts文件src 下的*.ts、測試使用 Vitest*.test.ts位于 src/test與 src/serializer/test、類型測試使用tsdtest-d/planck.test-d.ts。性能優(yōu)化方面從代碼結(jié)構(gòu)可以推斷幾個方向?qū)ο髲陀?池化模塊級復用DistanceOutput、SimplexCache、Simplex等對象[Distance.ts](https://link.gitcode.com/i/397dcbd86cb532fc38a5bf147b3c63f4#L740Vec2、Mat22等臨時對象通過內(nèi)部matrix.*工具復用src/util/Pool.ts 提供對象池構(gòu)建期常量折疊ASSERT、_ASSERT、CONSTRUCTOR_FACTORY在構(gòu)建時通過 Vitedefine替換為false/truevite.config.mts運行時斷言在生產(chǎn)構(gòu)建中被移除統(tǒng)計埋點stats.gjkCalls、stats.gjkIters等計數(shù)器Distance.ts服務于 benchmark 基準測試npm run benchmark會結(jié)合 Git 提交信息對比性能見 package.json。1.1.0Vite 構(gòu)建遷移Vite build migration構(gòu)建工具鏈統(tǒng)一遷移到 Vite由 vite.config.mts 完成以下工作雙產(chǎn)物構(gòu)建核心引擎planck入口 src/main.ts與可視化測試臺planck-with-testbed入口 testbed/main.ts分別打包vite.config.mts同時輸出 ES.mjs與 UMD.js兩種格式vite.config.mts類型聲明打包通過vite-plugin-dts-bundle-generator生成planck.d.tsvite.config.mts供package.json的exports字段分發(fā)package.jsonLicense 注入rollup-plugin-license在每個構(gòu)建產(chǎn)物頭部注入 MIT License 橫幅vite.config.mts壓縮產(chǎn)物npm run build額外用 terser 生成planck.min.js與planck-with-testbed.min.jspackage.json分別提供給 jsDelivr/unpkg CDN 使用package.json。從 1.1.0 起npm run dev/npm run testbed啟動 Vite 開發(fā)服務器并加載 testbed 交互式測試臺npm run test運行 Vitest 測試npm run docs:dev基于 Vitepress 預覽 docs 文檔站package.json。從 0.x 遷移到當前版本的快速對照綜合 0.1 與 0.2 的破壞性變更整理出面向升級者的核心對照表舊寫法0.x新寫法當前依據(jù)Vec2.wSet(a, v, b, w)vec.setCombine(a, v, b, w)Vec2.tsVec2.wAdd(a, v)vec.addMul(a, v)Vec2.tsVec2.wSub(a, v, b, w)vec.subCombine(a, v, b, w)Vec2.tsVec2.Min/MaxVec2.Upper/LowerCHANGES.md 0.1 條目數(shù)值類型枚舉字符串類型circle、dynamic、mouse-joint等Shape.ts、Body.ts、MouseJoint.tsWorldManifold.Initialize(...)manifold.getWorldManifold(wm, xfA, radiusA, xfB, radiusB)Manifold.ts二進制標志位布爾字段 isXxx/setXxxBody.ts監(jiān)聽器接口BeginContact、SayGoodbye等事件world.on(begin-contact, ...)、world.on(remove-body, ...)World.ts回調(diào)對象函數(shù)回調(diào)world.queryAABB(aabb, cb)、world.rayCast(p1, p2, cb)World.ts、World.ts關節(jié)多參數(shù)構(gòu)造定義對象構(gòu)造new RevoluteJoint({...}, bodyA, bodyB)Joint.ts延伸閱讀CHANGELOG.md更細粒度的逐版本變更說明docs/core-concepts.md 與 docs/world/simulation.md理解 World 事件與求解流程的使用語境src/dynamics/World.ts 與 src/common/Vec2.ts事件系統(tǒng)與向量 API 的第一手實現(xiàn)example 目錄下的 60 個示例如Breakable.ts、Pinball.ts、RayCast.ts新 API 的實際調(diào)用范式vite.config.mts 與 package.json構(gòu)建與發(fā)布產(chǎn)物全貌。贊分享游戲開發(fā)【免費下載鏈接】planck.js2D JavaScript Physics Engine項目地址https://gitcode.com/gh_mirrors/pl/planck.js點擊查看免費下載相關推薦Qlib 版本演進全解析從 0.1.0 到 0.8.0 的架構(gòu)變遷與技術脈絡Qlib 版本演進全解析從 0.1.0 到 0.8.0 的架構(gòu)變遷與技術脈絡 Qlib 是一款面向 AI 量化研究的開源平臺其核心代碼自 0.1.0 起步金融科技人工智能機器學習數(shù)據(jù)分析強化學習VCMI 引擎版本演進全解析從 1.8.0 開發(fā)版到 0.x 時代的完整技術變更脈絡VCMI 引擎版本演進全解析從 1.8.0 開發(fā)版到 0.x 時代的完整技術變更脈絡 本文以倉庫根目錄的 ChangeLog.md https://link.游戲開發(fā)flow-for-vscode 版本演進全景解析從 LSP 遷移、安全加固到 TypeScript 重寫的完整技術脈絡flow for vscode 版本演進全景解析從 LSP 遷移、安全加固到 TypeScript 重寫的完整技術脈絡 Flow 是 JavaScript 的開發(fā)工具靜態(tài)分析代碼質(zhì)量上一篇手機號找回QQ號碼Python工具如何幫你3分鐘搞定賬號關聯(lián)驗證下一篇超越傳統(tǒng)OCRPaddleOCR-VL-1.6-4bit如何處理傾斜文檔、表格和多語言內(nèi)容創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考