Compare commits

18 Commits

Author SHA1 Message Date
Morph01
4fd60e7874 bug animation ??? 2024-08-16 14:19:29 +02:00
Morph01
1662691b6e Better Implementation of Timer 2024-08-16 10:36:32 +02:00
Morph01
91d492c2d8 Bullets Colliding and Disappearing 2024-08-15 13:28:16 +02:00
Morph01
b92c5169c4 LaserGun without collisions 2024-08-14 18:46:31 +02:00
ef0bcd0a35 format
All checks were successful
Linux arm64 / Build (push) Successful in 1m2s
2024-08-13 20:21:05 +02:00
841e25a3ac fix import warnings 2024-08-13 20:02:31 +02:00
a43269910d real FPS 2024-08-13 20:00:21 +02:00
083bf2f04d xmake things 2024-08-13 19:59:33 +02:00
436e9a27c5 Revert "add a testing camera fps (switching cameras by pressing t)"
This reverts commit 4707d85150.
2024-08-13 17:40:57 +02:00
Morph01
4707d85150 add a testing camera fps (switching cameras by pressing t)
All checks were successful
Linux arm64 / Build (push) Successful in 57s
2024-08-13 10:10:31 +02:00
d59047d0ae remove template project tag
All checks were successful
Linux arm64 / Build (push) Successful in 56s
2024-08-12 13:28:25 +02:00
e93afbeaf1 fix warnings 2024-08-12 11:51:33 +02:00
d9aba1924f third persson prototype 2024-08-12 11:45:42 +02:00
ba66b7b3b4 remove icon import file 2024-08-12 11:45:17 +02:00
26b62dbdd7 ignore import files 2024-08-12 11:45:00 +02:00
fb0a4fc7a5 remove gdexample 2024-08-12 11:44:52 +02:00
cdbe8c3114 add debug define 2024-08-12 11:43:02 +02:00
35708456d4 add clang format 2024-08-12 11:42:47 +02:00
57 changed files with 27473 additions and 134 deletions

37
.clang-format Normal file
View File

@@ -0,0 +1,37 @@
Language: Cpp
BasedOnStyle: LLVM
AlignAfterOpenBracket: DontAlign
BreakConstructorInitializers: AfterColon
ConstructorInitializerAllOnOneLineOrOnePerLine: true
PointerAlignment: Left
SortIncludes: true
SpacesBeforeTrailingComments: 2
UseTab: Always
MaxEmptyLinesToKeep: 5
TabWidth: 4
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
IndentWidth: 4
IndentCaseLabels: true
ColumnLimit: 135
AlwaysBreakTemplateDeclarations: Yes
AllowShortFunctionsOnASingleLine: Empty
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true

1
.gitignore vendored
View File

