1
0
Fork 0

Add defend command

This commit is contained in:
Michaël Lemaire 2022-10-26 20:29:17 +02:00
parent 83b9617edd
commit 2b94671759
14 changed files with 153 additions and 43 deletions

View file

@ -1,8 +1,14 @@
extends Node2D extends Node2D
class_name BattleField class_name BattleField
@export var commands: Node
var _ticker1 := 0.0 var _ticker1 := 0.0
func _ready():
if not commands:
push_warning("No commands manager set to battlefield")
func _physics_process(delta): func _physics_process(delta):
_ticker1 += delta _ticker1 += delta
if _ticker1 > 1.0: if _ticker1 > 1.0:
@ -12,5 +18,14 @@ func _physics_process(delta):
func ticker(group_name: String): func ticker(group_name: String):
get_tree().call_group_flags(SceneTree.GROUP_CALL_DEFERRED, group_name, "tick") get_tree().call_group_flags(SceneTree.GROUP_CALL_DEFERRED, group_name, "tick")
func _on_commands_changed(commander, commands): func _on_commands_changed(comms):
get_tree().call_group("unit", "_on_commands_changed", commander, commands) get_tree().call_group("unit", "_on_commands_changed", comms)
func _on_child_entered_tree(node):
if node is Unit:
node.promoted.connect(_send_commands_to_unit.bind(node))
_send_commands_to_unit(node)
func _send_commands_to_unit(unit: Unit):
if commands:
unit._on_commands_changed(commands.get_active())

View file

@ -30,13 +30,19 @@ func _physics_process(delta):
if _spawning_since > spawn_duration: if _spawning_since > spawn_duration:
spawn() spawn()
func get_battlefield() -> BattleField:
return find_parent("battlefield") as BattleField
func spawn(): func spawn():
if unit_type: if unit_type:
var unit := unit_type.instantiate() var unit := unit_type.instantiate()
if unit is Unit: if unit is Unit:
_spawning_since = min(0.0, _spawning_since - spawn_duration) _spawning_since = min(0.0, _spawning_since - spawn_duration)
# FIXME add to battlefield
unit.player = player unit.player = player
add_child(unit) var battlefield := get_battlefield()
if battlefield:
battlefield.add_child(unit)
else:
add_child(unit)
unit.global_position = global_position unit.global_position = global_position
unit.move_to(delivery) unit.move_to(delivery)

19
core/tools.gd Normal file
View file

@ -0,0 +1,19 @@
class_name Tools
# Get the nearest node from a list, satisfying a predicate
static func get_nearest(from: Node2D, nodes: Array[Node], predicate: Callable) -> Node2D:
var from_position := from.global_position
var nearest: Node2D = null
var distance := INF
for node in nodes:
if predicate.call(node):
var d := from_position.distance_to(node.global_position)
if d < distance:
distance = d
nearest = node
return nearest
# Get a random position around a fixed position, in a given radius
static func jitter(pos: Vector2, min_dist = 0.0, max_dist = 100.0) -> Vector2:
# TODO uniform distribution
return pos + Vector2.from_angle(randf_range(0.0, PI * 2.0)) * randf_range(min_dist, max_dist)

View file

@ -12,19 +12,19 @@ signal clicked
icon = PlaceholderTexture2D.new() icon = PlaceholderTexture2D.new()
_check_compose() _check_compose()
@export var color: Color: @export var player: Node:
set(val): set(val):
if val is Color: if val is Player:
color = val player = val
else: else:
color = Color.BLACK player = null
_check_compose() _check_compose()
@export var code: String @export var code: String
func _compose(): func _compose():
%icon.texture = icon %icon.texture = icon
%badge.self_modulate = color %badge.self_modulate = player.color if player else Color.GRAY
super._compose() super._compose()
func apply(container: Node2D, pos: Vector2): func apply(container: Node2D, pos: Vector2):

View file

