181404010226 vor 4 Monaten
Ursprung
Commit
32bc65f16d

+ 0 - 130
assets/resources/data/excel/BallController导入修复说明.md

@@ -1,130 +0,0 @@
-# BallController配置导入修复说明
-
-## 问题描述
-用户报告在使用 `config_manager.py` 导入 `BallController标准配置表.xlsx` 时遇到导入失败的问题,虽然能识别内容但在转换过程中出现错误。
-
-## 问题根源
-原始的 `config_manager.py` 中的 `_set_config_mapping_for_files()` 方法没有为BallController配置文件设置专门的参数映射,导致:
-1. 文件被识别为默认的横向格式,但BallController使用纵向格式(参数名-数值)
-2. 参数类型映射为空,无法正确解析Excel中的参数
-3. 参数名不匹配,导致大部分参数无法被正确读取
-
-## 修复内容
-
-### 1. 添加BallController配置映射
-在 `config_manager.py` 的 `_set_config_mapping_for_files()` 方法中添加了专门的BallController配置映射:
-
-```python
-elif 'ballcontroller' in filename or '球控制' in filename or '标准配置表' in filename:
-    # BallController配置映射(纵向格式:参数名-数值)
-    self.current_mapping = {
-        'format_type': 'vertical',
-        'param_types': {
-            'baseSpeed': float,
-            'maxReflectionRandomness': float,
-            'antiTrapTimeWindow': float,
-            'antiTrapHitThreshold': int,
-            'deflectionAttemptThreshold': int,
-            'antiTrapDeflectionMultiplier': float,
-            'FIRE_COOLDOWN': float,
-            'ballRadius': float,
-            'gravityScale': float,
-            'linearDamping': float,
-            'angularDamping': float,
-            'colliderGroup': int,
-            'colliderTag': int,
-            'friction': float,
-            'restitution': float,
-            'safeDistance': float,
-            'edgeOffset': float,
-            'sensor': bool,
-            'maxAttempts': int
-        }
-    }
-```
-
-### 2. 支持的参数
-修复后的系统现在能正确识别和导入以下19个BallController参数:
-
-| 参数名 | 类型 | 描述 |
-|--------|------|------|
-| baseSpeed | float | 基础速度 |
-| maxReflectionRandomness | float | 最大反射随机性 |
-| antiTrapTimeWindow | float | 反陷阱时间窗口 |
-| antiTrapHitThreshold | int | 反陷阱碰撞阈值 |
-| deflectionAttemptThreshold | int | 偏转尝试阈值 |
-| antiTrapDeflectionMultiplier | float | 反陷阱偏转倍数 |
-| FIRE_COOLDOWN | float | 发射冷却时间 |
-| ballRadius | float | 球体半径 |
-| gravityScale | float | 重力缩放 |
-| linearDamping | float | 线性阻尼 |
-| angularDamping | float | 角度阻尼 |
-| colliderGroup | int | 碰撞器组 |
-| colliderTag | int | 碰撞器标签 |
-| friction | float | 摩擦力 |
-| restitution | float | 弹性系数 |
-| safeDistance | float | 安全距离 |
-| edgeOffset | float | 边缘偏移 |
-| sensor | bool | 传感器模式 |
-| maxAttempts | int | 最大尝试次数 |
-
-## 使用方法
-
-### 1. 启动配置管理器
-```bash
-cd d:\CocosGame\Pong\assets\resources\data\excel
-python config_manager.py
-```
-
-### 2. 导入BallController配置
-1. 在GUI界面中点击"浏览文件"或"扫描项目文件"
-2. 选择 `BallController标准配置表.xlsx` 文件
-3. 点击"预览选中文件"查看解析结果
-4. 确认无误后点击"导入配置"完成导入
-
-### 3. 验证导入结果
-导入成功后,系统会:
-- 显示"成功读取配置,共 19 个参数"
-- 列出所有参数及其值和数据类型
-- 生成对应的JSON配置文件
-
-## 测试验证
-
-可以使用提供的测试脚本验证修复效果:
-```bash
-python test_ballcontroller_import.py
-```
-
-测试脚本会:
-1. 自动检测BallController配置映射
-2. 读取Excel文件并解析所有参数
-3. 验证参数完整性和数据类型正确性
-4. 输出JSON格式的配置数据
-
-## 修复前后对比
-
-| 项目 | 修复前 | 修复后 |
-|------|--------|--------|
-| 识别文件类型 | ❌ 默认横向格式 | ✅ 正确识别为纵向格式 |
-| 参数映射 | ❌ 空映射 | ✅ 完整的19个参数映射 |
-| 读取参数数量 | ❌ 仅7个参数 | ✅ 全部19个参数 |
-| 数据类型转换 | ❌ 部分错误 | ✅ 全部正确 |
-| 布尔值处理 | ❌ 字符串 | ✅ 正确的布尔值 |
-| 导入成功率 | ❌ 失败 | ✅ 100%成功 |
-
-## 注意事项
-
-1. **文件命名**:确保Excel文件名包含 `ballcontroller`、`球控制` 或 `标准配置表` 关键词
-2. **文件格式**:保持纵向格式(参数名在A列,数值在B列)
-3. **数据类型**:确保Excel中的数值格式正确(数字、布尔值等)
-4. **参数完整性**:所有19个参数都应该在Excel文件中存在
-
-## 总结
-
-通过添加专门的BallController配置映射,修复了导入失败的问题。现在 `config_manager.py` 能够:
-- 正确识别BallController配置文件
-- 完整读取所有19个参数
-- 正确转换数据类型
-- 成功生成JSON配置文件
-
-用户现在可以正常使用GUI配置管理器导入BallController的Excel配置,无需再使用命令行脚本。

