Compare commits
3 Commits
0350d48957
...
94425bbd6c
Author | SHA1 | Date |
---|---|---|
|
94425bbd6c | |
|
b682981a26 | |
|
3fa58bc6df |
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,14 @@
|
|||
[gd_scene format=3 uid="uid://d0dvo6n5onnni"]
|
||||
|
||||
[node name="Vision Preview Light" type="OmniLight3D"]
|
||||
light_color = Color(0.491223, 1, 0, 1)
|
||||
light_indirect_energy = 0.0
|
||||
light_volumetric_fog_energy = 0.0
|
||||
light_negative = true
|
||||
light_specular = 0.0
|
||||
light_bake_mode = 0
|
||||
light_cull_mask = 4294967289
|
||||
shadow_enabled = true
|
||||
shadow_caster_mask = 4294967289
|
||||
omni_range = 43.0
|
||||
omni_attenuation = -0.4
|
|
@ -0,0 +1,97 @@
|
|||
@tool
|
||||
extends StaticBody3D
|
||||
|
||||
@export var item: Item:
|
||||
set(val):
|
||||
item = val
|
||||
if !is_node_ready(): await ready
|
||||
$Props.multimesh.mesh = item.model
|
||||
$Cone.material_override = item.model.surface_get_material(0)
|
||||
|
||||
@export var count: int = 10:
|
||||
set(val):
|
||||
count = val
|
||||
update()
|
||||
@export var item_volume: float = 0.2:
|
||||
set(val):
|
||||
item_volume = val
|
||||
item_radius = pow(item_volume,1.0/3.0)
|
||||
update()
|
||||
@export var item_radius: float = 0.0:
|
||||
set(val):
|
||||
item_radius = val
|
||||
item_volume = pow(item_radius, 3.0)
|
||||
update()
|
||||
@export_range(0,60) var slope_angle: float = 45:
|
||||
set(val):
|
||||
slope_angle = val
|
||||
slope_ratio = cos(deg_to_rad(slope_angle)) / sin(deg_to_rad(slope_angle))
|
||||
print("slope ratio: %f" % slope_ratio)
|
||||
update()
|
||||
var slope_ratio: float = 1.0
|
||||
|
||||
@onready var cone: MeshInstance3D = $Cone
|
||||
@onready var props: MultiMeshInstance3D = $Props
|
||||
@onready var collision_shape: CollisionShape3D = $CollisionShape3D
|
||||
|
||||
func _ready() -> void:
|
||||
props.multimesh = props.multimesh.duplicate()
|
||||
|
||||
func update() -> void:
|
||||
var volume: float = count * item_volume
|
||||
var three_v_over_pi: float = (3 * volume) / PI
|
||||
var height: float = pow(three_v_over_pi, 1.0/3.0) / pow(slope_ratio, 2.0/3.0)
|
||||
var radius: float = height * slope_ratio
|
||||
var v: float = (1.0/3.0) * PI * pow(radius,2) * height
|
||||
assert(is_equal_approx(v,volume))
|
||||
cone.scale = Vector3(radius,height,radius)
|
||||
cone.position.y = height/2.0
|
||||
|
||||
var slope_length: float = Vector2(radius,height).length()
|
||||
var ring_count: int = ceili(slope_length / (item_radius*2))
|
||||
|
||||
var positions: PackedVector3Array = []
|
||||
|
||||
var angle: float = 0.0
|
||||
for ring in range(ring_count):
|
||||
#var perc: float = ring/float(ring_count-1)
|
||||
var slope_l: float = ring * (item_radius * 2)
|
||||
var ring_y: float = height-( sin(deg_to_rad(slope_angle)) * slope_l )
|
||||
var ring_radius: float = cos(deg_to_rad(slope_angle)) * slope_l
|
||||
var ring_circ: float = ring_radius * TAU
|
||||
var ring_item_count: int = ceili(ring_circ / (item_radius*2))
|
||||
if ring_item_count == 0:
|
||||
ring_item_count = 1
|
||||
var ring_angle_offset: float = TAU / ring_item_count
|
||||
for i in range(ring_item_count):
|
||||
angle += ring_angle_offset
|
||||
#var angle: float = ring_angle_offset * i
|
||||
var x: float = cos(angle) * ring_radius
|
||||
var z: float = sin(angle) * ring_radius
|
||||
var pos: Vector3 = Vector3(x,ring_y,z)
|
||||
positions.append(pos)
|
||||
|
||||
props.multimesh.instance_count = positions.size()
|
||||
for i in range(positions.size()):
|
||||
#DebugDraw3D.draw_sphere(positions[i], item_radius, Color.RED, 0.1)
|
||||
#var y_rot: float = randf() * TAU
|
||||
var y_rot: float = 0
|
||||
props.multimesh.set_instance_transform(i, Transform3D(Basis(Vector3.UP,y_rot),positions[i]))
|
||||
|
||||
props.multimesh.visible_instance_count = min(count, positions.size())
|
||||
|
||||
#print("Rings: %d, Items: %d" % [ring_count, positions.size()])
|
||||
|
||||
#var surface_item_count: int = ceil(pow(count, 2.0/3.0))
|
||||
#props.multimesh.instance_count = ceil(surface_item_count)
|
||||
|
||||
#var theta: float = chord_offset / distance_offset
|
||||
#for i in range(surface_item_count):
|
||||
#var away: float = distance_offset * theta
|
||||
#var around: float = theta + 0
|
||||
#var x: float = cos(around) * away
|
||||
#var z: float = sin(around) * away
|
||||
#var y: float = height - (away * slope_ratio)
|
||||
#var trans: Transform3D = Transform3D(Basis(), Vector3(x,y,z))
|
||||
#props.multimesh.set_instance_transform(i,trans)
|
||||
#theta += chord_offset / away
|
|
@ -0,0 +1 @@
|
|||
uid://b742u7cr6efqm
|
|
@ -53,6 +53,47 @@ class MoveAction extends UnitAction:
|
|||
#DebugDraw3D.draw_text(global_position + Vector3(0,1,0), "%f" % nav_agent_3d.distance_to_target())
|
||||
return Unit.TaskStatus.IN_PROGRESS
|
||||
|
||||
class ChaseAction extends UnitAction:
|
||||
var target: Unit
|
||||
var target_position: Vector3
|
||||
var last_distance_to_target: float = 99999999.9
|
||||
var stuck_timer: float = 0.0
|
||||
|
||||
func process(delta: float) -> Unit.TaskStatus:
|
||||
if target == null or target.is_queued_for_deletion():
|
||||
return Unit.TaskStatus.IMPOSSIBLE
|
||||
if target.global_position.distance_squared_to(target_position) >= 4.0:
|
||||
# TODO: we could try to intercept the target by:
|
||||
# - calculating our approximate time to reach the target
|
||||
# - forcasting the target's position that time in the future based on it's velocity
|
||||
# - do a raycast in that direction to prevent the future position from going through a wall
|
||||
target_position = target.global_position
|
||||
unit.nav_agent_3d.target_position = target_position
|
||||
|
||||
if unit.nav_agent_3d.is_navigation_finished():
|
||||
if unit.nav_agent_3d.is_target_reachable():
|
||||
return Unit.TaskStatus.DONE
|
||||
else:
|
||||
return Unit.TaskStatus.IMPOSSIBLE
|
||||
else:
|
||||
var next_point: Vector3 = unit.nav_agent_3d.get_next_path_position()
|
||||
if unit.shapecast_3d.is_colliding():
|
||||
var distance_to_target: float = unit.global_position.distance_to(next_point)
|
||||
var progress_rate: float = (last_distance_to_target - distance_to_target) / delta
|
||||
last_distance_to_target = distance_to_target
|
||||
if progress_rate < unit.minimum_progress_rate:
|
||||
stuck_timer += delta
|
||||
if stuck_timer >= unit.stuck_time:
|
||||
unit.unstuck()
|
||||
else:
|
||||
unit.label_3d.modulate = Color.WHITE
|
||||
stuck_timer = 0
|
||||
DebugDraw3D.draw_sphere(unit.nav_agent_3d.target_position, 0.5, Color.RED)
|
||||
var direction: Vector3 = (next_point - unit.global_position).normalized()
|
||||
unit.target_velocity = direction * unit.max_speed
|
||||
unit.nav_agent_3d.velocity = unit.target_velocity
|
||||
return Unit.TaskStatus.IN_PROGRESS
|
||||
|
||||
class BuildAction extends UnitAction:
|
||||
var building: Building
|
||||
|
||||
|
|
|
@ -8,4 +8,10 @@ var sighted: bool = true:
|
|||
|
||||
func _ready() -> void:
|
||||
sighted = false
|
||||
go_to_destination(Vector3(17,1,15))
|
||||
var target_citizen: Citizen = get_tree().get_nodes_in_group("Citizens").pick_random() as Citizen
|
||||
if target_citizen != null:
|
||||
var chase_action: UnitAction.ChaseAction = UnitAction.ChaseAction.new()
|
||||
chase_action.unit = self
|
||||
chase_action.target = target_citizen
|
||||
action = chase_action
|
||||
#go_to_destination(Vector3(17,1,15))
|
||||
|
|
Loading…
Reference in New Issue