No.1|Godot|俄罗斯方块复刻|棋盘和初始方块的设置

  1. 删掉基础图标
  2. 新建assets、scenes、scripts文件夹

俄罗斯方块的每种方块都是由四个小方块组成的,很适合放在网格地图中

比如网格地图是宽10列,高20行

要实现网格的对齐和下落

Node2D节点
  1. 新建一个Node2D

  2. 添加2个TileMapLayer

  3. 一个命名为Board,另一个命名为Active

  4. 给Board新建一个图块库

  5. 图块大小为32乘32

  6. 下方打开TileSet

  7. 添加图块

  8. 选择TileMap和第八个灰色的图块

  9. 选择矩形

  10. 画一个12乘22的网格

  11. 再用鼠标右键点击,划掉中间的部分

Node2D脚本

添加脚本,将其添加到scripts文件夹里

main.gd 复制代码
extends Node2D # 此脚本扩展自Node2D,作为游戏的主节点

# 定义 I 型俄罗斯方块的所有旋转状态,每种状态由方块相对原点的坐标组成
var i_tetromino: Array = [
	[Vector2i(0, 1), Vector2i(1, 1), Vector2i(2, 1), Vector2i(3, 1)], # 0 degrees
	[Vector2i(2, 0), Vector2i(2, 1), Vector2i(2, 2), Vector2i(2, 3)], # 90 degrees
	[Vector2i(0, 2), Vector2i(1, 2), Vector2i(2, 2), Vector2i(3, 2)], # 180 degrees
	[Vector2i(1, 0), Vector2i(1, 1), Vector2i(1, 2), Vector2i(1, 3)]  # 270 degrees
]

# 定义 T 型俄罗斯方块的所有旋转状态
var t_tetromino: Array = [
	[Vector2i(1, 0), Vector2i(0, 1), Vector2i(1, 1), Vector2i(2, 1)], # 0 degrees
	[Vector2i(1, 0), Vector2i(1, 1), Vector2i(2, 1), Vector2i(1, 2)], # 90 degrees
	[Vector2i(0, 1), Vector2i(1, 1), Vector2i(2, 1), Vector2i(1, 2)], # 180 degrees
	[Vector2i(1, 0), Vector2i(0, 1), Vector2i(1, 1), Vector2i(1, 2)]  # 270 degrees
]

# 定义 O 型俄罗斯方块的所有旋转状态(所有旋转状态相同)
var o_tetromino: Array = [
	[Vector2i(0, 0), Vector2i(1, 0), Vector2i(0, 1), Vector2i(1, 1)], # All rotations are the same
	[Vector2i(0, 0), Vector2i(1, 0), Vector2i(0, 1), Vector2i(1, 1)], # All rotations are the same
	[Vector2i(0, 0), Vector2i(1, 0), Vector2i(0, 1), Vector2i(1, 1)], # All rotations are the same
	[Vector2i(0, 0), Vector2i(1, 0), Vector2i(0, 1), Vector2i(1, 1)]  # All rotations are the same
]

# 定义 Z 型俄罗斯方块的所有旋转状态
var z_tetromino: Array = [
	[Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(2, 1)], # 0 degrees
	[Vector2i(2, 0), Vector2i(1, 1), Vector2i(2, 1), Vector2i(1, 2)], # 90 degrees
	[Vector2i(0, 1), Vector2i(1, 1), Vector2i(1, 2), Vector2i(2, 2)], # 180 degrees
	[Vector2i(1, 0), Vector2i(0, 1), Vector2i(1, 1), Vector2i(0, 2)]  # 270 degrees
]

# 定义 S 型俄罗斯方块的所有旋转状态
var s_tetromino: Array = [
	[Vector2i(1, 0), Vector2i(2, 0), Vector2i(0, 1), Vector2i(1, 1)], # 0 degrees
	[Vector2i(1, 0), Vector2i(1, 1), Vector2i(2, 1), Vector2i(2, 2)], # 90 degrees
	[Vector2i(1, 1), Vector2i(2, 1), Vector2i(0, 2), Vector2i(1, 2)], # 180 degrees
	[Vector2i(0, 0), Vector2i(0, 1), Vector2i(1, 1), Vector2i(1, 2)]  # 270 degrees
]

# 定义 L 型俄罗斯方块的所有旋转状态
var l_tetromino: Array = [
	[Vector2i(2, 0), Vector2i(0, 1), Vector2i(1, 1), Vector2i(2, 1)], # 0 degrees
	[Vector2i(1, 0), Vector2i(1, 1), Vector2i(1, 2), Vector2i(2, 2)], # 90 degrees
	[Vector2i(0, 1), Vector2i(1, 1), Vector2i(2, 1), Vector2i(0, 2)], # 180 degrees
	[Vector2i(0, 0), Vector2i(1, 0), Vector2i(1, 1), Vector2i(1, 2)]  # 270 degrees
]

# 定义 J 型俄罗斯方块的所有旋转状态
var j_tetromino: Array = [
	[Vector2i(0, 0), Vector2i(0, 1), Vector2i(1, 1), Vector2i(2, 1)], # 0 degrees
	[Vector2i(1, 0), Vector2i(2, 0), Vector2i(1, 1), Vector2i(1, 2)], # 90 degrees
	[Vector2i(0, 1), Vector2i(1, 1), Vector2i(2, 1), Vector2i(2, 2)], # 180 degrees
	[Vector2i(1, 0), Vector2i(1, 1), Vector2i(0, 2), Vector2i(1, 2)]  # 270 degrees
]