@ -16,7 +16,6 @@ fill_to = Vector2(0.5, 0)
[node name="command" type="Node2D"] [node name="command" type="Node2D"]
script = ExtResource("1_bwbsk") script = ExtResource("1_bwbsk")
color = Color(0, 0, 0, 1)
code = "" code = ""
[node name="badge" type="TextureButton" parent="."] [node name="badge" type="TextureButton" parent="."]

View file

@ -11,7 +11,7 @@ extends Node2D
@export var available_commands: Array[PackedScene] @export var available_commands: Array[PackedScene]
signal commands_changed(commander, commands) signal commands_changed(commands)
func _ready(): func _ready():
%stock.visible = false %stock.visible = false
@ -20,6 +20,7 @@ func _ready():
if available_commands: if available_commands:
for command_scene in available_commands: for command_scene in available_commands:
var command := command_scene.instantiate() var command := command_scene.instantiate()
command.player = player
%stock.add_child(command) %stock.add_child(command)
func _show_command_wheel(pos: Vector2): func _show_command_wheel(pos: Vector2):
@ -37,7 +38,6 @@ func _show_command_wheel(pos: Vector2):
for command in %stock.get_children(): for command in %stock.get_children():
# TODO only available # TODO only available
command = command.duplicate() command = command.duplicate()
command.color = player.color
command.position = Vector2.from_angle(inc * idx) * 200.0 command.position = Vector2.from_angle(inc * idx) * 200.0
command.connect("clicked", _on_wheel_command_clicked.bind(command), CONNECT_ONE_SHOT) command.connect("clicked", _on_wheel_command_clicked.bind(command), CONNECT_ONE_SHOT)
var line := Line2D.new() var line := Line2D.new()
@ -55,11 +55,11 @@ func _on_wheel_command_clicked(command: Command):
command.apply(%active, %wheel.position) command.apply(%active, %wheel.position)
command.scale *= 0.5 command.scale *= 0.5
command.connect("clicked", _on_active_command_clicked.bind(command)) command.connect("clicked", _on_active_command_clicked.bind(command))
commands_changed.emit(player, %active.get_children()) commands_changed.emit(%active.get_children())
func _on_active_command_clicked(command: Command): func _on_active_command_clicked(command: Command):
command.queue_free() command.queue_free()
commands_changed.emit(player, %active.get_children()) commands_changed.emit(%active.get_children())
func background_clicked(pos): func background_clicked(pos):
if %wheel.visible: if %wheel.visible:
@ -68,3 +68,6 @@ func background_clicked(pos):
if camera: if camera:
pos = get_viewport().canvas_transform.affine_inverse() * pos pos = get_viewport().canvas_transform.affine_inverse() * pos
_show_command_wheel(pos) _show_command_wheel(pos)
func get_active():
return %active.get_children()

View file

