Compare commits

...

9 Commits

19 changed files with 1139 additions and 136 deletions

28
.gitignore vendored
View File

@@ -1,3 +1,31 @@
# Godot 4+ specific ignores # Godot 4+ specific ignores
.godot/ .godot/
/android/ /android/
.temp
.nomedia
.TMP
*~libgit*
exported_binarys
# Godot-specific ignores
.import/
export.cfg
export_credentials.cfg
export_presets.cfg
# Imported translations (automatically generated from CSV files)
*.translation
# Mono-specific ignores
.mono/
data_*/
mono_crash.*.json
mono_crash.*.json
# Blender temp files
*.blend[1-9]*
*.blend~
# Draw.IO temp files
*.bkp

18
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "GDScript: Launch Project",
"type": "godot",
"request": "launch",
"project": "${workspaceFolder}",
"debug_collisions": false,
"debug_paths": false,
"debug_navigation": false,
"additional_options": ""
}
]
}

View File

@@ -1,3 +0,0 @@
{
"godotTools.editorPath.godot4": "c:\\Program Files\\Godot\\Godot_v4.3-stable_win64.exe"
}

View File

@@ -12,5 +12,9 @@ config_version=5
config/name="dujorak" config/name="dujorak"
run/main_scene="res://src/scenes/game.tscn" run/main_scene="res://src/scenes/game.tscn"
config/features=PackedStringArray("4.3", "Forward Plus") config/features=PackedStringArray("4.4", "Forward Plus")
config/icon="res://icon.svg" config/icon="res://icon.svg"
[autoload]
Globals="*res://src/scripts/globals.gd"

BIN
src/assets/card2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/card2_bump.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

