Skip to content

Commit a93236a

Browse files
committed
Add 3D physics interpolation demo
Demonstrate first person shooter and third person shooter cameras.
1 parent 0d6b772 commit a93236a

15 files changed

+578
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8

3d/physics_interpolation_3d/box.tscn

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[gd_scene load_steps=4 format=3 uid="uid://cvgxw8nq67xxm"]
2+
3+
[sub_resource type="BoxShape3D" id="BoxShape3D_pq8q7"]
4+
5+
[sub_resource type="BoxMesh" id="BoxMesh_pyidc"]
6+
7+
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_oq5cr"]
8+
albedo_color = Color(0.5544661, 0.39379695, 0.15444939, 1)
9+
10+
[node name="Box" type="RigidBody3D"]
11+
mass = 10.0
12+
13+
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
14+
shape = SubResource("BoxShape3D_pq8q7")
15+
16+
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
17+
mesh = SubResource("BoxMesh_pyidc")
18+
surface_material_override/0 = SubResource("StandardMaterial3D_oq5cr")

3d/physics_interpolation_3d/bullet.gd

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
extends RigidBody3D
2+
3+
const _appearance_life = 1
4+
const _max_life = 100
5+
var _life = 0
6+
var _enabled = false
7+
8+
func _ready() -> void:
9+
$CollisionShape3D.disabled = true
10+
11+
func _physics_process(_delta: float) -> void:
12+
if !_enabled:
13+
$CollisionShape3D.disabled = false
14+
_enabled = true
15+
16+
17+
_life += 1
18+
19+
var life_left = _max_life - _life
20+
21+
var appearance_fract = min(float (_life) / float (_appearance_life), 1.0)
22+
var fract = float (life_left) / float (_max_life)
23+
fract *= appearance_fract
24+
25+
fract = max(fract, 0.0001)
26+
27+
$Scaler.scale = Vector3(fract, fract, fract)
28+
29+
if _life >= _max_life:
30+
queue_free()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
uid://dohdjr8ilotkr
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[gd_scene load_steps=12 format=3 uid="uid://2r5wc1n0ybju"]
2+
3+
[ext_resource type="Script" uid="uid://dohdjr8ilotkr" path="res://bullet.gd" id="1_v7oki"]
4+
[ext_resource type="Texture2D" uid="uid://b70s43gn8c3kx" path="res://spark_particle2.png" id="2_v8qja"]
5+
6+
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_v8qja"]
7+
bounce = 0.61
8+
9+
[sub_resource type="SphereShape3D" id="SphereShape3D_rtl8c"]
10+
radius = 0.2
11+
12+
[sub_resource type="Gradient" id="Gradient_v8qja"]
13+
14+
[sub_resource type="GradientTexture1D" id="GradientTexture1D_t4vbm"]
15+
gradient = SubResource("Gradient_v8qja")
16+
17+
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_v7oki"]
18+
direction = Vector3(0, 1, 0)
19+
initial_velocity_max = 1.0
20+
gravity = Vector3(0, 1, 0)
21+
scale_min = 0.19999999
22+
color_ramp = SubResource("GradientTexture1D_t4vbm")
23+
24+
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_t4vbm"]
25+
transparency = 1
26+
albedo_texture = ExtResource("2_v8qja")
27+
28+
[sub_resource type="QuadMesh" id="QuadMesh_rtl8c"]
29+
material = SubResource("StandardMaterial3D_t4vbm")
30+
size = Vector2(0.2, 0.2)
31+
32+
[sub_resource type="SphereMesh" id="SphereMesh_v7oki"]
33+
34+
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_v7oki"]
35+
albedo_color = Color(0.43164876, 0.5731902, 0.5013925, 1)
36+
metallic = 1.0
37+
38+
[node name="Bullet" type="RigidBody3D"]
39+
physics_material_override = SubResource("PhysicsMaterial_v8qja")
40+
script = ExtResource("1_v7oki")
41+
42+
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
43+
shape = SubResource("SphereShape3D_rtl8c")
44+
45+
[node name="GPUParticles3D" type="GPUParticles3D" parent="."]
46+
transform_align = 1
47+
process_material = SubResource("ParticleProcessMaterial_v7oki")
48+
draw_pass_1 = SubResource("QuadMesh_rtl8c")
49+
50+
[node name="Scaler" type="Node3D" parent="."]
51+
transform = Transform3D(0.001, 0, 0, 0, 0.001, 0, 0, 0, 0.001, 0, 0, 0)
52+
53+
[node name="MeshInstance3D" type="MeshInstance3D" parent="Scaler"]
54+
transform = Transform3D(0.4, 0, 0, 0, 0.4, 0, 0, 0, 0.4, 0, 0, 0)
55+
mesh = SubResource("SphereMesh_v7oki")
56+
skeleton = NodePath("../..")
57+
surface_material_override/0 = SubResource("StandardMaterial3D_v7oki")
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://c5avn6uhdr88"
6+
path.s3tc="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.s3tc.ctex"
7+
metadata={
8+
"imported_formats": ["s3tc_bptc"],
9+
"vram_texture": true
10+
}
11+
12+
[deps]
13+
14+
source_file="res://icon.png"
15+
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.s3tc.ctex"]
16+
17+
[params]
18+
19+
compress/mode=2
20+
compress/high_quality=false
21+
compress/lossy_quality=0.7
22+
compress/uastc_level=0
23+
compress/rdo_quality_loss=0.0
24+
compress/hdr_compression=1
25+
compress/normal_map=0
26+
compress/channel_pack=0
27+
mipmaps/generate=true
28+
mipmaps/limit=-1
29+
roughness/mode=0
30+
roughness/src_normal=""
31+
process/channel_remap/red=0
32+
process/channel_remap/green=1
33+
process/channel_remap/blue=2
34+
process/channel_remap/alpha=3
35+
process/fix_alpha_border=true
36+
process/premult_alpha=false
37+
process/normal_map_invert_y=false
38+
process/hdr_as_srgb=false
39+
process/hdr_clamp_exposure=false
40+
process/size_limit=0
41+
detect_3d/compress_to=0