@@ -14,6 +14,7 @@ build/
*.obj
*.lib
*.TMP
*.import
godot/.godot
godot/lib

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,26 @@
[gd_scene load_steps=4 format=3 uid="uid://d38w4ae3qj0k4"]
[ext_resource type="PackedScene" uid="uid://ciex3x7rhv1bx" path="res://Scenes/Weapons/steampunk_rifle.tscn" id="1_i6keg"]
[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)
[node name="Steampunk Rifle" parent="Head/Camera" instance=ExtResource("1_i6keg")]
transform = Transform3D(1, 0, 0, 0, 0.998135, -0.0610485, 0, 0.0610485, 0.998135, 0.19, -0.18, -0.55)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,109 @@
[gd_scene load_steps=20 format=3 uid="uid://coue2qehpn4fr"]
[ext_resource type="Texture2D" uid="uid://dujfl12rge3p4" path="res://Assets/Textures/Sky.png" id="1_mnexj"]
[ext_resource type="Texture2D" uid="uid://b8n5rff2a8h2u" path="res://Assets/Textures/Black.png" id="2_fkwcn"]
[ext_resource type="Texture2D" uid="uid://lpbttkw7gpxj" path="res://Assets/Textures/Orange.png" id="3_ux02w"]
[ext_resource type="Texture2D" uid="uid://di3uyny341483" path="res://Assets/Textures/Green.png" id="4_wp15n"]
[ext_resource type="PackedScene" uid="uid://bcawyy7lmwphr" path="res://Scenes/Characters/zombie.tscn" id="5_4vmh3"]
[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_mnexj")
[sub_resource type="Sky" id="Sky_5ngqa"]
sky_material = SubResource("PanoramaSkyMaterial_6c4vd")
[sub_resource type="Environment" id="Environment_ctwiv"]
background_mode = 2
sky = SubResource("Sky_5ngqa")
tonemap_mode = 2
glow_enabled = true
[sub_resource type="NavigationMesh" id="NavigationMesh_2pdqo"]
vertices = PackedVector3Array(-5.25, 0.5, 1, -5, 0.5, -1.75, -5.5, 0.5, -2, -11.25, 0.5, 1, -5.5, 0.5, -3.75, -3.25, 0.5, -4, -3.25, 0.5, -24.5, -11.25, 0.5, 1, -5.5, 0.5, -2, -5.5, 0.5, -3.75, -24.5, 0.5, 3.25, -11.5, 0.5, 3.25, -11.25, 0.5, 1, -24.5, 0.5, 3.25, -11.25, 0.5, 1, -5.5, 0.5, -3.75, -3.25, 0.5, -24.5, -24.5, 0.5, -24.5, -3.25, 0.5, -4, 3.5, 0.5, -4, 3.5, 0.5, -24.5, -3.25, 0.5, -24.5, 5.5, 0.5, -4, 5.75, 0.5, -3, 24.5, 0.5, -3, 24.5, 0.5, -24.5, 3.5, 0.5, -24.5, 3.5, 0.5, -24.5, 3.5, 0.5, -4, 5.5, 0.5, -4, -5, 0.5, -1.75, -5.25, 0.5, 1, -5, 0.75, 2, 5.25, 0.5, -1.75, -5, 0.75, 2, -7.25, 1.5, 2, -7.25, 1.5, 6, -5, 0.75, 6.25, 24.5, 0.5, -3, 5.75, 0.5, -3, 5.25, 0.5, -1.75, -5.25, 0.5, 7.25, -6.75, 0.5, 7.25, -6.5, 0.5, 24.5, 5.25, 0.5, -1.75, -5, 0.75, 2, -5, 0.75, 6.25, 5.25, 0.5, -1.75, -5, 0.75, 6.25, -5.25, 0.5, 7.25, -6.5, 0.5, 24.5, 24.5, 0.5, 24.5, 24.5, 0.5, -3, -7.25, 1.5, 6, -7.25, 1.5, 2, -14, 3.75, 2, -14, 3.75, 6, -11.5, 0.5, 7, -11.5, 0.5, 3.25, -24.5, 0.5, 3.25, -10, 0.5, 24.5, -9.75, 0.5, 7.25, -11.5, 0.5, 7, -11.5, 0.5, 7, -24.5, 0.5, 3.25, -24.5, 0.5, 24.5, -10, 0.5, 24.5, -10, 0.5, 24.5, -6.5, 0.5, 24.5, -6.75, 0.5, 7.25, -9.75, 0.5, 7.25)
polygons = [PackedInt32Array(1, 0, 2), PackedInt32Array(2, 0, 3), PackedInt32Array(6, 5, 4), PackedInt32Array(7, 9, 8), PackedInt32Array(12, 11, 10), PackedInt32Array(14, 13, 15), PackedInt32Array(15, 13, 16), PackedInt32Array(16, 13, 17), PackedInt32Array(21, 20, 18), PackedInt32Array(18, 20, 19), PackedInt32Array(23, 22, 24), PackedInt32Array(24, 22, 25), PackedInt32Array(25, 22, 26), PackedInt32Array(29, 28, 27), PackedInt32Array(31, 30, 32), PackedInt32Array(32, 30, 33), PackedInt32Array(35, 34, 36), PackedInt32Array(36, 34, 37), PackedInt32Array(40, 39, 38), PackedInt32Array(43, 42, 41), PackedInt32Array(46, 45, 44), PackedInt32Array(48, 47, 49), PackedInt32Array(49, 47, 50), PackedInt32Array(50, 47, 52), PackedInt32Array(50, 52, 51), PackedInt32Array(56, 55, 53), PackedInt32Array(53, 55, 54), PackedInt32Array(59, 58, 57), PackedInt32Array(62, 61, 60), PackedInt32Array(66, 65, 63), PackedInt32Array(63, 65, 64), PackedInt32Array(70, 69, 67), PackedInt32Array(67, 69, 68)]
agent_radius = 0.4
agent_max_slope = 60.0
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ajchh"]
albedo_texture = ExtResource("2_fkwcn")
uv1_triplanar = true
[sub_resource type="PlaneMesh" id="PlaneMesh_mmup0"]
material = SubResource("StandardMaterial3D_ajchh")
size = Vector2(50, 50)
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_26ptr"]
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("3_ux02w")
uv1_triplanar = true
[sub_resource type="BoxMesh" id="BoxMesh_plpqy"]
material = SubResource("StandardMaterial3D_jkvud")
size = Vector3(10, 3, 1)
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_v7prx"]
data = PackedVector3Array(-5, 1.5, 0.5, 5, 1.5, 0.5, -5, -1.5, 0.5, 5, 1.5, 0.5, 5, -1.5, 0.5, -5, -1.5, 0.5, 5, 1.5, -0.5, -5, 1.5, -0.5, 5, -1.5, -0.5, -5, 1.5, -0.5, -5, -1.5, -0.5, 5, -1.5, -0.5, 5, 1.5, 0.5, 5, 1.5, -0.5, 5, -1.5, 0.5, 5, 1.5, -0.5, 5, -1.5, -0.5, 5, -1.5, 0.5, -5, 1.5, -0.5, -5, 1.5, 0.5, -5, -1.5, -0.5, -5, 1.5, 0.5, -5, -1.5, 0.5, -5, -1.5, -0.5, 5, 1.5, 0.5, -5, 1.5, 0.5, 5, 1.5, -0.5, -5, 1.5, 0.5, -5, 1.5, -0.5, 5, 1.5, -0.5, -5, -1.5, 0.5, 5, -1.5, 0.5, -5, -1.5, -0.5, 5, -1.5, 0.5, 5, -1.5, -0.5, -5, -1.5, -0.5)
[sub_resource type="PrismMesh" id="PrismMesh_0l7qq"]
left_to_right = -2.0
size = Vector3(5, 5, 5)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_pfpgv"]
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="World" type="Node3D"]
[node name="Map" type="Node3D" parent="."]
[node name="WorldEnvironment" type="WorldEnvironment" parent="Map"]
environment = SubResource("Environment_ctwiv")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="Map"]
transform = Transform3D(-0.866026, -0.433013, 0.249999, 0.5, -0.750001, 0.433012, -1.3411e-07, 0.499999, 0.866026, 0, 0, 0)
shadow_enabled = true
[node name="NavigationRegion3D" type="NavigationRegion3D" parent="Map"]
navigation_mesh = SubResource("NavigationMesh_2pdqo")
[node name="Floor" type="MeshInstance3D" parent="Map/NavigationRegion3D"]
mesh = SubResource("PlaneMesh_mmup0")
skeleton = NodePath("../../..")
[node name="StaticBody3D" type="StaticBody3D" parent="Map/NavigationRegion3D/Floor"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Map/NavigationRegion3D/Floor/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_26ptr")
[node name="Wall" type="MeshInstance3D" parent="Map/NavigationRegion3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, -3)
mesh = SubResource("BoxMesh_plpqy")
skeleton = NodePath("../../..")
[node name="StaticBody3D" type="StaticBody3D" parent="Map/NavigationRegion3D/Wall"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Map/NavigationRegion3D/Wall/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_v7prx")
[node name="Slope" type="MeshInstance3D" parent="Map/NavigationRegion3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 1, 4)
mesh = SubResource("PrismMesh_0l7qq")
skeleton = NodePath("../../..")
surface_material_override/0 = SubResource("StandardMaterial3D_pfpgv")
[node name="StaticBody3D" type="StaticBody3D" parent="Map/NavigationRegion3D/Slope"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Map/NavigationRegion3D/Slope/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_rit6o")
[node name="zombie" parent="Map" instance=ExtResource("5_4vmh3")]
m_PlayerPath = NodePath("../../FirstPersonPlayer")
transform = Transform3D(-0.98774, 0, -0.156107, 0, 1, 0, 0.156107, 0, -0.98774, 0, 0, 7.38477)
[node name="FirstPersonPlayer" parent="." instance=ExtResource("5_8ctht")]

View File

@@ -0,0 +1,51 @@
[gd_scene load_steps=6 format=3 uid="uid://do601jl7p1u22"]
[sub_resource type="BoxMesh" id="BoxMesh_ibwn0"]
size = Vector3(0.05, 0.05, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2qdhl"]
albedo_color = Color(1, 0.764706, 0.294118, 1)
emission_enabled = true
emission = Color(0.568627, 1, 0.313726, 1)
emission_energy_multiplier = 5.0
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_618v8"]
direction = Vector3(0, 0, 1)
initial_velocity_min = 3.0
initial_velocity_max = 5.0
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_gn2fy"]
albedo_color = Color(1, 1, 0.443137, 1)
emission_enabled = true
emission = Color(0.568627, 1, 0.313726, 1)
emission_energy_multiplier = 8.0
[sub_resource type="BoxMesh" id="BoxMesh_5un5e"]
material = SubResource("StandardMaterial3D_gn2fy")
size = Vector3(0.04, 0.04, 0.04)
[node name="Bullet" type="Bullet"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -52730.2)
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_ibwn0")
surface_material_override/0 = SubResource("StandardMaterial3D_2qdhl")
[node name="RayCast3D" type="RayCast3D" parent="."]
target_position = Vector3(0, 0, -0.6)
[node name="GPUParticles3D" type="GPUParticles3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.7)
emitting = false
one_shot = true
explosiveness = 1.0
visibility_aabb = AABB(-1.00001, -6.06334, -1.00001, 2.00002, 7.06267, 41.4102)
process_material = SubResource("ParticleProcessMaterial_618v8")
draw_pass_1 = SubResource("BoxMesh_5un5e")
[node name="Timer" type="Timer" parent="."]
wait_time = 10.0
one_shot = true
autostart = true
[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"]

View File

@@ -0,0 +1,36 @@
[gd_scene load_steps=4 format=3 uid="uid://ciex3x7rhv1bx"]
[ext_resource type="PackedScene" uid="uid://bkskefixbe2cw" path="res://Assets/Models/Weapons/Steampunk Rifle.glb" id="1_0bnv5"]
[sub_resource type="Animation" id="Animation_20uwx"]
resource_name = "Shoot"
length = 0.1
step = 0.01
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Node:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.01, 0.1),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector3(0, 0, 0), Vector3(0, 0, 0.05), Vector3(0, 0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_113bo"]
_data = {
"Shoot": SubResource("Animation_20uwx")
}
[node name="Steampunk Rifle" instance=ExtResource("1_0bnv5")]
[node name="AnimationPlayer" type="AnimationPlayer" parent="." index="1"]
libraries = {
"": SubResource("AnimationLibrary_113bo")
}
[node name="RayCast3D" type="RayCast3D" parent="." index="2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1.10108)
target_position = Vector3(0, 0, -1)

View File

@@ -0,0 +1,63 @@
extends CharacterBody3D
const LERP_VALUE : float = 0.15
var snap_vector : Vector3 = Vector3.DOWN
var speed : float
@export_group("Movement variables")
@export var walk_speed : float = 2.0
@export var run_speed : float = 5.0
@export var jump_strength : float = 15.0
@export var gravity : float = 50.0
const ANIMATION_BLEND : float = 7.0
@onready var player_mesh : Node3D = $Mesh
@onready var spring_arm_pivot : Node3D = $SpringArmPivot
@onready var animator : AnimationTree = $AnimationTree
func _physics_process(delta):
var move_direction : Vector3 = Vector3.ZERO
move_direction.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
move_direction.z = Input.get_action_strength("move_backwards") - Input.get_action_strength("move_forwards")
move_direction = move_direction.rotated(Vector3.UP, spring_arm_pivot.rotation.y)
velocity.y -= gravity * delta
if Input.is_action_pressed("run"):
speed = run_speed
else:
speed = walk_speed
velocity.x = move_direction.x * speed
velocity.z = move_direction.z * speed
if move_direction:
player_mesh.rotation.y = lerp_angle(player_mesh.rotation.y, atan2(velocity.x, velocity.z), LERP_VALUE)
var just_landed := is_on_floor() and snap_vector == Vector3.ZERO
var is_jumping := is_on_floor() and Input.is_action_just_pressed("jump")
if is_jumping:
velocity.y = jump_strength
snap_vector = Vector3.ZERO
elif just_landed:
snap_vector = Vector3.DOWN
apply_floor_snap()
move_and_slide()
animate(delta)
func animate(delta):
if is_on_floor():
animator.set("parameters/ground_air_transition/transition_request", "grounded")
if velocity.length() > 0:
if speed == run_speed:
animator.set("parameters/iwr_blend/blend_amount", lerp(animator.get("parameters/iwr_blend/blend_amount"), 1.0, delta * ANIMATION_BLEND))
else:
animator.set("parameters/iwr_blend/blend_amount", lerp(animator.get("parameters/iwr_blend/blend_amount"), 0.0, delta * ANIMATION_BLEND))
else:
animator.set("parameters/iwr_blend/blend_amount", lerp(animator.get("parameters/iwr_blend/blend_amount"), -1.0, delta * ANIMATION_BLEND))
else:
animator.set("parameters/ground_air_transition/transition_request", "air")

View File

@@ -0,0 +1,30 @@
extends Node3D
@export_group("FOV")
@export var change_fov_on_run : bool
@export var normal_fov : float = 75.0
@export var run_fov : float = 90.0
const CAMERA_BLEND : float = 0.05
@onready var spring_arm : SpringArm3D = $SpringArm3D
@onready var camera : Camera3D = $SpringArm3D/Camera3D
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _unhandled_input(event):
if event is InputEventMouseMotion:
rotate_y(-event.relative.x * 0.005)
spring_arm.rotate_x(-event.relative.y * 0.005)
spring_arm.rotation.x = clamp(spring_arm.rotation.x, -PI/4, PI/4)
func _physics_process(_delta):
if change_fov_on_run:
if owner.is_on_floor():
if Input.is_action_pressed("run"):
camera.fov = lerp(camera.fov, run_fov, CAMERA_BLEND)
else:
camera.fov = lerp(camera.fov, normal_fov, CAMERA_BLEND)
else:
camera.fov = lerp(camera.fov, normal_fov, CAMERA_BLEND)

19
godot/bullet.tscn Normal file
View File

@@ -0,0 +1,19 @@
[gd_scene load_steps=3 format=3 uid="uid://bt0551kcc5tw4"]
[sub_resource type="BoxMesh" id="BoxMesh_ibwn0"]
size = Vector3(0.05, 0.05, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2qdhl"]
albedo_color = Color(1, 0.764706, 0.294118, 1)
emission_enabled = true
emission = Color(0.568627, 1, 0.313726, 1)
emission_energy_multiplier = 5.0
[node name="Bullet" type="Bullet"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_ibwn0")
surface_material_override/0 = SubResource("StandardMaterial3D_2qdhl")
[node name="RayCast3D" type="RayCast3D" parent="."]
target_position = Vector3(0, 0, -0.6)

View File

@@ -1 +1 @@
<svg height="128" width="128" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="124" height="124" rx="14" fill="#363d52" stroke="#212532" stroke-width="4"/><g transform="scale(.101) translate(122 122)"><g fill="#fff"><path d="M105 673v33q407 354 814 0v-33z"/><path d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z" fill="#478cbf"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></g></svg>
<svg height="128" width="128" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="124" height="124" rx="14" fill="#363d52" stroke="#212532" stroke-width="4"/><g transform="scale(.101) translate(122 122)"><g fill="#fff"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 813 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H447l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c3 34 55 34 58 0v-86c-3-34-55-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 949 B

After

Width:  |  Height:  |  Size: 950 B

View File

@@ -1,37 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cuend5rtkhbnp"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -1,10 +0,0 @@
[gd_scene load_steps=2 format=3 uid="uid://uiwigxsdnci1"]
[ext_resource type="Texture2D" uid="uid://cuend5rtkhbnp" path="res://icon.svg" id="1_q81dj"]
[node name="Node2D" type="Node2D"]
[node name="GDExample" type="GDExample" parent="."]
position = Vector2(5.20978, 6.34048)
texture = ExtResource("1_q81dj")
centered = false

View File

@@ -11,6 +11,49 @@ config_version=5
[application]
config/name="Blitz3"
run/main_scene="res://main.tscn"
run/main_scene="res://Scenes/Levels/world.tscn"
config/features=PackedStringArray("4.2", "Forward Plus")
config/icon="res://icon.svg"
[input]
move_left={
"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":65,"key_label":0,"unicode":97,"echo":false,"script":null)
]
}
move_right={
"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":68,"key_label":0,"unicode":100,"echo":false,"script":null)
]
}
move_forwards={
"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":87,"key_label":0,"unicode":119,"echo":false,"script":null)
]
}
move_backwards={
"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":83,"key_label":0,"unicode":115,"echo":false,"script":null)
]
}
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)
]
}
jump={
"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":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":-1,"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)
]
}
shoot={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(351, 9),"global_position":Vector2(355, 50),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
]
}

