refactor player

This commit is contained in:
2024-08-27 15:29:45 +02:00
parent 0d72e7f765
commit 3c6a3dba44
7 changed files with 80 additions and 93 deletions

View File

@@ -314,12 +314,13 @@ states/Start/position = Vector2(107.334, 120.683)
transitions = ["Start", "Movement", SubResource("AnimationNodeStateMachineTransition_d2yto"), "JumpBlend", "Movement", SubResource("AnimationNodeStateMachineTransition_04hs0"), "Movement", "JumpBlend", SubResource("AnimationNodeStateMachineTransition_a4m5g")] transitions = ["Start", "Movement", SubResource("AnimationNodeStateMachineTransition_d2yto"), "JumpBlend", "Movement", SubResource("AnimationNodeStateMachineTransition_04hs0"), "Movement", "JumpBlend", SubResource("AnimationNodeStateMachineTransition_a4m5g")]
graph_offset = Vector2(18, 52) graph_offset = Vector2(18, 52)
[node name="Player" type="CharacterBody3D"] [node name="Player" type="Player"]
collision_layer = 2 collision_layer = 2
collision_mask = 3 collision_mask = 3
[node name="Head" type="Node3D" parent="."] [node name="Head" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.55647, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.55647, 0)
visible = false
[node name="FPV" parent="Head" instance=ExtResource("9_0cwor")] [node name="FPV" parent="Head" instance=ExtResource("9_0cwor")]
transform = Transform3D(-1, 0, -1.50996e-07, 0, 1, 0, 1.50996e-07, 0, -1, 0, -1.55647, 0) transform = Transform3D(-1, 0, -1.50996e-07, 0, 1, 0, 1.50996e-07, 0, -1, 0, -1.55647, 0)

View File