3d/physics_interpolation_3d/icon.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[remap]
2+
3+
importer="texture"
4+
type="CompressedTexture2D"
5+
uid="uid://cb05v27t8vx5t"
6+
path.s3tc="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.s3tc.ctex"
7+
metadata={
8+
"imported_formats": ["s3tc_bptc"],
9+
"vram_texture": true
10+
}
11+
12+
[deps]
13+
14+
source_file="res://icon.svg"
15+
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.s3tc.ctex"]
16+
17+
[params]
18+
19+
compress/mode=2
20+
compress/high_quality=false
21+
compress/lossy_quality=0.7
22+
compress/uastc_level=0
23+
compress/rdo_quality_loss=0.0
24+
compress/hdr_compression=1
25+
compress/normal_map=0
26+
compress/channel_pack=0
27+
mipmaps/generate=true
28+
mipmaps/limit=-1
29+
roughness/mode=0
30+
roughness/src_normal=""
31+
process/channel_remap/red=0
32+
process/channel_remap/green=1
33+
process/channel_remap/blue=2
34+
process/channel_remap/alpha=3
35+
process/fix_alpha_border=true
36+
process/premult_alpha=false
37+
process/normal_map_invert_y=false
38+
process/hdr_as_srgb=false
39+
process/hdr_clamp_exposure=false
40+
process/size_limit=0
41+
detect_3d/compress_to=0
42+
svg/scale=1.0
43+
editor/scale_with_editor_scale=false
44+
editor/convert_colors_with_editor_theme=false

