Skip to content

Instantly share code, notes, and snippets.

@untodesu
Created January 29, 2020 16:16
Show Gist options
  • Save untodesu/7eb1e1625e45aadc8cc8b709e3e380aa to your computer and use it in GitHub Desktop.
Save untodesu/7eb1e1625e45aadc8cc8b709e3e380aa to your computer and use it in GitHub Desktop.
extends KinematicBody
# the user command structure
# this contains wish directions for player
var cmd = {
move_forward = 0.0,
move_right = 0.0,
move_up = 0.0, # is this actually needed here? Carmack, why?
};
# Export variables
export var mouse_sensitivity = 0.1;
export var gravity = 800;
export var friction = 6.0;
export var move_speed = 15.0;
export var run_accel = 25.0;
export var run_deaccel = 20.0;
export var air_accel = 2.0;
export var air_deaccel = 2.0;
export var air_control_value = 0.1;
export var side_strafe_accel = 25.0;
export var side_strafe_speed = 1.0;
export var jump_speed = 8.0;
export var move_scale = 1.0;
export var auto_jump = false;
var m_wish_jump = false;
var m_direction = Vector3();
var m_velocity = Vector3();
var m_vecUp = Vector3(0, 1, 0);
var m_camera;
var m_jump_sound;
# Check for jump needance
func queue_jump():
if(Input.is_action_just_pressed("in_jump") && !m_wish_jump):
m_wish_jump = true;
if(Input.is_action_just_released("in_jump")):
m_wish_jump = false;
# Process input (Moving, not jumping)
func process_input():
cmd.move_forward = 0.0;
cmd.move_right = 0.0;
cmd.move_forward += int(Input.is_action_pressed("in_forward"));
cmd.move_forward -= int(Input.is_action_pressed("in_backward"));
cmd.move_right += int(Input.is_action_pressed("in_right"));
cmd.move_right -= int(Input.is_action_pressed("in_left"));
# Calculate total commands scale
func cmd_scale():
var abs_fwd = abs(cmd.move_forward);
var abs_rgt = abs(cmd.move_right);
# Calculate maximum value
var var_max = abs_fwd;
if(abs_rgt > var_max):
var_max = abs_rgt;
if(var_max <= 0):
return 0;
# Final scale
var total = sqrt(cmd.move_forward * cmd.move_forward + cmd.move_right * cmd.move_right);
return (move_speed * var_max / (move_scale * total));
# Apply acceleration
func accelerate(wish_dir : Vector3, wish_speed : float, accel : float, delta : float):
# See if we are changing direction a bit
var current_speed = m_velocity.dot(wish_dir);
# Reduce wishspeed by the amount of veer.
var add_speed = (wish_speed - current_speed);
# If not going to add any speed, done.
if(add_speed <= 0):
return;
# Determine amount of accleration.
var accel_speed = (accel * wish_speed * delta);
# Cap at addspeed
if(accel_speed > add_speed):
accel_speed = add_speed;
# Adjust velocity.
m_velocity += (accel_speed * wish_dir);
# Apply friction to the player
func apply_friction(fct : float, delta : float):
var vec = m_velocity;
var speed = 0.0;
var new_speed = 0.0;
var control = 0.0;
var drop = 0.0;
# We 'braking' the player only on ground!
# so we calculate speed without the Y axis
vec.y = 0.0;
speed = vec.length();
# Calculate the speed drop
if(is_on_floor()):
if(speed < run_deaccel):
control = run_deaccel;
else:
control = speed;
drop = (control * friction * delta * fct);
# Calculate resulting speed factor
new_speed = (speed - drop);
if(new_speed < 0):
new_speed = 0;
if(new_speed > 0):
new_speed /= speed;
# Apply it to velocity
m_velocity.x *= new_speed;
m_velocity.z *= new_speed;
# Process movement on ground
func move_on_ground(delta : float):
var wish_dir = Vector3();
# Apply friction
if(!m_wish_jump):
apply_friction(1.0, delta);
else:
apply_friction(0.0, delta);
# Process cmd input
cmd_scale();
process_input();
# Calculate direction
wish_dir += transform.basis.x * cmd.move_right;
wish_dir -= transform.basis.z * cmd.move_forward;
# set the direction
wish_dir = wish_dir.normalized();
m_direction = wish_dir;
# Accelerate
var wish_speed = wish_dir.length();
wish_speed *= move_speed;
accelerate(wish_dir, wish_speed, run_accel, delta);
# Jump if needed
# Override Y
m_velocity.y = 0.0;
if(m_wish_jump):
m_velocity.y = jump_speed;
m_wish_jump = auto_jump;
m_jump_sound.play();
# Air movement helper
func air_control(wish_dir : Vector3, wish_speed : float, delta : float):
# If our speeds are so small, just ignore em
if(((abs(cmd.move_forward)) < 0.001) || (abs(wish_speed) < 0.001)):
return
# Save and discard the vertical speed
var y_speed = m_velocity.y;
m_velocity.y = 0.0;
# calculate horizontal speed and and prepare velocity vector
var speed = m_velocity.length();
m_velocity = m_velocity.normalized();
var dot_val = m_velocity.dot(wish_dir);
var k = 32.0 * (air_control_value * pow(dot_val, 2) * delta);
if(dot_val > 0):
m_velocity.x = (m_velocity.x * speed) + (wish_dir.x * k);
m_velocity.y = (m_velocity.y * speed) + (wish_dir.y * k);
m_velocity.z = (m_velocity.z * speed) + (wish_dir.z * k);
m_velocity = m_velocity.normalized();
m_direction = m_velocity;
m_velocity.x *= speed;
m_velocity.y = y_speed;
m_velocity.z *= speed;
# Process movement in the air
func move_in_air(delta : float):
var wish_dir = Vector3();
var accel = 0.0;
# Process input
cmd_scale();
process_input();
# Calculate the direction
wish_dir += transform.basis.x * cmd.move_right;
wish_dir -= transform.basis.z * cmd.move_forward;
# Calculate the speed
var wish_speed = wish_dir.length();
wish_speed *= move_speed;
wish_dir = wish_dir.normalized();
m_direction = wish_dir;
# air control (acceleration and stuff)
var wish_speed2 = wish_speed;
if(m_velocity.dot(wish_dir) < 0):
accel = air_deaccel;
else:
accel = air_accel;
# If strafing only, use different values
if((cmd.move_forward == 0) && (cmd.move_right != 0)):
if(wish_speed > side_strafe_speed):
wish_speed = side_strafe_speed;
accel = side_strafe_accel;
# Apply the air accel
accelerate(wish_dir, wish_speed, accel, delta);
if(air_control_value > 0):
air_control(wish_dir, wish_speed2, delta);
m_velocity.y -= (gravity * delta * 0.03125); # make it quake-like
# Setup
func _ready():
m_camera = get_node("Camera");
m_jump_sound = get_node("JumpSound");
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED);
pass
# Loop
func _physics_process(delta : float):
queue_jump();
if(is_on_floor()):
move_on_ground(delta);
else:
move_in_air(delta);
m_velocity = move_and_slide(m_velocity, m_vecUp);
# Process mouse input
func _input(ev):
if(ev is InputEventMouseMotion):
rotate_y(-deg2rad(ev.relative.x) * mouse_sensitivity);
m_camera.rotate_x(-deg2rad(ev.relative.y) * mouse_sensitivity);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment