perf: 删除不必要的文件
This commit is contained in:
496
ARCHITECTURE.md
496
ARCHITECTURE.md
@@ -1,496 +0,0 @@
|
|||||||
# Architecture Overview
|
|
||||||
|
|
||||||
## System Architecture Diagram
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ COCOS CREATOR GAME │
|
|
||||||
│ WeChat Mini-Game Version 3.8.8 │
|
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ PRESENTATION LAYER (UI) │
|
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ PageLoading.ts ──────┐ │
|
|
||||||
│ (Loading Screen) │ │
|
|
||||||
│ │ │
|
|
||||||
│ ┌──────────┐ │ ┌──────────┐ ┌──────────┐ │
|
|
||||||
│ │PageHome │─────────┴──────│PageLevel │──────│PassModal │ │
|
|
||||||
│ │(Menu) │ │ (Play) │ │(Victory) │ │
|
|
||||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
|
||||||
│ ▲ ▲ │ │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ └────────────────┬───────────┘ │ │
|
|
||||||
│ │ (Back button) │ │
|
|
||||||
│ └─────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ Toast.ts ────────────────────────────────────────────────────────────│
|
|
||||||
│ (Notifications) │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ CORE LOGIC LAYER │
|
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
|
||||||
│ │ PageLevel.ts │ │ PassModal.ts │ │
|
|
||||||
│ ├──────────────────────┤ ├──────────────────────┤ │
|
|
||||||
│ │ • Answer validation │ │ • Next level │ │
|
|
||||||
│ │ • Hint unlock (-life)│ │ • Share button │ │
|
|
||||||
│ │ • Countdown (60s) │ │ • Callbacks │ │
|
|
||||||
│ │ • Sound/Vibration │ │ │ │
|
|
||||||
│ │ • Life display │ │ │ │
|
|
||||||
│ └──────────────────────┘ └──────────────────────┘ │
|
|
||||||
│ ▲ ▲ │
|
|
||||||
│ │ │ │
|
|
||||||
│ └────────────────┬───────────────┘ │
|
|
||||||
│ │ │
|
|
||||||
│ ┌──────────────────────────┴──────────────────────────────────┐ │
|
|
||||||
│ │ ViewManager.ts (View Navigation) │ │
|
|
||||||
│ ├──────────────────────────────────────────────────────────────┤ │
|
|
||||||
│ │ • Page registration & caching │ │
|
|
||||||
│ │ • Page stack management (push/pop/replace) │ │
|
|
||||||
│ │ • Lifecycle: onViewLoad → onViewShow → onViewHide → destroy │ │
|
|
||||||
│ │ • Parameter passing between pages │ │
|
|
||||||
│ └──────────────────────────────────────────────────────────────┘ │
|
|
||||||
│ ▲ │
|
|
||||||
│ │ │
|
|
||||||
│ BaseView.ts (Abstract base class for all pages) │
|
|
||||||
│ • Lifecycle hooks │
|
|
||||||
│ • Page state management │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ DATA & STATE MANAGEMENT LAYER │
|
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ StorageManager.ts (Single Source of Truth) │ │
|
|
||||||
│ ├──────────────────────────────────────────────────────────────┤ │
|
|
||||||
│ │ Lives Management: │ │
|
|
||||||
│ │ • getLives() / setLives() / consumeLife() / addLife() │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ Progress Management: │ │
|
|
||||||
│ │ • getCurrentLevelIndex() / getMaxUnlockedLevelIndex() │ │
|
|
||||||
│ │ • onLevelCompleted(levelIndex) │ │
|
|
||||||
│ │ • isLevelUnlocked(levelIndex) │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ Storage Backend: sys.localStorage │ │
|
|
||||||
│ │ └─ game_lives: string number (default: "10") │ │
|
|
||||||
│ │ └─ game_progress: JSON with currentIndex & maxUnlockedIdx │ │
|
|
||||||
│ └──────────────────────────────────────────────────────────────┘ │
|
|
||||||
│ ▲ │
|
|
||||||
│ │ │
|
|
||||||
│ ┌──────────────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ LevelDataManager.ts (Level Data & Assets) │ │
|
|
||||||
│ ├──────────────────────────────────────────────────────────────┤ │
|
|
||||||
│ │ • initialize(onProgress) - Fetch API & load first level │ │
|
|
||||||
│ │ • getLevelConfig(index) - Get level data + image │ │
|
|
||||||
│ │ • ensureLevelReady(index) - On-demand level loading │ │
|
|
||||||
│ │ • preloadNextLevel(currentIndex) - Async preload │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ Memory Caches: │ │
|
|
||||||
│ │ • _apiData: All levels from server │ │
|
|
||||||
│ │ • _levelConfigs: Map of loaded level configs │ │
|
|
||||||
│ │ • _imageCache: Map of loaded images (SpriteFrames) │ │
|
|
||||||
│ │ • _loadingLevels: Set of levels being loaded │ │
|
|
||||||
│ └──────────────────────────────────────────────────────────────┘ │
|
|
||||||
│ ▲ │
|
|
||||||
│ │ │
|
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ UTILITY & SDK LAYER │
|
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ ┌────────────────────┐ ┌────────────────────┐ ┌──────────────────┐ │
|
|
||||||
│ │ HttpUtil.ts │ │ WxSDK.ts │ │ToastManager.ts │ │
|
|
||||||
│ ├────────────────────┤ ├────────────────────┤ ├──────────────────┤ │
|
|
||||||
│ │ • get<T>() │ │ • isWechat() │ │ • init() │ │
|
|
||||||
│ │ • post<T>() │ │ • initShare() │ │ • show() │ │
|
|
||||||
│ │ │ │ • shareAppMessage()│ │ │ │
|
|
||||||
│ │ Timeout: 10s │ │ • onShareAppMsg() │ │ Display duration │ │
|
|
||||||
│ │ Error handling │ │ • vibrateShort() │ │ Fade out anim │ │
|
|
||||||
│ │ │ │ • vibrateLong() │ │ │ │
|
|
||||||
│ └────────────────────┘ └────────────────────┘ └──────────────────┘ │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ EXTERNAL SYSTEMS │
|
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ ┌──────────────────────────────────────┐ │
|
|
||||||
│ │ WeChat Mini-Game SDK (wx global) │ │
|
|
||||||
│ ├──────────────────────────────────────┤ │
|
|
||||||
│ │ • wx.shareAppMessage() │ │
|
|
||||||
│ │ • wx.onShareAppMessage() │ │
|
|
||||||
│ │ • wx.showShareMenu() │ │
|
|
||||||
│ │ • wx.vibrateShort() │ │
|
|
||||||
│ │ • wx.vibrateLong() │ │
|
|
||||||
│ └──────────────────────────────────────┘ │
|
|
||||||
│ ▲ │
|
|
||||||
│ │ │
|
|
||||||
│ │ │
|
|
||||||
│ ┌──────────────────────────────────────┐ │
|
|
||||||
│ │ Backend API Server │ │
|
|
||||||
│ │ https://ilookai.cn │ │
|
|
||||||
│ ├──────────────────────────────────────┤ │
|
|
||||||
│ │ GET /api/v1/wechat-game/levels │ │
|
|
||||||
│ │ • Returns: {success, data, message} │ │
|
|
||||||
│ │ • Retry: 2x with 1s delay │ │
|
|
||||||
│ │ • Timeout: 8s │ │
|
|
||||||
│ └──────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Data Flow Diagram: Complete User Session
|
|
||||||
|
|
||||||
```
|
|
||||||
START
|
|
||||||
│
|
|
||||||
├─ [main.ts] onLoad()
|
|
||||||
│ └─ ViewManager.init(canvas)
|
|
||||||
│ └─ ToastManager.init(toastPrefab)
|
|
||||||
│ └─ Register PageHome & PageLevel
|
|
||||||
│
|
|
||||||
├─ [PageLoading.ts] start()
|
|
||||||
│ ├─ LevelDataManager.initialize()
|
|
||||||
│ │ ├─ HttpUtil.get() → API call
|
|
||||||
│ │ │ └─ https://ilookai.cn/api/v1/wechat-game/levels
|
|
||||||
│ │ ├─ Cache response → _apiData
|
|
||||||
│ │ ├─ Load first level image
|
|
||||||
│ │ │ └─ assetManager.loadRemote() → SpriteFrame
|
|
||||||
│ │ │ └─ Cache in _imageCache
|
|
||||||
│ │ └─ Return success
|
|
||||||
│ │
|
|
||||||
│ └─ ViewManager.preload('PageHome')
|
|
||||||
│ └─ ViewManager.open('PageHome')
|
|
||||||
│ └─ PageHome.onViewLoad()
|
|
||||||
│ └─ WxSDK.initShare()
|
|
||||||
│
|
|
||||||
├─ [USER CLICKS "START GAME"]
|
|
||||||
│
|
|
||||||
├─ ViewManager.open('PageLevel', {params: {levelIndex: 0}})
|
|
||||||
│ └─ PageLevel.onViewLoad()
|
|
||||||
│ ├─ StorageManager.getCurrentLevelIndex()
|
|
||||||
│ ├─ PageLevel.initLevel()
|
|
||||||
│ │ ├─ LevelDataManager.ensureLevelReady(levelIndex)
|
|
||||||
│ │ │ ├─ Check cache (_levelConfigs)
|
|
||||||
│ │ │ ├─ If not cached: load image + create config
|
|
||||||
│ │ │ └─ Store in cache
|
|
||||||
│ │ │
|
|
||||||
│ │ └─ PageLevel._applyLevelConfig()
|
|
||||||
│ │ ├─ Display main image (sprite)
|
|
||||||
│ │ ├─ Show Hint 1 (free)
|
|
||||||
│ │ ├─ Hide Hints 2, 3 (show unlock buttons)
|
|
||||||
│ │ ├─ Create input field based on answer.length
|
|
||||||
│ │ ├─ Display lives: StorageManager.getLives()
|
|
||||||
│ │ ├─ Start countdown (60s)
|
|
||||||
│ │ └─ LevelDataManager.preloadNextLevel() [async]
|
|
||||||
│
|
|
||||||
├─ [USER INTERACTS]
|
|
||||||
│
|
|
||||||
├─ Option A: UNLOCK HINT
|
|
||||||
│ ├─ PageLevel.onUnlockClue(2 or 3)
|
|
||||||
│ ├─ Check: StorageManager.hasLives()?
|
|
||||||
│ ├─ Yes → StorageManager.consumeLife() → display hint
|
|
||||||
│ └─ No → Show "生命值不足" message
|
|
||||||
│
|
|
||||||
├─ Option B: SUBMIT ANSWER
|
|
||||||
│ ├─ PageLevel.onSubmitAnswer()
|
|
||||||
│ ├─ Validate: userAnswer === correctAnswer?
|
|
||||||
│ │
|
|
||||||
│ ├─ YES (Correct)
|
|
||||||
│ │ ├─ PageLevel.showSuccess()
|
|
||||||
│ │ ├─ Stop countdown
|
|
||||||
│ │ ├─ Play successAudio
|
|
||||||
│ │ ├─ StorageManager.addLife() [+1]
|
|
||||||
│ │ ├─ PageLevel._showPassModal()
|
|
||||||
│ │ │ ├─ Instantiate PassModal prefab
|
|
||||||
│ │ │ ├─ PassModal.onViewLoad()
|
|
||||||
│ │ │ ├─ PassModal.onViewShow()
|
|
||||||
│ │ │ │ └─ Play success sound
|
|
||||||
│ │ │ │ └─ Adjust widget to full screen
|
|
||||||
│ │ │ │
|
|
||||||
│ │ │ └─ User clicks button:
|
|
||||||
│ │ │ ├─ "Next Level" → PageLevel.nextLevel()
|
|
||||||
│ │ │ │ ├─ StorageManager.onLevelCompleted(currentIndex)
|
|
||||||
│ │ │ │ │ ├─ currentLevelIndex++
|
|
||||||
│ │ │ │ │ ├─ maxUnlockedLevelIndex = max(prev, current)
|
|
||||||
│ │ │ │ │ └─ Save to localStorage
|
|
||||||
│ │ │ │ ├─ Reload PageLevel with new index
|
|
||||||
│ │ │ │ │ └─ Repeat from Level Setup
|
|
||||||
│ │ │ │ │
|
|
||||||
│ │ │ │ └─ If last level:
|
|
||||||
│ │ │ │ └─ ViewManager.back() → return to PageHome
|
|
||||||
│ │ │ │
|
|
||||||
│ │ │ └─ "Share" → WxSDK.shareAppMessage()
|
|
||||||
│ │ │ └─ query: `level=${currentIndex+1}`
|
|
||||||
│ │
|
|
||||||
│ ├─ NO (Wrong)
|
|
||||||
│ │ ├─ PageLevel.showError()
|
|
||||||
│ │ ├─ Play failAudio
|
|
||||||
│ │ ├─ WxSDK.vibrateLong() [device vibration]
|
|
||||||
│ │ ├─ ToastManager.show("答案错误,再试试吧!")
|
|
||||||
│ │ │ ├─ Create Toast node
|
|
||||||
│ │ │ ├─ Show for 2000ms
|
|
||||||
│ │ │ ├─ Fade out animation (300ms)
|
|
||||||
│ │ │ └─ Destroy node
|
|
||||||
│ │ │
|
|
||||||
│ │ └─ Continue playing (allow retry)
|
|
||||||
│
|
|
||||||
├─ Option C: TIMEOUT
|
|
||||||
│ └─ Countdown reaches 0
|
|
||||||
│ ├─ PageLevel.onTimeUp()
|
|
||||||
│ ├─ Play failAudio
|
|
||||||
│ └─ [Incomplete: can still submit after timeout]
|
|
||||||
│
|
|
||||||
├─ [USER CLICKS BACK BUTTON]
|
|
||||||
│ ├─ ViewManager.back()
|
|
||||||
│ │ ├─ PageLevel._doHide()
|
|
||||||
│ │ └─ PageHome._doShow()
|
|
||||||
│ │
|
|
||||||
│ └─ Return to home (progress saved in localStorage)
|
|
||||||
│
|
|
||||||
└─ END
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## State Management Flow
|
|
||||||
|
|
||||||
```
|
|
||||||
USER PROGRESS STATE
|
|
||||||
│
|
|
||||||
├─ localStorage: game_progress
|
|
||||||
│ └─ {
|
|
||||||
│ "currentLevelIndex": 5,
|
|
||||||
│ "maxUnlockedLevelIndex": 5
|
|
||||||
│ }
|
|
||||||
│
|
|
||||||
├─ Memory Cache (LevelDataManager)
|
|
||||||
│ ├─ _apiData: ApiLevelData[] (all levels)
|
|
||||||
│ ├─ _levelConfigs: Map<levelIndex, RuntimeLevelConfig>
|
|
||||||
│ ├─ _imageCache: Map<url, SpriteFrame>
|
|
||||||
│ └─ _loadingLevels: Set<levelIndex> (currently loading)
|
|
||||||
│
|
|
||||||
└─ Session State (PageLevel component)
|
|
||||||
├─ currentLevelIndex: number
|
|
||||||
├─ _currentConfig: RuntimeLevelConfig
|
|
||||||
├─ _countdown: number (60 → 0)
|
|
||||||
├─ _isTimeUp: boolean
|
|
||||||
├─ _isTransitioning: boolean
|
|
||||||
└─ _passModalNode: Node | null
|
|
||||||
|
|
||||||
|
|
||||||
LIVES STATE
|
|
||||||
│
|
|
||||||
├─ localStorage: game_lives
|
|
||||||
│ └─ "10" (string representation of number)
|
|
||||||
│
|
|
||||||
├─ Cached value (StorageManager._progressCache)
|
|
||||||
│ └─ Read on first access, cached for performance
|
|
||||||
│
|
|
||||||
└─ Operations (immediate storage update)
|
|
||||||
├─ getLives() → read from storage
|
|
||||||
├─ setLives(n) → validate & write to storage
|
|
||||||
├─ consumeLife() → getLives() - 1, setLives()
|
|
||||||
├─ addLife() → getLives() + 1, setLives()
|
|
||||||
└─ hasLives() → getLives() > 0
|
|
||||||
|
|
||||||
|
|
||||||
API CACHE
|
|
||||||
│
|
|
||||||
├─ First Load (Startup)
|
|
||||||
│ ├─ HttpUtil.get(apiUrl, 8000ms timeout)
|
|
||||||
│ ├─ Retry: 2 times (1s delay between)
|
|
||||||
│ └─ Cache in LevelDataManager._apiData
|
|
||||||
│
|
|
||||||
└─ Per-Level Resources (On-Demand)
|
|
||||||
├─ Check _levelConfigs cache
|
|
||||||
├─ If missing: assetManager.loadRemote(imageUrl)
|
|
||||||
├─ Create SpriteFrame
|
|
||||||
└─ Cache in _imageCache
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## View Stack & Navigation
|
|
||||||
|
|
||||||
```
|
|
||||||
VIEW STACK (LIFO - Last In First Out)
|
|
||||||
│
|
|
||||||
├─ Level 0 (Bottom)
|
|
||||||
│ └─ PageHome
|
|
||||||
│
|
|
||||||
├─ Level 1 (Middle)
|
|
||||||
│ └─ PageLevel
|
|
||||||
│
|
|
||||||
├─ Level 2 (Top - Current)
|
|
||||||
│ └─ PassModal (temporary, on PageLevel)
|
|
||||||
│
|
|
||||||
└─ Operations
|
|
||||||
├─ open(viewId) → push to stack + show
|
|
||||||
├─ back() → pop from stack + hide + show prev
|
|
||||||
├─ replace(viewId) → pop + push new view
|
|
||||||
└─ close() → pop + show previous
|
|
||||||
|
|
||||||
|
|
||||||
CACHING BEHAVIOR
|
|
||||||
│
|
|
||||||
├─ PageHome
|
|
||||||
│ ├─ cache: true
|
|
||||||
│ └─ Cached after first open, reused on back
|
|
||||||
│
|
|
||||||
├─ PageLevel
|
|
||||||
│ ├─ cache: true
|
|
||||||
│ └─ Cached per instance (but reinitializes on each open)
|
|
||||||
│
|
|
||||||
└─ PassModal
|
|
||||||
├─ Dynamically instantiated
|
|
||||||
├─ Not cached
|
|
||||||
└─ Destroyed after close
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Class Hierarchy
|
|
||||||
|
|
||||||
```
|
|
||||||
Component (Cocos)
|
|
||||||
│
|
|
||||||
├─ BaseView (Abstract base)
|
|
||||||
│ ├─ PageHome
|
|
||||||
│ ├─ PageLevel
|
|
||||||
│ └─ PassModal
|
|
||||||
│
|
|
||||||
└─ Toast
|
|
||||||
|
|
||||||
|
|
||||||
Managers (Singleton)
|
|
||||||
│
|
|
||||||
├─ ViewManager
|
|
||||||
│ └─ Manages page lifecycle & navigation
|
|
||||||
│
|
|
||||||
├─ LevelDataManager
|
|
||||||
│ └─ Manages API data & asset loading
|
|
||||||
│
|
|
||||||
├─ StorageManager
|
|
||||||
│ └─ Manages user data persistence
|
|
||||||
│
|
|
||||||
├─ ToastManager
|
|
||||||
│ └─ Manages toast notifications
|
|
||||||
│
|
|
||||||
└─ WxSDK
|
|
||||||
└─ Manages WeChat integration
|
|
||||||
|
|
||||||
|
|
||||||
Utilities
|
|
||||||
│
|
|
||||||
├─ HttpUtil
|
|
||||||
│ └─ Static HTTP methods (GET/POST)
|
|
||||||
│
|
|
||||||
└─ LevelTypes
|
|
||||||
└─ TypeScript interfaces for API data
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Dependency Graph
|
|
||||||
|
|
||||||
```
|
|
||||||
main.ts
|
|
||||||
├─ ViewManager
|
|
||||||
├─ ToastManager
|
|
||||||
└─ [Page Prefabs]
|
|
||||||
├─ PageHome
|
|
||||||
│ └─ WxSDK
|
|
||||||
│
|
|
||||||
├─ PageLevel
|
|
||||||
│ ├─ StorageManager
|
|
||||||
│ ├─ WxSDK
|
|
||||||
│ ├─ LevelDataManager
|
|
||||||
│ ├─ ToastManager
|
|
||||||
│ └─ PassModal
|
|
||||||
│ ├─ WxSDK
|
|
||||||
│ └─ BaseView
|
|
||||||
│
|
|
||||||
└─ PageLoading
|
|
||||||
├─ ViewManager
|
|
||||||
├─ LevelDataManager
|
|
||||||
│ ├─ HttpUtil
|
|
||||||
│ │ └─ XMLHttpRequest
|
|
||||||
│ ├─ LevelTypes
|
|
||||||
│ └─ Cocos assetManager
|
|
||||||
└─ ToastManager
|
|
||||||
|
|
||||||
|
|
||||||
EXTERNAL APIS
|
|
||||||
│
|
|
||||||
├─ https://ilookai.cn/api/v1/wechat-game/levels
|
|
||||||
│ └─ Called by LevelDataManager._fetchApiData()
|
|
||||||
│
|
|
||||||
└─ WeChat SDK (wx global)
|
|
||||||
├─ wx.shareAppMessage()
|
|
||||||
├─ wx.onShareAppMessage()
|
|
||||||
├─ wx.showShareMenu()
|
|
||||||
├─ wx.vibrateShort()
|
|
||||||
└─ wx.vibrateLong()
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Performance Considerations
|
|
||||||
|
|
||||||
### Memory Management
|
|
||||||
- **Image Loading**: Remote images loaded on-demand with local caching
|
|
||||||
- **Level Configs**: Loaded incrementally, current + next level only
|
|
||||||
- **View Caching**: Pages cached after first load, reused on navigation back
|
|
||||||
- **Message Queuing**: No event queue; direct method calls
|
|
||||||
|
|
||||||
### Network
|
|
||||||
- **Single API Call**: Startup only (all levels fetched at once)
|
|
||||||
- **Timeout**: 8 seconds for API requests
|
|
||||||
- **Retry Logic**: 2 attempts with 1-second delay
|
|
||||||
- **Cache Strategy**: In-memory cache, no expiration
|
|
||||||
|
|
||||||
### Storage
|
|
||||||
- **localStorage**: 2 keys (lives + progress)
|
|
||||||
- **No Batching**: Each update writes immediately
|
|
||||||
- **Synchronous**: No async operations needed
|
|
||||||
|
|
||||||
### UI/Graphics
|
|
||||||
- **Single Image**: Main puzzle image per level
|
|
||||||
- **Dynamic Input**: Input field size adjusts based on answer length
|
|
||||||
- **Audio**: One-shot playback, no loops
|
|
||||||
- **Animations**: Toast fade-out only
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security Considerations
|
|
||||||
|
|
||||||
### Current Implementation
|
|
||||||
- ⚠️ All data stored locally (no encryption)
|
|
||||||
- ⚠️ No user authentication
|
|
||||||
- ⚠️ No server-side validation
|
|
||||||
- ⚠️ Progress can be manually edited via localStorage
|
|
||||||
|
|
||||||
### Vulnerabilities
|
|
||||||
1. localStorage can be inspected/modified via browser console
|
|
||||||
2. No server-side checks on progress/lives
|
|
||||||
3. Can modify localStorage to skip levels
|
|
||||||
4. Can modify lives directly
|
|
||||||
|
|
||||||
### Improvements Needed
|
|
||||||
- Server-side progress validation
|
|
||||||
- User authentication
|
|
||||||
- Encrypted storage
|
|
||||||
- Server-side truth for lives/progress
|
|
||||||
|
|
||||||
@@ -1,665 +0,0 @@
|
|||||||
# Architecture & Flow Diagrams
|
|
||||||
|
|
||||||
## System Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────┐
|
|
||||||
│ Cocos Creator Runtime │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ UI Layer (This Analysis) │ │
|
|
||||||
│ ├──────────────────────────────────────────────────────────┤ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ ┌────────────────┐ ┌──────────────┐ │ │
|
|
||||||
│ │ │ main.ts │────────▶│ ViewManager │ │ │
|
|
||||||
│ │ │ (Bootstrap) │ │ (Singleton) │ │ │
|
|
||||||
│ │ └────────────────┘ └──────────────┘ │ │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ │ Pages (All extend BaseView): │ │ │
|
|
||||||
│ │ ┌─────────────────────────────────┼──────────────┐ │ │
|
|
||||||
│ │ │ • PageLoading (init data) │ │ │ │
|
|
||||||
│ │ │ • PageHome (hub) │ │ │ │
|
|
||||||
│ │ │ • PageLevel (game - complex) ◀┘ │ │ │
|
|
||||||
│ │ │ • PagePreviewLevels (list) │ │ │
|
|
||||||
│ │ │ • PassModal (modal) │ │ │
|
|
||||||
│ │ └────────────────────────────────────────────────┘ │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ ┌────────────────┐ ┌──────────────┐ │ │
|
|
||||||
│ │ │ ToastManager │────────▶│ Toast │ │ │
|
|
||||||
│ │ │ (Singleton) │ │ (Component) │ │ │
|
|
||||||
│ │ └────────────────┘ └──────────────┘ │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ └──────────────────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ Data Layer (External - Not Analyzed) │ │
|
|
||||||
│ ├──────────────────────────────────────────────────────────┤ │
|
|
||||||
│ │ • AuthManager • LevelDataManager │ │
|
|
||||||
│ │ • StorageManager • UserAssetsManager │ │
|
|
||||||
│ │ • ShareManager • WxSDK │ │
|
|
||||||
│ └──────────────────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Page State Machine
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────┐
|
|
||||||
│ Application Starts │
|
|
||||||
└──────────────┬──────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌──────────────────────┐
|
|
||||||
│ main.onLoad() │
|
|
||||||
│ Registers all pages │
|
|
||||||
└──────────┬───────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ PageLoading displayed │
|
|
||||||
│ - Load auth + levels │
|
|
||||||
│ - Sync progress │
|
|
||||||
│ - Check share code │
|
|
||||||
└──────────────┬───────────────┘
|
|
||||||
│
|
|
||||||
┌──────────────┴──────────────┐
|
|
||||||
│ Normal Mode │ Share Mode │
|
|
||||||
▼ ▼ │
|
|
||||||
┌──────────────────┐ ┌───────────────┐ │
|
|
||||||
│ PageHome │ │ PageLevel │ │
|
|
||||||
│ [Start] [PK] │ │ (in share) │ │
|
|
||||||
└────┬─────┬───────┘ └───────┬───────┘ │
|
|
||||||
│ │ │ │
|
|
||||||
┌────────▼─┐ └────────────┬──────┴────────┘
|
|
||||||
│ │ │
|
|
||||||
▼ ▼ ▼
|
|
||||||
PageLevel PageWrite (Repeat levels)
|
|
||||||
(game) Levels │
|
|
||||||
│ (create) ▼
|
|
||||||
│ │ PassModal
|
|
||||||
│ ▼ [Share]
|
|
||||||
│ PagePreview │
|
|
||||||
│ Levels ▼
|
|
||||||
│ (verify) Back to Home
|
|
||||||
│ │
|
|
||||||
│ ▼
|
|
||||||
│ PassModal
|
|
||||||
│ [Next/Share]
|
|
||||||
│ │
|
|
||||||
└──────────┼─────────┐
|
|
||||||
│ │
|
|
||||||
┌────▼──┐ ┌───▼────┐
|
|
||||||
│ Next │ │ Share │
|
|
||||||
│ Loop │ │ to WX │
|
|
||||||
└───────┘ └────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Page Stack Visualization
|
|
||||||
|
|
||||||
### Session Trace
|
|
||||||
|
|
||||||
```
|
|
||||||
INITIALIZATION:
|
|
||||||
┌────────────────────────────────────────────┐
|
|
||||||
│ Stack: [] │
|
|
||||||
│ (Nothing loaded yet) │
|
|
||||||
└────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼ main.onLoad()
|
|
||||||
┌────────────────────────────────────────────┐
|
|
||||||
│ Stack: [] │
|
|
||||||
│ ViewManager + pages registered in registry │
|
|
||||||
└────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼ PageLoading.start() → ViewManager.open('PageHome')
|
|
||||||
┌────────────────────────────────────────────┐
|
|
||||||
│ Stack: [PageHome] │
|
|
||||||
│ PageHome._doShow() called │
|
|
||||||
└────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
USER CLICKS "START GAME":
|
|
||||||
▼ PageHome._onStartGameClick() → ViewManager.open('PageLevel')
|
|
||||||
┌────────────────────────────────────────────┐
|
|
||||||
│ Stack: [PageHome, PageLevel] │
|
|
||||||
│ PageHome._doHide() called │
|
|
||||||
│ PageLevel._doShow() called │
|
|
||||||
└────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
COMPLETES LEVEL:
|
|
||||||
▼ PageLevel shows PassModal (not in stack, drawn on top)
|
|
||||||
┌────────────────────────────────────────────┐
|
|
||||||
│ Stack: [PageHome, PageLevel] │
|
|
||||||
│ UI Layer: [PageLevel, PassModal@z999] │
|
|
||||||
│ PassModal shown with instantiate() │
|
|
||||||
└────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
CLICKS "NEXT LEVEL":
|
|
||||||
▼ PassModal closed, PageLevel.nextLevel()
|
|
||||||
┌────────────────────────────────────────────┐
|
|
||||||
│ Stack: [PageHome, PageLevel] │
|
|
||||||
│ PageLevel loads next level config │
|
|
||||||
│ PassModal destroyed │
|
|
||||||
└────────────────────────────────────────────┘
|
|
||||||
|
|
||||||
CLICKS BACK FROM PageLevel:
|
|
||||||
▼ PageLevel.onIconSettingClick() → ViewManager.back()
|
|
||||||
┌────────────────────────────────────────────┐
|
|
||||||
│ Stack: [PageHome] │
|
|
||||||
│ PageLevel._doHide() called │
|
|
||||||
│ PageLevel destroyed (cache=true, not kept) │
|
|
||||||
│ PageHome._doShow() called │
|
|
||||||
└────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Component Communication Diagram
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────┐
|
|
||||||
│ ViewManager │
|
|
||||||
│ (Singleton) │
|
|
||||||
└──────────┬──────────┘
|
|
||||||
│
|
|
||||||
┌──────────────┼──────────────┐
|
|
||||||
│ │ │
|
|
||||||
▼ ▼ ▼
|
|
||||||
open() back() replace()
|
|
||||||
│ │ │
|
|
||||||
│ │ │
|
|
||||||
┌───────────┴────┐ ┌───┴────┐ ┌──┴───────┐
|
|
||||||
│ │ │ │ │ │
|
|
||||||
▼ ▼ ▼ ▼ ▼ ▼
|
|
||||||
PageHome PageLevel PassModal (back) (new page)
|
|
||||||
│ │ │
|
|
||||||
│ ├─ Timer ────┐
|
|
||||||
│ │ │
|
|
||||||
│ ├─ Points │
|
|
||||||
│ │ ↑ │
|
|
||||||
│ │ │ │
|
|
||||||
▼ ▼ │ ▼
|
|
||||||
ToastMgr Hints │ PassModal
|
|
||||||
│ │ │
|
|
||||||
├──────┤ └──▶ Share to WX
|
|
||||||
│ │
|
|
||||||
Unlock Earn Points
|
|
||||||
Consume (UserAssets)
|
|
||||||
(check hasPoints)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Data Flow: Level Completion
|
|
||||||
|
|
||||||
```
|
|
||||||
USER ENTERS ANSWER:
|
|
||||||
┌─────────────────────────────────────────────────────────┐
|
|
||||||
│ PageLevel.onSubmitAnswer() │
|
|
||||||
└─────────────────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
├─ getAnswer() ──▶ [Retrieve from EditBox]
|
|
||||||
│
|
|
||||||
├─ Compare with _currentConfig.answer
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌────────────────────────────────────────┐
|
|
||||||
│ CORRECT ANSWER │
|
|
||||||
└────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
├─ _isTransitioning = true [Prevent double-submit]
|
|
||||||
│
|
|
||||||
├─ stopCountdown()
|
|
||||||
│
|
|
||||||
├─ playSuccessSound()
|
|
||||||
│
|
|
||||||
├─ Calculate: timeSpent = 60 - _countdown
|
|
||||||
│
|
|
||||||
├─┐ Normal Mode:
|
|
||||||
│ │
|
|
||||||
│ └─▶ UserAssetsManager.earnPoint(levelId, timeSpent)
|
|
||||||
│ │
|
|
||||||
│ ▼
|
|
||||||
│ └─ UPDATE SERVER + LOCAL
|
|
||||||
│ └─ Get points amount
|
|
||||||
│ └─ PageLevel.updatePointsLabel()
|
|
||||||
│
|
|
||||||
├─┐ Share Mode:
|
|
||||||
│ │
|
|
||||||
│ └─▶ ShareManager.reportLevelProgress(...)
|
|
||||||
│ │
|
|
||||||
│ ▼
|
|
||||||
│ └─ SEND TO SERVER (fire-and-forget)
|
|
||||||
│
|
|
||||||
├─ _showPassModal()
|
|
||||||
│ │
|
|
||||||
│ ├─ instantiate(passModalPrefab)
|
|
||||||
│ │
|
|
||||||
│ ├─ Set z-index = 999 (topmost)
|
|
||||||
│ │
|
|
||||||
│ ├─ Add to Canvas
|
|
||||||
│ │
|
|
||||||
│ └─ Call passModal.onViewLoad() + onViewShow()
|
|
||||||
│
|
|
||||||
└─ WAIT FOR USER:
|
|
||||||
│
|
|
||||||
├─ [Next Level] ──▶ PassModal closed
|
|
||||||
│ │
|
|
||||||
│ ▼
|
|
||||||
│ nextLevel()
|
|
||||||
│ │
|
|
||||||
│ ┌────────┴────────┐
|
|
||||||
│ │ No More Levels │ Next Level
|
|
||||||
│ ▼ ▼
|
|
||||||
│ BACK HOME Load & Display
|
|
||||||
│ Restart Timer
|
|
||||||
│
|
|
||||||
└─ [Share] ──▶ WxSDK.shareAppMessage()
|
|
||||||
│
|
|
||||||
└─ Modal stays open
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Hint Unlocking Flow
|
|
||||||
|
|
||||||
```
|
|
||||||
USER CLICKS UNLOCK BUTTON:
|
|
||||||
┌──────────────────────────────────────────────┐
|
|
||||||
│ PageLevel.onUnlockClue(index: 2 or 3) │
|
|
||||||
└──────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
├─ Check: _isUnlocking == true?
|
|
||||||
│ └─ YES: Return immediately (prevent double-click)
|
|
||||||
│ └─ NO: Continue
|
|
||||||
│
|
|
||||||
├─ Check: StorageManager.hasPoints()?
|
|
||||||
│ └─ NO: Show toast "积分不足!"
|
|
||||||
│ └─ YES: Continue
|
|
||||||
│
|
|
||||||
├─ Set: _isUnlocking = true
|
|
||||||
│
|
|
||||||
├─ await UserAssetsManager.consumePoint(levelId, index)
|
|
||||||
│ │
|
|
||||||
│ ├─ ASYNC: Contact server/storage
|
|
||||||
│ │
|
|
||||||
│ └─ Returns: success boolean
|
|
||||||
│
|
|
||||||
├─ If success:
|
|
||||||
│ │
|
|
||||||
│ ├─ updatePointsLabel()
|
|
||||||
│ │
|
|
||||||
│ ├─ playClickSound()
|
|
||||||
│ │
|
|
||||||
│ ├─ hideUnlockButton(index)
|
|
||||||
│ │
|
|
||||||
│ ├─ showClue(index)
|
|
||||||
│ │
|
|
||||||
│ └─ setClue(index, config.clueN)
|
|
||||||
│
|
|
||||||
├─ If failed:
|
|
||||||
│ │
|
|
||||||
│ └─ Show toast "积分不足!"
|
|
||||||
│
|
|
||||||
└─ Finally: _isUnlocking = false
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Timer Sequence Diagram
|
|
||||||
|
|
||||||
```
|
|
||||||
Timeline: 1s 2s 3s ... 59s 60s 61s
|
|
||||||
│ │ │ │ │ │
|
|
||||||
▼ ▼ ▼ ▼ ▼ ▼
|
|
||||||
countdown: 60 59 58 1 0 (ended)
|
|
||||||
│ │ │ │ │
|
|
||||||
display: "60s" "59s" "58s" ......... "1s" "0s"
|
|
||||||
│ │ │ │ │
|
|
||||||
▼ ▼ ▼ ▼ ▼
|
|
||||||
|
|
||||||
LEVEL LOAD:
|
|
||||||
│
|
|
||||||
└─ startCountdown()
|
|
||||||
│
|
|
||||||
├─ _countdown = 60
|
|
||||||
├─ _isTimeUp = false
|
|
||||||
└─ schedule(onCountdownTick, 1.0) [Repeat every 1 sec]
|
|
||||||
│
|
|
||||||
▼ (Every 1 second)
|
|
||||||
onCountdownTick()
|
|
||||||
│
|
|
||||||
├─ if (_isTimeUp) return
|
|
||||||
│
|
|
||||||
├─ _countdown-- (60→59→58...→0)
|
|
||||||
│
|
|
||||||
├─ updateClockLabel() [Display: "59s"]
|
|
||||||
│
|
|
||||||
└─ if (_countdown <= 0):
|
|
||||||
│
|
|
||||||
├─ _isTimeUp = true
|
|
||||||
│
|
|
||||||
├─ stopCountdown()
|
|
||||||
│ └─ unschedule(onCountdownTick)
|
|
||||||
│
|
|
||||||
└─ onTimeUp()
|
|
||||||
│
|
|
||||||
└─ playFailSound()
|
|
||||||
|
|
||||||
ANSWER SUBMITTED (Correct):
|
|
||||||
│
|
|
||||||
└─ showSuccess()
|
|
||||||
│
|
|
||||||
├─ stopCountdown()
|
|
||||||
│ └─ Timer stops, no more ticks
|
|
||||||
│
|
|
||||||
└─ _showPassModal()
|
|
||||||
|
|
||||||
OR:
|
|
||||||
|
|
||||||
ANSWER SUBMITTED (Wrong):
|
|
||||||
│
|
|
||||||
└─ Timer continues running...
|
|
||||||
│
|
|
||||||
└─ User keeps playing
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Input Box Creation & Management
|
|
||||||
|
|
||||||
```
|
|
||||||
LEVEL LOADS:
|
|
||||||
│
|
|
||||||
└─ _applyLevelConfig(config)
|
|
||||||
│
|
|
||||||
└─ createSingleInput(config.answer.length)
|
|
||||||
│
|
|
||||||
├─ clearInputNodes()
|
|
||||||
│ │
|
|
||||||
│ └─ Destroy old input nodes
|
|
||||||
│ (If level changed)
|
|
||||||
│
|
|
||||||
├─ Hide inputTemplate
|
|
||||||
│
|
|
||||||
├─ instantiate(inputTemplate)
|
|
||||||
│
|
|
||||||
├─ Set properties:
|
|
||||||
│ │
|
|
||||||
│ ├─ active = true
|
|
||||||
│ ├─ name = 'singleInput'
|
|
||||||
│ ├─ position = (0, 0, 0)
|
|
||||||
│ │
|
|
||||||
│ └─ Get EditBox component
|
|
||||||
│ │
|
|
||||||
│ ├─ placeholder = "(Xlength个字)"
|
|
||||||
│ ├─ maxLength = answerLength
|
|
||||||
│ ├─ string = ""
|
|
||||||
│ │
|
|
||||||
│ └─ Listen events:
|
|
||||||
│ ├─ TEXT_CHANGED → onInputTextChanged()
|
|
||||||
│ └─ EDITING_DID_ENDED → onInputEditingEnded()
|
|
||||||
│
|
|
||||||
├─ Calculate width:
|
|
||||||
│ └─ Math.min(600, Math.max(200, length*60+40))
|
|
||||||
│
|
|
||||||
├─ Set UITransform contentSize to width x 100
|
|
||||||
│
|
|
||||||
├─ Adjust underline width to match
|
|
||||||
│
|
|
||||||
├─ Add to inputLayout
|
|
||||||
│
|
|
||||||
└─ Store in _inputNodes[0]
|
|
||||||
|
|
||||||
USER ENTERS TEXT:
|
|
||||||
│
|
|
||||||
├─ EditBox updates string property
|
|
||||||
└─ TEXT_CHANGED event fires
|
|
||||||
|
|
||||||
USER SUBMITS:
|
|
||||||
│
|
|
||||||
├─ getAnswer()
|
|
||||||
│ │
|
|
||||||
│ └─ _inputNodes[0].getComponent(EditBox).string.trim()
|
|
||||||
│
|
|
||||||
└─ Compare with config.answer
|
|
||||||
|
|
||||||
USER NAVIGATES AWAY:
|
|
||||||
│
|
|
||||||
└─ onViewDestroy() → clearInputNodes()
|
|
||||||
│
|
|
||||||
└─ Destroy all input nodes
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Share Challenge Mode Flow
|
|
||||||
|
|
||||||
```
|
|
||||||
LAUNCH FROM WeChat LINK:
|
|
||||||
│
|
|
||||||
└─ PageLoading.start()
|
|
||||||
│
|
|
||||||
└─ _startPreload()
|
|
||||||
│
|
|
||||||
├─ Initialize auth + levels (parallel)
|
|
||||||
│
|
|
||||||
├─ WxSDK.getShareCodeFromLaunch()
|
|
||||||
│ │
|
|
||||||
│ └─ Extract from wx.getLaunchOptionsSync().query
|
|
||||||
│
|
|
||||||
├─ if shareCode exists AND loginSuccess:
|
|
||||||
│ │
|
|
||||||
│ └─ ShareManager.instance.joinShare(shareCode)
|
|
||||||
│ │
|
|
||||||
│ ├─ ASYNC: Fetch share session from server
|
|
||||||
│ │
|
|
||||||
│ ├─ Get shared level set
|
|
||||||
│ │
|
|
||||||
│ └─ Return: success boolean
|
|
||||||
│
|
|
||||||
├─ if (joinSuccess):
|
|
||||||
│ │
|
|
||||||
│ ├─ Set progress = 1
|
|
||||||
│ │
|
|
||||||
│ ├─ ViewManager.open('PageLevel', {
|
|
||||||
│ │ params: { shareMode: true }
|
|
||||||
│ │ })
|
|
||||||
│ │
|
|
||||||
│ └─ Destroy self (PageLoading)
|
|
||||||
│
|
|
||||||
└─ else (normal flow)
|
|
||||||
│
|
|
||||||
└─ Preload PageHome → Open PageHome
|
|
||||||
|
|
||||||
IN SHARE MODE (PageLevel):
|
|
||||||
│
|
|
||||||
├─ onViewLoad():
|
|
||||||
│ │
|
|
||||||
│ ├─ params = getParams()
|
|
||||||
│ ├─ _isShareMode = params?.shareMode === true
|
|
||||||
│ │
|
|
||||||
│ ├─ if shareMode:
|
|
||||||
│ │ └─ currentLevelIndex = 0 (start at first)
|
|
||||||
│ │
|
|
||||||
│ └─ initLevel() loads from ShareManager, not LevelDataManager
|
|
||||||
│
|
|
||||||
├─ showSuccess():
|
|
||||||
│ │
|
|
||||||
│ ├─ if normal mode:
|
|
||||||
│ │ └─ earn points
|
|
||||||
│ │
|
|
||||||
│ └─ if share mode:
|
|
||||||
│ │
|
|
||||||
│ └─ ShareManager.reportLevelProgress(levelId, true, timeSpent)
|
|
||||||
│ │
|
|
||||||
│ └─ FIRE-AND-FORGET (no await)
|
|
||||||
│
|
|
||||||
├─ nextLevel():
|
|
||||||
│ │
|
|
||||||
│ ├─ if NOT shareMode:
|
|
||||||
│ │ └─ StorageManager.onLevelCompleted() [Save progress]
|
|
||||||
│ │
|
|
||||||
│ ├─ Check level count:
|
|
||||||
│ │ │
|
|
||||||
│ │ ├─ Share: ShareManager.getShareLevelCount()
|
|
||||||
│ │ └─ Normal: LevelDataManager.getLevelCount()
|
|
||||||
│ │
|
|
||||||
│ ├─ if (allLevelsComplete):
|
|
||||||
│ │ │
|
|
||||||
│ │ ├─ if shareMode:
|
|
||||||
│ │ │ │
|
|
||||||
│ │ │ ├─ ShareManager.clearShareMode()
|
|
||||||
│ │ │ │
|
|
||||||
│ │ │ └─ ViewManager.replace('PageHome')
|
|
||||||
│ │ │
|
|
||||||
│ │ └─ if normal:
|
|
||||||
│ │ └─ ViewManager.back()
|
|
||||||
│ │
|
|
||||||
│ └─ else (more levels):
|
|
||||||
│ └─ Load next level
|
|
||||||
│
|
|
||||||
└─ Back to PageHome (replaces, clears share state)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ViewManager Caching Mechanism
|
|
||||||
|
|
||||||
```
|
|
||||||
OPEN 'PageHome' (first time):
|
|
||||||
│
|
|
||||||
└─ ViewManager.open('PageHome')
|
|
||||||
│
|
|
||||||
├─ Check cache: _viewCache.get('PageHome')
|
|
||||||
│ └─ Cache miss (undefined)
|
|
||||||
│
|
|
||||||
├─ _instantiateView('PageHome', prefab)
|
|
||||||
│ │
|
|
||||||
│ ├─ instantiate(prefab)
|
|
||||||
│ │
|
|
||||||
│ ├─ Get BaseView component
|
|
||||||
│ │
|
|
||||||
│ ├─ Set viewId, config, params
|
|
||||||
│ │
|
|
||||||
│ ├─ Add to container
|
|
||||||
│ │
|
|
||||||
│ ├─ Call view.onViewLoad() ◄─── Called once
|
|
||||||
│ │
|
|
||||||
│ ├─ if (config.cache === true): ◄─── PageHome has cache:true
|
|
||||||
│ │ └─ _viewCache.set('PageHome', view)
|
|
||||||
│ │
|
|
||||||
│ └─ _showView(view)
|
|
||||||
│ │
|
|
||||||
│ └─ view._doShow()
|
|
||||||
│ └─ view.onViewShow() ◄─── Called now
|
|
||||||
│
|
|
||||||
└─ Stack: [PageHome]
|
|
||||||
|
|
||||||
OPEN 'PageLevel':
|
|
||||||
│
|
|
||||||
└─ ViewManager.open('PageLevel')
|
|
||||||
│
|
|
||||||
├─ PageHome._doHide()
|
|
||||||
│ └─ view.onViewHide() ◄─── First hide
|
|
||||||
│
|
|
||||||
└─ (Same as above for PageLevel)
|
|
||||||
│
|
|
||||||
└─ Stack: [PageHome, PageLevel]
|
|
||||||
|
|
||||||
BACK FROM 'PageLevel':
|
|
||||||
│
|
|
||||||
└─ ViewManager.back()
|
|
||||||
│
|
|
||||||
├─ Pop stack: PageLevel
|
|
||||||
│
|
|
||||||
├─ PageLevel._doHide()
|
|
||||||
│ └─ view.onViewHide()
|
|
||||||
│
|
|
||||||
├─ Decide: shouldDestroy?
|
|
||||||
│ │
|
|
||||||
│ └─ PageLevel has cache:true
|
|
||||||
│ └─ shouldDestroy = false (keep cached)
|
|
||||||
│
|
|
||||||
├─ Get current: PageHome
|
|
||||||
│
|
|
||||||
├─ PageHome._doShow()
|
|
||||||
│ └─ view.onViewShow() ◄─── Called again
|
|
||||||
│
|
|
||||||
└─ Stack: [PageHome]
|
|
||||||
Caches: {PageHome, PageLevel}
|
|
||||||
|
|
||||||
OPEN 'PageLevel' AGAIN (from cache):
|
|
||||||
│
|
|
||||||
└─ ViewManager.open('PageLevel')
|
|
||||||
│
|
|
||||||
├─ Check cache: _viewCache.get('PageLevel')
|
|
||||||
│ └─ Cache hit! (PageLevel instance)
|
|
||||||
│
|
|
||||||
├─ _showView(cachedView)
|
|
||||||
│ │
|
|
||||||
│ ├─ PageHome._doHide()
|
|
||||||
│ │
|
|
||||||
│ └─ cachedView._doShow()
|
|
||||||
│ └─ view.onViewShow() ◄─── Called again (2nd time)
|
|
||||||
│ onViewLoad() NOT called again ◄─── Important!
|
|
||||||
│
|
|
||||||
└─ Stack: [PageHome, PageLevel]
|
|
||||||
Same instance reused
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Error Handling Paths
|
|
||||||
|
|
||||||
```
|
|
||||||
LEVEL LOADING ERROR:
|
|
||||||
│
|
|
||||||
├─ initLevel()
|
|
||||||
│ │
|
|
||||||
│ └─ await LevelDataManager.ensureLevelReady(index)
|
|
||||||
│ │
|
|
||||||
│ └─ Returns null (error)
|
|
||||||
│
|
|
||||||
└─ Log warning, return early
|
|
||||||
│
|
|
||||||
└─ UI stays as-is (might be blank)
|
|
||||||
|
|
||||||
INSUFFICIENT POINTS:
|
|
||||||
│
|
|
||||||
└─ onUnlockClue()
|
|
||||||
│
|
|
||||||
├─ StorageManager.hasPoints() → false
|
|
||||||
│
|
|
||||||
└─ ToastManager.show("积分不足!")
|
|
||||||
│
|
|
||||||
└─ User sees notification, unlock blocked
|
|
||||||
|
|
||||||
DOUBLE-SUBMIT PREVENTION:
|
|
||||||
│
|
|
||||||
├─ onSubmitAnswer()
|
|
||||||
│ │
|
|
||||||
│ └─ if (_isTransitioning) return ◄─── Blocks multiple calls
|
|
||||||
│
|
|
||||||
└─ showSuccess()
|
|
||||||
│
|
|
||||||
└─ _isTransitioning = true ◄─── Set to block
|
|
||||||
│
|
|
||||||
└─ After modal shown/closed
|
|
||||||
└─ (Would be reset on nextLevel)
|
|
||||||
|
|
||||||
DOUBLE-CLICK UNLOCK:
|
|
||||||
│
|
|
||||||
└─ onUnlockClue()
|
|
||||||
│
|
|
||||||
└─ if (_isUnlocking) return ◄─── Blocks rapid clicks
|
|
||||||
│
|
|
||||||
└─ _isUnlocking = true at start
|
|
||||||
└─ Finally: _isUnlocking = false ◄─── Reset after async
|
|
||||||
```
|
|
||||||
|
|
||||||
288
DOCS_INDEX.md
288
DOCS_INDEX.md
@@ -1,288 +0,0 @@
|
|||||||
# Documentation Index
|
|
||||||
|
|
||||||
This directory contains comprehensive analysis of the mp-xieyingeng (写英语) Cocos Creator game point/score system.
|
|
||||||
|
|
||||||
## 📚 Documentation Files
|
|
||||||
|
|
||||||
### 1. **GAME_ANALYSIS.md** (19 KB) - COMPREHENSIVE ANALYSIS
|
|
||||||
The complete technical analysis of the game's point and score system. **Start here for complete understanding.**
|
|
||||||
|
|
||||||
**Contents:**
|
|
||||||
- PART 1: Points/Asset System (Lives currency)
|
|
||||||
- PART 2: Level Completion & Rewards (+1 life per pass)
|
|
||||||
- PART 3: Hint/Clue System (Costs 1 life each)
|
|
||||||
- PART 4: Game Play Logic (Answer validation, timing)
|
|
||||||
- PART 5: Loading Page Logic (Initialization flow)
|
|
||||||
- PART 6: API & Network Requests (Backend endpoint)
|
|
||||||
- PART 7: User Data Storage (localStorage schema)
|
|
||||||
- PART 8: WeChat Mini-Game SDK Usage
|
|
||||||
- PART 9: Complete Game Flow Diagram
|
|
||||||
- PART 10: Complete Resource Flow
|
|
||||||
- PART 11: Key Observations & Implementation Gaps
|
|
||||||
- PART 12: Network Architecture
|
|
||||||
- Summary table of all features
|
|
||||||
|
|
||||||
### 2. **QUICK_REFERENCE.md** (8.6 KB) - QUICK LOOKUP GUIDE
|
|
||||||
Fast reference guide for developers. Use this for quick lookups.
|
|
||||||
|
|
||||||
**Contents:**
|
|
||||||
- Core Currency Overview (Lives system)
|
|
||||||
- Flow Charts (Life economics, answer submission, app startup)
|
|
||||||
- Data Structures (localStorage, API response)
|
|
||||||
- Key Functions & Methods
|
|
||||||
- Missing Features & Implementation Gaps
|
|
||||||
- Network Calls Summary
|
|
||||||
- Game Loop Per Level
|
|
||||||
- Data Integrity Notes
|
|
||||||
- WeChat Features Status
|
|
||||||
- Extension Ideas (Easy/Medium/Complex)
|
|
||||||
|
|
||||||
### 3. **ARCHITECTURE.md** (26 KB) - SYSTEM DESIGN
|
|
||||||
Detailed architecture diagrams and system design documentation.
|
|
||||||
|
|
||||||
**Contents:**
|
|
||||||
- System Architecture Diagram (layered view)
|
|
||||||
- Data Flow Diagram (complete user session)
|
|
||||||
- State Management Flow
|
|
||||||
- View Stack & Navigation
|
|
||||||
- Class Hierarchy
|
|
||||||
- Dependency Graph
|
|
||||||
- Performance Considerations
|
|
||||||
- Security Considerations & Vulnerabilities
|
|
||||||
|
|
||||||
## 🎯 Quick Navigation
|
|
||||||
|
|
||||||
### "I want to understand..."
|
|
||||||
|
|
||||||
**...how the point system works**
|
|
||||||
→ Read: QUICK_REFERENCE.md "THE COMPLETE PICTURE"
|
|
||||||
|
|
||||||
**...the complete game flow**
|
|
||||||
→ Read: GAME_ANALYSIS.md "PART 9: Complete Game Flow Diagram"
|
|
||||||
|
|
||||||
**...how lives are stored and managed**
|
|
||||||
→ Read: GAME_ANALYSIS.md "PART 1: Points/Asset System" + PART 7: User Data Storage"
|
|
||||||
|
|
||||||
**...what happens when a user completes a level**
|
|
||||||
→ Read: GAME_ANALYSIS.md "PART 2: Level Completion & Rewards"
|
|
||||||
|
|
||||||
**...how hints work**
|
|
||||||
→ Read: GAME_ANALYSIS.md "PART 3: Hint/Clue System"
|
|
||||||
|
|
||||||
**...the API integration**
|
|
||||||
→ Read: GAME_ANALYSIS.md "PART 6: API & Network Requests"
|
|
||||||
|
|
||||||
**...the code organization**
|
|
||||||
→ Read: ARCHITECTURE.md "System Architecture Diagram" + "Dependency Graph"
|
|
||||||
|
|
||||||
**...what's missing in the implementation**
|
|
||||||
→ Read: GAME_ANALYSIS.md "PART 11: Key Observations & Gaps"
|
|
||||||
|
|
||||||
**...where to add new features**
|
|
||||||
→ Read: QUICK_REFERENCE.md "EXTENSION IDEAS"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔑 Key Findings Summary
|
|
||||||
|
|
||||||
### THE POINT SYSTEM
|
|
||||||
- **Currency**: Lives (生命值)
|
|
||||||
- **Default**: 10 lives
|
|
||||||
- **Earn**: +1 per level pass
|
|
||||||
- **Spend**: -1 per hint unlock (Hint 2 or 3 only)
|
|
||||||
- **Storage**: localStorage under key `game_lives`
|
|
||||||
- **No other currency**: No points, coins, or score counter
|
|
||||||
|
|
||||||
### LEVEL COMPLETION
|
|
||||||
- **Reward**: +1 life (only reward)
|
|
||||||
- **No time bonus**: Same reward regardless of speed
|
|
||||||
- **No partial credit**: Exact case-sensitive match required
|
|
||||||
- **Unlimited retries**: Can retry wrong answers indefinitely
|
|
||||||
- **Timeout incomplete**: 60s countdown exists but doesn't prevent submission
|
|
||||||
|
|
||||||
### HINT SYSTEM
|
|
||||||
- **Hint 1**: Free (always shown)
|
|
||||||
- **Hint 2**: Costs 1 life (unlock button)
|
|
||||||
- **Hint 3**: Costs 1 life (unlock button)
|
|
||||||
- **Max loss per level**: 2 lives (both hints)
|
|
||||||
- **Net per level**: -1 to +1 depending on hints used
|
|
||||||
|
|
||||||
### DATA STORAGE
|
|
||||||
- **Lives**: localStorage["game_lives"]
|
|
||||||
- **Progress**: localStorage["game_progress"] with currentLevelIndex & maxUnlockedLevelIndex
|
|
||||||
- **All local**: No server-side sync
|
|
||||||
- **No encryption**: Direct access via console
|
|
||||||
- **Immediate writes**: Each update written to storage immediately
|
|
||||||
|
|
||||||
### API INTEGRATION
|
|
||||||
- **Single endpoint**: GET https://ilookai.cn/api/v1/wechat-game/levels
|
|
||||||
- **Startup only**: Called once during initialization
|
|
||||||
- **Retry**: 2 attempts with 1s delay
|
|
||||||
- **Timeout**: 8 seconds
|
|
||||||
- **No other backend calls**: No score submission, no analytics, no leaderboard
|
|
||||||
|
|
||||||
### WECHAT FEATURES
|
|
||||||
- ✅ Sharing (with level parameter)
|
|
||||||
- ✅ Haptic feedback (vibration on errors)
|
|
||||||
- ❌ No authentication
|
|
||||||
- ❌ No cloud save
|
|
||||||
- ❌ No leaderboard
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📁 Source Files Referenced
|
|
||||||
|
|
||||||
All 16 TypeScript files in the project are analyzed:
|
|
||||||
|
|
||||||
**Core Pages:**
|
|
||||||
- `PageLoading.ts` - Loading screen & initialization
|
|
||||||
- `PageHome.ts` - Home menu page
|
|
||||||
- `PageLevel.ts` - Main game level (where all game logic happens)
|
|
||||||
- `PassModal.ts` - Level completion modal
|
|
||||||
|
|
||||||
**Management Systems:**
|
|
||||||
- `ViewManager.ts` - Page navigation & lifecycle
|
|
||||||
- `StorageManager.ts` - Lives & progress persistence
|
|
||||||
- `LevelDataManager.ts` - API integration & asset loading
|
|
||||||
|
|
||||||
**Utilities:**
|
|
||||||
- `BaseView.ts` - Base class for pages
|
|
||||||
- `HttpUtil.ts` - HTTP request wrapper
|
|
||||||
- `WxSDK.ts` - WeChat SDK integration
|
|
||||||
- `ToastManager.ts` - Toast notifications
|
|
||||||
- `Toast.ts` - Toast component
|
|
||||||
- `LevelTypes.ts` - TypeScript interfaces
|
|
||||||
- `RoundedRectMask.ts` - UI utility
|
|
||||||
- `BackgroundScaler.ts` - UI utility
|
|
||||||
- `main.ts` - App entry point
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔬 Analysis Methodology
|
|
||||||
|
|
||||||
This documentation was created by:
|
|
||||||
1. Finding all 16 TypeScript files in the assets/ directory
|
|
||||||
2. Reading and analyzing each file for:
|
|
||||||
- Score/points logic
|
|
||||||
- Currency/asset management
|
|
||||||
- Level completion mechanics
|
|
||||||
- Hint/cost systems
|
|
||||||
- API calls
|
|
||||||
- Storage mechanisms
|
|
||||||
- WeChat SDK usage
|
|
||||||
- Data flows
|
|
||||||
3. Mapping dependencies between files
|
|
||||||
4. Creating flowcharts and diagrams
|
|
||||||
5. Documenting observations and gaps
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Using This Documentation
|
|
||||||
|
|
||||||
### For Understanding the System
|
|
||||||
1. Start with QUICK_REFERENCE.md for overview
|
|
||||||
2. Read GAME_ANALYSIS.md for detailed understanding
|
|
||||||
3. Refer to ARCHITECTURE.md for system design
|
|
||||||
|
|
||||||
### For Making Changes
|
|
||||||
1. Check ARCHITECTURE.md "Dependency Graph"
|
|
||||||
2. Review relevant code sections in GAME_ANALYSIS.md
|
|
||||||
3. Use QUICK_REFERENCE.md to find specific methods
|
|
||||||
|
|
||||||
### For Adding Features
|
|
||||||
1. Review QUICK_REFERENCE.md "EXTENSION IDEAS"
|
|
||||||
2. Check ARCHITECTURE.md "Security Considerations"
|
|
||||||
3. Plan changes against current dependencies
|
|
||||||
|
|
||||||
### For Debugging
|
|
||||||
1. Review GAME_ANALYSIS.md "PART 9: Game Flow Diagram"
|
|
||||||
2. Check ARCHITECTURE.md "Data Flow Diagram"
|
|
||||||
3. Trace through StorageManager and LevelDataManager
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ Important Notes
|
|
||||||
|
|
||||||
### Security Issues
|
|
||||||
- ⚠️ All data stored locally without encryption
|
|
||||||
- ⚠️ No server-side validation of progress
|
|
||||||
- ⚠️ Users can modify localStorage directly
|
|
||||||
- ⚠️ Can skip levels by editing progress
|
|
||||||
|
|
||||||
### Implementation Gaps
|
|
||||||
- ❌ No points/coins display
|
|
||||||
- ❌ No time-based bonuses
|
|
||||||
- ❌ Timeout doesn't prevent submission
|
|
||||||
- ❌ No server-side progress sync
|
|
||||||
- ❌ No analytics tracking
|
|
||||||
|
|
||||||
### To Improve
|
|
||||||
- Add server-side progress validation
|
|
||||||
- Implement user authentication
|
|
||||||
- Add score API endpoint
|
|
||||||
- Track time-to-completion
|
|
||||||
- Consider leaderboard system
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Document Versions
|
|
||||||
|
|
||||||
- Created: April 5, 2026
|
|
||||||
- Cocos Creator Version: 3.8.8
|
|
||||||
- Project: mp-xieyingeng (写英语)
|
|
||||||
- Platform: WeChat Mini-Game
|
|
||||||
- Analysis Coverage: 100% of TypeScript codebase (16 files)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 Questions Answered
|
|
||||||
|
|
||||||
This documentation answers:
|
|
||||||
- ✅ What is the points/score system?
|
|
||||||
- ✅ How do users earn points?
|
|
||||||
- ✅ How are points spent?
|
|
||||||
- ✅ What happens on level completion?
|
|
||||||
- ✅ How do hints work and cost lives?
|
|
||||||
- ✅ Where is data stored?
|
|
||||||
- ✅ What API calls are made?
|
|
||||||
- ✅ How does WeChat integration work?
|
|
||||||
- ✅ What's the complete game flow?
|
|
||||||
- ✅ What features are missing?
|
|
||||||
- ✅ What's the system architecture?
|
|
||||||
- ✅ Where are the security issues?
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 Cross-References
|
|
||||||
|
|
||||||
| Topic | Main Document | Quick Ref | Architecture |
|
|
||||||
|-------|---------------|-----------|--------------|
|
|
||||||
| Lives System | PART 1 | Overview | State Mgmt |
|
|
||||||
| Level Rewards | PART 2 | Economics | Data Flow |
|
|
||||||
| Hints & Costs | PART 3 | Game Loop | Dependencies |
|
|
||||||
| API | PART 6 | Network | External |
|
|
||||||
| Storage | PART 7 | Data Structures | State Mgmt |
|
|
||||||
| WeChat | PART 8 | Features | Dependencies |
|
|
||||||
| Game Flow | PART 9 | Game Loop | Data Flow |
|
|
||||||
| Features | PART 11 | Missing | Performance |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Statistics
|
|
||||||
|
|
||||||
- **TypeScript Files Analyzed**: 16
|
|
||||||
- **Lines of Code Reviewed**: ~1,800
|
|
||||||
- **API Endpoints**: 1
|
|
||||||
- **Storage Keys**: 2
|
|
||||||
- **External SDKs**: 1 (WeChat)
|
|
||||||
- **Currency Types**: 1 (Lives)
|
|
||||||
- **Hint Levels**: 3
|
|
||||||
- **Levels Supported**: 100+ (from API)
|
|
||||||
- **Player Lives**: 10 (default)
|
|
||||||
- **Time Per Level**: 60 seconds
|
|
||||||
- **Max Hint Cost Per Level**: 2 lives
|
|
||||||
- **Max Life Gain Per Level**: 1 life
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**For questions or clarifications, refer to the specific document sections listed above.**
|
|
||||||
504
GAME_ANALYSIS.md
504
GAME_ANALYSIS.md
@@ -1,504 +0,0 @@
|
|||||||
# Cocos Creator Game - Complete Point/Score System Analysis
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
This is a WeChat Mini-Game built with Cocos Creator. It's a word puzzle game where players guess answers to images within a 60-second time limit. The game uses a "lives" system instead of traditional points/coins.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. LIVES/RESOURCE SYSTEM (The Currency/Points Equivalent)
|
|
||||||
|
|
||||||
### Storage & Persistence
|
|
||||||
**File:** `StorageManager.ts`
|
|
||||||
- **Storage Key:** `game_lives`
|
|
||||||
- **Default Lives:** 10 (for new users)
|
|
||||||
- **Minimum Lives:** 0
|
|
||||||
- **Storage Method:** `sys.localStorage` (Cocos local storage)
|
|
||||||
|
|
||||||
### Lives Management Methods:
|
|
||||||
```typescript
|
|
||||||
// Core Methods:
|
|
||||||
- getLives(): number // Get current lives (default 10 if not set)
|
|
||||||
- setLives(lives: number) // Set lives value (min 0)
|
|
||||||
- consumeLife(): boolean // Deduct 1 life, returns success status
|
|
||||||
- addLife(): void // Add 1 life
|
|
||||||
- hasLives(): boolean // Check if lives > 0
|
|
||||||
- resetLives(): void // Reset to default 10
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lives Usage:
|
|
||||||
1. **Unlocking Hints (Clues):** Each unlock costs 1 life
|
|
||||||
- Clue 1: Free (always unlocked)
|
|
||||||
- Clue 2: Costs 1 life to unlock
|
|
||||||
- Clue 3: Costs 1 life to unlock
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. LEVEL PROGRESSION SYSTEM
|
|
||||||
|
|
||||||
**File:** `StorageManager.ts` (User Progress section)
|
|
||||||
|
|
||||||
### Progress Data Structure:
|
|
||||||
```typescript
|
|
||||||
interface UserProgress {
|
|
||||||
currentLevelIndex: number; // Current level (0-based)
|
|
||||||
maxUnlockedLevelIndex: number; // Highest level player reached
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Progress Storage:
|
|
||||||
- **Storage Key:** `game_progress`
|
|
||||||
- **Default:** `{ currentLevelIndex: 0, maxUnlockedLevelIndex: 0 }`
|
|
||||||
- **Caching:** Cached in memory (`_progressCache`) to avoid repeated localStorage reads
|
|
||||||
|
|
||||||
### Progression Methods:
|
|
||||||
```typescript
|
|
||||||
- getCurrentLevelIndex(): number // Get current level
|
|
||||||
- setCurrentLevelIndex(index): void // Set current level
|
|
||||||
- getMaxUnlockedLevelIndex(): number // Get highest unlocked level
|
|
||||||
- isLevelUnlocked(levelIndex): boolean // Check if level is playable
|
|
||||||
- onLevelCompleted(completedLevelIndex) // Called when level is beaten
|
|
||||||
- resetProgress(): void // Reset to level 1
|
|
||||||
```
|
|
||||||
|
|
||||||
### Level Unlock Logic:
|
|
||||||
- **Level 1** is always unlocked
|
|
||||||
- When player completes level N:
|
|
||||||
- Current level → N+1
|
|
||||||
- Max unlocked → max(maxUnlocked, N)
|
|
||||||
- This allows replaying lower levels while progressing forward
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. GAME LEVEL DATA & API
|
|
||||||
|
|
||||||
**File:** `LevelDataManager.ts`
|
|
||||||
|
|
||||||
### API Configuration:
|
|
||||||
```typescript
|
|
||||||
API_URL = 'https://ilookai.cn/api/v1/wechat-game/levels'
|
|
||||||
REQUEST_TIMEOUT = 8000ms
|
|
||||||
API_RETRY_COUNT = 2 (retries on failure)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Level Data Structure (from API):
|
|
||||||
```typescript
|
|
||||||
interface ApiLevelData {
|
|
||||||
id: string; // UUID
|
|
||||||
level: number; // Level number
|
|
||||||
imageUrl: string; // Main image URL
|
|
||||||
hint1: string; // Free clue
|
|
||||||
hint2: string; // Paid clue (costs 1 life)
|
|
||||||
hint3: string; // Paid clue (costs 1 life)
|
|
||||||
answer: string; // The correct answer
|
|
||||||
sortOrder: number; // Sorting order
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### API Response:
|
|
||||||
```typescript
|
|
||||||
interface ApiResponse {
|
|
||||||
success: boolean;
|
|
||||||
message: string | null;
|
|
||||||
data: {
|
|
||||||
levels: ApiLevelData[];
|
|
||||||
total: number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Image Loading:
|
|
||||||
- Remote images loaded via `assetManager.loadRemote()`
|
|
||||||
- Cached in memory (`_imageCache: Map<URL, SpriteFrame>`)
|
|
||||||
- First level image preloaded during app initialization
|
|
||||||
- Next level image preloaded silently after entering current level
|
|
||||||
|
|
||||||
### Loading Strategy:
|
|
||||||
1. **On App Start:** Load all level metadata + first level image (80% of loading bar)
|
|
||||||
2. **On Level Enter:** Load current level image if needed
|
|
||||||
3. **After Level Completion:** Preload next level asynchronously (doesn't block gameplay)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. GAMEPLAY LOOP
|
|
||||||
|
|
||||||
**File:** `PageLevel.ts`
|
|
||||||
|
|
||||||
### Game Sequence:
|
|
||||||
1. Player enters level
|
|
||||||
2. Main image displays with hint 1 visible
|
|
||||||
3. 60-second countdown starts
|
|
||||||
4. Player enters answer in single EditBox
|
|
||||||
5. Player can unlock hints 2 & 3 by spending lives
|
|
||||||
6. Player submits answer
|
|
||||||
|
|
||||||
### Time Limit:
|
|
||||||
- **Duration:** 60 seconds per level
|
|
||||||
- **Implementation:** `schedule(this.onCountdownTick, 1)` (1-second interval)
|
|
||||||
- **On Time Up:** Plays fail sound, but doesn't force level exit
|
|
||||||
|
|
||||||
### Input System:
|
|
||||||
- **Type:** Single EditBox (not multi-input per character)
|
|
||||||
- **Width:** Dynamic (based on answer length)
|
|
||||||
- Formula: `Math.min(600, Math.max(200, answerLength * 60 + 40))` pixels
|
|
||||||
- **Max Length:** Match answer length
|
|
||||||
- **Placeholder:** Shows answer length as hint
|
|
||||||
|
|
||||||
### Answer Processing:
|
|
||||||
```typescript
|
|
||||||
getAnswer(): string {
|
|
||||||
const editBox = this._inputNodes[0].getComponent(EditBox);
|
|
||||||
return (editBox?.string ?? '').trim(); // Trimmed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comparison is case-sensitive:
|
|
||||||
if (userAnswer === this._currentConfig.answer) {
|
|
||||||
// WIN
|
|
||||||
} else {
|
|
||||||
// LOSE
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. WINNING & REWARDS
|
|
||||||
|
|
||||||
**File:** `PageLevel.ts`
|
|
||||||
|
|
||||||
### On Correct Answer:
|
|
||||||
1. **Stop Timer:** Countdown stops
|
|
||||||
2. **Play Sound:** Success audio plays
|
|
||||||
3. **Award 1 Life:** `addLife()` called
|
|
||||||
4. **Show Modal:** PassModal displays with buttons
|
|
||||||
|
|
||||||
### Pass Modal (Victory Screen):
|
|
||||||
- Shows "Next Level" button
|
|
||||||
- Shows "Share with Friends" button
|
|
||||||
- On "Next Level": Progress to next level (calls `onLevelCompleted()`)
|
|
||||||
- On "Share": Triggers WeChat share with query param `?level=<levelIndex>`
|
|
||||||
|
|
||||||
### Progression on Pass:
|
|
||||||
```typescript
|
|
||||||
StorageManager.onLevelCompleted(currentLevelIndex);
|
|
||||||
// Sets:
|
|
||||||
// - currentLevelIndex → currentLevelIndex + 1
|
|
||||||
// - maxUnlockedLevelIndex → max(maxUnlocked, currentLevelIndex)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Game End Condition:
|
|
||||||
- When `currentLevelIndex >= totalLevels`, player has beaten all levels
|
|
||||||
- Game returns to home page
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. LOSING & CONSEQUENCES
|
|
||||||
|
|
||||||
**File:** `PageLevel.ts`
|
|
||||||
|
|
||||||
### On Wrong Answer:
|
|
||||||
1. **Play Sound:** Fail audio plays
|
|
||||||
2. **Vibration:** `WxSDK.vibrateLong()` (400ms vibration on WeChat)
|
|
||||||
3. **Toast Message:** "答案错误,再试试吧!" (Answer wrong, try again!)
|
|
||||||
4. **No Penalty:** No life deducted, level doesn't change
|
|
||||||
|
|
||||||
### On Time Up:
|
|
||||||
1. **Play Sound:** Fail audio plays
|
|
||||||
2. **Countdown Stops:** `_isTimeUp = true`
|
|
||||||
3. **No Forced Exit:** Player can continue typing and submitting
|
|
||||||
4. **No Life Penalty:** Still can retry
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. HINT/CLUE SYSTEM
|
|
||||||
|
|
||||||
**File:** `PageLevel.ts`
|
|
||||||
|
|
||||||
### Clue Mechanics:
|
|
||||||
1. **Clue 1:** Always visible, FREE
|
|
||||||
2. **Clue 2:** Hidden by default, costs 1 life to unlock
|
|
||||||
3. **Clue 3:** Hidden by default, costs 1 life to unlock
|
|
||||||
|
|
||||||
### Unlocking Process:
|
|
||||||
```typescript
|
|
||||||
onUnlockClue(index: number) {
|
|
||||||
// 1. Check if lives available
|
|
||||||
if (!this.hasLives()) return;
|
|
||||||
|
|
||||||
// 2. Consume 1 life
|
|
||||||
if (!this.consumeLife()) return;
|
|
||||||
|
|
||||||
// 3. Play click sound
|
|
||||||
this.playClickSound();
|
|
||||||
|
|
||||||
// 4. Hide unlock button
|
|
||||||
this.hideUnlockButton(index);
|
|
||||||
|
|
||||||
// 5. Show clue content
|
|
||||||
this.showClue(index);
|
|
||||||
this.setClue(index, clueContent);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Clue Cost Implications:
|
|
||||||
- Player starts with 10 lives
|
|
||||||
- Can unlock both clues 2 & 3 = 2 lives spent minimum
|
|
||||||
- But only 8 lives remain per level if both used
|
|
||||||
- Player can conserve lives by solving without clues
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. NETWORK & API COMMUNICATION
|
|
||||||
|
|
||||||
**File:** `HttpUtil.ts`
|
|
||||||
|
|
||||||
### HTTP Methods:
|
|
||||||
```typescript
|
|
||||||
// GET request
|
|
||||||
HttpUtil.get<T>(url: string, timeout: number = 10000): Promise<T>
|
|
||||||
|
|
||||||
// POST request
|
|
||||||
HttpUtil.post<T>(url: string, data: object, timeout: number = 10000): Promise<T>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Implementation:
|
|
||||||
- Uses `XMLHttpRequest`
|
|
||||||
- Supports JSON responses
|
|
||||||
- Default timeout: 10 seconds
|
|
||||||
- Error handling: Rejects on HTTP errors, timeouts, or network failures
|
|
||||||
|
|
||||||
### Used By:
|
|
||||||
- `LevelDataManager` uses `HttpUtil.get()` to fetch level data from API
|
|
||||||
- No POST requests currently used
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. WECHAT SDK INTEGRATION
|
|
||||||
|
|
||||||
**File:** `WxSDK.ts`
|
|
||||||
|
|
||||||
### WeChat Features Used:
|
|
||||||
|
|
||||||
#### 1. Platform Detection:
|
|
||||||
```typescript
|
|
||||||
isWechat(): boolean
|
|
||||||
// Returns: sys.platform === sys.Platform.WECHAT_GAME
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. Sharing:
|
|
||||||
- **Share Menu:** `showShareMenu()` - Enables share button in header
|
|
||||||
- **Friend Share:** `onShareAppMessage(config)` - Right-click "Share" message
|
|
||||||
- **Timeline Share:** `onShareTimeline(config)` - Moments sharing
|
|
||||||
- **Active Share:** `shareAppMessage(config)` - Trigger share dialog
|
|
||||||
|
|
||||||
#### 3. Vibration:
|
|
||||||
- **Short Vibrate:** `vibrateShort()` - 15ms, for button clicks
|
|
||||||
- **Long Vibrate:** `vibrateLong()` - 400ms, for errors
|
|
||||||
|
|
||||||
#### 4. Share Configuration:
|
|
||||||
```typescript
|
|
||||||
interface WxShareConfig {
|
|
||||||
title: string; // Share title: "写英语"
|
|
||||||
imageUrl?: string; // Share image (optional)
|
|
||||||
query?: string; // Query params (e.g., "level=5")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 5. Initialization:
|
|
||||||
```typescript
|
|
||||||
WxSDK.initShare(config) {
|
|
||||||
// Calls in sequence:
|
|
||||||
// 1. showShareMenu()
|
|
||||||
// 2. onShareAppMessage(config)
|
|
||||||
// 3. onShareTimeline(config)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Called in:** PageHome on game start
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. GAME STATE MANAGEMENT
|
|
||||||
|
|
||||||
**File:** `ViewManager.ts` (Page Stack) + `StorageManager.ts` (Data)
|
|
||||||
|
|
||||||
### View Stack (Navigation):
|
|
||||||
- Maintains page stack for navigation
|
|
||||||
- `PageHome` (z-index 0) - Main menu
|
|
||||||
- `PageLevel` (z-index 1) - Game level
|
|
||||||
- `PassModal` (z-index 999) - Victory overlay
|
|
||||||
|
|
||||||
### Persistent State:
|
|
||||||
- Lives stored in localStorage with key `game_lives`
|
|
||||||
- Progress stored in localStorage with key `game_progress`
|
|
||||||
- Both persist across app sessions
|
|
||||||
- Data survives app closure and reopening
|
|
||||||
|
|
||||||
### Runtime State:
|
|
||||||
- Current countdown timer
|
|
||||||
- Current input box content
|
|
||||||
- Unlocked clues state (reset each level)
|
|
||||||
- Current level config (API data)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 11. LOADING PAGE FLOW
|
|
||||||
|
|
||||||
**File:** `PageLoading.ts`
|
|
||||||
|
|
||||||
### Initialization Sequence:
|
|
||||||
1. **Stage 1 (0-30%):** Fetch all levels from API via `LevelDataManager.initialize()`
|
|
||||||
- API call with retry logic
|
|
||||||
- Parse level metadata
|
|
||||||
- NOT loading all images yet
|
|
||||||
|
|
||||||
2. **Stage 2 (30-80%):** Preload first level image
|
|
||||||
- Uses `LevelDataManager.ensureLevelReady(0)`
|
|
||||||
- Shows "正在加载游戏必备资源..." message
|
|
||||||
|
|
||||||
3. **Stage 3 (80-100%):** Preload PageHome view
|
|
||||||
- `ViewManager.preload('PageHome')`
|
|
||||||
- Shows "正在加载界面资源..." message
|
|
||||||
|
|
||||||
4. **Completion (100%):** Open PageHome and destroy loading page
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 12. COMPLETE POINTS FLOW DIAGRAM
|
|
||||||
|
|
||||||
```
|
|
||||||
START GAME
|
|
||||||
↓
|
|
||||||
[10 Lives] (default)
|
|
||||||
↓
|
|
||||||
LEVEL 1 STARTS
|
|
||||||
├─ View Clue 1 (FREE)
|
|
||||||
├─ Option: Unlock Clue 2 (-1 Life) → [9 Lives]
|
|
||||||
├─ Option: Unlock Clue 3 (-1 Life) → [8 Lives]
|
|
||||||
├─ Player submits answer
|
|
||||||
│
|
|
||||||
├─ IF CORRECT:
|
|
||||||
│ ├─ Add 1 Life → [9 or 10+ Lives]
|
|
||||||
│ ├─ Show PassModal
|
|
||||||
│ └─ Move to LEVEL 2
|
|
||||||
│
|
|
||||||
└─ IF WRONG:
|
|
||||||
├─ Play fail sound & vibrate
|
|
||||||
├─ Show toast message
|
|
||||||
├─ Lives unchanged
|
|
||||||
└─ Can retry (no level exit)
|
|
||||||
|
|
||||||
IF ALL LEVELS COMPLETE:
|
|
||||||
└─ Return to home
|
|
||||||
|
|
||||||
IF TIME UP:
|
|
||||||
├─ Play fail sound
|
|
||||||
├─ Can still submit (lives unchanged)
|
|
||||||
└─ No forced exit
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 13. KEY FILES SUMMARY
|
|
||||||
|
|
||||||
| File | Purpose | Key Components |
|
|
||||||
|------|---------|-----------------|
|
|
||||||
| StorageManager.ts | Data persistence | Lives + Progress storage |
|
|
||||||
| LevelDataManager.ts | Level data loading | API calls + Image caching |
|
|
||||||
| PageLevel.ts | Main game logic | Countdown, input, hints, validation |
|
|
||||||
| PageLoading.ts | App initialization | Loading bar + progress |
|
|
||||||
| PageHome.ts | Home screen | Start game button |
|
|
||||||
| PassModal.ts | Victory screen | Next/Share buttons |
|
|
||||||
| ViewManager.ts | Page navigation | View stack + caching |
|
|
||||||
| WxSDK.ts | WeChat API | Share + vibration |
|
|
||||||
| HttpUtil.ts | Network requests | GET/POST + error handling |
|
|
||||||
| ToastManager.ts | Notifications | Brief toast messages |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 14. IMPORTANT CONSTANTS
|
|
||||||
|
|
||||||
### Game Constants:
|
|
||||||
- **Level Time Limit:** 60 seconds
|
|
||||||
- **Default Lives:** 10
|
|
||||||
- **Life Cost per Hint:** 1 life per hint (hints 2 & 3)
|
|
||||||
- **Reward per Level:** +1 life
|
|
||||||
|
|
||||||
### API Constants:
|
|
||||||
- **Endpoint:** `https://ilookai.cn/api/v1/wechat-game/levels`
|
|
||||||
- **Timeout:** 8000ms
|
|
||||||
- **Retry Count:** 2
|
|
||||||
|
|
||||||
### UI Constants:
|
|
||||||
- **PageHome z-index:** 0
|
|
||||||
- **PageLevel z-index:** 1
|
|
||||||
- **PassModal z-index:** 999
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 15. MISSING FEATURES (Observations)
|
|
||||||
|
|
||||||
1. **No User Authentication:** No wx.login call visible
|
|
||||||
2. **No Backend Sync:** No calls to save progress to server
|
|
||||||
3. **No Ads/IAP:** No monetization system
|
|
||||||
4. **No Leaderboards:** No score submission to WeChat
|
|
||||||
5. **No Analytics:** No tracking events beyond console logs
|
|
||||||
6. **No Life Refill:** No premium way to get more lives
|
|
||||||
7. **No Difficulty Levels:** All players see same levels
|
|
||||||
8. **No Sound Toggle:** Sound plays automatically
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 16. DATA FLOW SUMMARY
|
|
||||||
|
|
||||||
```
|
|
||||||
WeChat API: https://ilookai.cn/api/v1/wechat-game/levels
|
|
||||||
↓
|
|
||||||
LevelDataManager (fetch + cache)
|
|
||||||
↓
|
|
||||||
PageLevel (display + gameplay)
|
|
||||||
├─ InputBox (player answer)
|
|
||||||
├─ Clues (cost lives to unlock)
|
|
||||||
└─ Timer (60 second countdown)
|
|
||||||
↓
|
|
||||||
StorageManager (save lives + progress)
|
|
||||||
↓
|
|
||||||
localStorage
|
|
||||||
├─ game_lives: number
|
|
||||||
└─ game_progress: UserProgress (JSON)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 17. CRITICAL BUSINESS LOGIC
|
|
||||||
|
|
||||||
### Win Condition:
|
|
||||||
```
|
|
||||||
userAnswer (trimmed) === correctAnswer (from API)
|
|
||||||
→ Award +1 life
|
|
||||||
→ Save progress
|
|
||||||
→ Move to next level
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lose Condition:
|
|
||||||
```
|
|
||||||
userAnswer !== correctAnswer
|
|
||||||
→ No penalty
|
|
||||||
→ Can retry immediately
|
|
||||||
→ Timer continues (even after time up)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Progression:
|
|
||||||
```
|
|
||||||
Beat Level N
|
|
||||||
→ currentLevel = N + 1
|
|
||||||
→ maxUnlocked = max(maxUnlocked, N)
|
|
||||||
→ Reward: +1 life (so levels can chain profitably)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Economy Balance:
|
|
||||||
- Start: 10 lives
|
|
||||||
- Per level: Can spend 0-2 lives (hints) or 0 lives (no hints)
|
|
||||||
- Per level: Earn +1 life (net: -1 or +1 lives)
|
|
||||||
- Average player with no hints: +1 life/level → infinite scaling
|
|
||||||
- Average player with 1 hint: 0 lives/level → stable
|
|
||||||
- Hardcore with 2 hints: -1 life/level → finite runway
|
|
||||||
|
|
||||||
@@ -1,494 +0,0 @@
|
|||||||
# Complete Points/Lives Flow Diagram
|
|
||||||
|
|
||||||
## 🔴 INITIALIZATION PHASE
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────┐
|
|
||||||
│ GAME STARTS │
|
|
||||||
│ PageLoading initializes │
|
|
||||||
└──────────────┬──────────────────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌──────────────────────────┐
|
|
||||||
│ Check localStorage │
|
|
||||||
│ "game_lives" key │
|
|
||||||
└────┬──────────────┬──────┘
|
|
||||||
│ │
|
|
||||||
NOT SET EXISTS
|
|
||||||
(New User) (Returning)
|
|
||||||
│ │
|
|
||||||
↓ ↓
|
|
||||||
┌────────────┐ ┌────────────┐
|
|
||||||
│ 10 Lives │ │Parse Value │
|
|
||||||
│(DEFAULT) │ │from Storage│
|
|
||||||
└────┬───────┘ └────┬───────┘
|
|
||||||
│ │
|
|
||||||
└────────┬───────┘
|
|
||||||
↓
|
|
||||||
┌────────────────────────┐
|
|
||||||
│ LOAD LEVEL DATA │
|
|
||||||
│ (API fetch) │
|
|
||||||
│ https://ilookai.cn ... │
|
|
||||||
└────────┬───────────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌────────────────────────┐
|
|
||||||
│ Display PageHome │
|
|
||||||
│ (with shared config) │
|
|
||||||
└────────┬───────────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌────────────────────────┐
|
|
||||||
│ READY TO PLAY │
|
|
||||||
│ Lives: X | Level: Y │
|
|
||||||
└────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎮 GAMEPLAY PHASE (Single Level)
|
|
||||||
|
|
||||||
```
|
|
||||||
┌────────────────────────────────────────┐
|
|
||||||
│ LEVEL STARTS │
|
|
||||||
│ Load level data from cache │
|
|
||||||
│ Display image + Clue 1 (FREE) │
|
|
||||||
│ Start 60-second countdown │
|
|
||||||
└──────────────┬─────────────────────────┘
|
|
||||||
│
|
|
||||||
├─────────────────────────────────────┐
|
|
||||||
│ │
|
|
||||||
↓ ↓
|
|
||||||
┌──────────────────┐ ┌──────────────────────┐
|
|
||||||
│ UNLOCK CLUE 2 │ │ SUBMIT ANSWER │
|
|
||||||
│ onUnlockClue(2) │ │ onSubmitAnswer() │
|
|
||||||
│ │ │ │
|
|
||||||
│ Check: hasLives()├──NO──→ │ Compare: │
|
|
||||||
│ │ │ │ input === │
|
|
||||||
│ YES │ │ correctAnswer │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ ↓ │ │ ├──YES──→┐ │
|
|
||||||
│ consumeLife() │ │ │ │ │
|
|
||||||
│ Lives: -1 │ │ │ │ │
|
|
||||||
│ │ │ │ │ │ │
|
|
||||||
│ ↓ │ │ │ ┌┴─────────┐
|
|
||||||
│ Display Clue 2 │ │ │ │ │
|
|
||||||
│ Refresh Label │ │ │ ↓ │
|
|
||||||
│ │ │ │ │ SUCCESS! │
|
|
||||||
│ ↓ │ │ │ showSuccess() │
|
|
||||||
│ Continue Game │ │ │ │ │
|
|
||||||
└──────────────────┘ │ │ ↓ │
|
|
||||||
│ │ │ Play success │
|
|
||||||
│ │ │ sound │
|
|
||||||
↓ │ │ Stop timer │
|
|
||||||
┌──────────────────┐ │ │ addLife() │
|
|
||||||
│ UNLOCK CLUE 3 │ │ │ Lives: +1 │
|
|
||||||
│ onUnlockClue(3) │ │ │ │ │
|
|
||||||
│ │ │ │ ↓ │
|
|
||||||
│ Check: hasLives()├──NO──→ │ │ Show PassModal │
|
|
||||||
│ │ │ │ │ │ │
|
|
||||||
│ YES │ │ │ ├─►[NEXT] │
|
|
||||||
│ │ │ │ │ │ │
|
|
||||||
│ ↓ │ │ │ └─►[SHARE] │
|
|
||||||
│ consumeLife() │ │ │ │
|
|
||||||
│ Lives: -1 │ │ └──NO──────────────┘
|
|
||||||
│ │ │ │ │
|
|
||||||
│ ↓ │ │ ↓
|
|
||||||
│ Display Clue 3 │ │ ERROR!
|
|
||||||
│ Refresh Label │ │ showError()
|
|
||||||
│ │ │ │ │
|
|
||||||
│ ↓ │ │ ↓
|
|
||||||
│ Continue Game │ │ Play fail sound
|
|
||||||
│ │ │ Vibrate long
|
|
||||||
│ │ │ Show toast:
|
|
||||||
│ │ │ "答案错误,
|
|
||||||
└──────────────────┘ │ 再试试吧!"
|
|
||||||
│ │ Lives unchanged
|
|
||||||
│ │ │
|
|
||||||
│ │ ↓
|
|
||||||
│ │ Can retry
|
|
||||||
│ │ (same level)
|
|
||||||
│ │
|
|
||||||
└──────────────────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌──────────────────────┐
|
|
||||||
│ TIME UP? │
|
|
||||||
└──────────────────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌─────────────────────┐
|
|
||||||
│ Play fail sound │
|
|
||||||
│ Stop countdown │
|
|
||||||
│ Can still retry │
|
|
||||||
│ Lives unchanged │
|
|
||||||
└─────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 LIVES TRANSACTION FLOW
|
|
||||||
|
|
||||||
```
|
|
||||||
LEVEL START
|
|
||||||
│
|
|
||||||
┌────────┴─────────┐
|
|
||||||
│ │
|
|
||||||
OPTIONAL MANDATORY
|
|
||||||
(Hints) (Level)
|
|
||||||
│ │
|
|
||||||
┌───────┴────────┐ │
|
|
||||||
│ │ │
|
|
||||||
HINT 2 HINT 3 SUBMISSION
|
|
||||||
-1 Life -1 Life │
|
|
||||||
│ │ │
|
|
||||||
└────────┬───────┴─┬───────┤
|
|
||||||
│ │ │
|
|
||||||
(Spent) (Spent) ANSWER
|
|
||||||
│ │ │
|
|
||||||
└────┬────┴───┬───┘
|
|
||||||
│ │
|
|
||||||
0-2 LIVES SPENT
|
|
||||||
(Depends on choices)
|
|
||||||
│ │
|
|
||||||
┌─────────┼────────┼─────────┐
|
|
||||||
│ │ │ │
|
|
||||||
CORRECT WRONG TIMEOUT ...
|
|
||||||
│ │ │
|
|
||||||
│ │ │
|
|
||||||
+1 LIFE 0 LIVES 0 LIVES
|
|
||||||
│ │ │
|
|
||||||
↓ ↓ ↓
|
|
||||||
┌───────────────────────────────┐
|
|
||||||
│ NEW LIVES BALANCE │
|
|
||||||
│ │
|
|
||||||
│ Formula: │
|
|
||||||
│ newLives = │
|
|
||||||
│ oldLives │
|
|
||||||
│ - (hintsUnlocked × 1) │
|
|
||||||
│ + (if levelWon ? 1 : 0) │
|
|
||||||
│ │
|
|
||||||
│ Examples: │
|
|
||||||
│ 10 - 0 + 1 = 11 (no hints) │
|
|
||||||
│ 10 - 1 + 1 = 10 (1 hint) │
|
|
||||||
│ 10 - 2 + 1 = 9 (2 hints) │
|
|
||||||
│ 10 - 0 + 0 = 10 (retry) │
|
|
||||||
└───────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏆 LEVEL PROGRESSION & PERSISTENCE
|
|
||||||
|
|
||||||
```
|
|
||||||
LEVEL WON
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌────────────────────────────┐
|
|
||||||
│ StorageManager. │
|
|
||||||
│ onLevelCompleted() │
|
|
||||||
│ │
|
|
||||||
│ Takes: levelIndex (0-based) │
|
|
||||||
└────────────┬────────────────┘
|
|
||||||
│
|
|
||||||
┌────────┴────────┐
|
|
||||||
│ │
|
|
||||||
↓ ↓
|
|
||||||
┌────────────┐ ┌──────────────────┐
|
|
||||||
│ currentLevel │ maxUnlocked │
|
|
||||||
│ = N + 1 │ = max(N, current)│
|
|
||||||
└────────────┘ └──────────────────┘
|
|
||||||
│ │
|
|
||||||
└────────┬────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ Save to localStorage: │
|
|
||||||
│ "game_progress" = │
|
|
||||||
│ { │
|
|
||||||
│ currentLevelIndex: N+1, │
|
|
||||||
│ maxUnlockedLevelIndex: N │
|
|
||||||
│ } │
|
|
||||||
└────────┬─────────────────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌──────────────────────────────┐
|
|
||||||
│ NEXT GAME SESSION: │
|
|
||||||
│ Restore from localStorage │
|
|
||||||
│ Resume at Level N+1 │
|
|
||||||
│ Can replay Levels 0 to N │
|
|
||||||
└──────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💾 DATA PERSISTENCE
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────┐
|
|
||||||
│ localStorage (Browser) │
|
|
||||||
├─────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ KEY: "game_lives" │
|
|
||||||
│ VALUE: "10" (string number) │
|
|
||||||
│ Type: String │
|
|
||||||
│ Managed by: StorageManager │
|
|
||||||
│ Accessed by: PageLevel, PassModal │
|
|
||||||
│ │
|
|
||||||
├─────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ KEY: "game_progress" │
|
|
||||||
│ VALUE: JSON string │
|
|
||||||
│ { │
|
|
||||||
│ "currentLevelIndex": 2, │
|
|
||||||
│ "maxUnlockedLevelIndex": 4 │
|
|
||||||
│ } │
|
|
||||||
│ Type: String (JSON) │
|
|
||||||
│ Managed by: StorageManager │
|
|
||||||
│ Accessed by: PageLevel, ViewManager │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌐 API & LEVEL DATA FLOW
|
|
||||||
|
|
||||||
```
|
|
||||||
┌──────────────────────────────────────────┐
|
|
||||||
│ Remote API Server │
|
|
||||||
│ https://ilookai.cn/api/v1/... │
|
|
||||||
│ │
|
|
||||||
│ Returns: Array<ApiLevelData> │
|
|
||||||
│ Fields: id, level, imageUrl, hint1-3, │
|
|
||||||
│ answer, sortOrder │
|
|
||||||
└────────────────┬──────────────────────────┘
|
|
||||||
│
|
|
||||||
↓ (1st app load only)
|
|
||||||
HttpUtil.get()
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌──────────────────────────┐
|
|
||||||
│ LevelDataManager │
|
|
||||||
│ _fetchApiData() │
|
|
||||||
│ │
|
|
||||||
│ Retry: 2 attempts │
|
|
||||||
│ Timeout: 8000ms │
|
|
||||||
└────────┬─────────────────┘
|
|
||||||
│
|
|
||||||
┌────┴────┐
|
|
||||||
│ │
|
|
||||||
FAIL SUCCESS
|
|
||||||
│ │
|
|
||||||
│ ↓
|
|
||||||
│ ┌──────────────────┐
|
|
||||||
│ │ Cache all level │
|
|
||||||
│ │ metadata in │
|
|
||||||
│ │ memory │
|
|
||||||
│ │ (_apiData) │
|
|
||||||
│ └────┬─────────────┘
|
|
||||||
│ │
|
|
||||||
│ ↓
|
|
||||||
│ ┌──────────────────┐
|
|
||||||
│ │ Preload Level 0 │
|
|
||||||
│ │ image │
|
|
||||||
│ │ (_levelConfigs) │
|
|
||||||
│ └────┬─────────────┘
|
|
||||||
│ │
|
|
||||||
└────┬────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌──────────────────────────┐
|
|
||||||
│ PageLevel ready │
|
|
||||||
│ Display first level │
|
|
||||||
└──────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⏰ COUNTDOWN TIMER FLOW
|
|
||||||
|
|
||||||
```
|
|
||||||
┌──────────────────┐
|
|
||||||
│ startCountdown() │
|
|
||||||
│ _countdown = 60 │
|
|
||||||
│ _isTimeUp = false│
|
|
||||||
└────────┬─────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌─────────────────────────┐
|
|
||||||
│ schedule( │
|
|
||||||
│ onCountdownTick, 1 │ ← Every 1 second
|
|
||||||
│ ) │
|
|
||||||
└────────┬────────────────┘
|
|
||||||
│
|
|
||||||
├─────────────────────────────┐
|
|
||||||
│ EVERY SECOND │
|
|
||||||
│ (if _isTimeUp = false) │
|
|
||||||
│ │
|
|
||||||
├─→ _countdown-- │
|
|
||||||
├─→ updateClockLabel() │
|
|
||||||
│ (display "59s", "58s"...) │
|
|
||||||
│ │
|
|
||||||
└────────┬────────────────────┘
|
|
||||||
│
|
|
||||||
├─────────────────────────┐
|
|
||||||
│ │
|
|
||||||
_countdown > 0 _countdown <= 0
|
|
||||||
│ │
|
|
||||||
│ ↓
|
|
||||||
│ _isTimeUp = true
|
|
||||||
│ stopCountdown()
|
|
||||||
│ onTimeUp()
|
|
||||||
│ playFailSound()
|
|
||||||
│ │
|
|
||||||
│ ↓
|
|
||||||
│ Can still submit!
|
|
||||||
│ Lives unchanged
|
|
||||||
│ │
|
|
||||||
└──────────┬──────────────┘
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
┌────────────────┐
|
|
||||||
│ PLAYER ACTION: │
|
|
||||||
│ Submit Answer │
|
|
||||||
└────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📱 WECHAT INTEGRATION POINTS
|
|
||||||
|
|
||||||
```
|
|
||||||
┌──────────────────────────────────────┐
|
|
||||||
│ GAME START (PageHome) │
|
|
||||||
├──────────────────────────────────────┤
|
|
||||||
│ WxSDK.initShare({ │
|
|
||||||
│ title: "写英语", │
|
|
||||||
│ query: "" │
|
|
||||||
│ }) │
|
|
||||||
│ └─► Enable share menu in header │
|
|
||||||
└──────────────────────────────────────┘
|
|
||||||
|
|
||||||
┌──────────────────────────────────────┐
|
|
||||||
│ LEVEL WON (PassModal) │
|
|
||||||
├──────────────────────────────────────┤
|
|
||||||
│ User clicks "Share" │
|
|
||||||
│ WxSDK.shareAppMessage({ │
|
|
||||||
│ title: "快来一起玩...", │
|
|
||||||
│ query: "level=<levelIndex>" │
|
|
||||||
│ }) │
|
|
||||||
│ └─► Opens share dialog │
|
|
||||||
│ with level param │
|
|
||||||
└──────────────────────────────────────┘
|
|
||||||
|
|
||||||
┌──────────────────────────────────────┐
|
|
||||||
│ WRONG ANSWER (PageLevel) │
|
|
||||||
├──────────────────────────────────────┤
|
|
||||||
│ showError() │
|
|
||||||
│ WxSDK.vibrateLong() │
|
|
||||||
│ └─► 400ms vibration feedback │
|
|
||||||
└──────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Complete Player Journey
|
|
||||||
|
|
||||||
```
|
|
||||||
START
|
|
||||||
↓
|
|
||||||
┌─────────────────────┐
|
|
||||||
│ Check localStorage │
|
|
||||||
│ game_lives: 10 │
|
|
||||||
│ game_progress: {0,0}│
|
|
||||||
└──────────┬──────────┘
|
|
||||||
↓
|
|
||||||
┌─────────────────┐
|
|
||||||
│ PageHome │
|
|
||||||
│ Start Button │
|
|
||||||
└──────────┬──────┘
|
|
||||||
↓
|
|
||||||
┌──────────────────────────┐
|
|
||||||
│ PageLevel: LEVEL 1 │
|
|
||||||
│ Lives: 10 │ Answer: __ │
|
|
||||||
│ Clue 1: ✓ (FREE) │
|
|
||||||
│ Clue 2: Unlock? (-1 life)│
|
|
||||||
│ Clue 3: Unlock? (-1 life)│
|
|
||||||
│ ⏱️ 60s countdown... │
|
|
||||||
└──────────┬───────────────┘
|
|
||||||
│
|
|
||||||
┌──────┴──────┬────────────────┐
|
|
||||||
│ │ │
|
|
||||||
UNLOCK SUBMIT TIMEOUT
|
|
||||||
CLUE 2 ANSWER (still ok)
|
|
||||||
-1 Life │
|
|
||||||
│ ├─ CORRECT: +1 Life
|
|
||||||
│ │ ↓
|
|
||||||
│ │ PassModal
|
|
||||||
│ │ ├─ NEXT → Level 2
|
|
||||||
│ │ └─ SHARE → wx.share
|
|
||||||
│ │
|
|
||||||
│ └─ WRONG: Lives stay
|
|
||||||
│ ↓
|
|
||||||
│ Retry same level
|
|
||||||
│
|
|
||||||
└─ UNLOCK
|
|
||||||
CLUE 3
|
|
||||||
-1 Life
|
|
||||||
│
|
|
||||||
↓
|
|
||||||
(Try answer)
|
|
||||||
│
|
|
||||||
├─ CORRECT: +1 Life
|
|
||||||
│ ↓
|
|
||||||
│ PassModal
|
|
||||||
│ └─ NEXT → Level 2
|
|
||||||
│
|
|
||||||
└─ WRONG: Lives stay
|
|
||||||
↓
|
|
||||||
Retry
|
|
||||||
|
|
||||||
PROGRESSION CONTINUES...
|
|
||||||
|
|
||||||
BEAT ALL LEVELS
|
|
||||||
↓
|
|
||||||
Return to PageHome
|
|
||||||
(Save progress in localStorage)
|
|
||||||
↓
|
|
||||||
COMPLETE
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📈 Lives Over Time (Example Scenario)
|
|
||||||
|
|
||||||
```
|
|
||||||
Session 1: No hints used
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
Level 1: 10 Lives → Correct → 11 Lives
|
|
||||||
Level 2: 11 Lives → Correct → 12 Lives
|
|
||||||
Level 3: 12 Lives → Correct → 13 Lives
|
|
||||||
Session 1 ends: 13 Lives saved
|
|
||||||
|
|
||||||
Session 2: Some hints used
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
Start: 13 Lives
|
|
||||||
Level 4: 13 - 1 (hint) + 1 (win) = 13 Lives
|
|
||||||
Level 5: 13 - 2 (hints) + 1 (win) = 12 Lives
|
|
||||||
Level 6: 12 - 0 (no hints) + 1 (win) = 13 Lives
|
|
||||||
Level 7: 13 - 0 (no hints) + 1 (win) = 14 Lives
|
|
||||||
Session 2 ends: 14 Lives saved
|
|
||||||
|
|
||||||
Session 3: Struggling with hints
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
Start: 14 Lives
|
|
||||||
Level 8: 14 - 2 (hints) + 1 (win) = 13 Lives
|
|
||||||
Level 9: 13 - 2 (hints) + 1 (win) = 12 Lives
|
|
||||||
Level 10: 12 - 0 (retry, no hints) + 1 (eventually win) = 13 Lives
|
|
||||||
Session 3 ends: 13 Lives saved
|
|
||||||
|
|
||||||
PATTERN: Lives stay stable or grow over time
|
|
||||||
depending on hint usage
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1,336 +0,0 @@
|
|||||||
# 📚 Game Points/Lives System - Documentation Index
|
|
||||||
|
|
||||||
> Complete analysis of the Cocos Creator WeChat Mini-Game points/score/lives system
|
|
||||||
|
|
||||||
**Generated:** April 5, 2026
|
|
||||||
**Scope:** All 21 TypeScript source files analyzed
|
|
||||||
**Total Documentation:** ~45KB
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📄 Documentation Files
|
|
||||||
|
|
||||||
### 1. **SUMMARY.md** (11 KB) ⭐ **START HERE**
|
|
||||||
**Best for:** High-level overview and executive understanding
|
|
||||||
|
|
||||||
**Contains:**
|
|
||||||
- Executive summary of the lives-based economy
|
|
||||||
- 21 files analyzed (categorized)
|
|
||||||
- Complete points/lives flow table
|
|
||||||
- Data persistence details
|
|
||||||
- Level progression mechanics
|
|
||||||
- Hint system mechanics
|
|
||||||
- Gameplay loop description
|
|
||||||
- API integration overview
|
|
||||||
- WeChat integration features
|
|
||||||
- User journey example
|
|
||||||
- Testing scenarios
|
|
||||||
- Business logic highlights
|
|
||||||
|
|
||||||
**Read this if:** You want a quick understanding of how the entire system works
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. **GAME_ANALYSIS.md** (13 KB)
|
|
||||||
**Best for:** Deep technical analysis of every system component
|
|
||||||
|
|
||||||
**Contains 17 Sections:**
|
|
||||||
1. Project Overview
|
|
||||||
2. Lives/Resource System (complete)
|
|
||||||
3. Level Progression System
|
|
||||||
4. Game Level Data & API
|
|
||||||
5. Gameplay Loop
|
|
||||||
6. Winning & Rewards
|
|
||||||
7. Losing & Consequences
|
|
||||||
8. Hint/Clue System
|
|
||||||
9. Network & API Communication
|
|
||||||
10. WeChat SDK Integration
|
|
||||||
11. Game State Management
|
|
||||||
12. Loading Page Logic
|
|
||||||
13. Complete Points Flow Diagram
|
|
||||||
14. Key Files Summary (table)
|
|
||||||
15. Important Constants
|
|
||||||
16. Missing Features
|
|
||||||
17. Data Flow Summary & Business Logic
|
|
||||||
|
|
||||||
**Read this if:** You need comprehensive technical details on every aspect
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. **QUICK_REFERENCE.md** (5.6 KB)
|
|
||||||
**Best for:** Quick lookup while coding
|
|
||||||
|
|
||||||
**Contains:**
|
|
||||||
- What is the currency? (Lives)
|
|
||||||
- Lives management methods
|
|
||||||
- How lives are spent (table)
|
|
||||||
- How lives are earned (table)
|
|
||||||
- Level progression mechanics
|
|
||||||
- Level data structure (from API)
|
|
||||||
- Gameplay mechanics (time limit, input, conditions)
|
|
||||||
- Rewards & penalties (table)
|
|
||||||
- Economy balance formulas
|
|
||||||
- API integration details
|
|
||||||
- Storage schema
|
|
||||||
- WeChat integration points
|
|
||||||
- Key files list
|
|
||||||
- Important constants
|
|
||||||
- What's NOT implemented
|
|
||||||
|
|
||||||
**Read this if:** You need quick facts/numbers without reading full docs
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. **POINTS_FLOW_DIAGRAM.md** (22 KB)
|
|
||||||
**Best for:** Visual understanding of system flows
|
|
||||||
|
|
||||||
**Contains ASCII Diagrams For:**
|
|
||||||
1. Initialization Phase
|
|
||||||
2. Gameplay Phase (single level)
|
|
||||||
3. Lives Transaction Flow
|
|
||||||
4. Level Progression & Persistence
|
|
||||||
5. Data Persistence (localStorage)
|
|
||||||
6. API & Level Data Flow
|
|
||||||
7. Countdown Timer Flow
|
|
||||||
8. WeChat Integration Points
|
|
||||||
9. Complete Player Journey
|
|
||||||
10. Lives Over Time (example scenario)
|
|
||||||
|
|
||||||
**Read this if:** You prefer visual diagrams over text explanations
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. **POINTS_SYSTEM_INDEX.md** (This File!)
|
|
||||||
**Best for:** Navigation and understanding what exists where
|
|
||||||
|
|
||||||
**Contains:**
|
|
||||||
- Overview of all documentation
|
|
||||||
- Quick navigation by topic
|
|
||||||
- Search guide
|
|
||||||
- Related code file references
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Quick Navigation by Topic
|
|
||||||
|
|
||||||
### I want to understand...
|
|
||||||
|
|
||||||
**The Lives Economy**
|
|
||||||
- → SUMMARY.md → "The Complete Points/Lives Flow"
|
|
||||||
- → QUICK_REFERENCE.md → "Economy Balance"
|
|
||||||
- → GAME_ANALYSIS.md → Section 1 & 2
|
|
||||||
|
|
||||||
**How to Earn Lives**
|
|
||||||
- → SUMMARY.md → "EARNING Lives table"
|
|
||||||
- → QUICK_REFERENCE.md → "How Lives Are Earned"
|
|
||||||
- → POINTS_FLOW_DIAGRAM.md → "Complete Player Journey"
|
|
||||||
|
|
||||||
**How to Spend Lives**
|
|
||||||
- → SUMMARY.md → "SPENDING Lives table"
|
|
||||||
- → QUICK_REFERENCE.md → "How Lives Are Spent"
|
|
||||||
- → GAME_ANALYSIS.md → Section 7 "Hint/Clue System"
|
|
||||||
|
|
||||||
**Level Progression**
|
|
||||||
- → SUMMARY.md → "Level Progression System"
|
|
||||||
- → QUICK_REFERENCE.md → "Level Progression"
|
|
||||||
- → GAME_ANALYSIS.md → Section 2
|
|
||||||
- → POINTS_FLOW_DIAGRAM.md → "Level Progression & Persistence"
|
|
||||||
|
|
||||||
**Data Storage**
|
|
||||||
- → SUMMARY.md → "Data Persistence"
|
|
||||||
- → QUICK_REFERENCE.md → "Storage Schema"
|
|
||||||
- → GAME_ANALYSIS.md → Section 2 "Storage & Persistence"
|
|
||||||
- → POINTS_FLOW_DIAGRAM.md → "Data Persistence"
|
|
||||||
|
|
||||||
**API Integration**
|
|
||||||
- → SUMMARY.md → "API Integration"
|
|
||||||
- → GAME_ANALYSIS.md → Section 3 & 4
|
|
||||||
- → POINTS_FLOW_DIAGRAM.md → "API & Level Data Flow"
|
|
||||||
|
|
||||||
**WeChat Integration**
|
|
||||||
- → SUMMARY.md → "WeChat Integration"
|
|
||||||
- → GAME_ANALYSIS.md → Section 9
|
|
||||||
- → POINTS_FLOW_DIAGRAM.md → "WeChat Integration Points"
|
|
||||||
|
|
||||||
**Complete Gameplay Flow**
|
|
||||||
- → SUMMARY.md → "Gameplay Loop"
|
|
||||||
- → GAME_ANALYSIS.md → Section 4 & 5 & 6
|
|
||||||
- → POINTS_FLOW_DIAGRAM.md → "Gameplay Phase"
|
|
||||||
|
|
||||||
**Testing/Validation**
|
|
||||||
- → SUMMARY.md → "Testing Scenarios"
|
|
||||||
- → QUICK_REFERENCE.md → Check "What's NOT implemented" section
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📖 Code References
|
|
||||||
|
|
||||||
### Core Files & What They Do
|
|
||||||
|
|
||||||
**StorageManager.ts** (Lives + Progress)
|
|
||||||
- `getLives()` / `setLives()` / `consumeLife()` / `addLife()`
|
|
||||||
- `getCurrentLevelIndex()` / `onLevelCompleted()`
|
|
||||||
- Referenced in: GAME_ANALYSIS §2, SUMMARY "Data Persistence"
|
|
||||||
|
|
||||||
**PageLevel.ts** (Main Gameplay)
|
|
||||||
- `onUnlockClue()` / `onSubmitAnswer()` / `showSuccess()` / `showError()`
|
|
||||||
- `startCountdown()` / `onCountdownTick()`
|
|
||||||
- Referenced in: GAME_ANALYSIS §4-7, SUMMARY "Gameplay Loop"
|
|
||||||
|
|
||||||
**LevelDataManager.ts** (API + Caching)
|
|
||||||
- `initialize()` / `ensureLevelReady()` / `preloadNextLevel()`
|
|
||||||
- Referenced in: GAME_ANALYSIS §3, SUMMARY "API Integration"
|
|
||||||
|
|
||||||
**PassModal.ts** (Victory Screen)
|
|
||||||
- Victory UI and rewards display
|
|
||||||
- Referenced in: GAME_ANALYSIS §5
|
|
||||||
|
|
||||||
**WxSDK.ts** (WeChat Integration)
|
|
||||||
- `shareAppMessage()` / `vibrateLong()` / etc.
|
|
||||||
- Referenced in: GAME_ANALYSIS §9
|
|
||||||
|
|
||||||
**ViewManager.ts** (Page Navigation)
|
|
||||||
- Page stack management
|
|
||||||
- Referenced in: GAME_ANALYSIS §10
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔑 Key Numbers & Values
|
|
||||||
|
|
||||||
| Item | Value | Reference |
|
|
||||||
|------|-------|-----------|
|
|
||||||
| Default Lives | 10 | QUICK_REFERENCE, SUMMARY |
|
|
||||||
| Min Lives | 0 | QUICK_REFERENCE, SUMMARY |
|
|
||||||
| Hint Cost | 1 life each | QUICK_REFERENCE, SUMMARY |
|
|
||||||
| Win Reward | 1 life | QUICK_REFERENCE, SUMMARY |
|
|
||||||
| Level Time | 60 seconds | QUICK_REFERENCE, SUMMARY |
|
|
||||||
| API Timeout | 8000ms | QUICK_REFERENCE, GAME_ANALYSIS §3 |
|
|
||||||
| API Retries | 2 attempts | QUICK_REFERENCE, GAME_ANALYSIS §3 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧩 How Systems Interact
|
|
||||||
|
|
||||||
```
|
|
||||||
StorageManager (Lives + Progress)
|
|
||||||
↓
|
|
||||||
PageLevel (Gameplay)
|
|
||||||
├─ Uses Lives for: Hint Unlocks
|
|
||||||
├─ Updates Lives on: Level Complete
|
|
||||||
├─ Uses Progress for: Level Selection
|
|
||||||
└─ Updates Progress on: Level Complete
|
|
||||||
↓
|
|
||||||
LevelDataManager (API + Cache)
|
|
||||||
├─ Fetches: Level Data + Images
|
|
||||||
└─ Serves: Hints + Answers + Images to PageLevel
|
|
||||||
↓
|
|
||||||
WxSDK (WeChat)
|
|
||||||
├─ Shares: Victory with Level Param
|
|
||||||
└─ Vibrates: On Error
|
|
||||||
↓
|
|
||||||
ViewManager (Navigation)
|
|
||||||
└─ Manages: Page Stack + State
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Document Completeness Checklist
|
|
||||||
|
|
||||||
- [x] Lives earning mechanics
|
|
||||||
- [x] Lives spending mechanics
|
|
||||||
- [x] Level progression system
|
|
||||||
- [x] Hint/clue system
|
|
||||||
- [x] API integration
|
|
||||||
- [x] Data persistence
|
|
||||||
- [x] WeChat features
|
|
||||||
- [x] Gameplay loop
|
|
||||||
- [x] Win/lose conditions
|
|
||||||
- [x] User journey examples
|
|
||||||
- [x] Flow diagrams
|
|
||||||
- [x] Code references
|
|
||||||
- [x] Constants & values
|
|
||||||
- [x] Error handling
|
|
||||||
- [x] Performance optimizations
|
|
||||||
- [x] Missing features list
|
|
||||||
- [x] Testing scenarios
|
|
||||||
|
|
||||||
**Coverage:** 100% of points/lives/score system
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Using This Documentation
|
|
||||||
|
|
||||||
### For Understanding
|
|
||||||
1. Start with SUMMARY.md (5 min read)
|
|
||||||
2. Read QUICK_REFERENCE.md (3 min read)
|
|
||||||
3. Review POINTS_FLOW_DIAGRAM.md (5 min read)
|
|
||||||
4. Deep dive into GAME_ANALYSIS.md (15 min read)
|
|
||||||
|
|
||||||
### For Maintenance
|
|
||||||
- QUICK_REFERENCE.md is your quick lookup
|
|
||||||
- GAME_ANALYSIS.md has implementation details
|
|
||||||
- Code references show where logic lives
|
|
||||||
|
|
||||||
### For Modifications
|
|
||||||
- "Data Persistence" section for storage changes
|
|
||||||
- "Lives Transaction Flow" for economy tweaks
|
|
||||||
- "Constants" section for balance adjustments
|
|
||||||
- Individual sections in GAME_ANALYSIS for specific systems
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ❓ FAQ
|
|
||||||
|
|
||||||
**Q: Where is the lives starting value defined?**
|
|
||||||
A: `StorageManager.ts` line 25, `DEFAULT_LIVES = 10`
|
|
||||||
|
|
||||||
**Q: How do players earn lives?**
|
|
||||||
A: By completing levels correctly. See SUMMARY.md "Earning Lives"
|
|
||||||
|
|
||||||
**Q: Can players lose lives?**
|
|
||||||
A: Only by unlocking hints (-1 each). Wrong answers don't penalize. See SUMMARY.md "Spending Lives"
|
|
||||||
|
|
||||||
**Q: Where is progress stored?**
|
|
||||||
A: Browser localStorage under keys "game_lives" and "game_progress". See POINTS_FLOW_DIAGRAM.md "Data Persistence"
|
|
||||||
|
|
||||||
**Q: What happens when time runs out?**
|
|
||||||
A: Game plays fail sound but doesn't end. Players can still submit. See GAME_ANALYSIS.md Section 6
|
|
||||||
|
|
||||||
**Q: How does the hint system work?**
|
|
||||||
A: Hint 1 is free, Hints 2 & 3 cost 1 life each. See GAME_ANALYSIS.md Section 7
|
|
||||||
|
|
||||||
**Q: Is there backend sync?**
|
|
||||||
A: No. Progress is local-only. See SUMMARY.md "Missing Features"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 Document Metadata
|
|
||||||
|
|
||||||
| Property | Value |
|
|
||||||
|----------|-------|
|
|
||||||
| Total Files Analyzed | 21 TypeScript files |
|
|
||||||
| Total Lines of Code | ~2,500 lines |
|
|
||||||
| Documentation Generated | 4 files, ~45KB |
|
|
||||||
| Coverage | Complete (100%) |
|
|
||||||
| Last Updated | April 5, 2026 |
|
|
||||||
| Scope | Points/Lives/Score System |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎓 Summary of Key Takeaways
|
|
||||||
|
|
||||||
1. **Currency:** LIVES (renewable resource), not points
|
|
||||||
2. **Starting:** 10 lives for new players
|
|
||||||
3. **Economy:** +1 life per win, -1 per hint unlock
|
|
||||||
4. **Storage:** localStorage (persistent, survives app close)
|
|
||||||
5. **API:** Fetches level data on app start, cached in memory
|
|
||||||
6. **Progression:** Sequential level unlocking with level 1 always available
|
|
||||||
7. **Strategy:** No penalties for wrong answers, encourages replayability
|
|
||||||
8. **WeChat:** Sharing with level referral parameter
|
|
||||||
9. **Scope:** No backend sync, no authentication, local-only progress
|
|
||||||
10. **Design:** Simple, effective, encourages skill-based progression
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Questions?** All answers are in one of these 4 documentation files!
|
|
||||||
|
|
||||||
@@ -1,347 +0,0 @@
|
|||||||
# mp-xieyingeng 项目完整探索报告
|
|
||||||
|
|
||||||
## 📋 项目概述
|
|
||||||
**项目名称**: 写英语谐音梗小游戏 (mp-xieyingeng)
|
|
||||||
**引擎**: Cocos Creator 3.x (TypeScript)
|
|
||||||
**平台**: 微信小游戏
|
|
||||||
**架构**: 分布式页面管理系统 + 单例工具类
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📁 完整目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
assets/
|
|
||||||
├── main.ts # 主入口脚本,初始化 ViewManager
|
|
||||||
├── PageLoading.ts # 加载页面,处理登录、资源预加载、分享码检测
|
|
||||||
├── prefabs/ # 页面预制体和组件
|
|
||||||
│ ├── PageHome.ts # 首页
|
|
||||||
│ ├── PageLevel.ts # 关卡页面(核心游戏逻辑)
|
|
||||||
│ ├── PageWriteLevels.ts # 写关卡页面(创建/编辑关卡)
|
|
||||||
│ ├── PagePreviewLevels.ts # 预览关卡页面
|
|
||||||
│ ├── PagePKData.ts # 挑战数据页面
|
|
||||||
│ ├── PagePKDetail.ts # 挑战详情页面
|
|
||||||
│ ├── PassModal.ts # 通关弹窗
|
|
||||||
│ └── Toast.ts # Toast 提示组件
|
|
||||||
├── scripts/
|
|
||||||
│ ├── config/
|
|
||||||
│ │ └── ApiConfig.ts # API 配置(端点、超时时间等)
|
|
||||||
│ ├── core/
|
|
||||||
│ │ ├── BaseView.ts # 页面基类(生命周期管理)
|
|
||||||
│ │ └── ViewManager.ts # 页面管理器(单例,栈管理)
|
|
||||||
│ ├── types/
|
|
||||||
│ │ ├── LevelTypes.ts # 关卡数据类型定义
|
|
||||||
│ │ └── ApiTypes.ts # API 响应类型定义
|
|
||||||
│ └── utils/ # 工具类(单例)
|
|
||||||
│ ├── HttpUtil.ts # HTTP 请求工具(GET/POST + JWT 认证)
|
|
||||||
│ ├── ShareManager.ts # 分享管理器(创建分享、加入分享)
|
|
||||||
│ ├── LevelDataManager.ts # 关卡数据管理器(API 拉取、缓存、图片加载)
|
|
||||||
│ ├── UserAssetsManager.ts # 用户资产管理器(积分同步)
|
|
||||||
│ ├── AuthManager.ts # 认证管理器(微信登录、Token 管理)
|
|
||||||
│ ├── StorageManager.ts # 本地存储管理器(进度、积分、Token)
|
|
||||||
│ ├── WxSDK.ts # 微信 SDK 封装(登录、分享、震动等)
|
|
||||||
│ ├── ToastManager.ts # Toast 管理器
|
|
||||||
│ └── [其他工具类...]
|
|
||||||
└── resources/ # 游戏资源
|
|
||||||
├── audios/ # 音效文件
|
|
||||||
├── images/
|
|
||||||
│ ├── level/ # 关卡图片
|
|
||||||
│ ├── pageHome/ # 首页图片
|
|
||||||
│ ├── pageLevel/ # 关卡页面图片
|
|
||||||
│ └── pageLoading/ # 加载页面图片
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 所有 TypeScript 文件列表
|
|
||||||
|
|
||||||
### 核心入口
|
|
||||||
- `assets/main.ts` - 主脚本,注册所有页面到 ViewManager
|
|
||||||
- `assets/PageLoading.ts` - 加载页面,并行执行登录 + 资源加载
|
|
||||||
|
|
||||||
### 页面组件(每个继承 BaseView)
|
|
||||||
- `assets/prefabs/PageHome.ts` - 首页
|
|
||||||
- `assets/prefabs/PageLevel.ts` - **核心游戏逻辑**
|
|
||||||
- `assets/prefabs/PageWriteLevels.ts` - 写关卡
|
|
||||||
- `assets/prefabs/PagePreviewLevels.ts` - 预览关卡
|
|
||||||
- `assets/prefabs/PagePKData.ts` - PK 数据展示
|
|
||||||
- `assets/prefabs/PagePKDetail.ts` - PK 详情
|
|
||||||
- `assets/prefabs/PassModal.ts` - 通关弹窗
|
|
||||||
- `assets/prefabs/Toast.ts` - Toast 提示
|
|
||||||
|
|
||||||
### 核心框架
|
|
||||||
- `assets/scripts/core/BaseView.ts` - 页面基类(onViewLoad、onViewShow、onViewHide、onViewDestroy)
|
|
||||||
- `assets/scripts/core/ViewManager.ts` - 页面管理器(栈管理、缓存、生命周期调用)
|
|
||||||
|
|
||||||
### 配置
|
|
||||||
- `assets/scripts/config/ApiConfig.ts` - API 端点 + 超时配置
|
|
||||||
|
|
||||||
### 类型定义
|
|
||||||
- `assets/scripts/types/ApiTypes.ts` - API 响应类型
|
|
||||||
- `assets/scripts/types/LevelTypes.ts` - 关卡数据类型
|
|
||||||
|
|
||||||
### 工具类(单例)
|
|
||||||
- `assets/scripts/utils/HttpUtil.ts` - **HTTP 请求**(GET/POST + JWT)
|
|
||||||
- `assets/scripts/utils/ShareManager.ts` - **分享系统**
|
|
||||||
- `assets/scripts/utils/LevelDataManager.ts` - **关卡数据管理**
|
|
||||||
- `assets/scripts/utils/UserAssetsManager.ts` - 积分管理
|
|
||||||
- `assets/scripts/utils/AuthManager.ts` - **认证 + 登录**
|
|
||||||
- `assets/scripts/utils/StorageManager.ts` - 本地存储
|
|
||||||
- `assets/scripts/utils/WxSDK.ts` - 微信 SDK 封装
|
|
||||||
- `assets/scripts/utils/ToastManager.ts` - Toast 管理
|
|
||||||
- 其他:RoundedRectMask、BackgroundScaler 等
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💾 关卡通关逻辑核心
|
|
||||||
|
|
||||||
### 1. 通关判定(PageLevel.ts 第 660-673 行)
|
|
||||||
```typescript
|
|
||||||
onSubmitAnswer(): void {
|
|
||||||
const userAnswer = this.getAnswer();
|
|
||||||
if (userAnswer === this._currentConfig.answer) {
|
|
||||||
this.showSuccess();
|
|
||||||
} else {
|
|
||||||
this.showError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 通关奖励(PageLevel.ts 第 679-701 行)
|
|
||||||
```typescript
|
|
||||||
private async showSuccess(): Promise<void> {
|
|
||||||
// 停止倒计时
|
|
||||||
this.stopCountdown();
|
|
||||||
|
|
||||||
// 非分享模式才增加积分
|
|
||||||
if (!this._isShareMode) {
|
|
||||||
const levelId = this._currentConfig?.id;
|
|
||||||
const timeSpent = 60 - this._countdown;
|
|
||||||
await UserAssetsManager.instance.earnPoint(levelId, timeSpent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示通关弹窗
|
|
||||||
this._showPassModal();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 进度保存(PageLevel.ts 第 785-816 行)
|
|
||||||
```typescript
|
|
||||||
private async nextLevel(): Promise<void> {
|
|
||||||
// 非分享模式才保存进度
|
|
||||||
if (!this._isShareMode) {
|
|
||||||
StorageManager.onLevelCompleted(this.currentLevelIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentLevelIndex++;
|
|
||||||
|
|
||||||
// 检查是否全部通关
|
|
||||||
const totalLevels = this._isShareMode
|
|
||||||
? ShareManager.instance.getShareLevelCount()
|
|
||||||
: LevelDataManager.instance.getLevelCount();
|
|
||||||
|
|
||||||
if (this.currentLevelIndex >= totalLevels) {
|
|
||||||
// 全部通关,返回首页
|
|
||||||
ViewManager.instance.back();
|
|
||||||
} else {
|
|
||||||
// 加载下一关
|
|
||||||
await this.initLevel();
|
|
||||||
this.startCountdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 已通关关卡同步(PageLoading.ts 第 115-139 行)
|
|
||||||
```typescript
|
|
||||||
private _syncProgressFromServer(): void {
|
|
||||||
// 服务端返回的已通关关卡 ID
|
|
||||||
const completedIds = AuthManager.instance.completedLevelIds;
|
|
||||||
|
|
||||||
// 转换为本地索引
|
|
||||||
const maxCompletedIndex = LevelDataManager.instance.getMaxCompletedIndex(completedIds);
|
|
||||||
|
|
||||||
// 取较大值,防止进度回退
|
|
||||||
if (maxCompletedIndex > localMax) {
|
|
||||||
StorageManager.onLevelCompleted(maxCompletedIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 API 端点一览
|
|
||||||
|
|
||||||
### 已配置的 API(ApiConfig.ts)
|
|
||||||
```
|
|
||||||
API_BASE = 'https://ilookai.cn/api/v1'
|
|
||||||
|
|
||||||
端点:
|
|
||||||
- POST /auth/wx-login # 微信登录
|
|
||||||
- GET /user/assets # 获取用户积分
|
|
||||||
- POST /user/assets/consume # 消耗积分(解锁线索)
|
|
||||||
- POST /user/assets/earn # 获得积分(通关奖励)
|
|
||||||
- GET /user/game-data # 获取用户数据(进度 + 积分)
|
|
||||||
- GET /wechat-game/levels # 获取所有关卡
|
|
||||||
- POST /share # 创建分享
|
|
||||||
- POST /share/{code}/join # 加入分享
|
|
||||||
- GET /user/info # 获取用户信息
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🏗️ 架构特点
|
|
||||||
|
|
||||||
### 1. 单例模式
|
|
||||||
- `ViewManager` - 页面管理
|
|
||||||
- `LevelDataManager` - 关卡数据
|
|
||||||
- `ShareManager` - 分享管理
|
|
||||||
- `UserAssetsManager` - 积分管理
|
|
||||||
- `AuthManager` - 认证
|
|
||||||
- `StorageManager` - 本地存储(全静态)
|
|
||||||
- `ToastManager` - Toast 管理
|
|
||||||
- `WxSDK` - 微信 SDK(全静态)
|
|
||||||
- `HttpUtil` - HTTP 工具(全静态)
|
|
||||||
|
|
||||||
### 2. 页面栈管理
|
|
||||||
- `ViewManager` 维护页面栈
|
|
||||||
- `open()` - 打开页面,压栈
|
|
||||||
- `back()` - 返回上一页,出栈
|
|
||||||
- `replace()` - 替换当前页,不压栈
|
|
||||||
|
|
||||||
### 3. 生命周期
|
|
||||||
每个页面 4 个阶段:
|
|
||||||
- `onViewLoad()` - 首次创建时调用
|
|
||||||
- `onViewShow()` - 每次显示时调用
|
|
||||||
- `onViewHide()` - 隐藏时调用
|
|
||||||
- `onViewDestroy()` - 销毁时调用
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 关键发现
|
|
||||||
|
|
||||||
### ✅ 已有的工具类
|
|
||||||
|
|
||||||
#### HTTP 请求
|
|
||||||
- **HttpUtil.ts** - GET/POST + JWT 认证
|
|
||||||
- 支持自定义超时时间
|
|
||||||
- 自动添加 Authorization 头
|
|
||||||
- 泛型支持
|
|
||||||
|
|
||||||
#### 数据管理
|
|
||||||
- **LevelDataManager.ts** - 关卡数据 + 图片缓存
|
|
||||||
- API 请求重试机制
|
|
||||||
- 图片懒加载(预加载下一关)
|
|
||||||
- URL -> SpriteFrame 缓存
|
|
||||||
|
|
||||||
- **UserAssetsManager.ts** - 积分管理
|
|
||||||
- 消耗积分(解锁线索)
|
|
||||||
- 获得积分(通关奖励)
|
|
||||||
- 自动降级本地处理
|
|
||||||
|
|
||||||
- **AuthManager.ts** - 认证 + 登录
|
|
||||||
- 微信登录流程
|
|
||||||
- Token 恢复与验证
|
|
||||||
- 获取通关进度
|
|
||||||
|
|
||||||
- **StorageManager.ts** - 本地存储
|
|
||||||
- 积分、Token、进度、用户信息
|
|
||||||
- 全静态工具类
|
|
||||||
|
|
||||||
#### 游戏逻辑
|
|
||||||
- **ShareManager.ts** - 分享系统
|
|
||||||
- 创建分享、加入分享
|
|
||||||
- 独立数据管理,不影响正常进度
|
|
||||||
|
|
||||||
- **ViewManager.ts** - 页面管理
|
|
||||||
- 栈管理
|
|
||||||
- 缓存机制
|
|
||||||
- 生命周期管理
|
|
||||||
|
|
||||||
- **WxSDK.ts** - 微信 API 封装
|
|
||||||
- 登录、分享、震动
|
|
||||||
- 隐私授权、用户信息
|
|
||||||
- 非微信环境自动降级
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 游戏流程图
|
|
||||||
|
|
||||||
### 正常模式
|
|
||||||
```
|
|
||||||
启动 → PageLoading
|
|
||||||
├─ 并行加载:登录 + 关卡数据
|
|
||||||
├─ 检测分享码(无)
|
|
||||||
└─ 打开 PageHome
|
|
||||||
├─ 开始游戏 → PageLevel
|
|
||||||
│ ├─ 加载关卡
|
|
||||||
│ ├─ 倒计时 60s
|
|
||||||
│ ├─ 提交答案
|
|
||||||
│ ├─ 判定成功/失败
|
|
||||||
│ ├─ 通关 → PassModal
|
|
||||||
│ │ ├─ earnPoint()(加积分)
|
|
||||||
│ │ ├─ onLevelCompleted()(保存进度)
|
|
||||||
│ │ └─ nextLevel()
|
|
||||||
│ └─ 重复 2-7
|
|
||||||
└─ PK → PageWriteLevels
|
|
||||||
```
|
|
||||||
|
|
||||||
### 分享模式
|
|
||||||
```
|
|
||||||
微信分享链接(含 shareCode)
|
|
||||||
↓
|
|
||||||
PageLoading
|
|
||||||
├─ 检测到分享码
|
|
||||||
└─ ShareManager.joinShare(code)
|
|
||||||
↓
|
|
||||||
PageLevel(shareMode=true)
|
|
||||||
├─ 从 ShareManager 加载关卡
|
|
||||||
├─ 不增加积分
|
|
||||||
├─ 不保存本地进度
|
|
||||||
└─ 全部通关 → 返回首页
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 核心要点
|
|
||||||
|
|
||||||
1. **HTTP 工具** ✅
|
|
||||||
- HttpUtil.ts 已完整实现
|
|
||||||
- 支持 JWT 认证
|
|
||||||
- 可配置超时
|
|
||||||
|
|
||||||
2. **关卡数据** ✅
|
|
||||||
- LevelDataManager 从 API 拉取
|
|
||||||
- 支持图片缓存 + 懒加载
|
|
||||||
- 支持重试机制
|
|
||||||
|
|
||||||
3. **通关逻辑** ✅
|
|
||||||
- 判定:字符串比对(PageLevel.ts:660)
|
|
||||||
- 奖励:earnPoint()(PageLevel.ts:679)
|
|
||||||
- 进度:StorageManager.onLevelCompleted()(PageLevel.ts:785)
|
|
||||||
- 服务端同步:PageLoading.ts:115
|
|
||||||
|
|
||||||
4. **分享系统** ✅
|
|
||||||
- 创建 + 加入完全独立
|
|
||||||
- 不影响正常游戏进度
|
|
||||||
- 懒加载关卡数据
|
|
||||||
|
|
||||||
5. **页面管理** ✅
|
|
||||||
- ViewManager 栈管理
|
|
||||||
- 4 个生命周期回调
|
|
||||||
- 缓存机制
|
|
||||||
|
|
||||||
6. **认证系统** ✅
|
|
||||||
- 微信登录 + Token 恢复
|
|
||||||
- 自动添加授权头
|
|
||||||
- 获取用户通关记录
|
|
||||||
|
|
||||||
7. **本地存储** ✅
|
|
||||||
- StorageManager 集中管理
|
|
||||||
- 支持进度 + 积分 + Token
|
|
||||||
- 带有默认值和数据校验
|
|
||||||
|
|
||||||
8. **微信 API** ✅
|
|
||||||
- WxSDK 完整封装
|
|
||||||
- 非微信环境自动降级
|
|
||||||
- 支持分享、登录、震动等
|
|
||||||
|
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
# 快速文件参考指南
|
|
||||||
|
|
||||||
## 🚀 最重要的 5 个文件
|
|
||||||
|
|
||||||
### 1. **PageLevel.ts** - 核心游戏逻辑
|
|
||||||
位置:`assets/prefabs/PageLevel.ts`
|
|
||||||
```
|
|
||||||
关键方法:
|
|
||||||
- onViewLoad() → 初始化关卡
|
|
||||||
- onSubmitAnswer() → 第 660 行,提交答案判定
|
|
||||||
- showSuccess() → 第 679 行,通关逻辑
|
|
||||||
- nextLevel() → 第 785 行,进度保存
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. **HttpUtil.ts** - HTTP 请求工具
|
|
||||||
位置:`assets/scripts/utils/HttpUtil.ts`
|
|
||||||
```
|
|
||||||
关键方法:
|
|
||||||
- get<T>(url, timeout) → GET 请求
|
|
||||||
- post<T>(url, data, timeout) → POST 请求
|
|
||||||
- setAuthToken(token) → 设置 JWT
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. **LevelDataManager.ts** - 关卡数据管理
|
|
||||||
位置:`assets/scripts/utils/LevelDataManager.ts`
|
|
||||||
```
|
|
||||||
关键方法:
|
|
||||||
- initialize(onProgress) → API 加载 + 预加载第一关
|
|
||||||
- ensureLevelReady(index) → 按需加载关卡
|
|
||||||
- preloadNextLevel(index) → 静默预加载下一关
|
|
||||||
- getMaxCompletedIndex(ids) → 获取已通关索引
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. **ShareManager.ts** - 分享系统
|
|
||||||
位置:`assets/scripts/utils/ShareManager.ts`
|
|
||||||
```
|
|
||||||
关键方法:
|
|
||||||
- createShare(title, levelIds) → 创建分享
|
|
||||||
- joinShare(code) → 加入分享
|
|
||||||
- triggerWxShare(title, code) → 触发分享
|
|
||||||
- isShareMode → 判断是否分享模式
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. **AuthManager.ts** - 认证管理
|
|
||||||
位置:`assets/scripts/utils/AuthManager.ts`
|
|
||||||
```
|
|
||||||
关键方法:
|
|
||||||
- initialize() → 初始化(恢复 token 或微信登录)
|
|
||||||
- wxLogin() → 微信登录
|
|
||||||
- validateToken() → 验证 token 有效性
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 TypeScript 文件快速导航
|
|
||||||
|
|
||||||
### 文件位置速查表
|
|
||||||
|
|
||||||
| 文件名 | 路径 | 用途 |
|
|
||||||
|------|------|------|
|
|
||||||
| main.ts | assets/ | 主入口,初始化 ViewManager |
|
|
||||||
| PageLoading.ts | assets/ | 加载页面,登录 + 资源加载 |
|
|
||||||
| PageHome.ts | assets/prefabs/ | 首页 |
|
|
||||||
| PageLevel.ts | assets/prefabs/ | 关卡页面 **⭐** |
|
|
||||||
| PageWriteLevels.ts | assets/prefabs/ | 写关卡页面 |
|
|
||||||
| PagePreviewLevels.ts | assets/prefabs/ | 预览关卡 |
|
|
||||||
| PassModal.ts | assets/prefabs/ | 通关弹窗 |
|
|
||||||
| Toast.ts | assets/prefabs/ | Toast 提示 |
|
|
||||||
| BaseView.ts | assets/scripts/core/ | 页面基类 |
|
|
||||||
| ViewManager.ts | assets/scripts/core/ | 页面管理器 |
|
|
||||||
| ApiConfig.ts | assets/scripts/config/ | API 配置 |
|
|
||||||
| ApiTypes.ts | assets/scripts/types/ | API 类型定义 |
|
|
||||||
| LevelTypes.ts | assets/scripts/types/ | 关卡类型定义 |
|
|
||||||
| HttpUtil.ts | assets/scripts/utils/ | HTTP 工具 **⭐** |
|
|
||||||
| ShareManager.ts | assets/scripts/utils/ | 分享管理 **⭐** |
|
|
||||||
| LevelDataManager.ts | assets/scripts/utils/ | 关卡数据 **⭐** |
|
|
||||||
| UserAssetsManager.ts | assets/scripts/utils/ | 积分管理 |
|
|
||||||
| AuthManager.ts | assets/scripts/utils/ | 认证管理 **⭐** |
|
|
||||||
| StorageManager.ts | assets/scripts/utils/ | 本地存储 |
|
|
||||||
| WxSDK.ts | assets/scripts/utils/ | 微信 SDK |
|
|
||||||
| ToastManager.ts | assets/scripts/utils/ | Toast 管理 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 API 端点速查
|
|
||||||
|
|
||||||
```
|
|
||||||
基础地址:https://ilookai.cn/api/v1
|
|
||||||
|
|
||||||
认证相关:
|
|
||||||
- POST /auth/wx-login 微信登录
|
|
||||||
|
|
||||||
用户资产:
|
|
||||||
- GET /user/assets 获取积分
|
|
||||||
- POST /user/assets/consume 消耗积分(解锁线索)
|
|
||||||
- POST /user/assets/earn 获得积分(通关)
|
|
||||||
- GET /user/game-data 获取用户数据
|
|
||||||
|
|
||||||
关卡相关:
|
|
||||||
- GET /wechat-game/levels 获取所有关卡
|
|
||||||
|
|
||||||
分享相关:
|
|
||||||
- POST /share 创建分享
|
|
||||||
- POST /share/{code}/join 加入分享
|
|
||||||
|
|
||||||
用户相关:
|
|
||||||
- GET /user/info 获取用户信息
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💾 关键数据结构
|
|
||||||
|
|
||||||
### 关卡配置
|
|
||||||
```typescript
|
|
||||||
interface RuntimeLevelConfig {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
spriteFrame: SpriteFrame | null;
|
|
||||||
clue1: string;
|
|
||||||
clue2: string;
|
|
||||||
clue3: string;
|
|
||||||
answer: string;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### API 响应
|
|
||||||
```typescript
|
|
||||||
interface ApiEnvelope<T> {
|
|
||||||
success: boolean;
|
|
||||||
data: T | null;
|
|
||||||
message: string | null;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 用户进度
|
|
||||||
```typescript
|
|
||||||
interface UserProgress {
|
|
||||||
currentLevelIndex: number; // 当前关卡(0-based)
|
|
||||||
maxUnlockedLevelIndex: number; // 最高已解锁
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎮 游戏流程关键代码位置
|
|
||||||
|
|
||||||
| 步骤 | 文件 | 行数 | 描述 |
|
|
||||||
|-----|------|------|------|
|
|
||||||
| 初始化 | main.ts | 34-90 | 注册页面 |
|
|
||||||
| 加载 | PageLoading.ts | 27-90 | 并行登录 + 加载关卡 |
|
|
||||||
| 分享检测 | PageLoading.ts | 61-77 | 检测分享码 |
|
|
||||||
| 进度同步 | PageLoading.ts | 115-139 | 服务端进度同步 |
|
|
||||||
| 加载关卡 | PageLevel.ts | 175-197 | 初始化关卡 |
|
|
||||||
| 倒计时 | PageLevel.ts | 593-641 | 60 秒计时 |
|
|
||||||
| 提交答案 | PageLevel.ts | 660-673 | 判定答案 |
|
|
||||||
| 通关处理 | PageLevel.ts | 679-701 | 播放音效 + 加积分 + 弹窗 |
|
|
||||||
| 进度保存 | PageLevel.ts | 785-816 | 下一关 + 进度保存 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 工具类单例调用方式
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// HTTP 请求
|
|
||||||
HttpUtil.get<T>(url, timeout)
|
|
||||||
HttpUtil.post<T>(url, data, timeout)
|
|
||||||
HttpUtil.setAuthToken(token)
|
|
||||||
|
|
||||||
// 关卡数据
|
|
||||||
LevelDataManager.instance.initialize(onProgress)
|
|
||||||
LevelDataManager.instance.ensureLevelReady(index)
|
|
||||||
LevelDataManager.instance.getLevelCount()
|
|
||||||
|
|
||||||
// 用户资产
|
|
||||||
UserAssetsManager.instance.fetchPoints()
|
|
||||||
UserAssetsManager.instance.consumePoint(levelId, hintIndex)
|
|
||||||
UserAssetsManager.instance.earnPoint(levelId, timeSpent)
|
|
||||||
|
|
||||||
// 认证
|
|
||||||
AuthManager.instance.initialize()
|
|
||||||
AuthManager.instance.isLoggedIn
|
|
||||||
AuthManager.instance.userId
|
|
||||||
|
|
||||||
// 本地存储
|
|
||||||
StorageManager.getPoints()
|
|
||||||
StorageManager.setPoints(points)
|
|
||||||
StorageManager.getCurrentLevelIndex()
|
|
||||||
StorageManager.onLevelCompleted(index)
|
|
||||||
|
|
||||||
// 分享
|
|
||||||
ShareManager.instance.createShare(title, levelIds)
|
|
||||||
ShareManager.instance.joinShare(code)
|
|
||||||
ShareManager.instance.isShareMode
|
|
||||||
|
|
||||||
// 微信 API
|
|
||||||
WxSDK.isWechat()
|
|
||||||
WxSDK.login()
|
|
||||||
WxSDK.shareAppMessage(config)
|
|
||||||
|
|
||||||
// 页面管理
|
|
||||||
ViewManager.instance.open(viewId, options)
|
|
||||||
ViewManager.instance.back()
|
|
||||||
ViewManager.instance.replace(viewId, options)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 优先级指南(修改时参考)
|
|
||||||
|
|
||||||
### 优先级 A(核心,谨慎修改)
|
|
||||||
- `PageLevel.ts` - 游戏逻辑
|
|
||||||
- `HttpUtil.ts` - HTTP 请求
|
|
||||||
- `LevelDataManager.ts` - 数据加载
|
|
||||||
- `ViewManager.ts` - 页面管理
|
|
||||||
|
|
||||||
### 优先级 B(重要)
|
|
||||||
- `ShareManager.ts` - 分享系统
|
|
||||||
- `AuthManager.ts` - 认证系统
|
|
||||||
- `StorageManager.ts` - 本地存储
|
|
||||||
- `UserAssetsManager.ts` - 积分管理
|
|
||||||
|
|
||||||
### 优先级 C(可选)
|
|
||||||
- `WxSDK.ts` - 微信 API
|
|
||||||
- `ToastManager.ts` - 提示管理
|
|
||||||
- 其他 UI 文件
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 常见修改清单
|
|
||||||
|
|
||||||
### 修改 API 端点
|
|
||||||
→ `assets/scripts/config/ApiConfig.ts`
|
|
||||||
|
|
||||||
### 修改通关逻辑
|
|
||||||
→ `assets/prefabs/PageLevel.ts`(第 660-816 行)
|
|
||||||
|
|
||||||
### 修改关卡数据加载
|
|
||||||
→ `assets/scripts/utils/LevelDataManager.ts`
|
|
||||||
|
|
||||||
### 修改积分系统
|
|
||||||
→ `assets/scripts/utils/UserAssetsManager.ts`
|
|
||||||
|
|
||||||
### 修改分享流程
|
|
||||||
→ `assets/scripts/utils/ShareManager.ts`
|
|
||||||
|
|
||||||
### 修改页面流转
|
|
||||||
→ `assets/scripts/core/ViewManager.ts`
|
|
||||||
|
|
||||||
### 修改本地存储
|
|
||||||
→ `assets/scripts/utils/StorageManager.ts`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 快速查找
|
|
||||||
|
|
||||||
**如果要找 xxx 功能:**
|
|
||||||
|
|
||||||
| 功能 | 查看 |
|
|
||||||
|-----|------|
|
|
||||||
| HTTP 请求 | HttpUtil.ts |
|
|
||||||
| 关卡加载 | LevelDataManager.ts |
|
|
||||||
| 通关判定 | PageLevel.ts:660 |
|
|
||||||
| 通关奖励 | PageLevel.ts:679 |
|
|
||||||
| 进度保存 | PageLevel.ts:785 |
|
|
||||||
| 分享功能 | ShareManager.ts |
|
|
||||||
| 登录流程 | AuthManager.ts |
|
|
||||||
| 本地数据 | StorageManager.ts |
|
|
||||||
| 页面跳转 | ViewManager.ts |
|
|
||||||
| 微信功能 | WxSDK.ts |
|
|
||||||
| Toast 提示 | ToastManager.ts |
|
|
||||||
|
|
||||||
@@ -1,348 +0,0 @@
|
|||||||
# UI Components - Quick Reference Guide
|
|
||||||
|
|
||||||
## Component Overview
|
|
||||||
|
|
||||||
| Component | Purpose | Extends | Key Responsibilities |
|
|
||||||
|-----------|---------|---------|----------------------|
|
|
||||||
| **main.ts** | App bootstrap | Component | Register pages, init ViewManager & ToastManager |
|
|
||||||
| **PageLoading.ts** | Splash screen | Component | Load data, sync progress, detect share code |
|
|
||||||
| **PageHome.ts** | Landing page | BaseView | Navigation hub (game/PK buttons) |
|
|
||||||
| **PageLevel.ts** | Game level | BaseView | Core gameplay (timer, hints, scoring, input) |
|
|
||||||
| **PagePreviewLevels.ts** | Level preview | BaseView | Scrollable list of selected levels |
|
|
||||||
| **PassModal.ts** | Completion modal | BaseView | Next level & share buttons, success sound |
|
|
||||||
| **Toast.ts** | Notification | Component | Display message with fade animation |
|
|
||||||
| **ToastManager.ts** | Toast system | Singleton | Centralized toast creation & display |
|
|
||||||
| **BaseView.ts** | Page base class | Component | Lifecycle interface for all pages |
|
|
||||||
| **ViewManager.ts** | Page manager | Singleton | Navigation, stacking, caching, lifecycle |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Lifecycle Stages
|
|
||||||
|
|
||||||
### Page Lifecycle (BaseView)
|
|
||||||
```
|
|
||||||
onViewLoad() → onViewShow() → onViewHide() → onViewDestroy()
|
|
||||||
(once) (each show) (each hide) (on destroy)
|
|
||||||
```
|
|
||||||
|
|
||||||
### App Startup Flow
|
|
||||||
```
|
|
||||||
main.onLoad()
|
|
||||||
↓ (Initialize ViewManager + register pages)
|
|
||||||
PageLoading.start()
|
|
||||||
↓ (Load auth + levels in parallel, check share code)
|
|
||||||
PageHome (normal) OR PageLevel (share mode)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Data Flows
|
|
||||||
|
|
||||||
### Level Progression
|
|
||||||
```
|
|
||||||
PageLevel loads config → Displays image + clue1 → User enters answer
|
|
||||||
↓ (correct) → Earn points → Show PassModal → Next level
|
|
||||||
↓ (wrong) → Show toast → Continue playing
|
|
||||||
↓ (timeout) → Play fail sound
|
|
||||||
```
|
|
||||||
|
|
||||||
### Hint Unlocking
|
|
||||||
```
|
|
||||||
User clicks unlock button → Check points available
|
|
||||||
↓ (yes) → Consume point from UserAssetsManager
|
|
||||||
↓ → Hide unlock button, show clue
|
|
||||||
↓ (no) → Show "insufficient points" toast
|
|
||||||
```
|
|
||||||
|
|
||||||
### Share Challenge Mode
|
|
||||||
```
|
|
||||||
WeChat link → PageLoading detects share code
|
|
||||||
↓ → ShareManager.joinShare(code)
|
|
||||||
↓ → Play through shared levels (doesn't save local progress)
|
|
||||||
↓ → Report progress to server
|
|
||||||
↓ → Return to PageHome
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Component Properties Summary
|
|
||||||
|
|
||||||
### PageLevel (Most Complex)
|
|
||||||
**UI Elements:**
|
|
||||||
- inputLayout, submitButton, inputTemplate, actionNode
|
|
||||||
- iconSetting (back button)
|
|
||||||
- tipsLayout, tipsItem1/2/3 (clues)
|
|
||||||
- unLockItem2/3 (unlock buttons)
|
|
||||||
- clockLabel (timer), liveLabel (points)
|
|
||||||
- mainImage (level image)
|
|
||||||
|
|
||||||
**Audio:**
|
|
||||||
- clickAudio, successAudio, failAudio
|
|
||||||
|
|
||||||
**Internal State:**
|
|
||||||
- _countdown (60 sec timer)
|
|
||||||
- _isTimeUp (timer expired flag)
|
|
||||||
- _currentConfig (level data)
|
|
||||||
- _isTransitioning (prevent double-submit)
|
|
||||||
- _isUnlocking (prevent double-click unlock)
|
|
||||||
- _passModalNode (modal reference)
|
|
||||||
- _isShareMode (shared vs normal)
|
|
||||||
|
|
||||||
**Key Methods:**
|
|
||||||
- onViewLoad/Show/Hide/Destroy (lifecycle)
|
|
||||||
- initLevel() (async load config)
|
|
||||||
- createSingleInput(length) (input box)
|
|
||||||
- onUnlockClue(index) (consume points for hints)
|
|
||||||
- onSubmitAnswer() (check answer)
|
|
||||||
- showSuccess() (correct: earn points, show modal)
|
|
||||||
- showError() (wrong: toast + vibration)
|
|
||||||
- nextLevel() (progress to next)
|
|
||||||
- startCountdown() / onCountdownTick() (60s timer)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Points & Scoring System
|
|
||||||
|
|
||||||
**Earning Points:**
|
|
||||||
- `UserAssetsManager.earnPoint(levelId, timeSpent)`
|
|
||||||
- Called in PageLevel.showSuccess()
|
|
||||||
- Time spent = 60 - countdown
|
|
||||||
|
|
||||||
**Consuming Points:**
|
|
||||||
- `UserAssetsManager.consumePoint(levelId, hintIndex)`
|
|
||||||
- Called in PageLevel.onUnlockClue()
|
|
||||||
- Check `StorageManager.hasPoints()` before consuming
|
|
||||||
|
|
||||||
**Displaying Points:**
|
|
||||||
- `StorageManager.getPoints()` → Display as "x {points}"
|
|
||||||
- Called in PageLevel.updatePointsLabel()
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Timer System
|
|
||||||
|
|
||||||
**60-Second Countdown:**
|
|
||||||
- Starts when level loads: `startCountdown()`
|
|
||||||
- Ticks every 1 second: `onCountdownTick()`
|
|
||||||
- Displayed as: "60s", "59s", ..., "0s"
|
|
||||||
- On timeout: plays fail sound, doesn't end game
|
|
||||||
|
|
||||||
**Stop Timer:**
|
|
||||||
- `stopCountdown()` called when:
|
|
||||||
- Answer submitted (correct)
|
|
||||||
- Page destroyed
|
|
||||||
- All levels completed
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Hint/Clue System
|
|
||||||
|
|
||||||
**3 Clues Per Level:**
|
|
||||||
1. **Clue 1** - Always visible (free)
|
|
||||||
2. **Clue 2** - Unlock button, costs points
|
|
||||||
3. **Clue 3** - Unlock button, costs points
|
|
||||||
|
|
||||||
**Display:**
|
|
||||||
- Text in tipsItem1/2/3 nodes
|
|
||||||
- Hidden if locked (tipsItem.active = false)
|
|
||||||
- Unlock button visible if locked
|
|
||||||
|
|
||||||
**Unlock Flow:**
|
|
||||||
1. User clicks unLockItem2 or unLockItem3
|
|
||||||
2. Check points: `StorageManager.hasPoints()`
|
|
||||||
3. Consume: `UserAssetsManager.consumePoint(levelId, index)`
|
|
||||||
4. Hide button, show clue, update UI
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Navigation Stack
|
|
||||||
|
|
||||||
**Structure:**
|
|
||||||
- LIFO stack managed by ViewManager
|
|
||||||
- Each open() adds to stack
|
|
||||||
- back() pops from stack
|
|
||||||
- replace() swaps top
|
|
||||||
|
|
||||||
**Example Session:**
|
|
||||||
```
|
|
||||||
[PageHome]
|
|
||||||
↓ open PageLevel
|
|
||||||
[PageHome, PageLevel]
|
|
||||||
↓ open PassModal (or inline)
|
|
||||||
[PageHome, PageLevel, PassModal?]
|
|
||||||
↓ close/back
|
|
||||||
[PageHome]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Methods:**
|
|
||||||
- `ViewManager.open(viewId, options?)` - Push to stack
|
|
||||||
- `ViewManager.back()` - Pop from stack, show previous
|
|
||||||
- `ViewManager.replace(viewId, options?)` - Pop current, push new
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Caching Strategy
|
|
||||||
|
|
||||||
**Cached Views (default):**
|
|
||||||
- Instance reused on re-open
|
|
||||||
- onViewLoad() called once
|
|
||||||
- onViewShow() called each time
|
|
||||||
- Memory persists
|
|
||||||
|
|
||||||
**Non-Cached Views:**
|
|
||||||
- New instance each time
|
|
||||||
- onViewLoad() called each time
|
|
||||||
- Memory released on close
|
|
||||||
|
|
||||||
**Configuration:**
|
|
||||||
```typescript
|
|
||||||
// In main.ts registration
|
|
||||||
ViewManager.instance.register('PageHome', {
|
|
||||||
prefab: pageHomePrefab,
|
|
||||||
cache: true, // ← Reuse instance
|
|
||||||
zIndex: 0 // ← Layer depth
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Toast System
|
|
||||||
|
|
||||||
**Show Toast:**
|
|
||||||
```typescript
|
|
||||||
ToastManager.show("消息内容", 2000); // duration in ms
|
|
||||||
```
|
|
||||||
|
|
||||||
**Initialization (main.ts):**
|
|
||||||
```typescript
|
|
||||||
ToastManager.instance.init(toastPrefab, canvasNode);
|
|
||||||
```
|
|
||||||
|
|
||||||
**Toast Behavior:**
|
|
||||||
- Creates Toast instance from prefab
|
|
||||||
- Displays for duration (default 2000ms)
|
|
||||||
- Fades out over 300ms
|
|
||||||
- Auto-destroys
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## WeChat Integration
|
|
||||||
|
|
||||||
**Share Initialization (PageHome):**
|
|
||||||
```typescript
|
|
||||||
WxSDK.initShare({
|
|
||||||
title: '写英语',
|
|
||||||
imageUrl: '',
|
|
||||||
query: ''
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
**Share in Challenge (PassModal):**
|
|
||||||
```typescript
|
|
||||||
WxSDK.shareAppMessage({
|
|
||||||
title: '快来一起玩这款游戏吧',
|
|
||||||
query: `level={levelIndex}`
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
**Share Code Detection (PageLoading):**
|
|
||||||
```typescript
|
|
||||||
const shareCode = WxSDK.getShareCodeFromLaunch();
|
|
||||||
if (shareCode) {
|
|
||||||
const joined = await ShareManager.instance.joinShare(shareCode);
|
|
||||||
// Launch PageLevel in share mode
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Other WeChat Features:**
|
|
||||||
- `WxSDK.vibrateLong()` - Haptic feedback on wrong answer
|
|
||||||
- `WxSDK.isWechat()` - Check if running in WeChat
|
|
||||||
- `checkPrivacySetting()` - Check privacy authorization
|
|
||||||
- `requirePrivacyAuthorize()` - Prompt for privacy consent
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Error Handling & Edge Cases
|
|
||||||
|
|
||||||
**Level Loading:**
|
|
||||||
- Try cache first, then async load
|
|
||||||
- Preload next level without blocking
|
|
||||||
- Handle missing config gracefully
|
|
||||||
|
|
||||||
**Point Consumption:**
|
|
||||||
- Check availability before consuming
|
|
||||||
- Show toast if insufficient
|
|
||||||
- Prevent double-click with flag
|
|
||||||
|
|
||||||
**Answer Submission:**
|
|
||||||
- Prevent multiple submissions with transition flag
|
|
||||||
- Trim whitespace from answer
|
|
||||||
- Case-sensitive comparison
|
|
||||||
|
|
||||||
**Page Navigation:**
|
|
||||||
- Share mode: clears share state before returning home
|
|
||||||
- Normal mode: simple back() navigation
|
|
||||||
- Modal: stays on top (z-index 999)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Common Tasks
|
|
||||||
|
|
||||||
### Add Toast
|
|
||||||
```typescript
|
|
||||||
ToastManager.show('提示信息');
|
|
||||||
```
|
|
||||||
|
|
||||||
### Navigate to Page
|
|
||||||
```typescript
|
|
||||||
ViewManager.instance.open('PageLevel'); // Push
|
|
||||||
ViewManager.instance.back(); // Pop
|
|
||||||
ViewManager.instance.replace('PageHome');// Swap
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get Current Level
|
|
||||||
```typescript
|
|
||||||
const index = StorageManager.getCurrentLevelIndex();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check/Consume Points
|
|
||||||
```typescript
|
|
||||||
if (StorageManager.hasPoints()) {
|
|
||||||
await UserAssetsManager.consumePoint(levelId, hintIndex);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Start Game
|
|
||||||
```typescript
|
|
||||||
// From PageHome
|
|
||||||
ViewManager.instance.open('PageLevel');
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create & Share Challenge
|
|
||||||
```typescript
|
|
||||||
// User flow:
|
|
||||||
PageHome → [PK Button] → PageWriteLevels [Select 6]
|
|
||||||
→ PagePreviewLevels [Verify]
|
|
||||||
→ PassModal [Share Button]
|
|
||||||
→ WxSDK.shareAppMessage()
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## File Size & Complexity
|
|
||||||
|
|
||||||
| File | Lines | Complexity |
|
|
||||||
|------|-------|-----------|
|
|
||||||
| main.ts | 92 | Simple (init only) |
|
|
||||||
| PageLoading.ts | 141 | Medium (parallel loading, sync) |
|
|
||||||
| PageHome.ts | 119 | Simple (two buttons) |
|
|
||||||
| PageLevel.ts | 823 | **Very High** (core game logic) |
|
|
||||||
| PagePreviewLevels.ts | 247 | Medium (scroll list) |
|
|
||||||
| PassModal.ts | 155 | Simple (two buttons) |
|
|
||||||
| Toast.ts | 50 | Simple (fade animation) |
|
|
||||||
| ToastManager.ts | 59 | Simple (factory pattern) |
|
|
||||||
| BaseView.ts | 132 | Medium (lifecycle) |
|
|
||||||
| ViewManager.ts | 320 | High (stack navigation) |
|
|
||||||
|
|
||||||
**Total: ~2,138 lines** | **Focal Point: PageLevel.ts (38% of code)**
|
|
||||||
|
|
||||||
416
SUMMARY.md
416
SUMMARY.md
@@ -1,416 +0,0 @@
|
|||||||
# Game System Summary - Points/Score/Lives Analysis
|
|
||||||
|
|
||||||
**Project:** Cocos Creator WeChat Mini-Game ("写英语" - Write English)
|
|
||||||
**Date Analyzed:** April 5, 2026
|
|
||||||
**Analysis Scope:** Complete TypeScript codebase (21 source files)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Executive Summary
|
|
||||||
|
|
||||||
This game uses a **LIVES-based economy** rather than traditional points/coins:
|
|
||||||
|
|
||||||
- **Currency:** Lives (renewable resource)
|
|
||||||
- **Starting Value:** 10 lives per new player
|
|
||||||
- **Earning Mechanic:** +1 life per completed level
|
|
||||||
- **Spending Mechanic:** -1 life per hint unlock (optional, 2 hints available)
|
|
||||||
- **Net Effect:** Players naturally gain lives if they solve without hints, stay stable with 1 hint/level, or lose lives if using both hints
|
|
||||||
|
|
||||||
The system is **fully persistent** (saved to localStorage) and **progression-aware** (can replay earlier levels while advancing).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Files Analyzed (21 total)
|
|
||||||
|
|
||||||
### Core Game Logic (4 files)
|
|
||||||
1. **PageLevel.ts** (786 lines) - Main gameplay, hint system, answer validation
|
|
||||||
2. **LevelDataManager.ts** (312 lines) - API calls, level caching, image loading
|
|
||||||
3. **StorageManager.ts** (240 lines) - Lives & progress persistence
|
|
||||||
4. **PageLoading.ts** (88 lines) - App initialization, preloading
|
|
||||||
|
|
||||||
### UI/Navigation (3 files)
|
|
||||||
5. **ViewManager.ts** (320 lines) - Page stack management
|
|
||||||
6. **BaseView.ts** (132 lines) - View lifecycle
|
|
||||||
7. **PassModal.ts** (155 lines) - Victory screen with rewards
|
|
||||||
|
|
||||||
### Utilities (5 files)
|
|
||||||
8. **ToastManager.ts** (59 lines) - Toast notifications
|
|
||||||
9. **WxSDK.ts** (188 lines) - WeChat API wrapper
|
|
||||||
10. **HttpUtil.ts** (76 lines) - HTTP requests
|
|
||||||
11. **Toast.ts** (50 lines) - Toast display component
|
|
||||||
12. **LevelTypes.ts** (59 lines) - TypeScript interfaces
|
|
||||||
|
|
||||||
### Prefabs & Entry Points (3 files)
|
|
||||||
13. **PageHome.ts** (78 lines) - Home page
|
|
||||||
14. **main.ts** (59 lines) - App entry point
|
|
||||||
15. Plus UI utilities (BackgroundScaler, RoundedRectMask)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Complete Points/Lives Flow
|
|
||||||
|
|
||||||
### 🟢 EARNING Lives
|
|
||||||
| Event | Amount | Condition |
|
|
||||||
|-------|--------|-----------|
|
|
||||||
| Correct Answer | +1 | Submitted answer matches API answer exactly (case-sensitive, trimmed) |
|
|
||||||
| New Game | +10 | First time players only (default) |
|
|
||||||
| **Cannot Earn** | 0 | Wrong answers, timeouts, hint unlocks, returning players don't reset |
|
|
||||||
|
|
||||||
### 🔴 SPENDING Lives
|
|
||||||
| Event | Amount | Condition |
|
|
||||||
|--------|--------|-----------|
|
|
||||||
| Unlock Hint 2 | -1 | Player clicks unlock, must have lives > 0 |
|
|
||||||
| Unlock Hint 3 | -1 | Player clicks unlock, must have lives > 0 |
|
|
||||||
| No Other Costs | - | No penalties for wrong answers or timeouts |
|
|
||||||
|
|
||||||
### 📊 Net Economy Per Level
|
|
||||||
```
|
|
||||||
Best Case (No Hints): +1 life/level → Infinite scaling
|
|
||||||
Average Case (1 Hint): 0 lives/level → Stable indefinitely
|
|
||||||
Hard Case (2 Hints): -1 life/level → Runs out after 10-20 levels
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Data Persistence
|
|
||||||
|
|
||||||
### localStorage Keys
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
"game_lives": "10", // Current lives count
|
|
||||||
"game_progress": "{ // Player progression
|
|
||||||
\"currentLevelIndex\": 0,
|
|
||||||
\"maxUnlockedLevelIndex\": 0
|
|
||||||
}"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lifespan
|
|
||||||
- **Initial:** Set when first loading game
|
|
||||||
- **Updates:** Every level completion or hint unlock
|
|
||||||
- **Persistence:** Survives app close/reopen (native browser storage)
|
|
||||||
- **Manual Reset:** Available via `StorageManager.resetAll()`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Level Progression System
|
|
||||||
|
|
||||||
### Mechanics
|
|
||||||
1. **Level 1 Always Unlocked** - New players start here
|
|
||||||
2. **Sequential Unlocking** - Beat level N to unlock level N+1
|
|
||||||
3. **Non-Linear Progress** - Can replay earlier levels anytime
|
|
||||||
4. **Max Tracking** - Tracks highest level reached for achievements
|
|
||||||
|
|
||||||
### Data Structure
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
currentLevelIndex: number, // Which level to play next (0-based)
|
|
||||||
maxUnlockedLevelIndex: number // Highest level player has beaten
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example Progression
|
|
||||||
```
|
|
||||||
User beats Level 3 (index 2)
|
|
||||||
↓
|
|
||||||
currentLevelIndex → 2+1 = 3 (level 4)
|
|
||||||
maxUnlockedLevelIndex → max(2, previous) = 2
|
|
||||||
↓
|
|
||||||
Can now play levels 0-3
|
|
||||||
Must complete level 3 to unlock level 4
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Hint System
|
|
||||||
|
|
||||||
### Mechanics
|
|
||||||
- **Hint 1:** Always visible, completely free
|
|
||||||
- **Hint 2:** Hidden by default, costs 1 life to unlock
|
|
||||||
- **Hint 3:** Hidden by default, costs 1 life to unlock
|
|
||||||
|
|
||||||
### Implementation
|
|
||||||
```typescript
|
|
||||||
onUnlockClue(index: 2|3) {
|
|
||||||
if (!hasLives()) return; // Must have >= 1 life
|
|
||||||
consumeLife(); // Deduct 1 life
|
|
||||||
showClue(index); // Reveal the clue content
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Strategic Element
|
|
||||||
Players must decide if they want to spend lives for hints or solve blindly to accumulate more lives for future levels.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Gameplay Loop
|
|
||||||
|
|
||||||
### Per-Level Sequence
|
|
||||||
1. Load level image from API cache
|
|
||||||
2. Display Hint 1 (free) + two "Unlock" buttons
|
|
||||||
3. Start 60-second countdown
|
|
||||||
4. Player can:
|
|
||||||
- Unlock hints by spending lives (optional, repeatable)
|
|
||||||
- Type their answer in single text box
|
|
||||||
- Submit answer
|
|
||||||
5. Outcome:
|
|
||||||
- **Correct:** Reward +1 life, show victory modal
|
|
||||||
- **Wrong:** No penalty, show error toast, can retry
|
|
||||||
- **Timeout:** Play fail sound, can still submit
|
|
||||||
|
|
||||||
### Victory Rewards
|
|
||||||
```
|
|
||||||
onSubmitAnswer(userAnswer) {
|
|
||||||
if (userAnswer.trim() === correctAnswer) {
|
|
||||||
playSuccessSound();
|
|
||||||
addLife(); // +1 life
|
|
||||||
StorageManager.onLevelCompleted(currentLevel);
|
|
||||||
showPassModal(); // Next/Share buttons
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API Integration
|
|
||||||
|
|
||||||
### Endpoint
|
|
||||||
```
|
|
||||||
GET https://ilookai.cn/api/v1/wechat-game/levels
|
|
||||||
```
|
|
||||||
|
|
||||||
### Response Format
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
success: boolean,
|
|
||||||
message: string | null,
|
|
||||||
data: {
|
|
||||||
levels: [
|
|
||||||
{
|
|
||||||
id: "uuid",
|
|
||||||
level: 1,
|
|
||||||
imageUrl: "https://...",
|
|
||||||
hint1: "Free clue",
|
|
||||||
hint2: "Paid clue",
|
|
||||||
hint3: "Paid clue",
|
|
||||||
answer: "CORRECT_ANSWER",
|
|
||||||
sortOrder: 1
|
|
||||||
},
|
|
||||||
// ... more levels
|
|
||||||
],
|
|
||||||
total: number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Reliability Features
|
|
||||||
- **Retry Logic:** 2 attempts on failure
|
|
||||||
- **Timeout:** 8 seconds per request
|
|
||||||
- **Fallback:** Shows error message if all retries fail
|
|
||||||
- **Caching:** All levels cached in memory after first load
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## WeChat Integration
|
|
||||||
|
|
||||||
### Features Implemented
|
|
||||||
1. **Sharing** - Share game to friends with level parameter
|
|
||||||
2. **Vibration** - Haptic feedback on errors
|
|
||||||
3. **Platform Detection** - Gracefully degrade on non-WeChat platforms
|
|
||||||
|
|
||||||
### Share Implementation
|
|
||||||
```typescript
|
|
||||||
// On victory, user can click "Share"
|
|
||||||
WxSDK.shareAppMessage({
|
|
||||||
title: "快来一起玩这款游戏吧",
|
|
||||||
query: `level=${victoryLevelIndex}`
|
|
||||||
});
|
|
||||||
// Opens WeChat share dialog with referral link
|
|
||||||
```
|
|
||||||
|
|
||||||
### Not Implemented
|
|
||||||
- ❌ User authentication (wx.login)
|
|
||||||
- ❌ Backend progress sync
|
|
||||||
- ❌ Analytics
|
|
||||||
- ❌ Ads/Monetization
|
|
||||||
- ❌ Leaderboards
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## User Journey Example
|
|
||||||
|
|
||||||
```
|
|
||||||
New User Opens Game
|
|
||||||
↓
|
|
||||||
[Initialize: 10 lives, Level 1]
|
|
||||||
↓
|
|
||||||
Attempt Level 1
|
|
||||||
├─ Unlocks Hint 2 (-1 life) → 9 lives
|
|
||||||
├─ Unlocks Hint 3 (-1 life) → 8 lives
|
|
||||||
├─ Submits Answer
|
|
||||||
│
|
|
||||||
├─ CORRECT
|
|
||||||
│ ├─ Awards +1 life → 9 lives
|
|
||||||
│ ├─ Saves progress (level → 2)
|
|
||||||
│ └─ Shows PassModal
|
|
||||||
│ ├─ Can click "Next Level" → Level 2
|
|
||||||
│ └─ Can click "Share" → wx.share
|
|
||||||
│
|
|
||||||
└─ WRONG
|
|
||||||
├─ No penalty → 9 lives unchanged
|
|
||||||
├─ Shows error toast
|
|
||||||
└─ Can retry immediately
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Loading & Initialization
|
|
||||||
|
|
||||||
### On App Start
|
|
||||||
1. **Detect New vs. Returning User**
|
|
||||||
- Check localStorage "game_lives" key
|
|
||||||
- New: Initialize to 10
|
|
||||||
- Returning: Restore value
|
|
||||||
|
|
||||||
2. **Load Level Metadata**
|
|
||||||
- API call to fetch all levels
|
|
||||||
- Retry up to 2 times on failure
|
|
||||||
- Cache all level data in memory
|
|
||||||
|
|
||||||
3. **Preload First Level**
|
|
||||||
- Download image for level 1
|
|
||||||
- Cache in memory for instant display
|
|
||||||
|
|
||||||
4. **Show Home Screen**
|
|
||||||
- Display "Start Game" button
|
|
||||||
- Initialize WeChat sharing
|
|
||||||
|
|
||||||
### On Subsequent Game Sessions
|
|
||||||
1. Restore lives from localStorage
|
|
||||||
2. Restore progress from localStorage
|
|
||||||
3. Resume at saved level
|
|
||||||
4. API already cached (no refetch unless app restarted)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Constants
|
|
||||||
|
|
||||||
| Constant | Value | Usage |
|
|
||||||
|----------|-------|-------|
|
|
||||||
| DEFAULT_LIVES | 10 | New player starting amount |
|
|
||||||
| MIN_LIVES | 0 | Cannot go negative |
|
|
||||||
| LEVEL_TIME_LIMIT | 60 seconds | Countdown timer |
|
|
||||||
| API_TIMEOUT | 8000ms | HTTP request timeout |
|
|
||||||
| API_RETRY_COUNT | 2 | Attempts on failure |
|
|
||||||
| HINT_COST | 1 life each | Unlock clue 2 or 3 |
|
|
||||||
| WIN_REWARD | 1 life | Completion bonus |
|
|
||||||
| MODAL_Z_INDEX | 999 | Victory modal layer |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Business Logic Highlights
|
|
||||||
|
|
||||||
### Win Condition
|
|
||||||
```typescript
|
|
||||||
userAnswer.trim() === correctAnswer
|
|
||||||
```
|
|
||||||
- Case-sensitive
|
|
||||||
- Whitespace trimmed
|
|
||||||
- Must match exactly
|
|
||||||
|
|
||||||
### No Lose Condition
|
|
||||||
- Wrong answers: No penalty
|
|
||||||
- Time up: No penalty
|
|
||||||
- Can retry infinitely on same level
|
|
||||||
|
|
||||||
### Safety Checks
|
|
||||||
- Can't unlock hints if lives ≤ 0
|
|
||||||
- Can't go below 0 lives
|
|
||||||
- Can't exceed total levels
|
|
||||||
- Invalid data resets to defaults
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Performance Optimizations
|
|
||||||
|
|
||||||
1. **Image Caching** - Downloaded images cached in memory
|
|
||||||
2. **Level Metadata Caching** - API data cached to avoid re-fetching
|
|
||||||
3. **Progress Caching** - localStorage data cached to reduce reads
|
|
||||||
4. **Async Preloading** - Next level preloaded silently
|
|
||||||
5. **Efficient UI** - Single EditBox (not per-character)
|
|
||||||
6. **Lazy Loading** - Pages cached after first load
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Missing Features / Gaps
|
|
||||||
|
|
||||||
| Feature | Status | Impact |
|
|
||||||
|---------|--------|--------|
|
|
||||||
| User Authentication | ❌ | No way to sync across devices |
|
|
||||||
| Backend Progress Save | ❌ | Progress lost if localStorage clears |
|
|
||||||
| Monetization | ❌ | No revenue stream |
|
|
||||||
| Ads | ❌ | No ad integration |
|
|
||||||
| Analytics | ❌ | Can't track player behavior |
|
|
||||||
| Leaderboards | ❌ | No competition mechanics |
|
|
||||||
| Sound Toggle | ❌ | Always plays sounds |
|
|
||||||
| Difficulty Levels | ❌ | All players see same levels |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing Scenarios
|
|
||||||
|
|
||||||
### Test Case 1: Lives Economy
|
|
||||||
```
|
|
||||||
1. New game → 10 lives
|
|
||||||
2. Beat level without hints → 11 lives
|
|
||||||
3. Beat level with 1 hint → 11 lives (net 0)
|
|
||||||
4. Beat level with 2 hints → 10 lives (net -1)
|
|
||||||
→ Verify localStorage updated after each
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Case 2: Progression
|
|
||||||
```
|
|
||||||
1. Complete level 1
|
|
||||||
2. Verify currentLevel → 2
|
|
||||||
3. Verify maxUnlocked → 1
|
|
||||||
4. Restart app
|
|
||||||
5. Verify levels still saved
|
|
||||||
6. Replay level 1
|
|
||||||
7. Verify no duplicate progress
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Case 3: Hint Cost
|
|
||||||
```
|
|
||||||
1. Start with 10 lives
|
|
||||||
2. Unlock hint 2 → 9 lives displayed
|
|
||||||
3. Unlock hint 3 → 8 lives displayed
|
|
||||||
4. Can't unlock again (button inactive)
|
|
||||||
5. Wrong answer → 8 lives still
|
|
||||||
6. Correct answer → 9 lives (net -1)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
This is a **well-architected mini-game** with:
|
|
||||||
- ✅ Clear lives-based economy
|
|
||||||
- ✅ Persistent progress tracking
|
|
||||||
- ✅ Strategic hint system
|
|
||||||
- ✅ Reliable API integration
|
|
||||||
- ✅ Good error handling
|
|
||||||
- ✅ WeChat platform integration
|
|
||||||
|
|
||||||
The point system is **intentionally forgiving** - players who solve puzzles smartly gain lives indefinitely, while those using hints maintain stability. This encourages skill development without hard progress walls.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Documentation Files Generated
|
|
||||||
|
|
||||||
1. **GAME_ANALYSIS.md** - Comprehensive 17-section analysis (13KB)
|
|
||||||
2. **QUICK_REFERENCE.md** - Quick lookup guide (5.6KB)
|
|
||||||
3. **POINTS_FLOW_DIAGRAM.md** - Visual flow diagrams (15KB)
|
|
||||||
4. **SUMMARY.md** - This executive summary (8KB)
|
|
||||||
|
|
||||||
**Total:** 42KB of detailed documentation covering every aspect of the points/score/lives system.
|
|
||||||
|
|
||||||
@@ -1,489 +0,0 @@
|
|||||||
# UI Components Complete Analysis - Index
|
|
||||||
|
|
||||||
## 📚 Documentation Files Created
|
|
||||||
|
|
||||||
This analysis consists of three comprehensive documents:
|
|
||||||
|
|
||||||
### 1. **UI_COMPONENT_ANALYSIS.md** (Main Reference)
|
|
||||||
**1,424 lines | 45 KB**
|
|
||||||
- Detailed breakdown of all 10 files
|
|
||||||
- Complete method signatures and implementations
|
|
||||||
- Lifecycle method documentation
|
|
||||||
- Data manager interactions
|
|
||||||
- Game flow explanations
|
|
||||||
- Key concepts and patterns
|
|
||||||
|
|
||||||
**Best for:** Deep dives into specific components, understanding implementation details
|
|
||||||
|
|
||||||
### 2. **QUICK_REFERENCE.md** (Developer Cheat Sheet)
|
|
||||||
**~400 lines | 8.6 KB**
|
|
||||||
- Component overview table
|
|
||||||
- Lifecycle stages summary
|
|
||||||
- Key data flows (visual)
|
|
||||||
- Component properties summary
|
|
||||||
- Points & scoring system quick look
|
|
||||||
- Timer system overview
|
|
||||||
- Hint/clue system
|
|
||||||
- Navigation stack examples
|
|
||||||
- Toast system usage
|
|
||||||
- WeChat integration quick reference
|
|
||||||
- Common tasks & code snippets
|
|
||||||
- File complexity metrics
|
|
||||||
|
|
||||||
**Best for:** Quick lookups, copy-paste code patterns, understanding overall architecture
|
|
||||||
|
|
||||||
### 3. **ARCHITECTURE_DIAGRAM.md** (Visual Reference)
|
|
||||||
**~1,000 lines | 26 KB**
|
|
||||||
- System architecture diagram
|
|
||||||
- Page state machine
|
|
||||||
- Page stack visualization with session traces
|
|
||||||
- Component communication diagrams
|
|
||||||
- Data flow diagrams (level completion, hint unlocking)
|
|
||||||
- Timer sequence diagrams
|
|
||||||
- Input box creation flow
|
|
||||||
- Share challenge mode flow
|
|
||||||
- ViewManager caching mechanism
|
|
||||||
- Error handling paths
|
|
||||||
|
|
||||||
**Best for:** Understanding flow, tracing execution, visual learners
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Component Summary
|
|
||||||
|
|
||||||
### Core Infrastructure
|
|
||||||
- **main.ts** (92 lines) - App bootstrap, register pages and managers
|
|
||||||
- **BaseView.ts** (132 lines) - Abstract page lifecycle interface
|
|
||||||
- **ViewManager.ts** (320 lines) - Stack-based page navigation system
|
|
||||||
|
|
||||||
### UI Pages (All extend BaseView)
|
|
||||||
- **PageLoading.ts** (141 lines) - Splash screen, load data, detect share code
|
|
||||||
- **PageHome.ts** (119 lines) - Landing page hub with game/PK buttons
|
|
||||||
- **PageLevel.ts** (823 lines) ⭐ **Most Complex** - Main game with timer, hints, scoring
|
|
||||||
- **PagePreviewLevels.ts** (247 lines) - Scrollable list of selected levels
|
|
||||||
- **PassModal.ts** (155 lines) - Completion modal with next/share buttons
|
|
||||||
|
|
||||||
### Notification System
|
|
||||||
- **Toast.ts** (50 lines) - Individual toast notification with fade animation
|
|
||||||
- **ToastManager.ts** (59 lines) - Singleton manager for toast creation
|
|
||||||
|
|
||||||
**Total: ~2,138 lines across 10 files**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔑 Key Topics Quick Index
|
|
||||||
|
|
||||||
### Game Mechanics
|
|
||||||
| Topic | Location | Key Method |
|
|
||||||
|-------|----------|-----------|
|
|
||||||
| 60-second countdown | PageLevel | startCountdown() / onCountdownTick() |
|
|
||||||
| Hint/clue system (3 levels) | PageLevel | onUnlockClue(index) |
|
|
||||||
| Answer verification | PageLevel | onSubmitAnswer() / getAnswer() |
|
|
||||||
| Level progression | PageLevel | nextLevel() |
|
|
||||||
| Points earning | PageLevel | showSuccess() + UserAssetsManager.earnPoint() |
|
|
||||||
| Points spending | PageLevel | onUnlockClue() + UserAssetsManager.consumePoint() |
|
|
||||||
|
|
||||||
### UI Management
|
|
||||||
| Topic | Location | Key Method |
|
|
||||||
|-------|----------|-----------|
|
|
||||||
| Page navigation | ViewManager | open() / back() / replace() |
|
|
||||||
| Page lifecycle | BaseView | onViewLoad/Show/Hide/Destroy |
|
|
||||||
| Page caching | ViewManager | _viewCache Map |
|
|
||||||
| Page stacking | ViewManager | _viewStack array (LIFO) |
|
|
||||||
| Toast notifications | ToastManager | show(content, duration) |
|
|
||||||
|
|
||||||
### Special Features
|
|
||||||
| Topic | Location | Key Method |
|
|
||||||
|-------|----------|-----------|
|
|
||||||
| Share challenge mode | PageLevel + ShareManager | _isShareMode flag |
|
|
||||||
| WeChat integration | PageHome, PassModal, WxSDK | initShare() / shareAppMessage() |
|
|
||||||
| Server progress sync | PageLoading | _syncProgressFromServer() |
|
|
||||||
| Level preloading | PageLevel | preloadNextLevel() |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Complexity Breakdown
|
|
||||||
|
|
||||||
```
|
|
||||||
PageLevel.ts (823 lines - 38% of total code)
|
|
||||||
├─ Input management
|
|
||||||
├─ Timer system
|
|
||||||
├─ Hint unlocking
|
|
||||||
├─ Answer validation
|
|
||||||
├─ Point interactions
|
|
||||||
├─ Audio effects
|
|
||||||
├─ Modal handling
|
|
||||||
└─ Share mode support
|
|
||||||
|
|
||||||
ViewManager.ts (320 lines - 15% of total code)
|
|
||||||
├─ Page registration
|
|
||||||
├─ Stack management
|
|
||||||
├─ Instance caching
|
|
||||||
├─ Lifecycle coordination
|
|
||||||
└─ Error handling
|
|
||||||
|
|
||||||
All Other Components (995 lines - 47% of total code)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎮 Game Flow Overview
|
|
||||||
|
|
||||||
```
|
|
||||||
User Launches App
|
|
||||||
↓
|
|
||||||
main.ts registers pages & managers
|
|
||||||
↓
|
|
||||||
PageLoading loads auth + levels (parallel)
|
|
||||||
↓
|
|
||||||
┌─ Detect Share Code ──→ Enter Share Mode (PageLevel)
|
|
||||||
│ ↓
|
|
||||||
│ Play Levels
|
|
||||||
│ ↓
|
|
||||||
│ Return Home
|
|
||||||
│
|
|
||||||
└─ Normal Path ──→ Open PageHome
|
|
||||||
↓
|
|
||||||
┌──────┴──────┐
|
|
||||||
↓ ↓
|
|
||||||
Play Game Create Challenge
|
|
||||||
(PageLevel) (PageWriteLevels)
|
|
||||||
↓ ↓
|
|
||||||
Win Level PagePreviewLevels
|
|
||||||
↓ ↓
|
|
||||||
PassModal PassModal/Share
|
|
||||||
↓ ↓
|
|
||||||
Next/Back Share to WeChat
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💾 Data Manager Interactions
|
|
||||||
|
|
||||||
### By Page
|
|
||||||
|
|
||||||
**PageLoading**
|
|
||||||
- AuthManager.initialize()
|
|
||||||
- LevelDataManager.initialize()
|
|
||||||
- StorageManager.getMaxUnlockedLevelIndex()
|
|
||||||
- StorageManager.onLevelCompleted()
|
|
||||||
- ShareManager.joinShare()
|
|
||||||
- WxSDK.getShareCodeFromLaunch()
|
|
||||||
|
|
||||||
**PageHome**
|
|
||||||
- WxSDK.initShare()
|
|
||||||
- checkPrivacySetting()
|
|
||||||
- requirePrivacyAuthorize()
|
|
||||||
|
|
||||||
**PageLevel** (Most interactions)
|
|
||||||
- LevelDataManager (load, preload, get count)
|
|
||||||
- StorageManager (get/set progress, get points)
|
|
||||||
- UserAssetsManager (earn/consume points)
|
|
||||||
- ShareManager (share mode, report progress)
|
|
||||||
- WxSDK (vibration, sharing)
|
|
||||||
- ToastManager (notifications)
|
|
||||||
- ViewManager (navigation)
|
|
||||||
|
|
||||||
**PagePreviewLevels**
|
|
||||||
- LevelDataManager.ensureLevelReady()
|
|
||||||
|
|
||||||
**PassModal**
|
|
||||||
- WxSDK.shareAppMessage()
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ Important Flags & Preventing Issues
|
|
||||||
|
|
||||||
### Double-Submission Prevention
|
|
||||||
```typescript
|
|
||||||
// In PageLevel.onSubmitAnswer()
|
|
||||||
if (this._isTransitioning) return; // Blocks rapid re-submission
|
|
||||||
```
|
|
||||||
|
|
||||||
### Double-Click Unlock Prevention
|
|
||||||
```typescript
|
|
||||||
// In PageLevel.onUnlockClue()
|
|
||||||
if (this._isUnlocking) return; // Blocks rapid hint unlocking
|
|
||||||
```
|
|
||||||
|
|
||||||
### Share Mode Detection
|
|
||||||
```typescript
|
|
||||||
// In PageLevel.onViewLoad()
|
|
||||||
this._isShareMode = params?.shareMode === true;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Timer Running Flag
|
|
||||||
```typescript
|
|
||||||
// In PageLevel.onCountdownTick()
|
|
||||||
if (this._isTimeUp) return; // Prevents countdown after timeout
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Page Lifecycle Details
|
|
||||||
|
|
||||||
### First-Time Open
|
|
||||||
1. ViewManager.open() called
|
|
||||||
2. Prefab instantiated
|
|
||||||
3. onViewLoad() called (do heavy init here)
|
|
||||||
4. Page added to stack
|
|
||||||
5. onViewShow() called
|
|
||||||
|
|
||||||
### Re-open (if cached)
|
|
||||||
1. ViewManager.open() called
|
|
||||||
2. Cache hit found
|
|
||||||
3. Previous page onViewHide() called
|
|
||||||
4. This page onViewShow() called (not onViewLoad!)
|
|
||||||
5. Page already in stack (or re-added)
|
|
||||||
|
|
||||||
### Close/Back
|
|
||||||
1. ViewManager.back() called
|
|
||||||
2. Current page onViewHide() called
|
|
||||||
3. Current page destroyed (if not cached)
|
|
||||||
4. Previous page onViewShow() called
|
|
||||||
|
|
||||||
### Destroy
|
|
||||||
1. onViewDestroy() called
|
|
||||||
2. All listeners removed
|
|
||||||
3. Resources cleaned up
|
|
||||||
4. Node destroyed
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Common Code Patterns
|
|
||||||
|
|
||||||
### Open Page with Parameters
|
|
||||||
```typescript
|
|
||||||
ViewManager.instance.open('PageLevel', {
|
|
||||||
params: { shareMode: true },
|
|
||||||
onComplete: (view) => {
|
|
||||||
console.log('PageLevel opened');
|
|
||||||
},
|
|
||||||
onError: (err) => {
|
|
||||||
console.error('Failed to open:', err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Get Page Parameters
|
|
||||||
```typescript
|
|
||||||
onViewLoad(): void {
|
|
||||||
const params = this.getParams();
|
|
||||||
if (params?.shareMode) {
|
|
||||||
// Handle share mode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Show Toast Notification
|
|
||||||
```typescript
|
|
||||||
ToastManager.show('提示信息', 2000); // 2 second display
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check & Consume Points
|
|
||||||
```typescript
|
|
||||||
if (StorageManager.hasPoints()) {
|
|
||||||
const success = await UserAssetsManager.consumePoint(levelId, hintIndex);
|
|
||||||
if (success) {
|
|
||||||
this.updatePointsLabel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Schedule & Unschedule
|
|
||||||
```typescript
|
|
||||||
startCountdown(): void {
|
|
||||||
this.schedule(this.onCountdownTick, 1); // Every 1 second
|
|
||||||
}
|
|
||||||
|
|
||||||
stopCountdown(): void {
|
|
||||||
this.unschedule(this.onCountdownTick); // Stop callback
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐛 Known Patterns to Watch
|
|
||||||
|
|
||||||
### Caching Implications
|
|
||||||
- Pages with cache:true keep their onViewLoad() state
|
|
||||||
- onViewShow() is called each time, even if cached
|
|
||||||
- If you modify state in onViewLoad(), it persists!
|
|
||||||
- Solution: Reset state in onViewShow() if needed
|
|
||||||
|
|
||||||
### Share Mode Edge Cases
|
|
||||||
- Share mode doesn't save local progress
|
|
||||||
- Share mode uses ShareManager instead of LevelDataManager
|
|
||||||
- Share mode clears state on return to home
|
|
||||||
- Must check _isShareMode before saving
|
|
||||||
|
|
||||||
### Modal Positioning
|
|
||||||
- PassModal instantiated with z-index 999 (topmost)
|
|
||||||
- Added to Canvas root node (not PageLevel child)
|
|
||||||
- This allows full-screen coverage with proper Widget alignment
|
|
||||||
|
|
||||||
### Timer Edge Cases
|
|
||||||
- Timer continues even if page is hidden
|
|
||||||
- Must stop timer on destroy or completion
|
|
||||||
- onTimeUp() plays sound but doesn't end game automatically
|
|
||||||
- Wrong answer doesn't stop timer
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Tips for Modifications
|
|
||||||
|
|
||||||
### Adding New Hint Types
|
|
||||||
1. Add hint4 config to RuntimeLevelConfig
|
|
||||||
2. Add unLockItem4 property to PageLevel
|
|
||||||
3. Add tipsItem4 property to PageLevel
|
|
||||||
4. Call showUnlockButton(4) in _applyLevelConfig()
|
|
||||||
5. Handle in onUnlockClue() switch/case
|
|
||||||
|
|
||||||
### Adding Page Analytics
|
|
||||||
1. Add tracking in onViewLoad() (first visit)
|
|
||||||
2. Add tracking in onViewShow() (each visit)
|
|
||||||
3. Use page viewId for identification
|
|
||||||
4. Track user actions in event handlers
|
|
||||||
|
|
||||||
### Changing Point System
|
|
||||||
1. Modify UserAssetsManager (not shown)
|
|
||||||
2. Update updatePointsLabel() display format
|
|
||||||
3. Adjust hasPoints() check if needed
|
|
||||||
4. Test unlock flow with new values
|
|
||||||
|
|
||||||
### Adjusting Timer
|
|
||||||
1. Change `_countdown = 60` to desired seconds
|
|
||||||
2. Update display frequency if needed
|
|
||||||
3. Adjust point calculation if time-based
|
|
||||||
4. Test timeout behavior
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📖 How to Use This Documentation
|
|
||||||
|
|
||||||
**For a new developer:**
|
|
||||||
1. Start with QUICK_REFERENCE.md for overview
|
|
||||||
2. Read UI_COMPONENT_ANALYSIS.md sections for specific pages
|
|
||||||
3. Reference ARCHITECTURE_DIAGRAM.md for flow understanding
|
|
||||||
|
|
||||||
**For debugging:**
|
|
||||||
1. Find error in component name
|
|
||||||
2. Look up methods in UI_COMPONENT_ANALYSIS.md
|
|
||||||
3. Check flow in ARCHITECTURE_DIAGRAM.md
|
|
||||||
4. Use QUICK_REFERENCE.md for code patterns
|
|
||||||
|
|
||||||
**For adding features:**
|
|
||||||
1. Understand game flow in QUICK_REFERENCE.md
|
|
||||||
2. Find where to hook in UI_COMPONENT_ANALYSIS.md
|
|
||||||
3. Check data flows in ARCHITECTURE_DIAGRAM.md
|
|
||||||
4. Copy patterns from QUICK_REFERENCE.md
|
|
||||||
|
|
||||||
**For optimization:**
|
|
||||||
1. Note complexity metrics in QUICK_REFERENCE.md
|
|
||||||
2. Identify bottlenecks in PageLevel.ts
|
|
||||||
3. Check async operations in PageLoading.ts
|
|
||||||
4. Review caching in ViewManager.ts
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 Cross-References
|
|
||||||
|
|
||||||
### Frequently Referenced Files
|
|
||||||
- **PageLevel.ts** - Most complex, used from PageHome and PageLoading
|
|
||||||
- **ViewManager.ts** - Used by all pages for navigation
|
|
||||||
- **StorageManager** - Used by PageLoading and PageLevel
|
|
||||||
- **UserAssetsManager** - Used by PageLevel for points
|
|
||||||
- **LevelDataManager** - Used by PageLoading and PageLevel
|
|
||||||
|
|
||||||
### Integration Points
|
|
||||||
```
|
|
||||||
main.ts (startup)
|
|
||||||
↓
|
|
||||||
PageLoading (data loading)
|
|
||||||
├─ AuthManager
|
|
||||||
├─ LevelDataManager
|
|
||||||
└─ ShareManager
|
|
||||||
↓
|
|
||||||
PageHome (navigation hub)
|
|
||||||
├─ PageLevel (game)
|
|
||||||
│ ├─ StorageManager
|
|
||||||
│ ├─ UserAssetsManager
|
|
||||||
│ ├─ WxSDK
|
|
||||||
│ └─ PassModal (modal)
|
|
||||||
│ └─ WxSDK
|
|
||||||
│
|
|
||||||
└─ PageWriteLevels (not analyzed)
|
|
||||||
└─ PagePreviewLevels
|
|
||||||
└─ LevelDataManager
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 File Statistics
|
|
||||||
|
|
||||||
| Metric | Value |
|
|
||||||
|--------|-------|
|
|
||||||
| Total Lines | 2,138 |
|
|
||||||
| Total Files Analyzed | 10 |
|
|
||||||
| Most Complex File | PageLevel.ts (823 lines, 38%) |
|
|
||||||
| Most Reused Manager | ViewManager |
|
|
||||||
| Total Data Managers Used | 7+ |
|
|
||||||
| UI Components | 5 pages + 2 utilities |
|
|
||||||
| Lifecycle Methods | 4 per BaseView |
|
|
||||||
| Key Patterns | Stack navigation, caching, events |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Next Steps for Development
|
|
||||||
|
|
||||||
1. **Run the game** and trace through the flows documented here
|
|
||||||
2. **Add logging** to key methods to understand real execution order
|
|
||||||
3. **Modify a page** to get familiar with lifecycle
|
|
||||||
4. **Create new page** following BaseView pattern
|
|
||||||
5. **Add new feature** using documented patterns
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 Quick Troubleshooting
|
|
||||||
|
|
||||||
**Page not showing?**
|
|
||||||
- Check ViewManager.open() called
|
|
||||||
- Verify prefab has BaseView component
|
|
||||||
- Check registration in main.ts
|
|
||||||
|
|
||||||
**Points not updating?**
|
|
||||||
- Verify UserAssetsManager call succeeds
|
|
||||||
- Check updatePointsLabel() is called
|
|
||||||
- Test StorageManager.getPoints() returns value
|
|
||||||
|
|
||||||
**Timer not stopping?**
|
|
||||||
- Check stopCountdown() called on completion
|
|
||||||
- Verify unschedule() works in Cocos
|
|
||||||
- Test onDestroy calls stopCountdown()
|
|
||||||
|
|
||||||
**Modal not appearing?**
|
|
||||||
- Check z-index set to 999
|
|
||||||
- Verify added to Canvas root
|
|
||||||
- Test instantiate() succeeds
|
|
||||||
- Check onViewLoad/Show called manually
|
|
||||||
|
|
||||||
**Share mode broken?**
|
|
||||||
- Verify share code detected in PageLoading
|
|
||||||
- Check _isShareMode set properly
|
|
||||||
- Test ShareManager.joinShare() succeeds
|
|
||||||
- Verify clearShareMode() called on exit
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Analysis Complete
|
|
||||||
|
|
||||||
All 10 UI component files have been thoroughly analyzed and documented.
|
|
||||||
|
|
||||||
**Total Documentation: 3 comprehensive guides**
|
|
||||||
- **UI_COMPONENT_ANALYSIS.md** - Deep technical reference (1,424 lines)
|
|
||||||
- **QUICK_REFERENCE.md** - Developer cheat sheet (~400 lines)
|
|
||||||
- **ARCHITECTURE_DIAGRAM.md** - Visual flow diagrams (~1,000 lines)
|
|
||||||
- **This file** - Navigation & index (this document)
|
|
||||||
|
|
||||||
**Ready for:** Development, debugging, feature implementation, onboarding
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user