45
src/Bullet.cpp Normal file
View File

@@ -0,0 +1,45 @@
#include "Bullet.h"
using namespace godot;
namespace blitz {
static constexpr float BULLET_SPEED = 40.0f;
void Bullet::_bind_methods() {
ClassDB::bind_method(D_METHOD("_on_timer_timeout"), &Bullet::_on_timer_timeout);
}
Bullet::Bullet() {}
Bullet::~Bullet() {}
void Bullet::_ready() {
m_Particles = Object::cast_to<GPUParticles3D>(find_child("GPUParticles3D"));
DEV_ASSERT(m_Particles);
m_Ray = Object::cast_to<RayCast3D>(find_child("RayCast3D"));
DEV_ASSERT(m_Ray);
m_Mesh = Object::cast_to<MeshInstance3D>(find_child("MeshInstance3D"));
DEV_ASSERT(m_Mesh);
m_Timer = memnew(godot::Timer);
add_child(m_Timer);
m_Timer->connect("timeout", callable_mp(this, &Bullet::_on_timer_timeout));
}
void Bullet::_physics_process(float a_Delta) {
Vector3 movement = Vector3(0, 0, -BULLET_SPEED) * a_Delta;
set_position(get_transform().xform(movement));
if (m_Ray->is_colliding()) {
m_Mesh->set_visible(false);
m_Particles->set_emitting(true);
m_Timer->set_wait_time(1.0);
m_Timer->start();
}
}
void Bullet::_on_timer_timeout() {
queue_free();
}
} // namespace blitz

