feat: game loop

This commit is contained in:
istamarahsan 2025-01-25 15:07:03 +07:00
parent 7d05df6e39
commit d47c2e513b
12 changed files with 97 additions and 37 deletions

View file

@ -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"] [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] [resource]
script = ExtResource("1_v65bb") script = ExtResource("1_v65bb")
rock = 100 rock = 100
@ -16,4 +9,3 @@ paper = 100
scissors = 100 scissors = 100
energy_cost = 3 energy_cost = 3
base_health = 170 base_health = 170
art = SubResource("GradientTexture1D_784dy")

View file

@ -32,6 +32,7 @@ var transition_history: Array[PhaseTransition] = []
func _on_match_manager_state_transitioned(transition: PhaseTransition): func _on_match_manager_state_transitioned(transition: PhaseTransition):
start_game_btn.visible = match_manager.phase == Match.Phase.PREGAME start_game_btn.visible = match_manager.phase == Match.Phase.PREGAME
transition_history.append(transition) 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: func _on_start_game_button_button_up() -> void:
match_manager.resolve({}) match_manager.resolve({})

View file

@ -26,7 +26,7 @@ func _on_update(transition):
if monster: if monster:
monster_name_label.text = "Name: " + monster.card.id monster_name_label.text = "Name: " + monster.card.id
monster_health_label.text = "Health: " + str(monster.health) 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]: if match_manager.phase in [Match.Phase.SUMMON, Match.Phase.SUPPORT_1, Match.Phase.SUPPORT_2]:
for card: Card in player.hand: for card: Card in player.hand:
if match_manager.phase == Match.Phase.SUMMON and card is not MonsterCard: if match_manager.phase == Match.Phase.SUMMON and card is not MonsterCard:

View file

@ -15,6 +15,10 @@ run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.3", "Mobile") config/features=PackedStringArray("4.3", "Mobile")
config/icon="res://icon.svg" config/icon="res://icon.svg"
[autoload]
Match="*res://tcg/match/match.gd"
[rendering] [rendering]
renderer/rendering_method="mobile" renderer/rendering_method="mobile"

View file

@ -6,3 +6,11 @@ class_name MonsterCard
@export var scissors: int = 0 @export var scissors: int = 0
@export var energy_cost: int = 1 @export var energy_cost: int = 1
@export var base_health: int = 100 @export var base_health: int = 100
var damage: Dictionary:
get:
return {
"rock": rock,
"paper": paper,
"scissors": scissors
}

View file

@ -3,3 +3,7 @@ class_name EventDamageDealt
var target_player_id: int var target_player_id: int
var amount: int var amount: int
func _init(target_player_id: int, amount: int) -> void:
self.target_player_id = target_player_id
self.amount = amount

View file

@ -2,3 +2,6 @@ extends Event
class_name EventMonsterDied class_name EventMonsterDied
var player_id: int var player_id: int
func _init(player_id: int) -> void:
self.player_id = player_id

View file

@ -1,10 +1,26 @@
extends Object extends Node
class_name Match
enum Phase { enum Phase {
PREGAME = 0, PREGAME = 0,
SUMMON = 1, SUMMON = 1,
SUPPORT_1 = 2, SUPPORT_1 = 2,
RPS = 3, 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"

View file

@ -70,12 +70,12 @@ func resolve(action_by_player_id: Dictionary) -> PhaseTransition:
phase = Match.Phase.SUPPORT_1 phase = Match.Phase.SUPPORT_1
Match.Phase.SUPPORT_1: Match.Phase.SUPPORT_1:
var support_cards = [] 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({ support_cards.append({
"player": player_1, "player": player_1,
"card": player_1_action.card "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({ support_cards.append({
"player": player_2, "player": player_2,
"card": player_2_action.card "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)) events.append_array(_resolve_support_card_effects(player, card))
phase = Match.Phase.RPS phase = Match.Phase.RPS
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_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 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 pass
var transition = PhaseTransition.new(events, initial_phase, phase) 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 var magnitude = effect_instance.magnitude
match effect.id: match effect.id:
"heal": "heal":
player.monster.health += magnitude player.monster.health_delta += magnitude
events.append(EventSupportEffectApplied.new(player.id, effect_instance)) events.append(EventSupportEffectApplied.new(player.id, effect_instance))
return events return events

View file

@ -3,9 +3,9 @@ class_name MatchMonster
var card: MonsterCard var card: MonsterCard
var health: int 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.card = card
self.health = health self.health = health
self.damage_incoming = damage_incoming self.health_delta = health_delta

View file

@ -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")

View file

@ -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")