create ant gathering routine

This commit is contained in:
2024-10-06 22:34:34 +10:00
parent 0e1dd1b2f2
commit 2074e57cc4
10 changed files with 246 additions and 36 deletions

View File

@@ -8,6 +8,7 @@
radius = 0.213583
[node name="Honeydew" type="CharacterBody3D"]
collision_mask = 0
script = ExtResource("1_6fg3d")
[node name="Sprite3D" type="Sprite3D" parent="."]

View File

@@ -19,8 +19,12 @@ func _ready() -> void:
super._ready()
func space_left() -> int:
return max_honeydew - honeydew
## Returns amount of honeydew that did not fit
func put_honeydew(amount: int) -> int:
func deposit_honeydew(amount: int) -> int:
var new_honeydew_amount := honeydew + amount
var leftover: int = 0
if new_honeydew_amount > max_honeydew:

View File

@@ -1,6 +1,6 @@
extends Node
var honeydews: Array[Honeydew] = []
var honeydews: Dictionary = {}
var honeydew_scene := preload("res://scenes/items/honeydew.tscn")
@@ -9,7 +9,7 @@ var honeydew_scene := preload("res://scenes/items/honeydew.tscn")
func _ready() -> void:
assert(items_holder != null, "items_holder missing!")
spawn_a_bunch(Vector3.ZERO, 5, 0.5)
spawn_a_bunch(Vector3.ZERO, 125, 3)
func spawn_honeydew(pos: Vector3) -> Honeydew:
@@ -24,5 +24,19 @@ func spawn_a_bunch(pos: Vector3, amount: int, spread: float) -> void:
var new_pos := pos
new_pos.x += randf_range(-spread, spread)
new_pos.z += randf_range(-spread, spread)
var new_honeydew :=spawn_honeydew(new_pos)
honeydews.append(new_honeydew)
var new_honeydew := spawn_honeydew(new_pos)
put_honeydew(new_honeydew)
func put_honeydew(item: Honeydew) -> void:
var item_id := item.get_instance_id()
if honeydews.keys().has(item_id):
return
honeydews[item_id] = item
func erase_honeydew(item: Honeydew) -> void:
var item_id := item.get_instance_id()
if not honeydews.keys().has(item_id):
return
honeydews.erase(item_id)

View File

@@ -30,8 +30,8 @@ func _ready() -> void:
frustrum_polygon.points = frustrum_polygon_points
frustrum_collision_shape.shape = frustrum_polygon
rect_panel.visible = false
frustrum_area.body_entered.connect(_on_frustrum_area_unit_entered)
frustrum_area.body_exited.connect(_on_frustrum_area_unit_exited)
frustrum_area.body_entered.connect(_on_frustrum_area_body_entered)
frustrum_area.body_exited.connect(_on_frustrum_area_body_exited)
frustrum_area.input_ray_pickable = false
rect_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
rect_panel.add_theme_stylebox_override("panel", rect_style)
@@ -108,29 +108,30 @@ func _handle_unit_selection() -> void:
func _set_selection_state(hover: bool) -> void:
var rect_abs := selection_rect.abs()
for unit: Node3D in visible_units.values():
for unit: ControlledUnit in visible_units.values():
var point := camera.unproject_position(
unit.global_position
+ (Vector3.UP * UNIT_SELECT_OFFSET)
)
if unit is ControlledUnit:
var controlled_unit := unit as ControlledUnit
if hover:
controlled_unit.set_hovered_rect(rect_abs.has_point(point))
else:
controlled_unit.set_selected(rect_abs.has_point(point))
controlled_unit.set_hovered_rect(false)
if hover:
unit.set_hovered_rect(rect_abs.has_point(point))
else:
unit.set_selected(rect_abs.has_point(point))
unit.set_hovered_rect(false)
func _on_frustrum_area_unit_entered(unit: Node3D) -> void:
func _on_frustrum_area_body_entered(unit: Node3D) -> void:
if unit is not ControlledUnit:
return
var unit_id := unit.get_instance_id()
if visible_units.keys().has(unit_id):
return
visible_units[unit_id] = unit
visible_units[unit_id] = unit as ControlledUnit
func _on_frustrum_area_unit_exited(unit: Node3D) -> void:
func _on_frustrum_area_body_exited(unit: Node3D) -> void:
var unit_id := unit.get_instance_id()
if not visible_units.keys().has(unit_id):
return