31
src/Bullet.h Normal file
View File

@@ -0,0 +1,31 @@
#pragma once
#include <godot_cpp/classes/gpu_particles3d.hpp>
#include <godot_cpp/classes/mesh_instance3d.hpp>
#include <godot_cpp/classes/node3d.hpp>
#include <godot_cpp/classes/ray_cast3d.hpp>
#include <godot_cpp/classes/timer.hpp>
namespace blitz {
class Bullet : public godot::Node3D {
GDCLASS(Bullet, godot::Node3D)
protected:
static void _bind_methods();
public:
Bullet();
~Bullet();
void _ready();
void _physics_process(float delta);
private:
godot::GPUParticles3D* m_Particles;
godot::RayCast3D* m_Ray;
godot::MeshInstance3D* m_Mesh;
godot::Timer* m_Timer;
void _on_timer_timeout();
};
} // namespace blitz

159
src/FirstPersonPlayer.cpp Normal file
View File

@@ -0,0 +1,159 @@
#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/classes/resource_loader.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);
m_WeaponAnimation = Object::cast_to<AnimationPlayer>(find_child("AnimationPlayer"));
DEV_ASSERT(m_WeaponAnimation);
m_GunBarrel = Object::cast_to<RayCast3D>(find_child("RayCast3D"));
DEV_ASSERT(m_GunBarrel);
m_BulletScene = ResourceLoader::get_singleton()->load("res://Scenes/Weapons/bullet.tscn");
if (!m_BulletScene.is_valid()) {
ERR_PRINT("Failed to load bullet scene.");
}
}
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);
if (Input->is_action_pressed("shoot")) {
if (!m_WeaponAnimation->is_playing()) {
m_WeaponAnimation->play("Shoot");
m_BulletInstance = m_BulletScene->instantiate();
m_BulletInstance->set("position", m_GunBarrel->get_global_transform().origin);
m_BulletInstance->set("rotation", m_GunBarrel->get_global_transform().basis.get_euler());
get_parent()->add_child(m_BulletInstance);
}
}
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

