generated from Persson-dev/Godot-Xmake
real FPS
This commit is contained in:
21
godot/Scenes/Characters/first_person_player.tscn
Normal file
21
godot/Scenes/Characters/first_person_player.tscn
Normal file
@@ -0,0 +1,21 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://d38w4ae3qj0k4"]
|
||||
|
||||
[sub_resource type="CapsuleMesh" id="CapsuleMesh_ky6st"]
|
||||
|
||||
[sub_resource type="ConvexPolygonShape3D" id="ConvexPolygonShape3D_qjfxs"]
|
||||
points = PackedVector3Array(-0.125207, -0.532801, -0.480507, 0.0227831, 0.47607, 0.498884, 0.169713, 0.559144, 0.464172, 0.231051, -0.803591, 0.320455, 0.40741, 0.651043, -0.243523, -0.482789, 0.594843, 0.0822132, -0.362868, -0.682312, 0.289697, 0.469044, -0.654529, -0.0662713, -0.127444, 0.842701, -0.338103, -0.393435, -0.683942, -0.244717, 0.438255, 0.623309, 0.200849, 0.0841477, 0.977454, 0.114795, -0.0682023, -0.976458, -0.12927, 0.20055, -0.563129, -0.451454, -0.185527, 0.595453, -0.453475, -0.273363, 0.592268, 0.407754, -0.00693649, -0.476823, 0.49966, 0.375821, -0.588614, 0.316955, 0.111579, 0.563059, -0.481177, -0.41725, 0.527866, -0.270497, -0.484546, -0.596972, -0.0665097, -0.279747, 0.908561, 0.0533361, -0.250197, -0.880712, 0.205319, 0.263647, -0.902771, -0.127394, 0.293368, 0.871526, -0.157196, 0.373412, -0.526319, -0.328246, 0.499663, 0.476641, -0.00688856, 0.0531056, 0.875001, 0.324703, -0.154543, -0.590854, 0.465879, -0.0972799, -0.782358, -0.398188, -0.387649, -0.498171, 0.31565, -0.30068, -0.587995, -0.388901)
|
||||
|
||||
[node name="FirstPersonPlayer" type="FirstPersonPlayer"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
mesh = SubResource("CapsuleMesh_ky6st")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
shape = SubResource("ConvexPolygonShape3D_qjfxs")
|
||||
|
||||
[node name="Head" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.578545, 0)
|
||||
|
||||
[node name="Camera" type="Camera3D" parent="Head"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0)
|
||||
@@ -1,13 +1,13 @@
|
||||
[gd_scene load_steps=18 format=3 uid="uid://coue2qehpn4fr"]
|
||||
|
||||
[ext_resource type="Texture2D" path="res://Assets/Textures/Black.png" id="1_hwes2"]
|
||||
[ext_resource type="Texture2D" path="res://Assets/Textures/Sky.png" id="1_rrvcb"]
|
||||
[ext_resource type="Texture2D" path="res://Assets/Textures/Orange.png" id="2_087ax"]
|
||||
[ext_resource type="Texture2D" path="res://Assets/Textures/Green.png" id="3_qkav0"]
|
||||
[ext_resource type="PackedScene" path="res://Scenes/Characters/player.tscn" id="5_2382e"]
|
||||
[ext_resource type="Texture2D" uid="uid://raamjcrv2txf" path="res://Assets/Textures/Sky.png" id="1_mnexj"]
|
||||
[ext_resource type="Texture2D" uid="uid://cwlithvge34pb" path="res://Assets/Textures/Black.png" id="2_fkwcn"]
|
||||
[ext_resource type="Texture2D" uid="uid://cqoqcor7jk066" path="res://Assets/Textures/Orange.png" id="3_ux02w"]
|
||||
[ext_resource type="Texture2D" uid="uid://btpyap77skggq" path="res://Assets/Textures/Green.png" id="4_wp15n"]
|
||||
[ext_resource type="PackedScene" uid="uid://d38w4ae3qj0k4" path="res://Scenes/Characters/first_person_player.tscn" id="5_8ctht"]
|
||||
|
||||
[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_6c4vd"]
|
||||
panorama = ExtResource("1_rrvcb")
|
||||
panorama = ExtResource("1_mnexj")
|
||||
|
||||
[sub_resource type="Sky" id="Sky_5ngqa"]
|
||||
sky_material = SubResource("PanoramaSkyMaterial_6c4vd")
|
||||
@@ -19,7 +19,7 @@ tonemap_mode = 2
|
||||
glow_enabled = true
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ajchh"]
|
||||
albedo_texture = ExtResource("1_hwes2")
|
||||
albedo_texture = ExtResource("2_fkwcn")
|
||||
uv1_triplanar = true
|
||||
|
||||
[sub_resource type="PlaneMesh" id="PlaneMesh_mmup0"]
|
||||
@@ -30,7 +30,7 @@ size = Vector2(50, 50)
|
||||
data = PackedVector3Array(25, 0, 25, -25, 0, 25, 25, 0, -25, -25, 0, 25, -25, 0, -25, 25, 0, -25)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jkvud"]
|
||||
albedo_texture = ExtResource("2_087ax")
|
||||
albedo_texture = ExtResource("3_ux02w")
|
||||
uv1_triplanar = true
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_plpqy"]
|
||||
@@ -45,13 +45,13 @@ left_to_right = -2.0
|
||||
size = Vector3(5, 5, 5)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_pfpgv"]
|
||||
albedo_texture = ExtResource("3_qkav0")
|
||||
albedo_texture = ExtResource("4_wp15n")
|
||||
uv1_triplanar = true
|
||||
|
||||
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_rit6o"]
|
||||
data = PackedVector3Array(-12.5, 2.5, 2.5, 2.5, -2.5, 2.5, -2.5, -2.5, 2.5, -12.5, 2.5, -2.5, -2.5, -2.5, -2.5, 2.5, -2.5, -2.5, -12.5, 2.5, 2.5, -12.5, 2.5, -2.5, 2.5, -2.5, 2.5, -12.5, 2.5, -2.5, 2.5, -2.5, -2.5, 2.5, -2.5, 2.5, -12.5, 2.5, -2.5, -12.5, 2.5, 2.5, -2.5, -2.5, -2.5, -12.5, 2.5, 2.5, -2.5, -2.5, 2.5, -2.5, -2.5, -2.5, -2.5, -2.5, 2.5, 2.5, -2.5, 2.5, -2.5, -2.5, -2.5, 2.5, -2.5, 2.5, 2.5, -2.5, -2.5, -2.5, -2.5, -2.5)
|
||||
|
||||
[node name="Prototype" type="Node3D"]
|
||||
[node name="World" type="Node3D"]
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_ctwiv")
|
||||
@@ -87,6 +87,4 @@ surface_material_override/0 = SubResource("StandardMaterial3D_pfpgv")
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Slope/StaticBody3D"]
|
||||
shape = SubResource("ConcavePolygonShape3D_rit6o")
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("5_2382e")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0130468, 0)
|
||||
velocity = Vector3(0, 0, 0)
|
||||
[node name="FirstPersonPlayer" parent="." instance=ExtResource("5_8ctht")]
|
||||
@@ -11,8 +11,7 @@ config_version=5
|
||||
[application]
|
||||
|
||||
config/name="Blitz3"
|
||||
config/tags=PackedStringArray()
|
||||
run/main_scene="res://Scenes/Levels/prototype.tscn"
|
||||
run/main_scene="res://Scenes/Levels/world.tscn"
|
||||
config/features=PackedStringArray("4.2", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
@@ -38,7 +37,7 @@ move_backwards={
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
run={
|
||||
sprint={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
@@ -48,3 +47,8 @@ jump={
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
escape={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
139
src/FirstPersonPlayer.cpp
Normal file
139
src/FirstPersonPlayer.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
#include "FirstPersonPlayer.h"
|
||||
|
||||
#include <godot_cpp/classes/engine.hpp>
|
||||
#include <godot_cpp/classes/input.hpp>
|
||||
#include <godot_cpp/classes/input_event_mouse_motion.hpp>
|
||||
#include <godot_cpp/classes/input_map.hpp>
|
||||
#include <godot_cpp/core/math.hpp>
|
||||
|
||||
using namespace godot;
|
||||
|
||||
namespace blitz {
|
||||
|
||||
static constexpr float WALK_SPEED = 5.0f;
|
||||
static constexpr float SPRINT_SPEED = 7.0f;
|
||||
|
||||
static constexpr float JUMP_VELOCITY = 4.5f;
|
||||
|
||||
static constexpr float GRAVITY = 9.81f;
|
||||
|
||||
static constexpr float SENSITIVITY = 0.003f;
|
||||
|
||||
static constexpr float BOB_FREQ = 2.0f;
|
||||
static constexpr float BOB_AMP = 0.08f;
|
||||
|
||||
static constexpr float AIR_MOVEMENT = 3.0f;
|
||||
|
||||
static constexpr float GROUND_FRICTION = 7.0f;
|
||||
|
||||
static constexpr float BASE_FOV = 75.0f;
|
||||
static constexpr float FOV_CHANGE = 1.5f;
|
||||
static constexpr float FOV_TRANSITION = 8.0f;
|
||||
static constexpr float MIN_FOV_VELOCITY = 0.5;
|
||||
static constexpr float MAX_FOV_VELOCITY = SPRINT_SPEED * 2.0f;
|
||||
|
||||
void FirstPersonPlayer::_bind_methods() {}
|
||||
|
||||
FirstPersonPlayer::FirstPersonPlayer() : m_BobTime(0) {}
|
||||
|
||||
FirstPersonPlayer::~FirstPersonPlayer() {}
|
||||
|
||||
void FirstPersonPlayer::_ready() {
|
||||
InputMap::get_singleton()->load_from_project_settings();
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
|
||||
}
|
||||
m_Head = Object::cast_to<Node3D>(find_child("Head"));
|
||||
DEV_ASSERT(m_Head);
|
||||
m_Camera = Object::cast_to<Camera3D>(m_Head->find_child("Camera"));
|
||||
DEV_ASSERT(m_Camera);
|
||||
}
|
||||
|
||||
void FirstPersonPlayer::_unhandled_input(const godot::Ref<godot::InputEvent>& a_Event) {
|
||||
auto* event = Object::cast_to<InputEventMouseMotion>(a_Event.ptr());
|
||||
if (event)
|
||||
UpdateCamera(*event);
|
||||
|
||||
// TODO: remove
|
||||
if (Input::get_singleton()->is_action_just_pressed("escape")) {
|
||||
Input::MouseMode current = Input::get_singleton()->get_mouse_mode();
|
||||
Input::get_singleton()->set_mouse_mode(
|
||||
(current == Input::MOUSE_MODE_CAPTURED) ? Input::MOUSE_MODE_VISIBLE : Input::MOUSE_MODE_CAPTURED);
|
||||
}
|
||||
}
|
||||
|
||||
void FirstPersonPlayer::_physics_process(float a_Delta) {
|
||||
#if DEBUG_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto* Input = Input::get_singleton();
|
||||
|
||||
if (!is_on_floor())
|
||||
set_velocity(get_velocity() - Vector3{0, GRAVITY * a_Delta, 0});
|
||||
|
||||
if (Input->is_action_pressed("jump") && is_on_floor())
|
||||
set_velocity({get_velocity().x, JUMP_VELOCITY, get_velocity().z});
|
||||
|
||||
m_Speed = Input->is_action_pressed("sprint") ? SPRINT_SPEED : WALK_SPEED;
|
||||
|
||||
UpdatePosition(a_Delta);
|
||||
|
||||
UpdateFOV(a_Delta);
|
||||
UpdateBobbing(a_Delta);
|
||||
|
||||
move_and_slide();
|
||||
}
|
||||
|
||||
void FirstPersonPlayer::UpdateBobbing(float a_Delta) {
|
||||
m_BobTime += a_Delta * get_velocity().length() * is_on_floor();
|
||||
|
||||
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};
|
||||
|
||||
m_Camera->set_transform({m_Camera->get_transform().basis, newPos});
|
||||
}
|
||||
|
||||
void FirstPersonPlayer::UpdateCamera(const InputEventMouseMotion& a_Event) {
|
||||
m_Head->rotate_y(-a_Event.get_relative().x * SENSITIVITY);
|
||||
m_Camera->rotate_x(-a_Event.get_relative().y * SENSITIVITY);
|
||||
|
||||
float rotationX = m_Camera->get_rotation().x;
|
||||
CLAMP(rotationX, Math::deg_to_rad(-40.0), Math::deg_to_rad(60.0));
|
||||
m_Camera->set_rotation({rotationX, get_rotation().y, get_rotation().z});
|
||||
}
|
||||
|
||||
void FirstPersonPlayer::UpdatePosition(float delta) {
|
||||
auto* Input = Input::get_singleton();
|
||||
|
||||
Vector2 inputDirection = Input->get_vector("move_left", "move_right", "move_forwards", "move_backwards");
|
||||
Vector3 direction = (m_Head->get_transform().basis.xform(Vector3(inputDirection.x, 0, inputDirection.y))).normalized();
|
||||
|
||||
if (is_on_floor()) {
|
||||
if (!direction.is_zero_approx()) {
|
||||
set_velocity({direction.x * m_Speed, get_velocity().y, direction.z * m_Speed});
|
||||
} else {
|
||||
set_velocity({Math::lerp(static_cast<float>(get_velocity().x), static_cast<float>(direction.x * m_Speed),
|
||||
static_cast<float>(delta * GROUND_FRICTION)),
|
||||
get_velocity().y,
|
||||
Math::lerp(static_cast<float>(get_velocity().z), static_cast<float>(direction.z * m_Speed),
|
||||
static_cast<float>(delta * GROUND_FRICTION))});
|
||||
}
|
||||
} else {
|
||||
set_velocity({Math::lerp(static_cast<float>(get_velocity().x), static_cast<float>(direction.x * m_Speed),
|
||||
static_cast<float>(delta * AIR_MOVEMENT)),
|
||||
get_velocity().y,
|
||||
Math::lerp(static_cast<float>(get_velocity().z), static_cast<float>(direction.z * m_Speed),
|
||||
static_cast<float>(delta * AIR_MOVEMENT))});
|
||||
}
|
||||
}
|
||||
|
||||
void FirstPersonPlayer::UpdateFOV(float a_Delta) {
|
||||
float velocityClamped = Math::clamp(get_velocity().length(), MIN_FOV_VELOCITY, MAX_FOV_VELOCITY);
|
||||
float targetFOV = BASE_FOV + FOV_CHANGE * velocityClamped;
|
||||
m_Camera->set_fov(Math::lerp(m_Camera->get_fov(), targetFOV, a_Delta * FOV_TRANSITION));
|
||||
}
|
||||
|
||||
} // namespace blitz
|
||||
36
src/FirstPersonPlayer.h
Normal file
36
src/FirstPersonPlayer.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <godot_cpp/classes/camera3d.hpp>
|
||||
#include <godot_cpp/classes/character_body3d.hpp>
|
||||
#include <godot_cpp/classes/node3d.hpp>
|
||||
#include <godot_cpp/classes/input_event_mouse_motion.hpp>
|
||||
|
||||
namespace blitz {
|
||||
|
||||
class FirstPersonPlayer : public godot::CharacterBody3D {
|
||||
GDCLASS(FirstPersonPlayer, godot::CharacterBody3D)
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
FirstPersonPlayer();
|
||||
~FirstPersonPlayer();
|
||||
|
||||
// Godot overrides
|
||||
void _unhandled_input(const godot::Ref<godot::InputEvent>&);
|
||||
void _physics_process(float delta);
|
||||
void _ready();
|
||||
|
||||
private:
|
||||
godot::Camera3D* m_Camera;
|
||||
godot::Node3D* m_Head;
|
||||
float m_BobTime;
|
||||
float m_Speed;
|
||||
|
||||
void UpdateBobbing(float delta);
|
||||
void UpdateFOV(float delta);
|
||||
void UpdateCamera(const godot::InputEventMouseMotion&);
|
||||
void UpdatePosition(float delta);
|
||||
};
|
||||
|
||||
} // namespace blitz
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Player.h"
|
||||
#include "SpringArmPivot.h"
|
||||
#include "FirstPersonPlayer.h"
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
@@ -16,6 +17,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) {
|
||||
|
||||
ClassDB::register_class<blitz::Player>();
|
||||
ClassDB::register_class<blitz::SpringArmPivot>();
|
||||
ClassDB::register_class<blitz::FirstPersonPlayer>();
|
||||
}
|
||||
|
||||
void uninitialize_example_module(ModuleInitializationLevel p_level) {
|
||||
|
||||
Reference in New Issue
Block a user