完善客户端功能并加入40250一致性审计
This commit is contained in:
@@ -65,6 +65,13 @@ var rotation_speed_deg := ROT_SPEED_DEFAULT_DEG # 上/下马时由 net_play 切
|
||||
# CActorInstance::CanSkipCollision():网络状态包驱动的移动整段跳过 Actor 碰撞
|
||||
# (§3.2 __EnableSkipCollision,观战 / 服务器纠正时置真)。
|
||||
var skip_actor_collision := false
|
||||
# 40250 CPythonPlayer::NEW_SetSingleDirKeyState:方向由进入游戏后的按下/松开事件
|
||||
# 维护,不能每帧查询系统全局键盘状态。否则加载场景时仍按着的键会被继承,表现为
|
||||
# 刚进入游戏角色就自动移动。
|
||||
var _key_up := false
|
||||
var _key_down := false
|
||||
var _key_left := false
|
||||
var _key_right := false
|
||||
var _last_wasd := Vector2.ZERO
|
||||
var _mobile_axis := Vector2.ZERO
|
||||
var _mobile_active := false
|
||||
@@ -79,13 +86,21 @@ var _dst_rot := 0.0
|
||||
var _reserved_ground: Variant = null # __ReserveClickGround 的待处理点
|
||||
var _reserved_delay_time := 0.0 # NEW_IsEmptyReservedDelayTime 递减到 0 才生效
|
||||
|
||||
var active := true # 进游戏装配/加载中置假,防止过早响应点地
|
||||
var active := true: # 进游戏装配/加载中置假,防止过早响应点地
|
||||
set(value):
|
||||
if active == value:
|
||||
return
|
||||
active = value
|
||||
# 切换输入阶段相当于 40250 game.Close/Open 重建按键状态。只有在游戏窗
|
||||
# 激活后新收到的 KeyDown 才能驱动角色。
|
||||
_clear_direction_keys()
|
||||
# 40250 CInstanceBase::NEW_Stop() / CPythonPlayer::NEW_Stop():停止点地移动与方向输入,重置预约
|
||||
func stop() -> void:
|
||||
_is_going = false
|
||||
_reserved_ground = null
|
||||
_reserved_delay_time = 0.0
|
||||
_last_wasd = Vector2.ZERO
|
||||
_clear_direction_keys()
|
||||
_mobile_active = false
|
||||
_mobile_axis = Vector2.ZERO
|
||||
_mobile_ui_touches.clear()
|
||||
@@ -97,6 +112,39 @@ func stop() -> void:
|
||||
_dst_pos = player.position
|
||||
anim_state.emit("wait")
|
||||
|
||||
func _clear_direction_keys() -> void:
|
||||
_key_up = false
|
||||
_key_down = false
|
||||
_key_left = false
|
||||
_key_right = false
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_APPLICATION_FOCUS_OUT:
|
||||
# KeyUp 可能在窗口失焦期间丢失;参考客户端失去游戏窗口输入后停止移动。
|
||||
_clear_direction_keys()
|
||||
_last_wasd = Vector2.ZERO
|
||||
|
||||
func _input(e: InputEvent) -> void:
|
||||
if not (e is InputEventKey) or e.echo:
|
||||
return
|
||||
var key := e as InputEventKey
|
||||
# 松开事件必须始终接收,即使此时 UI 正在拦截游戏输入,否则会留下粘键。
|
||||
# KeyDown 则在 _unhandled_input 中接收,让聊天输入框有机会先消费 WASD。
|
||||
if not key.pressed:
|
||||
_set_direction_key_state(key, false)
|
||||
|
||||
func _set_direction_key_state(e: InputEventKey, pressed: bool) -> void:
|
||||
var logical := e.keycode
|
||||
var physical := e.physical_keycode
|
||||
if logical in [KEY_W, KEY_UP] or physical in [KEY_W, KEY_UP]:
|
||||
_key_up = pressed
|
||||
elif logical in [KEY_S, KEY_DOWN] or physical in [KEY_S, KEY_DOWN]:
|
||||
_key_down = pressed
|
||||
elif logical in [KEY_A, KEY_LEFT] or physical in [KEY_A, KEY_LEFT]:
|
||||
_key_left = pressed
|
||||
elif logical in [KEY_D, KEY_RIGHT] or physical in [KEY_D, KEY_RIGHT]:
|
||||
_key_right = pressed
|
||||
|
||||
# CInstanceBase::__IsSyncing():Dead / Stun / Pushing 中不接受移动输入(net_play 置 frozen)。
|
||||
func is_going() -> bool:
|
||||
return _is_going
|
||||
@@ -184,7 +232,11 @@ func _goto(dst_flat: Vector3) -> bool:
|
||||
func _unhandled_input(e: InputEvent) -> void:
|
||||
if not active:
|
||||
return
|
||||
if e is InputEventMouseButton and e.button_index == MOUSE_BUTTON_LEFT and e.pressed:
|
||||
if e is InputEventKey:
|
||||
var key := e as InputEventKey
|
||||
if key.pressed and not key.echo:
|
||||
_set_direction_key_state(key, true)
|
||||
elif e is InputEventMouseButton and e.button_index == MOUSE_BUTTON_LEFT and e.pressed:
|
||||
_on_click(e.position)
|
||||
elif e is InputEventScreenTouch:
|
||||
_on_touch(e)
|
||||
@@ -326,26 +378,17 @@ func _ray_ground(from: Vector3, dir: Vector3) -> Variant:
|
||||
return null
|
||||
|
||||
func _wasd() -> Vector2:
|
||||
if ui_manager and ui_manager.has_method("blocks_game_input"):
|
||||
var dummy := InputEventKey.new()
|
||||
dummy.keycode = KEY_W
|
||||
if ui_manager.blocks_game_input(dummy):
|
||||
return Vector2.ZERO
|
||||
var is_up := Input.is_key_pressed(KEY_W) or Input.is_physical_key_pressed(KEY_W) or Input.is_key_pressed(KEY_UP)
|
||||
var is_down := Input.is_key_pressed(KEY_S) or Input.is_physical_key_pressed(KEY_S) or Input.is_key_pressed(KEY_DOWN)
|
||||
var is_left := Input.is_key_pressed(KEY_A) or Input.is_physical_key_pressed(KEY_A) or Input.is_key_pressed(KEY_LEFT)
|
||||
var is_right := Input.is_key_pressed(KEY_D) or Input.is_physical_key_pressed(KEY_D) or Input.is_key_pressed(KEY_RIGHT)
|
||||
if not (is_up or is_down or is_left or is_right):
|
||||
if not (_key_up or _key_down or _key_left or _key_right):
|
||||
return Vector2.ZERO
|
||||
var d := Vector2.ZERO
|
||||
# 对齐 40250 CPythonPlayer::NEW_GetMultiKeyDirRotation: Up优先于Down,Left优先于Right
|
||||
if is_up:
|
||||
if _key_up:
|
||||
d.y = -1.0
|
||||
elif is_down:
|
||||
elif _key_down:
|
||||
d.y = 1.0
|
||||
if is_left:
|
||||
if _key_left:
|
||||
d.x = -1.0
|
||||
elif is_right:
|
||||
elif _key_right:
|
||||
d.x = 1.0
|
||||
return d.normalized()
|
||||
|
||||
@@ -396,18 +439,17 @@ func _actor_blocked(next_pos: Vector3) -> bool:
|
||||
func _turn_toward(target_yaw: float, dt: float) -> void:
|
||||
if player == null:
|
||||
return
|
||||
player.rotation.x = 0.0
|
||||
player.rotation.z = 0.0
|
||||
var cur_yaw: float = wrapf(player.rotation.y, -PI, PI)
|
||||
var diff: float = wrapf(target_yaw - cur_yaw, -PI, PI)
|
||||
var spd := rotation_speed_deg
|
||||
if absf(diff) <= deg_to_rad(45.0):
|
||||
spd *= 5.0 / 12.0
|
||||
var max_step := deg_to_rad(spd) * dt
|
||||
if max_step <= 0.0 or absf(diff) <= max_step:
|
||||
player.rotation.y = target_yaw
|
||||
else:
|
||||
player.rotation.y = wrapf(cur_yaw + signf(diff) * max_step, -PI, PI)
|
||||
var next_yaw := target_yaw if max_step <= 0.0 or absf(diff) <= max_step \
|
||||
else wrapf(cur_yaw + signf(diff) * max_step, -PI, PI)
|
||||
# 只允许直立偏航。逐项修改 Euler 分量在 W/S 180° 快切和 ±PI 边界附近可能
|
||||
# 被引擎重新分解为 X/Z = PI,看起来就是角色翻跟头。
|
||||
player.rotation = Vector3(0.0, wrapf(next_yaw, -PI, PI), 0.0)
|
||||
|
||||
func _process(dt: float) -> void:
|
||||
if player == null or not active:
|
||||
|
||||
Reference in New Issue
Block a user