44
src/FirstPersonPlayer.h Normal file
View File

@@ -0,0 +1,44 @@
#pragma once
#include <godot_cpp/classes/animation_player.hpp>
#include <godot_cpp/classes/camera3d.hpp>
#include <godot_cpp/classes/character_body3d.hpp>
#include <godot_cpp/classes/input_event_mouse_motion.hpp>
#include <godot_cpp/classes/node3d.hpp>
#include <godot_cpp/classes/packed_scene.hpp>
#include <godot_cpp/classes/ray_cast3d.hpp>
#include <godot_cpp/classes/ref.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;
godot::AnimationPlayer* m_WeaponAnimation;
godot::RayCast3D* m_GunBarrel;
godot::Node* m_BulletInstance;
godot::Ref<godot::PackedScene> m_BulletScene;
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

111
src/Player.cpp Normal file
View File

@@ -0,0 +1,111 @@
#include "Player.h"
#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/classes/input.hpp>
#include <godot_cpp/classes/input_map.hpp>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
static const float WalkSpeed = 2.0;
static const float RunSpeed = 5.0;
static const float JumpStrength = 15.0;
static const float Gravity = 50.0;
static const float LerpValue = 0.15;
static const float AnimationBlend = 7.0;
namespace blitz {
void Player::_bind_methods() {}
Player::Player() {}
Player::~Player() {}
void Player::_ready() {
godot::InputMap::get_singleton()->load_from_project_settings();
m_PlayerMesh = Object::cast_to<godot::Node3D>(get_child(0));
m_SpringArmPivot = Object::cast_to<godot::Node3D>(get_child(2));
m_AnimationTree = Object::cast_to<godot::AnimationTree>(get_child(4));
DEV_ASSERT(m_PlayerMesh);
DEV_ASSERT(m_SpringArmPivot);
DEV_ASSERT(m_AnimationTree);
apply_floor_snap();
animate(0);
}
void Player::_physics_process(float delta) {
if (godot::Engine::get_singleton()->is_editor_hint())
return;
auto* Input = godot::Input::get_singleton();
godot::Vector3 move_direction{0, 0, 0};
move_direction.x = Input->get_action_strength("move_right") - Input->get_action_strength("move_left");
move_direction.z = Input->get_action_strength("move_backwards") - Input->get_action_strength("move_forwards");
move_direction = move_direction.rotated({0, 1, 0}, m_SpringArmPivot->get_rotation().y);
godot::Vector3 newVelocity = get_velocity();
newVelocity.y -= Gravity * delta;
set_velocity(newVelocity);
if (Input->is_action_pressed("run"))
m_Speed = RunSpeed;
else
m_Speed = WalkSpeed;
newVelocity = get_velocity();
newVelocity.x = move_direction.x * m_Speed;
newVelocity.z = move_direction.z * m_Speed;
set_velocity(newVelocity);
if (move_direction != godot::Vector3{0, 0, 0}) {
godot::Vector3 newRotation = m_PlayerMesh->get_rotation();
newRotation.y = godot::UtilityFunctions::lerp_angle(
newRotation.y, godot::UtilityFunctions::atan2(get_velocity().x, get_velocity().z), LerpValue);
m_PlayerMesh->set_rotation(newRotation);
}
bool justLanded = is_on_floor() && m_SnapVector == godot::Vector3{0, 0, 0};
bool isJumping = is_on_floor() && Input->is_action_just_pressed("jump");
if (isJumping) {
newVelocity = get_velocity();
newVelocity.y = JumpStrength;
set_velocity(newVelocity);
m_SnapVector.zero();
} else if (justLanded) {
m_SnapVector = {0, -1, 0};
}
apply_floor_snap();
move_and_slide();
animate(delta);
}
void Player::animate(float delta) {
if (is_on_floor()) {
m_AnimationTree->set("parameters/ground_air_transition/transition_request", "grounded");
if (get_velocity().length() > 0) {
if (m_Speed == RunSpeed) {
m_AnimationTree->set("parameters/iwr_blend/blend_amount",
godot::UtilityFunctions::lerp(
m_AnimationTree->get("parameters/iwr_blend/blend_amount"), 1.0, delta * AnimationBlend));
} else {
m_AnimationTree->set("parameters/iwr_blend/blend_amount",
godot::UtilityFunctions::lerp(
m_AnimationTree->get("parameters/iwr_blend/blend_amount"), 0.0, delta * AnimationBlend));
}
} else {
m_AnimationTree->set("parameters/iwr_blend/blend_amount",
godot::UtilityFunctions::lerp(
m_AnimationTree->get("parameters/iwr_blend/blend_amount"), -1.0, delta * AnimationBlend));
}
} else {
m_AnimationTree->set("parameters/ground_air_transition/transition_request", "air");
}
}
} // namespace blitz

