update
This commit is contained in:
@@ -7,6 +7,7 @@ var ok := 0
|
||||
var fail := 0
|
||||
var worst := 0.0
|
||||
var elapsed := 0.0
|
||||
var sfx_first := false
|
||||
|
||||
func chk(n: String, c: bool, i := "") -> void:
|
||||
if c: ok += 1; print(" OK %s %s" % [n, i])
|
||||
@@ -23,11 +24,14 @@ func _process(d):
|
||||
if not main.started:
|
||||
main._start_solo()
|
||||
return
|
||||
if not main.audio.loaded:
|
||||
if not main.audio.music_loaded:
|
||||
elapsed += d
|
||||
worst = maxf(worst, d)
|
||||
if main.audio.loaded:
|
||||
sfx_first = true
|
||||
return
|
||||
if step == 0:
|
||||
chk("Klänge vor der Musik verfügbar", sfx_first)
|
||||
chk("Kein Ruckler beim Erzeugen", worst < 0.2,
|
||||
"längster Frame %.0f ms in %.1f s Ladezeit" % [worst * 1000.0, elapsed])
|
||||
if wait > 0.0:
|
||||
@@ -56,7 +60,7 @@ func _process(d):
|
||||
chk("Thread beendet", a._thread == null)
|
||||
var m: AudioStreamWAV = a._music.stream
|
||||
chk("Musik ist eine Schleife", m.loop_mode == AudioStreamWAV.LOOP_FORWARD)
|
||||
chk("Musik lang genug", m.data.size() / 2 > 20 * 22050,
|
||||
chk("Musik hat drei Teile", m.data.size() / 2 > 75 * 22050,
|
||||
"%.1f s" % (m.data.size() / 2.0 / 22050.0))
|
||||
chk("Musik nicht stumm", _peak(m) > 3000, "peak=%d" % _peak(m))
|
||||
chk("Rumble läuft leise", a._rumble.playing and a._rumble.volume_db < -40.0,
|
||||
@@ -134,7 +138,7 @@ func _peak(w: AudioStreamWAV) -> int:
|
||||
func _check_harmony() -> void:
|
||||
var Sfx = load("res://scripts/sfx.gd")
|
||||
var bad: Array[String] = []
|
||||
for stage in Sfx.PROGRESSION:
|
||||
for stage in Sfx.PROGRESSION + Sfx.PROGRESSION_B:
|
||||
var voices: Array[float] = []
|
||||
for f in stage["pad"]:
|
||||
voices.append(float(f))
|
||||
|
||||
@@ -31,6 +31,7 @@ func _process(d):
|
||||
if role == "host":
|
||||
main._start_host(7788)
|
||||
elif role == "client" and step == 0:
|
||||
main.menu._name.text = "Tester"
|
||||
main._start_join("127.0.0.1", 7788)
|
||||
step = 1
|
||||
return
|
||||
@@ -42,14 +43,24 @@ func _process(d):
|
||||
else:
|
||||
_client_step()
|
||||
|
||||
func _key(c: int, d: bool) -> void:
|
||||
var e := InputEventKey.new(); e.physical_keycode = c; e.keycode = c; e.pressed = d
|
||||
Input.parse_input_event(e)
|
||||
|
||||
func _host_step() -> void:
|
||||
match step:
|
||||
0:
|
||||
print("[host] Sitzung gestartet")
|
||||
for i in 4:
|
||||
main.spawn_passenger(0, 2)
|
||||
wait = 30.0
|
||||
wait = 16.0
|
||||
1:
|
||||
# Host faehrt los, der Client soll das weich sehen
|
||||
main._srv_toggle_drive(1)
|
||||
_key(KEY_W, true)
|
||||
wait = 20.0
|
||||
2:
|
||||
_key(KEY_W, false)
|
||||
print("[host] Ende. money=%d driver=%d" % [main.money, main.driver_id])
|
||||
get_tree().quit()
|
||||
step += 1
|
||||
@@ -59,7 +70,7 @@ func _client_step() -> void:
|
||||
1:
|
||||
wait = 6.0
|
||||
2:
|
||||
chk("Welt gebaut", main.stations.size() == 5)
|
||||
chk("Welt gebaut", main.stations.size() == 6)
|
||||
chk("Zug übernommen", main.train.cars.size() == 3, "cars=%d" % main.train.cars.size())
|
||||
chk("Eigene Peer-ID", main.my_id > 1)
|
||||
chk("Fahrgäste sichtbar", main.passengers.size() >= 4, "n=%d" % main.passengers.size())
|
||||
@@ -69,6 +80,11 @@ func _client_step() -> void:
|
||||
seated += 1
|
||||
chk("Gäste sitzen", seated >= 4, "seated=%d" % seated)
|
||||
chk("Geld synchron", main.money == 1500)
|
||||
chk("Eigener Name beim Host angekommen",
|
||||
String(main.players[main.my_id]["name"]) == "Tester",
|
||||
"%s" % main.players[main.my_id]["name"])
|
||||
var host_av = main.players.get(1, {}).get("avatar")
|
||||
chk("Avatar des Hosts sichtbar", host_av != null)
|
||||
main.request("drive")
|
||||
wait = 1.5
|
||||
3:
|
||||
@@ -96,6 +112,36 @@ func _client_step() -> void:
|
||||
wait = 2.0
|
||||
6:
|
||||
chk("Kein Selbstlauf ohne Gas", main.train.speed < 0.01)
|
||||
main.request("drive") # Steuerung abgeben, der Host faehrt gleich
|
||||
_measuring = true
|
||||
wait = 12.0
|
||||
7:
|
||||
_measuring = false
|
||||
chk("Zug beim Client in Fahrt", _top_speed > 3.0, "v=%.1f" % _top_speed)
|
||||
chk("Zug beim Client ruckelfrei", _frames > 100 and _jumps * 20 < _frames,
|
||||
"%d Sprünge in %d Frames, größter %.2f m" % [_jumps, _frames, _worst])
|
||||
print("[client] == %d ok, %d fail ==" % [ok, fail])
|
||||
get_tree().quit(1 if fail > 0 else 0)
|
||||
step += 1
|
||||
|
||||
var _measuring := false
|
||||
var _last := Vector3.ZERO
|
||||
var _frames := 0
|
||||
var _jumps := 0
|
||||
var _worst := 0.0
|
||||
var _top_speed := 0.0
|
||||
|
||||
func _physics_process(d: float) -> void:
|
||||
if not _measuring or main == null or not main.started:
|
||||
return
|
||||
var t = main.train
|
||||
var p: Vector3 = t.cars[0].global_position
|
||||
if _last != Vector3.ZERO and t.speed > 1.0:
|
||||
_frames += 1
|
||||
var moved := p.distance_to(_last)
|
||||
var expected: float = t.speed * d
|
||||
_worst = maxf(_worst, absf(moved - expected))
|
||||
if absf(moved - expected) > 0.6:
|
||||
_jumps += 1
|
||||
_top_speed = maxf(_top_speed, t.speed)
|
||||
_last = p
|
||||
|
||||
10
tests/run.sh
10
tests/run.sh
@@ -27,6 +27,12 @@ install_test tests/input_test.gd
|
||||
"$GODOT" --path . --resolution 1280x720 2>&1 | grep -E "OK|FAIL|=="
|
||||
INPUT=${PIPESTATUS[0]}
|
||||
|
||||
echo
|
||||
echo "=== Weichen-Tests ==="
|
||||
install_test tests/switch_test.gd
|
||||
"$GODOT" --path . --resolution 1280x720 2>&1 | grep -E "OK|FAIL|=="
|
||||
SWITCH=${PIPESTATUS[0]}
|
||||
|
||||
echo
|
||||
echo "=== Klang-Tests ==="
|
||||
install_test tests/audio_test.gd
|
||||
@@ -50,5 +56,5 @@ NET=${PIPESTATUS[0]}
|
||||
wait $HOST 2>/dev/null
|
||||
|
||||
echo
|
||||
[ "$SOLO" -eq 0 ] && [ "$INPUT" -eq 0 ] && [ "$DIR" -eq 0 ] && [ "$AUDIO" -eq 0 ] && [ "$NET" -eq 0 ] && echo "Alle Tests bestanden." || echo "Es sind Tests fehlgeschlagen."
|
||||
exit $(( SOLO || INPUT || DIR || AUDIO || NET ))
|
||||
[ "$SOLO" -eq 0 ] && [ "$SWITCH" -eq 0 ] && [ "$INPUT" -eq 0 ] && [ "$DIR" -eq 0 ] && [ "$AUDIO" -eq 0 ] && [ "$NET" -eq 0 ] && echo "Alle Tests bestanden." || echo "Es sind Tests fehlgeschlagen."
|
||||
exit $(( SOLO || SWITCH || INPUT || DIR || AUDIO || NET ))
|
||||
|
||||
@@ -112,6 +112,36 @@ func _process(d):
|
||||
var before = main.train.consist.size()
|
||||
main.sell_car(0)
|
||||
chk("Wagen verkauft", main.train.consist.size() == before - 1)
|
||||
# Lok verkaufen: Dampf-Veteran springt ein, Geld kommt zurueck
|
||||
var m_before = main.money
|
||||
main.request("sell_loco")
|
||||
chk("Lok verkauft", main.train.loco_id == "steam", "loco=%s" % main.train.loco_id)
|
||||
chk("Rücknahme gutgeschrieben", main.money - m_before == 6600, "+%d €" % (main.money - m_before))
|
||||
main.buy_loco("express")
|
||||
# Speichern und Laden
|
||||
main.save_game()
|
||||
var saved_money = main.money
|
||||
var saved_consist = main.train.consist.duplicate()
|
||||
var saved_seg = main.train.seg
|
||||
var saved_prog = main.train.progress
|
||||
main.money = 1
|
||||
main.train.consist = ["coach"] as Array[String]
|
||||
main.train.loco_id = "steam"
|
||||
main._rebuild_train()
|
||||
chk("Spielstand geladen", main.load_game())
|
||||
chk("Geld wiederhergestellt", main.money == saved_money, "%d vs %d" % [main.money, saved_money])
|
||||
chk("Zug wiederhergestellt", main.train.consist == saved_consist and main.train.loco_id == "express",
|
||||
"%s %s" % [main.train.loco_id, main.train.consist])
|
||||
chk("Position wiederhergestellt", main.train.seg == saved_seg and absf(main.train.progress - saved_prog) < 0.5)
|
||||
# Ziele
|
||||
main.tickets_checked = 10
|
||||
var m_goal = main.money
|
||||
main._check_goals()
|
||||
chk("Ziel erreicht", main.goals_done.has("tickets10"))
|
||||
chk("Belohnung gezahlt", main.money - m_goal == 250, "+%d €" % (main.money - m_goal))
|
||||
chk("Ziele der Reihe nach", not main.goals_done.has("cargo30") and not main.won)
|
||||
var g = main.current_goal()
|
||||
chk("Nächstes Ziel im HUD", String(g.get("text", "")).begins_with("30 Einheiten"), "%s" % g)
|
||||
wait = 0.3
|
||||
7:
|
||||
chk("Spieler im Zug", main.train.locate(main.player.s)["index"] == 0)
|
||||
@@ -121,6 +151,9 @@ func _process(d):
|
||||
wait = 3.0
|
||||
8:
|
||||
chk("Zug fährt", main.train.speed > 3.0, "v=%.1f m/s" % main.train.speed)
|
||||
var e: Vector3 = main.train.cars[0].global_transform.basis.get_euler()
|
||||
chk("Wagen wackelt bei Fahrt", absf(e.z) > 0.0005 or absf(e.x) > 0.0005,
|
||||
"roll=%.4f pitch=%.4f" % [e.z, e.x])
|
||||
_key(KEY_W, false)
|
||||
_key(KEY_S, true)
|
||||
wait = 4.0
|
||||
|
||||
175
tests/switch_test.gd
Normal file
175
tests/switch_test.gd
Normal file
@@ -0,0 +1,175 @@
|
||||
extends Node
|
||||
## Weichen: Route wählen, Übergang ohne Sprung, Bergstrecke erreichbar.
|
||||
var main
|
||||
var step := 0
|
||||
var wait := 0.0
|
||||
var ok := 0
|
||||
var fail := 0
|
||||
var last_pos := Vector3.ZERO
|
||||
var worst_jump := 0.0
|
||||
var jump_frames := 0
|
||||
var _dbg := 0.0
|
||||
var _cam_hits := 0
|
||||
var _cam_pulled := 0
|
||||
var _cam_yaw := 0
|
||||
|
||||
func chk(n: String, c: bool, i := "") -> void:
|
||||
if c: ok += 1; print(" OK %s %s" % [n, i])
|
||||
else: fail += 1; print(" FAIL %s %s" % [n, i])
|
||||
|
||||
func _key(c: int, d: bool) -> void:
|
||||
var e := InputEventKey.new(); e.physical_keycode = c; e.keycode = c; e.pressed = d
|
||||
Input.parse_input_event(e)
|
||||
|
||||
func _watch(d: float) -> void:
|
||||
var t = main.train
|
||||
var p: Vector3 = t.cars[t.cars.size() - 1].global_position
|
||||
if last_pos != Vector3.ZERO and d > 0.0:
|
||||
var jump := p.distance_to(last_pos)
|
||||
var allowed: float = t.speed * d * 1.5 + 0.05
|
||||
if jump > allowed:
|
||||
jump_frames += 1
|
||||
worst_jump = maxf(worst_jump, jump - t.speed * d)
|
||||
last_pos = p
|
||||
|
||||
## Im Physik-Takt messen: dort bewegt sich der Zug genau einmal pro Aufruf.
|
||||
func _physics_process(d: float) -> void:
|
||||
if main != null and main.started and step >= 1 and step <= 8:
|
||||
_watch(d)
|
||||
|
||||
func _process(d):
|
||||
if main == null:
|
||||
main = get_tree().current_scene
|
||||
return
|
||||
if not main.started:
|
||||
main._start_solo()
|
||||
return
|
||||
var t = main.train
|
||||
if wait > 0.0:
|
||||
wait -= d
|
||||
return
|
||||
match step:
|
||||
0:
|
||||
chk("Drei Abschnitte", main.track.segments.size() == 3)
|
||||
chk("Heimstrecke hat Weiche", main.track.is_switch(2))
|
||||
chk("Sechs Bahnhöfe", main.stations.size() == 6)
|
||||
main._park_at(main.stations[4]) # Ahornstadt, Heimstrecke
|
||||
chk("Start auf Heimstrecke", t.seg == 2, "seg=%d" % t.seg)
|
||||
chk("Weiche voraus erkannt", t.upcoming_switch() == 2)
|
||||
var nxt: Array = t.next_station()
|
||||
chk("Nächster Halt Waldkirch (links)", nxt[0].station_name == "Waldkirch",
|
||||
"%s" % nxt[0].station_name)
|
||||
t.switch_choice = 1
|
||||
var nxt2: Array = t.next_station()
|
||||
chk("Nächster Halt Bergblick (rechts)", nxt2[0].station_name == "Bergblick",
|
||||
"%s" % nxt2[0].station_name)
|
||||
t.switch_choice = 0
|
||||
main.driver_id = 1
|
||||
_key(KEY_W, true)
|
||||
last_pos = Vector3.ZERO
|
||||
wait = 1.0
|
||||
1:
|
||||
wait = 0.5
|
||||
2:
|
||||
if t.seg != 0:
|
||||
step -= 1
|
||||
wait = 0.3
|
||||
_dbg += 0.3
|
||||
if _dbg >= 2.0:
|
||||
_dbg = 0.0
|
||||
print("[dbg] seg=%d prog=%.1f/%.1f v=%.1f thr=%.1f driver=%d mode=%d" % [t.seg, t.progress,
|
||||
main.track.seg_length(t.seg), t.speed, t.throttle, main.driver_id, main.player.mode])
|
||||
else:
|
||||
_key(KEY_W, false)
|
||||
_key(KEY_S, true)
|
||||
chk("Links -> Talstrecke", t.seg == 0, "seg=%d" % t.seg)
|
||||
chk("Historie geführt", t.history.size() > 0 and t.history[t.history.size() - 1] == 2,
|
||||
"%s" % [t.history])
|
||||
chk("Letzter Wagen ohne Sprung", jump_frames == 0,
|
||||
"Sprungframes=%d, größter Sprung %.2f m" % [jump_frames, worst_jump])
|
||||
wait = 4.0
|
||||
3:
|
||||
_key(KEY_S, false)
|
||||
main._park_at(main.stations[4])
|
||||
t.switch_choice = 1
|
||||
last_pos = Vector3.ZERO
|
||||
jump_frames = 0
|
||||
worst_jump = 0.0
|
||||
_key(KEY_D, true)
|
||||
_key(KEY_W, true)
|
||||
wait = 1.0
|
||||
4:
|
||||
wait = 0.5
|
||||
5:
|
||||
if t.seg != 1:
|
||||
step -= 1
|
||||
wait = 0.3
|
||||
else:
|
||||
chk("Rechts -> Bergstrecke", t.seg == 1, "seg=%d" % t.seg)
|
||||
chk("D hält die Weiche rechts", t.switch_choice == 1)
|
||||
chk("Übergang rechts ohne Sprung", jump_frames == 0,
|
||||
"Sprungframes=%d" % jump_frames)
|
||||
_key(KEY_D, false)
|
||||
wait = 0.5
|
||||
6:
|
||||
var nxt: Array = t.next_station()
|
||||
chk("Bergblick voraus", nxt[0].station_name == "Bergblick", "%s" % nxt[0].station_name)
|
||||
wait = 0.5
|
||||
7:
|
||||
# bis kurz vor Bergblick fahren, dann bremsen
|
||||
var berg = main.stations[5]
|
||||
var ahead: float = t.distance_ahead(berg)
|
||||
if ahead > t.speed * t.speed / 16.0 + 8.0:
|
||||
step -= 1
|
||||
wait = 0.2
|
||||
else:
|
||||
_key(KEY_W, false)
|
||||
_key(KEY_S, true)
|
||||
wait = 6.0
|
||||
8:
|
||||
_key(KEY_S, false)
|
||||
chk("Zug steht", t.speed < 0.05, "v=%.2f" % t.speed)
|
||||
chk("Am Bergblick angekommen", t.docked_at != null and t.docked_at.station_name == "Bergblick",
|
||||
"dock=%s" % ("-" if t.docked_at == null else t.docked_at.station_name))
|
||||
# Sichtkontrolle: Kreuzung von oben
|
||||
main._park_at(main.stations[4])
|
||||
t.place_head(2, main.track.seg_length(2) - 6.0)
|
||||
main._toggle_camera()
|
||||
main.cam_rig.distance = 95.0
|
||||
main.cam_rig.pitch = deg_to_rad(-70.0)
|
||||
main.cam_rig.yaw = 0.4
|
||||
wait = 1.0
|
||||
9:
|
||||
get_viewport().get_texture().get_image().save_png("user://junction.png")
|
||||
t.place_head(0, main.track.seg_length(0) - 20.0)
|
||||
main.cam_rig.snap_to(t.cars[0].global_position)
|
||||
wait = 1.0
|
||||
10:
|
||||
get_viewport().get_texture().get_image().save_png("user://junction2.png")
|
||||
# Kamera-Kollision: Fokus auf den Bahnsteig, rundherum drehen
|
||||
var st = main.stations[0]
|
||||
main.cam_rig.target = null
|
||||
main.cam_rig.snap_to(st.global_position + Vector3(0, 0, 0))
|
||||
main.cam_rig.distance = 30.0
|
||||
main.cam_rig.pitch = deg_to_rad(-10.0)
|
||||
_cam_hits = 0
|
||||
_cam_yaw = 0
|
||||
wait = 0.2
|
||||
11:
|
||||
if _cam_yaw < 12:
|
||||
main.cam_rig.yaw = _cam_yaw * TAU / 12.0
|
||||
_cam_yaw += 1
|
||||
step -= 1
|
||||
wait = 0.15
|
||||
if main.cam_rig.blocked:
|
||||
_cam_hits += 1
|
||||
var dist: float = main.cam_rig._cam.global_position.distance_to(main.cam_rig.global_position)
|
||||
if dist < 29.0:
|
||||
_cam_pulled += 1
|
||||
else:
|
||||
chk("Kamera stößt am Gebäude an", _cam_hits > 0, "%d von 12 Richtungen" % _cam_hits)
|
||||
chk("Kamera rückt davor", _cam_pulled == _cam_hits, "%d/%d" % [_cam_pulled, _cam_hits])
|
||||
12:
|
||||
print("== %d ok, %d fail ==" % [ok, fail])
|
||||
get_tree().quit(1 if fail > 0 else 0)
|
||||
step += 1
|
||||
Reference in New Issue
Block a user