Files
my-world/tools/test/race_tour.gd
T
aibrashandClaude Sonnet 5.5 9130202a51 Карта Race: гонка на ногах по киберпанк-антиутопии, 8 игроков
- maps/race: трасса 633 м из Blender (три развилки: срез по контейнерам, каньон со стенами
  против нижней дороги, труба с лазерами против коридора), запечённый свет, небо, дождь, гул;
  фоновая песня (Ogg Vorbis, ~0,6 МБ) включается на «СТАРТ!»
- Правила (race_rules.gd): R — готов; когда готовы все — отсчёт 6 с, заморозка в слотах,
  ворота строго по порядку, сплиты, место, итоги, личный рекорд (user://race_best.cfg)
- Сеть: Net.submit_race / recv_race / race_event (RACE_READY, START, CP, FINISH, STATE).
  ВНИМАНИЕ: набор RPC изменён — клиент и сервер выкладываются вместе, старый клиент
  с новым сервером не работает (rpc node checksum failed)
- player.gd: input_frozen и place() для режимов карт; project.godot: действие ready (R)
- Портал RACE в хабе, пресет экспорта Race (include_filter для ресурсов, грузимых строкой)
- tools/test: двухклиентный тест гонки на локальном сервере, бот, облёт, проверка пакета
- README: правила гонки, события, проверки, заметки

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WxZo3ekR5m1af437Qzqwc1
2026-10-28 17:28:05 +05:00

59 lines
2.9 KiB
GDScript

extends Node
# Облёт карты Race для скриншотов (окно мелькнёт; кадры пишет Godot через --write-movie).
# --mode=gates (по умолчанию): телепорт игрока к воротам и видам трассы, смотрит вдоль трассы
# --mode=hud: «жмёт R», ждёт отсчёт, пробегает ворота (телепортом перед воротами + шаг вперёд), финиш, итоги
# Запуск:
# godot --path . --resolution 1152x648 --fixed-fps 10 --write-movie /tmp/shots/r.png --quit-after 60 res://tools/test/race_tour.tscn -- --client
# godot --path . --resolution 1152x648 --fixed-fps 10 --write-movie /tmp/shots/h.png --quit-after 260 res://tools/test/race_tour.tscn -- --client --mode=hud --race-best=/tmp/shots/best.cfg
const Data = preload("res://maps/race/race_data.gd")
var level
var p
var frame := 0
var mode := "gates"
var gate := 0
# (позиция центра капсулы, рыскание°, наклон°) — виды вдоль трассы
var spots := [
[Vector3(0, 1.25, -20), 0, 4], [Vector3(0, 1.25, -70), 0, 4], [Vector3(0, 5.7, -100), 0, 4], [Vector3(40, 5.7, -195), -90, 4],
[Vector3(120, 5.2, -195), -90, 4], [Vector3(163, 0.4, -290), 0, 4], [Vector3(162, -5.7, -350), 0, 4], [Vector3(161, -5.7, -420), 0, 4],
[Vector3(161, -5.7, -470), 0, 4], [Vector3(161, -6.7, -495), 180, 4],
]
func _ready() -> void:
for a in OS.get_cmdline_user_args():
if a.begins_with("--mode="):
mode = a.substr(7)
level = (load("res://maps/race/race.tscn") as PackedScene).instantiate()
add_child(level)
p = level.get_node("Player")
if mode == "gates":
p.set_physics_process(false)
func _process(_d: float) -> void:
frame += 1
if mode == "gates":
var i := int(frame / 5)
if i < spots.size() and frame % 5 == 1:
var s = spots[i]
p.global_position = s[0]
p.rotation.y = deg_to_rad(s[1])
p.head.rotation.x = deg_to_rad(s[2])
return
var rules = level.get_node("Rules")
if frame == 8:
rules.toggle_ready()
# после старта: каждые 25 кадров ставим игрока за 4 м до очередных ворот лицом вперёд и бежим
if rules.phase == 2 and not rules.finish.has(rules.my_id) and frame % 25 == 0:
var g: int = rules.passed.get(rules.my_id, 0)
if g < Data.CHECKPOINTS.size():
var gp: Vector3 = Data.CHECKPOINTS[g][0]
var yaw := deg_to_rad(Data.CHECKPOINTS[g][2])
if g < 6:
p.global_position = gp - Vector3(-sin(yaw), 0, -cos(yaw)) * 6.0
p.rotation.y = yaw
p.velocity = Vector3.ZERO
Input.action_press("move_forward")
Input.action_press("sprint")
else: # дальше просто засчитываем ворота (облёт проверяет только HUD; проход трассы — в race_game_test)
Input.action_release("move_forward")
Input.action_release("sprint")
p.global_position = gp
rules._pass_gate(g)