diff options
Diffstat (limited to '')
| -rw-r--r-- | rust/src/basic_die.rs | 331 | ||||
| -rw-r--r-- | rust/src/game.rs | 4 | ||||
| -rw-r--r-- | rust/src/lib.rs | 2 | 
3 files changed, 334 insertions, 3 deletions
diff --git a/rust/src/basic_die.rs b/rust/src/basic_die.rs new file mode 100644 index 0000000..9dab3ce --- /dev/null +++ b/rust/src/basic_die.rs @@ -0,0 +1,331 @@ +use std::borrow::Borrow; +use gdnative::api::*; +use gdnative::prelude::*; + +/// the input state for the player +enum InputState { +    Default, +    Shooting, +    Moving +} + +/// the basic die used by the player +#[derive(NativeClass)] +#[inherit(RigidBody)] +#[register_with(Self::register_builder)] +pub struct BasicDie { +    #[property(path="camera/camera_clamp")] +    camera_clamp: Vector2, +    #[property(path="shooting/max_force")] +    max_force: f32, +    #[property(path="shooting/up_angle")] +    up_angle: f32, +    #[property(path="shooting/stopping_velocity")] +    stopping_velocity: f32, +    #[property(path="input/camera_mouse_sensitivity")] +    mouse_sensitivity: Vector2, +    #[property(path="input/shoot_sensitivity")] +    shoot_sensitivity: f32, + +    input_state: InputState, +    current_force: f32, + +    action_shooting: String, + +    node_camera_arm_horizontal: Option<Ref<Spatial>>, +    node_camera_arm_vertical: Option<Ref<Spatial>>, +    node_camera: Option<Ref<Spatial>>, +} + +#[methods] +impl BasicDie { +    // Register the builder for methods, properties and/or signals. +    fn register_builder(_builder: &ClassBuilder<Self>) { +        godot_print!("BasicDie builder is registered!"); +    } + +    fn new(_owner: &RigidBody) -> Self { +        BasicDie { +            camera_clamp: Vector2 { x: 0.0, y: 0.0 }, +            max_force: 0.0, +            up_angle: 5.0, +            stopping_velocity: 0.0, +            mouse_sensitivity: Vector2 { x: 1.0, y: 1.0 }, +            shoot_sensitivity: 1.0, + +            input_state: InputState::Default, +            current_force: 0.0, + +            action_shooting: String::from("mouse_btn_left"), + +            node_camera_arm_horizontal: None, +            node_camera_arm_vertical: None, +            node_camera: None, +        } +    } + +    #[export] +    unsafe fn _ready(&mut self, owner: &RigidBody) { +        owner.set_physics_process(true); + +        // look for the vertical camera arm +        match self.node_camera_arm_horizontal { +            Some(arm) => { +                let save_arm = arm.assume_safe(); +                match save_arm.get_node(NodePath::from_str("CameraArmVertical")) { +                    Some(node) => { +                        let save_node = node.assume_safe(); +                        match save_node.cast::<Spatial>() { +                            Some(casted) => { +                                let save_casted = casted.claim();  +                                self.node_camera_arm_vertical = Some(save_casted)}, +                            _ => godot_warn!("Camera Arm was not of type 'Spatial'"), +                        } +                    }, +                    _ => godot_warn!("No vertical arm found.") +                } +            }, +            _ => godot_warn!("No horizontal arm to look for the vertical arm") +        } + +        // look for the camera +        match self.node_camera_arm_vertical { +            Some(arm) => { +                let save_arm = arm.assume_safe(); +                match save_arm.get_node(NodePath::from_str("Camera")) { +                    Some(node) => { +                        let save_node = node.assume_safe(); +                        match save_node.cast::<Spatial>() { +                            Some(casted) => { +                                let save_casted = casted.claim();  +                                self.node_camera = Some(save_casted)}, +                            _ => godot_warn!("Camera was not of type 'Spatial'"), +                        } +                    }, +                    _ => godot_warn!("No camera found.") +                } +            }, +            _ => godot_warn!("No vertical arm to look for the camera") +        } +    } + +    #[export] +    unsafe fn _physics_process(&mut self, owner: &RigidBody, _delta: f64) { + +        // detect if the die stops moving +        if matches!(self.input_state, InputState::Moving) { +            // get the current velocity +            let current_vel = owner.linear_velocity().length(); + +            godot_print!("current velocity: {}", current_vel); + +            // check if the velocity is less than the threshold and change input state in that case +            if current_vel <= self.stopping_velocity { +                self.input_state = InputState::Default; +            } +        }; +    } + +    #[export] +    unsafe fn _input(&mut self, owner: &RigidBody, event: Ref<InputEvent>) { + +        self.general_input(event.borrow()); + +        match self.input_state { +            InputState::Default => self.default_input(event), +            InputState::Shooting => self.shooting_input(owner, event), +            InputState::Moving => self.moving_input(event), +        } + +        // look for the horizontal camera arm +        match owner.get_node(NodePath::from_str("CameraArmHorizontal")) { +            Some(node) => { +                let save_node = node.assume_safe(); +                match save_node.cast::<Spatial>() { +                    Some(casted) => { +                        let save_casted = casted.claim();  +                        self.node_camera_arm_horizontal = Some(save_casted)}, +                    _ => godot_warn!("Camera Arm was not of type 'Spatial'"), +                } +            }, +            _ => godot_warn!("No horizontal arm found") +        } + +        // look for the vertical camera arm +        match self.node_camera_arm_horizontal { +            Some(arm) => { +                let save_arm = arm.assume_safe(); +                match save_arm.get_node(NodePath::from_str("CameraArmVertical")) { +                    Some(node) => { +                        let save_node = node.assume_safe(); +                        match save_node.cast::<Spatial>() { +                            Some(casted) => { +                                let save_casted = casted.claim();  +                                self.node_camera_arm_vertical = Some(save_casted)}, +                            _ => godot_warn!("Camera Arm was not of type 'Spatial'"), +                        } +                    }, +                    _ => godot_warn!("No vertical arm found.") +                } +            }, +            _ => godot_warn!("No horizontal arm to look for the vertical arm") +        } + +        // look for the camera +        match self.node_camera_arm_vertical { +            Some(arm) => { +                let save_arm = arm.assume_safe(); +                match save_arm.get_node(NodePath::from_str("Camera")) { +                    Some(node) => { +                        let save_node = node.assume_safe(); +                        match save_node.cast::<Spatial>() { +                            Some(casted) => { +                                let save_casted = casted.claim();  +                                self.node_camera = Some(save_casted)}, +                            _ => godot_warn!("Camera was not of type 'Spatial'"), +                        } +                    }, +                    _ => godot_warn!("No camera found.") +                } +            }, +            _ => godot_warn!("No vertical arm to look for the camera") +        } +    } + +    /// this input method will always be called, regardless of the input state +    unsafe fn general_input(&mut self, event: &Ref<InputEvent>) { +        let save_event = event.assume_safe(); + +        // rotate camera horizontally +        let mouse_event = save_event.cast::<InputEventMouseMotion>(); // get the input as mouse input +        match mouse_event { +            Some(motion_event) => { +                let x_mov = motion_event.relative().x * self.mouse_sensitivity.x; +                self.rotate_cam_horizontal(x_mov); +            }, +            _ => {} +        } +    } + +    /// this input method will be called when looking around, before taking a shot +    unsafe fn default_input(&mut self, event: Ref<InputEvent>) { +        let save_event = event.assume_safe(); + +        // left mouse button was pressed => switch to shooting mode +        if save_event.is_action_pressed(GodotString::from_str(&self.action_shooting), false, false) { +            godot_print!("mouse_button, switching to shooting mode"); +            self.input_state = InputState::Shooting; +            return; +        } + +        // rotate camera vertically +        let mouse_event = save_event.cast::<InputEventMouseMotion>(); // get the input as mouse input +        match mouse_event { +            Some(motion_event) => { +                let y_mov = -motion_event.relative().y * self.mouse_sensitivity.y; +                self.rotate_cam_vertical(y_mov); +            }, +            _ => {} +        }; +    } + +    /// this input method will be called when player is currently taking a shot +    unsafe fn shooting_input(&mut self, owner: &RigidBody, event: Ref<InputEvent>) { +        let save_event = event.assume_safe(); + +        // mouse released, shoot +        if save_event.is_action_released(GodotString::from_str(&self.action_shooting), false) { +            self.input_state = InputState::Moving; +            self.shoot(owner); +            return; +        } + +        // charge shot with vertical mouse movement +        let mouse_event = save_event.cast::<InputEventMouseMotion>(); // get the input as mouse input +        match mouse_event { +            Some(motion_event) => { +                let y_mov = motion_event.relative().y * self.mouse_sensitivity.y; +                self.current_force = match self.current_force + y_mov { +                    x if x < 0.0 => 0.0, +                    x if x > self.max_force => self.max_force, +                    x => x +                }; + +                godot_print!("current force: {}", self.current_force); +            }, +            _ => {} +        }; +    } + +    /// this input method will be called when player is moving +    unsafe fn moving_input(&mut self, event: Ref<InputEvent>) { +        let save_event = event.assume_safe(); + +        // rotate camera vertically +        let mouse_event = save_event.cast::<InputEventMouseMotion>(); // get the input as mouse input +        match mouse_event { +            Some(motion_event) => { +                let y_mov = motion_event.relative().y * self.mouse_sensitivity.y; +                self.rotate_cam_vertical(y_mov); +            }, +            _ => {} +        }; +    } + +    unsafe fn rotate_cam_horizontal(&mut self, input: f32) { +        // make sure the arm exists +        match self.node_camera_arm_horizontal { +            Some(arm) => { +                // rotate the horizontal camera arm +                let save_arm = arm.assume_safe(); +                save_arm.rotate_object_local(Vector3 {x: 0.0, y: 1.0, z: 0.0}, input as f64) +            }, +            _ => godot_warn!("No horizontal camera arm assigned.") +        } +    } + +    unsafe fn rotate_cam_vertical(&mut self, input: f32) { +        // make sure the camera arm actually exists +        match self.node_camera_arm_vertical { +            Some(arm) => { +                // check for the current rotation +                let save_arm = arm.assume_safe(); +                let current_rot = save_arm.rotation(); + +                // clamp the rotation +                if current_rot.x + input > self.camera_clamp.x || current_rot.x + input <= self.camera_clamp.y { +                    return; +                } + +                // actually rotate if possible +                let save_arm = arm.assume_safe(); +                save_arm.rotate_object_local(Vector3 {x: 1.0, y: 0.0, z: 0.0}, input as f64) +            }, +            _ => godot_warn!("No vertical camera arm assigned") +        } +    } + +    unsafe fn shoot(&mut self, owner: &RigidBody) { +        // make sure the camera actually exists +        match self.node_camera { +            Some(cam) => { +                // get the base position of the node +                let base_pos = owner.transform().origin; + +                // get the save reference +                let save_cam = cam.assume_safe(); +                 +                // get the forward vector of the camera setting the up angle to the defined value in the editor +                let mut forward_vector = save_cam.global_transform().basis.c(); +                forward_vector.y = self.up_angle; + +                // calculate the impulse force +                let impulse = forward_vector.normalized() * self.current_force; + +                // actually add the force +                owner.apply_impulse(base_pos, impulse);  +            }, +            None => godot_warn!("No camera assigned!"), +        } +    } +} diff --git a/rust/src/game.rs b/rust/src/game.rs index ece5a54..61b23ed 100644 --- a/rust/src/game.rs +++ b/rust/src/game.rs @@ -40,7 +40,5 @@ impl Game {      // This function will be called in every frame      #[export] -    unsafe fn _process(&self, _owner: &Spatial, delta: f64) { -        godot_print!("Inside {} _process(), delta is {}", self.name, delta); -    } +    unsafe fn _process(&self, _owner: &Spatial, _delta: f64) { }  } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 7958395..de26e5d 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,6 +1,7 @@  mod game;  mod spinning_cube;  mod test; +mod basic_die;  use gdnative::prelude::{godot_init, InitHandle}; @@ -9,6 +10,7 @@ fn init(handle: InitHandle) {      handle.add_class::<game::Game>();      handle.add_class::<spinning_cube::SpinningCube>();      handle.add_class::<test::SpinningCubeReverse>(); +    handle.add_class::<basic_die::BasicDie>();  }  // macros that create the entry-points of the dynamic library.  | 
