Ники, общий рейтинг (топ-10 по картам), таблица Tab, сдача в гонке, таймер Parkour
- Ники: профиль user://profile.cfg (client_id + ник), панель при первом запуске и по N; Net.nick_of(id); ники над призраками, в HUD/итогах гонки и таблицах - Рейтинг на сервере: лучшее время каждого игрока по картам race/parkour/metro, топ-10, user://leaderboard.json (атомарная запись, лимиты, проверка карты/комнаты/времени) - Таблица лидеров по Tab, доски топ-3 над порталами в хабе, итоги гонки с общим рейтингом - Гонка: сдача (G, удержание 1,5 с), RACE_GIVEUP; Parkour: таймер, финиш на вершине, R — перезапуск - Новые RPC (submit_profile, recv_nick, submit_record, recv_record_result, request_leaderboard, recv_leaderboard): клиент и сервер выкладываются вместе - Тесты: nicks_lb_test, race_giveup_test, parkour_run_test, nick_ui_test, ui_tour; README обновлён Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WxZo3ekR5m1af437Qzqwc1
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
extends Node
|
||||
# Кадры интерфейса ников и рейтинга для проверки глазами (окно мелькнёт; кадры пишет Godot через --write-movie).
|
||||
# Рейтинг подставляется «из головы» (сервер не нужен). Режимы:
|
||||
# --mode=hub доски над порталами (кадр ~20), панель ника (~40), таблица с вкладками (~65, ~85)
|
||||
# --mode=race HUD с индикатором сдачи (кадры 10..25), итоги с рейтингом (~50), таблица Tab поверх (~70)
|
||||
# --mode=parkour таймер (~20), итоги забега (~40), таблица Tab (~125)
|
||||
# Запуск (кадры a00000040.png и т. д.):
|
||||
# godot --path . --resolution 1152x648 --fixed-fps 10 --write-movie /tmp/shots/hub.png --quit-after 100 res://tools/test/ui_tour.tscn -- --client --mode=hub --profile=/tmp/shots/prof.cfg --server-url=ws://127.0.0.1:1
|
||||
var mode := "hub"
|
||||
var level
|
||||
var p
|
||||
var frame := 0
|
||||
|
||||
func fake_board(rank: int, with_me: bool) -> Dictionary:
|
||||
var names := ["Алиса", "Bob [b]жирный", "Мир", "Zed", "Игрок 417", "Кирилл_К", "NightRunner", "Тень", "ab", "Макс"]
|
||||
var top := []
|
||||
for i in 10:
|
||||
top.append([names[i], 52.318 + i * 1.7321, 0])
|
||||
return {"top": top, "my_rank": rank, "my_time": 52.318 + (rank - 1) * 1.7321 if rank <= 10 else 71.456, "tick": Time.get_ticks_msec()}
|
||||
|
||||
func _ready() -> void:
|
||||
for a in OS.get_cmdline_user_args():
|
||||
if a.begins_with("--mode="):
|
||||
mode = a.substr(7)
|
||||
Net.my_nick = "Мир"
|
||||
Net.nick_asked = true
|
||||
Net.boards["race"] = fake_board(3, true)
|
||||
Net.boards["parkour"] = fake_board(14, true)
|
||||
Net.boards["parkour"].top = Net.boards["parkour"].top.slice(0, 10)
|
||||
Net.boards["metro"] = {"top": [], "my_rank": 0, "my_time": 0.0, "tick": 0}
|
||||
Net.nicks[111] = "Алиса"
|
||||
Net.nicks[222] = "Bob [b]жирный"
|
||||
Net.nicks[333] = "Тень"
|
||||
var scene: String = {"hub": "res://maps/hub/hub.tscn", "race": "res://maps/race/race.tscn", "parkour": "res://maps/parkour/parkour.tscn"}[mode]
|
||||
level = (load(scene) as PackedScene).instantiate()
|
||||
add_child(level)
|
||||
p = level.get_node("Player")
|
||||
if mode == "hub":
|
||||
Net.current_map = "hub"
|
||||
p.set_physics_process(false)
|
||||
p.global_position = Vector3(0, 1.2, 0.5)
|
||||
p.head.rotation.x = deg_to_rad(21)
|
||||
# доски в хабе: подставляем топ вручную (сервера нет)
|
||||
level._on_board_updated("race")
|
||||
level._on_board_updated("parkour")
|
||||
else:
|
||||
p.set_physics_process(false)
|
||||
|
||||
func _process(_d: float) -> void:
|
||||
frame += 1
|
||||
match mode:
|
||||
"hub": _hub()
|
||||
"race": _race()
|
||||
"parkour": _parkour()
|
||||
|
||||
func _hub() -> void:
|
||||
if frame == 35:
|
||||
Overlay.open_nick(true)
|
||||
Overlay._edit.text = "Алиса"
|
||||
Overlay._edit.caret_column = 5
|
||||
if frame == 55:
|
||||
Overlay._nick_layer.visible = false # (настоящее закрытие захватило бы мышь окна)
|
||||
Overlay.nick_open = false
|
||||
Net.input_blocked = false
|
||||
if frame == 60:
|
||||
Overlay.open_lb()
|
||||
if frame == 80:
|
||||
Overlay._lb_index = 1
|
||||
Overlay._lb_refresh()
|
||||
|
||||
func _race() -> void:
|
||||
var rules = level.get_node("Rules")
|
||||
if frame == 3:
|
||||
var now := Time.get_ticks_msec()
|
||||
rules.participants = [rules.my_id]
|
||||
rules.passed = {rules.my_id: 3}
|
||||
rules.start_tick = now - 31000
|
||||
rules.phase = rules.Phase.RACE
|
||||
Input.action_press("giveup")
|
||||
if frame == 28:
|
||||
Input.action_release("giveup")
|
||||
if frame == 40: # итоги: эксперимент вне _process правил (иначе вымышленные игроки «выйдут»)
|
||||
rules.set_process(false)
|
||||
rules.set_physics_process(false)
|
||||
rules.participants = [111, 222, 333, rules.my_id]
|
||||
rules.finish = {111: 52.318, rules.my_id: 55.78}
|
||||
rules.gave_up = {333: true}
|
||||
rules.passed = {111: 8, 222: 5, 333: 2, rules.my_id: 8}
|
||||
Net.last_record["race"] = {"time": 55.78, "rank": 3, "personal": true, "map_record": false}
|
||||
rules._end_race()
|
||||
rules._timer_label.visible = false
|
||||
rules._giveup_label.visible = false
|
||||
if frame == 70:
|
||||
Overlay.open_lb()
|
||||
|
||||
func _parkour() -> void:
|
||||
if frame == 5:
|
||||
p.global_position = Vector3(0, 1.25, -20)
|
||||
level.run_active = true
|
||||
level.run_start_tick = Time.get_ticks_msec() - 23400
|
||||
level._hud_timer = 0.0
|
||||
if frame == 30:
|
||||
level.run_time = 47.512
|
||||
level._finish_run()
|
||||
Net.last_record["parkour"] = {"time": 47.512, "rank": 14, "personal": true, "map_record": false}
|
||||
level._show_results()
|
||||
if frame == 125:
|
||||
Overlay.open_lb()
|
||||
Reference in New Issue
Block a user