diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0af181c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +/android/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9457256 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "godotTools.editorPath.godot4": "c:\\Program Files\\Godot\\Godot_v4.3-stable_win64.exe" +} \ No newline at end of file diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..9d8b7fa --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..b26269c --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dcwx6pxubtivy" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +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 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..13329fd --- /dev/null +++ b/project.godot @@ -0,0 +1,16 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="dujorak" +run/main_scene="res://src/scenes/game.tscn" +config/features=PackedStringArray("4.3", "Forward Plus") +config/icon="res://icon.svg" diff --git a/src/assets/card_atlas.png b/src/assets/card_atlas.png new file mode 100644 index 0000000..2153e00 Binary files /dev/null and b/src/assets/card_atlas.png differ diff --git a/src/assets/card_atlas.png.import b/src/assets/card_atlas.png.import new file mode 100644 index 0000000..1431080 --- /dev/null +++ b/src/assets/card_atlas.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dj3k1qd5ahoa2" +path="res://.godot/imported/card_atlas.png-574f342db327405a75c03c3a7250402c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://src/assets/card_atlas.png" +dest_files=["res://.godot/imported/card_atlas.png-574f342db327405a75c03c3a7250402c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +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 diff --git a/src/scenes/game.tscn b/src/scenes/game.tscn new file mode 100644 index 0000000..f964a9c --- /dev/null +++ b/src/scenes/game.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=3 format=3 uid="uid://b3cyy67wp6hd0"] + +[ext_resource type="Script" path="res://src/scripts/game.gd" id="1_vl3q8"] +[ext_resource type="Script" path="res://src/scripts/ui.gd" id="2_dljv7"] + +[node name="Game" type="Node2D"] +script = ExtResource("1_vl3q8") + +[node name="UI" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("2_dljv7") diff --git a/src/scripts/game.gd b/src/scripts/game.gd new file mode 100644 index 0000000..8f7dd96 --- /dev/null +++ b/src/scripts/game.gd @@ -0,0 +1,389 @@ +extends Node2D + +enum Suits {HEARTS, DIAMONDS, CLUBS, SPADES} +enum Values {SIX = 6, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE} +enum GameState {SETUP, ATTACK, DEFEND, DRAW_PHASE, GAME_OVER} +enum JokerType {DOUBLE_ATTACK, TRUMP_CHANGE, DRAW_BLOCK} + +class Player: + var hand: Array = [] + var jokers_hand: Array = [] + var coins: int = 100 + var is_attacker: bool = false + + func add_joker_to_hand(joker_type: JokerType): + jokers_hand.append(joker_type) + + func has_jokers_in_hand() -> bool: + return jokers_hand.size() > 0 + + func remove_card(card): + hand.erase(card) + + func has_card_value(value) -> bool: + for card in hand: + if card.value == value: + return true + return false + +# Game Variables +var deck: Array = [] +var trump_suit: Suits +var player1: Player +var player2: Player +var current_attacker: Player +var current_defender: Player +var game_phase: GameState = GameState.SETUP +var active_jokers: Array = [] +var MAX_JOKERS: int = 3 + +# Battle Variables +var attacking_cards: Array = [] +var defending_cards: Array = [] +var table_pairs: Array = [] # [{attack: card, defend: card}] +var can_add_attack: bool = false + +# UI Reference +@onready var ui = $UI + +func _ready(): + player1 = Player.new() + player2 = Player.new() + current_attacker = player1 + current_defender = player2 + player1.is_attacker = true + + if ui: + ui.card_played.connect(_on_card_played) + ui.joker_played.connect(_on_joker_played) + ui.booster_bought.connect(_on_booster_bought) + ui.defend_button_pressed.connect(_on_defend_complete) + ui.take_cards_pressed.connect(_on_take_cards) + + start_new_game() + +func start_new_game(): + create_deck() + setup_initial_jokers() + shuffle_deck() + deal_cards() + set_trump() + game_phase = GameState.ATTACK + update_ui() + print("Spiel gestartet! ", current_attacker, " greift an") + +func create_deck(): + deck.clear() + for suit in [Suits.HEARTS, Suits.DIAMONDS, Suits.CLUBS, Suits.SPADES]: + for value in [Values.SIX, Values.SEVEN, Values.EIGHT, Values.NINE, Values.TEN, Values.JACK, Values.QUEEN, Values.KING, Values.ACE]: + deck.append({"suit": suit, "value": value, "is_joker": false}) + +func setup_initial_jokers(): + pass + +func shuffle_deck(): + deck.shuffle() + +func deal_cards(): + for i in range(6): + if deck.size() > 0: + var card = deck.pop_back() + if card.is_joker: + player1.add_joker_to_hand(card.joker_type) + else: + player1.hand.append(card) + + if deck.size() > 0: + var card = deck.pop_back() + if card.is_joker: + player2.add_joker_to_hand(card.joker_type) + else: + player2.hand.append(card) + +func set_trump(): + if deck.size() > 0: + var trump_card = deck[0] + if not trump_card.is_joker: + trump_suit = trump_card.suit + +# MAIN GAME LOGIC +func _on_card_played(card): + match game_phase: + GameState.ATTACK: + handle_attack(card) + GameState.DEFEND: + handle_defense(card) + +func handle_attack(card): + # Prüfen ob Angriff erlaubt + if not can_attack_with_card(card): + print("Angriff mit dieser Karte nicht möglich!") + return + + # Karte vom Angreifer entfernen + current_attacker.remove_card(card) + attacking_cards.append(card) + + print("Angriff mit: ", card) + + # Wechsel zu Verteidigung + game_phase = GameState.DEFEND + update_ui() + +func handle_defense(card): + if attacking_cards.size() == 0: + print("Nichts zu verteidigen!") + return + + var attack_card = attacking_cards[-1] # Letzte Angriffskarte + + if can_beat_card(attack_card, card): + # Erfolgreiche Verteidigung + current_defender.remove_card(card) + defending_cards.append(card) + + # Paar erstellen + table_pairs.append({"attack": attack_card, "defend": card}) + attacking_cards.pop_back() + + print("Verteidigt: ", attack_card, " mit ", card) + + # Prüfen ob weitere Angriffe möglich + can_add_attack = true + check_round_end() + else: + print("Karte kann nicht verteidigen!") + +func can_attack_with_card(card) -> bool: + # Erster Angriff: Jede Karte erlaubt + if attacking_cards.size() == 0 and table_pairs.size() == 0: + return true + + # Weitere Angriffe: Nur Werte die schon auf dem Tisch liegen + var table_values = [] + for pair in table_pairs: + table_values.append(pair.attack.value) + table_values.append(pair.defend.value) + for attack in attacking_cards: + table_values.append(attack.value) + + return card.value in table_values + +func can_beat_card(attacking_card, defending_card) -> bool: + # Trump schlägt alles außer höheren Trump + if defending_card.suit == trump_suit and attacking_card.suit != trump_suit: + return true + + # Gleiche Farbe: höherer Wert gewinnt + if attacking_card.suit == defending_card.suit: + return defending_card.value > attacking_card.value + + return false + +func check_round_end(): + # Alle Angriffe verteidigt + if attacking_cards.size() == 0: + if can_add_attack and current_attacker.hand.size() > 0: + # Angreifer kann weitere Karten spielen + game_phase = GameState.ATTACK + print("Weitere Angriffe möglich") + else: + # Runde erfolgreich verteidigt + end_round_defended() + else: + # Warten auf weitere Verteidigung + print("Warte auf Verteidigung...") + +func end_round_defended(): + print("Runde erfolgreich verteidigt!") + + # Karten vom Tisch entfernen + table_pairs.clear() + attacking_cards.clear() + defending_cards.clear() + can_add_attack = false + + # Rollen tauschen: Verteidiger wird Angreifer + swap_roles() + + # Karten nachziehen + draw_phase() + +func end_round_taken(): + print("Verteidiger nimmt alle Karten!") + + # Alle Karten an Verteidiger geben + for pair in table_pairs: + current_defender.hand.append(pair.attack) + current_defender.hand.append(pair.defend) + + for card in attacking_cards: + current_defender.hand.append(card) + + # Aufräumen + table_pairs.clear() + attacking_cards.clear() + defending_cards.clear() + can_add_attack = false + + # Angreifer bleibt Angreifer (Verteidiger nimmt) + # Karten nachziehen + draw_phase() + +func swap_roles(): + var temp = current_attacker + current_attacker = current_defender + current_defender = temp + + current_attacker.is_attacker = true + current_defender.is_attacker = false + + print("Rollen getauscht: ", current_attacker, " greift an") + +func draw_phase(): + game_phase = GameState.DRAW_PHASE + + # Angreifer zieht zuerst auf 6 Karten + draw_cards_to_six(current_attacker) + + # Dann Verteidiger + draw_cards_to_six(current_defender) + + # Spielende prüfen + if check_game_end(): + return + + # Nächste Runde starten + game_phase = GameState.ATTACK + update_ui() + +func draw_cards_to_six(player: Player): + while player.hand.size() < 6 and deck.size() > 0: + var card = deck.pop_back() + if card.is_joker: + player.add_joker_to_hand(card.joker_type) + # UI: Joker-Dialog anzeigen + show_joker_dialog(player, card.joker_type) + else: + player.hand.append(card) + +func show_joker_dialog(player: Player, joker_type: JokerType): + if player == player1: # Nur für menschlichen Spieler + ui.show_joker_choice(joker_type) + +func _on_joker_choice(play_immediately: bool, joker_type: JokerType): + if play_immediately: + play_joker_to_field(player1, joker_type) + # Sonst bleibt Joker auf der Hand (Risiko!) + +# UI Event Handlers +func _on_defend_complete(): + if game_phase == GameState.DEFEND: + # Verteidiger gibt auf, nimmt alle Karten + end_round_taken() + +func _on_take_cards(): + if game_phase == GameState.DEFEND: + end_round_taken() + +func _on_joker_played(joker_type): + if play_joker_to_field(player1, joker_type): + update_ui() + +func _on_booster_bought(): + var booster = buy_booster(player1) + for item in booster: + if item.type == "joker": + player1.add_joker_to_hand(item.joker_type) + elif item.type == "coins": + player1.coins += item.amount + update_ui() + +# Game End Logic +func check_game_end() -> bool: + if deck.size() == 0: + # Kein Deck mehr, prüfe wer keine Karten hat + if player1.hand.size() == 0: + if player1.has_jokers_in_hand(): + print("Spieler 1 verliert - Joker auf der Hand!") + game_phase = GameState.GAME_OVER + return true + else: + print("Spieler 1 gewinnt!") + game_phase = GameState.GAME_OVER + return true + + if player2.hand.size() == 0: + if player2.has_jokers_in_hand(): + print("Spieler 2 verliert - Joker auf der Hand!") + game_phase = GameState.GAME_OVER + return true + else: + print("Spieler 2 gewinnt!") + game_phase = GameState.GAME_OVER + return true + + return false + +# Joker System +func play_joker_to_field(player: Player, joker_type: JokerType) -> bool: + if active_jokers.size() >= MAX_JOKERS: + print("Maximale Joker-Anzahl erreicht!") + return false + + if joker_type in player.jokers_hand: + player.jokers_hand.erase(joker_type) + active_jokers.append(joker_type) + print("Joker aktiviert: ", joker_type) + apply_joker_effect(joker_type) + return true + return false + +func apply_joker_effect(joker_type: JokerType): + match joker_type: + JokerType.TRUMP_CHANGE: + print("Trump-Wechsel verfügbar!") + # UI für Trump-Auswahl + JokerType.DOUBLE_ATTACK: + print("Doppel-Angriff möglich!") + # Ermöglicht 2 Karten gleichzeitig + JokerType.DRAW_BLOCK: + print("Zieh-Block aktiv!") + # Gegner kann nicht ziehen + +func buy_booster(player: Player, cost: int = 50) -> Array: + if player.coins >= cost: + player.coins -= cost + var booster_content = [] + + for i in range(3): + if randf() < 0.3: + var joker_types = [JokerType.DOUBLE_ATTACK, JokerType.TRUMP_CHANGE, JokerType.DRAW_BLOCK] + var random_joker = joker_types[randi() % joker_types.size()] + booster_content.append({"type": "joker", "joker_type": random_joker}) + else: + booster_content.append({"type": "coins", "amount": randi() % 20 + 10}) + + return booster_content + return [] + +func update_ui(): + if ui: + ui.update_player_hand(player1.hand) + ui.update_opponent_hand(player2.hand.size()) + ui.update_joker_slots(active_jokers) + ui.update_coins(player1.coins) + ui.update_table(table_pairs, attacking_cards) + ui.update_game_state(game_phase, current_attacker == player1) + + if deck.size() > 0: + ui.update_trump(deck[0]) + +# Input for testing +func _input(event): + if event.is_action_pressed("ui_accept"): + _on_booster_bought() + + if event.is_action_pressed("ui_cancel"): + if game_phase == GameState.DEFEND: + _on_take_cards() \ No newline at end of file diff --git a/src/scripts/ui.gd b/src/scripts/ui.gd new file mode 100644 index 0000000..b122c61 --- /dev/null +++ b/src/scripts/ui.gd @@ -0,0 +1,372 @@ +extends Control + +# Signals +signal card_played(card) +signal joker_played(joker_type) +signal booster_bought +signal defend_button_pressed +signal take_cards_pressed + +# UI Components +var player_hand_container: HBoxContainer +var opponent_hand_container: HBoxContainer +var table_area: GridContainer +var trump_display: Control +var joker_slots_container: HBoxContainer +var coins_label: Label +var deck_display: Control +var game_state_label: Label +var action_buttons: HBoxContainer + +# Card Settings +var card_size: Vector2 = Vector2(80, 120) +var card_atlas: Texture2D + +func _ready(): + # Load card atlas if exists + if FileAccess.file_exists("res://src/assets/card_atlas.png"): + card_atlas = load("res://src/assets/card_atlas.png") + + setup_ui() + +func setup_ui(): + # Main layout + var main_vbox = VBoxContainer.new() + add_child(main_vbox) + main_vbox.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + + # Game state info + game_state_label = Label.new() + game_state_label.text = "Spiel wird geladen..." + game_state_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + main_vbox.add_child(game_state_label) + + # Top area (Opponent + Jokers) + var top_hbox = HBoxContainer.new() + main_vbox.add_child(top_hbox) + + setup_opponent_area(top_hbox) + setup_joker_area(top_hbox) + + # Middle area (Table + Trump) + var middle_hbox = HBoxContainer.new() + main_vbox.add_child(middle_hbox) + + setup_table_area(middle_hbox) + setup_trump_area(middle_hbox) + + # Action buttons + action_buttons = HBoxContainer.new() + action_buttons.alignment = BoxContainer.ALIGNMENT_CENTER + main_vbox.add_child(action_buttons) + + setup_action_buttons() + + # Bottom area (Player hand + Controls) + var bottom_vbox = VBoxContainer.new() + main_vbox.add_child(bottom_vbox) + + setup_controls(bottom_vbox) + setup_player_area(bottom_vbox) + +func setup_opponent_area(parent): + var area = VBoxContainer.new() + parent.add_child(area) + + var label = Label.new() + label.text = "Gegner" + area.add_child(label) + + opponent_hand_container = HBoxContainer.new() + area.add_child(opponent_hand_container) + +func setup_joker_area(parent): + var area = VBoxContainer.new() + parent.add_child(area) + + var label = Label.new() + label.text = "Joker (0/3)" + label.name = "JokerLabel" + area.add_child(label) + + joker_slots_container = HBoxContainer.new() + area.add_child(joker_slots_container) + + # Create 3 joker slots + for i in range(3): + var slot = create_joker_slot() + joker_slots_container.add_child(slot) + +func setup_table_area(parent): + var table_container = VBoxContainer.new() + parent.add_child(table_container) + + var label = Label.new() + label.text = "Spielfeld" + label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + table_container.add_child(label) + + table_area = GridContainer.new() + table_area.columns = 4 # Angriff/Verteidigung Paare + table_container.add_child(table_area) + +func setup_trump_area(parent): + var area = VBoxContainer.new() + parent.add_child(area) + + var label = Label.new() + label.text = "Trump" + area.add_child(label) + + trump_display = create_card_back() + area.add_child(trump_display) + + var deck_label = Label.new() + deck_label.text = "Deck" + area.add_child(deck_label) + + deck_display = create_card_back() + area.add_child(deck_display) + +func setup_action_buttons(): + var defend_btn = Button.new() + defend_btn.text = "Verteidigung beenden" + defend_btn.pressed.connect(_on_defend_button_pressed) + action_buttons.add_child(defend_btn) + + var take_btn = Button.new() + take_btn.text = "Karten nehmen" + take_btn.pressed.connect(_on_take_cards_pressed) + action_buttons.add_child(take_btn) + + # Initially hidden + action_buttons.visible = false + +func setup_controls(parent): + var controls = HBoxContainer.new() + parent.add_child(controls) + + coins_label = Label.new() + coins_label.text = "Münzen: 100" + controls.add_child(coins_label) + + var booster_btn = Button.new() + booster_btn.text = "Booster kaufen (50)" + booster_btn.pressed.connect(_on_booster_button_pressed) + controls.add_child(booster_btn) + +func setup_player_area(parent): + var area = VBoxContainer.new() + parent.add_child(area) + + var label = Label.new() + label.text = "Deine Karten" + area.add_child(label) + + player_hand_container = HBoxContainer.new() + area.add_child(player_hand_container) + +# Card Creation Functions +func create_card_ui(card, clickable: bool = true) -> Control: + var card_button = Button.new() + card_button.custom_minimum_size = card_size + card_button.disabled = not clickable + + if card.is_joker: + card_button.text = "JOKER\n" + str(card.joker_type) + card_button.modulate = Color.GOLD + else: + var suit_symbols = ["♥", "♦", "♣", "♠"] + var suit_text = suit_symbols[card.suit] + card_button.text = str(card.value) + "\n" + suit_text + + # Color coding + if card.suit in [0, 1]: # Hearts, Diamonds + card_button.modulate = Color.RED + else: # Clubs, Spades + card_button.modulate = Color.BLACK + + if clickable: + card_button.pressed.connect(_on_card_clicked.bind(card)) + + return card_button + +func create_card_back() -> Control: + var card_back = ColorRect.new() + card_back.color = Color.BLUE + card_back.custom_minimum_size = card_size + + var label = Label.new() + label.text = "🂠" + label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + card_back.add_child(label) + + return card_back + +func create_joker_slot() -> Control: + var slot = Panel.new() + slot.custom_minimum_size = card_size * 0.7 + + var style = StyleBoxFlat.new() + style.bg_color = Color.GRAY + style.border_width_left = 2 + style.border_width_right = 2 + style.border_width_top = 2 + style.border_width_bottom = 2 + style.border_color = Color.WHITE + slot.add_theme_stylebox_override("panel", style) + + return slot + +# Update Functions +func update_player_hand(cards: Array): + # Clear existing cards + for child in player_hand_container.get_children(): + child.queue_free() + + # Add new cards + for card in cards: + var card_ui = create_card_ui(card, true) + player_hand_container.add_child(card_ui) + +func update_opponent_hand(card_count: int): + # Clear existing cards + for child in opponent_hand_container.get_children(): + child.queue_free() + + # Add card backs + for i in range(card_count): + var card_back = create_card_back() + card_back.custom_minimum_size = card_size * 0.8 + opponent_hand_container.add_child(card_back) + +func update_table(table_pairs: Array, attacking_cards: Array): + # Clear existing table + for child in table_area.get_children(): + child.queue_free() + + # Show completed pairs + for pair in table_pairs: + var attack_card = create_card_ui(pair.attack, false) + attack_card.modulate = Color.ORANGE # Angriff + table_area.add_child(attack_card) + + var defend_card = create_card_ui(pair.defend, false) + defend_card.modulate = Color.GREEN # Verteidigung + table_area.add_child(defend_card) + + # Show undefended attacks + for card in attacking_cards: + var attack_card = create_card_ui(card, false) + attack_card.modulate = Color.RED # Unverteidigt + table_area.add_child(attack_card) + + # Empty slot for defense + var empty_slot = Panel.new() + empty_slot.custom_minimum_size = card_size + var style = StyleBoxFlat.new() + style.bg_color = Color.DARK_GRAY + empty_slot.add_theme_stylebox_override("panel", style) + table_area.add_child(empty_slot) + +func update_joker_slots(active_jokers: Array): + var label = joker_slots_container.get_parent().get_node("JokerLabel") + label.text = "Joker (" + str(active_jokers.size()) + "/3)" + + # Update slots + for i in range(3): + var slot = joker_slots_container.get_child(i) + if i < active_jokers.size(): + slot.modulate = Color.GREEN + + # Add joker label + var joker_label = Label.new() + joker_label.text = str(active_jokers[i]) + joker_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + joker_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + slot.add_child(joker_label) + else: + slot.modulate = Color.WHITE + +func update_coins(amount: int): + coins_label.text = "Münzen: " + str(amount) + +func update_trump(trump_card): + if trump_card and trump_display: + # Replace with actual card + trump_display.queue_free() + trump_display = create_card_ui(trump_card, false) + trump_display.modulate = Color.YELLOW + trump_display.get_parent().add_child(trump_display) + +func update_game_state(state, is_player_turn: bool): + match state: + 0: # GameState.SETUP + game_state_label.text = "Spiel wird vorbereitet..." + action_buttons.visible = false + 1: # GameState.ATTACK + if is_player_turn: + game_state_label.text = "Du bist am Zug - Wähle eine Angriffskarte" + else: + game_state_label.text = "Gegner greift an..." + action_buttons.visible = false + 2: # GameState.DEFEND + if is_player_turn: + game_state_label.text = "Gegner greift an - Verteidige oder nimm die Karten" + action_buttons.visible = true + else: + game_state_label.text = "Du greifst an - Gegner verteidigt..." + action_buttons.visible = false + 3: # GameState.DRAW_PHASE + game_state_label.text = "Karten werden nachgezogen..." + action_buttons.visible = false + 4: # GameState.GAME_OVER + game_state_label.text = "Spiel beendet!" + action_buttons.visible = false + +# Joker Dialog +func show_joker_choice(joker_type): + var dialog = AcceptDialog.new() + dialog.title = "Joker gezogen!" + + var vbox = VBoxContainer.new() + + var info_label = Label.new() + info_label.text = "Du hast einen " + str(joker_type) + " Joker gezogen!" + vbox.add_child(info_label) + + var play_btn = Button.new() + play_btn.text = "Sofort spielen" + play_btn.pressed.connect(_on_joker_play_immediate.bind(joker_type, dialog)) + vbox.add_child(play_btn) + + var keep_btn = Button.new() + keep_btn.text = "Behalten (Risiko!)" + keep_btn.pressed.connect(_on_joker_keep.bind(dialog)) + vbox.add_child(keep_btn) + + dialog.add_child(vbox) + add_child(dialog) + dialog.popup_centered() + +func _on_joker_play_immediate(joker_type, dialog): + joker_played.emit(joker_type) + dialog.queue_free() + +func _on_joker_keep(dialog): + print("Joker behalten - Vorsicht!") + dialog.queue_free() + +# Event Handlers +func _on_card_clicked(card): + card_played.emit(card) + +func _on_booster_button_pressed(): + booster_bought.emit() + +func _on_defend_button_pressed(): + defend_button_pressed.emit() + +func _on_take_cards_pressed(): + take_cards_pressed.emit()