916
src/assets/card_atlas.pdn Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dpahjbok4tj31"
path="res://.godot/imported/card_atlas_sprites.png-999525584d336e8b1ecafef7f7df1d0a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://src/assets/card_atlas_sprites.png"
dest_files=["res://.godot/imported/card_atlas_sprites.png-999525584d336e8b1ecafef7f7df1d0a.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

BIN
src/assets/cards.blend Normal file

Binary file not shown.

3
src/scenes/card.tscn Normal file
View File

@@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://kah10l7jtv2p"]
[node name="Card" type="Node3D"]

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=3 format=3 uid="uid://b3cyy67wp6hd0"] [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" uid="uid://dvscisoria6aj" path="res://src/scripts/game.gd" id="1_vl3q8"]
[ext_resource type="Script" path="res://src/scripts/ui.gd" id="2_dljv7"] [ext_resource type="Script" uid="uid://j8w01uew0ovu" path="res://src/scripts/ui.gd" id="2_dljv7"]
[node name="Game" type="Node2D"] [node name="Game" type="Node2D"]
script = ExtResource("1_vl3q8") script = ExtResource("1_vl3q8")

View File

@@ -1,25 +1,19 @@
extends Node2D 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: class Player:
var hand: Array = [] var hand: Array = []
var jokers_hand: Array = [] var jokers_hand: Array = []
var coins: int = 100 var coins: int = 100
var is_attacker: bool = false var is_attacker: bool = false
func add_joker_to_hand(joker_type: JokerType): func add_joker_to_hand(joker_type: Globals.JokerType):
jokers_hand.append(joker_type) jokers_hand.append(joker_type)
func has_jokers_in_hand() -> bool: func has_jokers_in_hand() -> bool:
return jokers_hand.size() > 0 return jokers_hand.size() > 0
func remove_card(card): func remove_card(card):
hand.erase(card) hand.erase(card)
func has_card_value(value) -> bool: func has_card_value(value) -> bool:
for card in hand: for card in hand:
if card.value == value: if card.value == value:
@@ -28,19 +22,19 @@ class Player:
# Game Variables # Game Variables
var deck: Array = [] var deck: Array = []
var trump_suit: Suits var trump_suit: Globals.Suits
var player1: Player var player1: Player
var player2: Player var player2: Player
var current_attacker: Player var current_attacker: Player
var current_defender: Player var current_defender: Player
var game_phase: GameState = GameState.SETUP var game_phase: Globals.GameState = Globals.GameState.SETUP
var active_jokers: Array = [] var active_jokers: Array = []
var MAX_JOKERS: int = 3 var MAX_JOKERS: int = 3
# Battle Variables # Battle Variables
var attacking_cards: Array = [] var attacking_cards: Array = []
var defending_cards: Array = [] var defending_cards: Array = []
var table_pairs: Array = [] # [{attack: card, defend: card}] var table_pairs: Array = [] # [{attack: card, defend: card}]
var can_add_attack: bool = false var can_add_attack: bool = false
# UI Reference # UI Reference
@@ -52,14 +46,14 @@ func _ready():
current_attacker = player1 current_attacker = player1
current_defender = player2 current_defender = player2
player1.is_attacker = true player1.is_attacker = true
if ui: if ui:
ui.card_played.connect(_on_card_played) ui.card_played.connect(_on_card_played)
ui.joker_played.connect(_on_joker_played) ui.joker_played.connect(_on_joker_played)
ui.booster_bought.connect(_on_booster_bought) ui.booster_bought.connect(_on_booster_bought)
ui.defend_button_pressed.connect(_on_defend_complete) ui.defend_button_pressed.connect(_on_defend_complete)
ui.take_cards_pressed.connect(_on_take_cards) ui.take_cards_pressed.connect(_on_take_cards)
start_new_game() start_new_game()
func start_new_game(): func start_new_game():
@@ -68,14 +62,14 @@ func start_new_game():
shuffle_deck() shuffle_deck()
deal_cards() deal_cards()
set_trump() set_trump()
game_phase = GameState.ATTACK game_phase = Globals.GameState.ATTACK
update_ui() update_ui()
print("Spiel gestartet! ", current_attacker, " greift an") print("Spiel gestartet! ", current_attacker, " greift an")
func create_deck(): func create_deck():
deck.clear() deck.clear()
for suit in [Suits.HEARTS, Suits.DIAMONDS, Suits.CLUBS, Suits.SPADES]: for suit in [Globals.Suits.HEARTS, Globals.Suits.DIAMONDS, Globals.Suits.CLUBS, Globals.Suits.SPADES]:
for value in [Values.SIX, Values.SEVEN, Values.EIGHT, Values.NINE, Values.TEN, Values.JACK, Values.QUEEN, Values.KING, Values.ACE]: for value in [Globals.Values.SIX, Globals.Values.SEVEN, Globals.Values.EIGHT, Globals.Values.NINE, Globals.Values.TEN, Globals.Values.JACK, Globals.Values.QUEEN, Globals.Values.KING, Globals.Values.ACE]:
deck.append({"suit": suit, "value": value, "is_joker": false}) deck.append({"suit": suit, "value": value, "is_joker": false})
func setup_initial_jokers(): func setup_initial_jokers():
@@ -92,7 +86,7 @@ func deal_cards():
player1.add_joker_to_hand(card.joker_type) player1.add_joker_to_hand(card.joker_type)
else: else:
player1.hand.append(card) player1.hand.append(card)
if deck.size() > 0: if deck.size() > 0:
var card = deck.pop_back() var card = deck.pop_back()
if card.is_joker: if card.is_joker:
@@ -109,9 +103,9 @@ func set_trump():
# MAIN GAME LOGIC # MAIN GAME LOGIC
func _on_card_played(card): func _on_card_played(card):
match game_phase: match game_phase:
GameState.ATTACK: Globals.GameState.ATTACK:
handle_attack(card) handle_attack(card)
GameState.DEFEND: Globals.GameState.DEFEND:
handle_defense(card) handle_defense(card)
func handle_attack(card): func handle_attack(card):
@@ -119,35 +113,35 @@ func handle_attack(card):
if not can_attack_with_card(card): if not can_attack_with_card(card):
print("Angriff mit dieser Karte nicht möglich!") print("Angriff mit dieser Karte nicht möglich!")
return return
# Karte vom Angreifer entfernen # Karte vom Angreifer entfernen
current_attacker.remove_card(card) current_attacker.remove_card(card)
attacking_cards.append(card) attacking_cards.append(card)
print("Angriff mit: ", card) print("Angriff mit: ", card)
# Wechsel zu Verteidigung # Wechsel zu Verteidigung
game_phase = GameState.DEFEND game_phase = Globals.GameState.DEFEND
update_ui() update_ui()
func handle_defense(card): func handle_defense(card):
if attacking_cards.size() == 0: if attacking_cards.size() == 0:
print("Nichts zu verteidigen!") print("Nichts zu verteidigen!")
return return
var attack_card = attacking_cards[-1] # Letzte Angriffskarte var attack_card = attacking_cards[-1] # Letzte Angriffskarte
if can_beat_card(attack_card, card): if can_beat_card(attack_card, card):
# Erfolgreiche Verteidigung # Erfolgreiche Verteidigung
current_defender.remove_card(card) current_defender.remove_card(card)
defending_cards.append(card) defending_cards.append(card)
# Paar erstellen # Paar erstellen
table_pairs.append({"attack": attack_card, "defend": card}) table_pairs.append({"attack": attack_card, "defend": card})
attacking_cards.pop_back() attacking_cards.pop_back()
print("Verteidigt: ", attack_card, " mit ", card) print("Verteidigt: ", attack_card, " mit ", card)
# Prüfen ob weitere Angriffe möglich # Prüfen ob weitere Angriffe möglich
can_add_attack = true can_add_attack = true
check_round_end() check_round_end()
@@ -158,26 +152,26 @@ func can_attack_with_card(card) -> bool:
# Erster Angriff: Jede Karte erlaubt # Erster Angriff: Jede Karte erlaubt
if attacking_cards.size() == 0 and table_pairs.size() == 0: if attacking_cards.size() == 0 and table_pairs.size() == 0:
return true return true
# Weitere Angriffe: Nur Werte die schon auf dem Tisch liegen # Weitere Angriffe: Nur Werte die schon auf dem Tisch liegen
var table_values = [] var table_Globals = []
for pair in table_pairs: for pair in table_pairs:
table_values.append(pair.attack.value) table_Globals.Values.append(pair.attack.value)
table_values.append(pair.defend.value) table_Globals.Values.append(pair.defend.value)
for attack in attacking_cards: for attack in attacking_cards:
table_values.append(attack.value) table_Globals.Values.append(attack.value)
return card.value in table_values return card.value in table_Globals.Values
func can_beat_card(attacking_card, defending_card) -> bool: func can_beat_card(attacking_card, defending_card) -> bool:
# Trump schlägt alles außer höheren Trump # Trump schlägt alles außer höheren Trump
if defending_card.suit == trump_suit and attacking_card.suit != trump_suit: if defending_card.suit == trump_suit and attacking_card.suit != trump_suit:
return true return true
# Gleiche Farbe: höherer Wert gewinnt # Gleiche Farbe: höherer Wert gewinnt
if attacking_card.suit == defending_card.suit: if attacking_card.suit == defending_card.suit:
return defending_card.value > attacking_card.value return defending_card.value > attacking_card.value
return false return false
func check_round_end(): func check_round_end():
@@ -185,7 +179,7 @@ func check_round_end():
if attacking_cards.size() == 0: if attacking_cards.size() == 0:
if can_add_attack and current_attacker.hand.size() > 0: if can_add_attack and current_attacker.hand.size() > 0:
# Angreifer kann weitere Karten spielen # Angreifer kann weitere Karten spielen
game_phase = GameState.ATTACK game_phase = Globals.GameState.ATTACK
print("Weitere Angriffe möglich") print("Weitere Angriffe möglich")
else: else:
# Runde erfolgreich verteidigt # Runde erfolgreich verteidigt
@@ -196,36 +190,36 @@ func check_round_end():
func end_round_defended(): func end_round_defended():
print("Runde erfolgreich verteidigt!") print("Runde erfolgreich verteidigt!")
# Karten vom Tisch entfernen # Karten vom Tisch entfernen
table_pairs.clear() table_pairs.clear()
attacking_cards.clear() attacking_cards.clear()
defending_cards.clear() defending_cards.clear()
can_add_attack = false can_add_attack = false
# Rollen tauschen: Verteidiger wird Angreifer # Rollen tauschen: Verteidiger wird Angreifer
swap_roles() swap_roles()
# Karten nachziehen # Karten nachziehen
draw_phase() draw_phase()
func end_round_taken(): func end_round_taken():
print("Verteidiger nimmt alle Karten!") print("Verteidiger nimmt alle Karten!")
# Alle Karten an Verteidiger geben # Alle Karten an Verteidiger geben
for pair in table_pairs: for pair in table_pairs:
current_defender.hand.append(pair.attack) current_defender.hand.append(pair.attack)
current_defender.hand.append(pair.defend) current_defender.hand.append(pair.defend)
for card in attacking_cards: for card in attacking_cards:
current_defender.hand.append(card) current_defender.hand.append(card)
# Aufräumen # Aufräumen
table_pairs.clear() table_pairs.clear()
attacking_cards.clear() attacking_cards.clear()
defending_cards.clear() defending_cards.clear()
can_add_attack = false can_add_attack = false
# Angreifer bleibt Angreifer (Verteidiger nimmt) # Angreifer bleibt Angreifer (Verteidiger nimmt)
# Karten nachziehen # Karten nachziehen
draw_phase() draw_phase()
@@ -234,27 +228,27 @@ func swap_roles():
var temp = current_attacker var temp = current_attacker
current_attacker = current_defender current_attacker = current_defender
current_defender = temp current_defender = temp
current_attacker.is_attacker = true current_attacker.is_attacker = true
current_defender.is_attacker = false current_defender.is_attacker = false
print("Rollen getauscht: ", current_attacker, " greift an") print("Rollen getauscht: ", current_attacker, " greift an")
func draw_phase(): func draw_phase():
game_phase = GameState.DRAW_PHASE game_phase = Globals.GameState.DRAW_PHASE
# Angreifer zieht zuerst auf 6 Karten # Angreifer zieht zuerst auf 6 Karten
draw_cards_to_six(current_attacker) draw_cards_to_six(current_attacker)
# Dann Verteidiger # Dann Verteidiger
draw_cards_to_six(current_defender) draw_cards_to_six(current_defender)
# Spielende prüfen # Spielende prüfen
if check_game_end(): if check_game_end():
return return
# Nächste Runde starten # Nächste Runde starten
game_phase = GameState.ATTACK game_phase = Globals.GameState.ATTACK
update_ui() update_ui()
func draw_cards_to_six(player: Player): func draw_cards_to_six(player: Player):
@@ -267,23 +261,23 @@ func draw_cards_to_six(player: Player):
else: else:
player.hand.append(card) player.hand.append(card)
func show_joker_dialog(player: Player, joker_type: JokerType): func show_joker_dialog(player: Player, joker_type: Globals.JokerType):
if player == player1: # Nur für menschlichen Spieler if player == player1: # Nur für menschlichen Spieler
ui.show_joker_choice(joker_type) ui.show_joker_choice(joker_type)
func _on_joker_choice(play_immediately: bool, joker_type: JokerType): func _on_joker_choice(play_immediately: bool, joker_type: Globals.JokerType):
if play_immediately: if play_immediately:
play_joker_to_field(player1, joker_type) play_joker_to_field(player1, joker_type)
# Sonst bleibt Joker auf der Hand (Risiko!) # Sonst bleibt Joker auf der Hand (Risiko!)
# UI Event Handlers # UI Event Handlers
func _on_defend_complete(): func _on_defend_complete():
if game_phase == GameState.DEFEND: if game_phase == Globals.GameState.DEFEND:
# Verteidiger gibt auf, nimmt alle Karten # Verteidiger gibt auf, nimmt alle Karten
end_round_taken() end_round_taken()
func _on_take_cards(): func _on_take_cards():
if game_phase == GameState.DEFEND: if game_phase == Globals.GameState.DEFEND:
end_round_taken() end_round_taken()
func _on_joker_played(joker_type): func _on_joker_played(joker_type):
@@ -306,31 +300,31 @@ func check_game_end() -> bool:
if player1.hand.size() == 0: if player1.hand.size() == 0:
if player1.has_jokers_in_hand(): if player1.has_jokers_in_hand():
print("Spieler 1 verliert - Joker auf der Hand!") print("Spieler 1 verliert - Joker auf der Hand!")
game_phase = GameState.GAME_OVER game_phase = Globals.GameState.GAME_OVER
return true return true
else: else:
print("Spieler 1 gewinnt!") print("Spieler 1 gewinnt!")
game_phase = GameState.GAME_OVER game_phase = Globals.GameState.GAME_OVER
return true return true
if player2.hand.size() == 0: if player2.hand.size() == 0:
if player2.has_jokers_in_hand(): if player2.has_jokers_in_hand():
print("Spieler 2 verliert - Joker auf der Hand!") print("Spieler 2 verliert - Joker auf der Hand!")
game_phase = GameState.GAME_OVER game_phase = Globals.GameState.GAME_OVER
return true return true
else: else:
print("Spieler 2 gewinnt!") print("Spieler 2 gewinnt!")
game_phase = GameState.GAME_OVER game_phase = Globals.GameState.GAME_OVER
return true return true
return false return false
# Joker System # Joker System
func play_joker_to_field(player: Player, joker_type: JokerType) -> bool: func play_joker_to_field(player: Player, joker_type: Globals.JokerType) -> bool:
if active_jokers.size() >= MAX_JOKERS: if active_jokers.size() >= MAX_JOKERS:
print("Maximale Joker-Anzahl erreicht!") print("Maximale Joker-Anzahl erreicht!")
return false return false
if joker_type in player.jokers_hand: if joker_type in player.jokers_hand:
player.jokers_hand.erase(joker_type) player.jokers_hand.erase(joker_type)
active_jokers.append(joker_type) active_jokers.append(joker_type)
@@ -339,15 +333,15 @@ func play_joker_to_field(player: Player, joker_type: JokerType) -> bool:
return true return true
return false return false
func apply_joker_effect(joker_type: JokerType): func apply_joker_effect(joker_type: Globals.JokerType):
match joker_type: match joker_type:
JokerType.TRUMP_CHANGE: Globals.JokerType.TRUMP_CHANGE:
print("Trump-Wechsel verfügbar!") print("Trump-Wechsel verfügbar!")
# UI für Trump-Auswahl # UI für Trump-Auswahl
JokerType.DOUBLE_ATTACK: Globals.JokerType.DOUBLE_ATTACK:
print("Doppel-Angriff möglich!") print("Doppel-Angriff möglich!")
# Ermöglicht 2 Karten gleichzeitig # Ermöglicht 2 Karten gleichzeitig
JokerType.DRAW_BLOCK: Globals.JokerType.DRAW_BLOCK:
print("Zieh-Block aktiv!") print("Zieh-Block aktiv!")
# Gegner kann nicht ziehen # Gegner kann nicht ziehen
@@ -355,15 +349,15 @@ func buy_booster(player: Player, cost: int = 50) -> Array:
if player.coins >= cost: if player.coins >= cost:
player.coins -= cost player.coins -= cost
var booster_content = [] var booster_content = []
for i in range(3): for i in range(3):
if randf() < 0.3: if randf() < 0.3:
var joker_types = [JokerType.DOUBLE_ATTACK, JokerType.TRUMP_CHANGE, JokerType.DRAW_BLOCK] var joker_types = [Globals.JokerType.DOUBLE_ATTACK, Globals.JokerType.TRUMP_CHANGE, Globals.JokerType.DRAW_BLOCK]
var random_joker = joker_types[randi() % joker_types.size()] var random_joker = joker_types[randi() % joker_types.size()]
booster_content.append({"type": "joker", "joker_type": random_joker}) booster_content.append({"type": "joker", "joker_type": random_joker})
else: else:
booster_content.append({"type": "coins", "amount": randi() % 20 + 10}) booster_content.append({"type": "coins", "amount": randi() % 20 + 10})
return booster_content return booster_content
return [] return []
@@ -375,15 +369,15 @@ func update_ui():
ui.update_coins(player1.coins) ui.update_coins(player1.coins)
ui.update_table(table_pairs, attacking_cards) ui.update_table(table_pairs, attacking_cards)
ui.update_game_state(game_phase, current_attacker == player1) ui.update_game_state(game_phase, current_attacker == player1)
if deck.size() > 0: if deck.is_empty():
ui.update_trump(deck[0]) ui.update_trump(deck[0])
# Input for testing # Input for testing
func _input(event): func _input(event):
if event.is_action_pressed("ui_accept"): if event.is_action_pressed("ui_accept"):
_on_booster_bought() _on_booster_bought()
if event.is_action_pressed("ui_cancel"): if event.is_action_pressed("ui_cancel"):
if game_phase == GameState.DEFEND: if game_phase == Globals.GameState.DEFEND:
_on_take_cards() _on_take_cards()

1
src/scripts/game.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://dvscisoria6aj

6
src/scripts/globals.gd Normal file
View File

@@ -0,0 +1,6 @@
extends Node
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}

