generated from krampus/template-godot4
Terrain physics uses surface drag model
This commit is contained in:
parent
2f4801dbaa
commit
9bef191bda
|
@ -1,6 +1,6 @@
|
|||
extends GameBall
|
||||
|
||||
const INFO_FMT := "speed: {0} m/s\nlin.damp: {1}\nang.spd: {2}\nang.damp: {3}\ntime: {4} s\nsurface decay: {5}"
|
||||
const INFO_FMT := "speed: {0} m/s\nang.spd: {1}\nsurface: {2}\ntime: {3} s"
|
||||
|
||||
@onready var debug_info: Label3D = %DebugInfo
|
||||
|
||||
|
@ -11,10 +11,8 @@ func _physics_process(delta: float) -> void:
|
|||
debug_info.text = INFO_FMT.format(
|
||||
[
|
||||
linear_velocity.length(),
|
||||
linear_damp,
|
||||
angular_velocity.length(),
|
||||
angular_damp,
|
||||
_shot_time_s,
|
||||
terrain_physics.get_decay_factor(_surface_time_s)
|
||||
Terrain.Type.keys()[_surface_terrain],
|
||||
_shot_time_s
|
||||
]
|
||||
)
|
||||
|
|
|
@ -19,6 +19,7 @@ size = Vector2(0.05, 0.05)
|
|||
|
||||
[sub_resource type="SystemFont" id="SystemFont_td87w"]
|
||||
font_names = PackedStringArray("Monospace")
|
||||
subpixel_positioning = 0
|
||||
|
||||
[node name="DebugBall" instance=ExtResource("1_gcsxs")]
|
||||
script = ExtResource("2_edye5")
|
||||
|
|
|
@ -14,18 +14,12 @@ enum Type {
|
|||
POWER,
|
||||
}
|
||||
|
||||
const TERRAIN_DAMPING_EPSILON := 1e-6
|
||||
const MAGNUS_EPSILON := 1e-3
|
||||
const VELOCITY_SQ_EPSILON := 1e-4
|
||||
const MAGNUS_SQ_EPSILON := 1e-3
|
||||
|
||||
## If enabled, ball ability cooldown is only reset at end of shot.
|
||||
@export var once_per_shot_ability := false
|
||||
|
||||
## Linear damping while in the air.
|
||||
@export var aerial_linear_damping := 0.0
|
||||
|
||||
## Angular damping while in the air.
|
||||
@export var aerial_angular_damping := 0.0
|
||||
|
||||
## Material physics configuration for this ball.
|
||||
@export var terrain_physics: TerrainPhysics
|
||||
|
||||
|
@ -64,6 +58,7 @@ var _ability_triggered := false
|
|||
var _zones: Array[BallZone] = []
|
||||
var _shot_time_s := 0.0
|
||||
var _surface_time_s := 0.0
|
||||
var _surface_terrain: Terrain.Type
|
||||
|
||||
@onready var ability_cooldown: Timer = %AbilityCooldown
|
||||
@onready var manual_sleep_timer: Timer = %ManualSleepTimer
|
||||
|
@ -74,9 +69,6 @@ var _surface_time_s := 0.0
|
|||
"res://src/equipment/balls/physics_ball/normal_physics.tres"
|
||||
)
|
||||
|
||||
@onready var default_surface_linear_damping := linear_damp
|
||||
@onready var default_surface_angular_damping := angular_damp
|
||||
|
||||
|
||||
## Should this ball stick to surfaces, rather than bounce?
|
||||
func is_sticky() -> bool:
|
||||
|
@ -131,43 +123,45 @@ func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
|
|||
|
||||
# We want the contact normal which minimizes the angle to the up vector
|
||||
var min_dot := -1.0
|
||||
var primary_body: Node
|
||||
for i: int in range(state.get_contact_count()):
|
||||
var norm := state.get_contact_local_normal(i)
|
||||
var dot := norm.dot(Vector3.UP)
|
||||
if dot > min_dot:
|
||||
min_dot = dot
|
||||
_last_contact_normal = norm
|
||||
primary_body = state.get_contact_collider_object(i)
|
||||
|
||||
# Use first contact to determine terrain properties
|
||||
var primary_body: Node = state.get_contact_collider_object(0)
|
||||
|
||||
var terrain := Terrain.from_collision(global_position, primary_body)
|
||||
var params := terrain_physics.get_params(terrain)
|
||||
if params:
|
||||
linear_damp = params.linear_damping
|
||||
angular_damp = params.angular_damping
|
||||
else:
|
||||
linear_damp = default_surface_linear_damping
|
||||
angular_damp = default_surface_angular_damping
|
||||
|
||||
var decay := 1.0 + terrain_physics.get_decay_factor(_surface_time_s)
|
||||
#linear_damp *= decay
|
||||
#angular_damp *= decay
|
||||
|
||||
_surface_terrain = Terrain.from_collision(global_position, primary_body)
|
||||
_surface_time_s += state.step
|
||||
else:
|
||||
# Ball is in the air
|
||||
linear_damp = aerial_linear_damping
|
||||
angular_damp = aerial_angular_damping
|
||||
_surface_terrain = Terrain.Type.NONE
|
||||
_surface_time_s = 0.0
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
# Simulate magnus effect
|
||||
var magnus := _magnus_force()
|
||||
if magnus.length_squared() > MAGNUS_EPSILON:
|
||||
if magnus.length_squared() > MAGNUS_SQ_EPSILON:
|
||||
apply_central_force(magnus)
|
||||
|
||||
# Apply drag
|
||||
var params := terrain_physics.get_params(_surface_terrain)
|
||||
if linear_velocity.length() > params.linear_drag:
|
||||
linear_velocity -= params.linear_drag * linear_velocity.normalized()
|
||||
else:
|
||||
linear_velocity = Vector3.ZERO
|
||||
if angular_velocity.length() > params.angular_drag:
|
||||
angular_velocity -= params.angular_drag * angular_velocity.normalized()
|
||||
else:
|
||||
angular_velocity = Vector3.ZERO
|
||||
|
||||
if linear_velocity.length_squared() < VELOCITY_SQ_EPSILON:
|
||||
linear_velocity = Vector3.ZERO
|
||||
if angular_velocity.length_squared() < VELOCITY_SQ_EPSILON:
|
||||
angular_velocity = Vector3.ZERO
|
||||
|
||||
# Keep shot time
|
||||
_shot_time_s += delta
|
||||
|
||||
|
|
|
@ -19,58 +19,56 @@
|
|||
|
||||
[sub_resource type="Resource" id="Resource_casfi"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 0.5
|
||||
linear_drag = 0.0
|
||||
angular_drag = 1.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_3k63c"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 8.0
|
||||
linear_drag = 0.0
|
||||
angular_drag = 0.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_xf73q"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 2.0
|
||||
linear_drag = 0.0
|
||||
angular_drag = 1.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_nhn3l"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 0.1
|
||||
linear_drag = 0.0
|
||||
angular_drag = 1.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_m3wjo"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 1.0
|
||||
linear_drag = 0.0
|
||||
angular_drag = 1.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_h4rld"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 0.1
|
||||
linear_drag = 0.0
|
||||
angular_drag = 1.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_j6lib"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 2.0
|
||||
linear_drag = 0.0
|
||||
angular_drag = 1.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_7f7ql"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 8.0
|
||||
linear_drag = 0.0
|
||||
angular_drag = 3.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_pusmf"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 1.0
|
||||
angular_damping = 24.0
|
||||
linear_drag = 1.0
|
||||
angular_drag = 10.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_edkxb"]
|
||||
script = ExtResource("4_onl6o")
|
||||
linear_damping = 0.0
|
||||
angular_damping = 1.0
|
||||
linear_drag = 0.0
|
||||
angular_drag = 1.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_3ngau"]
|
||||
script = ExtResource("3_52hui")
|
||||
damping_decay_curve = 12.0
|
||||
damping_decay_scale = 8.0
|
||||
default = SubResource("Resource_3k63c")
|
||||
rough = SubResource("Resource_7f7ql")
|
||||
fairway = SubResource("Resource_xf73q")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class_name TerrainParameters extends Resource
|
||||
## Physical parameters for an individual terrain type.
|
||||
|
||||
@export var linear_damping := 0.0
|
||||
@export var angular_damping := 0.0
|
||||
@export var linear_drag := 0.0
|
||||
@export var angular_drag := 0.0
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
class_name TerrainPhysics extends Resource
|
||||
## Container for ball behavior parameters when in contact with different terrain types
|
||||
|
||||
@export_exp_easing() var damping_decay_curve := 1.0
|
||||
@export var damping_decay_scale := 8.0
|
||||
|
||||
@export var default: TerrainParameters
|
||||
|
||||
@export var rough: TerrainParameters
|
||||
|
@ -41,10 +38,3 @@ func get_params(type: Terrain.Type) -> TerrainParameters:
|
|||
return glass
|
||||
_:
|
||||
return default
|
||||
|
||||
|
||||
func get_decay_factor(time: float) -> float:
|
||||
var x := time / damping_decay_scale
|
||||
if damping_decay_curve < 1.0:
|
||||
return 1.0 - pow(1.0 - x, 1.0 / damping_decay_curve)
|
||||
return pow(x, damping_decay_curve)
|
||||
|
|
Loading…
Reference in New Issue