Browse Source

BlockSelection优化

181404010226 5 months ago
parent
commit
8cb819772e

File diff suppressed because it is too large
+ 668 - 208
assets/Scenes/GameLevel.scene


+ 76 - 0
assets/scripts/CombatSystem/BallController.ts

@@ -162,6 +162,82 @@ export class BallController extends Component {
         this.initialized = true;
     }
 
+
+    // 为指定节点随机定位
+    private positionBallRandomlyForNode(ballNode: Node) {
+        const transform = ballNode.getComponent(UITransform);
+        const ballRadius = transform ? transform.width / 2 : 25;
+        
+        // 计算可生成的范围
+        const minX = this.gameBounds.left + ballRadius + 20;
+        const maxX = this.gameBounds.right - ballRadius - 20;
+        const minY = this.gameBounds.bottom + ballRadius + 20;
+        const maxY = this.gameBounds.top - ballRadius - 20;
+
+        // 随机生成位置
+        const randomX = Math.random() * (maxX - minX) + minX;
+        const randomY = Math.random() * (maxY - minY) + minY;
+
+        // 将世界坐标转换为相对于GameArea的本地坐标
+        const gameArea = find('Canvas/GameLevelUI/GameArea');
+        if (gameArea) {
+            const localPos = gameArea.getComponent(UITransform).convertToNodeSpaceAR(new Vec3(randomX, randomY, 0));
+            ballNode.position = localPos;
+        }
+    }
+
+    // 为指定小球设置碰撞组件
+    private setupColliderForBall(ballNode: Node, ballRadius: number) {
+        // 确保小球有刚体组件
+        let rigidBody = ballNode.getComponent(RigidBody2D);
+        if (!rigidBody) {
+            rigidBody = ballNode.addComponent(RigidBody2D);
+            rigidBody.type = 2; // Dynamic
+            rigidBody.gravityScale = 0;
+            rigidBody.enabledContactListener = true;
+            rigidBody.fixedRotation = true;
+            rigidBody.allowSleep = false;
+            rigidBody.linearDamping = 0;
+            rigidBody.angularDamping = 0;
+        }
+
+        // 确保小球有碰撞组件
+        let collider = ballNode.getComponent(CircleCollider2D);
+        if (!collider) {
+            collider = ballNode.addComponent(CircleCollider2D);
+            collider.radius = ballRadius;
+            collider.tag = 1;
+            collider.group = 1;
+            collider.sensor = false;
+            collider.friction = 0;
+            collider.restitution = 1;
+        }
+
+        // 设置碰撞监听
+        const physics = PhysicsManager.getInstance()?.getSystem();
+        if (physics) {
+            physics.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
+            physics.on(Contact2DType.END_CONTACT, this.onEndContact, this);
+            physics.on(Contact2DType.PRE_SOLVE, this.onPreSolve, this);
+            physics.on(Contact2DType.POST_SOLVE, this.onPostSolve, this);
+        }
+    }
+
+    // 启动指定小球的运动
+    private startBallMovement(ballNode: Node) {
+        const rigidBody = ballNode.getComponent(RigidBody2D);
+        if (rigidBody) {
+            // 随机初始方向
+            const angle = Math.random() * Math.PI * 2;
+            const direction = new Vec2(Math.cos(angle), Math.sin(angle));
+            
+            rigidBody.linearVelocity = new Vec2(
+                direction.x * this.speed,
+                direction.y * this.speed
+            );
+        }
+    }
+
     // 检查所有已放置方块的碰撞体组件
     private checkBlockColliders() {
         

+ 0 - 21
assets/scripts/CombatSystem/BlockManager.ts

@@ -86,13 +86,6 @@ export class BlockManager extends Component {
     // 方块武器配置映射
     private blockWeaponConfigs: Map<Node, WeaponConfig> = new Map();
     
-    // 刷新方块按钮节点(ann003)
-    @property({
-        type: Node,
-        tooltip: '拖拽BlockSelectionUI/diban/ann003按钮节点到这里'
-    })
-    public refreshButton: Node = null;
-    
     /** 冷却机制已废弃,方块随时可移动 */
     private canMoveBlock(block: Node): boolean { return true; }
 
@@ -155,15 +148,6 @@ export class BlockManager extends Component {
         // 初始化网格占用情况
         this.initGridOccupationMap();
         
-        if (this.refreshButton) {
-            const btn = this.refreshButton.getComponent(Button);
-            if (btn) {
-                this.refreshButton.on(Button.EventType.CLICK, this.onRefreshButtonClicked, this);
-            } else {
-                // 兼容没有 Button 组件的情况
-                this.refreshButton.on(Node.EventType.TOUCH_END, this.onRefreshButtonClicked, this);
-            }
-        }
         // 等待配置加载完成后生成方块
         this.scheduleOnce(() => {
             this.generateRandomBlocksInKuang();
@@ -1150,11 +1134,6 @@ export class BlockManager extends Component {
         this.generateRandomBlocksInKuang();
     }
 
-    // 刷新按钮点击回调
-    private onRefreshButtonClicked() {
-        this.refreshBlocks();
-    }
-
     /* =================== 合成逻辑 =================== */
 
     private readonly rarityOrder: string[] = ['common','uncommon','rare','epic','legendary'];

+ 9 - 0
assets/scripts/CombatSystem/BlockSelection.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "1.2.0",
+  "importer": "directory",
+  "imported": true,
+  "uuid": "4a6e5305-2ca9-4a24-aa9b-935ea9a49f86",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 307 - 0
assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts

@@ -0,0 +1,307 @@
+import { _decorator, Component, Node, Button, Label, find, UITransform, Sprite, Color } from 'cc';
+import { LevelSessionManager } from '../../Core/LevelSessionManager';
+import { BallController } from '../BallController';
+import { BlockManager } from '../BlockManager';
+import { GameStartMove } from '../../Animations/GameStartMove';
+const { ccclass, property } = _decorator;
+
+@ccclass('GameBlockSelection')
+export class GameBlockSelection extends Component {
+    
+    @property({
+        type: Node,
+        tooltip: '拖拽BlockSelectionUI/diban/ann001按钮节点到这里'
+    })
+    public addBallButton: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽BlockSelectionUI/diban/ann002按钮节点到这里'
+    })
+    public addCoinButton: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽BlockSelectionUI/diban/ann003按钮节点到这里'
+    })
+    public refreshButton: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽Canvas-001/TopArea/CoinNode/CoinLabel节点到这里'
+    })
+    public coinLabelNode: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽Canvas/InsufficientCoinsUI节点到这里'
+    })
+    public insufficientCoinsUI: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽Canvas/GameLevelUI/BallController节点到这里'
+    })
+    public ballControllerNode: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽Canvas/GameLevelUI/BlockController节点到这里'
+    })
+    public blockManagerNode: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽Canvas/Camera节点到这里'
+    })
+    public cameraNode: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽Canvas/GameLevelUI/GameArea/GridContainer节点到这里'
+    })
+    public gridContainer: Node = null;
+
+    @property({
+        type: Node,
+        tooltip: '拖拽confirm按钮节点到这里'
+    })
+    public confirmButton: Node = null;
+
+    // 按钮费用配置
+    private readonly ADD_BALL_COST = 80;
+    private readonly ADD_COIN_AMOUNT = 80;
+    private readonly REFRESH_COST = 5;
+
+    private session: LevelSessionManager = null;
+    private ballController: BallController = null;
+    private blockManager: BlockManager = null;
+    private gameStartMove: GameStartMove = null;
+
+    // 回调函数,用于通知GameManager
+    public onConfirmCallback: () => void = null;
+
+    start() {
+        // 获取管理器实例
+        this.session = LevelSessionManager.inst;
+        
+        // 获取BallController
+        if (this.ballControllerNode) {
+            this.ballController = this.ballControllerNode.getComponent(BallController);
+        } else {
+            console.warn('BallController节点未绑定,请在Inspector中拖拽Canvas/GameLevelUI/BallController节点');
+        }
+
+        // 获取BlockManager
+        if (this.blockManagerNode) {
+            this.blockManager = this.blockManagerNode.getComponent(BlockManager);
+        } else {
+            console.warn('BlockManager节点未绑定,请在Inspector中拖拽Canvas/GameLevelUI/BlockController节点');
+        }
+
+        // 获取GameStartMove组件
+        if (this.cameraNode) {
+            this.gameStartMove = this.cameraNode.getComponent(GameStartMove);
+        }
+
+        // 如果没有指定coinLabelNode,尝试找到它
+        if (!this.coinLabelNode) {
+            this.coinLabelNode = find('Canvas-001/TopArea/CoinNode/CoinLabel');
+        }
+
+        // 绑定按钮事件
+        this.bindButtonEvents();
+    }
+
+    // 绑定按钮事件
+    private bindButtonEvents() {
+        // 绑定新增小球按钮
+        if (this.addBallButton) {
+            const btn = this.addBallButton.getComponent(Button);
+            if (btn) {
+                this.addBallButton.on(Button.EventType.CLICK, this.onAddBallClicked, this);
+            } else {
+                this.addBallButton.on(Node.EventType.TOUCH_END, this.onAddBallClicked, this);
+            }
+        }
+
+        // 绑定增加金币按钮
+        if (this.addCoinButton) {
+            const btn = this.addCoinButton.getComponent(Button);
+            if (btn) {
+                this.addCoinButton.on(Button.EventType.CLICK, this.onAddCoinClicked, this);
+            } else {
+                this.addCoinButton.on(Node.EventType.TOUCH_END, this.onAddCoinClicked, this);
+            }
+        }
+
+        // 绑定刷新方块按钮
+        if (this.refreshButton) {
+            const btn = this.refreshButton.getComponent(Button);
+            if (btn) {
+                this.refreshButton.on(Button.EventType.CLICK, this.onRefreshClicked, this);
+            } else {
+                this.refreshButton.on(Node.EventType.TOUCH_END, this.onRefreshClicked, this);
+            }
+        }
+
+        // 绑定确认按钮
+        if (this.confirmButton) {
+            const btn = this.confirmButton.getComponent(Button);
+            if (btn) {
+                this.confirmButton.on(Button.EventType.CLICK, this.onConfirmButtonClicked, this);
+            } else {
+                this.confirmButton.on(Node.EventType.TOUCH_END, this.onConfirmButtonClicked, this);
+            }
+        }
+    }
+
+    // 新增小球按钮点击
+    private onAddBallClicked() {
+        if (!this.canSpendCoins(this.ADD_BALL_COST)) {
+            this.showInsufficientCoinsUI();
+            return;
+        }
+
+        // 扣除金币
+        if (this.session.spendCoins(this.ADD_BALL_COST)) {
+            this.updateCoinDisplay();
+            
+            // 创建新的小球
+            if (this.ballController) {
+                this.ballController.createBall();
+                console.log(`新增小球成功,扣除${this.ADD_BALL_COST}金币`);
+            } else {
+                console.error('找不到BallController,无法创建小球');
+            }
+        }
+    }
+
+    // 增加金币按钮点击
+    private onAddCoinClicked() {
+        this.session.addCoins(this.ADD_COIN_AMOUNT);
+        this.updateCoinDisplay();
+        console.log(`增加${this.ADD_COIN_AMOUNT}金币`);
+    }
+
+    // 刷新方块按钮点击
+    private onRefreshClicked() {
+        if (!this.canSpendCoins(this.REFRESH_COST)) {
+            this.showInsufficientCoinsUI();
+            return;
+        }
+
+        // 扣除金币
+        if (this.session.spendCoins(this.REFRESH_COST)) {
+            this.updateCoinDisplay();
+            
+            // 刷新方块
+            if (this.blockManager) {
+                this.blockManager.refreshBlocks();
+                console.log(`刷新方块成功,扣除${this.REFRESH_COST}金币`);
+            } else {
+                console.error('找不到BlockManager,无法刷新方块');
+            }
+        }
+    }
+
+    // 确认按钮点击(从GameManager迁移的onConfirmButtonClicked)
+    public onConfirmButtonClicked() {
+        // 执行相机动画和UI关闭
+        if (this.gameStartMove) {
+            this.gameStartMove.slideDibanDownAndHide();
+        } else {
+            // Fallback: 若未挂载 GameStartMove,直接关闭
+            this.node.active = false;
+        }
+
+        // Camera move back up with smooth animation
+        if (this.gameStartMove) {
+            this.gameStartMove.moveUpSmooth();
+        }
+
+        // 显示GridContainer
+        if (this.gridContainer) {
+            this.gridContainer.active = true;
+        }
+        
+        // 保存已放置的方块
+        this.preservePlacedBlocks();
+
+        // 回调通知GameManager
+        if (this.onConfirmCallback) {
+            this.onConfirmCallback();
+        }
+    }
+
+    // 保存已放置的方块(从GameManager迁移)
+    private preservePlacedBlocks() {
+        if (this.blockManager) {
+            this.blockManager.onGameStart();
+        }
+    }
+
+    // 检查是否有足够金币
+    private canSpendCoins(amount: number): boolean {
+        return this.session.getCoins() >= amount;
+    }
+
+    // 更新金币显示
+    private updateCoinDisplay() {
+        if (this.coinLabelNode) {
+            const label = this.coinLabelNode.getComponent(Label);
+            if (label) {
+                label.string = this.session.getCoins().toString();
+            }
+        }
+    }
+
+    // 显示金币不足UI
+    private showInsufficientCoinsUI() {
+        if (!this.insufficientCoinsUI) {
+            console.error('金币不足UI节点未绑定,请在Inspector中拖拽Canvas/InsufficientCoinsUI节点');
+            return;
+        }
+
+        // 显示金币不足UI
+        this.insufficientCoinsUI.active = true;
+
+        // 3秒后自动隐藏
+        this.scheduleOnce(() => {
+            if (this.insufficientCoinsUI && this.insufficientCoinsUI.isValid) {
+                this.insufficientCoinsUI.active = false;
+            }
+        }, 3.0);
+
+        console.log('金币不足!');
+    }
+
+    // === 公共方法:供GameManager调用 ===
+
+    // 显示方块选择UI(用于游戏开始或下一波)
+    public showBlockSelection(isNextWave: boolean = false) {
+        this.node.active = true;
+        
+        if (this.gridContainer) {
+            this.gridContainer.active = true;
+        }
+
+        console.log(isNextWave ? '显示下一波方块选择UI' : '显示游戏开始方块选择UI');
+    }
+
+    // 隐藏方块选择UI
+    public hideBlockSelection() {
+        this.node.active = false;
+        
+        if (this.gridContainer) {
+            this.gridContainer.active = false;
+        }
+
+        console.log('隐藏方块选择UI');
+    }
+
+    // 设置确认回调
+    public setConfirmCallback(callback: () => void) {
+        this.onConfirmCallback = callback;
+    }
+}