3d/physics_interpolation_3d/player.gd

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
extends CharacterBody3D
2+
3+
var _yaw : float = 0
4+
var _pitch = 0
5+
var _dir = Vector3(sin(_yaw), 0, cos(_yaw))
6+
var _prox = 3
7+
8+
var _tps_look_from = Vector3()
9+
10+
enum CameraType {CAM_FIXED, CAM_FPS, CAM_TPS}
11+
12+
var _bullet_scene = load("res://bullet.tscn")
13+
var _cam_type = CameraType.CAM_FIXED
14+
15+
func _ready():
16+
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
17+
$Rig/Camera_TPS.set_as_top_level(true)
18+
toggle_camera_type()
19+
20+
func _input(event: InputEvent) -> void:
21+
if event is InputEventMouseMotion:
22+
_yaw -= event.relative.x * 0.005
23+
_pitch += event.relative.y * 0.01
24+
_pitch = clamp(_pitch, -PI, PI)
25+
$Rig.rotation = Vector3(0, _yaw, 0)
26+
27+
func _update_camera(_delta: float):
28+
_dir.x = sin(_yaw)
29+
_dir.z = cos(_yaw)
30+
31+
$Rig/Head.rotation = Vector3(_pitch * -0.5, 0, 0)
32+
33+
match _cam_type:
34+
CameraType.CAM_TPS:
35+
var target = $Rig/Head.get_global_transform_interpolated().origin
36+
var pos = target
37+
pos.x += _dir.x * _prox
38+
pos.z += _dir.z * _prox
39+
pos.y += 2.0 + (_pitch * (0.2 * _prox))
40+
41+
var offset = pos - _tps_look_from
42+
var l = offset.length()
43+
44+
var tps_cam_speed = _delta * 8.0
45+
if (l > tps_cam_speed):
46+
offset *= tps_cam_speed / l
47+
_tps_look_from += offset
48+
49+
$Rig/Camera_TPS.look_at_from_position(_tps_look_from, target, Vector3(0, 1, 0))
50+
51+
52+
func toggle_camera_type():
53+
match _cam_type:
54+
CameraType.CAM_FIXED:
55+
_cam_type = CameraType.CAM_FPS
56+
$Rig/Head/Camera_FPS.make_current()
57+
CameraType.CAM_FPS:
58+
_cam_type = CameraType.CAM_TPS
59+
$Rig/Camera_TPS.make_current()
60+
CameraType.CAM_TPS:
61+
_cam_type = CameraType.CAM_FIXED
62+
get_node("../Camera_Fixed").make_current()
63+
64+
# Hide body in FPS view.
65+
$Rig/Mesh_Body.visible = _cam_type != CameraType.CAM_FPS
66+
67+
func _process(_delta: float) -> void:
68+
if (Input.is_action_just_pressed("ui_focus_next")):
69+
toggle_camera_type()
70+
71+
if (Input.is_action_just_pressed("fire")):
72+
#print("fire")
73+
var bul = _bullet_scene.instantiate()
74+
var tr : Transform3D = $Rig/Head/Fire_Origin.get_global_transform_interpolated()
75+
bul.position = tr.origin
76+
var bul_dir = tr.basis[2].normalized()
77+
bul.linear_velocity = bul_dir * -9
78+
get_node("..").add_child(bul)
79+
bul.reset_physics_interpolation()
80+
81+
bul.position -= bul_dir * (1.0 - Engine.get_physics_interpolation_fraction())
82+
83+
84+
# If we pressed reset, or too far from the origin... move back to origin.
85+
if (Input.is_action_just_pressed("ui_accept") or position.length() > 10):
86+
position = Vector3(0, 1, 0)
87+
velocity = Vector3()
88+
reset_physics_interpolation()
89+
_yaw = 0
90+
_pitch = 0
91+
92+
if (Input.is_action_just_pressed("jump")) and is_on_floor():
93+
velocity += Vector3(0, 12, 0)
94+
95+
96+
_update_camera(_delta)
97+
98+
99+
func _physics_process(_delta: float) -> void:
100+
101+
var move : Vector3 = Vector3()
102+
103+
if Input.is_action_pressed("ui_up"):
104+
move.z -= 1
105+
if Input.is_action_pressed("ui_down"):
106+
move.z += 1
107+
if Input.is_action_pressed("ui_left"):
108+
move.x -= 1
109+
if Input.is_action_pressed("ui_right"):
110+
move.x += 1
111+
112+
move.y -= 0.9
113+
114+
# Apply mouse rotation to the move.
115+
move = move.rotated(Vector3(0, 1, 0), _yaw)
116+
117+
velocity += move
118+
119+
move_and_slide()
120+
121+
velocity *= 0.9
122+
123+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
uid://cusp3a7wm67ss

0 commit comments

Comments
 (0)