update
This commit is contained in:
@@ -9,8 +9,9 @@ const SPEED_TRAUM := 8.0
|
||||
const SPEED_GEIST := 11.0
|
||||
const GRAVITY := 24.0
|
||||
const JUMP := 9.0
|
||||
const FOLGE_ABSTAND := 2.2
|
||||
const FOLGE_SPIEL := 1.5
|
||||
const FOLGE_ABSTAND := 2.5 # so weit bleibt der Geist auf der Spur zurück
|
||||
const LEINE := 14.0 # weiter weg reißt die Leine: er wird nachgezogen
|
||||
const SCHWEBE := 0.25 # eine Handbreit über dem Boden
|
||||
const PITCH := -0.96 # 55° von oben, fest wie in Diablo
|
||||
const CAM_YAW := PI * 0.25 # Blick diagonal über den Bezirk
|
||||
const ZOOM := [26.0, 40.0] # zwei Stufen, Mausrad
|
||||
@@ -27,7 +28,6 @@ var arm: Node3D
|
||||
var cam: Camera3D
|
||||
var _dreh_rest := 0.0 # noch zu drehender Winkel (Q)
|
||||
var _zoom_stufe := 0
|
||||
var _schwebe_ziel := -1.0 # Etage, zu der der Geist gerade gleitet
|
||||
var body: Node3D
|
||||
var _schleier: MeshInstance3D
|
||||
var _kern: MeshInstance3D
|
||||
@@ -51,10 +51,10 @@ const FUNKEN_MAX := 6
|
||||
func _ready() -> void:
|
||||
var cs := CollisionShape3D.new()
|
||||
var shape := CapsuleShape3D.new()
|
||||
shape.radius = 0.45
|
||||
shape.height = 1.9
|
||||
shape.radius = 0.4
|
||||
shape.height = 1.6
|
||||
cs.shape = shape
|
||||
cs.position.y = 0.95
|
||||
cs.position.y = 0.8
|
||||
add_child(cs)
|
||||
|
||||
body = Node3D.new()
|
||||
@@ -107,18 +107,15 @@ func _ready() -> void:
|
||||
func set_mode(m: int) -> void:
|
||||
mode = m
|
||||
folgt = null
|
||||
collision_layer = 1
|
||||
collision_mask = 1
|
||||
if m == Mode.GEIST:
|
||||
collision_layer = 0
|
||||
collision_mask = 0
|
||||
body.scale = Vector3.ONE * 0.6
|
||||
_schleier_mat.albedo_color.a = 0.3
|
||||
else:
|
||||
collision_layer = 1
|
||||
collision_mask = 1
|
||||
body.scale = Vector3.ONE * 0.8
|
||||
_schleier_mat.albedo_color.a = 0.55
|
||||
velocity = Vector3.ZERO
|
||||
_schwebe_ziel = -1.0
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
@@ -157,56 +154,16 @@ func _physics_process(delta: float) -> void:
|
||||
elif dir.length() > 0.01:
|
||||
folgt = null # eigene Bewegung löst die Verfolgung
|
||||
else:
|
||||
var rechts := Basis(Vector3.UP, yaw) * Vector3(1, 0, 0)
|
||||
var schulter := folgt.global_position + Vector3(0, 1.4, 0) \
|
||||
+ rechts * FOLGE_ABSTAND - blickrichtung() * 0.8
|
||||
global_position = global_position.lerp(schulter, 1.0 - pow(0.004, delta))
|
||||
# weich nachziehen, aber an der Leine: sonst reißt der Faden beim Gehen
|
||||
var ab := global_position - schulter
|
||||
if ab.length() > FOLGE_SPIEL:
|
||||
global_position = schulter + ab.normalized() * FOLGE_SPIEL
|
||||
velocity = Vector3.ZERO
|
||||
body.rotation.y = lerp_angle(body.rotation.y, yaw, 1.0 - pow(0.001, delta))
|
||||
_an_der_leine(delta)
|
||||
return
|
||||
|
||||
if mode == Mode.GEIST:
|
||||
var v := dir * SPEED_GEIST
|
||||
velocity.x = lerpf(velocity.x, v.x, 1.0 - pow(0.001, delta))
|
||||
velocity.z = lerpf(velocity.z, v.z, 1.0 - pow(0.001, delta))
|
||||
# Steigen und Sinken wechseln die Etage: der Geist gleitet ein Stockwerk
|
||||
if look_enabled:
|
||||
var von: float = _schwebe_ziel if _schwebe_ziel >= 0.0 else global_position.y
|
||||
if Input.is_action_just_pressed("steigen"):
|
||||
_schwebe_ziel = clampf(von + Orte.ETAGE, 0.4, 45.0)
|
||||
if Input.is_action_just_pressed("sinken"):
|
||||
_schwebe_ziel = clampf(von - Orte.ETAGE, 0.4, 45.0)
|
||||
if _schwebe_ziel >= 0.0:
|
||||
var dy := _schwebe_ziel - global_position.y
|
||||
velocity.y = clampf(dy * 6.0, -SPEED_GEIST, SPEED_GEIST)
|
||||
if absf(dy) < 0.05:
|
||||
global_position.y = _schwebe_ziel
|
||||
velocity.y = 0.0
|
||||
_schwebe_ziel = -1.0
|
||||
else:
|
||||
velocity.y = 0.0
|
||||
move_and_slide()
|
||||
if global_position.y < 0.4:
|
||||
global_position.y = 0.4
|
||||
if global_position.y > 45.0:
|
||||
global_position.y = 45.0
|
||||
else:
|
||||
velocity.x = lerpf(velocity.x, dir.x * SPEED_TRAUM, 1.0 - pow(0.0005, delta))
|
||||
velocity.z = lerpf(velocity.z, dir.z * SPEED_TRAUM, 1.0 - pow(0.0005, delta))
|
||||
if is_on_floor():
|
||||
if look_enabled and Input.is_action_pressed("steigen"):
|
||||
velocity.y = JUMP
|
||||
else:
|
||||
velocity.y = -1.0
|
||||
else:
|
||||
velocity.y -= GRAVITY * delta
|
||||
move_and_slide()
|
||||
if global_position.y < -400.0:
|
||||
global_position.y = 2.0
|
||||
var tempo := SPEED_GEIST if mode == Mode.GEIST else SPEED_TRAUM
|
||||
velocity.x = lerpf(velocity.x, dir.x * tempo, 1.0 - pow(0.0005, delta))
|
||||
velocity.z = lerpf(velocity.z, dir.z * tempo, 1.0 - pow(0.0005, delta))
|
||||
_fallen(delta)
|
||||
move_and_slide()
|
||||
if global_position.y < -400.0:
|
||||
global_position.y = 2.0
|
||||
|
||||
if dir.length() > 0.01:
|
||||
var ziel := atan2(-dir.x, -dir.z)
|
||||
@@ -217,6 +174,40 @@ func blickrichtung() -> Vector3:
|
||||
return -Vector3(sin(yaw), 0, cos(yaw))
|
||||
|
||||
|
||||
## Schwerkraft in beiden Welten. Springen kann nur der Läufer im Traum.
|
||||
func _fallen(delta: float) -> void:
|
||||
if is_on_floor():
|
||||
if mode == Mode.TRAUM and look_enabled and Input.is_action_pressed("steigen"):
|
||||
velocity.y = JUMP
|
||||
else:
|
||||
velocity.y = -1.0
|
||||
else:
|
||||
velocity.y -= GRAVITY * delta
|
||||
|
||||
|
||||
## Folgen heißt: seiner Spur nachgehen, durch dieselben Türen und Treppen.
|
||||
## Er läuft so schnell wie nötig, um dranzubleiben -- auch bei hohem Tempo.
|
||||
func _an_der_leine(delta: float) -> void:
|
||||
var mensch := folgt as Bewohner
|
||||
var ziel: Vector3 = mensch.spur_punkt(FOLGE_ABSTAND)
|
||||
var d := ziel - global_position
|
||||
d.y = 0.0
|
||||
var tempo := maxf(SPEED_GEIST, Bewohner.GEHTEMPO * Game.zeit_faktor() * 1.4)
|
||||
if d.length() > 0.3:
|
||||
var v := d.normalized() * minf(tempo, d.length() / delta)
|
||||
velocity.x = v.x
|
||||
velocity.z = v.z
|
||||
body.rotation.y = lerp_angle(body.rotation.y, atan2(-d.x, -d.z), 1.0 - pow(0.001, delta))
|
||||
else:
|
||||
velocity.x = 0.0
|
||||
velocity.z = 0.0
|
||||
_fallen(delta)
|
||||
move_and_slide()
|
||||
if global_position.distance_to(mensch.global_position) > LEINE:
|
||||
global_position = ziel # hängen geblieben: die Leine zieht ihn nach
|
||||
velocity = Vector3.ZERO
|
||||
|
||||
|
||||
## Schweben, Funken, Schweif und Modusfarbe -- der Zustand ist am Geist ablesbar.
|
||||
func _beleben(delta: float) -> void:
|
||||
var t := Time.get_ticks_msec() * 0.001
|
||||
@@ -233,7 +224,7 @@ func _beleben(delta: float) -> void:
|
||||
_kopf_mat.albedo_color = _farbe.lightened(0.4)
|
||||
_kopf_mat.emission = _farbe.lightened(0.4)
|
||||
|
||||
body.position.y = sin(t * 1.6) * 0.08
|
||||
body.position.y = (SCHWEBE if mode == Mode.GEIST else 0.0) + sin(t * 1.6) * 0.08
|
||||
_kern.scale = Vector3.ONE * (1.0 + sin(t * 3.1) * 0.12)
|
||||
var tempo_flach := Vector2(velocity.x, velocity.z).length()
|
||||
var neigung := -0.16 * clampf(tempo_flach / SPEED_TRAUM, 0.0, 1.0)
|
||||
|
||||
Reference in New Issue
Block a user