Геймпад Xbox, меню паузы с настройками, новый хаб с музыкой
- Геймпад: раскладка под паркур и гонки, обзор правым стиком, навигация по меню (A/B/крестовина) - Меню паузы (Esc/Start): выход в хаб, настройки (мышь, стик, FOV, громкость, инверсия), справка по управлению - Хаб 48x32x10 м: колонны, окна с городом, голограмма, лавки; музыка «Local Forecast - Elevator» (Kevin MacLeod, CC-BY) - Тесты: pause_test, pad_menu_test, hub_tour; README обновлён Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
+32
-9
@@ -207,7 +207,8 @@ func _ready() -> void:
|
||||
add_to_group("local_player")
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
head_base_pos = head.position
|
||||
base_fov = head.fov
|
||||
base_fov = Settings.fov
|
||||
head.fov = base_fov
|
||||
|
||||
# Тело видно в редакторе и отбрасывает тень, но своя камера его не рисует (слой 2)
|
||||
for mi: MeshInstance3D in $Model.find_children("*", "MeshInstance3D", true, false):
|
||||
@@ -245,8 +246,7 @@ func _setup_vignette() -> void:
|
||||
rect.material = vignette_material
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
# Esc / Start теперь открывают меню паузы (core/pause_menu.gd), оно само освобождает мышь
|
||||
|
||||
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and not Net.input_blocked:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED # (панель ника открыта — мышь нужна на экране)
|
||||
@@ -255,10 +255,7 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||
return
|
||||
|
||||
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
||||
var zoom_factor := head.fov / base_fov
|
||||
rotate_y(-event.relative.x * MOUSE_SENSITIVITY * zoom_factor)
|
||||
head.rotate_x(-event.relative.y * MOUSE_SENSITIVITY * zoom_factor)
|
||||
head.rotation.x = clamp(head.rotation.x, deg_to_rad(-80), deg_to_rad(80))
|
||||
_mouse_look(event.relative)
|
||||
|
||||
if input_frozen or Net.input_blocked:
|
||||
return
|
||||
@@ -268,6 +265,32 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||
elif event.is_action_pressed("dash"):
|
||||
_try_dash()
|
||||
|
||||
# Обзор мышью: смещение в пикселях -> поворот с учётом чувствительности из настроек и зума
|
||||
func _mouse_look(relative: Vector2) -> void:
|
||||
var k := MOUSE_SENSITIVITY * Settings.mouse_sens * head.fov / base_fov
|
||||
_look(relative.x * k, relative.y * k)
|
||||
|
||||
# Поворот обзора (радианы за событие/кадр); вертикаль можно инвертировать в настройках
|
||||
func _look(dx: float, dy: float) -> void:
|
||||
if Settings.invert_y:
|
||||
dy = -dy
|
||||
rotate_y(-dx)
|
||||
head.rotate_x(-dy)
|
||||
head.rotation.x = clamp(head.rotation.x, deg_to_rad(-80), deg_to_rad(80))
|
||||
|
||||
# Обзор правым стиком геймпада (плавно, каждый кадр); кривая 1.6 даёт точность у центра и быстрый разворот на краю
|
||||
func _process(delta: float) -> void:
|
||||
base_fov = Settings.fov
|
||||
if is_dead or Net.input_blocked: # открыто меню/панель ника (на отсчёте гонки обзор разрешён, как мышью)
|
||||
return
|
||||
var v := Input.get_vector("look_left", "look_right", "look_up", "look_down")
|
||||
if v == Vector2.ZERO:
|
||||
return
|
||||
var strength := pow(minf(v.length(), 1.0), 1.6)
|
||||
v = v.normalized() * strength
|
||||
var k := Settings.STICK_LOOK_SPEED * Settings.stick_sens * delta * head.fov / base_fov
|
||||
_look(v.x * k, v.y * k)
|
||||
|
||||
# Битовые флаги состояния для сетевой синхронизации (см. Net.FLAG_*)
|
||||
func get_net_flags() -> int:
|
||||
var flags := 0
|
||||
@@ -887,8 +910,8 @@ func _update_camera(delta: float, input_dir: Vector2) -> void:
|
||||
head.rotation.z = current_roll + randf_range(-1.0, 1.0) * shake_strength * 0.3
|
||||
|
||||
# Зум на ЛКМ
|
||||
is_zooming = Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) \
|
||||
and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED
|
||||
is_zooming = (Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED) \
|
||||
or (Input.is_action_pressed("zoom") and not Net.input_blocked)
|
||||
|
||||
# FOV: зум > рывок > слайд > стена > скорость бега
|
||||
var target_fov := base_fov + sprint_factor * SPRINT_FOV_BONUS
|
||||
|
||||
Reference in New Issue
Block a user