@@ -1,17 +1,18 @@
#pragma once #pragma once
#include <blitz/common/Types.h>
#include <godot_cpp/classes/animation_tree.hpp> #include <godot_cpp/classes/animation_tree.hpp>
#include <godot_cpp/classes/character_body3d.hpp> #include <godot_cpp/classes/character_body3d.hpp>
#include <godot_cpp/classes/node3d.hpp> #include <godot_cpp/classes/node3d.hpp>
#include <blitz/common/Types.h>
namespace blitz { namespace blitz {
class World; class World;
class PlayerController;
class Player : public godot::Node { class Player : public godot::CharacterBody3D {
GDCLASS(Player, godot::Node); GDCLASS(Player, godot::CharacterBody3D);
protected: protected:
static void _bind_methods(); static void _bind_methods();
@@ -39,9 +40,7 @@ class Player : public godot::Node {
protected: protected:
godot::Node3D* m_Mesh; godot::Node3D* m_Mesh;
godot::Node3D* m_Head;
godot::AnimationTree* m_AnimationTree; godot::AnimationTree* m_AnimationTree;
godot::CharacterBody3D* m_Player;
godot::Vector3 m_SnapVector; godot::Vector3 m_SnapVector;
PeerID m_PeerId; PeerID m_PeerId;
@@ -51,5 +50,6 @@ class Player : public godot::Node {
void BlendAnimation(const godot::String& a_AnimationName, float a_Goal, float a_Delta); void BlendAnimation(const godot::String& a_AnimationName, float a_Goal, float a_Delta);
friend class World; friend class World;
friend class PlayerController;
}; };
} // namespace blitz } // namespace blitz

View File

@@ -5,29 +5,31 @@
namespace blitz { namespace blitz {
class FirstPersonPlayer : public Player { class PlayerController : public godot::Node {
GDCLASS(FirstPersonPlayer, godot::Node) GDCLASS(PlayerController, godot::Node)
protected: protected:
static void _bind_methods(); static void _bind_methods();
public: public:
FirstPersonPlayer(); PlayerController();
~FirstPersonPlayer(); ~PlayerController();
// Godot overrides // Godot overrides
void _unhandled_input(const godot::Ref<godot::InputEvent>&); void _unhandled_input(const godot::Ref<godot::InputEvent>&);
void _physics_process(float delta) override; void _process(float delta);
void _ready(); void _ready();
private: private:
godot::Camera3D* m_Camera; godot::Camera3D* m_Camera;
float m_BobTime; float m_BobTime;
float m_Speed; float m_Speed;
Player* m_Player;
godot::Node3D* m_Head;
void UpdateBobbing(float delta); void UpdateBobbing(float delta);
void UpdateFOV(float delta); void UpdateFOV(float delta);
void UpdateCamera(const godot::InputEventMouseMotion&); void UpdateCamera(const godot::InputEventMouseMotion&);
void UpdatePosition(float delta); void UpdateVelocity(float delta);
void Shoot(); void Shoot();
}; };

View File

@@ -1,8 +1,8 @@
#include <blitz/godot/World.h> #include <blitz/godot/World.h>
#include <blitz/godot/NetworkInterface.h> #include <blitz/godot/NetworkInterface.h>
#include <client/FirstPersonPlayer.h>
#include <client/Player.h> #include <client/Player.h>
#include <client/PlayerController.h>
#include <godot_cpp/classes/engine.hpp> #include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/classes/multiplayer_api.hpp> #include <godot_cpp/classes/multiplayer_api.hpp>
#include <godot_cpp/classes/packed_scene.hpp> #include <godot_cpp/classes/packed_scene.hpp>
@@ -65,28 +65,18 @@ void World::HandlePacket(const protocol::packets::PlayerLeave& a_PlayerLeave) {
void World::AddPlayer(PlayerID a_PlayerId, String a_PlayerName) { void World::AddPlayer(PlayerID a_PlayerId, String a_PlayerName) {
UtilityFunctions::print("New Player with id : ", a_PlayerId, " and name ", a_PlayerName); UtilityFunctions::print("New Player with id : ", a_PlayerId, " and name ", a_PlayerName);
Ref<PackedScene> serverScene = ResourceLoader::get_singleton()->load(PlayerScenePath);
Player* player = Object::cast_to<Player>(serverScene->instantiate());
player->set_name(UtilityFunctions::var_to_str(a_PlayerId));
player->m_PeerId = a_PlayerId;
m_Players->add_child(player);
if (a_PlayerId == get_multiplayer()->get_unique_id()) { if (a_PlayerId == get_multiplayer()->get_unique_id()) {
Ref<PackedScene> serverScene = ResourceLoader::get_singleton()->load(PlayerScenePath); PlayerController* playerController = memnew(PlayerController);
player->add_child(playerController);
Node* playerContent = serverScene->instantiate();
FirstPersonPlayer* player = memnew(FirstPersonPlayer);
player->set_name(UtilityFunctions::var_to_str(a_PlayerId));
player->m_PeerId = a_PlayerId;
player->add_child(playerContent);
m_Players->add_child(player);
} else {
Ref<PackedScene> serverScene = ResourceLoader::get_singleton()->load(PlayerScenePath);
Node* playerContent = serverScene->instantiate();
Player* player = memnew(Player);
player->set_name(UtilityFunctions::var_to_str(a_PlayerId));
player->m_PeerId = a_PlayerId;
player->add_child(playerContent);
m_Players->add_child(player);
} }
} }

View File

@@ -31,19 +31,13 @@ void Player::_ready() {
return; return;
} }
m_Player = get_node<CharacterBody3D>("Player");
DEV_ASSERT(m_Player);
// we set the player to an invalid position // we set the player to an invalid position
m_Player->set_position({-99999, -999999, -999999}); set_position({-99999, -999999, -999999});
m_Head = get_node<Node3D>("Player/Head"); m_Mesh = get_node<Node3D>("Armature");
DEV_ASSERT(m_Head);
m_Mesh = get_node<Node3D>("Player/Armature");
DEV_ASSERT(m_Mesh); DEV_ASSERT(m_Mesh);
m_AnimationTree = get_node<AnimationTree>("Player/AnimationTree"); m_AnimationTree = get_node<AnimationTree>("AnimationTree");
DEV_ASSERT(m_AnimationTree); DEV_ASSERT(m_AnimationTree);
} }
@@ -51,29 +45,29 @@ void Player::_physics_process(float delta) {
if (godot::Engine::get_singleton()->is_editor_hint()) if (godot::Engine::get_singleton()->is_editor_hint())
return; return;
m_Player->move_and_slide(); move_and_slide();
UpdateAnimation(delta); UpdateAnimation(delta);
} }
Vector3 Player::GetPosition() const { Vector3 Player::GetPosition() const {
return m_Player->get_position(); return get_position();
} }
void Player::SetPosition(const Vector3& a_Position) { void Player::SetPosition(const Vector3& a_Position) {
m_Player->set_position(a_Position); set_position(a_Position);
} }
Vector3 Player::GetVelocity() const { Vector3 Player::GetVelocity() const {
return m_Player->get_velocity(); return get_velocity();
} }
void Player::SetVelocity(const Vector3& a_Velocity) { void Player::SetVelocity(const Vector3& a_Velocity) {
m_Player->set_velocity(a_Velocity); set_velocity(a_Velocity);
} }
void Player::UpdateAnimation(float a_Delta) { void Player::UpdateAnimation(float a_Delta) {
Vector3 velocity = m_Player->get_velocity(); Vector3 velocity = get_velocity();
float angle = m_Player->get_rotation().y; float angle = get_rotation().y;
Vector3 direction = velocity.rotated({0, 1, 0}, -angle); Vector3 direction = velocity.rotated({0, 1, 0}, -angle);
if (direction.length() < 1.0f) { if (direction.length() < 1.0f) {
@@ -91,8 +85,8 @@ void Player::UpdateAnimation(float a_Delta) {
float ratio = 0.5f - (UtilityFunctions::absf(direction.z) - UtilityFunctions::absf(direction.x)) * 0.5f; float ratio = 0.5f - (UtilityFunctions::absf(direction.z) - UtilityFunctions::absf(direction.x)) * 0.5f;
BlendAnimation("parameters/Movement/Walking/blend_amount", ratio, a_Delta); BlendAnimation("parameters/Movement/Walking/blend_amount", ratio, a_Delta);
m_AnimationTree->set("parameters/conditions/jump", !m_Player->is_on_floor() && m_Player->get_velocity().y > 0.0f); m_AnimationTree->set("parameters/conditions/jump", !is_on_floor() && get_velocity().y > 0.0f);
m_AnimationTree->set("parameters/conditions/is_on_floor", m_Player->is_on_floor()); m_AnimationTree->set("parameters/conditions/is_on_floor", is_on_floor());
} }
void Player::BlendAnimation(const godot::String& a_AnimationName, float a_Goal, float a_Delta) { void Player::BlendAnimation(const godot::String& a_AnimationName, float a_Goal, float a_Delta) {
@@ -117,11 +111,11 @@ void Player::SetModelVisible(bool a_Visible) {
} }
Vector3 Player::GetCameraRotation() const { Vector3 Player::GetCameraRotation() const {
return m_Player->get_rotation(); return get_rotation();
} }
void Player::SetCameraRotation(const Vector3& a_Rotation) { void Player::SetCameraRotation(const Vector3& a_Rotation) {
m_Player->set_rotation(a_Rotation); set_rotation(a_Rotation);
} }
} // namespace blitz } // namespace blitz

View File

@@ -1,4 +1,4 @@
#include <client/FirstPersonPlayer.h> #include <client/PlayerController.h>
#include <godot_cpp/classes/camera3d.hpp> #include <godot_cpp/classes/camera3d.hpp>
#include <godot_cpp/classes/engine.hpp> #include <godot_cpp/classes/engine.hpp>
@@ -41,15 +41,13 @@ static const float AnimationBlend = 7.0;
static const char BulletScenePath[] = "res://Scenes/Weapons/pen.tscn"; static const char BulletScenePath[] = "res://Scenes/Weapons/pen.tscn";
void FirstPersonPlayer::_bind_methods() {} void PlayerController::_bind_methods() {}
FirstPersonPlayer::FirstPersonPlayer() : Player(), m_BobTime(0) {} PlayerController::PlayerController() : m_BobTime(0) {}
FirstPersonPlayer::~FirstPersonPlayer() {} PlayerController::~PlayerController() {}
void FirstPersonPlayer::_ready() {
Player::_ready();
void PlayerController::_ready() {
InputMap::get_singleton()->load_from_project_settings(); InputMap::get_singleton()->load_from_project_settings();
if (!Engine::get_singleton()->is_editor_hint()) { if (!Engine::get_singleton()->is_editor_hint()) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
@@ -57,18 +55,25 @@ void FirstPersonPlayer::_ready() {
return; return;
} }
m_Player = Object::cast_to<Player>(get_parent());
m_Head = m_Player->get_node<Node3D>("Head");
DEV_ASSERT(m_Head);
m_Head->set_visible(true);
m_Camera = memnew(Camera3D); m_Camera = memnew(Camera3D);
m_Camera->set_name("FirstPersonCamera"); m_Camera->set_name("FirstPersonCamera");
m_Head->add_child(m_Camera); m_Head->add_child(m_Camera);
m_Camera->make_current(); m_Camera->make_current();
SetModelVisible(false); m_Player->SetModelVisible(false);
SetPosition({0, 100, 0}); m_Player->SetPosition({0, 1, 0});
SetVelocity({0, 0, 0}); m_Player->SetVelocity({0, 0, 0});
} }
void FirstPersonPlayer::_unhandled_input(const godot::Ref<godot::InputEvent>& a_Event) { void PlayerController::_unhandled_input(const godot::Ref<godot::InputEvent>& a_Event) {
auto* event = Object::cast_to<InputEventMouseMotion>(a_Event.ptr()); auto* event = Object::cast_to<InputEventMouseMotion>(a_Event.ptr());
if (event) if (event)
UpdateCamera(*event); UpdateCamera(*event);
@@ -81,7 +86,7 @@ void FirstPersonPlayer::_unhandled_input(const godot::Ref<godot::InputEvent>& a_
} }
} }
void FirstPersonPlayer::_physics_process(float a_Delta) { void PlayerController::_process(float a_Delta) {
#if DEBUG_ENABLED #if DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint()) { if (Engine::get_singleton()->is_editor_hint()) {
return; return;
@@ -91,26 +96,21 @@ void FirstPersonPlayer::_physics_process(float a_Delta) {
auto* Input = Input::get_singleton(); auto* Input = Input::get_singleton();
if (!m_Player->is_on_floor()) if (!m_Player->is_on_floor())
SetVelocity(GetVelocity() - Vector3{0, GRAVITY * a_Delta, 0}); m_Player->SetVelocity(m_Player->GetVelocity() - Vector3{0, GRAVITY * a_Delta, 0});
if (Input->is_action_pressed("jump") && m_Player->is_on_floor()) if (Input->is_action_pressed("jump") && m_Player->is_on_floor())
SetVelocity({GetVelocity().x, JUMP_VELOCITY, GetVelocity().z}); m_Player->SetVelocity({m_Player->GetVelocity().x, JUMP_VELOCITY, m_Player->GetVelocity().z});
m_Speed = Input->is_action_pressed("sprint") ? SPRINT_SPEED : WALK_SPEED; m_Speed = Input->is_action_pressed("sprint") ? SPRINT_SPEED : WALK_SPEED;
UpdatePosition(a_Delta);
UpdateFOV(a_Delta); UpdateFOV(a_Delta);
UpdateBobbing(a_Delta); UpdateBobbing(a_Delta);
UpdateVelocity(a_Delta);
m_Player->move_and_slide();
UpdateAnimation(a_Delta);
Shoot(); Shoot();
} }
void FirstPersonPlayer::Shoot() { void PlayerController::Shoot() {
if (Input::get_singleton()->is_action_pressed("shoot")) { if (Input::get_singleton()->is_action_pressed("shoot")) {
Ref<PackedScene> bulletScene = ResourceLoader::get_singleton()->load(BulletScenePath); Ref<PackedScene> bulletScene = ResourceLoader::get_singleton()->load(BulletScenePath);
auto* bullet = Object::cast_to<Node3D>(bulletScene->instantiate()); auto* bullet = Object::cast_to<Node3D>(bulletScene->instantiate());
@@ -118,13 +118,13 @@ void FirstPersonPlayer::Shoot() {
bullet->set_position(m_Camera->get_global_position()); bullet->set_position(m_Camera->get_global_position());
bullet->set_transform(m_Camera->get_global_transform()); bullet->set_transform(m_Camera->get_global_transform());
Node* entities = get_node<Node>("../../Entities"); Node* entities = m_Player->get_node<Node>("../../Entities");
entities->add_child(bullet); entities->add_child(bullet);
} }
} }
void FirstPersonPlayer::UpdateBobbing(float a_Delta) { void PlayerController::UpdateBobbing(float a_Delta) {
m_BobTime += a_Delta * GetVelocity().length() * m_Player->is_on_floor(); m_BobTime += a_Delta * m_Player->GetVelocity().length() * m_Player->is_on_floor();
Vector3 newPos{static_cast<float>(Math::cos(m_BobTime * BOB_FREQ / 2.0) * BOB_AMP), Vector3 newPos{static_cast<float>(Math::cos(m_BobTime * BOB_FREQ / 2.0) * BOB_AMP),
static_cast<float>(Math::sin(m_BobTime * BOB_FREQ) * BOB_AMP), 0}; static_cast<float>(Math::sin(m_BobTime * BOB_FREQ) * BOB_AMP), 0};
@@ -132,7 +132,7 @@ void FirstPersonPlayer::UpdateBobbing(float a_Delta) {
// m_Camera->set_transform({m_Camera->get_transform().basis, newPos}); // m_Camera->set_transform({m_Camera->get_transform().basis, newPos});
} }
void FirstPersonPlayer::UpdateCamera(const InputEventMouseMotion& a_Event) { void PlayerController::UpdateCamera(const InputEventMouseMotion& a_Event) {
m_Player->rotate_y(-a_Event.get_relative().x * SENSITIVITY); m_Player->rotate_y(-a_Event.get_relative().x * SENSITIVITY);
m_Head->rotate_x(-a_Event.get_relative().y * SENSITIVITY); m_Head->rotate_x(-a_Event.get_relative().y * SENSITIVITY);
@@ -141,7 +141,7 @@ void FirstPersonPlayer::UpdateCamera(const InputEventMouseMotion& a_Event) {
m_Head->set_rotation({rotationX, m_Head->get_rotation().y, m_Head->get_rotation().z}); m_Head->set_rotation({rotationX, m_Head->get_rotation().y, m_Head->get_rotation().z});
} }
void FirstPersonPlayer::UpdatePosition(float delta) { void PlayerController::UpdateVelocity(float delta) {
auto* Input = Input::get_singleton(); auto* Input = Input::get_singleton();
Vector2 inputDirection = Input->get_vector("move_left", "move_right", "move_forwards", "move_backwards"); Vector2 inputDirection = Input->get_vector("move_left", "move_right", "move_forwards", "move_backwards");
@@ -149,25 +149,25 @@ void FirstPersonPlayer::UpdatePosition(float delta) {
if (m_Player->is_on_floor()) { if (m_Player->is_on_floor()) {
if (!direction.is_zero_approx()) { if (!direction.is_zero_approx()) {
SetVelocity({direction.x * m_Speed, GetVelocity().y, direction.z * m_Speed}); m_Player->SetVelocity({direction.x * m_Speed, m_Player->GetVelocity().y, direction.z * m_Speed});
} else { } else {
SetVelocity({Math::lerp(static_cast<float>(GetVelocity().x), static_cast<float>(direction.x * m_Speed), m_Player->SetVelocity({Math::lerp(static_cast<float>(m_Player->GetVelocity().x), static_cast<float>(direction.x * m_Speed),
static_cast<float>(delta * GROUND_FRICTION)), static_cast<float>(delta * GROUND_FRICTION)),
GetVelocity().y, m_Player->GetVelocity().y,
Math::lerp(static_cast<float>(GetVelocity().z), static_cast<float>(direction.z * m_Speed), Math::lerp(static_cast<float>(m_Player->GetVelocity().z), static_cast<float>(direction.z * m_Speed),
static_cast<float>(delta * GROUND_FRICTION))}); static_cast<float>(delta * GROUND_FRICTION))});
} }
} else { } else {
SetVelocity({Math::lerp(static_cast<float>(GetVelocity().x), static_cast<float>(direction.x * m_Speed), m_Player->SetVelocity({Math::lerp(static_cast<float>(m_Player->GetVelocity().x), static_cast<float>(direction.x * m_Speed),
static_cast<float>(delta * AIR_MOVEMENT)), static_cast<float>(delta * AIR_MOVEMENT)),
GetVelocity().y, m_Player->GetVelocity().y,
Math::lerp(static_cast<float>(GetVelocity().z), static_cast<float>(direction.z * m_Speed), Math::lerp(static_cast<float>(m_Player->GetVelocity().z), static_cast<float>(direction.z * m_Speed),
static_cast<float>(delta * AIR_MOVEMENT))}); static_cast<float>(delta * AIR_MOVEMENT))});
} }
} }
void FirstPersonPlayer::UpdateFOV(float a_Delta) { void PlayerController::UpdateFOV(float a_Delta) {
float velocityClamped = Math::clamp(GetVelocity().length(), MIN_FOV_VELOCITY, MAX_FOV_VELOCITY); float velocityClamped = Math::clamp(m_Player->GetVelocity().length(), MIN_FOV_VELOCITY, MAX_FOV_VELOCITY);
float targetFOV = BASE_FOV + FOV_CHANGE * velocityClamped; float targetFOV = BASE_FOV + FOV_CHANGE * velocityClamped;
m_Camera->set_fov(Math::lerp(static_cast<float>(m_Camera->get_fov()), targetFOV, a_Delta * FOV_TRANSITION)); m_Camera->set_fov(Math::lerp(static_cast<float>(m_Camera->get_fov()), targetFOV, a_Delta * FOV_TRANSITION));
} }

View File

@@ -1,10 +1,10 @@
#include <blitz/godot/NetworkInterface.h> #include <blitz/godot/NetworkInterface.h>
#include <client/Bullet.h> #include <client/Bullet.h>
#include <client/ClientWorld.h> #include <client/ClientWorld.h>
#include <client/FirstPersonPlayer.h>
#include <client/Main.h> #include <client/Main.h>
#include <client/MainMenu.h> #include <client/MainMenu.h>
#include <client/Player.h> #include <client/Player.h>
#include <client/PlayerController.h>
#include <server/Server.h> #include <server/Server.h>
#include <server/ServerWorld.h> #include <server/ServerWorld.h>
@@ -16,7 +16,7 @@ using namespace godot;
static void RegisterClasses() { static void RegisterClasses() {
GDREGISTER_CLASS(blitz::Player); GDREGISTER_CLASS(blitz::Player);
GDREGISTER_CLASS(blitz::FirstPersonPlayer); GDREGISTER_CLASS(blitz::PlayerController);
GDREGISTER_CLASS(blitz::MainMenu); GDREGISTER_CLASS(blitz::MainMenu);
GDREGISTER_CLASS(blitz::Main); GDREGISTER_CLASS(blitz::Main);
GDREGISTER_CLASS(blitz::NetworkInterface); GDREGISTER_CLASS(blitz::NetworkInterface);