打飛機小游戲(29)-模擬器調(diào)試與性能優(yōu)化)
基于鴻蒙OS開發(fā)打飛機小游戲29-模擬器調(diào)試與性能優(yōu)化第一章ArkTS嚴格模式的全景解析[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rJM1zIId-1785678973533)(https://i.ibb.co/Kj2JTz3Z/02-debug-panel.jpg)]1.1 ArkTS與TypeScript的關(guān)系A(chǔ)rkTS是HarmonyOS基于TypeScript擴展的聲明式開發(fā)語言。它在TypeScript的基礎(chǔ)上引入了更嚴格的類型約束和性能優(yōu)化規(guī)則以適應(yīng)HarmonyOS的運行時環(huán)境。理解ArkTS與TypeScript的關(guān)系是理解其嚴格模式的前提維度TypeScriptArkTS嚴格模式類型系統(tǒng)結(jié)構(gòu)化類型Structural更傾向名義類型Nominalany類型允許需顯式啟用noImplicitAny完全禁止unknown類型允許完全禁止類型斷言(as)允許完全禁止解構(gòu)賦值允許完全禁止動態(tài)屬性訪問允許(obj[key])完全禁止對象字面量類型允許({x: number})需要類型上下文裝飾器實驗性支持核心特性(Component, State等)模塊系統(tǒng)ES ModulesES Modules kit擴展1.2 no-any約束arkts-no-any規(guī)則禁止在代碼中使用any類型。這意味著禁止的寫法let data: any getData() function process(input: any): any { ... }必須的替代let data: GameData getData() function process(input: PlayerState): GameResult { ... }在游戲開發(fā)中no-any約束的影響尤為深遠。游戲代碼通常涉及大量的動態(tài)數(shù)據(jù)結(jié)構(gòu)——敵人屬性、技能參數(shù)、碰撞結(jié)果等。在沒有any的情況下開發(fā)者必須為每一種數(shù)據(jù)結(jié)構(gòu)定義明確的類型。EmojiShooter的類型設(shè)計示例游戲概念無any的解決方案any時的常見做法敵人屬性class Enemy { hp: number; size: number; ... }{ hp: number, size: number }[string]: any技能參數(shù)class SkillConfig { interval: number; damage: number; ... }Recordstring, any碰撞結(jié)果class CollisionResult { hit: boolean; damage: number; ... }anyBoss定義class BossDefinition { name: string; hp: number; parts: Part[]; ... }{ [key: string]: any }no-any約束迫使開發(fā)者采用先設(shè)計類型后實現(xiàn)邏輯的開發(fā)流程——這是一種更工程化的方法雖然在初期需要更多設(shè)計時間但在后期維護和重構(gòu)時顯著降低了bug率。1.3 no-unknown約束arkts-no-unknown規(guī)則禁止使用unknown類型。unknown是TypeScript中的類型安全版的any——它可以賦任何值但在使用前必須進行類型檢查。ArkTS禁止unknown的原因可能是運行時安全unknown的類型檢查在編譯時完成但ArkTS的運行時可能不支持完整的類型反射性能考量unknown的類型檢查需要額外的運行時開銷代碼清晰性unknown的安全但模糊與ArkTS追求的精確且明確的設(shè)計理念沖突在游戲開發(fā)中unknown的常見場景是JSON解析和網(wǎng)絡(luò)響應(yīng)。在ArkTS中這些場景需要使用具體的類型定義和類型守衛(wèi)// 禁止 let response: unknown JSON.parse(data) // 允許 interface ApiResponse { status: number; data: GameData } let response: ApiResponse JSON.parse(data) as ApiResponse // 注意as也被禁止 // 實際需要使用類型轉(zhuǎn)換函數(shù)或類構(gòu)造器 let response parseApiResponse(data) // 返回ApiResponse類型的函數(shù)1.4 no-as約束禁止類型斷言arkts-no-as規(guī)則禁止使用as關(guān)鍵字進行類型斷言。這是ArkTS中最具爭議的約束之一因為類型斷言在TypeScript開發(fā)中極為常見。禁止的寫法let boss enemy as Boss let num value as number替代方案類型守衛(wèi)使用instanceof檢查后TypeScript/ArkTS會自動收窄類型if (enemy instanceof Boss) { enemy.bossSpecificMethod() // 類型自動收窄為Boss }工廠函數(shù)使用返回特定類型的構(gòu)造函數(shù)function createBoss(definition: BossDefinition): Boss { let boss new Boss() boss.hp definition.hp // ... return boss }泛型函數(shù)使用泛型參數(shù)傳遞類型信息function convertT, U(input: T, converter: (t: T) U): U { return converter(input) }在EmojiShooter中no-as約束意味著所有的類型轉(zhuǎn)換都必須通過顯式的構(gòu)造函數(shù)或工廠方法實現(xiàn)。例如從BOSS_DEFINITIONS創(chuàng)建Boss實例時不能簡單地將定義對象斷言為Boss類型而必須通過構(gòu)造函數(shù)逐步構(gòu)建function createBossFromDefinition(def: BossDefinition): Boss { let boss new Boss() boss.name def.name boss.hp def.hp boss.maxHp def.hp boss.size def.size boss.emoji def.emoji boss.shootInterval def.shootInterval // ... 所有屬性逐一賦值 return boss }這種方式雖然冗長但確保了類型安全——編譯器可以驗證每個賦值的類型正確性而不是依賴開發(fā)者的斷言。1.5 no-destructuring約束arkts-no-destructuring規(guī)則禁止使用解構(gòu)賦值。這包括對象解構(gòu)和數(shù)組解構(gòu)禁止的寫法let { hp, size, emoji } enemy let [x, y] position function draw({ x, y, size }: Entity) { ... }必須的替代let hp enemy.hp let size enemy.size let emoji enemy.emoji let x position[0] let y position[1] function draw(entity: Entity) { let x entity.x let y entity.y let size entity.size }解構(gòu)賦值的禁止對代碼風(fēng)格有顯著影響代碼冗長原本一行的解構(gòu)需要多行逐一賦值函數(shù)簽名簡化函數(shù)參數(shù)不能使用解構(gòu)必須接受對象參數(shù)可讀性爭議解構(gòu)賦值提高了緊湊性但降低了顯式性——ArkTS選擇了后者在游戲開發(fā)中解構(gòu)禁止的影響體現(xiàn)在頻繁的向量操作上。2D游戲需要大量的x/y坐標操作解構(gòu)賦值的缺失意味著每次向量操作都需要顯式的屬性訪問// 如果允許解構(gòu) let [dx, dy] [target.x - source.x, target.y - source.y] // ArkTS中 let dx target.x - source.x let dy target.y - source.y1.6 no-dynamic-property-access約束arkts-no-dynamic-property-access規(guī)則禁止使用動態(tài)屬性訪問即obj[key]語法。這意味著所有屬性訪問必須使用點號表示法禁止的寫法let value enemy[hp] let key shootInterval let interval boss[key]必須的替代let value enemy.hp let interval boss.shootInterval這一約束對游戲數(shù)據(jù)驅(qū)動設(shè)計的影響尤為顯著。在傳統(tǒng)游戲開發(fā)中數(shù)據(jù)驅(qū)動模式通常使用字符串鍵訪問配置數(shù)據(jù)// 傳統(tǒng)數(shù)據(jù)驅(qū)動 let bossConfig { dragon: { hp: 200, shootInterval: 90 }, wizard: { hp: 150, shootInterval: 60 } } let config bossConfig[bossType] // 動態(tài)屬性訪問在ArkTS中這種模式需要替換為類型安全的替代方案// ArkTS數(shù)據(jù)驅(qū)動 class BossConfig { hp: number 0 shootInterval: number 0 } let configs: BossConfig[] [dragonConfig, wizardConfig] let config configs[bossInd