View File

@@ -4,6 +4,7 @@ class_name Interactable
const MIN_DRAG_DISTANCE: float = 15
var hovered: bool = false
var can_interact: bool = true
var click_position: Vector2 = Vector2.ZERO
@onready var hover_sprite: Sprite3D = $HoverSprite
@@ -15,10 +16,15 @@ func _ready() -> void:
func _process(_delta: float) -> void:
hovered = HoveringManager.hovered_node == self
if not can_interact:
hovered = false
return
hover_sprite.visible = hovered
func _input(event: InputEvent) -> void:
if not can_interact:
return
if event is InputEventMouseButton and hovered:
var button_event := event as InputEventMouseButton
if button_event.button_index != MOUSE_BUTTON_LEFT:

View File

@@ -2,7 +2,24 @@ extends Interactable
class_name Honeydew
const HEIGHT_OFFSET: float = 0.1
const DROP_SPREAD: float = 0.1
var carried: bool = false
@onready var collision_shape: CollisionShape3D = $CollisionShape3D
func _ready() -> void:
assert(collision_shape != null, "collision_shape missing!")
super._ready()
global_position.y = HEIGHT_OFFSET
func set_carried(on: bool) -> void:
carried = on
can_interact = not carried
collision_shape.disabled = carried
if (not carried):
global_position.x += randf_range(-DROP_SPREAD, DROP_SPREAD)
global_position.y = HEIGHT_OFFSET
global_position.z += randf_range(-DROP_SPREAD, DROP_SPREAD)

View File

@@ -46,8 +46,8 @@ func _on_nitwit_button_pressed() -> void:
func _on_add_one_button_pressed() -> void:
anthill.put_honeydew(1)
anthill.deposit_honeydew(1)
func _on_add_five_button_pressed() -> void:
anthill.put_honeydew(5)
anthill.deposit_honeydew(5)

View File

@@ -4,15 +4,27 @@ class_name AntNitwit
enum AntNitwitState {
WANDERING,
MOVING,
GATHERING,
}
var state: AntNitwitState = AntNitwitState.WANDERING
@onready var gathering: Gathering = $Gathering
static func get_cost() -> int:
return 5
func _ready() -> void:
assert(gathering != null, "gathering missing!")
super._ready()
moving_started.connect(_on_moving_started)
moving_ended.connect(_on_moving_ended)
nav_agent.navigation_finished.connect(gathering.on_nav_agent_navigation_finished)
gathering.anthill = anthill
gathering.target_set.connect(_on_gathering_target_set)
gathering.stop_gathering.connect(_on_gathering_stop)
func _process(delta: float) -> void:
@@ -21,10 +33,13 @@ func _process(delta: float) -> void:
state = AntNitwitState.MOVING
_handle_wandering(delta)
_handle_gathering()
static func get_cost() -> int:
return 5
func _interact(with: Interactable) -> void:
if with is Honeydew:
state = AntNitwitState.GATHERING
gathering.go_gather(with as Honeydew)
func _handle_wandering(delta: float) -> void:
@@ -34,9 +49,29 @@ func _handle_wandering(delta: float) -> void:
_wander(delta)
func _handle_gathering() -> void:
gathering.handle_gathering(state != AntNitwitState.GATHERING)
func _on_moving_ended() -> void:
state = AntNitwitState.WANDERING
func _on_moving_started() -> void:
if state == AntNitwitState.GATHERING:
gathering.stop_all_gathering()
state = AntNitwitState.MOVING
func _on_gathering_target_set(pos: Vector3) -> void:
if state != AntNitwitState.GATHERING:
return
if pos != Vector3.ZERO:
nav_agent.set_target_position(pos)
else:
nav_agent.set_target_position(anthill.global_position)
func _on_gathering_stop() -> void:
state = AntNitwitState.WANDERING

View File