+ 0 - 11
assets/resources/data/excel/BallController导入修复说明.md.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "1.0.1",
-  "importer": "text",
-  "imported": true,
-  "uuid": "33874a85-2f45-4030-ba86-59666b9f757c",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 141
assets/resources/data/excel/BallController配置表说明.md

@@ -1,141 +0,0 @@
- BallController配置表说明文档
-
-## 概述
-本配置表用于配置游戏中小球控制器(BallController)的各项参数,策划可以通过调整这些参数来平衡游戏难度和体验。
-
-## 文件说明
-- **文件位置**: `assets/resources/data/excel/BallController配置表.csv`
-- **对应脚本**: `assets/scripts/CombatSystem/BallController.ts`
-- **格式说明**: 第一行为参数名称,第二行为中文翻译,第三行开始为具体配置数据
-
-## 参数详细说明
-
-### 核心运动参数
-
-#### baseSpeed (基础球速)
-- **默认值**: 60
-- **推荐范围**: 30-200
-- **说明**: 控制小球的基础移动速度,直接影响游戏节奏
-- **调整建议**: 
-  - 数值越大游戏越快,难度越高
-  - 新手关卡建议使用较低数值(30-50)
-  - 高难度关卡可使用较高数值(100-200)
-
-#### maxReflectionRandomness (反弹随机偏移角度)
-- **默认值**: 0.2
-- **推荐范围**: 0-1
-- **说明**: 球反弹时的随机偏移最大角度(弧度),增加游戏随机性
-- **调整建议**:
-  - 0表示完全规律反弹
-  - 0.2-0.5适合大多数情况
-  - 过高会导致球运动过于随机
-
-### 防围困机制参数
-
-#### antiTrapTimeWindow (防围困检测时间窗口)
-- **默认值**: 5.0秒
-- **推荐范围**: 3-10秒
-- **说明**: 检测球是否被困的时间窗口
-- **调整建议**: 时间越短,防围困机制越敏感
-
-#### antiTrapHitThreshold (防围困撞击阈值)
-- **默认值**: 5次
-- **推荐范围**: 3-10次
-- **说明**: 在时间窗口内连续撞击多少次后触发防围困
-- **调整建议**: 次数越少,防围困越容易触发
-
-#### deflectionAttemptThreshold (偏移尝试次数阈值)
-- **默认值**: 3次
-- **推荐范围**: 1-5次
-- **说明**: 偏移尝试次数达到后使用穿透而非偏移
-- **调整建议**: 影响防围困的处理方式
-
-#### antiTrapDeflectionMultiplier (防围困偏移强度倍数)
-- **默认值**: 3.0
-- **推荐范围**: 1.5-5.0
-- **说明**: 防围困偏移的强度倍数
-- **调整建议**: 数值越大,偏移效果越明显
-
-### 战斗系统参数
-
-#### FIRE_COOLDOWN (子弹发射冷却时间)
-- **默认值**: 0.05秒
-- **推荐范围**: 0.01-0.2秒
-- **说明**: 方块发射子弹的间隔时间
-- **调整建议**: 
-  - 数值越小,子弹发射越频繁
-  - 影响游戏的战斗节奏
-
-### 物理系统参数
-
-#### ballRadius (球半径)
-- **默认值**: 25
-- **推荐范围**: 15-40
-- **说明**: 小球的碰撞半径
-- **调整建议**: 影响碰撞检测的精度和游戏难度
-
-#### restitution (弹性系数)
-- **默认值**: 1
-- **推荐范围**: 0.8-1.0
-- **说明**: 碰撞弹性系数,1为完全弹性碰撞
-- **调整建议**: 数值越小,球的弹跳越弱
-
-#### linearDamping (线性阻尼)
-- **默认值**: 0
-- **推荐范围**: 0-0.1
-- **说明**: 刚体线性阻尼,0表示无阻尼
-- **调整建议**: 通常保持为0以保持球的恒定速度
-
-### 生成系统参数
-
-#### safeDistance (安全距离)
-- **默认值**: 20
-- **推荐范围**: 10-50
-- **说明**: 小球生成时与方块的最小距离
-- **调整建议**: 避免球生成时立即碰撞
-
-#### edgeOffset (边缘偏移)
-- **默认值**: 20
-- **推荐范围**: 10-30
-- **说明**: 距离游戏区域边缘的偏移量
-- **调整建议**: 避免球生成在边缘位置
-
-#### maxAttempts (最大尝试次数)
-- **默认值**: 50
-- **推荐范围**: 20-100
-- **说明**: 寻找有效生成位置的最大尝试次数
-- **调整建议**: 影响生成算法的性能
-
-### 系统参数
-
-#### checkInterval (检查间隔)
-- **默认值**: 1.0秒
-- **推荐范围**: 0.5-2.0秒
-- **说明**: 状态检查的时间间隔
-- **调整建议**: 影响系统检查的频率
-
-## 使用建议
-
-### 难度调整
-1. **简单难度**: baseSpeed=40, maxReflectionRandomness=0.1
-2. **普通难度**: baseSpeed=60, maxReflectionRandomness=0.2
-3. **困难难度**: baseSpeed=100, maxReflectionRandomness=0.3
-4. **地狱难度**: baseSpeed=150, maxReflectionRandomness=0.4
-
-### 关卡设计
-- 早期关卡建议使用较低的球速和较强的防围困机制
-- 后期关卡可以适当提高球速,减弱防围困机制
-- 特殊关卡可以调整物理参数创造独特体验
-
-## 注意事项
-
-1. **性能考虑**: 过低的冷却时间可能影响性能
-2. **平衡性**: 极端数值可能破坏游戏平衡
-3. **测试建议**: 每次调整后都应进行充分测试
-4. **备份**: 修改前请备份原始配置
-
-## 更新日志
-
-- 2024-01-XX: 初始版本创建
-- 包含20个核心配置参数
-- 支持完整的球控制器功能配置

