wave-survival/modules/wave_survival/player_camera.cpp

108 lines
3 KiB
C++

#include "player_camera.h"
#include "macros.h"
#include "player_body.h"
#include "player_input.h"
void PlayerCamera::_bind_methods() {
}
void PlayerCamera::on_look_input(Vector2 input) {
// PI / 2.1 to avoid change to the flattened forward vector
static const double LOOK_LIM{ Math::PI / 2.1 };
GETSET(rotation, {
rotation.x = CLAMP(rotation.x + input.y, -LOOK_LIM, LOOK_LIM);
});
global_rotate(Vector3{ 0.f, 1.f, 0.f }, input.x);
lead_weapon(input * this->weapon_lead_speed);
}
void PlayerCamera::lead_weapon(Vector2 movement) {
this->weapon_lead_rotation.x += movement.y;
this->weapon_lead_rotation.y += movement.x;
this->weapon_lead_rotation = this->weapon_lead_rotation.normalized() * CLAMP(this->weapon_lead_rotation.length(), -this->weapon_lead_limit, this->weapon_lead_limit);
for (Variant child : get_children()) {
if (Node3D * child3d{ cast_to<Node3D>(child) }) {
child3d->set_rotation(this->weapon_lead_rotation);
}
}
}
void PlayerCamera::update_fov() {
if (!Engine::get_singleton()->is_editor_hint() && is_ready()) {
set_fov(CLAMP(this->base_fov * this->fov_factor, 1, 179));
}
}
void PlayerCamera::update_offset() {
bool const is_running{ this->body->get_is_running() && this->body->is_on_floor() };
if (is_running != this->was_running) {
this->was_running = is_running;
this->run_bob_time = 0.0;
}
double wave{ Math::sin(this->run_bob_time) };
Vector3 offset{ Vector3{ float(wave), float(Math::abs(wave)), 0 } * this->run_bob_amplitude };
if (!is_running) {
this->run_bob_time = MIN(this->run_bob_time, this->run_bob_blend_out);
offset = offset.lerp(Vector3(), this->run_bob_time / this->run_bob_blend_out);
}
GETSET(position, {
Basis const basis{ get_basis() };
position = this->home + basis.get_column(0) * offset.x + basis.get_column(1) * offset.y * 5.0;
});
for (Variant child : get_children()) {
Node3D *child_3d{ cast_to<Node3D>(child) };
GETSETM(child_3d, position, {
position = offset;
});
}
}
void PlayerCamera::ready() {
PlayerInput *input{ cast_to<PlayerInput>(get_node(NodePath("%PlayerInput"))) };
input->connect(PlayerInput::sig_look_input, callable_mp(this, &self_type::on_look_input));
this->base_fov = get_fov();
this->home = get_position();
this->body = cast_to<PlayerBody>(get_parent());
}
void PlayerCamera::process(double delta) {
this->run_bob_time += delta * this->run_bob_frequency;
update_offset();
this->fov_factor = 1.0;
update_fov();
}
void PlayerCamera::_notification(int what) {
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
switch (what) {
default:
return;
case NOTIFICATION_READY:
set_process(true);
set_process_priority(-1);
ready();
return;
case NOTIFICATION_PROCESS:
process(get_process_delta_time());
return;
}
}
void PlayerCamera::set_fov_factor(float value) {
this->fov_factor *= value;
update_fov();
}
float PlayerCamera::get_fov_factor() const {
return this->fov_factor;
}
void PlayerCamera::recoil(float r) {
GETSET(rotation, {
rotation.x = CLAMP(rotation.x + r, -Math::PI / 2.0, Math::PI / 2.0);
});
lead_weapon({ 0, 0.02f });
}