View File

@@ -0,0 +1 @@
uid://cp7yt3d324xiv

View File

@@ -26,7 +26,7 @@ func _ready():
# Load card atlas if exists # Load card atlas if exists
if FileAccess.file_exists("res://src/assets/card_atlas.png"): if FileAccess.file_exists("res://src/assets/card_atlas.png"):
card_atlas = load("res://src/assets/card_atlas.png") card_atlas = load("res://src/assets/card_atlas.png")
setup_ui() setup_ui()
func setup_ui(): func setup_ui():
@@ -34,64 +34,64 @@ func setup_ui():
var main_vbox = VBoxContainer.new() var main_vbox = VBoxContainer.new()
add_child(main_vbox) add_child(main_vbox)
main_vbox.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) main_vbox.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
# Game state info # Game state info
game_state_label = Label.new() game_state_label = Label.new()
game_state_label.text = "Spiel wird geladen..." game_state_label.text = "Spiel wird geladen..."
game_state_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER game_state_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
main_vbox.add_child(game_state_label) main_vbox.add_child(game_state_label)
# Top area (Opponent + Jokers) # Top area (Opponent + Jokers)
var top_hbox = HBoxContainer.new() var top_hbox = HBoxContainer.new()
main_vbox.add_child(top_hbox) main_vbox.add_child(top_hbox)
setup_opponent_area(top_hbox) setup_opponent_area(top_hbox)
setup_joker_area(top_hbox) setup_joker_area(top_hbox)
# Middle area (Table + Trump) # Middle area (Table + Trump)
var middle_hbox = HBoxContainer.new() var middle_hbox = HBoxContainer.new()
main_vbox.add_child(middle_hbox) main_vbox.add_child(middle_hbox)
setup_table_area(middle_hbox) setup_table_area(middle_hbox)
setup_trump_area(middle_hbox) setup_trump_area(middle_hbox)
# Action buttons # Action buttons
action_buttons = HBoxContainer.new() action_buttons = HBoxContainer.new()
action_buttons.alignment = BoxContainer.ALIGNMENT_CENTER action_buttons.alignment = BoxContainer.ALIGNMENT_CENTER
main_vbox.add_child(action_buttons) main_vbox.add_child(action_buttons)
setup_action_buttons() setup_action_buttons()
# Bottom area (Player hand + Controls) # Bottom area (Player hand + Controls)
var bottom_vbox = VBoxContainer.new() var bottom_vbox = VBoxContainer.new()
main_vbox.add_child(bottom_vbox) main_vbox.add_child(bottom_vbox)
setup_controls(bottom_vbox) setup_controls(bottom_vbox)
setup_player_area(bottom_vbox) setup_player_area(bottom_vbox)
func setup_opponent_area(parent): func setup_opponent_area(parent):
var area = VBoxContainer.new() var area = VBoxContainer.new()
parent.add_child(area) parent.add_child(area)
var label = Label.new() var label = Label.new()
label.text = "Gegner" label.text = "Gegner"
area.add_child(label) area.add_child(label)
opponent_hand_container = HBoxContainer.new() opponent_hand_container = HBoxContainer.new()
area.add_child(opponent_hand_container) area.add_child(opponent_hand_container)
func setup_joker_area(parent): func setup_joker_area(parent):
var area = VBoxContainer.new() var area = VBoxContainer.new()
parent.add_child(area) parent.add_child(area)
var label = Label.new() var label = Label.new()
label.text = "Joker (0/3)" label.text = "Joker (0/3)"
label.name = "JokerLabel" label.name = "JokerLabel"
area.add_child(label) area.add_child(label)
joker_slots_container = HBoxContainer.new() joker_slots_container = HBoxContainer.new()
area.add_child(joker_slots_container) area.add_child(joker_slots_container)
# Create 3 joker slots # Create 3 joker slots
for i in range(3): for i in range(3):
var slot = create_joker_slot() var slot = create_joker_slot()
@@ -100,12 +100,12 @@ func setup_joker_area(parent):
func setup_table_area(parent): func setup_table_area(parent):
var table_container = VBoxContainer.new() var table_container = VBoxContainer.new()
parent.add_child(table_container) parent.add_child(table_container)
var label = Label.new() var label = Label.new()
label.text = "Spielfeld" label.text = "Spielfeld"
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
table_container.add_child(label) table_container.add_child(label)
table_area = GridContainer.new() table_area = GridContainer.new()
table_area.columns = 4 # Angriff/Verteidigung Paare table_area.columns = 4 # Angriff/Verteidigung Paare
table_container.add_child(table_area) table_container.add_child(table_area)
@@ -113,18 +113,18 @@ func setup_table_area(parent):
func setup_trump_area(parent): func setup_trump_area(parent):
var area = VBoxContainer.new() var area = VBoxContainer.new()
parent.add_child(area) parent.add_child(area)
var label = Label.new() var label = Label.new()
label.text = "Trump" label.text = "Trump"
area.add_child(label) area.add_child(label)
trump_display = create_card_back() trump_display = create_card_back()
area.add_child(trump_display) area.add_child(trump_display)
var deck_label = Label.new() var deck_label = Label.new()
deck_label.text = "Deck" deck_label.text = "Deck"
area.add_child(deck_label) area.add_child(deck_label)
deck_display = create_card_back() deck_display = create_card_back()
area.add_child(deck_display) area.add_child(deck_display)
@@ -133,23 +133,23 @@ func setup_action_buttons():
defend_btn.text = "Verteidigung beenden" defend_btn.text = "Verteidigung beenden"
defend_btn.pressed.connect(_on_defend_button_pressed) defend_btn.pressed.connect(_on_defend_button_pressed)
action_buttons.add_child(defend_btn) action_buttons.add_child(defend_btn)
var take_btn = Button.new() var take_btn = Button.new()
take_btn.text = "Karten nehmen" take_btn.text = "Karten nehmen"
take_btn.pressed.connect(_on_take_cards_pressed) take_btn.pressed.connect(_on_take_cards_pressed)
action_buttons.add_child(take_btn) action_buttons.add_child(take_btn)
# Initially hidden # Initially hidden
action_buttons.visible = false action_buttons.visible = false
func setup_controls(parent): func setup_controls(parent):
var controls = HBoxContainer.new() var controls = HBoxContainer.new()
parent.add_child(controls) parent.add_child(controls)
coins_label = Label.new() coins_label = Label.new()
coins_label.text = "Münzen: 100" coins_label.text = "Münzen: 100"
controls.add_child(coins_label) controls.add_child(coins_label)
var booster_btn = Button.new() var booster_btn = Button.new()
booster_btn.text = "Booster kaufen (50)" booster_btn.text = "Booster kaufen (50)"
booster_btn.pressed.connect(_on_booster_button_pressed) booster_btn.pressed.connect(_on_booster_button_pressed)
@@ -158,11 +158,11 @@ func setup_controls(parent):
func setup_player_area(parent): func setup_player_area(parent):
var area = VBoxContainer.new() var area = VBoxContainer.new()
parent.add_child(area) parent.add_child(area)
var label = Label.new() var label = Label.new()
label.text = "Deine Karten" label.text = "Deine Karten"
area.add_child(label) area.add_child(label)
player_hand_container = HBoxContainer.new() player_hand_container = HBoxContainer.new()
area.add_child(player_hand_container) area.add_child(player_hand_container)
@@ -171,7 +171,7 @@ func create_card_ui(card, clickable: bool = true) -> Control:
var card_button = Button.new() var card_button = Button.new()
card_button.custom_minimum_size = card_size card_button.custom_minimum_size = card_size
card_button.disabled = not clickable card_button.disabled = not clickable
if card.is_joker: if card.is_joker:
card_button.text = "JOKER\n" + str(card.joker_type) card_button.text = "JOKER\n" + str(card.joker_type)
card_button.modulate = Color.GOLD card_button.modulate = Color.GOLD
@@ -179,35 +179,35 @@ func create_card_ui(card, clickable: bool = true) -> Control:
var suit_symbols = ["", "", "", ""] var suit_symbols = ["", "", "", ""]
var suit_text = suit_symbols[card.suit] var suit_text = suit_symbols[card.suit]
card_button.text = str(card.value) + "\n" + suit_text card_button.text = str(card.value) + "\n" + suit_text
# Color coding # Color coding
if card.suit in [0, 1]: # Hearts, Diamonds if card.suit in [0, 1]: # Hearts, Diamonds
card_button.modulate = Color.RED card_button.modulate = Color.RED
else: # Clubs, Spades else: # Clubs, Spades
card_button.modulate = Color.BLACK card_button.modulate = Color.BLACK
if clickable: if clickable:
card_button.pressed.connect(_on_card_clicked.bind(card)) card_button.pressed.connect(_on_card_clicked.bind(card))
return card_button return card_button
func create_card_back() -> Control: func create_card_back() -> Control:
var card_back = ColorRect.new() var card_back = ColorRect.new()
card_back.color = Color.BLUE card_back.color = Color.BLUE
card_back.custom_minimum_size = card_size card_back.custom_minimum_size = card_size
var label = Label.new() var label = Label.new()
label.text = "🂠" label.text = "🂠"
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
card_back.add_child(label) card_back.add_child(label)
return card_back return card_back
func create_joker_slot() -> Control: func create_joker_slot() -> Control:
var slot = Panel.new() var slot = Panel.new()
slot.custom_minimum_size = card_size * 0.7 slot.custom_minimum_size = card_size * 0.7
var style = StyleBoxFlat.new() var style = StyleBoxFlat.new()
style.bg_color = Color.GRAY style.bg_color = Color.GRAY
style.border_width_left = 2 style.border_width_left = 2
@@ -216,7 +216,7 @@ func create_joker_slot() -> Control:
style.border_width_bottom = 2 style.border_width_bottom = 2
style.border_color = Color.WHITE style.border_color = Color.WHITE
slot.add_theme_stylebox_override("panel", style) slot.add_theme_stylebox_override("panel", style)
return slot return slot
# Update Functions # Update Functions
@@ -224,7 +224,7 @@ func update_player_hand(cards: Array):
# Clear existing cards # Clear existing cards
for child in player_hand_container.get_children(): for child in player_hand_container.get_children():
child.queue_free() child.queue_free()
# Add new cards # Add new cards
for card in cards: for card in cards:
var card_ui = create_card_ui(card, true) var card_ui = create_card_ui(card, true)
@@ -234,7 +234,7 @@ func update_opponent_hand(card_count: int):
# Clear existing cards # Clear existing cards
for child in opponent_hand_container.get_children(): for child in opponent_hand_container.get_children():
child.queue_free() child.queue_free()
# Add card backs # Add card backs
for i in range(card_count): for i in range(card_count):
var card_back = create_card_back() var card_back = create_card_back()
@@ -245,23 +245,23 @@ func update_table(table_pairs: Array, attacking_cards: Array):
# Clear existing table # Clear existing table
for child in table_area.get_children(): for child in table_area.get_children():
child.queue_free() child.queue_free()
# Show completed pairs # Show completed pairs
for pair in table_pairs: for pair in table_pairs:
var attack_card = create_card_ui(pair.attack, false) var attack_card = create_card_ui(pair.attack, false)
attack_card.modulate = Color.ORANGE # Angriff attack_card.modulate = Color.ORANGE # Angriff
table_area.add_child(attack_card) table_area.add_child(attack_card)
var defend_card = create_card_ui(pair.defend, false) var defend_card = create_card_ui(pair.defend, false)
defend_card.modulate = Color.GREEN # Verteidigung defend_card.modulate = Color.GREEN # Verteidigung
table_area.add_child(defend_card) table_area.add_child(defend_card)
# Show undefended attacks # Show undefended attacks
for card in attacking_cards: for card in attacking_cards:
var attack_card = create_card_ui(card, false) var attack_card = create_card_ui(card, false)
attack_card.modulate = Color.RED # Unverteidigt attack_card.modulate = Color.RED # Unverteidigt
table_area.add_child(attack_card) table_area.add_child(attack_card)
# Empty slot for defense # Empty slot for defense
var empty_slot = Panel.new() var empty_slot = Panel.new()
empty_slot.custom_minimum_size = card_size empty_slot.custom_minimum_size = card_size
@@ -273,13 +273,13 @@ func update_table(table_pairs: Array, attacking_cards: Array):
func update_joker_slots(active_jokers: Array): func update_joker_slots(active_jokers: Array):
var label = joker_slots_container.get_parent().get_node("JokerLabel") var label = joker_slots_container.get_parent().get_node("JokerLabel")
label.text = "Joker (" + str(active_jokers.size()) + "/3)" label.text = "Joker (" + str(active_jokers.size()) + "/3)"
# Update slots # Update slots
for i in range(3): for i in range(3):
var slot = joker_slots_container.get_child(i) var slot = joker_slots_container.get_child(i)
if i < active_jokers.size(): if i < active_jokers.size():
slot.modulate = Color.GREEN slot.modulate = Color.GREEN
# Add joker label # Add joker label
var joker_label = Label.new() var joker_label = Label.new()
joker_label.text = str(active_jokers[i]) joker_label.text = str(active_jokers[i])
@@ -329,23 +329,23 @@ func update_game_state(state, is_player_turn: bool):
func show_joker_choice(joker_type): func show_joker_choice(joker_type):
var dialog = AcceptDialog.new() var dialog = AcceptDialog.new()
dialog.title = "Joker gezogen!" dialog.title = "Joker gezogen!"
var vbox = VBoxContainer.new() var vbox = VBoxContainer.new()
var info_label = Label.new() var info_label = Label.new()
info_label.text = "Du hast einen " + str(joker_type) + " Joker gezogen!" info_label.text = "Du hast einen " + str(joker_type) + " Joker gezogen!"
vbox.add_child(info_label) vbox.add_child(info_label)
var play_btn = Button.new() var play_btn = Button.new()
play_btn.text = "Sofort spielen" play_btn.text = "Sofort spielen"
play_btn.pressed.connect(_on_joker_play_immediate.bind(joker_type, dialog)) play_btn.pressed.connect(_on_joker_play_immediate.bind(joker_type, dialog))
vbox.add_child(play_btn) vbox.add_child(play_btn)
var keep_btn = Button.new() var keep_btn = Button.new()
keep_btn.text = "Behalten (Risiko!)" keep_btn.text = "Behalten (Risiko!)"
keep_btn.pressed.connect(_on_joker_keep.bind(dialog)) keep_btn.pressed.connect(_on_joker_keep.bind(dialog))
vbox.add_child(keep_btn) vbox.add_child(keep_btn)
dialog.add_child(vbox) dialog.add_child(vbox)
add_child(dialog) add_child(dialog)
dialog.popup_centered() dialog.popup_centered()

1
src/scripts/ui.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://j8w01uew0ovu