+ 0 - 11
assets/resources/data/excel/BallController配置表说明.md.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "1.0.1",
-  "importer": "text",
-  "imported": true,
-  "uuid": "c77fffcf-7e29-4e38-b678-0f102503d752",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 128
assets/resources/data/excel/BallController配置说明.md

@@ -1,128 +0,0 @@
-# BallController Excel配置系统使用说明
-
-## 概述
-
-本系统为 `BallController.ts` 提供了基于Excel的配置管理方案,解决了原有复杂Excel表格导入困难的问题。
-
-## 文件结构
-
-```
-excel/
-├── BallController标准配置表.xlsx    # 标准化配置表格
-├── import_ball_config.py            # 配置导入脚本
-├── BallController配置说明.md         # 本说明文档
-└── BallController配置表.xlsx         # 原始复杂表格(已废弃)
-```
-
-## 配置参数说明
-
-### 速度相关
-- `baseSpeed`: 球的基础速度 (默认: 30)
-- `maxReflectionRandomness`: 反射随机性最大值 (默认: 0.2)
-
-### 防围困机制
-- `antiTrapTimeWindow`: 防围困时间窗口 (默认: 5秒)
-- `antiTrapHitThreshold`: 防围困碰撞阈值 (默认: 5次)
-- `deflectionAttemptThreshold`: 偏转尝试阈值 (默认: 3次)
-- `antiTrapDeflectionMultiplier`: 防围困偏转倍数 (默认: 3)
-
-### 发射控制
-- `FIRE_COOLDOWN`: 发射冷却时间 (默认: 0.05秒)
-
-### 物理属性
-- `ballRadius`: 球的半径 (默认: 25)
-- `gravityScale`: 重力缩放 (默认: 0)
-- `linearDamping`: 线性阻尼 (默认: 0)
-- `angularDamping`: 角阻尼 (默认: 0)
-
-### 碰撞检测
-- `colliderGroup`: 碰撞组 (默认: 1)
-- `colliderTag`: 碰撞标签 (默认: 1)
-- `friction`: 摩擦力 (默认: 0)
-- `restitution`: 弹性系数 (默认: 1)
-- `sensor`: 是否为传感器 (默认: false)
-
-### 生成参数
-- `safeDistance`: 安全距离 (默认: 20)
-- `edgeOffset`: 边缘偏移 (默认: 20)
-- `maxAttempts`: 最大尝试次数 (默认: 50)
-
-## 使用方法
-
-### 1. 修改配置
-
-1. 打开 `BallController标准配置表.xlsx`
-2. 在"数值"列中修改对应参数的值
-3. 保存Excel文件
-
-**注意事项:**
-- 不要修改"参数名"列的内容
-- 布尔值请使用 `true` 或 `false`
-- 数值参数请使用数字格式,避免被Excel识别为日期
-
-### 2. 导入配置
-
-在Excel目录下运行导入脚本:
-
-```bash
-python import_ball_config.py
-```
-
-成功后会看到类似输出:
-```
-✅ 配置导入成功!
-📁 Excel文件: BallController标准配置表.xlsx
-📄 JSON文件: ../ballController.json
-📊 导入了 19 个配置参数
-```
-
-### 3. 验证配置
-
-导入后的JSON配置文件位于:`../ballController.json`
-
-可以检查该文件确认配置是否正确导入。
-
-## 故障排除
-
-### 常见问题
-
-1. **Excel文件格式错误**
-   - 确保表格只有两列:"参数名" 和 "数值"
-   - 不要添加额外的描述列或标题行
-
-2. **数值格式问题**
-   - 避免Excel自动将数字识别为日期
-   - 布尔值使用 `true`/`false` 而不是 `TRUE`/`FALSE`
-
-3. **导入脚本错误**
-   - 确保安装了 `pandas` 和 `openpyxl` 库
-   - 检查文件路径是否正确
-
-### 依赖安装
-
-如果缺少依赖库,请运行:
-```bash
-pip install pandas openpyxl
-```
-
-## 与原系统的区别
-
-| 特性 | 原始表格 | 标准表格 |
-|------|----------|----------|
-| 列数 | 6列(包含描述) | 2列(精简) |
-| 格式复杂度 | 高 | 低 |
-| 导入成功率 | 低(格式问题) | 高 |
-| 维护难度 | 高 | 低 |
-| 数据类型错误 | 常见 | 罕见 |
-
-## 技术实现
-
-- **Excel读取**: 使用 `pandas.read_excel()` 读取标准格式表格
-- **数据转换**: 自动处理数值和布尔类型转换
-- **JSON输出**: 生成符合 `BallControllerConfig` 接口的JSON配置
-- **错误处理**: 提供详细的错误信息和验证机制
-
----
-
-*最后更新: 2024年*
-*版本: 1.0*

