浏览代码

新方块标签反悔放置

181404010226 5 月之前
父节点
当前提交
b51a272ac4

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

@@ -154,7 +154,115 @@ export class BallController extends Component {
 
         this.initialized = true;
     }
+    
+    // 创建额外的小球(不替换现有的小球)
+    public createAdditionalBall() {
+        if (!this.ballPrefab) {
+            console.error('无法创建额外小球:ballPrefab 未设置');
+            return;
+        }
+
+        // 实例化新的小球
+        const newBall = instantiate(this.ballPrefab);
+        newBall.name = 'AdditionalBall';
+        
+        // 将小球添加到GameArea中
+        const gameArea = find('Canvas/GameLevelUI/GameArea');
+        if (gameArea) {
+            gameArea.addChild(newBall);
+        } else {
+            this.node.addChild(newBall);
+        }
+
+        // 随机位置小球
+        this.positionAdditionalBall(newBall);
+
+        // 设置球的碰撞组件
+        this.setupBallCollider(newBall);
+        
+        // 设置初始方向和速度
+        this.initializeBallDirection(newBall);
+        
+        console.log('创建了额外的小球');
+        return newBall;
+    }
+
+    // 为额外小球设置随机位置
+    private positionAdditionalBall(ball: Node) {
+        if (!ball) return;
+
+        const transform = ball.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;
+
+        // 获取GameArea节点
+        const gameArea = find('Canvas/GameLevelUI/GameArea');
+        if (!gameArea) {
+            return;
+        }
+        
+        // 随机生成位置
+        const randomX = Math.random() * (maxX - minX) + minX;
+        const randomY = Math.random() * (maxY - minY) + minY;
+        
+        // 将世界坐标转换为相对于GameArea的本地坐标
+        const localPos = gameArea.getComponent(UITransform).convertToNodeSpaceAR(new Vec3(randomX, randomY, 0));
+        ball.position = localPos;
+    }
 
+    // 为额外小球设置碰撞组件
+    private setupBallCollider(ball: Node) {
+        // 确保有碰撞组件
+        let collider = ball.getComponent(CircleCollider2D);
+        if (!collider) {
+            collider = ball.addComponent(CircleCollider2D);
+        }
+        
+        // 设置碰撞属性
+        collider.radius = ball.getComponent(UITransform)?.width / 2 || 25;
+        collider.group = 1; // 设置为球的碰撞组
+        collider.sensor = false;
+        
+        // 添加刚体组件
+        let rigidBody = ball.getComponent(RigidBody2D);
+        if (!rigidBody) {
+            rigidBody = ball.addComponent(RigidBody2D);
+        }
+        
+        // 设置刚体属性
+        rigidBody.type = 2; // 2 = 动态刚体
+        rigidBody.allowSleep = false;
+        rigidBody.gravityScale = 0;
+        rigidBody.linearDamping = 0;
+        rigidBody.angularDamping = 0;
+        rigidBody.fixedRotation = true;
+        
+        // 添加碰撞回调
+        if (collider) {
+            collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
+        }
+    }
+
+    // 为额外小球初始化方向和速度
+    private initializeBallDirection(ball: Node) {
+        // 随机初始方向
+        const angle = Math.random() * Math.PI * 2; // 0-2π之间的随机角度
+        const direction = new Vec2(Math.cos(angle), Math.sin(angle)).normalize();
+        
+        // 设置初始速度
+        const rigidBody = ball.getComponent(RigidBody2D);
+        if (rigidBody) {
+            rigidBody.linearVelocity = new Vec2(
+                direction.x * this.speed,
+                direction.y * this.speed
+            );
+        }
+    }
 
  
   

+ 28 - 2
assets/scripts/CombatSystem/BlockManager.ts

