Last active
January 19, 2022 20:01
-
-
Save Einlander/b3ba88426dbedb23756329c36006ac35 to your computer and use it in GitHub Desktop.
Prototype Godot FPS Controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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