37
src/Player.h Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include <godot_cpp/classes/animation_tree.hpp>
#include <godot_cpp/classes/character_body3d.hpp>
#include <godot_cpp/classes/node3d.hpp>
namespace blitz {
class Player : public godot::CharacterBody3D {
GDCLASS(Player, godot::CharacterBody3D);
protected:
static void _bind_methods();
public:
Player();
~Player();
void _ready();
void _physics_process(float delta);
void animate(float delta);
private:
godot::Node3D* m_PlayerMesh;
godot::Node3D* m_SpringArmPivot;
godot::AnimationTree* m_AnimationTree;
godot::Vector3 m_SnapVector;
float m_Speed;
/*
@onready var player_mesh : Node3D = $Mesh
@onready var spring_arm_pivot : Node3D = $SpringArmPivot
@onready var animator : AnimationTree = $AnimationTree
*/
};
} // namespace blitz

65
src/SpringArmPivot.cpp Normal file
View File

@@ -0,0 +1,65 @@
#include "SpringArmPivot.h"
#include "Player.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/spring_arm3d.hpp>
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
static const float NormalFov = 75.0;
static const float RunFov = 90.0;
static const float CameraBlend = 0.05;
namespace blitz {
void SpringArmPivot::_bind_methods() {
godot::ClassDB::bind_method(godot::D_METHOD("get_dynfov"), &SpringArmPivot::IsFovDynamic);
godot::ClassDB::bind_method(godot::D_METHOD("set_dynfov", "dynamic_fov"), &SpringArmPivot::SetDynamicFov);
ADD_PROPERTY(godot::PropertyInfo(godot::Variant::BOOL, "dynamic_fov"), "set_dynfov", "get_dynfov");
}
SpringArmPivot::SpringArmPivot() {}
SpringArmPivot::~SpringArmPivot() {}
void SpringArmPivot::_ready() {
m_SpringArm = Object::cast_to<godot::SpringArm3D>(get_child(0));
m_Camera = Object::cast_to<godot::Camera3D>(m_SpringArm->get_child(0));
DEV_ASSERT(m_SpringArm);
DEV_ASSERT(m_Camera);
if (!godot::Engine::get_singleton()->is_editor_hint()) {
godot::Input::get_singleton()->set_mouse_mode(godot::Input::MOUSE_MODE_CAPTURED);
}
}
void SpringArmPivot::_unhandled_input(const godot::Ref<godot::InputEvent>& p_event) {
auto* event = Object::cast_to<godot::InputEventMouseMotion>(p_event.ptr());
if (event) {
rotate_y(-event->get_relative().x * 0.005);
m_SpringArm->rotate_x(-event->get_relative().y * 0.005);
godot::Vector3 rotationClamped = m_SpringArm->get_rotation();
rotationClamped.x = godot::UtilityFunctions::clamp(rotationClamped.x, -Math_PI / 4, Math_PI / 4);
m_SpringArm->set_rotation(rotationClamped);
}
}
void SpringArmPivot::_physics_process(float delta) {
if (m_DynamicFOV) {
auto* parent = Object::cast_to<Player>(get_owner());
if (parent->is_on_floor()) {
if (godot::Input::get_singleton()->is_action_pressed("run")) {
m_Camera->set_fov(godot::UtilityFunctions::lerp(m_Camera->get_fov(), RunFov, CameraBlend));
} else {
m_Camera->set_fov(godot::UtilityFunctions::lerp(m_Camera->get_fov(), NormalFov, CameraBlend));
}
} else {
m_Camera->set_fov(godot::UtilityFunctions::lerp(m_Camera->get_fov(), NormalFov, CameraBlend));
}
}
}
} // namespace blitz

