create ant gathering routine
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
radius = 0.213583
|
radius = 0.213583
|
||||||
|
|
||||||
[node name="Honeydew" type="CharacterBody3D"]
|
[node name="Honeydew" type="CharacterBody3D"]
|
||||||
|
collision_mask = 0
|
||||||
script = ExtResource("1_6fg3d")
|
script = ExtResource("1_6fg3d")
|
||||||
|
|
||||||
[node name="Sprite3D" type="Sprite3D" parent="."]
|
[node name="Sprite3D" type="Sprite3D" parent="."]
|
||||||
|
|||||||
@@ -19,8 +19,12 @@ func _ready() -> void:
|
|||||||
super._ready()
|
super._ready()
|
||||||
|
|
||||||
|
|
||||||
|
func space_left() -> int:
|
||||||
|
return max_honeydew - honeydew
|
||||||
|
|
||||||
|
|
||||||
## Returns amount of honeydew that did not fit
|
## 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 new_honeydew_amount := honeydew + amount
|
||||||
var leftover: int = 0
|
var leftover: int = 0
|
||||||
if new_honeydew_amount > max_honeydew:
|
if new_honeydew_amount > max_honeydew:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
var honeydews: Array[Honeydew] = []
|
var honeydews: Dictionary = {}
|
||||||
|
|
||||||
var honeydew_scene := preload("res://scenes/items/honeydew.tscn")
|
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:
|
func _ready() -> void:
|
||||||
assert(items_holder != null, "items_holder missing!")
|
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:
|
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
|
var new_pos := pos
|
||||||
new_pos.x += randf_range(-spread, spread)
|
new_pos.x += randf_range(-spread, spread)
|
||||||
new_pos.z += randf_range(-spread, spread)
|
new_pos.z += randf_range(-spread, spread)
|
||||||
var new_honeydew :=spawn_honeydew(new_pos)
|
var new_honeydew := spawn_honeydew(new_pos)
|
||||||
honeydews.append(new_honeydew)
|
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)
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ func _ready() -> void:
|
|||||||
frustrum_polygon.points = frustrum_polygon_points
|
frustrum_polygon.points = frustrum_polygon_points
|
||||||
frustrum_collision_shape.shape = frustrum_polygon
|
frustrum_collision_shape.shape = frustrum_polygon
|
||||||
rect_panel.visible = false
|
rect_panel.visible = false
|
||||||
frustrum_area.body_entered.connect(_on_frustrum_area_unit_entered)
|
frustrum_area.body_entered.connect(_on_frustrum_area_body_entered)
|
||||||
frustrum_area.body_exited.connect(_on_frustrum_area_unit_exited)
|
frustrum_area.body_exited.connect(_on_frustrum_area_body_exited)
|
||||||
frustrum_area.input_ray_pickable = false
|
frustrum_area.input_ray_pickable = false
|
||||||
rect_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
rect_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
rect_panel.add_theme_stylebox_override("panel", rect_style)
|
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:
|
func _set_selection_state(hover: bool) -> void:
|
||||||
var rect_abs := selection_rect.abs()
|
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(
|
var point := camera.unproject_position(
|
||||||
unit.global_position
|
unit.global_position
|
||||||
+ (Vector3.UP * UNIT_SELECT_OFFSET)
|
+ (Vector3.UP * UNIT_SELECT_OFFSET)
|
||||||
)
|
)
|
||||||
if unit is ControlledUnit:
|
if hover:
|
||||||
var controlled_unit := unit as ControlledUnit
|
unit.set_hovered_rect(rect_abs.has_point(point))
|
||||||
if hover:
|
else:
|
||||||
controlled_unit.set_hovered_rect(rect_abs.has_point(point))
|
unit.set_selected(rect_abs.has_point(point))
|
||||||
else:
|
unit.set_hovered_rect(false)
|
||||||
controlled_unit.set_selected(rect_abs.has_point(point))
|
|
||||||
controlled_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()
|
var unit_id := unit.get_instance_id()
|
||||||
if visible_units.keys().has(unit_id):
|
if visible_units.keys().has(unit_id):
|
||||||
return
|
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()
|
var unit_id := unit.get_instance_id()
|
||||||
if not visible_units.keys().has(unit_id):
|
if not visible_units.keys().has(unit_id):
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ class_name Interactable
|
|||||||
const MIN_DRAG_DISTANCE: float = 15
|
const MIN_DRAG_DISTANCE: float = 15
|
||||||
|
|
||||||
var hovered: bool = false
|
var hovered: bool = false
|
||||||
|
var can_interact: bool = true
|
||||||
var click_position: Vector2 = Vector2.ZERO
|
var click_position: Vector2 = Vector2.ZERO
|
||||||
|
|
||||||
@onready var hover_sprite: Sprite3D = $HoverSprite
|
@onready var hover_sprite: Sprite3D = $HoverSprite
|
||||||
@@ -15,10 +16,15 @@ func _ready() -> void:
|
|||||||
|
|
||||||
func _process(_delta: float) -> void:
|
func _process(_delta: float) -> void:
|
||||||
hovered = HoveringManager.hovered_node == self
|
hovered = HoveringManager.hovered_node == self
|
||||||
|
if not can_interact:
|
||||||
|
hovered = false
|
||||||
|
return
|
||||||
hover_sprite.visible = hovered
|
hover_sprite.visible = hovered
|
||||||
|
|
||||||
|
|
||||||
func _input(event: InputEvent) -> void:
|
func _input(event: InputEvent) -> void:
|
||||||
|
if not can_interact:
|
||||||
|
return
|
||||||
if event is InputEventMouseButton and hovered:
|
if event is InputEventMouseButton and hovered:
|
||||||
var button_event := event as InputEventMouseButton
|
var button_event := event as InputEventMouseButton
|
||||||
if button_event.button_index != MOUSE_BUTTON_LEFT:
|
if button_event.button_index != MOUSE_BUTTON_LEFT:
|
||||||
|
|||||||
@@ -2,7 +2,24 @@ extends Interactable
|
|||||||
class_name Honeydew
|
class_name Honeydew
|
||||||
|
|
||||||
const HEIGHT_OFFSET: float = 0.1
|
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:
|
func _ready() -> void:
|
||||||
|
assert(collision_shape != null, "collision_shape missing!")
|
||||||
|
super._ready()
|
||||||
global_position.y = HEIGHT_OFFSET
|
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)
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ func _on_nitwit_button_pressed() -> void:
|
|||||||
|
|
||||||
|
|
||||||
func _on_add_one_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:
|
func _on_add_five_button_pressed() -> void:
|
||||||
anthill.put_honeydew(5)
|
anthill.deposit_honeydew(5)
|
||||||
|
|||||||
@@ -4,15 +4,27 @@ class_name AntNitwit
|
|||||||
enum AntNitwitState {
|
enum AntNitwitState {
|
||||||
WANDERING,
|
WANDERING,
|
||||||
MOVING,
|
MOVING,
|
||||||
|
GATHERING,
|
||||||
}
|
}
|
||||||
|
|
||||||
var state: AntNitwitState = AntNitwitState.WANDERING
|
var state: AntNitwitState = AntNitwitState.WANDERING
|
||||||
|
|
||||||
|
@onready var gathering: Gathering = $Gathering
|
||||||
|
|
||||||
|
|
||||||
|
static func get_cost() -> int:
|
||||||
|
return 5
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
assert(gathering != null, "gathering missing!")
|
||||||
super._ready()
|
super._ready()
|
||||||
moving_started.connect(_on_moving_started)
|
moving_started.connect(_on_moving_started)
|
||||||
moving_ended.connect(_on_moving_ended)
|
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:
|
func _process(delta: float) -> void:
|
||||||
@@ -21,10 +33,13 @@ func _process(delta: float) -> void:
|
|||||||
state = AntNitwitState.MOVING
|
state = AntNitwitState.MOVING
|
||||||
|
|
||||||
_handle_wandering(delta)
|
_handle_wandering(delta)
|
||||||
|
_handle_gathering()
|
||||||
|
|
||||||
|
|
||||||
static func get_cost() -> int:
|
func _interact(with: Interactable) -> void:
|
||||||
return 5
|
if with is Honeydew:
|
||||||
|
state = AntNitwitState.GATHERING
|
||||||
|
gathering.go_gather(with as Honeydew)
|
||||||
|
|
||||||
|
|
||||||
func _handle_wandering(delta: float) -> void:
|
func _handle_wandering(delta: float) -> void:
|
||||||
@@ -34,9 +49,29 @@ func _handle_wandering(delta: float) -> void:
|
|||||||
_wander(delta)
|
_wander(delta)
|
||||||
|
|
||||||
|
|
||||||
|
func _handle_gathering() -> void:
|
||||||
|
gathering.handle_gathering(state != AntNitwitState.GATHERING)
|
||||||
|
|
||||||
|
|
||||||
func _on_moving_ended() -> void:
|
func _on_moving_ended() -> void:
|
||||||
state = AntNitwitState.WANDERING
|
state = AntNitwitState.WANDERING
|
||||||
|
|
||||||
|
|
||||||
func _on_moving_started() -> void:
|
func _on_moving_started() -> void:
|
||||||
|
if state == AntNitwitState.GATHERING:
|
||||||
|
gathering.stop_all_gathering()
|
||||||
state = AntNitwitState.MOVING
|
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
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
extends Area3D
|
extends Area3D
|
||||||
class_name Gathering
|
class_name Gathering
|
||||||
|
|
||||||
|
signal target_set(pos: Vector3)
|
||||||
|
signal stop_gathering
|
||||||
|
|
||||||
enum GatherState {
|
enum GatherState {
|
||||||
PICKING_UP,
|
PICKING_UP,
|
||||||
DEPOSITING,
|
DEPOSITING,
|
||||||
|
STOP,
|
||||||
}
|
}
|
||||||
|
|
||||||
var items: Dictionary = {}
|
var nearby_items: Dictionary = {}
|
||||||
|
var carrying_items: Array[Honeydew] = []
|
||||||
var max_carrying: int = 3
|
var max_carrying: int = 3
|
||||||
var carrying: int = 0
|
var deposit_leftover: int = 0
|
||||||
var state: GatherState = GatherState.PICKING_UP
|
var state: GatherState = GatherState.STOP
|
||||||
var target: Honeydew
|
var target: Honeydew
|
||||||
|
var anthill: Anthill
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
@@ -18,9 +24,136 @@ func _ready() -> void:
|
|||||||
body_exited.connect(_on_body_exited)
|
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
|
target = item
|
||||||
state = GatherState.PICKING_UP
|
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:
|
func _on_body_entered(item: Node3D) -> void:
|
||||||
@@ -28,15 +161,14 @@ func _on_body_entered(item: Node3D) -> void:
|
|||||||
return
|
return
|
||||||
|
|
||||||
var item_id := item.get_instance_id()
|
var item_id := item.get_instance_id()
|
||||||
if items.keys().has(item_id):
|
if nearby_items.keys().has(item_id):
|
||||||
return
|
return
|
||||||
|
|
||||||
items[item_id] = item
|
nearby_items[item_id] = item as Honeydew
|
||||||
|
|
||||||
|
|
||||||
func _on_body_exited(item: Node3D) -> void:
|
func _on_body_exited(item: Node3D) -> void:
|
||||||
var item_id := item.get_instance_id()
|
if item is not Honeydew:
|
||||||
if not items.keys().has(item_id):
|
|
||||||
return
|
return
|
||||||
|
|
||||||
items.erase(item_id)
|
_erase_honeydew(item as Honeydew)
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ var ground_plane: Plane = Plane(Vector3.UP, 0)
|
|||||||
@onready var selection_sprite: Sprite3D = $SelectionSprite
|
@onready var selection_sprite: Sprite3D = $SelectionSprite
|
||||||
|
|
||||||
|
|
||||||
|
static func get_cost() -> int:
|
||||||
|
return 5
|
||||||
|
|
||||||
|
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
max_wander_distance = 2
|
max_wander_distance = 2
|
||||||
min_wander_interval = 0.5
|
min_wander_interval = 0.5
|
||||||
@@ -73,10 +77,6 @@ func set_hovered_rect(on: bool) -> void:
|
|||||||
hovered_rect = on
|
hovered_rect = on
|
||||||
|
|
||||||
|
|
||||||
static func get_cost() -> int:
|
|
||||||
return 5
|
|
||||||
|
|
||||||
|
|
||||||
func set_selected(on: bool) -> void:
|
func set_selected(on: bool) -> void:
|
||||||
selected = on
|
selected = on
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user