1
1
mirror of https://github.com/Rundll86/Dog-Lynx-And-HCN.git synced 2026-05-29 23:41:54 +08:00

feat(多人游戏): 实现基础多人游戏功能

- 添加玩家位置同步功能
- 实现服务器和客户端连接管理
- 添加玩家名称输入和生成逻辑
- 完善多人游戏UI界面
- 移除单机模式下的预设玩家角色
This commit is contained in:
2025-11-09 17:00:39 +08:00
parent c28d725d3e
commit 79bc956b71
5 changed files with 117 additions and 20 deletions
+28
View File
@@ -3,6 +3,7 @@ extends FullscreenPanelBase
@onready var diffEdit: HSlider = $"%diffEdit"
@onready var startBtn: Button = $"%startBtn"
@onready var startMultiplayerBtn: Button = $"%startMultiplayerBtn"
@onready var levelShow: Label = $"%levelShow"
@onready var hostInput: LineEdit = $"%hostInput"
@onready var portInput: LineEdit = $"%portInput"
@@ -11,15 +12,30 @@ extends FullscreenPanelBase
@onready var maxPlayerInput: LineEdit = $"%maxPlayerInput"
@onready var connectionState: Label = $"%connectionState"
@onready var disconnectBtn: Button = $"%disconnectBtn"
@onready var playerNameInput: LineEdit = $"%playerNameInput"
@onready var serverConfig: VBoxContainer = $"%serverConfig"
func _ready():
diffEdit.min_value = GameRule.difficultyRange.x
diffEdit.max_value = GameRule.difficultyRange.y
multiplayer.connection_failed.connect(
func():
setState(MultiplayerState.ConnectionState.DISCONNECTED)
)
multiplayer.peer_connected.connect(
func():
setState(MultiplayerState.ConnectionState.CONNECTED_CLIENT)
)
startBtn.pressed.connect(
func():
EntityBase.generatePlayer(playerNameInput.text)
Wave.next()
UIState.closeCurrentPanel()
)
startMultiplayerBtn.pressed.connect(
func():
pass
)
maxPlayerInput.text_changed.connect(
func(text):
MultiplayerState.maxPlayer = int(text)
@@ -27,6 +43,16 @@ func _ready():
launchBtn.pressed.connect(
func():
MultiplayerState.launchServer(int(portInput.text))
setState(MultiplayerState.ConnectionState.CONNECTED_HOST)
)
connectBtn.pressed.connect(
func():
multiplayer.multiplayer_peer = MultiplayerState.connectClient(hostInput.text, int(portInput.text))
setState(MultiplayerState.ConnectionState.CONNECTING)
)
disconnectBtn.pressed.connect(
func():
setState(MultiplayerState.ConnectionState.DISCONNECTED)
)
setState(MultiplayerState.ConnectionState.DISCONNECTED)
func _physics_process(_delta):
@@ -38,3 +64,5 @@ func setState(state: MultiplayerState.ConnectionState):
connectionState.text = "状态:%s" % MultiplayerState.stateTextMap[state]
connectionState.modulate = MultiplayerState.stateColorMap[state]
disconnectBtn.disabled = not MultiplayerState.isConnected()
startMultiplayerBtn.disabled = not MultiplayerState.isConnected()
serverConfig.visible = MultiplayerState.state == MultiplayerState.ConnectionState.CONNECTED_HOST
+23 -1
View File
@@ -175,6 +175,7 @@ func _physics_process(_delta: float) -> void:
move_and_slide()
storeEnergy(randf_range(0.01, 0.05 + fields.get(FieldStore.Entity.ENERGY_REGENERATION) - 1), true)
trailParticle.emitting = trailing
rpc("syncPosition", displayName, position)
# 通用方法
func rebuildWeaponIcons():
@@ -393,11 +394,26 @@ func summon(who: PackedScene, syncFields: bool = true, lockValue: bool = true) -
get_parent().add_child(instance)
return instance
# 多人游戏数据同步
@rpc("any_peer")
func syncPosition(player: String, newPosition: Vector2):
if player == displayName:
position = newPosition
@rpc("any_peer")
func syncHealth(player: String, newHealth: float):
if player == displayName:
health = newHealth
healthChanged.emit(health)
@rpc("any_peer")
func syncAttack(player: String, index: int):
if player == displayName:
tryAttack(index)
# 关于追踪
func getTrackingAnchor() -> Vector2:
return hurtbox.get_node("hitbox").global_position
# 关于分组
# 关于实体类型
func isPlayer() -> bool:
return is_in_group("players")
func isSummon() -> bool:
@@ -430,6 +446,10 @@ func enterStage(_stage: int):
func kill():
pass
static func generatePlayer(playerName: String):
var player = generate(ComponentManager.getCharacter("Rooster"), Vector2.ZERO, false, false, true)
player.displayName = playerName
return player
static func generate(
entity: PackedScene,
spawnPosition: Vector2,
@@ -443,6 +463,8 @@ static func generate(
instance.level = clamp((round(Wave.current * (1 + GameRule.entityLevelOffsetByWave * randf_range(-1, 1)))), 1, INF)
if isMob:
instance.add_to_group("mobs")
else:
instance.add_to_group("players")
if addToWorld:
WorldManager.rootNode.add_child(instance)
return instance
+3 -4
View File
@@ -9,7 +9,7 @@ enum ConnectionState {
}
static var stateTextMap = {
ConnectionState.DISCONNECTED: "未连接到服务器。",
ConnectionState.CONNECTING: "连接中...",
ConnectionState.CONNECTING: "正在连接到服务器...",
ConnectionState.CONNECTED_HOST: "服务器启动成功!",
ConnectionState.CONNECTED_CLIENT: "已连接到服务器!",
}
@@ -21,18 +21,17 @@ static var stateColorMap = {
}
static var state: ConnectionState = ConnectionState.DISCONNECTED
static var isMultiplayer: bool = false
static var maxPlayer: int = 10
static func isConnected():
return [ConnectionState.CONNECTED_HOST, ConnectionState.CONNECTED_CLIENT].has(state)
static func launchServer(port: int):
static func launchServer(port: int) -> ENetMultiplayerPeer:
var peer = ENetMultiplayerPeer.new()
peer.create_server(port, maxPlayer)
state = ConnectionState.CONNECTED_HOST
return peer
static func connectClient(host: String, port: int):
static func connectClient(host: String, port: int) -> ENetMultiplayerPeer:
var peer = ENetMultiplayerPeer.new()
peer.create_client(host, port)
state = ConnectionState.CONNECTED_CLIENT