funnymemellama/Player.gd
2023-10-01 23:40:46 -04:00

172 lines
4.1 KiB
GDScript

extends CharacterBody3D
# Member variables
const QUAKE = 0.0625
const g = -800 * QUAKE
const MAX_SPEED = 320 * QUAKE
const FRICTION = 4# * QUAKE
const STOP_SPEED = 100 * QUAKE
const ACCEL= 10# * QUAKE
const FORWARD_SPEED = 400 * QUAKE
const SIDE_SPEED = 350 * QUAKE
const UP_SPEED = 270 * QUAKE
# const DEACCEL= 8
# const MAX_SLOPE_ANGLE = 30
@onready
var camera = $CSGMesh3D/Camera3D
var _paused = false
var _noclip = false
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _physics_process(delta):
# Shamelessly stolen code from quake :)
var fmove = 0.0
var smove = 0.0
var upmove = 0.0
if Input.is_action_pressed("move_forward"):
fmove += -FORWARD_SPEED
if Input.is_action_pressed("move_backwards"):
fmove += FORWARD_SPEED
if Input.is_action_pressed("move_left"):
smove += -SIDE_SPEED
if Input.is_action_pressed("move_right"):
smove += SIDE_SPEED
if Input.is_action_pressed("jump"):
upmove += UP_SPEED
if Input.is_action_pressed("run"):
fmove *= 2.0
smove *= 2.0
var wishvel = Vector3()
var cam_xform: Transform3D = camera.get_global_transform()
var cam_basis: Basis = cam_xform.basis
wishvel = cam_basis.z * fmove + cam_basis.x * smove
if _noclip:
wishvel.y += upmove
# else:
# wishvel.y = upmove
var wishdir = wishvel.normalized()
var wishspeed = wishvel.length()
if wishspeed > MAX_SPEED:
wishvel *= MAX_SPEED / wishspeed
wishspeed = MAX_SPEED
if is_on_floor():
velocity.y += upmove
var vel = velocity
if _noclip:
vel = wishvel
elif is_on_floor():
vel = _apply_friction(vel, delta)
vel = _apply_accel(vel, wishdir, wishspeed, delta)
else:
vel = _apply_air_accel(vel, wishvel, wishspeed, delta)
if not _noclip:
vel.y += g * delta
velocity = vel
move_and_slide()
$Ball.global_position = camera.global_position - camera.global_transform.basis.z * 2.0
func _apply_friction(vel: Vector3, delta: float):
var speed = sqrt(vel.x ** 2 + vel.z ** 2)
if(speed == 0.0): return vel
# TODO: edge detect friction?
var friction = FRICTION
var control = 0.0
if speed < STOP_SPEED:
control = STOP_SPEED
else:
control = speed
var newspeed = speed - delta * control * friction
if newspeed < 0.0:
newspeed = 0.0
newspeed /= speed
return vel * newspeed
func _apply_accel(vel: Vector3, wishdir: Vector3, wishspeed: float, delta: float):
var currentspeed = vel.dot(wishdir)
var addspeed = wishspeed - currentspeed
if addspeed <= 0.0:
return vel
var accelspeed = ACCEL * delta * wishspeed
if accelspeed > addspeed:
accelspeed = addspeed
return vel + accelspeed * wishdir
func _apply_air_accel(vel: Vector3, wishvel: Vector3, wishspeed: float, delta: float):
var wishveloc = wishvel.normalized()
var wishspd = wishvel.length()
if wishspd > 30 * QUAKE:
wishspd = 30 * QUAKE
var currentspeed = vel.dot(wishveloc)
var addspeed = wishspd - currentspeed
if addspeed <= 0:
return vel
var accelspeed = ACCEL * wishspeed * delta
if accelspeed > addspeed:
accelspeed = addspeed
return vel + accelspeed * wishveloc
func _input(event):
if event.is_action_pressed("pause"):
_paused = not _paused
if _paused:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
if _paused: return
if event.is_action_pressed('noclip'):
_noclip = not _noclip
if _noclip:
$CollisionShape3D.disabled = true
else:
$CollisionShape3D.disabled = false
# Check for mouse motion input
if event is InputEventMouseMotion:
rotation.y += -event.relative.x * 0.005
camera.rotation.x += -event.relative.y * 0.005
camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-70), deg_to_rad(70))
if event.is_action_pressed("interact"):
var space_state = get_world_3d().direct_space_state
# use global coordinates, not local to node
var query = PhysicsRayQueryParameters3D.create(camera.global_position, $Ball.global_position)
# Don't collide with ourselves
query.exclude = [self]
var result = space_state.intersect_ray(query)
if result.has('collider'):
var other: Node3D = result.collider
if other.has_method('interact'):
other.interact(self)