进一步完善服务器功能,添加远程命令系统,踢人系统
This commit is contained in:
317
Scene/SmallGame/PushBox.gd
Normal file
317
Scene/SmallGame/PushBox.gd
Normal file
@@ -0,0 +1,317 @@
|
||||
extends Panel
|
||||
|
||||
# 游戏常量
|
||||
const CELL_SIZE = 40
|
||||
|
||||
# 地图元素
|
||||
enum CellType {
|
||||
EMPTY, # 空地
|
||||
WALL, # 墙壁
|
||||
TARGET, # 目标点
|
||||
BOX, # 箱子
|
||||
PLAYER, # 玩家
|
||||
BOX_ON_TARGET # 箱子在目标点上
|
||||
}
|
||||
|
||||
# 颜色配置
|
||||
const CELL_COLORS = {
|
||||
CellType.EMPTY: Color.WHITE,
|
||||
CellType.WALL: Color.DARK_GRAY,
|
||||
CellType.TARGET: Color.LIGHT_BLUE,
|
||||
CellType.BOX: Color.SADDLE_BROWN,
|
||||
CellType.PLAYER: Color.GREEN,
|
||||
CellType.BOX_ON_TARGET: Color.DARK_GREEN
|
||||
}
|
||||
|
||||
# 关卡数据
|
||||
const LEVELS = [
|
||||
# 关卡1 - 简单入门
|
||||
[
|
||||
"########",
|
||||
"#......#",
|
||||
"#..##..#",
|
||||
"#..#*..#",
|
||||
"#..#$..#",
|
||||
"#..@...#",
|
||||
"#......#",
|
||||
"########"
|
||||
],
|
||||
# 关卡2 - 两个箱子
|
||||
[
|
||||
"########",
|
||||
"#......#",
|
||||
"#.*$*..#",
|
||||
"#......#",
|
||||
"#..$...#",
|
||||
"#..@...#",
|
||||
"#......#",
|
||||
"########"
|
||||
],
|
||||
# 关卡3 - 稍微复杂
|
||||
[
|
||||
"##########",
|
||||
"#........#",
|
||||
"#..####..#",
|
||||
"#..*##*..#",
|
||||
"#..$$....#",
|
||||
"#........#",
|
||||
"#...@....#",
|
||||
"#........#",
|
||||
"##########"
|
||||
],
|
||||
# 关卡4 - 更复杂的布局
|
||||
[
|
||||
"############",
|
||||
"#..........#",
|
||||
"#..######..#",
|
||||
"#..*....#..#",
|
||||
"#..$....#..#",
|
||||
"#.......#..#",
|
||||
"#..#....#..#",
|
||||
"#..*....#..#",
|
||||
"#..$......@#",
|
||||
"#..........#",
|
||||
"############"
|
||||
]
|
||||
]
|
||||
|
||||
# 游戏变量
|
||||
var current_level = 0
|
||||
var level_data = []
|
||||
var player_pos = Vector2()
|
||||
var moves = 0
|
||||
var level_completed = false
|
||||
var map_width = 0
|
||||
var map_height = 0
|
||||
|
||||
# 节点引用
|
||||
@onready var game_area = $GameArea
|
||||
@onready var level_label = $LevelLabel
|
||||
@onready var moves_label = $MovesLabel
|
||||
@onready var win_label = $WinLabel
|
||||
|
||||
func _ready():
|
||||
# 设置游戏区域样式
|
||||
game_area.modulate = Color(0.9, 0.9, 0.9)
|
||||
|
||||
# 初始化游戏
|
||||
init_level()
|
||||
|
||||
func init_level():
|
||||
# 重置游戏状态
|
||||
level_completed = false
|
||||
moves = 0
|
||||
|
||||
# 加载当前关卡
|
||||
load_level(current_level)
|
||||
|
||||
# 更新UI
|
||||
update_ui()
|
||||
win_label.visible = false
|
||||
|
||||
queue_redraw()
|
||||
|
||||
func load_level(level_index: int):
|
||||
if level_index >= LEVELS.size():
|
||||
level_index = LEVELS.size() - 1
|
||||
|
||||
var level_strings = LEVELS[level_index]
|
||||
map_height = level_strings.size()
|
||||
map_width = level_strings[0].length()
|
||||
|
||||
# 初始化关卡数据
|
||||
level_data.clear()
|
||||
for y in range(map_height):
|
||||
var row = []
|
||||
for x in range(map_width):
|
||||
row.append(CellType.EMPTY)
|
||||
level_data.append(row)
|
||||
|
||||
# 解析关卡字符串
|
||||
for y in range(map_height):
|
||||
var line = level_strings[y]
|
||||
for x in range(line.length()):
|
||||
var char = line[x]
|
||||
match char:
|
||||
'#': # 墙壁
|
||||
level_data[y][x] = CellType.WALL
|
||||
'*': # 目标点
|
||||
level_data[y][x] = CellType.TARGET
|
||||
'$': # 箱子
|
||||
level_data[y][x] = CellType.BOX
|
||||
'@': # 玩家
|
||||
level_data[y][x] = CellType.PLAYER
|
||||
player_pos = Vector2(x, y)
|
||||
'+': # 箱子在目标点上
|
||||
level_data[y][x] = CellType.BOX_ON_TARGET
|
||||
'.': # 空地
|
||||
level_data[y][x] = CellType.EMPTY
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey and event.pressed:
|
||||
if level_completed:
|
||||
match event.keycode:
|
||||
KEY_N:
|
||||
next_level()
|
||||
KEY_R:
|
||||
init_level()
|
||||
return
|
||||
|
||||
# 移动控制
|
||||
var direction = Vector2.ZERO
|
||||
match event.keycode:
|
||||
KEY_UP, KEY_W:
|
||||
direction = Vector2(0, -1)
|
||||
KEY_DOWN, KEY_S:
|
||||
direction = Vector2(0, 1)
|
||||
KEY_LEFT, KEY_A:
|
||||
direction = Vector2(-1, 0)
|
||||
KEY_RIGHT, KEY_D:
|
||||
direction = Vector2(1, 0)
|
||||
KEY_R:
|
||||
init_level()
|
||||
return
|
||||
KEY_P:
|
||||
prev_level()
|
||||
return
|
||||
KEY_N:
|
||||
next_level()
|
||||
return
|
||||
|
||||
if direction != Vector2.ZERO:
|
||||
move_player(direction)
|
||||
|
||||
func move_player(direction: Vector2):
|
||||
var new_pos = player_pos + direction
|
||||
|
||||
# 检查边界
|
||||
if new_pos.x < 0 or new_pos.x >= map_width or new_pos.y < 0 or new_pos.y >= map_height:
|
||||
return
|
||||
|
||||
var target_cell = level_data[new_pos.y][new_pos.x]
|
||||
|
||||
# 检查是否撞墙
|
||||
if target_cell == CellType.WALL:
|
||||
return
|
||||
|
||||
# 检查是否推箱子
|
||||
if target_cell == CellType.BOX or target_cell == CellType.BOX_ON_TARGET:
|
||||
var box_new_pos = new_pos + direction
|
||||
|
||||
# 检查箱子新位置是否有效
|
||||
if box_new_pos.x < 0 or box_new_pos.x >= map_width or box_new_pos.y < 0 or box_new_pos.y >= map_height:
|
||||
return
|
||||
|
||||
var box_target_cell = level_data[box_new_pos.y][box_new_pos.x]
|
||||
|
||||
# 箱子不能推到墙上或其他箱子上
|
||||
if box_target_cell == CellType.WALL or box_target_cell == CellType.BOX or box_target_cell == CellType.BOX_ON_TARGET:
|
||||
return
|
||||
|
||||
# 移动箱子
|
||||
var was_on_target = (target_cell == CellType.BOX_ON_TARGET)
|
||||
var moving_to_target = (box_target_cell == CellType.TARGET)
|
||||
|
||||
# 更新箱子原位置
|
||||
if was_on_target:
|
||||
level_data[new_pos.y][new_pos.x] = CellType.TARGET
|
||||
else:
|
||||
level_data[new_pos.y][new_pos.x] = CellType.EMPTY
|
||||
|
||||
# 更新箱子新位置
|
||||
if moving_to_target:
|
||||
level_data[box_new_pos.y][box_new_pos.x] = CellType.BOX_ON_TARGET
|
||||
else:
|
||||
level_data[box_new_pos.y][box_new_pos.x] = CellType.BOX
|
||||
|
||||
# 移动玩家
|
||||
# 恢复玩家原位置(检查是否在目标点上)
|
||||
var level_strings = LEVELS[current_level]
|
||||
if player_pos.y < level_strings.size() and player_pos.x < level_strings[player_pos.y].length():
|
||||
var original_char = level_strings[player_pos.y][player_pos.x]
|
||||
if original_char == '*': # 玩家原来在目标点上
|
||||
level_data[player_pos.y][player_pos.x] = CellType.TARGET
|
||||
else:
|
||||
level_data[player_pos.y][player_pos.x] = CellType.EMPTY
|
||||
else:
|
||||
level_data[player_pos.y][player_pos.x] = CellType.EMPTY
|
||||
|
||||
# 更新玩家位置
|
||||
player_pos = new_pos
|
||||
level_data[player_pos.y][player_pos.x] = CellType.PLAYER
|
||||
|
||||
# 增加步数
|
||||
moves += 1
|
||||
|
||||
# 检查是否过关
|
||||
check_win_condition()
|
||||
|
||||
# 更新UI和重绘
|
||||
update_ui()
|
||||
queue_redraw()
|
||||
|
||||
func check_win_condition():
|
||||
# 检查是否所有箱子都在目标点上
|
||||
for y in range(map_height):
|
||||
for x in range(map_width):
|
||||
if level_data[y][x] == CellType.BOX:
|
||||
return # 还有箱子不在目标点上
|
||||
|
||||
# 所有箱子都在目标点上,过关!
|
||||
level_completed = true
|
||||
win_label.visible = true
|
||||
|
||||
func next_level():
|
||||
if current_level < LEVELS.size() - 1:
|
||||
current_level += 1
|
||||
init_level()
|
||||
|
||||
func prev_level():
|
||||
if current_level > 0:
|
||||
current_level -= 1
|
||||
init_level()
|
||||
|
||||
func update_ui():
|
||||
level_label.text = "关卡: " + str(current_level + 1)
|
||||
moves_label.text = "步数: " + str(moves)
|
||||
|
||||
func _draw():
|
||||
if not game_area:
|
||||
return
|
||||
|
||||
# 获取游戏区域位置
|
||||
var area_pos = game_area.position
|
||||
|
||||
# 计算起始绘制位置(居中)
|
||||
var start_x = area_pos.x + (game_area.size.x - map_width * CELL_SIZE) / 2
|
||||
var start_y = area_pos.y + (game_area.size.y - map_height * CELL_SIZE) / 2
|
||||
|
||||
# 绘制地图
|
||||
for y in range(map_height):
|
||||
for x in range(map_width):
|
||||
var cell_x = start_x + x * CELL_SIZE
|
||||
var cell_y = start_y + y * CELL_SIZE
|
||||
var rect = Rect2(cell_x, cell_y, CELL_SIZE, CELL_SIZE)
|
||||
|
||||
var cell_type = level_data[y][x]
|
||||
var color = CELL_COLORS[cell_type]
|
||||
|
||||
# 绘制单元格
|
||||
draw_rect(rect, color, true)
|
||||
|
||||
# 绘制边框
|
||||
draw_rect(rect, Color.BLACK, false, 1)
|
||||
|
||||
# 特殊处理:如果是玩家在目标点上,需要先绘制目标点
|
||||
if cell_type == CellType.PLAYER:
|
||||
# 检查玩家下面是否有目标点(通过检查原始关卡数据)
|
||||
var level_strings = LEVELS[current_level]
|
||||
if y < level_strings.size() and x < level_strings[y].length():
|
||||
var original_char = level_strings[y][x]
|
||||
if original_char == '*': # 玩家在目标点上
|
||||
draw_rect(rect, CELL_COLORS[CellType.TARGET], true)
|
||||
draw_rect(rect, Color.BLACK, false, 1)
|
||||
# 再绘制玩家(半透明)
|
||||
var player_color = CELL_COLORS[CellType.PLAYER]
|
||||
player_color.a = 0.8
|
||||
draw_rect(rect, player_color, true)
|
||||
Reference in New Issue
Block a user