2024-11-26 23:41:39 +00:00
|
|
|
#include "player.hpp"
|
|
|
|
#include "utils/godot_macros.hpp"
|
2024-11-27 15:32:58 +00:00
|
|
|
#include <godot_cpp/variant/utility_functions.hpp>
|
|
|
|
#include <godot_cpp/classes/input_event_joypad_motion.hpp>
|
2024-11-26 23:41:39 +00:00
|
|
|
|
2024-11-27 19:25:44 +00:00
|
|
|
void Player::_bind_methods() {
|
|
|
|
#define CLASSNAME Player
|
2024-11-30 22:48:30 +00:00
|
|
|
GDFUNCTION(get_input_directions);
|
2024-12-01 20:38:30 +00:00
|
|
|
GDFUNCTION(get_input_fire);
|
2024-11-27 19:25:44 +00:00
|
|
|
}
|
2024-11-26 23:41:39 +00:00
|
|
|
|
|
|
|
void Player::_ready() {
|
2024-11-30 22:48:30 +00:00
|
|
|
if(gd::Engine::get_singleton()->is_editor_hint())
|
|
|
|
return;
|
2024-11-26 23:41:39 +00:00
|
|
|
this->anim_tree = this->get_node<gd::AnimationTree>("%AnimationTree");
|
2024-12-01 20:38:30 +00:00
|
|
|
this->fsm = gd::Object::cast_to<gd::AnimationNodeStateMachinePlayback>(this->anim_tree->get("parameters/Actions/playback"));
|
2024-11-27 15:32:58 +00:00
|
|
|
this->input = this->get_node<utils::PlayerInput>("%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)));
|
2024-12-01 20:38:30 +00:00
|
|
|
this->input->listen_to(utils::PlayerInput::Listener("fire", callable_mp(this, &Player::_on_fire)));
|
2024-11-26 23:41:39 +00:00
|
|
|
this->model_node = this->get_node<gd::Node3D>("%CharacterModel");
|
2024-12-01 20:38:30 +00:00
|
|
|
this->camera_parent = this->get_node<gd::Node3D>("%CameraParent");
|
|
|
|
this->camera_parent->set_global_rotation(this->get_global_rotation());
|
2024-11-26 23:41:39 +00:00
|
|
|
}
|
|
|
|
|
2024-11-30 22:48:30 +00:00
|
|
|
void Player::_process(double delta) {
|
|
|
|
if(gd::Engine::get_singleton()->is_editor_hint())
|
|
|
|
return;
|
2024-12-01 20:38:30 +00:00
|
|
|
if(this->input_fire >= 0.0)
|
|
|
|
this->input_fire -= delta;
|
|
|
|
this->process_rotate(delta);
|
|
|
|
this->process_transform_camera(delta);
|
2024-11-27 19:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Player::_physics_process(double delta [[maybe_unused]]) {
|
2024-11-30 22:48:30 +00:00
|
|
|
if(gd::Engine::get_singleton()->is_editor_hint())
|
|
|
|
return;
|
2024-11-27 19:25:44 +00:00
|
|
|
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) +
|
2024-11-30 22:48:30 +00:00
|
|
|
local_motion.z * model_basis.get_column(2) +
|
|
|
|
(this->is_on_floor() ? gd::Vector3{} : gd::Vector3{0.f, -1.f, 0.f})
|
2024-11-27 19:25:44 +00:00
|
|
|
};
|
|
|
|
this->set_velocity(motion / delta);
|
|
|
|
this->move_and_slide();
|
|
|
|
}
|
|
|
|
|
2024-12-01 20:38:30 +00:00
|
|
|
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) {
|
2024-12-02 17:39:30 +00:00
|
|
|
if(this->fsm->get_current_node().contains("[turn")) {
|
2024-12-01 20:38:30 +00:00
|
|
|
//! 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);
|
2024-12-02 22:18:08 +00:00
|
|
|
this->anim_tree->set("parameters/Actions/Stationary [turn]/Turn/blend_position", diff * M_PI_2f);
|
2024-12-01 20:38:30 +00:00
|
|
|
} else {
|
2024-12-02 22:18:08 +00:00
|
|
|
this->anim_tree->set("parameters/Actions/Stationary [turn_animated]/blend_position", 0.f);
|
2024-12-01 20:38:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-27 15:32:58 +00:00
|
|
|
void Player::_on_dir_horizontal(gd::Ref<gd::InputEvent>, float value) {
|
|
|
|
this->input_directions.x = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::_on_dir_vertical(gd::Ref<gd::InputEvent>, float value) {
|
|
|
|
this->input_directions.y = value;
|
|
|
|
}
|
|
|
|
|
2024-12-01 20:38:30 +00:00
|
|
|
void Player::_on_fire(gd::Ref<gd::InputEvent>, float value) {
|
|
|
|
if(value > 0.f) {
|
|
|
|
this->input_fire = 0.5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-27 19:25:44 +00:00
|
|
|
gd::Vector2 Player::get_input_directions() const {
|
|
|
|
return this->input_directions;
|
2024-11-26 23:41:39 +00:00
|
|
|
}
|
2024-12-01 20:38:30 +00:00
|
|
|
|
|
|
|
bool Player::get_input_fire() {
|
|
|
|
bool const val = this->input_fire > 0.0;
|
|
|
|
this->input_fire = 0.0;
|
|
|
|
return val;
|
|
|
|
}
|