@@ -2,6 +2,7 @@ import { _decorator, Component, Node, Prefab, instantiate, Vec3, EventTouch, Vec
 import { ConfigManager, WeaponConfig } from '../Core/ConfigManager';
 import { SaveDataManager } from '../LevelSystem/SaveDataManager';
 import { LevelSessionManager } from '../Core/LevelSessionManager';
+import { BlockTag } from './BlockSelection/BlockTag';
 import { sp } from 'cc';
 const { ccclass, property } = _decorator;
 
@@ -231,6 +232,7 @@ export class BlockManager extends Component {
     
     // 在kuang下随机生成三个方块
     private generateRandomBlocksInKuang() {
+        // 清除kuang区域中的旧方块,但不清除已放置在网格中的方块的标签
         this.clearBlocks();
         
         // 检查配置管理器是否可用
@@ -316,6 +318,9 @@ export class BlockManager extends Component {
             this.setupBlockWeaponVisual(block, weaponConfig);
             
             this.setupDragEvents(block);
+            
+            // 为新生成的方块添加标签
+            BlockTag.addTag(block);
         }
         
         this.updateCoinDisplay();
@@ -477,7 +482,14 @@ export class BlockManager extends Component {
         const startLocation = this.currentDragBlock['startLocation'];
         
         if (this.isInKuangArea(touchPos)) {
-            this.returnBlockToKuang(startLocation);
+            // 检查是否有标签,只有有标签的方块才能放回kuang
+            if (BlockTag.hasTag(this.currentDragBlock)) {
+                this.returnBlockToKuang(startLocation);
+            } else {
+                // 没有标签的方块不能放回kuang,返回原位置
+                console.log(`[BlockManager] 方块 ${this.currentDragBlock.name} 没有标签,不能放回kuang区域`);
+                this.returnBlockToOriginalPosition();
+            }
         } else if (this.tryPlaceBlockToGrid(this.currentDragBlock)) {
             this.handleSuccessfulPlacement(startLocation);
         } else {
@@ -545,6 +557,9 @@ export class BlockManager extends Component {
             // 如果游戏已开始,添加锁定视觉提示
             if (this.gameStarted) {
                 this.addLockedVisualHint(this.currentDragBlock);
+                
+                // 游戏开始后放置的方块移除标签,不能再放回kuang
+                BlockTag.removeTag(this.currentDragBlock);
             }
 
             // 检查并执行合成
@@ -568,6 +583,9 @@ export class BlockManager extends Component {
                 // 如果游戏已开始,添加锁定视觉提示
                 if (this.gameStarted) {
                     this.addLockedVisualHint(this.currentDragBlock);
+                    
+                    // 游戏开始后放置的方块移除标签,不能再放回kuang
+                    BlockTag.removeTag(this.currentDragBlock);
                 }
 
                 // 检查并执行合成
@@ -928,6 +946,9 @@ export class BlockManager extends Component {
                     
                     this.moveBlockToPlacedBlocks(block);
                     this.addLockedVisualHint(block);
+                    
+                    // 游戏开始后放置的方块移除标签,不能再放回kuang
+                    BlockTag.removeTag(block);
                 }
             }
         }
@@ -989,7 +1010,6 @@ export class BlockManager extends Component {
         }
         
         // 根据武器类型或稀有度选择预制体
-        // 这里可以根据实际需求来选择不同的预制体
         // 目前简单地随机选择一个预制体
         const randomIndex = Math.floor(Math.random() * this.blockPrefabs.length);
         return this.blockPrefabs[randomIndex];
@@ -1140,6 +1160,12 @@ export class BlockManager extends Component {
     
     // 刷新方块 - 重新生成三个新的武器方块
     public refreshBlocks() {
+        // 移除PlacedBlocks容器中所有方块的标签
+        if (this.placedBlocksContainer && this.placedBlocksContainer.isValid) {
+            BlockTag.removeTagsInContainer(this.placedBlocksContainer);
+        }
+        
+        // 生成新的方块
         this.generateRandomBlocksInKuang();
     }
 

+ 90 - 0
assets/scripts/CombatSystem/BlockSelection/BlockTag.ts

@@ -0,0 +1,90 @@
+import { _decorator, Component, Node } from 'cc';
+const { ccclass, property } = _decorator;
+
+/**
+ * BlockTag - 管理方块标签,控制哪些方块可以放回kuang区域
+ * 只有带有标签的方块可以从游戏区域拖回kuang区域
+ */
+@ccclass('BlockTag')
+export class BlockTag {
+    // 存储带有标签的方块UUID
+    private static taggedBlocks: Set<string> = new Set<string>();
+
+    /**
+     * 为方块添加标签
+     * @param block 要添加标签的方块节点
+     */
+    public static addTag(block: Node): void {
+        if (!block) return;
+        
+        // 将方块UUID添加到标签集合中
+        this.taggedBlocks.add(block.uuid);
+        console.log(`[BlockTag] 为方块 ${block.name} (UUID: ${block.uuid}) 添加标签`);
+    }
+
+    /**
+     * 检查方块是否有标签
+     * @param block 要检查的方块节点
+     * @returns 如果方块有标签则返回true,否则返回false
+     */
+    public static hasTag(block: Node): boolean {
+        if (!block) return false;
+        
+        const hasTag = this.taggedBlocks.has(block.uuid);
+        return hasTag;
+    }
+
+    /**
+     * 移除方块的标签
+     * @param block 要移除标签的方块节点
+     */
+    public static removeTag(block: Node): void {
+        if (!block) return;
+        
+        if (this.taggedBlocks.has(block.uuid)) {
+            this.taggedBlocks.delete(block.uuid);
+            console.log(`[BlockTag] 移除方块 ${block.name} (UUID: ${block.uuid}) 的标签`);
+        }
+    }
+
+    /**
+     * 清除所有方块标签
+     */
+    public static clearAllTags(): void {
+        const count = this.taggedBlocks.size;
+        this.taggedBlocks.clear();
+        console.log(`[BlockTag] 清除了所有方块标签 (共 ${count} 个)`);
+    }
+
+    /**
+     * 获取当前标记的方块数量
+     */
+    public static getTaggedBlockCount(): number {
+        return this.taggedBlocks.size;
+    }
+    
+    /**
+     * 移除容器节点中所有方块的标签
+     * @param containerNode 包含方块的容器节点
+     */
+    public static removeTagsInContainer(containerNode: Node): void {
+        if (!containerNode || !containerNode.isValid) {
+            return;
+        }
+        
+        let removedCount = 0;
+        
+        // 遍历容器中的所有子节点
+        for (let i = 0; i < containerNode.children.length; i++) {
+            const block = containerNode.children[i];
+            if (this.hasTag(block)) {
+                this.removeTag(block);
+                removedCount++;
+            }
+        }
+        
+        if (removedCount > 0) {
+            console.log(`[BlockTag] 从容器 ${containerNode.name} 中移除了 ${removedCount} 个方块的标签`);
+        }
+    }
+}

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

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "0523e610-c6f8-4520-b8b7-4a96f921e2f6",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 19 - 4
assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts

@@ -5,6 +5,7 @@ import { BlockManager } from '../BlockManager';
 import { GameStartMove } from '../../Animations/GameStartMove';
 import { GameManager } from '../../LevelSystem/GameManager';
 import { GamePause } from '../GamePause';
+import { BlockTag } from './BlockTag';
 const { ccclass, property } = _decorator;
 
 @ccclass('GameBlockSelection')
@@ -216,11 +217,17 @@ export class GameBlockSelection extends Component {
             this.updateCoinDisplay();
             
             // 创建新的小球
-            if (this.ballController) {
-                this.ballController.createBall();
-                console.log(`新增小球成功,扣除${this.ADD_BALL_COST}金币`);
+            if (this.ballControllerNode) {
+                const ballController = this.ballControllerNode.getComponent(BallController);
+                if (ballController) {
+                    // 使用createAdditionalBall方法创建额外的小球,而不是替换现有的小球
+                    ballController.createAdditionalBall();
+                    console.log(`新增小球成功,扣除${this.ADD_BALL_COST}金币`);
+                } else {
+                    console.error('找不到BallController组件');
+                }
             } else {
-                console.error('找不到BallController,无法创建小球');
+                console.error('找不到BallController节点,无法创建小球');
             }
         }
     }
@@ -245,6 +252,14 @@ export class GameBlockSelection extends Component {
             
             // 刷新方块
             if (this.blockManager) {
+                // 找到PlacedBlocks容器
+                const placedBlocksContainer = find('Canvas/GameLevelUI/PlacedBlocks');
+                if (placedBlocksContainer) {
+                    // 移除已放置方块的标签
+                    BlockTag.removeTagsInContainer(placedBlocksContainer);
+                }
+                
+                // 刷新方块
                 this.blockManager.refreshBlocks();
                 console.log(`刷新方块成功,扣除${this.REFRESH_COST}金币`);
             } else {

+ 4 - 4
assets/scripts/CombatSystem/EnemyController.ts

@@ -506,10 +506,10 @@ export class EnemyController extends BaseSingleton {
         } else {
             // 如果没有引用,尝试查找GameManager
             const gameManagerNode = find('Canvas/GameManager');
-            if (gameManagerNode) {
+        if (gameManagerNode) {
                 const gameManager = gameManagerNode.getComponent(GameManager);
-                if (gameManager) {
-                    gameManager.gameOver();
+            if (gameManager) {
+                gameManager.gameOver();
                 }
             }
         }
@@ -599,7 +599,7 @@ export class EnemyController extends BaseSingleton {
             }
             
             if (this.gameManager.onEnemyKilled) {
-                this.gameManager.onEnemyKilled();
+            this.gameManager.onEnemyKilled();
             }
         }
     }

+ 1 - 0
assets/scripts/LevelSystem/GameManager.ts

@@ -12,6 +12,7 @@ import { BlockManager } from '../CombatSystem/BlockManager';
 import { LevelSessionManager } from '../Core/LevelSessionManager';
 import { GameStartMove } from '../Animations/GameStartMove';
 import { GameBlockSelection } from '../CombatSystem/BlockSelection/GameBlockSelection';
+import { BlockTag } from '../CombatSystem/BlockSelection/BlockTag';
 import { GamePause } from '../CombatSystem/GamePause';
 const { ccclass, property } = _decorator;