From cf4f54f8e43d1deb03e1b644f6a374530efa11e3 Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Sun, 25 Aug 2024 23:47:22 +0200 Subject: next commit --- Mob.gd | 124 +++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 91 insertions(+), 33 deletions(-) (limited to 'Mob.gd') diff --git a/Mob.gd b/Mob.gd index f582ccd..a83a119 100644 --- a/Mob.gd +++ b/Mob.gd @@ -2,12 +2,15 @@ class_name Mob extends CharacterBody2D +signal selected + static var selected_unit: Mob var is_selected = false : set(value): if value: Mob.selected_unit = self + selected.emit() else: if Mob.selected_unit == self: Mob.selected_unit = null @@ -19,12 +22,24 @@ var is_hovered = false : is_hovered = value queue_redraw() -var target: Vector2 +var target: Node2D : + set(value): + target = value + reset_path() var immediate_target: Vector2 -var path: PackedVector2Array +var current_path: PackedVector2Array var current_path_idx = 0 +var previous_path: PackedVector2Array +var previous_path_idx = 0 + +var previous_position: Vector2 + +var recent_closest_paths: Array[PackedVector2Array] + +var roaming_mode = false + @export var speed: float = 100 @export var hp = 50 @@ -33,46 +48,39 @@ var current_path_idx = 0 # Called when the node enters the scene tree for the first time. func _ready(): if not target: - print("No target!") - set_process(false) - queue_free() - - path = Game.path_grid.get_point_path(Game.map.local_to_map(global_position), Game.map.local_to_map(target)) + target = get_tree().current_scene.find_child("Goal") + reset_path() Game.path_grid_changed.connect(func(): - path = Game.path_grid.get_point_path(Game.map.local_to_map(global_position), Game.map.local_to_map(target)) - current_path_idx = min(1, path.size() - 1) + reset_path() + current_path_idx = min(1, current_path.size() - 1) ) - %HP.max_value = hp + %HPBar.init(hp) set_hp(hp) func _physics_process(delta): - # TODO: if path is empty - # TODO: change state to "AttackClosestTowerState" - # TODO: get all towers, sort by distance to mob - # TODO: walk to and attack/destroy closest tower - # TODO: repeat, unless => - # TODO: check path every frame if still closed off (empty) - # TODO: if path not empty anymore change state to walk next path + previous_position = global_position - if not path.is_empty(): - if (global_position - path[current_path_idx]).is_zero_approx(): + if not current_path.is_empty(): + if (global_position - current_path[current_path_idx]).is_zero_approx(): current_path_idx += 1 - if current_path_idx >= path.size(): - path = Game.path_grid.get_point_path(Game.map.local_to_map(global_position), Game.map.local_to_map(target)) - current_path_idx = 0 + if current_path_idx >= current_path.size(): + reset_path() + + walk_along_path(current_path, current_path_idx, delta) - #var displacement := target - global_transform.origin - immediate_target = path[current_path_idx] - var displacement := (path[current_path_idx]) - global_position - var direction := displacement.normalized() - var distance := displacement.length() - - var max_speed: float = (distance / delta) - velocity = direction * minf(speed, max_speed) - move_and_slide() + if roaming_mode: + var collision = get_last_slide_collision() + if collision: + var tower = collision.get_collider() as Node2D + Game.destroy_tower(tower) + + # if unit stuck in tower + if previous_position == global_position: # doesn't work with 0.05 fluctuating position + reset_path() + roaming_mode = true func _draw(): @@ -100,15 +108,28 @@ func _draw(): func _on_navigation_base_area_entered(area: Area2D): if area.is_in_group("goal"): + Game.score += 1 queue_free() if area.is_in_group("path"): var path_node = area.get_parent() - target = path_node.next_node.global_position + if path_node == target: + target = path_node.next_node + + +func walk_along_path(path: PackedVector2Array, index: int, delta: float): + immediate_target = path[index] + var displacement := (path[index]) - global_position + var direction := displacement.normalized() + var distance := displacement.length() + + var max_speed: float = (distance / delta) + velocity = direction * minf(speed, max_speed) + move_and_slide() func set_hp(value): hp = value - %HP.value = value + %HPBar.set_value(value) if is_selected: $Label.text = str(hp) @@ -119,6 +140,43 @@ func set_hp(value): queue_free() +func reset_path(): + roaming_mode = false + current_path = get_grid_path() + + if current_path.is_empty(): + current_path = get_grid_path(true) + recent_closest_paths.append(current_path) + + # reached end of partial path + if current_path.size() == 1 and current_path[0] == global_position: + roaming_mode = true + current_path = PackedVector2Array([target.global_position]) + + # iterating between one or more closest paths + elif recent_closest_paths.count(current_path) >= 2: + roaming_mode = true + current_path = PackedVector2Array([target.global_position]) + recent_closest_paths = [] + else: + recent_closest_paths = [] + roaming_mode = false + + current_path_idx = 0 + +func get_grid_path(partial = false): + #return Game.path_grid.get_point_path( + #Game.map.local_to_map(global_position) * 2, + #Game.map.local_to_map(target.global_position) * 2, + #partial + #) + return Game.path_grid.get_point_path( + Game.map.local_to_map(global_position), + Game.map.local_to_map(target.global_position), + partial + ) + + func _on_input_event(_viewport: Node, event: InputEvent, _shape_idx: int) -> void: if Game.mode == Game.Mode.DEFAULT: if event.is_action_pressed("select"): -- cgit v1.2.3