38
src/SpringArmPivot.h Normal file
View File

@@ -0,0 +1,38 @@
#pragma once
#include <godot_cpp/classes/input_event.hpp>
#include <godot_cpp/classes/node3d.hpp>
#include <godot_cpp/classes/spring_arm3d.hpp>
#include <godot_cpp/classes/camera3d.hpp>
namespace blitz {
class SpringArmPivot : public godot::Node3D {
GDCLASS(SpringArmPivot, godot::Node3D);
protected:
static void _bind_methods();
public:
SpringArmPivot();
~SpringArmPivot();
void _ready();
void _unhandled_input(const godot::Ref<godot::InputEvent>& p_event);
void _physics_process(float delta);
void SetDynamicFov(bool fov) {
m_DynamicFOV = fov;
}
bool IsFovDynamic() const {
return m_DynamicFOV;
}
private:
godot::SpringArm3D* m_SpringArm;
godot::Camera3D* m_Camera;
bool m_DynamicFOV = false;
};
} // namespace blitz

60
src/Zombie.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include "Zombie.h"
#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
using namespace godot;
namespace blitz {
static constexpr float SPEED = 2.0f;
void Zombie::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_m_PlayerPath", "m_PlayerPath"), &Zombie::set_m_PlayerPath);
ClassDB::bind_method(D_METHOD("get_m_PlayerPath"), &Zombie::get_m_PlayerPath);
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "m_PlayerPath"), "set_m_PlayerPath", "get_m_PlayerPath");
}
Zombie::Zombie() {}
Zombie::~Zombie() {}
void Zombie::_ready() {
#if DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
#endif
m_Player = Object::cast_to<FirstPersonPlayer>(get_parent()->get_parent()->find_child("FirstPersonPlayer"));
DEV_ASSERT(m_Player);
m_NavigationAgent = Object::cast_to<NavigationAgent3D>(find_child("NavigationAgent3D"));
DEV_ASSERT(m_NavigationAgent);
m_Velocity = Vector3(0, 0, 0);
}
void Zombie::_process(float a_Delta) {
#if DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
#endif
this->set_velocity(m_Velocity);
m_NavigationAgent->set_target_position(m_Player->get_global_position());
Vector3 next_nav_point = m_NavigationAgent->get_next_path_position();
m_Velocity = (next_nav_point - get_global_position()).normalized() * SPEED;
this->set_velocity(m_Velocity);
look_at(Vector3(m_Player->get_global_position().x, get_global_position().y, m_Player->get_global_position().z), Vector3(0, 1, 0));
move_and_slide();
}
void Zombie::set_m_PlayerPath(const NodePath& path) {
m_PlayerPath = path;
}
NodePath Zombie::get_m_PlayerPath() const {
return m_PlayerPath;
}
} // namespace blitz

33
src/Zombie.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include <godot_cpp/classes/character_body3d.hpp>
#include <godot_cpp/classes/navigation_agent3d.hpp>
#include <godot_cpp/variant/node_path.hpp>
#include "FirstPersonPlayer.h"
namespace blitz {
class Zombie : public godot::CharacterBody3D {
GDCLASS(Zombie, godot::CharacterBody3D)
protected:
static void _bind_methods();
public:
Zombie();
~Zombie();
void _ready();
void _process(float delta);
private:
godot::NavigationAgent3D* m_NavigationAgent;
FirstPersonPlayer* m_Player;
godot::NodePath m_PlayerPath;
godot::Vector3 m_Velocity;
void set_m_PlayerPath(const godot::NodePath& path);
godot::NodePath get_m_PlayerPath() const;
};
} // namespace blitz