@@ -1,16 +1,22 @@
extends Area3D
class_name Gathering
signal target_set(pos: Vector3)
signal stop_gathering
enum GatherState {
PICKING_UP,
DEPOSITING,
STOP,
}
var items: Dictionary = {}
var nearby_items: Dictionary = {}
var carrying_items: Array[Honeydew] = []
var max_carrying: int = 3
var carrying: int = 0
var state: GatherState = GatherState.PICKING_UP
var deposit_leftover: int = 0
var state: GatherState = GatherState.STOP
var target: Honeydew
var anthill: Anthill
func _ready() -> void:
@@ -18,9 +24,136 @@ func _ready() -> void:
body_exited.connect(_on_body_exited)
func gather(item: Honeydew)->void:
func _process(_delta: float) -> void:
for i in range(carrying_items.size()):
var item := carrying_items[i]
item.global_position = (
global_position
+ (Vector3.UP * 0.5)
+ (Vector3.UP * 0.1 * i)
)
if target != null:
DebugDraw.circle(target.global_position)
func go_gather(item: Honeydew) -> void:
if anthill.space_left() <= 0:
return
if carrying_items.size() >= max_carrying:
go_deposit()
return
target = item
state = GatherState.PICKING_UP
target_set.emit(item.global_position)
func go_deposit() -> void:
state = GatherState.DEPOSITING
target_set.emit(Vector3.ZERO)
func handle_gathering(stop: bool) -> void:
if stop:
state = GatherState.STOP
func on_nav_agent_navigation_finished() -> void:
if state == GatherState.PICKING_UP and target != null:
_pick_up()
if state == GatherState.DEPOSITING:
_deposit()
func set_leftover(value: int) -> void:
deposit_leftover = value
func stop_all_gathering() -> void:
state = GatherState.STOP
target = null
func _pick_up() -> void:
if not target.carried:
carrying_items.append(target)
target.set_carried(true)
await get_tree().create_timer(0.5).timeout
if carrying_items.size() >= max_carrying:
go_deposit()
return
var nearest := _find_nearest(nearby_items.values())
if nearest != null:
go_gather(nearest)
return
go_deposit()
func _deposit() -> void:
await get_tree().create_timer(0.5).timeout
while carrying_items.size() > 0:
if state != GatherState.DEPOSITING:
return
if anthill.space_left() <= 0:
print('DROP!')
_drop_everything()
stop_all_gathering()
stop_gathering.emit()
return
var item := carrying_items.pop_back() as Honeydew
ItemsManager.erase_honeydew(item)
_erase_honeydew(item)
item.queue_free()
anthill.deposit_honeydew(1)
await get_tree().create_timer(0.25).timeout
state = GatherState.PICKING_UP
var nearest := _find_nearest(nearby_items.values())
if nearest != null:
go_gather(nearest)
return
var nearest_global := _find_nearest(ItemsManager.honeydews.values())
if nearest_global != null:
go_gather(nearest_global)
return
stop_all_gathering()
stop_gathering.emit()
func _drop_everything() -> void:
while carrying_items.size() > 0:
var item := carrying_items.pop_back() as Honeydew
item.set_carried(false)
await get_tree().create_timer(0.25).timeout
func _find_nearest(items: Array) -> Honeydew:
var nearest: Node3D = null
var nearest_distance: float = INF
for item: Honeydew in items:
if item.carried:
continue
var distance := global_position.distance_to(item.global_position)
if distance < nearest_distance:
nearest_distance = distance
nearest = item
return nearest
func _erase_honeydew(item: Honeydew) -> void:
var item_id := item.get_instance_id()
if not nearby_items.keys().has(item_id):
return
nearby_items.erase(item_id)
func _on_body_entered(item: Node3D) -> void:
@@ -28,15 +161,14 @@ func _on_body_entered(item: Node3D) -> void:
return
var item_id := item.get_instance_id()
if items.keys().has(item_id):
if nearby_items.keys().has(item_id):
return
items[item_id] = item
nearby_items[item_id] = item as Honeydew
func _on_body_exited(item: Node3D) -> void:
var item_id := item.get_instance_id()
if not items.keys().has(item_id):
if item is not Honeydew:
return
items.erase(item_id)
_erase_honeydew(item as Honeydew)

View File

@@ -16,6 +16,10 @@ var ground_plane: Plane = Plane(Vector3.UP, 0)
@onready var selection_sprite: Sprite3D = $SelectionSprite
static func get_cost() -> int:
return 5
func _init() -> void:
max_wander_distance = 2
min_wander_interval = 0.5
@@ -73,10 +77,6 @@ func set_hovered_rect(on: bool) -> void:
hovered_rect = on
static func get_cost() -> int:
return 5
func set_selected(on: bool) -> void:
selected = on