+ 0 - 11
assets/resources/data/excel/BallController配置说明.md.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "1.0.1",
-  "importer": "text",
-  "imported": true,
-  "uuid": "7415a9dd-324a-4b4e-b772-18069b358835",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

BIN
assets/resources/data/excel/技能配置表.xlsx


BIN
assets/resources/data/excel/方块武器配置/~$方块武器配置表.xlsx


+ 2 - 2
assets/resources/data/excel/验证BallController导入修复.py.meta → assets/resources/data/excel/方块武器配置/~$方块武器配置表.xlsx.meta

@@ -2,10 +2,10 @@
   "ver": "1.0.0",
   "importer": "*",
   "imported": true,
-  "uuid": "3bed2600-db8f-47ba-b829-3a4ff64071e4",
+  "uuid": "1bd54b45-2df3-499a-a775-1720b8084173",
   "files": [
     ".json",
-    ".py"
+    ".xlsx"
   ],
   "subMetas": {},
   "userData": {}

+ 0 - 104
assets/resources/data/excel/验证BallController导入修复.py

@@ -1,104 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-BallController配置导入修复验证脚本
-用于验证config_manager.py中的BallController导入功能是否正常工作
-"""
-
-import sys
-import os
-import json
-from pathlib import Path
-
-# 添加当前目录到Python路径
-sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
-
-def test_ballcontroller_import():
-    """测试BallController配置导入功能"""
-    print("=== BallController配置导入修复验证 ===")
-    
-    # 检查必要文件是否存在
-    excel_file = Path("BallController标准配置表.xlsx")
-    json_file = Path("../ballController.json")
-    
-    if not excel_file.exists():
-        print(f"❌ Excel文件不存在: {excel_file}")
-        return False
-    
-    if not json_file.exists():
-        print(f"❌ JSON文件不存在: {json_file}")
-        return False
-    
-    print(f"✓ Excel文件存在: {excel_file}")
-    print(f"✓ JSON文件存在: {json_file}")
-    
-    # 读取JSON配置
-    try:
-        with open(json_file, 'r', encoding='utf-8') as f:
-            config_data = json.load(f)
-        print(f"✓ JSON文件读取成功")
-    except Exception as e:
-        print(f"❌ JSON文件读取失败: {e}")
-        return False
-    
-    # 验证必要参数
-    expected_params = [
-        'baseSpeed', 'maxReflectionRandomness', 'antiTrapTimeWindow', 'antiTrapHitThreshold',
-        'deflectionAttemptThreshold', 'antiTrapDeflectionMultiplier', 'FIRE_COOLDOWN', 'ballRadius',
-        'gravityScale', 'linearDamping', 'angularDamping', 'colliderGroup',
-        'colliderTag', 'friction', 'restitution', 'safeDistance',
-        'edgeOffset', 'sensor', 'maxAttempts'
-    ]
-    
-    missing_params = [param for param in expected_params if param not in config_data]
-    if missing_params:
-        print(f"❌ 缺少参数: {missing_params}")
-        return False
-    
-    print(f"✓ 所有19个参数都存在")
-    
-    # 验证数据类型
-    type_checks = {
-        'baseSpeed': (int, float),
-        'sensor': (bool,),
-        'colliderGroup': (int,),
-        'maxAttempts': (int,)
-    }
-    
-    for param, expected_types in type_checks.items():
-        actual_type = type(config_data[param])
-        if actual_type not in expected_types:
-            print(f"❌ 参数 {param} 类型错误: 期望 {expected_types}, 实际 {actual_type}")
-            return False
-    
-    print(f"✓ 关键参数数据类型正确")
-    
-    # 显示配置摘要
-    print(f"\n=== 配置摘要 ===")
-    print(f"基础速度: {config_data['baseSpeed']}")
-    print(f"球半径: {config_data['ballRadius']}")
-    print(f"重力缩放: {config_data['gravityScale']}")
-    print(f"传感器模式: {config_data['sensor']}")
-    print(f"碰撞组: {config_data['colliderGroup']}")
-    
-    print(f"\n✅ BallController配置导入功能验证通过!")
-    return True
-
-def main():
-    """主函数"""
-    try:
-        success = test_ballcontroller_import()
-        if success:
-            print(f"\n🎉 修复验证成功!BallController配置导入功能正常工作。")
-            return 0
-        else:
-            print(f"\n❌ 修复验证失败!请检查配置导入功能。")
-            return 1
-    except Exception as e:
-        print(f"\n💥 验证过程中发生错误: {e}")
-        import traceback
-        traceback.print_exc()
-        return 1
-
-if __name__ == "__main__":
-    exit(main())

+ 77 - 4
assets/scripts/CombatSystem/BlockManager.ts

@@ -1,4 +1,4 @@
-import { _decorator, Component, Node, Prefab, instantiate, Vec3, EventTouch, Color, Vec2, UITransform, find, Rect, Label, Size, Sprite, SpriteFrame, resources, Button, Collider2D, Material } from 'cc';
+import { _decorator, Component, Node, Prefab, instantiate, Vec3, EventTouch, Color, Vec2, UITransform, find, Rect, Label, Size, Sprite, SpriteFrame, resources, Button, Collider2D, Material, tween } from 'cc';
 import { ConfigManager, WeaponConfig } from '../Core/ConfigManager';
 import { SaveDataManager } from '../LevelSystem/SaveDataManager';
 import { LevelSessionManager } from '../Core/LevelSessionManager';
@@ -68,7 +68,7 @@ export class BlockManager extends Component {
     // 存储网格节点信息
     private gridNodes: Node[][] = [];
     // 网格间距
-    private gridSpacing = 54;
+    private gridSpacing = 54; // 默认值,将在initGridInfo中动态计算
     // 不参与占用的节点名称列表
     private readonly NON_BLOCK_NODES: string[] = ['Weapon', 'Price'];
     // 临时保存方块的原始占用格子
@@ -301,16 +301,44 @@ export class BlockManager extends Component {
             }
         }
         
+        // 动态计算网格间距,适应不同分辨率
+        this.calculateGridSpacing();
+        
+        this.gridInitialized = true;
+    }
+
+    // 动态计算网格间距
+    private calculateGridSpacing() {
+        // 优先使用相邻行之间的距离计算间距
         if (this.GRID_ROWS > 1 && this.GRID_COLS > 0) {
             if (this.gridNodes[0][0] && this.gridNodes[1][0]) {
                 const pos1 = this.gridNodes[0][0].position;
                 const pos2 = this.gridNodes[1][0].position;
                 this.gridSpacing = Math.abs(pos2.y - pos1.y);
+                console.log(`动态计算网格间距(行间距): ${this.gridSpacing}`);
+                return;
             }
         }
         
-        this.gridInitialized = true;
-    }
+        // 如果行间距计算失败,尝试使用相邻列之间的距离
+        if (this.GRID_COLS > 1 && this.GRID_ROWS > 0) {
+            if (this.gridNodes[0][0] && this.gridNodes[0][1]) {
+                const pos1 = this.gridNodes[0][0].position;
+                const pos2 = this.gridNodes[0][1].position;
+                this.gridSpacing = Math.abs(pos2.x - pos1.x);
+                console.log(`动态计算网格间距(列间距): ${this.gridSpacing}`);
+                return;
+            }
+        }
+        
+        // 如果都失败了,保持默认值
+         console.warn(`无法动态计算网格间距,使用默认值: ${this.gridSpacing}`);
+     }
+
+     // 获取当前网格间距
+     public getGridSpacing(): number {
+         return this.gridSpacing;
+     }
     
     // 初始化网格占用情况
     initGridOccupationMap() {
@@ -475,6 +503,12 @@ export class BlockManager extends Component {
                     return;
                 }
                 
+                // 检查方块是否正在被拖动,如果是则隐藏价格标签
+                if (block['isDragging']) {
+                    dbNode.active = false;
+                    return;
+                }
+                
                 dbNode.active = true;
                 
                 const worldPos = block.parent.getComponent(UITransform).convertToWorldSpaceAR(block.position);
@@ -536,6 +570,45 @@ export class BlockManager extends Component {
         return success;
     }
     
+    // 显示金币不足时的价格标签闪烁效果
+    showInsufficientCoinsEffect(block: Node) {
+        const priceNode = this.blockPriceMap.get(block);
+        if (!priceNode) {
+            console.warn('[BlockManager] 找不到方块对应的价格标签');
+            return;
+        }
+        
+        const label = priceNode.getComponent(Label);
+        if (!label) {
+            console.warn('[BlockManager] 价格节点缺少Label组件');
+            return;
+        }
+        
+        // 保存原始颜色
+        const originalColor = label.color.clone();
+        
+        // 设置红色
+        const redColor = new Color(255, 0, 0, 255);
+        
+        // 创建闪烁动画:变红 -> 恢复原色,重复3次,总时长2秒
+        tween(label)
+            .to(0.2, { color: redColor })
+            .to(0.2, { color: originalColor })
+            .to(0.2, { color: redColor })
+            .to(0.2, { color: originalColor })
+            .to(0.2, { color: redColor })
+            .to(1.0, { color: originalColor })
+            .start();
+        
+        // 发送显示Toast事件
+        EventBus.getInstance().emit(GameEvents.SHOW_TOAST, {
+            message: '金币不足',
+            duration: 2.0
+        });
+        
+        console.log('[BlockManager] 显示金币不足效果');
+    }
+    
     // 归还玩家金币
     refundPlayerCoins(amount: number) {
         this.session.addCoins(amount);

+ 17 - 2
assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts

@@ -612,6 +612,9 @@ export class GameBlockSelection extends Component {
             this.blockStartPos.set(block.position);
             this.currentDragBlock['startLocation'] = this.blockManager.blockLocations.get(block);
             
+            // 设置拖动状态,隐藏价格标签
+            block['isDragging'] = true;
+            
             block.setSiblingIndex(block.parent.children.length - 1);
             // 拖拽开始时禁用碰撞体
             const collider = block.getComponent(Collider2D);
@@ -657,6 +660,9 @@ export class GameBlockSelection extends Component {
                     this.returnBlockToOriginalPosition();
                 }
                 
+                // 清除拖动状态,恢复价格标签显示
+                block['isDragging'] = false;
+                
                 this.currentDragBlock = null;
                 // 拖拽结束时恢复碰撞体
                 const collider = block.getComponent(Collider2D);
@@ -670,6 +676,10 @@ export class GameBlockSelection extends Component {
         block.on(Node.EventType.TOUCH_CANCEL, () => {
             if (this.currentDragBlock) {
                 this.returnBlockToOriginalPosition();
+                
+                // 清除拖动状态,恢复价格标签显示
+                block['isDragging'] = false;
+                
                 this.currentDragBlock = null;
                 // 拖拽取消时恢复碰撞体
                 const collider = block.getComponent(Collider2D);
@@ -843,6 +853,8 @@ export class GameBlockSelection extends Component {
                         // 合成失败不影响方块放置,只记录错误
                     }
                 } else {
+                    // 金币不足时显示价格标签闪烁效果和Toast提示
+                    this.blockManager.showInsufficientCoinsEffect(this.currentDragBlock);
                     this.returnBlockToOriginalPosition();
                 }
             }
@@ -866,6 +878,9 @@ export class GameBlockSelection extends Component {
             this.currentDragBlock.position = this.blockStartPos.clone();
         }
         
+        // 清除拖动状态,恢复价格标签显示
+        this.currentDragBlock['isDragging'] = false;
+        
         this.blockManager.showPriceLabel(this.currentDragBlock);
         
         const dbNode = this.currentDragBlock['dbNode'];
@@ -901,7 +916,7 @@ export class GameBlockSelection extends Component {
         this.debugGraphics.lineWidth = 2;
         
         // 通过BlockManager获取网格信息来绘制吸附范围
-        const gridSpacing = 54; // 网格间距
+        const gridSpacing = this.blockManager.getGridSpacing(); // 动态获取网格间距
         const snapRange = gridSpacing * 0.8; // 吸附范围
         
         // 遍历所有网格位置,绘制吸附范围
@@ -932,7 +947,7 @@ export class GameBlockSelection extends Component {
         this.debugGraphics.lineWidth = 3;
         
         const blockParts = this.blockManager.getBlockParts(block);
-        const gridSpacing = 54; // 网格间距
+        const gridSpacing = this.blockManager.getGridSpacing(); // 动态获取网格间距
         const snapRange = gridSpacing * 0.6; // 吸附范围
         
         blockParts.forEach(part => {

+ 8 - 8
assets/scripts/Core/PhysicsManager.ts

@@ -22,14 +22,14 @@ export class PhysicsManager extends BaseSingleton {
         // 设置物理系统的重力为零(因为是2D平面游戏)
         PhysicsSystem2D.instance.gravity = new Vec2(0, 0);
         
-        // // // // 调试绘制
-        // PhysicsSystem2D.instance.debugDrawFlags = this.debugDraw ?
-        //     (EPhysics2DDrawFlags.Aabb |
-        //      EPhysics2DDrawFlags.Pair |
-        //      EPhysics2DDrawFlags.CenterOfMass |
-        //      EPhysics2DDrawFlags.Joint |
-        //      EPhysics2DDrawFlags.Shape) :
-        //     EPhysics2DDrawFlags.None;
+        // // // 调试绘制
+        PhysicsSystem2D.instance.debugDrawFlags = this.debugDraw ?
+            (EPhysics2DDrawFlags.Aabb |
+             EPhysics2DDrawFlags.Pair |
+             EPhysics2DDrawFlags.CenterOfMass |
+             EPhysics2DDrawFlags.Joint |
+             EPhysics2DDrawFlags.Shape) :
+            EPhysics2DDrawFlags.None;
     }
 
     /**