# 将所有俄罗斯方块的数组存入 tetrominoes 数组
var tetrominoes: Array = [i_tetromino, t_tetromino, o_tetromino, z_tetromino, s_tetromino, l_tetromino, j_tetromino]

# 创建所有方块的副本用于重置
var all_tetrominoes: Array = tetrominoes.duplicate()

# 设置游戏区域的列数和行数
const COLS: int = 10
const ROWS: int = 20

# 定义初始方块生成的起始位置
const START_POSITION: Vector2i = Vector2i(5, 1)
# 当前方块的位置
var current_position: Vector2i

# 当前和下一个方块的形状及旋转角度
var cunrrent_tetromino_type: Array
var next_tetromino_type: Array
# 当前旋转状态
var rotation_index: int = 0
# 当前方块的形态
var active_tetromino: Array = []

# Tile ID 和图块信息
var tile_id: int = 0
var piece_atlas: Vector2i
var next_piece_atlas: Vector2i

# 连接节点
@onready var board_layer: TileMapLayer = $Board
@onready var active_layer: TileMapLayer = $Active

# 准备函数,在游戏开始时调用
func _ready() -> void:
	start_new_game()

# 开始新的游戏
func start_new_game() -> void:
	# 随机选择一个方块类型
	cunrrent_tetromino_type = choose_tetromino()
	# 计算方块在 Tileset 中的图块索引
	piece_atlas = Vector2i(all_tetrominoes.find(cunrrent_tetromino_type), 0)
	# 初始化方块的位置和显示
	initialize_tetromino()

# 随机选择一个方块类型
func choose_tetromino() -> Array:
	var selected_tetromino: Array
	# 如果当前类型池不为空
	if not tetrominoes.is_empty():
		# 打乱类型池顺序
		tetrominoes.shuffle()
		# 取出第一个类型
		selected_tetromino = tetrominoes.pop_front()
	else:
		# 重置类型池
		tetrominoes = all_tetrominoes.duplicate()
		tetrominoes.shuffle()
		selected_tetromino = tetrominoes.pop_front()
	return selected_tetromino

# 初始化当前方块
func initialize_tetromino() -> void:
	# 将当前方块的位置设置为起始位置(通常在游戏顶部中央)
	current_position = START_POSITION
	# 获取当前方块在当前旋转状态下的形态
	active_tetromino = cunrrent_tetromino_type[rotation_index]
	# 渲染当前方块到网格层(显示方块)
	render_tetromino(active_tetromino, current_position, piece_atlas)

# 渲染俄罗斯方块到指定位置
func render_tetromino(tetromino: Array, position: Vector2i, atlas: Vector2i) -> void:
	# 遍历当前方块的所有方块单元(每个单元以 Vector2i 表示)
	for block in tetromino:
		# 使用方块的全局位置(初始位置加单元偏移量)设置网格层的对应单元
		# - position + block: 当前单元格在网格中的全局位置
		# - tile_id: 当前方块的唯一标识符,用于区分不同类型的方块
		# - atlas: 方块对应的图块信息,用于绘制特定样式
		board_layer.set_cell(position + block, tile_id, atlas)

这段代码定义了一个俄罗斯方块游戏的基础框架,用于管理游戏中的方块数据、游戏区域以及方块的生成和显示逻辑。

核心思想
  • 方块表示与旋转: 每种俄罗斯方块由其所有可能的旋转状态定义(0°、90°、180°、270°),这些状态通过Vector2i表示的相对坐标来描述。
  • 动态方块池管理: 使用一个池子管理可用的方块类型,每次随机从池中取出一个方块,当池为空时重新填充并随机打乱顺序。
  • 游戏区域: 游戏区域被定义为一个网格,玩家的目标是控制方块在网格内移动、旋转,并最终填满一行消除得分。
  • 图块渲染: 使用TileMapLayer将方块的形状和位置显示到游戏画面中。
相关推荐
1024小神几秒前
tauri2项目中自定义执行cmd命令界面卡死以及中文出错问题
前端·javascript
菜菜驴2 分钟前
关于 AI 应用的前端具体实践
前端·架构
JavaDog程序狗3 分钟前
【Java】集合遍历remove-add操作,这些坑你掉过几个
java·后端
懋学的前端攻城狮4 分钟前
深入浅出JVM-02自动内存管理机制全面剖析
java·jvm·后端
打破砂锅问到底0076 分钟前
前端验证下跨域问题(npm验证)
前端·npm·node.js
lyc23333310 分钟前
鸿蒙UIAbility:构建交互界面的「舞台主角」🎭
前端
lyc23333311 分钟前
鸿蒙AbilityStage:Stage模型的「舞台总指挥」🎬
前端
快乐星球喂11 分钟前
长图边滚动边加载动画
前端
前端布鲁伊13 分钟前
一周搞定!已有系统快速接入多语言的实战指南
前端·面试
空城机13 分钟前
从零打造前沿Web聊天组件:从设计到交互
前端·vue.js·交互设计