View File

@@ -1,28 +0,0 @@
#include "gdexample.h"
#include <godot_cpp/core/class_db.hpp>
using namespace godot;
void GDExample::_bind_methods() {
// ClassDB::bind_method(D_METHOD("_process", "delta"), &GDExample::_process);
}
GDExample::GDExample()
{
time_passed = 0.0;
}
GDExample::~GDExample() {}
void GDExample::_process(float delta)
{
time_passed += delta;
auto new_position = Vector2(
10.0 + (10.0 * sin(time_passed * 2.0)),
10.0 + (10.0 * cos(time_passed * 1.5)));
set_position(new_position);
}

View File

@@ -1,24 +0,0 @@
#ifndef GDEXAMPLE_H
#define GDEXAMPLE_H
#include <godot_cpp/classes/sprite2d.hpp>
namespace godot
{
class GDExample : public Sprite2D
{
GDCLASS(GDExample, Sprite2D)
private:
double time_passed;
protected:
static void _bind_methods();
public:
GDExample();
~GDExample();
void _process(float delta);
};
}
#endif

View File

@@ -1,6 +1,10 @@
#include "register_types.h"
#include "gdexample.h"
#include "Bullet.h"
#include "FirstPersonPlayer.h"
#include "Player.h"
#include "SpringArmPivot.h"
#include "Zombie.h"
#include <gdextension_interface.h>
#include <godot_cpp/core/defs.hpp>
@@ -8,37 +12,31 @@
using namespace godot;
void initialize_example_module(ModuleInitializationLevel p_level)
{
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE)
{
return;
}
void initialize_example_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
ClassDB::register_class<GDExample>();
ClassDB::register_class<blitz::Player>();
ClassDB::register_class<blitz::SpringArmPivot>();
ClassDB::register_class<blitz::FirstPersonPlayer>();
ClassDB::register_class<blitz::Bullet>();
ClassDB::register_class<blitz::Zombie>();
}
void uninitialize_example_module(ModuleInitializationLevel p_level)
{
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE)
{
return;
}
void uninitialize_example_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
}
extern "C"
{
GDExtensionBool GDE_EXPORT library_init(
GDExtensionInterfaceGetProcAddress p_get_proc,
const GDExtensionClassLibraryPtr p_library,
GDExtensionInitialization *r_initialization)
{
godot::GDExtensionBinding::InitObject init_obj(p_get_proc, p_library, r_initialization);
extern "C" GDExtensionBool GDE_EXPORT library_init(GDExtensionInterfaceGetProcAddress p_get_proc,
const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization* r_initialization) {
godot::GDExtensionBinding::InitObject init_obj(p_get_proc, p_library, r_initialization);
init_obj.register_initializer(initialize_example_module);
init_obj.register_terminator(uninitialize_example_module);
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
init_obj.register_initializer(initialize_example_module);
init_obj.register_terminator(uninitialize_example_module);
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
return init_obj.init();
}
}
return init_obj.init();
}

View File

@@ -1,3 +1,9 @@
if is_mode("debug") then
add_defines("DEBUG_ENABLED")
end
-- more on https://xmake.io/#/manual/project_target
target(PROJECT_NAME)
set_kind("shared")
@@ -35,8 +41,9 @@ target(PROJECT_NAME)
on_run(
(function(godot_project_folder)
return function(target)
os.execv("echo", {"godot --path", godot_project_folder})
os.exec("godot --path " .. godot_project_folder)
local cmd = format("godot --path %s", godot_project_folder)
os.execv("echo", {cmd})
os.exec(cmd)
end
end)(GODOT_PROJECT_FOLDER)
)

View File

@@ -6,7 +6,7 @@
-- target_platform: the target platform, like "Windows Desktop"
-- name: the export execute name, it will be endswith ".exe" on windows
task("export")
on_run((function(godot_project_folder, publish_folder, project_name)
on_run((function(godot_project_folder, publish_folder, project_name)
return function(target_platform)
local name = godot_project_folder
@@ -37,8 +37,10 @@ task("export")
local export_path = path.absolute(path.join(publish_folder, project_name))
os.execv("echo", {"godot", godot_project_file, export_mode, target_platform, export_path})
os.exec("godot %s --headless --%s %s %s", godot_project_file, export_mode, "\"" .. target_platform .. "\"", export_path)
local cmd = format("godot %s --headless --%s %s %s", godot_project_file, export_mode, "\"" .. target_platform .. "\"", export_path)
os.execv("echo", {cmd})
os.exec(cmd)
end
end)(GODOT_PROJECT_FOLDER, PUBLISH_FOLDER, PROJECT_NAME))
@@ -202,3 +204,22 @@ android.release.arm64 = "res://lib/libProjectName.android_release_arm64.so"
description = "Generate gdextension file",
}
task_end()
task("import-assets")
on_run((function(godot_project_folder, project_name)
return function ()
local godot_project_file = path.join(godot_project_folder, "project.godot")
local cmd = format("godot --headless --import %s", godot_project_file)
os.execv("echo", {cmd})
os.exec(cmd)
end
end)(GODOT_PROJECT_FOLDER, PROJECT_NAME))
set_menu {
usage = "xmake import-assets",
description = "Import project assets",
}
task_end()