Created
November 20, 2023 18:27
-
-
Save ByteAtATime/4de202127e02687c2e8c65604d0f34b9 to your computer and use it in GitHub Desktop.
godot-rust Simple Player Controller
This file contains 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
#[derive(GodotClass)] | |
#[class(base = CharacterBody3D)] | |
struct Player { | |
#[export] | |
base_speed: f32, | |
#[export] | |
sprint_speed_multiplier: f32, | |
#[export] | |
air_speed_multiplier: f32, | |
#[export] | |
jump_velocity: f32, | |
#[export] | |
sensitivity: f32, | |
#[export] | |
accel: f32, | |
#[export] | |
default_fov: f32, | |
#[export] | |
sprint_fov: f32, | |
speed: f32, | |
sprinting: bool, | |
camera: Option<Gd<Camera3D>>, | |
#[base] | |
body: Base<CharacterBody3D>, | |
} | |
#[godot_api] | |
impl Player {} | |
#[godot_api] | |
impl ICharacterBody3D for Player { | |
fn init(body: Base<CharacterBody3D>) -> Self { | |
let base_speed = 15.0; | |
Self { | |
base_speed, | |
sprint_speed_multiplier: 1.5, | |
air_speed_multiplier: 0.5, | |
jump_velocity: 20.0, | |
sensitivity: 0.3, | |
accel: 15.0, | |
default_fov: 75.0, | |
sprint_fov: 90.0, | |
speed: base_speed, | |
sprinting: false, | |
camera: None, | |
body, | |
} | |
} | |
fn process(&mut self, delta: f64) { | |
let delta = delta as f32; | |
let fov = self.camera.as_ref().unwrap().get_fov(); | |
if Input::singleton().is_action_pressed("move_sprint".into()) { | |
self.sprinting = true; | |
self.camera.as_mut().unwrap().set_fov(fov.lerp(self.sprint_fov, 10.0 * delta)); | |
} else { | |
self.sprinting = false; | |
self.camera.as_mut().unwrap().set_fov(fov.lerp(self.default_fov, 10.0 * delta)); | |
} | |
} | |
fn physics_process(&mut self, delta: f64) { | |
if self.body.is_on_floor() { | |
self.speed = self.base_speed * if self.sprinting { self.sprint_speed_multiplier } else { 1.0 }; | |
} else { | |
self.speed = self.base_speed * self.air_speed_multiplier * if self.sprinting { self.sprint_speed_multiplier } else { 1.0 }; | |
} | |
let delta = delta as f32; | |
let gravity = ProjectSettings::singleton().get_setting("physics/3d/default_gravity".into()).to::<f32>(); | |
let mut velocity = self.body.get_velocity(); | |
if !self.body.is_on_floor() { | |
velocity.y -= gravity * delta; | |
} | |
if Input::singleton().is_action_pressed("move_jump".into()) && self.body.is_on_floor() { | |
velocity.y += self.jump_velocity; | |
} | |
let input_dir = Input::singleton().get_vector("move_left".into(), "move_right".into(), "move_forward".into(), "move_backward".into()); | |
let direction = input_dir.normalized().rotated(-self.body.get_rotation().y); | |
let direction = Vector3::new(direction.x, 0.0, direction.y); | |
velocity.x = velocity.x.lerp(direction.x * self.speed, self.accel * delta); | |
velocity.z = velocity.z.lerp(direction.z * self.speed, self.accel * delta); | |
self.body.set_velocity(velocity); | |
self.body.move_and_slide(); | |
} | |
fn ready(&mut self) { | |
Input::singleton().set_mouse_mode(MouseMode::MOUSE_MODE_CAPTURED); | |
self.camera = Some(Camera3D::new_alloc()); | |
self.body.add_child(self.camera.as_mut().unwrap().clone().upcast()); | |
} | |
fn input(&mut self, event: Gd<InputEvent>) { | |
if !event.is_class("InputEventMouseMotion".into()) { return; } | |
let event = event.cast::<InputEventMouseMotion>(); | |
let cur_rotation = self.body.get_rotation_degrees(); | |
self.body.set_rotation_degrees(Vector3::new( | |
clamp((cur_rotation.x - event.get_relative().y * self.sensitivity).to_variant(), (-85.0).to_variant(), 85.0.to_variant()).to(), | |
cur_rotation.y - event.get_relative().x * self.sensitivity, | |
0.0, | |
)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment