进一步完善服务器功能,添加远程命令系统,踢人系统
This commit is contained in:
333
Scene/SmallGame/Tetris.gd
Normal file
333
Scene/SmallGame/Tetris.gd
Normal file
@@ -0,0 +1,333 @@
|
||||
extends Panel
|
||||
|
||||
# 游戏常量
|
||||
const BOARD_WIDTH = 10
|
||||
const BOARD_HEIGHT = 20
|
||||
const CELL_SIZE = 30
|
||||
|
||||
# 方块类型
|
||||
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 drop_time = 1.0
|
||||
|
||||
# 节点引用
|
||||
@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
|
||||
|
||||
func _ready():
|
||||
# 连接定时器信号
|
||||
drop_timer.timeout.connect(_on_drop_timer_timeout)
|
||||
|
||||
# 设置游戏区域样式
|
||||
game_area.modulate = Color(0.1, 0.1, 0.1, 1.0)
|
||||
next_piece_area.modulate = Color(0.2, 0.2, 0.2, 1.0)
|
||||
|
||||
# 初始化游戏
|
||||
init_game()
|
||||
|
||||
func init_game():
|
||||
# 重置游戏状态
|
||||
game_over = false
|
||||
score = 0
|
||||
level = 1
|
||||
lines_cleared = 0
|
||||
drop_time = 1.0
|
||||
|
||||
# 初始化游戏板
|
||||
board.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:
|
||||
if game_over:
|
||||
if event.keycode == KEY_SPACE:
|
||||
init_game()
|
||||
return
|
||||
|
||||
if not current_piece:
|
||||
return
|
||||
|
||||
# 控制方块
|
||||
match event.keycode:
|
||||
KEY_A:
|
||||
move_piece(-1, 0)
|
||||
KEY_D:
|
||||
move_piece(1, 0)
|
||||
KEY_S:
|
||||
move_piece(0, 1)
|
||||
KEY_W:
|
||||
rotate_piece()
|
||||
KEY_SPACE:
|
||||
drop_piece()
|
||||
|
||||
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)
|
||||
|
||||
# 清除行并下移
|
||||
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:
|
||||
lines_cleared += lines_to_clear.size()
|
||||
score += lines_to_clear.size() * 100 * level
|
||||
|
||||
# 每10行提升一个等级
|
||||
level = lines_cleared / 10 + 1
|
||||
drop_time = max(0.1, 1.0 - (level - 1) * 0.1)
|
||||
drop_timer.wait_time = drop_time
|
||||
|
||||
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)
|
||||
level_label.text = "等级: " + str(level)
|
||||
lines_label.text = "消除行数: " + str(lines_cleared)
|
||||
|
||||
func show_game_over():
|
||||
drop_timer.stop()
|
||||
game_over_label.visible = true
|
||||
|
||||
func _on_drop_timer_timeout():
|
||||
if 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 _draw():
|
||||
if not game_area:
|
||||
return
|
||||
|
||||
# 获取游戏区域的位置
|
||||
var area_pos = game_area.position
|
||||
|
||||
# 绘制游戏板
|
||||
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 - 1,
|
||||
CELL_SIZE - 1
|
||||
)
|
||||
var color = PIECE_COLORS[cell_value - 1]
|
||||
draw_rect(rect, color)
|
||||
|
||||
# 绘制当前方块
|
||||
if current_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:
|
||||
var rect = Rect2(
|
||||
area_pos.x + board_x * CELL_SIZE,
|
||||
area_pos.y + board_y * CELL_SIZE,
|
||||
CELL_SIZE - 1,
|
||||
CELL_SIZE - 1
|
||||
)
|
||||
var color = PIECE_COLORS[current_piece.type]
|
||||
draw_rect(rect, color)
|
||||
|
||||
# 绘制网格线
|
||||
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.GRAY, 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.GRAY, 1)
|
||||
|
||||
# 绘制下一个方块预览
|
||||
var next_area_pos = next_piece_area.position
|
||||
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,
|
||||
19,
|
||||
19
|
||||
)
|
||||
var color = PIECE_COLORS[next_piece_type]
|
||||
draw_rect(rect, color)
|
||||
Reference in New Issue
Block a user