#include "player.hpp" #include "utils/godot_macros.hpp" #include #include void Player::_bind_methods() { #define CLASSNAME Player GDFUNCTION(get_input_directions); GDFUNCTION(get_input_fire); } void Player::_ready() { if(gd::Engine::get_singleton()->is_editor_hint()) return; this->anim_tree = this->get_node("%AnimationTree"); this->fsm = gd::Object::cast_to(this->anim_tree->get("parameters/Actions/playback")); this->input = this->get_node("%PlayerInput"); this->input->listen_to(utils::PlayerInput::Listener("dir_left", "dir_right", callable_mp(this, &Player::_on_dir_horizontal))); this->input->listen_to(utils::PlayerInput::Listener("dir_backward", "dir_forward", callable_mp(this, &Player::_on_dir_vertical))); this->input->listen_to(utils::PlayerInput::Listener("fire", callable_mp(this, &Player::_on_fire))); this->model_node = this->get_node("%CharacterModel"); this->camera_parent = this->get_node("%CameraParent"); this->camera_parent->set_global_rotation(this->get_global_rotation()); } void Player::_process(double delta) { if(gd::Engine::get_singleton()->is_editor_hint()) return; if(this->input_fire >= 0.0) this->input_fire -= delta; this->process_rotate(delta); this->process_transform_camera(delta); } void Player::_physics_process(double delta [[maybe_unused]]) { if(gd::Engine::get_singleton()->is_editor_hint()) return; gd::Basis const &model_basis{this->model_node->get_global_basis()}; gd::Vector3 const local_motion{this->anim_tree->get_root_motion_position()}; gd::Vector3 const motion { local_motion.x * model_basis.get_column(0) + local_motion.y * model_basis.get_column(1) + local_motion.z * model_basis.get_column(2) + (this->is_on_floor() ? gd::Vector3{} : gd::Vector3{0.f, -1.f, 0.f}) }; this->set_velocity(motion / delta); this->move_and_slide(); } void Player::process_transform_camera(double delta) { this->camera_parent->set_global_position(this->get_global_position()); float const camera_speed{float(delta) * (this->fsm->get_current_node().contains("[aim]") ? this->AIMING_CAMERA_ROTATION_SPEED : this->CAMERA_ROTATION_SPEED)}; this->camera_parent->rotate_y(this->input_directions.x * -camera_speed); } void Player::process_rotate(double delta) { if(this->fsm->get_current_node().contains("[turn")) { //! the signed angle difference between the left axes of the camera parent and Player float const diff = -this->camera_parent->get_global_basis().get_column(0).signed_angle_to(this->get_global_basis().get_column(0), {0.f, 1.f, 0.f}); //! the maximum rotation to allow for this frame float const speed{float(delta) * this->ROTATION_SPEED}; float const actual_speed{speed < gd::Math::abs(diff) ? gd::Math::sign(diff) * speed : diff}; // rotate by max allowed or full difference, whichever has the smaller magnitude this->rotate_y(actual_speed); this->anim_tree->set("parameters/Actions/Stationary [turn]/Turn/blend_position", diff * M_PI_2f); } else { this->anim_tree->set("parameters/Actions/Stationary [turn_animated]/blend_position", 0.f); } } void Player::_on_dir_horizontal(gd::Ref, float value) { this->input_directions.x = value; } void Player::_on_dir_vertical(gd::Ref, float value) { this->input_directions.y = value; } void Player::_on_fire(gd::Ref, float value) { if(value > 0.f) { this->input_fire = 0.5; } } gd::Vector2 Player::get_input_directions() const { return this->input_directions; } bool Player::get_input_fire() { bool const val = this->input_fire > 0.0; this->input_fire = 0.0; return val; }