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:
Paul Bailey
2026-11-06 16:48:20 +00:00
parent 68e6d814d9
commit 9b88a10609
9 changed files with 400 additions and 43 deletions

View File

@@ -811,7 +811,8 @@ func _respawn() -> void:
player.rotation = Vector3(0.0, _spawn_yaw, 0.0)
player.get_node("Camera3D").rotation.x = 0.0
func _physics_process(_delta: float) -> void:
func _physics_process(delta: float) -> void:
_current(delta)
var p := player.global_position
var half: float = terrain.size * 0.5
if p.y < terrain.min_height - 30.0 or absf(p.x) > half or absf(p.z) > half \
@@ -819,6 +820,25 @@ func _physics_process(_delta: float) -> void:
push_warning("[world] player left the map at %s; respawning" % p)
_respawn()
## Off a beach (W2), a current carries anyone swimming too far out back
## towards the shore: the sea's version of the invisible wall. It's faster
## than you can swim, so you can't push through it, and it says so once.
const CURRENT_SPEED := 4.5
var _in_current := false
func _current(delta: float) -> void:
var p := player.global_position
var c: float = terrain.current_at(p.x, p.z) if p.y < terrain.sea_level else 0.0
if c <= 0.0:
_in_current = false
return
var back := -Vector3(p.x, 0.0, p.z).normalized()
player.global_position += back * CURRENT_SPEED * c * delta
if not _in_current and c > 0.2:
_in_current = true
if hud != null:
hud.toast("A strong current pulls you back towards the shore")
# --- building ---------------------------------------------------------------
## Whether a piece can go at `xf`: inside the valley, on dry fairly flat
@@ -887,11 +907,14 @@ func _update_grass_cuts() -> void:
## fishing (and later swimming, boats) work on any world that answers it.
func water_at(x: float, z: float) -> Dictionary:
var ground: float = terrain.sample_height(x, z)
var beach: bool = terrain.beach_weight(x, z) > 0.5
if terrain.inside_boundary(x, z, -2.0) and ground < terrain.water_level:
if beach and not _in_lake(x, z):
return {"type": "sea", "surface": terrain.sea_level, "depth": terrain.sea_level - ground}
if hazards != null and hazards.iced(x, z):
return {} # (frozen over in a hard winter: cast further out)
return {"type": "lake", "surface": terrain.water_level, "depth": terrain.water_level - ground}
if terrain.sea_weight(x, z) > 0.5 and ground < terrain.sea_level:
if (beach or terrain.sea_weight(x, z) > 0.5) and ground < terrain.sea_level:
return {"type": "sea", "surface": terrain.sea_level, "depth": terrain.sea_level - ground}
return {}
@@ -916,12 +939,22 @@ func water_bodies() -> Array:
match String(b.type):
"lake":
out.append({"type": "lake", "surface": terrain.water_level,
"center": terrain.lake_center, "radius": terrain.lake_radius})
"center": b._c, "radius": b._r})
"sea_cliff":
out.append({"type": "sea", "surface": terrain.sea_level,
"center": terrain.coast_point(terrain.sea_angle_deg, 20.0), "radius": 0.0})
"beach":
out.append({"type": "sea", "surface": terrain.sea_level,
"center": terrain.shore_point(12.0), "radius": 0.0})
return out
## Whether (x, z) is in one of the lakes or ponds (not the sea off a beach).
func _in_lake(x: float, z: float) -> bool:
for l in terrain.lakes:
if Vector2(x - l.center.x, z - l.center.y).length() < float(l.radius) * 1.3:
return true
return false
## Its climate: {"snowline": m, ...} (more as worldlets differ).
func climate() -> Dictionary:
var c: Dictionary = terrain.worldlet.get("climate", {}).duplicate()