请通过 godot-mcp 在当前空项目中从头构建一个完整的俄罗斯方块游戏(Godot 4),并严格遵循以下要求,确保颜色区分和落点位置正确。
【核心要求】
1. 颜色区分:为 7 种方块(I, O, T, S, Z, J, L)分别指定以下 RGB 颜色(0~1):
- I: (0, 1, 1) 青色
- O: (1, 1, 0) 黄色
- T: (0.5, 0, 1) 紫色
- S: (0, 1, 0) 绿色
- Z: (1, 0, 0) 红色
- J: (0, 0, 1) 蓝色
- L: (1, 0.5, 0) 橙色
这些颜色必须同时用于活动块和固定块,且固定块存储的是颜色索引(1~7),绘制时从该数组中取色。
2. 坐标与位置修正:
- 棋盘尺寸:10 列 x 20 行,格子大小 CELL_SIZE = 32 像素。
- 棋盘容器 `GameBoard` (Node2D) 的 position 设为 (160, 80)(居中偏左)。
- 在 `GameBoard` 下的所有子节点(Grid 和 ActivePiece)的 position 必须为 (0,0),即它们的本地原点就是棋盘的左上角。
- 绘制活动块时,使用格子坐标 (col, row) 乘以 CELL_SIZE 得到本地坐标 (col*32, row*32),然后绘制矩形。
- 固定块用 TileMap,其 cell 坐标 (col, row) 对应 board[row][col],TileMap 的 position 也为 (0,0)。
- 下落速度、移动等所有操作的单位均为格子坐标(整数),不要混入像素值。
3. 旋转与墙踢:
- 顺时针旋转:先对形状二维数组进行转置,然后每行反转(即 matrix transpose + reverse each row)。
- 墙踢尝试顺序:先 (0,0),再 (-1,0),(1,0),(0,-1),(0,1),尝试任一偏移后若碰撞检测通过则应用。
- 碰撞检测函数必须正确处理边界(col 0~9,row 0~19)和已有方块。
4. 落点与固定:
- 当方块下移碰撞或硬降时,将其形状数据写入 board 数组,写入时使用当前 pos(格子坐标)加上形状内相对偏移。
- 写入后立即检查并消除满行,然后生成下一个方块。
- 消除行时,上方所有行整体下移,确保 board 数组更新正确(使用深拷贝或逐行复制)。
5. 游戏结束判定:
- 在 spawn_new_piece() 中,生成新方块时先检测其初始位置(通常在 (COLS/2 - 1, -1))是否碰撞,若碰撞则直接结束游戏。
【完整功能要求】
- 输入映射:move_left(左箭头/A),move_right(右箭头/D),move_down(下箭头/S),rotate_cw(上箭头/W,按下瞬间),hard_drop(空格,按下瞬间)。
- 开始界面:包含标题和“开始游戏”按钮,点击后切换到游戏场景。
- 游戏界面:包含棋盘、下一个方块预览(位于棋盘右侧)、当前分数和等级显示、游戏结束面板(含重新开始按钮)。
- 游戏逻辑:7-Bag随机生成,自动下落(速度随等级提升),左右移动(按住连续),旋转,硬降,软降加速(按住下箭头),消行计分(1行100,2行300,3行500,4行800,均乘以当前等级),等级每500分升1级。
- 绘制:活动块和预览块均通过 _draw() 绘制矩形(带黑色边框),固定块通过 TileMap 设置单元格(每个格子使用不同的 Tile,但你可以只用一个 TileSet,然后用颜色索引映射到不同编号,或者直接用 TileMap 的 modulate 修改颜色?为了简单,建议使用多个 Tile 或直接使用 draw_rect 绘制所有块,但 TileMap 更高效。本次要求使用 TileMap 绘制固定块,但为了颜色区分,你可以在 TileSet 中创建 7 个不同的 Tile,每个对应一种颜色,或者使用代码在 _draw 中绘制所有内容。为简化,此处统一使用 _draw 绘制所有方块(包括固定块)?但固定块较多,建议使用 TileMap。你可以创建一个 1x1 的 TileSet,然后通过 set_cell 并设置 tile 的 modulate 属性?Godot 4 中 TileMap 的 set_cell 可以传入自定义数据,但最简单的方法:使用多个 Tile,每个颜色一个。或者直接使用 draw_rect 在 ActivePiece 中绘制全部,但那样不适用于固定块。稳妥做法:固定块用 TileMap,活动块用 _draw。TileMap 的 tile_set 中预置 7 种颜色的方块,每个颜色一个 Tile,编号对应颜色索引。设置 TileMap 的 cell_size = (32,32),然后在 update_ui() 中用 set_cell(坐标, 0, 颜色索引-1)(因为 Tile 编号从0开始)。这样就不需要额外颜色处理了。请按此实现。
【场景结构】
- 根节点 CanvasLayer(GameScreen)
- Background (ColorRect)
- GameBoard (Node2D) : position = (160, 80)
- Grid (TileMap) : position = (0,0), cell_size = (32,32)
- ActivePiece (Node2D) : position = (0,0)
- NextPreview (Node2D) : position = (480, 160)
- PreviewPiece (Node2D) : position = (0,0)
- ScoreLabel, LevelLabel, GameOverPanel (含 RestartButton)
【执行要求】
- 所有脚本必须附加到对应节点,逻辑集中在 GameScreen 的脚本中,ActivePiece 和 PreviewPiece 只负责 _draw()。
- 确保在 _ready() 中完成初始化、信号连接、启动下落计时(通过 _process)。
- 确保 start_screen.tscn 和 game_screen.tscn 保存到指定路径。
- 将主场景设为 start_screen.tscn。
- 生成完成后运行项目,验证颜色正确、方块落点准确(应在棋盘网格内,不会变形或偏移),且所有功能正常。
请一次性完成以上所有工作,不展示代码,只执行操作。如果遇到问题,自动修复并继续。