Fix rain puddle splash lifecycle
This commit is contained in:
parent
2b5b0a63ec
commit
1163cef320
3 changed files with 55 additions and 28 deletions
|
|
@ -83,11 +83,14 @@ func add_item_to_storage(item_id: StringName, quantity: int = 1) -> bool:
|
||||||
if existing != null:
|
if existing != null:
|
||||||
existing.quantity += quantity
|
existing.quantity += quantity
|
||||||
else:
|
else:
|
||||||
var owned := OwnedItemType.new()
|
var new_owned_item := OwnedItemType.new()
|
||||||
owned.item_id = item_id
|
new_owned_item.item_id = item_id
|
||||||
owned.quantity = quantity
|
new_owned_item.quantity = quantity
|
||||||
owned.storage_slot = _first_available_storage_slot(item, _items)
|
new_owned_item.storage_slot = _first_available_storage_slot(
|
||||||
_items.append(owned)
|
item,
|
||||||
|
_items,
|
||||||
|
)
|
||||||
|
_items.append(new_owned_item)
|
||||||
contents_changed.emit()
|
contents_changed.emit()
|
||||||
return true
|
return true
|
||||||
if existing != null:
|
if existing != null:
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,19 @@ func _run() -> void:
|
||||||
assert(not puddles.is_processing())
|
assert(not puddles.is_processing())
|
||||||
puddles.set_active(true)
|
puddles.set_active(true)
|
||||||
assert(puddles.is_processing())
|
assert(puddles.is_processing())
|
||||||
|
var splash_root := puddles.get_node("PuddleSplashes") as Node3D
|
||||||
|
assert(splash_root != null)
|
||||||
|
splash_root.position = Vector3(5.0, 1.0, -4.0)
|
||||||
|
var expected_splash_position := Vector3(1.5, 2.04, -3.0)
|
||||||
|
puddles.call("_emit_splash", Vector3(1.5, 0.0, -3.0), 2.0)
|
||||||
|
assert(splash_root.get_child_count() == 1)
|
||||||
|
var splash := splash_root.get_child(0) as CPUParticles3D
|
||||||
|
assert(splash != null and splash.is_inside_tree())
|
||||||
|
assert(splash.global_position.is_equal_approx(expected_splash_position))
|
||||||
|
await create_timer(0.55).timeout
|
||||||
|
await process_frame
|
||||||
|
assert(not is_instance_valid(splash))
|
||||||
|
splash_root.position = Vector3.ZERO
|
||||||
for _tick: int in 18:
|
for _tick: int in 18:
|
||||||
puddles.call("_process", 0.25)
|
puddles.call("_process", 0.25)
|
||||||
assert(puddles.get_active_puddle_count() > 0)
|
assert(puddles.get_active_puddle_count() > 0)
|
||||||
|
|
|
||||||
|
|
@ -286,21 +286,21 @@ func _spawn_puddle_near(player_position: Vector3) -> bool:
|
||||||
if triangle_index < 0 or triangle_index >= _surface_triangles.size():
|
if triangle_index < 0 or triangle_index >= _surface_triangles.size():
|
||||||
return false
|
return false
|
||||||
var triangle: PackedVector3Array = _surface_triangles[triangle_index]
|
var triangle: PackedVector3Array = _surface_triangles[triangle_index]
|
||||||
var position: Vector3 = _random_point_in_triangle(triangle)
|
var candidate_position: Vector3 = _random_point_in_triangle(triangle)
|
||||||
var horizontal_distance: float = Vector2(
|
var horizontal_distance: float = Vector2(
|
||||||
position.x,
|
candidate_position.x,
|
||||||
position.z,
|
candidate_position.z,
|
||||||
).distance_to(Vector2(player_position.x, player_position.z))
|
).distance_to(Vector2(player_position.x, player_position.z))
|
||||||
if (
|
if (
|
||||||
horizontal_distance < MINIMUM_PLAYER_DISTANCE
|
horizontal_distance < MINIMUM_PLAYER_DISTANCE
|
||||||
or horizontal_distance > MAXIMUM_PLAYER_DISTANCE
|
or horizontal_distance > MAXIMUM_PLAYER_DISTANCE
|
||||||
or _is_candidate_blocked(position)
|
or _is_candidate_blocked(candidate_position)
|
||||||
or _is_near_existing_puddle(position)
|
or _is_near_existing_puddle(candidate_position)
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
var maximum_radius: float = minf(
|
var maximum_radius: float = minf(
|
||||||
MAXIMUM_PUDDLE_RADIUS,
|
MAXIMUM_PUDDLE_RADIUS,
|
||||||
_minimum_triangle_edge_distance(position, triangle) * 0.65,
|
_minimum_triangle_edge_distance(candidate_position, triangle) * 0.65,
|
||||||
)
|
)
|
||||||
if maximum_radius < MINIMUM_PUDDLE_RADIUS:
|
if maximum_radius < MINIMUM_PUDDLE_RADIUS:
|
||||||
continue
|
continue
|
||||||
|
|
@ -311,7 +311,7 @@ func _spawn_puddle_near(player_position: Vector3) -> bool:
|
||||||
var radius_z: float = radius_x * _random.randf_range(0.58, 0.86)
|
var radius_z: float = radius_x * _random.randf_range(0.58, 0.86)
|
||||||
_activate_puddle(
|
_activate_puddle(
|
||||||
puddle,
|
puddle,
|
||||||
position,
|
candidate_position,
|
||||||
Vector2(radius_x, radius_z),
|
Vector2(radius_x, radius_z),
|
||||||
_random.randf_range(0.0, TAU),
|
_random.randf_range(0.0, TAU),
|
||||||
)
|
)
|
||||||
|
|
@ -440,15 +440,15 @@ func _apply_puddle_alpha(puddle: PuddleState) -> void:
|
||||||
puddle.material.albedo_color = color
|
puddle.material.albedo_color = color
|
||||||
|
|
||||||
|
|
||||||
func _is_candidate_blocked(position: Vector3) -> bool:
|
func _is_candidate_blocked(candidate_position: Vector3) -> bool:
|
||||||
if not is_inside_tree():
|
if not is_inside_tree():
|
||||||
return false
|
return false
|
||||||
var world: World3D = get_world_3d()
|
var world: World3D = get_world_3d()
|
||||||
if world == null:
|
if world == null:
|
||||||
return false
|
return false
|
||||||
var query := PhysicsRayQueryParameters3D.create(
|
var query := PhysicsRayQueryParameters3D.create(
|
||||||
position + Vector3.UP * 0.05,
|
candidate_position + Vector3.UP * 0.05,
|
||||||
position + Vector3.UP * 1.75,
|
candidate_position + Vector3.UP * 1.75,
|
||||||
TERRAIN_COLLISION_MASK,
|
TERRAIN_COLLISION_MASK,
|
||||||
)
|
)
|
||||||
query.collide_with_areas = false
|
query.collide_with_areas = false
|
||||||
|
|
@ -456,8 +456,11 @@ func _is_candidate_blocked(position: Vector3) -> bool:
|
||||||
return not world.direct_space_state.intersect_ray(query).is_empty()
|
return not world.direct_space_state.intersect_ray(query).is_empty()
|
||||||
|
|
||||||
|
|
||||||
func _is_near_existing_puddle(position: Vector3) -> bool:
|
func _is_near_existing_puddle(candidate_position: Vector3) -> bool:
|
||||||
var horizontal_position := Vector2(position.x, position.z)
|
var horizontal_position := Vector2(
|
||||||
|
candidate_position.x,
|
||||||
|
candidate_position.z,
|
||||||
|
)
|
||||||
for puddle: PuddleState in _puddles:
|
for puddle: PuddleState in _puddles:
|
||||||
if not puddle.active:
|
if not puddle.active:
|
||||||
continue
|
continue
|
||||||
|
|
@ -505,15 +508,14 @@ func _update_player_splashes(
|
||||||
|
|
||||||
|
|
||||||
func _emit_splash(player_position: Vector3, surface_height: float) -> void:
|
func _emit_splash(player_position: Vector3, surface_height: float) -> void:
|
||||||
if _splash_root == null or not _splash_root.visible:
|
if (
|
||||||
|
_splash_root == null
|
||||||
|
or not _splash_root.is_inside_tree()
|
||||||
|
or not _splash_root.visible
|
||||||
|
):
|
||||||
return
|
return
|
||||||
var particles := CPUParticles3D.new()
|
var particles := CPUParticles3D.new()
|
||||||
particles.name = "RainPuddleSplash"
|
particles.name = "RainPuddleSplash"
|
||||||
particles.global_position = Vector3(
|
|
||||||
player_position.x,
|
|
||||||
surface_height + 0.04,
|
|
||||||
player_position.z,
|
|
||||||
)
|
|
||||||
particles.amount = 7
|
particles.amount = 7
|
||||||
particles.lifetime = 0.38
|
particles.lifetime = 0.38
|
||||||
particles.one_shot = true
|
particles.one_shot = true
|
||||||
|
|
@ -535,7 +537,13 @@ func _emit_splash(player_position: Vector3, surface_height: float) -> void:
|
||||||
droplet_mesh.size = Vector3(0.028, 0.04, 0.028)
|
droplet_mesh.size = Vector3(0.028, 0.04, 0.028)
|
||||||
droplet_mesh.material = material
|
droplet_mesh.material = material
|
||||||
particles.mesh = droplet_mesh
|
particles.mesh = droplet_mesh
|
||||||
|
particles.emitting = false
|
||||||
_splash_root.add_child(particles)
|
_splash_root.add_child(particles)
|
||||||
|
particles.global_position = Vector3(
|
||||||
|
player_position.x,
|
||||||
|
surface_height + 0.04,
|
||||||
|
player_position.z,
|
||||||
|
)
|
||||||
particles.emitting = true
|
particles.emitting = true
|
||||||
var cleanup := create_tween()
|
var cleanup := create_tween()
|
||||||
cleanup.tween_interval(0.5)
|
cleanup.tween_interval(0.5)
|
||||||
|
|
@ -548,10 +556,10 @@ func _seed_for_world() -> int:
|
||||||
return max(_test_world.get_generation_seed(), 1) ^ 0x5261696e
|
return max(_test_world.get_generation_seed(), 1) ^ 0x5261696e
|
||||||
|
|
||||||
|
|
||||||
func _surface_cell_for(position: Vector3) -> Vector2i:
|
func _surface_cell_for(surface_position: Vector3) -> Vector2i:
|
||||||
return Vector2i(
|
return Vector2i(
|
||||||
floori(position.x / SURFACE_CELL_SIZE),
|
floori(surface_position.x / SURFACE_CELL_SIZE),
|
||||||
floori(position.z / SURFACE_CELL_SIZE),
|
floori(surface_position.z / SURFACE_CELL_SIZE),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -567,10 +575,13 @@ func _random_point_in_triangle(triangle: PackedVector3Array) -> Vector3:
|
||||||
|
|
||||||
|
|
||||||
func _minimum_triangle_edge_distance(
|
func _minimum_triangle_edge_distance(
|
||||||
position: Vector3,
|
candidate_position: Vector3,
|
||||||
triangle: PackedVector3Array,
|
triangle: PackedVector3Array,
|
||||||
) -> float:
|
) -> float:
|
||||||
var horizontal_position := Vector2(position.x, position.z)
|
var horizontal_position := Vector2(
|
||||||
|
candidate_position.x,
|
||||||
|
candidate_position.z,
|
||||||
|
)
|
||||||
return minf(
|
return minf(
|
||||||
_horizontal_distance_to_segment(
|
_horizontal_distance_to_segment(
|
||||||
horizontal_position,
|
horizontal_position,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue