perf: 删除不必要的文件

This commit is contained in:
richarjiang
2026-04-19 12:00:19 +08:00
parent 5d472e1c30
commit 34e06480ce
12 changed files with 0 additions and 6079 deletions

View File

@@ -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

View File

@@ -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
```

View File

@@ -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.**

View File

@@ -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

View File

@@ -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
```

View File

@@ -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!

View File

@@ -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 端点一览
### 已配置的 APIApiConfig.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)
PageLevelshareMode=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 完整封装
- 非微信环境自动降级
- 支持分享、登录、震动等

View File

@@ -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 |

View File

@@ -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)**

View File

@@ -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.

View File

@@ -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