658 lines
18 KiB
GDScript
658 lines
18 KiB
GDScript
extends Panel
|
||
|
||
# 游戏常量
|
||
const BOARD_WIDTH = 10
|
||
const BOARD_HEIGHT = 20
|
||
const CELL_SIZE = 30
|
||
const DATA_FILE_PATH = "user://playergamedata.json"
|
||
|
||
# 特殊方块类型
|
||
enum SpecialType {
|
||
NORMAL,
|
||
BOMB, # 炸弹方块,消除周围方块
|
||
LINE, # 直线方块,消除整行
|
||
RAINBOW # 彩虹方块,消除同色方块
|
||
}
|
||
|
||
# 方块类型
|
||
enum PieceType {
|
||
I, O, T, S, Z, J, L
|
||
}
|
||
|
||
# 方块形状定义
|
||
const PIECE_SHAPES = {
|
||
PieceType.I: [
|
||
[[1, 1, 1, 1]],
|
||
[[1], [1], [1], [1]]
|
||
],
|
||
PieceType.O: [
|
||
[[1, 1], [1, 1]]
|
||
],
|
||
PieceType.T: [
|
||
[[0, 1, 0], [1, 1, 1]],
|
||
[[1, 0], [1, 1], [1, 0]],
|
||
[[1, 1, 1], [0, 1, 0]],
|
||
[[0, 1], [1, 1], [0, 1]]
|
||
],
|
||
PieceType.S: [
|
||
[[0, 1, 1], [1, 1, 0]],
|
||
[[1, 0], [1, 1], [0, 1]]
|
||
],
|
||
PieceType.Z: [
|
||
[[1, 1, 0], [0, 1, 1]],
|
||
[[0, 1], [1, 1], [1, 0]]
|
||
],
|
||
PieceType.J: [
|
||
[[1, 0, 0], [1, 1, 1]],
|
||
[[1, 1], [1, 0], [1, 0]],
|
||
[[1, 1, 1], [0, 0, 1]],
|
||
[[0, 1], [0, 1], [1, 1]]
|
||
],
|
||
PieceType.L: [
|
||
[[0, 0, 1], [1, 1, 1]],
|
||
[[1, 0], [1, 0], [1, 1]],
|
||
[[1, 1, 1], [1, 0, 0]],
|
||
[[1, 1], [0, 1], [0, 1]]
|
||
]
|
||
}
|
||
|
||
# 方块颜色
|
||
const PIECE_COLORS = {
|
||
PieceType.I: Color.CYAN,
|
||
PieceType.O: Color.YELLOW,
|
||
PieceType.T: Color.MAGENTA,
|
||
PieceType.S: Color.GREEN,
|
||
PieceType.Z: Color.RED,
|
||
PieceType.J: Color.BLUE,
|
||
PieceType.L: Color.ORANGE
|
||
}
|
||
|
||
# 游戏变量
|
||
var board = []
|
||
var current_piece = null
|
||
var current_piece_pos = Vector2()
|
||
var current_piece_rotation = 0
|
||
var next_piece_type = PieceType.I
|
||
var score = 0
|
||
var level = 1
|
||
var lines_cleared = 0
|
||
var game_over = false
|
||
var game_started = false # 添加游戏开始状态
|
||
var drop_time = 1.0
|
||
var best_score = 0
|
||
var games_played = 0
|
||
var total_lines_cleared = 0
|
||
var combo_count = 0
|
||
var special_pieces = [] # 存储特殊方块位置和类型
|
||
var player_data = {}
|
||
|
||
# 节点引用
|
||
@onready var game_area = $GameArea
|
||
@onready var next_piece_area = $NextPieceArea
|
||
@onready var score_label = $ScoreLabel
|
||
@onready var level_label = $LevelLabel
|
||
@onready var lines_label = $LinesLabel
|
||
@onready var game_over_label = $GameOverLabel
|
||
@onready var drop_timer = $DropTimer
|
||
@onready var virtual_controls = $VirtualControls
|
||
|
||
func _ready():
|
||
# 连接定时器信号
|
||
drop_timer.timeout.connect(_on_drop_timer_timeout)
|
||
|
||
# 设置游戏区域样式
|
||
game_area.modulate = Color(0.08, 0.12, 0.18, 0.9)
|
||
next_piece_area.modulate = Color(0.1, 0.15, 0.25, 0.9)
|
||
|
||
# 设置虚拟控制
|
||
setup_virtual_controls()
|
||
|
||
# 加载玩家数据
|
||
load_player_data()
|
||
|
||
# 显示游戏开始界面
|
||
show_start_screen()
|
||
|
||
func init_game():
|
||
# 重置游戏状态
|
||
game_over = false
|
||
game_started = true
|
||
score = 0
|
||
level = 1
|
||
lines_cleared = 0
|
||
drop_time = 1.0
|
||
combo_count = 0
|
||
games_played += 1
|
||
|
||
# 初始化游戏板
|
||
board.clear()
|
||
special_pieces.clear()
|
||
for y in range(BOARD_HEIGHT):
|
||
var row = []
|
||
for x in range(BOARD_WIDTH):
|
||
row.append(0)
|
||
board.append(row)
|
||
|
||
# 生成第一个方块
|
||
next_piece_type = randi() % PieceType.size()
|
||
spawn_new_piece()
|
||
|
||
# 更新UI
|
||
update_ui()
|
||
game_over_label.visible = false
|
||
|
||
# 启动定时器
|
||
drop_timer.wait_time = drop_time
|
||
drop_timer.start()
|
||
|
||
func _input(event):
|
||
if event is InputEventKey and event.pressed:
|
||
# 游戏未开始时,按Q键开始游戏
|
||
if not game_started:
|
||
if event.keycode == KEY_Q:
|
||
init_game()
|
||
return
|
||
|
||
if game_over:
|
||
if event.keycode == KEY_SPACE:
|
||
init_game()
|
||
elif event.keycode == KEY_Q:
|
||
init_game()
|
||
return
|
||
|
||
if not current_piece:
|
||
return
|
||
|
||
# 控制方块
|
||
match event.keycode:
|
||
KEY_A:
|
||
handle_move_left()
|
||
KEY_D:
|
||
handle_move_right()
|
||
KEY_S:
|
||
handle_move_down()
|
||
KEY_W:
|
||
handle_rotate()
|
||
KEY_SPACE:
|
||
handle_drop()
|
||
|
||
# 控制函数
|
||
func handle_move_left():
|
||
move_piece(-1, 0)
|
||
|
||
func handle_move_right():
|
||
move_piece(1, 0)
|
||
|
||
func handle_move_down():
|
||
move_piece(0, 1)
|
||
|
||
func handle_rotate():
|
||
rotate_piece()
|
||
|
||
func handle_drop():
|
||
drop_piece()
|
||
|
||
func handle_restart():
|
||
init_game()
|
||
|
||
func spawn_new_piece():
|
||
current_piece = {
|
||
"type": next_piece_type,
|
||
"rotation": 0
|
||
}
|
||
current_piece_pos = Vector2(BOARD_WIDTH / 2 - 1, 0)
|
||
current_piece_rotation = 0
|
||
|
||
# 生成下一个方块
|
||
next_piece_type = randi() % PieceType.size()
|
||
|
||
# 检查游戏是否结束
|
||
if not can_place_piece(current_piece_pos, current_piece_rotation):
|
||
game_over = true
|
||
show_game_over()
|
||
|
||
func move_piece(dx: int, dy: int):
|
||
var new_pos = current_piece_pos + Vector2(dx, dy)
|
||
if can_place_piece(new_pos, current_piece_rotation):
|
||
current_piece_pos = new_pos
|
||
queue_redraw()
|
||
|
||
func rotate_piece():
|
||
var new_rotation = (current_piece_rotation + 1) % get_piece_rotations(current_piece.type)
|
||
if can_place_piece(current_piece_pos, new_rotation):
|
||
current_piece_rotation = new_rotation
|
||
queue_redraw()
|
||
|
||
func drop_piece():
|
||
while can_place_piece(current_piece_pos + Vector2(0, 1), current_piece_rotation):
|
||
current_piece_pos.y += 1
|
||
place_piece()
|
||
|
||
func can_place_piece(pos: Vector2, rotation: int) -> bool:
|
||
var shape = get_piece_shape(current_piece.type, rotation)
|
||
for y in range(shape.size()):
|
||
for x in range(shape[y].size()):
|
||
if shape[y][x] == 1:
|
||
var board_x = pos.x + x
|
||
var board_y = pos.y + y
|
||
|
||
# 检查边界
|
||
if board_x < 0 or board_x >= BOARD_WIDTH or board_y >= BOARD_HEIGHT:
|
||
return false
|
||
|
||
# 检查碰撞
|
||
if board_y >= 0 and board[board_y][board_x] != 0:
|
||
return false
|
||
return true
|
||
|
||
func place_piece():
|
||
var shape = get_piece_shape(current_piece.type, current_piece_rotation)
|
||
for y in range(shape.size()):
|
||
for x in range(shape[y].size()):
|
||
if shape[y][x] == 1:
|
||
var board_x = current_piece_pos.x + x
|
||
var board_y = current_piece_pos.y + y
|
||
if board_y >= 0:
|
||
board[board_y][board_x] = current_piece.type + 1
|
||
|
||
# 检查并清除完整的行
|
||
clear_lines()
|
||
|
||
# 生成新方块
|
||
spawn_new_piece()
|
||
|
||
queue_redraw()
|
||
|
||
func clear_lines():
|
||
var lines_to_clear = []
|
||
|
||
# 找到完整的行
|
||
for y in range(BOARD_HEIGHT):
|
||
var is_full = true
|
||
for x in range(BOARD_WIDTH):
|
||
if board[y][x] == 0:
|
||
is_full = false
|
||
break
|
||
if is_full:
|
||
lines_to_clear.append(y)
|
||
|
||
# 处理特殊方块效果
|
||
process_special_pieces(lines_to_clear)
|
||
|
||
# 清除行并下移
|
||
for line_y in lines_to_clear:
|
||
board.erase(board[line_y])
|
||
var new_row = []
|
||
for x in range(BOARD_WIDTH):
|
||
new_row.append(0)
|
||
board.insert(0, new_row)
|
||
|
||
# 更新分数和等级
|
||
if lines_to_clear.size() > 0:
|
||
# 连击系统
|
||
combo_count += 1
|
||
var combo_bonus = combo_count * 50
|
||
|
||
lines_cleared += lines_to_clear.size()
|
||
total_lines_cleared += lines_to_clear.size()
|
||
|
||
# 计算分数(包含连击奖励)
|
||
var base_score = lines_to_clear.size() * 100 * level
|
||
var line_bonus = 0
|
||
match lines_to_clear.size():
|
||
1: line_bonus = 0
|
||
2: line_bonus = 300
|
||
3: line_bonus = 500
|
||
4: line_bonus = 800 # 俄罗斯方块
|
||
|
||
score += base_score + line_bonus + combo_bonus
|
||
|
||
# 每10行提升一个等级,速度递增
|
||
level = lines_cleared / 10 + 1
|
||
drop_time = max(0.05, 1.0 - (level - 1) * 0.08)
|
||
drop_timer.wait_time = drop_time
|
||
|
||
# 随机生成特殊方块
|
||
if randf() < 0.1 + level * 0.02: # 等级越高,特殊方块概率越大
|
||
generate_special_piece()
|
||
else:
|
||
# 重置连击
|
||
combo_count = 0
|
||
|
||
update_ui()
|
||
|
||
func get_piece_shape(type: PieceType, rotation: int) -> Array:
|
||
return PIECE_SHAPES[type][rotation]
|
||
|
||
func get_piece_rotations(type: PieceType) -> int:
|
||
return PIECE_SHAPES[type].size()
|
||
|
||
func update_ui():
|
||
score_label.text = "🏆 分数: " + str(score) + "\n💎 最高: " + str(best_score)
|
||
level_label.text = "⚡ 等级: " + str(level) + "\n🎮 游戏: " + str(games_played)
|
||
lines_label.text = "📊 消除: " + str(lines_cleared) + "\n🔥 连击: " + str(combo_count)
|
||
|
||
func show_game_over():
|
||
drop_timer.stop()
|
||
game_started = false
|
||
|
||
# 检查并更新最高分
|
||
if score > best_score:
|
||
best_score = score
|
||
|
||
# 保存玩家数据
|
||
save_player_data()
|
||
|
||
# 显示游戏结束信息
|
||
game_over_label.text = "🎮 游戏结束 🎮\n\n🏆 本次分数: " + str(score) + "\n💎 最高分数: " + str(best_score) + "\n📊 消除行数: " + str(lines_cleared) + "\n⚡ 达到等级: " + str(level) + "\n\n🔄 按Q键或空格重新开始"
|
||
game_over_label.visible = true
|
||
|
||
func _on_drop_timer_timeout():
|
||
if not game_started or game_over or not current_piece:
|
||
return
|
||
|
||
if can_place_piece(current_piece_pos + Vector2(0, 1), current_piece_rotation):
|
||
current_piece_pos.y += 1
|
||
queue_redraw()
|
||
else:
|
||
place_piece()
|
||
|
||
# 虚拟控制设置
|
||
func setup_virtual_controls():
|
||
if virtual_controls:
|
||
virtual_controls.get_node("LeftButton").pressed.connect(_on_virtual_button_pressed.bind("left"))
|
||
virtual_controls.get_node("RightButton").pressed.connect(_on_virtual_button_pressed.bind("right"))
|
||
virtual_controls.get_node("DownButton").pressed.connect(_on_virtual_button_pressed.bind("down"))
|
||
virtual_controls.get_node("RotateButton").pressed.connect(_on_virtual_button_pressed.bind("rotate"))
|
||
virtual_controls.get_node("DropButton").pressed.connect(_on_virtual_button_pressed.bind("drop"))
|
||
virtual_controls.get_node("RestartButton").pressed.connect(_on_virtual_button_pressed.bind("restart"))
|
||
|
||
func _on_virtual_button_pressed(action: String):
|
||
if not game_started:
|
||
if action == "restart":
|
||
init_game()
|
||
return
|
||
|
||
if game_over and action == "restart":
|
||
handle_restart()
|
||
return
|
||
|
||
if game_over or not current_piece:
|
||
return
|
||
|
||
match action:
|
||
"left":
|
||
handle_move_left()
|
||
"right":
|
||
handle_move_right()
|
||
"down":
|
||
handle_move_down()
|
||
"rotate":
|
||
handle_rotate()
|
||
"drop":
|
||
handle_drop()
|
||
|
||
# 特殊方块处理
|
||
func process_special_pieces(lines_to_clear: Array):
|
||
# 处理特殊方块效果
|
||
for special in special_pieces:
|
||
var pos = special.position
|
||
var type = special.type
|
||
|
||
match type:
|
||
SpecialType.BOMB:
|
||
# 炸弹方块:清除周围3x3区域
|
||
for dy in range(-1, 2):
|
||
for dx in range(-1, 2):
|
||
var x = pos.x + dx
|
||
var y = pos.y + dy
|
||
if x >= 0 and x < BOARD_WIDTH and y >= 0 and y < BOARD_HEIGHT:
|
||
board[y][x] = 0
|
||
SpecialType.LINE:
|
||
# 直线方块:清除整行
|
||
for x in range(BOARD_WIDTH):
|
||
board[pos.y][x] = 0
|
||
SpecialType.RAINBOW:
|
||
# 彩虹方块:清除同色方块
|
||
var target_color = board[pos.y][pos.x]
|
||
if target_color > 0:
|
||
for y in range(BOARD_HEIGHT):
|
||
for x in range(BOARD_WIDTH):
|
||
if board[y][x] == target_color:
|
||
board[y][x] = 0
|
||
|
||
# 清空特殊方块列表
|
||
special_pieces.clear()
|
||
|
||
func generate_special_piece():
|
||
# 在随机位置生成特殊方块
|
||
var x = randi() % BOARD_WIDTH
|
||
var y = randi() % (BOARD_HEIGHT - 5) + 5 # 在下半部分生成
|
||
|
||
if board[y][x] != 0: # 只在有方块的位置生成特殊效果
|
||
var special_type = randi() % 3 + 1 # 随机选择特殊类型
|
||
special_pieces.append({
|
||
"position": Vector2(x, y),
|
||
"type": special_type
|
||
})
|
||
|
||
# 数据存储功能
|
||
func load_player_data():
|
||
if FileAccess.file_exists(DATA_FILE_PATH):
|
||
var file = FileAccess.open(DATA_FILE_PATH, FileAccess.READ)
|
||
if file:
|
||
var json_string = file.get_as_text()
|
||
file.close()
|
||
|
||
var json = JSON.new()
|
||
var parse_result = json.parse(json_string)
|
||
if parse_result == OK:
|
||
player_data = json.data
|
||
if player_data.has("tetris"):
|
||
var tetris_data = player_data["tetris"]
|
||
best_score = tetris_data.get("best_score", 0)
|
||
games_played = tetris_data.get("games_played", 0)
|
||
total_lines_cleared = tetris_data.get("total_lines_cleared", 0)
|
||
|
||
func show_start_screen():
|
||
# 重置状态
|
||
game_started = false
|
||
game_over = false
|
||
current_piece = null
|
||
|
||
# 显示开始提示
|
||
game_over_label.text = "🎮 俄罗斯方块 🎮\n\n🏆 最高分数: " + str(best_score) + "\n🎯 游戏次数: " + str(games_played) + "\n\n🎮 按Q键开始游戏\n\n🎯 操作说明:\nA/D - 左右移动\nW - 旋转\nS - 快速下落\n空格 - 直接落下"
|
||
game_over_label.visible = true
|
||
|
||
# 停止定时器
|
||
drop_timer.stop()
|
||
|
||
# 清空游戏板
|
||
board.clear()
|
||
special_pieces.clear()
|
||
for y in range(BOARD_HEIGHT):
|
||
var row = []
|
||
for x in range(BOARD_WIDTH):
|
||
row.append(0)
|
||
board.append(row)
|
||
|
||
update_ui()
|
||
queue_redraw()
|
||
|
||
func save_player_data():
|
||
if not player_data.has("tetris"):
|
||
player_data["tetris"] = {}
|
||
|
||
player_data["tetris"]["best_score"] = best_score
|
||
player_data["tetris"]["games_played"] = games_played
|
||
player_data["tetris"]["total_lines_cleared"] = total_lines_cleared
|
||
player_data["tetris"]["last_played"] = Time.get_datetime_string_from_system()
|
||
|
||
var file = FileAccess.open(DATA_FILE_PATH, FileAccess.WRITE)
|
||
if file:
|
||
var json_string = JSON.stringify(player_data)
|
||
file.store_string(json_string)
|
||
file.close()
|
||
|
||
func _draw():
|
||
if not game_area:
|
||
return
|
||
|
||
# 绘制背景渐变
|
||
var gradient = Gradient.new()
|
||
gradient.add_point(0.0, Color(0.05, 0.1, 0.2, 0.95))
|
||
gradient.add_point(0.5, Color(0.1, 0.15, 0.25, 0.9))
|
||
gradient.add_point(1.0, Color(0.15, 0.2, 0.3, 0.95))
|
||
draw_rect(Rect2(Vector2.ZERO, size), gradient.sample(0.5), true)
|
||
|
||
# 获取游戏区域的位置
|
||
var area_pos = game_area.position
|
||
var area_size = Vector2(BOARD_WIDTH * CELL_SIZE, BOARD_HEIGHT * CELL_SIZE)
|
||
|
||
# 绘制游戏区域阴影
|
||
var shadow_offset = Vector2(4, 4)
|
||
var area_rect = Rect2(area_pos + shadow_offset, area_size)
|
||
draw_rect(area_rect, Color(0, 0, 0, 0.4), true)
|
||
|
||
# 绘制游戏区域背景
|
||
area_rect = Rect2(area_pos, area_size)
|
||
draw_rect(area_rect, Color(0.08, 0.12, 0.18, 0.9), true)
|
||
|
||
# 绘制网格线(淡色)
|
||
for x in range(BOARD_WIDTH + 1):
|
||
var start_pos = Vector2(area_pos.x + x * CELL_SIZE, area_pos.y)
|
||
var end_pos = Vector2(area_pos.x + x * CELL_SIZE, area_pos.y + BOARD_HEIGHT * CELL_SIZE)
|
||
draw_line(start_pos, end_pos, Color(0.3, 0.3, 0.4, 0.3), 1)
|
||
|
||
for y in range(BOARD_HEIGHT + 1):
|
||
var start_pos = Vector2(area_pos.x, area_pos.y + y * CELL_SIZE)
|
||
var end_pos = Vector2(area_pos.x + BOARD_WIDTH * CELL_SIZE, area_pos.y + y * CELL_SIZE)
|
||
draw_line(start_pos, end_pos, Color(0.3, 0.3, 0.4, 0.3), 1)
|
||
|
||
# 绘制游戏板
|
||
for y in range(BOARD_HEIGHT):
|
||
for x in range(BOARD_WIDTH):
|
||
var cell_value = board[y][x]
|
||
if cell_value > 0:
|
||
var rect = Rect2(
|
||
area_pos.x + x * CELL_SIZE,
|
||
area_pos.y + y * CELL_SIZE,
|
||
CELL_SIZE - 2,
|
||
CELL_SIZE - 2
|
||
)
|
||
var color = PIECE_COLORS[cell_value - 1]
|
||
|
||
# 检查是否为特殊方块
|
||
var is_special = false
|
||
var special_type = SpecialType.NORMAL
|
||
for special in special_pieces:
|
||
if special.position == Vector2(x, y):
|
||
is_special = true
|
||
special_type = special.type
|
||
break
|
||
|
||
if is_special:
|
||
# 绘制特殊方块效果
|
||
match special_type:
|
||
SpecialType.BOMB:
|
||
# 炸弹方块(红色闪烁)
|
||
var pulse = sin(Time.get_ticks_msec() * 0.01) * 0.3 + 0.7
|
||
draw_rect(rect, Color.RED * pulse, true)
|
||
draw_rect(Rect2(rect.position + Vector2(2, 2), rect.size - Vector2(4, 4)), Color.ORANGE, true)
|
||
SpecialType.LINE:
|
||
# 直线方块(蓝色闪烁)
|
||
var pulse = sin(Time.get_ticks_msec() * 0.008) * 0.3 + 0.7
|
||
draw_rect(rect, Color.CYAN * pulse, true)
|
||
draw_rect(Rect2(rect.position + Vector2(2, 2), rect.size - Vector2(4, 4)), Color.LIGHT_BLUE, true)
|
||
SpecialType.RAINBOW:
|
||
# 彩虹方块(彩虹色)
|
||
var rainbow_time = Time.get_ticks_msec() * 0.003
|
||
var rainbow_color = Color.from_hsv(fmod(rainbow_time, 1.0), 1.0, 1.0)
|
||
draw_rect(rect, rainbow_color, true)
|
||
draw_rect(Rect2(rect.position + Vector2(2, 2), rect.size - Vector2(4, 4)), Color.WHITE, true)
|
||
else:
|
||
# 普通方块(立体效果)
|
||
draw_rect(rect, color, true)
|
||
# 高光
|
||
var highlight_rect = Rect2(rect.position + Vector2(1, 1), Vector2(rect.size.x - 2, rect.size.y * 0.3))
|
||
draw_rect(highlight_rect, Color(1, 1, 1, 0.3), true)
|
||
# 阴影
|
||
var shadow_rect = Rect2(rect.position + Vector2(1, rect.size.y * 0.7), Vector2(rect.size.x - 2, rect.size.y * 0.3))
|
||
draw_rect(shadow_rect, Color(0, 0, 0, 0.2), true)
|
||
|
||
# 绘制当前方块(带透明度预览)
|
||
if current_piece:
|
||
var shape = get_piece_shape(current_piece.type, current_piece_rotation)
|
||
|
||
# 绘制投影(显示方块会落在哪里)
|
||
var shadow_pos = current_piece_pos
|
||
while can_place_piece(shadow_pos + Vector2(0, 1), current_piece_rotation):
|
||
shadow_pos.y += 1
|
||
|
||
for y in range(shape.size()):
|
||
for x in range(shape[y].size()):
|
||
if shape[y][x] == 1:
|
||
var board_x = shadow_pos.x + x
|
||
var board_y = shadow_pos.y + y
|
||
if board_y >= 0 and board_x >= 0 and board_x < BOARD_WIDTH and board_y < BOARD_HEIGHT:
|
||
var rect = Rect2(
|
||
area_pos.x + board_x * CELL_SIZE,
|
||
area_pos.y + board_y * CELL_SIZE,
|
||
CELL_SIZE - 2,
|
||
CELL_SIZE - 2
|
||
)
|
||
var shadow_color = PIECE_COLORS[current_piece.type]
|
||
shadow_color.a = 0.3
|
||
draw_rect(rect, shadow_color, false, 2)
|
||
|
||
# 绘制当前方块
|
||
for y in range(shape.size()):
|
||
for x in range(shape[y].size()):
|
||
if shape[y][x] == 1:
|
||
var board_x = current_piece_pos.x + x
|
||
var board_y = current_piece_pos.y + y
|
||
if board_y >= 0:
|
||
var rect = Rect2(
|
||
area_pos.x + board_x * CELL_SIZE,
|
||
area_pos.y + board_y * CELL_SIZE,
|
||
CELL_SIZE - 2,
|
||
CELL_SIZE - 2
|
||
)
|
||
var color = PIECE_COLORS[current_piece.type]
|
||
# 立体效果
|
||
draw_rect(rect, color, true)
|
||
# 高光
|
||
var highlight_rect = Rect2(rect.position + Vector2(1, 1), Vector2(rect.size.x - 2, rect.size.y * 0.3))
|
||
draw_rect(highlight_rect, Color(1, 1, 1, 0.4), true)
|
||
|
||
# 绘制下一个方块预览区域背景
|
||
var next_area_pos = next_piece_area.position
|
||
var next_area_size = next_piece_area.size
|
||
draw_rect(Rect2(next_area_pos + Vector2(2, 2), next_area_size), Color(0, 0, 0, 0.3), true)
|
||
draw_rect(Rect2(next_area_pos, next_area_size), Color(0.1, 0.15, 0.25, 0.9), true)
|
||
|
||
# 绘制下一个方块预览
|
||
var next_shape = get_piece_shape(next_piece_type, 0)
|
||
for y in range(next_shape.size()):
|
||
for x in range(next_shape[y].size()):
|
||
if next_shape[y][x] == 1:
|
||
var rect = Rect2(
|
||
next_area_pos.x + 20 + x * 20,
|
||
next_area_pos.y + 50 + y * 20,
|
||
18,
|
||
18
|
||
)
|
||
var color = PIECE_COLORS[next_piece_type]
|
||
# 立体效果
|
||
draw_rect(rect, color, true)
|
||
# 高光
|
||
var highlight_rect = Rect2(rect.position + Vector2(1, 1), Vector2(rect.size.x - 2, rect.size.y * 0.3))
|
||
draw_rect(highlight_rect, Color(1, 1, 1, 0.3), true)
|
||
|
||
|
||
func _on_quit_button_pressed() -> void:
|
||
self.hide()
|
||
get_parent().remove_child(self)
|
||
queue_free()
|
||
pass
|