W2: several lakes per worldlet, a beach block shelving into the sea with a current that turns swimmers back; testbay test worldlet through the water, edge and boundary suites; the two ways to play (journey, one land) recorded
This commit is contained in:
@@ -4,34 +4,63 @@ extends SceneTree
|
||||
## the invisible wall, falls off the map, or ends up stuck below the waterline
|
||||
## (in a pit near the edge).
|
||||
##
|
||||
## Then the same on a worldlet with a beach (W2, tests/worldlets/testbay.json):
|
||||
## off the beach you swim out into the sea, and the current must turn you back
|
||||
## before the wall (being afloat in the open sea there is fine).
|
||||
##
|
||||
## Run: godot --headless --path . --fixed-fps 30 --script res://tests/test_boundary.gd
|
||||
|
||||
const DIRECTIONS := 24
|
||||
const BAY_DIRECTIONS := 8 # (spread over the beach and its headlands)
|
||||
const SECONDS_PER_TRY := 25.0
|
||||
|
||||
var _failures := 0
|
||||
var _tries := 0
|
||||
|
||||
func _initialize() -> void:
|
||||
_run.call_deferred()
|
||||
|
||||
func _run() -> void:
|
||||
var S: Node = root.get_node("Saves")
|
||||
S.root_dir = "user://test_boundary_worlds"
|
||||
for w in S.list_worlds():
|
||||
S.delete_world(w.id)
|
||||
print("the Valley")
|
||||
await _escape_all(DIRECTIONS, -1.0)
|
||||
print("a beach (testbay)")
|
||||
S.current_id = S.create_world("Bay", 1337, {"worldlet": "testbay"})
|
||||
await _escape_all(BAY_DIRECTIONS, 90.0)
|
||||
for w in S.list_worlds():
|
||||
S.delete_world(w.id)
|
||||
DirAccess.remove_absolute(S.root_dir)
|
||||
print("RESULT: %s (%d/%d directions held)" % ["PASS" if _failures == 0 else "FAIL", _tries - _failures, _tries])
|
||||
quit(1 if _failures > 0 else 0)
|
||||
|
||||
## Walks out in `count` directions: all round, or (beach_deg >= 0) across the
|
||||
## beach's arc and a little past it either side.
|
||||
func _escape_all(count: int, beach_deg: float) -> void:
|
||||
var world: Node3D = load("res://scenes/world.tscn").instantiate()
|
||||
root.add_child(world)
|
||||
_run.call_deferred(world)
|
||||
|
||||
func _run(world: Node3D) -> void:
|
||||
for _i in range(10):
|
||||
await physics_frame
|
||||
var terrain: Node3D = world.get_node("Terrain")
|
||||
var player: CharacterBody3D = world.get_node("Player")
|
||||
var failures := 0
|
||||
var tick := 1.0 / Engine.physics_ticks_per_second
|
||||
for i in range(DIRECTIONS):
|
||||
var ang := TAU * i / DIRECTIONS
|
||||
var pulled := 0
|
||||
for i in range(count):
|
||||
var ang := TAU * i / count
|
||||
if beach_deg >= 0.0:
|
||||
ang = deg_to_rad(beach_deg + lerpf(-65.0, 65.0, float(i) / (count - 1)))
|
||||
var out := Vector3(cos(ang), 0.0, sin(ang))
|
||||
var start: Vector3 = out * (terrain.play_radius - 12.0)
|
||||
start.y = terrain.sample_height(start.x, start.z) + 1.0
|
||||
start.y = maxf(terrain.sample_height(start.x, start.z), terrain.water_level) + 1.0
|
||||
player.global_position = start
|
||||
player.velocity = Vector3.ZERO
|
||||
player.rotation = Vector3(0.0, atan2(-out.x, -out.z), 0.0)
|
||||
Input.action_press("move_forward")
|
||||
var escaped := false
|
||||
var max_d := 0.0
|
||||
var in_current := false
|
||||
var frames := int(SECONDS_PER_TRY / tick)
|
||||
for f in range(frames):
|
||||
if f % 12 == 0:
|
||||
@@ -41,17 +70,28 @@ func _run(world: Node3D) -> void:
|
||||
await physics_frame
|
||||
var p := player.global_position
|
||||
max_d = maxf(max_d, Vector2(p.x, p.z).length())
|
||||
in_current = in_current or terrain.current_at(p.x, p.z) > 0.2
|
||||
if not terrain.inside_boundary(p.x, p.z, -1.5) or p.y < terrain.min_height - 5.0:
|
||||
escaped = true
|
||||
break
|
||||
Input.action_release("move_forward")
|
||||
Input.action_release("jump")
|
||||
var p := player.global_position
|
||||
if not escaped and p.y < terrain.water_level - 0.5:
|
||||
var at_sea: bool = world.water_at(p.x, p.z).get("type", "") == "sea"
|
||||
if not escaped and p.y < terrain.water_level - 0.5 and not at_sea:
|
||||
escaped = true # stuck in a pit below the waterline
|
||||
print("dir %2d (%3d deg): %s max radius %.1f final (%.1f, %.1f, %.1f)" % [
|
||||
i, int(rad_to_deg(ang)), "FAILED" if escaped else "held", max_d, p.x, p.y, p.z])
|
||||
if in_current:
|
||||
pulled += 1
|
||||
print("dir %2d (%3d deg): %s max radius %.1f final (%.1f, %.1f, %.1f)%s" % [
|
||||
i, int(rad_to_deg(ang)), "FAILED" if escaped else "held", max_d, p.x, p.y, p.z,
|
||||
" (the current turned them back)" if in_current else ""])
|
||||
_tries += 1
|
||||
if escaped:
|
||||
failures += 1
|
||||
print("RESULT: %s (%d/%d directions held)" % ["PASS" if failures == 0 else "FAIL", DIRECTIONS - failures, DIRECTIONS])
|
||||
quit(1 if failures > 0 else 0)
|
||||
_failures += 1
|
||||
if beach_deg >= 0.0 and pulled == 0:
|
||||
print("FAILED: nobody swam far enough out to meet the current")
|
||||
_failures += 1
|
||||
_tries += 1
|
||||
world.queue_free()
|
||||
for _i in range(3):
|
||||
await process_frame
|
||||
|
||||
Reference in New Issue
Block a user