151 lines
4.2 KiB
GDScript
151 lines
4.2 KiB
GDScript
extends CharacterBody3D
|
|
class_name Player
|
|
## Ein Wesen aus der Traumwelt. In der Traumwelt läuft es, auf der Erde schwebt
|
|
## es als unsichtbarer Geist durch Wände.
|
|
|
|
enum Mode { TRAUM, GEIST }
|
|
|
|
const SPEED_TRAUM := 8.0
|
|
const SPEED_GEIST := 11.0
|
|
const GRAVITY := 24.0
|
|
const JUMP := 9.0
|
|
const MAUS := 0.0026
|
|
|
|
var mode: int = Mode.TRAUM
|
|
var yaw := 0.0
|
|
var pitch := -0.25
|
|
var look_enabled := true
|
|
|
|
var pivot: Node3D
|
|
var arm: SpringArm3D
|
|
var cam: Camera3D
|
|
var body: Node3D
|
|
var _kern: MeshInstance3D
|
|
var _ringe: Array = []
|
|
|
|
|
|
func _ready() -> void:
|
|
var cs := CollisionShape3D.new()
|
|
var shape := CapsuleShape3D.new()
|
|
shape.radius = 0.45
|
|
shape.height = 1.9
|
|
cs.shape = shape
|
|
cs.position.y = 0.95
|
|
add_child(cs)
|
|
|
|
body = Node3D.new()
|
|
add_child(body)
|
|
_kern = Prims.capsule(body, Vector3(0, 1.0, 0), 0.42, 1.6, Color(0.55, 0.85, 1.0))
|
|
_kern.material_override = Prims.mat(Color(0.55, 0.85, 1.0), 0.9)
|
|
var kopf := Prims.sphere(body, Vector3(0, 2.0, 0), 0.28, Color(0.80, 0.92, 1.0), 0.6)
|
|
kopf.name = "Kopf"
|
|
for i in range(2):
|
|
var r := Prims.cyl(body, Vector3(0, 0.5 + i * 0.9, 0), 0.75 + i * 0.15, 0.06,
|
|
Color(0.6, 0.9, 1.0), false, 1.6)
|
|
r.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
|
|
_ringe.append(r)
|
|
# kleiner Blick nach vorn, damit man die Laufrichtung sieht
|
|
Prims.box(body, Vector3(0, 1.55, -0.36), Vector3(0.5, 0.12, 0.12), Color(1, 1, 1), false, 2.0)
|
|
|
|
pivot = Node3D.new()
|
|
pivot.position.y = 1.5
|
|
add_child(pivot)
|
|
arm = SpringArm3D.new()
|
|
arm.position.x = 0.75
|
|
arm.spring_length = 6.5
|
|
arm.margin = 0.3
|
|
pivot.add_child(arm)
|
|
cam = Camera3D.new()
|
|
cam.fov = 74.0
|
|
arm.add_child(cam)
|
|
set_mode(Mode.TRAUM)
|
|
|
|
|
|
func set_mode(m: int) -> void:
|
|
mode = m
|
|
if m == Mode.GEIST:
|
|
collision_layer = 0
|
|
collision_mask = 0
|
|
arm.collision_mask = 0
|
|
arm.spring_length = 5.0
|
|
pivot.position.y = 2.1
|
|
body.scale = Vector3.ONE * 0.72
|
|
_kern.material_override = Prims.mat(Color(0.65, 0.9, 1.0, 0.26), 0.5)
|
|
for r in _ringe:
|
|
r.material_override = Prims.mat(Color(0.7, 0.95, 1.0, 0.20), 0.8)
|
|
r.scale = Vector3(0.55, 1.0, 0.55)
|
|
else:
|
|
collision_layer = 1
|
|
collision_mask = 1
|
|
arm.collision_mask = 1
|
|
arm.spring_length = 6.5
|
|
pivot.position.y = 1.5
|
|
body.scale = Vector3.ONE
|
|
_kern.material_override = Prims.mat(Color(0.55, 0.85, 1.0), 0.9)
|
|
for r in _ringe:
|
|
r.material_override = Prims.mat(Color(0.6, 0.9, 1.0), 1.6)
|
|
r.scale = Vector3.ONE
|
|
velocity = Vector3.ZERO
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if not look_enabled:
|
|
return
|
|
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
|
yaw -= event.relative.x * MAUS
|
|
pitch = clampf(pitch - event.relative.y * MAUS, -1.3, 0.6)
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
pivot.rotation.y = yaw
|
|
arm.rotation.x = pitch
|
|
|
|
for i in range(_ringe.size()):
|
|
var r: MeshInstance3D = _ringe[i]
|
|
r.rotation.y += delta * (0.8 + 0.5 * i)
|
|
r.position.y = 0.5 + i * 0.9 + sin(Time.get_ticks_msec() * 0.001 * (1.2 + i * 0.4)) * 0.12
|
|
|
|
var input := Vector2.ZERO
|
|
if look_enabled:
|
|
input.x = Input.get_axis("links", "rechts")
|
|
input.y = Input.get_axis("vor", "zurueck")
|
|
var dir := Vector3.ZERO
|
|
if input.length() > 0.01:
|
|
var basis_yaw := Basis(Vector3.UP, yaw)
|
|
dir = (basis_yaw * Vector3(input.x, 0, input.y)).normalized()
|
|
|
|
if mode == Mode.GEIST:
|
|
var v := dir * SPEED_GEIST
|
|
if look_enabled:
|
|
if Input.is_action_pressed("steigen"):
|
|
v.y += SPEED_GEIST * 0.75
|
|
if Input.is_action_pressed("sinken"):
|
|
v.y -= SPEED_GEIST * 0.75
|
|
velocity = velocity.lerp(v, 1.0 - pow(0.001, delta))
|
|
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
|
|
|
|
if dir.length() > 0.01:
|
|
var ziel := atan2(-dir.x, -dir.z)
|
|
body.rotation.y = lerp_angle(body.rotation.y, ziel, 1.0 - pow(0.0005, delta))
|
|
|
|
|
|
func blickrichtung() -> Vector3:
|
|
return -Vector3(sin(yaw), 0, cos(yaw))
|