+ 9 - 0
assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "130350ee-5a3b-443c-9e95-a5aa4860d038",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 0 - 0
assets/scripts/CombatSystem/GamePause.ts


+ 9 - 0
assets/scripts/CombatSystem/GamePause.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "4aa80acf-bd3e-4e54-ac24-42a811c458c8",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 45 - 44
assets/scripts/LevelSystem/GameManager.ts

@@ -11,6 +11,7 @@ import { BallController } from '../CombatSystem/BallController';
 import { BlockManager } from '../CombatSystem/BlockManager';
 import { LevelSessionManager } from '../Core/LevelSessionManager';
 import { GameStartMove } from '../Animations/GameStartMove';
+import { GameBlockSelection } from '../CombatSystem/BlockSelection/GameBlockSelection';
 const { ccclass, property } = _decorator;
 
 /**
@@ -39,9 +40,9 @@ export class GameManager extends Component {
 
     @property({
         type: Node,
-        tooltip: '拖拽BlockSelectionUI节点到这里'
+        tooltip: '拖拽GameBlockSelection节点到这里'
     })
-    public blockSelectionUI: Node = null;
+    public gameBlockSelection: Node = null;
 
     @property({
         type: Node,
@@ -141,6 +142,9 @@ export class GameManager extends Component {
     private readonly ENERGY_MAX: number = 5;
     private energyBar: ProgressBar = null;
 
+    // GameBlockSelection组件
+    private blockSelectionComponent: GameBlockSelection = null;
+
     start() {
         // 初始化物理系统
         this.initPhysicsSystem();
@@ -177,6 +181,9 @@ export class GameManager extends Component {
         // 设置UI按钮
         this.setupUIButtons();
         
+        // 初始化GameBlockSelection组件
+        this.initGameBlockSelection();
+        
         // 加载当前关卡配置
         this.loadCurrentLevelConfig();
     }
@@ -762,41 +769,7 @@ export class GameManager extends Component {
     }
 
     // === 原GameManager方法 ===
-    public onConfirmButtonClicked() {
-        if (this.blockSelectionUI) {
-            const cam = find('Canvas/Camera');
-            const gsm = cam?.getComponent(GameStartMove);
-            if (gsm) {
-                gsm.slideDibanDownAndHide();
-            } else {
-                // Fallback: 若未挂载 GameStartMove,直接关闭
-                this.blockSelectionUI.active = false;
-            }
-        }
-
-        // Camera move back up with smooth animation
-        const camNode = find('Canvas/Camera');
-        const gsm = camNode?.getComponent(GameStartMove);
-        gsm?.moveUpSmooth();
-
-        if (this.preparingNextWave) {
-            // 进入下一波
-            this.preparingNextWave = false;
-            this.enemyController.showStartWavePromptUI();  // 弹 startWaveUI 后自动 startGame()
-            this.nextWave();                               // 更新 wave 计数 & total
-            return;
-        }
-
-        // ---------- 首波逻辑(原有代码) ----------
-        const gridContainer = find('Canvas/GameLevelUI/GameArea/GridContainer');
-        if (gridContainer) {
-            gridContainer.active = true;
-        }
-        
-        this.preservePlacedBlocks();
-
-        this.startGame();
-    }
+    // onConfirmButtonClicked方法已移除,逻辑已整合到handleConfirmAction中
     
     private preservePlacedBlocks() {
         const blockController = find('Canvas/GameLevelUI/BlockController');
@@ -1154,7 +1127,16 @@ export class GameManager extends Component {
 
     /** 显示下一波提示并在短暂延迟后开始下一波 */
     private showNextWavePrompt() {
-        this.openBlockSelectionUIForNextWave();   // 只打开布阵,不弹 StartWaveUI
+        this.showBlockSelectionForNextWave();   // 使用新的方法
+    }
+
+    // 显示方块选择UI用于下一波
+    private showBlockSelectionForNextWave() {
+        if (this.blockSelectionComponent) {
+            this.blockSelectionComponent.showBlockSelection(true);
+            this.preparingNextWave = true;
+            this.enemyController.pauseSpawning();   // 保险
+        }
     }
 
     /** 敌人被消灭时由 EnemyController 调用 */