@ -2,6 +2,8 @@
class_name Unit class_name Unit
extends Composer extends Composer
signal promoted
@export var sprite: Texture2D: @export var sprite: Texture2D:
set(val): set(val):
sprite = val sprite = val
@ -68,9 +70,11 @@ func die():
queue_free() queue_free()
func promote_chief(): func promote_chief():
is_chief = true if not is_chief:
if player: is_chief = true
add_to_group("chief:" + player.code) if player:
add_to_group("chief:" + player.code)
promoted.emit()
func set_chief(chief): func set_chief(chief):
if chief is Unit and chief.is_chief and chief != self: if chief is Unit and chief.is_chief and chief != self:

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=3 uid="uid://c6omib6txy3qh"] [gd_scene load_steps=9 format=3 uid="uid://c6omib6txy3qh"]
[ext_resource type="PackedScene" uid="uid://ck41r2je85sm3" path="res://core/ui/camera.tscn" id="1_7evrt"] [ext_resource type="PackedScene" uid="uid://ck41r2je85sm3" path="res://core/ui/camera.tscn" id="1_7evrt"]
[ext_resource type="PackedScene" uid="uid://brbtq46uk18gg" path="res://core/battlefield.tscn" id="1_x63ik"] [ext_resource type="PackedScene" uid="uid://brbtq46uk18gg" path="res://core/battlefield.tscn" id="1_x63ik"]
@ -7,6 +7,7 @@
[ext_resource type="PackedScene" uid="uid://b8uik6q4v35o3" path="res://tac/units/factory.tscn" id="2_wnc50"] [ext_resource type="PackedScene" uid="uid://b8uik6q4v35o3" path="res://tac/units/factory.tscn" id="2_wnc50"]
[ext_resource type="PackedScene" uid="uid://xoup4vukp3ni" path="res://core/ui/commands.tscn" id="4_1gkbi"] [ext_resource type="PackedScene" uid="uid://xoup4vukp3ni" path="res://core/ui/commands.tscn" id="4_1gkbi"]
[ext_resource type="PackedScene" uid="uid://dr1e0h27nuam" path="res://tac/commands/delivery.tscn" id="5_fi2mi"] [ext_resource type="PackedScene" uid="uid://dr1e0h27nuam" path="res://tac/commands/delivery.tscn" id="5_fi2mi"]
[ext_resource type="PackedScene" uid="uid://cmaup0f5ud8vr" path="res://tac/commands/defend.tscn" id="5_fmegp"]
[node name="main" type="Node2D"] [node name="main" type="Node2D"]
@ -17,7 +18,7 @@
[node name="commands" parent="." node_paths=PackedStringArray("player", "camera") instance=ExtResource("4_1gkbi")] [node name="commands" parent="." node_paths=PackedStringArray("player", "camera") instance=ExtResource("4_1gkbi")]
player = NodePath("../world/player1") player = NodePath("../world/player1")
camera = NodePath("../camera") camera = NodePath("../camera")
available_commands = [ExtResource("5_fi2mi")] available_commands = [ExtResource("5_fi2mi"), ExtResource("5_fmegp")]
[node name="world" type="Node2D" parent="."] [node name="world" type="Node2D" parent="."]
@ -29,7 +30,8 @@ code = "p1"
color = Color(1, 0, 0, 1) color = Color(1, 0, 0, 1)
code = "p2" code = "p2"
[node name="battlefield" parent="world" instance=ExtResource("1_x63ik")] [node name="battlefield" parent="world" node_paths=PackedStringArray("commands") instance=ExtResource("1_x63ik")]
commands = NodePath("../../commands")
[node name="factory1" parent="world/battlefield" node_paths=PackedStringArray("player") instance=ExtResource("2_wnc50")] [node name="factory1" parent="world/battlefield" node_paths=PackedStringArray("player") instance=ExtResource("2_wnc50")]
position = Vector2(270, 222) position = Vector2(270, 222)
@ -43,3 +45,4 @@ player = NodePath("../../player2")
[connection signal="scrolled" from="inputs" to="camera" method="scroll"] [connection signal="scrolled" from="inputs" to="camera" method="scroll"]
[connection signal="zoomed" from="inputs" to="camera" method="change_zoom"] [connection signal="zoomed" from="inputs" to="camera" method="change_zoom"]
[connection signal="commands_changed" from="commands" to="world/battlefield" method="_on_commands_changed"] [connection signal="commands_changed" from="commands" to="world/battlefield" method="_on_commands_changed"]
[connection signal="child_entered_tree" from="world/battlefield" to="world/battlefield" method="_on_child_entered_tree"]

View file

