From f0168d681b645ed55453a9fcf80ff5041d1c06d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Mon, 17 Feb 2020 19:52:36 +0100 Subject: [PATCH] Added some state to distinguish attacker and defender units --- cards/base_card.gd | 8 ++++-- helpers/battle.gd | 15 +++++++++++- helpers/nodes.gd | 8 ++++++ project.godot | 6 +++++ screens/battle/battle.gd | 38 ++++++++++++++++++----------- screens/battle/battle.tscn | 20 ++++++++++++++- screens/battle/hand.gd | 43 ++++++++++++++++++++++++++++++++ tests/hand_play_card.tscn | 43 ++++++++++++++++++++++++++++++++ tests/unit_combat.tscn | 12 +++++++++ units/base_unit.gd | 50 ++++++++++++++++++++++++++------------ units/base_unit.tscn | 2 ++ 11 files changed, 212 insertions(+), 33 deletions(-) create mode 100644 helpers/nodes.gd create mode 100644 screens/battle/hand.gd create mode 100644 tests/hand_play_card.tscn diff --git a/cards/base_card.gd b/cards/base_card.gd index b1011d9..54d9e82 100644 --- a/cards/base_card.gd +++ b/cards/base_card.gd @@ -1,6 +1,8 @@ tool extends Panel +signal played(card, anchor) + const AnimHelper = preload("res://helpers/anims.gd") const BattleHelper = preload("res://helpers/battle.gd") @@ -64,8 +66,10 @@ func update_anchors(): func play(anchor): if spawned_unit: - anchor.set_content(spawned_unit.instance()) - queue_free() + var unit = spawned_unit.instance() + unit.attacker = hero.attacker if hero else false + anchor.set_content(unit) + emit_signal("played", self, anchor) func return_to_base(): AnimHelper.linear_goto(self, base_position, 0.3) diff --git a/helpers/battle.gd b/helpers/battle.gd index ad2592d..21d6e32 100644 --- a/helpers/battle.gd +++ b/helpers/battle.gd @@ -19,14 +19,27 @@ static func update_anchors(tree: SceneTree, position, acceptability) -> Anchor: return selected_anchor -static func spawn_unit(name: String, anchor: Anchor) -> Node: +static func spawn_unit(name: String, anchor: Anchor, attacker: bool) -> Node: """ Spawn a unit on an empty anchor """ var scene = load("res://units/" + name + ".tscn") var node = scene.instance() anchor.set_content(node) + node.attacker = attacker return node +static func list_units(tree: SceneTree): + """ List all units in battle + """ + var units = [] + + for anchor in tree.get_nodes_in_group("anchors"): + var content = anchor.get_content() + if content: + units.append(content) + + return units + static func get_state(tree: SceneTree): """ Build the simple state associated with current battle scene """ diff --git a/helpers/nodes.gd b/helpers/nodes.gd new file mode 100644 index 0000000..e1cc157 --- /dev/null +++ b/helpers/nodes.gd @@ -0,0 +1,8 @@ +static func set_parent(node: Node, parent: Node): + """ Set the parent of a node, reparenting if needed + """ + var old_parent = node.get_parent() + if old_parent and old_parent != parent: + old_parent.remove_child(node) + + parent.add_child(node) diff --git a/project.godot b/project.godot index 9c35dc9..de81fed 100644 --- a/project.godot +++ b/project.godot @@ -45,6 +45,12 @@ boot_splash/image="res://loading.png" boot_splash/bg_color=Color( 0, 0, 0, 1 ) config/icon="res://icon.png" +[debug] + +gdscript/warnings/unused_argument=false +gdscript/warnings/incompatible_ternary=false +gdscript/warnings/return_value_discarded=false + [display] window/size/width=1080 diff --git a/screens/battle/battle.gd b/screens/battle/battle.gd index 3ac6c5e..6d80522 100644 --- a/screens/battle/battle.gd +++ b/screens/battle/battle.gd @@ -9,15 +9,21 @@ onready var deck_attack_cards = deck_attack.instance() onready var deck_defend_cards = deck_defend.instance() var hero_attack var hero_defend +var turn_attack = true func _ready(): - hero_attack = create_hero_unit("tomahawk", "attack_start") - hero_defend = create_hero_unit("rhino", "defend_start") + hero_attack = create_hero_unit("tomahawk", "attack_start", true) + hero_defend = create_hero_unit("rhino", "defend_start", false) fill_hand($hand_attack, deck_attack_cards, hero_attack) fill_hand($hand_defend, deck_defend_cards, hero_defend) - print(BattleHelper.get_state(get_tree())) + $hand_attack.connect("turn_end", self, "end_turn") + $hand_defend.connect("turn_end", self, "end_turn") + + adjust_playable() + + #print(BattleHelper.get_state(get_tree())) func find_free_anchor(anchor_type: String): for anchor in get_tree().get_nodes_in_group("anchors"): @@ -25,25 +31,29 @@ func find_free_anchor(anchor_type: String): return anchor return null -func create_hero_unit(name: String, anchor_type: String): +func create_hero_unit(name: String, anchor_type: String, attacker: bool): var anchor = find_free_anchor(anchor_type) if anchor: - return BattleHelper.spawn_unit("heroes/" + name, anchor) + return BattleHelper.spawn_unit("heroes/" + name, anchor, attacker) else: return null func fill_hand(hand: Node, deck: Node, hero: Node, limit=4): - while hand.get_child_count() < 4: + while hand.get_card_count() < 4: var count = deck.get_child_count() var index = floor(rand_range(0, count)) var card = deck.get_child(index).duplicate() card.set_hero(hero) - hand.add_child(card) + hand.add_card(card) - reorganize_hand(hand) - -func reorganize_hand(hand: Node): - var i = 0 - for card in hand.get_children(): - card.set_hand_location(Vector2(i * 210, 0)) - i += 1 + hand.rearrange() + +func end_turn(): + turn_attack = not turn_attack + adjust_playable() + +func adjust_playable(): + $hand_attack.visible = turn_attack + + for unit in BattleHelper.list_units(get_tree()): + unit.playable = unit.attacker == turn_attack diff --git a/screens/battle/battle.tscn b/screens/battle/battle.tscn index 51cd2d1..dd87865 100644 --- a/screens/battle/battle.tscn +++ b/screens/battle/battle.tscn @@ -1,14 +1,17 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=8 format=2] [ext_resource path="res://screens/battle/mechanolith.ogg" type="AudioStream" id=1] +[ext_resource path="res://theme/ui.tres" type="Theme" id=2] [ext_resource path="res://arenas/normal1.tscn" type="PackedScene" id=3] [ext_resource path="res://screens/battle/background.jpg" type="Texture" id=4] [ext_resource path="res://screens/battle/battle.gd" type="Script" id=5] +[ext_resource path="res://screens/battle/hand.gd" type="Script" id=6] [ext_resource path="res://decks/all.tscn" type="PackedScene" id=9] [node name="view" type="Panel"] anchor_right = 1.0 anchor_bottom = 1.0 +theme = ExtResource( 2 ) script = ExtResource( 5 ) __meta__ = { "_edit_use_anchors_": false @@ -36,10 +39,24 @@ margin_left = 240.0 margin_top = 1660.0 margin_right = 1050.0 margin_bottom = 1900.0 +script = ExtResource( 6 ) __meta__ = { "_edit_use_anchors_": false, "_editor_description_": "" } +attack = true + +[node name="skip" type="Button" parent="hand_attack"] +anchor_top = 1.0 +anchor_bottom = 1.0 +margin_left = -240.0 +margin_top = -69.0 +margin_right = 82.0 +margin_bottom = 20.0 +text = "Skip" +__meta__ = { +"_edit_use_anchors_": false +} [node name="hand_defend" type="Control" parent="."] visible = false @@ -48,6 +65,7 @@ margin_left = 1180.0 margin_top = 760.0 margin_right = 1990.0 margin_bottom = 1000.0 +script = ExtResource( 6 ) __meta__ = { "_edit_use_anchors_": false } diff --git a/screens/battle/hand.gd b/screens/battle/hand.gd new file mode 100644 index 0000000..cba9bc1 --- /dev/null +++ b/screens/battle/hand.gd @@ -0,0 +1,43 @@ +extends Control + +const NodesHelpers = preload("res://helpers/nodes.gd") + +signal turn_end + +export var attack = false +var cards = [] + +func _ready(): + if has_node("skip"): + $skip.connect("pressed", self, "emit_turn_end") + +func add_card(card): + """ Add a card to the hand + """ + cards.append(card) + NodesHelpers.set_parent(card, self) + card.connect("played", self, "on_card_played") + +func get_card_count(): + """ Get the number of cards in hand + """ + return len(cards) + +func rearrange(): + """ Rearrange visually the cards in hand + """ + var i = 0 + for card in cards: + card.set_hand_location(Vector2(i * 210, 0)) + i += 1 + +func on_card_played(card, anchor): + """ Called when a card is played + """ + card.queue_free() + cards.erase(card) + rearrange() + emit_turn_end() + +func emit_turn_end(): + emit_signal("turn_end") diff --git a/tests/hand_play_card.tscn b/tests/hand_play_card.tscn new file mode 100644 index 0000000..b7a62b2 --- /dev/null +++ b/tests/hand_play_card.tscn @@ -0,0 +1,43 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://screens/battle/hand.gd" type="Script" id=1] +[ext_resource path="res://arenas/anchor.tscn" type="PackedScene" id=2] +[ext_resource path="res://cards/spawn_breeze.tscn" type="PackedScene" id=3] +[ext_resource path="res://theme/ui.tres" type="Theme" id=4] + +[sub_resource type="GDScript" id=1] +script/source = "extends Node2D + +func _ready(): + $hand.add_card($card) + $hand.rearrange() +" + +[node name="Node2D" type="Node2D"] +script = SubResource( 1 ) + +[node name="anchor" parent="." instance=ExtResource( 2 )] +position = Vector2( 570, 900 ) + +[node name="hand" type="Control" parent="."] +margin_left = 160.0 +margin_top = 1050.0 +margin_right = 990.0 +margin_bottom = 1380.0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="card" parent="." instance=ExtResource( 3 )] + +[node name="help" type="Label" parent="."] +margin_left = 170.0 +margin_top = 470.0 +margin_right = 953.0 +margin_bottom = 519.0 +theme = ExtResource( 4 ) +text = "Drag the card to the anchor, to deploy it" +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/tests/unit_combat.tscn b/tests/unit_combat.tscn index a92f202..87717ad 100644 --- a/tests/unit_combat.tscn +++ b/tests/unit_combat.tscn @@ -23,15 +23,27 @@ position = Vector2( 400, 800 ) content = NodePath("flea") [node name="flea" parent="anchor" instance=ExtResource( 4 )] +base_move_points = 1 +base_hull_points = 2 +base_damage_points = 2 +attacker = true +playable = true [node name="anchor2" parent="." instance=ExtResource( 2 )] position = Vector2( 700, 800 ) content = NodePath("trapper") [node name="trapper" parent="anchor2" instance=ExtResource( 3 )] +modulate = Color( 0.5, 0.5, 0.5, 1 ) +base_move_points = 0 +base_hull_points = 1 +base_shield_points = 0 +base_damage_points = 2 [node name="anchor3" parent="." instance=ExtResource( 2 )] position = Vector2( 550, 1100 ) content = NodePath("avenger") [node name="avenger" parent="anchor3" instance=ExtResource( 5 )] +modulate = Color( 0.5, 0.5, 0.5, 1 ) +base_shield_points = 3 diff --git a/units/base_unit.gd b/units/base_unit.gd index 8d80523..5206414 100644 --- a/units/base_unit.gd +++ b/units/base_unit.gd @@ -11,6 +11,8 @@ export var base_move_points = 0 setget set_base_move_points export var base_hull_points = 0 setget set_base_hull_points export var base_shield_points = 0 setget set_base_shield_points export var base_damage_points = 0 setget set_base_damage_points +export var attacker = false setget set_attacker +export var playable = false setget set_playable var selected_anchor var dragged @@ -24,6 +26,8 @@ func _ready(): set_base_move_points(base_move_points) set_base_hull_points(base_hull_points) set_base_shield_points(base_shield_points) + set_attacker(attacker) + set_playable(playable) func destroy(): if get_parent() is Anchor: @@ -31,6 +35,21 @@ func destroy(): queue_free() +func set_attacker(val): + attacker = val + if has_node("points"): + if attacker: + $points.modulate = Color(1.0, 1.0, 1.0) + else: + $points.modulate = Color(1.0, 0.3, 0.3) + +func set_playable(val): + playable = val + if playable: + modulate = Color(1.0, 1.0, 1.0) + else: + modulate = Color(0.5, 0.5, 0.5) + func set_sprite(val): sprite = val if has_node("sprite"): @@ -55,36 +74,34 @@ func set_base_damage_points(val): base_damage_points = val if has_node("points"): $points.damage = val - + func can_target(other): - if other == self: + if not playable or not other or other == self: return false else: - return true + return other.attacker != attacker func can_be_used_on_anchor(anchor): - return anchor is Anchor and anchor.is_connected_to(get_parent()) and (anchor.is_empty() or can_target(anchor.get_content())) + return playable and anchor is Anchor and anchor.is_connected_to(get_parent()) and (anchor.is_empty() or can_target(anchor.get_content())) func update_anchors(): var cursor = rect_global_position + dragged if dragged else null selected_anchor = BattleHelper.update_anchors(get_tree(), cursor, funcref(self, "can_be_used_on_anchor")) func play(anchor): - if anchor.is_empty(): - move_to(anchor) - else: - var other = anchor.get_content() - if other.has_method("get_points"): - var won = attack(other) - if won: - move_to(anchor) - else: - return_to_base() + if playable: + if anchor.is_empty(): + move_to(anchor) else: + var other = anchor.get_content() + if other.has_method("get_points"): + attack(other) return_to_base() func move_to(anchor): - anchor.set_content(self) + if $points.move: + $points.move -= 1 + anchor.set_content(self) func get_points() -> UnitPoints: if $points is UnitPoints: @@ -125,6 +142,9 @@ func return_to_base(): $move_hint.set_point_position(1, Vector2(0, 0)) func _gui_input(event): + if not playable: + return + if event is InputEventMouseButton and event.button_index == 1: if event.pressed: dragged = event.position diff --git a/units/base_unit.tscn b/units/base_unit.tscn index a2a9fa4..336cbbb 100644 --- a/units/base_unit.tscn +++ b/units/base_unit.tscn @@ -23,6 +23,7 @@ position = Vector2( 50, 50 ) texture = ExtResource( 2 ) [node name="points" parent="." instance=ExtResource( 3 )] +modulate = Color( 1, 0.5, 0.5, 1 ) anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 @@ -31,5 +32,6 @@ margin_top = 70.0 margin_bottom = 115.0 [node name="move_hint" type="Line2D" parent="."] +visible = false points = PoolVector2Array( 50, 50, 0, 0 ) antialiased = true