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将方块的形状和位置显示到游戏画面中。
相关推荐
shuair1 小时前
idea 2023.3.7常用插件
java·ide·intellij-idea
小安同学iter1 小时前
使用Maven将Web应用打包并部署到Tomcat服务器运行
java·tomcat·maven
Yvonne9781 小时前
创建三个节点
java·大数据
天宇&嘘月2 小时前
web第三次作业
前端·javascript·css
小王不会写code2 小时前
axios
前端·javascript·axios
不会飞的小龙人2 小时前
Kafka消息服务之Java工具类
java·kafka·消息队列·mq
是小崔啊3 小时前
java网络编程02 - HTTP、HTTPS详解
java·网络·http
brevity_souls4 小时前
Spring Boot 内置工具类
java·spring boot
发呆的薇薇°4 小时前
vue3 配置@根路径
前端·vue.js
小钊(求职中)4 小时前
Java开发实习面试笔试题(含答案)
java·开发语言·spring boot·spring·面试·tomcat·maven