Skip to content

Instantly share code, notes, and snippets.

@Einlander
Last active January 19, 2022 20:01
Show Gist options
  • Save Einlander/b3ba88426dbedb23756329c36006ac35 to your computer and use it in GitHub Desktop.
Save Einlander/b3ba88426dbedb23756329c36006ac35 to your computer and use it in GitHub Desktop.
Prototype Godot FPS Controller
extends KinematicBody
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
export(float) var walk_speed = 4
export(float) var run_speed = 6
export(float) var acceleration = 5
export(float) var deceleration = 8
export(float) var jump_force = 4
export(float) var use_distance = 4
export(float) var max_slope = 45
export(float) var view_sensitivity = 0.5
export(float,.1,1) var camera_smoothing = .3
export(float) var player_height = 1.82
export(float) var eye_height = 1.8
export(float) var player_radius = .5
export(float) var step_height = .7
var player_shape = CollisionShape.new()
var player_ray = RayCast.new()
var player_camera = Camera.new()
const GRAVITY = -9.8
var velocity = Vector3()
var camera_yaw = 0
var camera_pitch = 0
var camera_height = 0
var is_moving = false
func _ready():
initialize_controller()
pass
#func _process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
# pass
func initialize_controller():
player_ray.translation.y = step_height
player_ray.cast_to = Vector3(0,-step_height,0)
player_ray.enabled = true
self.add_child(player_ray)
var temp_shape = CapsuleShape.new()
temp_shape.height = ((player_height-step_height) - (player_radius*2))
temp_shape.radius = player_radius
player_shape.shape = temp_shape
player_shape.rotation.x = PI/2
#player_shape.translation.y = (player_height/2)+ step_height
player_shape.translation.y = ((player_height+step_height)/2)
self.add_child(player_shape)
player_camera.translation.y = eye_height
self.add_child(player_camera)
camera_height = player_camera.global_transform.origin.y
get_viewport().warp_mouse(Vector2(get_viewport().size.x/2,get_viewport().size.y/2))
pass
func _enter_tree():
Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED and Input.MOUSE_MODE_HIDDEN)
pass
func _exit_tree():
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
pass
func on_ground():
return player_ray.is_colliding()
pass
func get_ground_angle():
var n = player_ray.get_collision_normal()
return acos(n.dot(Vector3(0,1,0)))
pass
func is_stepping():
pass
func _input(event):
if event is InputEventKey:
if event.scancode == KEY_ESCAPE:
get_tree().quit()
pass
pass
func get_input():
pass
func mouselook():
var new_mouse = get_viewport().get_mouse_position() - Vector2(get_viewport().size.x/2,get_viewport().size.y/2)
if abs(new_mouse.x) < 2:
new_mouse.x = 0
pass
if abs(new_mouse.y) < 2:
new_mouse.y = 0
pass
camera_yaw = fmod(camera_yaw - new_mouse.x * view_sensitivity,360)
camera_pitch = max(min(camera_pitch - new_mouse.y * view_sensitivity,89),-89)
player_camera.rotation.y = deg2rad(camera_yaw)
player_camera.rotation.x = deg2rad(camera_pitch)
get_viewport().warp_mouse(Vector2(get_viewport().size.x/2,get_viewport().size.y/2))
pass
func get_direction():
var direction = Vector3()
if Input.is_action_pressed("player_backward"):
direction.z = direction.z + 1
if Input.is_action_pressed("player_forward"):
direction.z = direction.z - 1
if Input.is_action_pressed("player_left"):
direction.x = direction.x - 1
if Input.is_action_pressed("player_right"):
direction.x = direction.x + 1
direction = direction.normalized()
is_moving=(direction.length()>0)
return direction
pass
func get_direction_rotated():
return get_direction().rotated(Vector3(0,1,0),deg2rad(camera_yaw))
pass
func move_player(velocity):
velocity = move_and_slide(velocity,Vector3(0,1,0))
pass
func acceleration():
var accel
if (is_moving):
accel = acceleration
else:
accel = deceleration
return accel
func _physics_process(delta):
mouselook()
var direction = get_direction_rotated()
var target = Vector3()
if Input.is_action_pressed("player_run"):
target = direction * run_speed
else:
target = direction * walk_speed
if on_ground() == true:
#make sure the ground isint too sloped
if rad2deg(get_ground_angle()) <= max_slope:
#Jumping
#print(rad2deg(get_ground_angle()) <= max_slope)
if( Input.is_action_pressed("player_jump")):
print("jump"+var2str(OS.get_unix_time()))
velocity.y = jump_force
else:
print("clamping"+var2str(OS.get_unix_time()))
var n = player_ray.get_collision_normal()
velocity.y += delta * GRAVITY * -GRAVITY
velocity = velocity - velocity.dot(n)*n
target = -direction
#needs a special check for when the feet are not colliding but the shape bottom is
if player_ray.is_colliding():
self.translation = player_ray.get_collision_point()
else:
velocity.y += delta * GRAVITY
#camera smooting. Needs to be done in global space
camera_height = lerp(camera_height, self.global_transform.origin.y + eye_height,camera_smoothing)
#$"../Label".text =var2str(camera_height)
player_camera.global_transform.origin.y = camera_height
var hvel = velocity
hvel.y = 0
hvel = hvel.linear_interpolate(target,acceleration()*delta)
velocity.x = hvel.x
velocity.z = hvel.z
velocity = move_player(velocity)
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment