From d47c2e513bab849c7e946717d6f374b38a0c9623 Mon Sep 17 00:00:00 2001 From: istamarahsan Date: Sat, 25 Jan 2025 15:07:03 +0700 Subject: [PATCH] feat: game loop --- data/cards/baraga.tres | 10 +----- demo_game.gd | 1 + player_side.gd | 2 +- project.godot | 4 +++ tcg/card/monster_card.gd | 8 +++++ tcg/match/event/event_damage_dealt.gd | 4 +++ tcg/match/event/event_monster_died.gd | 3 ++ tcg/match/match.gd | 22 ++++++++++-- tcg/match/match_manager.gd | 51 ++++++++++++++++++++++++--- tcg/match/match_monster.gd | 6 ++-- tcg/match/match_monster.tscn | 6 ++++ tcg/match/monster.tscn | 17 --------- 12 files changed, 97 insertions(+), 37 deletions(-) create mode 100644 tcg/match/match_monster.tscn delete mode 100644 tcg/match/monster.tscn diff --git a/data/cards/baraga.tres b/data/cards/baraga.tres index 0b217a1..a979300 100644 --- a/data/cards/baraga.tres +++ b/data/cards/baraga.tres @@ -1,14 +1,7 @@ -[gd_resource type="Resource" script_class="MonsterCard" load_steps=4 format=3 uid="uid://cs7q8i7bvohmj"] +[gd_resource type="Resource" script_class="MonsterCard" load_steps=2 format=3 uid="uid://cs7q8i7bvohmj"] [ext_resource type="Script" path="res://tcg/card/monster_card.gd" id="1_v65bb"] -[sub_resource type="Gradient" id="Gradient_mubps"] -offsets = PackedFloat32Array(0, 0.510204, 1) -colors = PackedColorArray(0, 0, 0, 1, 0.159184, 0.159184, 0.159184, 1, 1, 1, 1, 1) - -[sub_resource type="GradientTexture1D" id="GradientTexture1D_784dy"] -gradient = SubResource("Gradient_mubps") - [resource] script = ExtResource("1_v65bb") rock = 100 @@ -16,4 +9,3 @@ paper = 100 scissors = 100 energy_cost = 3 base_health = 170 -art = SubResource("GradientTexture1D_784dy") diff --git a/demo_game.gd b/demo_game.gd index d7c041b..359338d 100644 --- a/demo_game.gd +++ b/demo_game.gd @@ -32,6 +32,7 @@ var transition_history: Array[PhaseTransition] = [] func _on_match_manager_state_transitioned(transition: PhaseTransition): start_game_btn.visible = match_manager.phase == Match.Phase.PREGAME transition_history.append(transition) + print("Phase: ", Match.phase_to_str(transition.from), " -> ", Match.phase_to_str(transition.to)) func _on_start_game_button_button_up() -> void: match_manager.resolve({}) diff --git a/player_side.gd b/player_side.gd index 1660986..03eddf3 100644 --- a/player_side.gd +++ b/player_side.gd @@ -26,7 +26,7 @@ func _on_update(transition): if monster: monster_name_label.text = "Name: " + monster.card.id monster_health_label.text = "Health: " + str(monster.health) - incoming_damage_label.text = "Incoming Damage: " + str(monster.damage_incoming) + incoming_damage_label.text = "Incoming Damage: " + str(monster.health_delta) if match_manager.phase in [Match.Phase.SUMMON, Match.Phase.SUPPORT_1, Match.Phase.SUPPORT_2]: for card: Card in player.hand: if match_manager.phase == Match.Phase.SUMMON and card is not MonsterCard: diff --git a/project.godot b/project.godot index 0bfa3d6..f8f23d6 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,10 @@ run/main_scene="res://main.tscn" config/features=PackedStringArray("4.3", "Mobile") config/icon="res://icon.svg" +[autoload] + +Match="*res://tcg/match/match.gd" + [rendering] renderer/rendering_method="mobile" diff --git a/tcg/card/monster_card.gd b/tcg/card/monster_card.gd index 0d5304e..4b82987 100644 --- a/tcg/card/monster_card.gd +++ b/tcg/card/monster_card.gd @@ -6,3 +6,11 @@ class_name MonsterCard @export var scissors: int = 0 @export var energy_cost: int = 1 @export var base_health: int = 100 + +var damage: Dictionary: + get: + return { + "rock": rock, + "paper": paper, + "scissors": scissors + } \ No newline at end of file diff --git a/tcg/match/event/event_damage_dealt.gd b/tcg/match/event/event_damage_dealt.gd index e8b8f2a..bc342c7 100644 --- a/tcg/match/event/event_damage_dealt.gd +++ b/tcg/match/event/event_damage_dealt.gd @@ -3,3 +3,7 @@ class_name EventDamageDealt var target_player_id: int var amount: int + +func _init(target_player_id: int, amount: int) -> void: + self.target_player_id = target_player_id + self.amount = amount diff --git a/tcg/match/event/event_monster_died.gd b/tcg/match/event/event_monster_died.gd index 1c6341c..4a3ec4b 100644 --- a/tcg/match/event/event_monster_died.gd +++ b/tcg/match/event/event_monster_died.gd @@ -2,3 +2,6 @@ extends Event class_name EventMonsterDied var player_id: int + +func _init(player_id: int) -> void: + self.player_id = player_id diff --git a/tcg/match/match.gd b/tcg/match/match.gd index 1faf54f..64ec037 100644 --- a/tcg/match/match.gd +++ b/tcg/match/match.gd @@ -1,10 +1,26 @@ -extends Object -class_name Match +extends Node enum Phase { PREGAME = 0, SUMMON = 1, SUPPORT_1 = 2, RPS = 3, - SUPPORT_2 = 4 + SUPPORT_2 = 4, + END } + +func phase_to_str(phase: Phase): + match phase: + Phase.PREGAME: + return "Pregame" + Phase.SUMMON: + return "Summon" + Phase.SUPPORT_1: + return "Support 1" + Phase.RPS: + return "RPS" + Phase.SUPPORT_2: + return "Support 2" + Phase.END: + return "End" + diff --git a/tcg/match/match_manager.gd b/tcg/match/match_manager.gd index 799b712..19cfe87 100644 --- a/tcg/match/match_manager.gd +++ b/tcg/match/match_manager.gd @@ -70,12 +70,12 @@ func resolve(action_by_player_id: Dictionary) -> PhaseTransition: phase = Match.Phase.SUPPORT_1 Match.Phase.SUPPORT_1: var support_cards = [] - if player_1_action is ActionPlayCard and player_1_action.card is SupportCard: + if player_1_action is ActionPlayCard: support_cards.append({ "player": player_1, "card": player_1_action.card }) - if player_2_action is ActionPlayCard and player_2_action.card is SupportCard: + if player_2_action is ActionPlayCard: support_cards.append({ "player": player_2, "card": player_2_action.card @@ -87,10 +87,53 @@ func resolve(action_by_player_id: Dictionary) -> PhaseTransition: events.append_array(_resolve_support_card_effects(player, card)) phase = Match.Phase.RPS Match.Phase.RPS: + var tie = player_1_action.move == player_2_action.move var player_1_win = rps_wins[player_1_action.move] == player_2_action.move var player_2_win = rps_wins[player_2_action.move] == player_1_action.move - var tie = not player_1_win and not player_2_win + if tie or player_1_win: + player_2.monster.health_delta -= player_1.monster.card.damage[player_1_action.move] + if tie or player_2_win: + player_1.monster.health_delta -= player_2.monster.card.damage[player_2_action.move] + phase = Match.Phase.SUPPORT_2 + Match.Phase.SUPPORT_2: + var support_cards = [] + if player_1_action is ActionPlayCard: + support_cards.append({ + "player": player_1, + "card": player_1_action.card + }) + if player_2_action is ActionPlayCard: + support_cards.append({ + "player": player_2, + "card": player_2_action.card + }) + support_cards.sort_custom(func(a, b): return a.card.priority < b.card.priority) + for played_card in support_cards: + var player: MatchPlayer = played_card.player + var card: SupportCard = played_card.card + events.append_array(_resolve_support_card_effects(player, card)) + for player: MatchPlayer in players.values(): + var monster_final_health = player.monster.health + player.monster.health_delta + if monster_final_health <= 0: + player.monster = null + events.append(EventMonsterDied.new(player.id)) + else: + player.monster.health += player.monster.health_delta + player.monster.health_delta = 0 + var drawn_card = player.deck.pop_back() + if drawn_card: + player.hand.append(drawn_card) + events.append(EventCardDrawn.new(player.id, drawn_card)) + var players_without_monster = players.values().filter(func (player): return player.monster == null) + if players_without_monster.size() == 0: + phase = Match.Phase.SUPPORT_1 + elif players_without_monster.all( + func (player): return player.hand.any(func (it): return it is MonsterCard and it.energy_cost <= player.energy) + ): + phase = Match.Phase.SUMMON + else: + phase = Match.Phase.END _: pass var transition = PhaseTransition.new(events, initial_phase, phase) @@ -107,6 +150,6 @@ func _resolve_support_card_effects(player: MatchPlayer, card: SupportCard) -> Ar var magnitude = effect_instance.magnitude match effect.id: "heal": - player.monster.health += magnitude + player.monster.health_delta += magnitude events.append(EventSupportEffectApplied.new(player.id, effect_instance)) return events diff --git a/tcg/match/match_monster.gd b/tcg/match/match_monster.gd index e9dfb1c..f35e889 100644 --- a/tcg/match/match_monster.gd +++ b/tcg/match/match_monster.gd @@ -3,9 +3,9 @@ class_name MatchMonster var card: MonsterCard var health: int -var damage_incoming: int +var health_delta: int -func _init(card: MonsterCard, health: int, damage_incoming: int) -> void: +func _init(card: MonsterCard, health: int, health_delta: int) -> void: self.card = card self.health = health - self.damage_incoming = damage_incoming + self.health_delta = health_delta diff --git a/tcg/match/match_monster.tscn b/tcg/match/match_monster.tscn new file mode 100644 index 0000000..1f7131e --- /dev/null +++ b/tcg/match/match_monster.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://d3dm1bnooaxmu"] + +[ext_resource type="Script" path="res://tcg/match/match_monster.gd" id="1_o6dlj"] + +[node name="Monster" type="Node"] +script = ExtResource("1_o6dlj") diff --git a/tcg/match/monster.tscn b/tcg/match/monster.tscn deleted file mode 100644 index 9e1d1a5..0000000 --- a/tcg/match/monster.tscn +++ /dev/null @@ -1,17 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://d3dm1bnooaxmu"] - -[sub_resource type="GDScript" id="GDScript_dtwp4"] -script/source = "extends Node -class_name Monster - -var health: int -var card: MonsterCard -var damage_incoming: int = 0 - -func from_card(card: MonsterCard): - self.card = card - health = card.base_health -" - -[node name="Monster" type="Node"] -script = SubResource("GDScript_dtwp4")