@@ -1267,11 +1249,30 @@ export class GameManager extends Component {
         };
     }
 
-    private openBlockSelectionUIForNextWave() {
-        if (this.blockSelectionUI) this.blockSelectionUI.active = true;
-        const grid = find('Canvas/GameLevelUI/GameArea/GridContainer');
-        if (grid) grid.active = true;
-        this.preparingNextWave = true;
-        this.enemyController.pauseSpawning();   // 保险
+    // 初始化GameBlockSelection组件
+    private initGameBlockSelection() {
+        if (this.gameBlockSelection) {
+            this.blockSelectionComponent = this.gameBlockSelection.getComponent(GameBlockSelection);
+            if (this.blockSelectionComponent) {
+                // 设置确认回调
+                this.blockSelectionComponent.setConfirmCallback(() => {
+                    this.handleConfirmAction();
+                });
+            }
+        }
+    }
+
+    // 处理确认操作(替代原来的onConfirmButtonClicked)
+    private handleConfirmAction() {
+        if (this.preparingNextWave) {
+            // 进入下一波
+            this.preparingNextWave = false;
+            this.enemyController.showStartWavePromptUI();  // 弹 startWaveUI 后自动 startGame()
+            this.nextWave();                               // 更新 wave 计数 & total
+            return;
+        }
+
+        // ---------- 首波逻辑(原有代码) ----------
+        this.startGame();
     }
 } 

Some files were not shown because too many files changed in this diff