@ -34,6 +34,11 @@ _global_script_classes=[{
"language": &"GDScript", "language": &"GDScript",
"path": "res://core/spawner.gd" "path": "res://core/spawner.gd"
}, { }, {
"base": "RefCounted",
"class": &"Tools",
"language": &"GDScript",
"path": "res://core/tools.gd"
}, {
"base": "Composer", "base": "Composer",
"class": &"Unit", "class": &"Unit",
"language": &"GDScript", "language": &"GDScript",
@ -50,6 +55,7 @@ _global_script_class_icons={
"Composer": "", "Composer": "",
"Player": "", "Player": "",
"Spawner": "", "Spawner": "",
"Tools": "",
"Unit": "", "Unit": "",
"Weapon": "" "Weapon": ""
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dgatvtgtb6j8d"
path="res://.godot/imported/defend.png-0d992a483323ca4da1938cf20130bd2f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://tac/assets/commands/defend.png"
dest_files=["res://.godot/imported/defend.png-0d992a483323ca4da1938cf20130bd2f.ctex"]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

11
tac/commands/defend.tscn Normal file
View file

@ -0,0 +1,11 @@
[gd_scene load_steps=3 format=3 uid="uid://cmaup0f5ud8vr"]
[ext_resource type="PackedScene" uid="uid://b3l4jfjieucrc" path="res://core/ui/command.tscn" id="1_s822j"]
[ext_resource type="Texture2D" uid="uid://dgatvtgtb6j8d" path="res://tac/assets/commands/defend.png" id="2_6gky5"]
[node name="command_defend" instance=ExtResource("1_s822j")]
icon = ExtResource("2_6gky5")
code = "defend"
[node name="icon" parent="." index="1"]
texture = ExtResource("2_6gky5")

View file

@ -11,15 +11,8 @@ func _compose():
$spawner.player = player $spawner.player = player
super._compose() super._compose()
func _on_commands_changed(commander, commands): func _on_commands_changed(commands):
if commander == player: var delivery = Tools.get_nearest(self, commands,
var nearest := Vector2(INF, INF) func filter(command): return command.player == player and command.code == "delivery")
var distance := INF if delivery:
for command in commands: $spawner.delivery = delivery.global_position
if command.code == "delivery":
var d := position.distance_to(command.position)
if d < distance:
distance = d
nearest = command.position
if distance != INF:
$spawner.delivery = nearest

View file

@ -1,5 +1,7 @@
extends Unit extends Unit
var current_command := WeakRef.new()
func _compose(): func _compose():
$chief.visible = is_chief $chief.visible = is_chief
super._compose() super._compose()
@ -7,17 +9,24 @@ func _compose():
func tick(): func tick():
chief_maintenance() chief_maintenance()
# go to nearest enemy if is_chief:
var enemy: Unit = null var command := current_command.get_ref() as Command
var closest := INF if command and command.global_position.distance_to(global_position) > 100.0:
for unit in get_tree().get_nodes_in_group("unit"): # go near current command
if unit is Unit and unit.player != player: move_to(Tools.jitter(command.global_position, 50.0, 100.0))
var distance := global_position.distance_to(unit.global_position) return
if distance < closest: else:
closest = distance var chief = get_chief()
enemy = unit if chief and chief.global_position.distance_to(global_position) > 100.0:
# go near chief
move_to(Tools.jitter(chief.global_position, 50.0, 100.0))
return
var enemy := Tools.get_nearest(self, get_tree().get_nodes_in_group("unit"),
func filter(unit): return unit is Unit and unit.player != player)
if enemy: if enemy:
move_to(enemy.global_position + Vector2.from_angle(randf_range(0.0, PI * 2.0)) * randf_range(100.0, 300.0)) # go near current target enemy
move_to(Tools.jitter(enemy.global_position, 100.0, 300.0))
$turret.set_target(enemy) $turret.set_target(enemy)
func chief_maintenance(): func chief_maintenance():
@ -31,7 +40,15 @@ func chief_maintenance():
var chiefs = list_chiefs() var chiefs = list_chiefs()
# TODO sort by distance, experience and subordinate count # TODO sort by distance, experience and subordinate count
if chiefs.size() > 0: if chiefs.size() > 0:
chief = chiefs[0] set_chief(chiefs[0])
else: else:
promote_chief() promote_chief()
_compose() _compose()
func _on_commands_changed(commands):
if is_chief:
var defend := Tools.get_nearest(self, commands,
func filter(command): return command.player == player and command.code == "defend")
if defend:
current_command = weakref(defend)