uploud new
This commit is contained in:
parent
f780897670
commit
63d73ad605
@ -1,327 +0,0 @@
|
||||
import pygame
|
||||
import random
|
||||
import sys
|
||||
import os
|
||||
|
||||
# -------------------------------
|
||||
# Country–Capital Memory Game
|
||||
# -------------------------------
|
||||
|
||||
CARD_BACK_COLOR = (100, 100, 200)
|
||||
CARD_FRONT_COLOR = (230, 230, 250)
|
||||
MATCH_COLOR = (120, 200, 120)
|
||||
TEXT_COLOR = (0, 0, 0)
|
||||
BG_COLOR = (50, 50, 80)
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600
|
||||
FPS = 30
|
||||
# Design-Bild (für Kartenrückseite + optionalen Hintergrund)
|
||||
DESIGN_FILE = "GlobalHintergrund.png"
|
||||
|
||||
|
||||
|
||||
class MemoryGame:
|
||||
def __init__(self):
|
||||
self.deck = []
|
||||
self.pair_map = {}
|
||||
self.matched = []
|
||||
self.revealed = []
|
||||
self.scores = [0, 0]
|
||||
self.current_player = 0
|
||||
self.font = None
|
||||
self.card_rects = []
|
||||
self.selected = []
|
||||
self.found_pairs = 0
|
||||
self.total_pairs = 0
|
||||
self.running = True
|
||||
self.awaiting_confirmation = False
|
||||
self.confirmation_result = None
|
||||
self.correct_answer_expected = None
|
||||
self.state = "continent" # continent → americas → difficulty → pairs → game
|
||||
self.buttons = []
|
||||
self.selected_continents = []
|
||||
self.level = None
|
||||
self.pair_count = 6 # Default
|
||||
|
||||
# -------------------------------
|
||||
# Card Loading
|
||||
# -------------------------------
|
||||
def load_cards(self, filename):
|
||||
"""Loads pairs from a text file."""
|
||||
if not os.path.exists(filename):
|
||||
print(f"⚠️ File not found: {filename}")
|
||||
return []
|
||||
|
||||
pairs = []
|
||||
with open(filename, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
parts = line.strip().split()
|
||||
if len(parts) >= 2:
|
||||
pairs.append((parts[0], parts[1]))
|
||||
return pairs
|
||||
|
||||
def prepare_deck(self):
|
||||
"""Loads all relevant continent + difficulty files."""
|
||||
self.deck = []
|
||||
for continent in self.selected_continents:
|
||||
base = continent
|
||||
if self.level == "Easy":
|
||||
self.deck += self.load_cards(base + "-major.txt")
|
||||
elif self.level == "Normal":
|
||||
self.deck += self.load_cards(base + "-major.txt")
|
||||
self.deck += self.load_cards(base + "-Minor.txt")
|
||||
elif self.level == "Hard":
|
||||
self.deck += self.load_cards(base + "-major.txt")
|
||||
self.deck += self.load_cards(base + "-Minor.txt")
|
||||
self.deck += self.load_cards(base + "-Dependent.txt")
|
||||
|
||||
if not self.deck:
|
||||
print("⚠️ No cards loaded, check text files.")
|
||||
sys.exit()
|
||||
|
||||
random.shuffle(self.deck)
|
||||
# Limit to selected pair count
|
||||
self.deck = self.deck[:self.pair_count]
|
||||
|
||||
def setup_game(self):
|
||||
self.cards = []
|
||||
self.pair_map = {}
|
||||
for country, capital in self.deck:
|
||||
self.cards.append(country)
|
||||
self.cards.append(capital)
|
||||
self.pair_map[country] = capital
|
||||
self.pair_map[capital] = country
|
||||
random.shuffle(self.cards)
|
||||
self.matched = [False] * len(self.cards)
|
||||
self.revealed = [False] * len(self.cards)
|
||||
self.total_pairs = len(self.deck)
|
||||
self.card_rects = []
|
||||
self.selected = []
|
||||
|
||||
cols = 4
|
||||
rows = (len(self.cards) + cols - 1) // cols
|
||||
margin = 10
|
||||
card_width = (SCREEN_WIDTH - (cols + 1) * margin) // cols
|
||||
card_height = (SCREEN_HEIGHT - (rows + 1) * margin - 100) // rows
|
||||
y_offset = 80
|
||||
|
||||
for i, _ in enumerate(self.cards):
|
||||
col = i % cols
|
||||
row = i // cols
|
||||
x = margin + col * (card_width + margin)
|
||||
y = y_offset + margin + row * (card_height + margin)
|
||||
rect = pygame.Rect(x, y, card_width, card_height)
|
||||
self.card_rects.append(rect)
|
||||
|
||||
# -------------------------------
|
||||
# Drawing Menus
|
||||
# -------------------------------
|
||||
def draw_menu(self, screen, title, options):
|
||||
screen.fill(BG_COLOR)
|
||||
title_text = self.font.render(title, True, (255, 255, 255))
|
||||
screen.blit(title_text, (SCREEN_WIDTH // 2 - title_text.get_width() // 2, 100))
|
||||
self.buttons = []
|
||||
|
||||
for i, option in enumerate(options):
|
||||
rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, 200 + i * 70, 300, 50)
|
||||
pygame.draw.rect(screen, (100, 100, 250), rect)
|
||||
pygame.draw.rect(screen, (255, 255, 255), rect, 2)
|
||||
text = self.font.render(option, True, (255, 255, 255))
|
||||
screen.blit(text, (rect.centerx - text.get_width() // 2, rect.centery - text.get_height() // 2))
|
||||
self.buttons.append((rect, option))
|
||||
pygame.display.flip()
|
||||
|
||||
def draw_game(self, screen):
|
||||
screen.fill(BG_COLOR)
|
||||
title = self.font.render(f"Player {self.current_player + 1}'s turn", True, (255, 255, 255))
|
||||
screen.blit(title, (20, 20))
|
||||
score_text = self.font.render(f"Scores: P1={self.scores[0]} P2={self.scores[1]}", True, (200, 200, 200))
|
||||
screen.blit(score_text, (20, 50))
|
||||
|
||||
for i, rect in enumerate(self.card_rects):
|
||||
if self.matched[i]:
|
||||
color = MATCH_COLOR
|
||||
elif self.revealed[i]:
|
||||
color = CARD_FRONT_COLOR
|
||||
else:
|
||||
color = CARD_BACK_COLOR
|
||||
pygame.draw.rect(screen, color, rect)
|
||||
pygame.draw.rect(screen, (0, 0, 0), rect, 2)
|
||||
if self.revealed[i] or self.matched[i]:
|
||||
text = self.font.render(self.cards[i], True, TEXT_COLOR)
|
||||
text_rect = text.get_rect(center=rect.center)
|
||||
screen.blit(text, text_rect)
|
||||
|
||||
if self.awaiting_confirmation:
|
||||
self.draw_confirmation_box(screen)
|
||||
pygame.display.flip()
|
||||
|
||||
def draw_confirmation_box(self, screen): #y-axis Box
|
||||
box_rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT // 2 - 320, 300, 160)
|
||||
pygame.draw.rect(screen, (250, 250, 250), box_rect)
|
||||
pygame.draw.rect(screen, (0, 0, 0), box_rect, 3)
|
||||
text = self.font.render("Is that correct?", True, (0, 0, 0))
|
||||
screen.blit(text, (box_rect.centerx - text.get_width() // 2, box_rect.y + 20))
|
||||
|
||||
yes_rect = pygame.Rect(box_rect.x + 50, box_rect.y + 90, 80, 40)
|
||||
no_rect = pygame.Rect(box_rect.x + 170, box_rect.y + 90, 80, 40)
|
||||
pygame.draw.rect(screen, (0, 200, 0), yes_rect)
|
||||
pygame.draw.rect(screen, (200, 0, 0), no_rect)
|
||||
yes_text = self.font.render("Yes", True, (255, 255, 255))
|
||||
no_text = self.font.render("No", True, (255, 255, 255))
|
||||
screen.blit(yes_text, (yes_rect.centerx - yes_text.get_width() // 2, yes_rect.centery - yes_text.get_height() // 2))
|
||||
screen.blit(no_text, (no_rect.centerx - no_text.get_width() // 2, no_rect.centery - no_text.get_height() // 2))
|
||||
self.yes_rect, self.no_rect = yes_rect, no_rect
|
||||
|
||||
# -------------------------------
|
||||
# Handling Clicks
|
||||
# -------------------------------
|
||||
def handle_click(self, pos):
|
||||
if self.state in ["continent", "americas", "difficulty", "pairs"]:
|
||||
for rect, option in self.buttons:
|
||||
if rect.collidepoint(pos):
|
||||
if self.state == "continent":
|
||||
if option == "Americas":
|
||||
self.state = "americas"
|
||||
elif option == "All Continents":
|
||||
self.selected_continents = ["Europe", "Asia", "Africa", "Oceania", "North-America", "South-America"]
|
||||
self.state = "difficulty"
|
||||
else:
|
||||
self.selected_continents = [option]
|
||||
self.state = "difficulty"
|
||||
|
||||
elif self.state == "americas":
|
||||
if option == "North-America":
|
||||
self.selected_continents = ["North-America"]
|
||||
elif option == "South-America":
|
||||
self.selected_continents = ["South-America"]
|
||||
elif option == "Americas":
|
||||
self.selected_continents = ["North-America", "South-America"]
|
||||
self.state = "difficulty"
|
||||
|
||||
elif self.state == "difficulty":
|
||||
self.level = option
|
||||
self.state = "pairs"
|
||||
|
||||
elif self.state == "pairs":
|
||||
self.pair_count = int(option)
|
||||
self.prepare_deck()
|
||||
self.setup_game()
|
||||
self.state = "game"
|
||||
return
|
||||
|
||||
elif self.state == "game":
|
||||
if self.awaiting_confirmation:
|
||||
if self.yes_rect.collidepoint(pos):
|
||||
self.confirmation_result = "yes"
|
||||
elif self.no_rect.collidepoint(pos):
|
||||
self.confirmation_result = "no"
|
||||
return
|
||||
|
||||
for i, rect in enumerate(self.card_rects):
|
||||
if rect.collidepoint(pos) and not self.revealed[i] and not self.matched[i]:
|
||||
self.revealed[i] = True
|
||||
self.selected.append(i)
|
||||
return
|
||||
|
||||
# -------------------------------
|
||||
# Game Logic Most important
|
||||
# -------------------------------
|
||||
def check_selected(self):
|
||||
if self.state != "game":
|
||||
return
|
||||
|
||||
# Wenn zwei Karten ausgewählt wurden → prüfen
|
||||
if len(self.selected) == 2 and not self.awaiting_confirmation:
|
||||
a, b = self.selected
|
||||
is_match = self.pair_map.get(self.cards[a]) == self.cards[b]
|
||||
self.correct_answer_expected = "yes" if is_match else "no"
|
||||
self.awaiting_confirmation = True
|
||||
|
||||
# Wenn der Spieler im "Is that correct?"-Dialog geantwortet hat
|
||||
elif self.awaiting_confirmation and self.confirmation_result:
|
||||
a, b = self.selected
|
||||
expected = self.correct_answer_expected
|
||||
player_correct = self.confirmation_result == expected
|
||||
|
||||
if player_correct:
|
||||
# Spieler hat korrekt geantwortet
|
||||
if expected == "yes":
|
||||
# Richtiges Paar bestätigt
|
||||
self.matched[a] = self.matched[b] = True
|
||||
self.scores[self.current_player] += 1
|
||||
self.found_pairs += 1
|
||||
else:
|
||||
# "No" richtig bestätigt → kein Paar
|
||||
self.revealed[a] = self.revealed[b] = False
|
||||
else:
|
||||
# Spieler hat sich vertan → Karten umdrehen & Punkt abziehen
|
||||
self.scores[self.current_player] -= 1
|
||||
self.revealed[a] = self.revealed[b] = False
|
||||
|
||||
# Reset für nächsten Zug
|
||||
self.awaiting_confirmation = False
|
||||
self.confirmation_result = None
|
||||
self.selected = []
|
||||
self.current_player = 1 - self.current_player
|
||||
|
||||
# -------------------------------
|
||||
# Main Game Loop
|
||||
# -------------------------------
|
||||
def run(self):
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
pygame.display.set_caption("Country–Capital Memory Game")
|
||||
clock = pygame.time.Clock()
|
||||
self.font = pygame.font.SysFont(None, 32)
|
||||
|
||||
while self.running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
self.running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
||||
self.handle_click(event.pos)
|
||||
|
||||
if self.state == "continent":
|
||||
self.draw_menu(screen, "Select Continent", ["Europe", "Americas", "Asia", "Africa", "Oceania", "All Continents"])
|
||||
elif self.state == "americas":
|
||||
self.draw_menu(screen, "Select Region", ["North-America", "South-America", "Americas"])
|
||||
elif self.state == "difficulty":
|
||||
self.draw_menu(screen, "Select Difficulty", ["Easy", "Normal", "Hard"])
|
||||
elif self.state == "pairs":
|
||||
self.draw_menu(screen, "Select Number of Pairs", ["4", "6", "8", "10", "12"])
|
||||
elif self.state == "game":
|
||||
self.draw_game(screen)
|
||||
self.check_selected()
|
||||
if self.found_pairs == self.total_pairs:
|
||||
self.display_winner(screen)
|
||||
pygame.display.flip()
|
||||
pygame.time.wait(4000)
|
||||
self.running = False
|
||||
|
||||
clock.tick(FPS)
|
||||
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
|
||||
# -------------------------------
|
||||
# Winner Display
|
||||
# -------------------------------
|
||||
def display_winner(self, screen):
|
||||
if self.scores[0] > self.scores[1]:
|
||||
text = "🏆 Player 1 Wins!"
|
||||
elif self.scores[1] > self.scores[0]:
|
||||
text = "🏆 Player 2 Wins!"
|
||||
else:
|
||||
text = "🤝 Draw!"
|
||||
win_text = self.font.render(text, True, (255, 255, 0))
|
||||
rect = win_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
|
||||
screen.blit(win_text, rect)
|
||||
|
||||
|
||||
# -------------------------------
|
||||
# Run the Game
|
||||
# -------------------------------
|
||||
if __name__ == "__main__":
|
||||
game = MemoryGame()
|
||||
game.run()
|
||||
|
||||
34
app.py
Normal file
34
app.py
Normal file
@ -0,0 +1,34 @@
|
||||
from flask import Flask, request, render_template
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
# Option A: Direkt die Python-Funktion ausführen (wenn dein Spiel in demselben Prozess laufen darf)
|
||||
# from global_match_memory import run_memory
|
||||
|
||||
@app.get("/")
|
||||
def home():
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
@app.get("/start")
|
||||
def start_game():
|
||||
players = request.args.get("players", "1")
|
||||
# --- Option A: direkt aufrufen ---
|
||||
# run_memory(int(players))
|
||||
# return "started"
|
||||
|
||||
# --- Option B: separates Fenster/Prozess (robuster) ---
|
||||
# Startet global_match_memory.py als eigenen Prozess mit Argument "players"
|
||||
py = sys.executable # aktueller Python-Interpreter
|
||||
script_path = os.path.join(os.path.dirname(__file__), "global_match_memory.py")
|
||||
subprocess.Popen([py, script_path, players])
|
||||
return "started"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Auf Mac/Windows lokal erreichbar: http://localhost:5000
|
||||
app.run(host="127.0.0.1", port=5000, debug=True)
|
||||
@ -1,334 +1,345 @@
|
||||
import pygame
|
||||
import sys
|
||||
import random
|
||||
import sys
|
||||
import os
|
||||
from typing import List, Tuple
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Design / Layout
|
||||
# ----------------------------------------------------------
|
||||
WINDOW_W, WINDOW_H = 900, 900
|
||||
BG_COLOR = (10, 58, 94) # Global-Match Blau
|
||||
HUD_BAR_H = 88
|
||||
PADDING = 28
|
||||
GRID_COLS, GRID_ROWS = 4, 3 # 12 Karten (6 Paare)
|
||||
GAP = 18
|
||||
CARD_RADIUS = 20
|
||||
CARD_BORDER = (220, 226, 235)
|
||||
CARD_FACE = (255, 255, 255)
|
||||
CARD_TEXT = (22, 44, 66)
|
||||
BADGE_BG = (18, 122, 138)
|
||||
BADGE_TEXT = (255, 255, 255)
|
||||
HIGHLIGHT = (255, 224, 128)
|
||||
# -------------------------------
|
||||
# Country–Capital Memory Game
|
||||
# -------------------------------
|
||||
|
||||
LOGO_FILE = "LogoSpiel.png" # <— Dein Logo (Rückseite)
|
||||
CARD_BACK_COLOR = (100, 100, 200)
|
||||
CARD_FRONT_COLOR = (230, 230, 250)
|
||||
MATCH_COLOR = (120, 200, 120)
|
||||
TEXT_COLOR = (0, 0, 0)
|
||||
BG_COLOR = (50, 50, 80)
|
||||
SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600
|
||||
FPS = 30
|
||||
# Design-Bild (für Kartenrückseite + optionalen Hintergrund)
|
||||
DESIGN_FILE = "GlobalHintergrund.png"
|
||||
|
||||
MISMATCH_DELAY_MS = 900
|
||||
SINGLEPLAYER_SECONDS = 90
|
||||
FPS = 60
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Daten (Deutsch)
|
||||
# ----------------------------------------------------------
|
||||
DATA = {
|
||||
"Europa": [
|
||||
("Deutschland", "Berlin"), ("Frankreich", "Paris"), ("Italien", "Rom"),
|
||||
("Spanien", "Madrid"), ("Portugal", "Lissabon"), ("Niederlande", "Amsterdam"),
|
||||
("Belgien", "Brüssel"), ("Österreich", "Wien"), ("Schweiz", "Bern"),
|
||||
("Polen", "Warschau"), ("Tschechien", "Prag"), ("Ungarn", "Budapest"),
|
||||
("Dänemark", "Kopenhagen"), ("Schweden", "Stockholm"), ("Norwegen", "Oslo")
|
||||
],
|
||||
"Amerika": [
|
||||
("USA", "Washington, D.C."), ("Kanada", "Ottawa"), ("Mexiko", "Mexiko-Stadt"),
|
||||
("Brasilien", "Brasília"), ("Argentinien", "Buenos Aires"), ("Chile", "Santiago"),
|
||||
("Peru", "Lima"), ("Kolumbien", "Bogotá"), ("Venezuela", "Caracas"),
|
||||
("Uruguay", "Montevideo"), ("Bolivien", "Sucre"), ("Ecuador", "Quito")
|
||||
],
|
||||
"Asien": [
|
||||
("China", "Peking"), ("Japan", "Tokio"), ("Südkorea", "Seoul"),
|
||||
("Indien", "Neu-Delhi"), ("Pakistan", "Islamabad"),
|
||||
("Bangladesch", "Dhaka"), ("Sri Lanka", "Sri Jayewardenepura Kotte"),
|
||||
("Nepal", "Kathmandu"), ("Saudi-Arabien", "Riad"),
|
||||
("VAE", "Abu Dhabi"), ("Türkei", "Ankara"), ("Indonesien", "Jakarta"),
|
||||
("Malaysia", "Kuala Lumpur"), ("Thailand", "Bangkok"), ("Vietnam", "Hanoi")
|
||||
],
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Helpers
|
||||
# ----------------------------------------------------------
|
||||
def load_logo_scaled(size: Tuple[int, int]) -> pygame.Surface:
|
||||
"""Lädt LogoSpiel.png und skaliert mit 10% Rand. Fallback: dunkles GM-Pattern."""
|
||||
w, h = size
|
||||
surf = pygame.Surface((w, h), pygame.SRCALPHA)
|
||||
# weiße Karte
|
||||
pygame.draw.rect(surf, CARD_FACE, (0, 0, w, h), border_radius=CARD_RADIUS)
|
||||
pygame.draw.rect(surf, CARD_BORDER, (0, 0, w, h), width=2, border_radius=CARD_RADIUS)
|
||||
class MemoryGame:
|
||||
def __init__(self):
|
||||
self.deck = []
|
||||
self.pair_map = {}
|
||||
self.matched = []
|
||||
self.revealed = []
|
||||
self.scores = [0, 0]
|
||||
self.current_player = 0
|
||||
self.font = None
|
||||
self.card_rects = []
|
||||
self.selected = []
|
||||
self.found_pairs = 0
|
||||
self.total_pairs = 0
|
||||
self.running = True
|
||||
self.awaiting_confirmation = False
|
||||
self.confirmation_result = None
|
||||
self.correct_answer_expected = None
|
||||
self.state = "continent" # continent → americas → difficulty → pairs → game
|
||||
self.buttons = []
|
||||
self.selected_continents = []
|
||||
self.level = None
|
||||
self.pair_count = 6 # Default
|
||||
|
||||
inner_pad = int(min(w, h) * 0.12)
|
||||
logo_rect = pygame.Rect(inner_pad, inner_pad, w - 2*inner_pad, h - 2*inner_pad)
|
||||
# -------------------------------
|
||||
# Card Loading
|
||||
# -------------------------------
|
||||
def load_cards(self, filename):
|
||||
"""Loads pairs from a text file."""
|
||||
if not os.path.exists(filename):
|
||||
print(f"⚠️ File not found: {filename}")
|
||||
return []
|
||||
|
||||
if os.path.exists(LOGO_FILE):
|
||||
try:
|
||||
img = pygame.image.load(LOGO_FILE).convert_alpha()
|
||||
img = scale_to_fit(img, logo_rect.size)
|
||||
surf.blit(img, (
|
||||
logo_rect.centerx - img.get_width() // 2,
|
||||
logo_rect.centery - img.get_height() // 2
|
||||
))
|
||||
return surf
|
||||
except Exception:
|
||||
pass
|
||||
pairs = []
|
||||
with open(filename, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
parts = line.strip().split()
|
||||
if len(parts) >= 2:
|
||||
pairs.append((parts[0], parts[1]))
|
||||
return pairs
|
||||
|
||||
# Fallback: Text "GLOBAL MATCH"
|
||||
font = pygame.font.SysFont(None, int(h * 0.16), bold=True)
|
||||
t1 = font.render("GLOBAL", True, (10, 80, 110))
|
||||
t2 = font.render("MATCH", True, (240, 180, 60))
|
||||
surf.blit(t1, (w//2 - t1.get_width()//2, h//2 - t1.get_height()))
|
||||
surf.blit(t2, (w//2 - t2.get_width()//2, h//2 + 4))
|
||||
return surf
|
||||
def prepare_deck(self):
|
||||
"""Loads all relevant continent + difficulty files."""
|
||||
self.deck = []
|
||||
for continent in self.selected_continents:
|
||||
base = continent
|
||||
if self.level == "Easy":
|
||||
self.deck += self.load_cards(base + "-major.txt")
|
||||
elif self.level == "Normal":
|
||||
self.deck += self.load_cards(base + "-major.txt")
|
||||
self.deck += self.load_cards(base + "-Minor.txt")
|
||||
elif self.level == "Hard":
|
||||
self.deck += self.load_cards(base + "-major.txt")
|
||||
self.deck += self.load_cards(base + "-Minor.txt")
|
||||
self.deck += self.load_cards(base + "-Dependent.txt")
|
||||
|
||||
def scale_to_fit(img: pygame.Surface, target_size: Tuple[int, int]) -> pygame.Surface:
|
||||
tw, th = target_size
|
||||
iw, ih = img.get_width(), img.get_height()
|
||||
scale = min(tw / iw, th / ih)
|
||||
return pygame.transform.smoothscale(img, (int(iw * scale), int(ih * scale)))
|
||||
|
||||
def wrap_text(text: str, font: pygame.font.Font, max_w: int) -> List[str]:
|
||||
words = text.split()
|
||||
lines, line = [], ""
|
||||
for w in words:
|
||||
t = (line + " " + w).strip()
|
||||
if font.size(t)[0] <= max_w:
|
||||
line = t
|
||||
else:
|
||||
if line:
|
||||
lines.append(line)
|
||||
line = w
|
||||
if line:
|
||||
lines.append(line)
|
||||
return lines
|
||||
|
||||
def pick_payloads(level: str, n_pairs=6) -> List[dict]:
|
||||
pool = DATA[level][:] if level in DATA else DATA["Europa"][:]
|
||||
random.shuffle(pool)
|
||||
chosen = pool[:n_pairs]
|
||||
payloads = []
|
||||
pid = 0
|
||||
for land, cap in chosen:
|
||||
payloads.append({"pair": pid, "label": land, "kind": "country"})
|
||||
payloads.append({"pair": pid, "label": cap, "kind": "capital"})
|
||||
pid += 1
|
||||
random.shuffle(payloads)
|
||||
return payloads
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Card
|
||||
# ----------------------------------------------------------
|
||||
class Card:
|
||||
def __init__(self, rect: pygame.Rect, payload: dict, fonts, back_img: pygame.Surface):
|
||||
self.rect = rect
|
||||
self.payload = payload
|
||||
self.font, self.small = fonts
|
||||
self.back = pygame.transform.smoothscale(back_img, (rect.w, rect.h))
|
||||
self.front = pygame.Surface((rect.w, rect.h), pygame.SRCALPHA)
|
||||
self.is_revealed = False
|
||||
self.is_matched = False
|
||||
self._render_front()
|
||||
|
||||
def _render_front(self):
|
||||
w, h = self.rect.w, self.rect.h
|
||||
# weiße Karte + Rand
|
||||
pygame.draw.rect(self.front, CARD_FACE, (0, 0, w, h), border_radius=CARD_RADIUS)
|
||||
pygame.draw.rect(self.front, CARD_BORDER, (0, 0, w, h), width=2, border_radius=CARD_RADIUS)
|
||||
|
||||
# Badge
|
||||
badge = "Land" if self.payload["kind"] == "country" else "Hauptstadt"
|
||||
bsurf = self.small.render(badge, True, BADGE_TEXT)
|
||||
bw, bh = bsurf.get_size()
|
||||
badge_bg = pygame.Surface((bw + 18, bh + 8), pygame.SRCALPHA)
|
||||
pygame.draw.rect(badge_bg, BADGE_BG, badge_bg.get_rect(), border_radius=12)
|
||||
badge_bg.blit(bsurf, (9, 4))
|
||||
self.front.blit(badge_bg, (w - badge_bg.get_width() - 12, 12))
|
||||
|
||||
# Text
|
||||
lines = wrap_text(self.payload["label"], self.font, w - 28)
|
||||
total_h = len(lines) * self.font.get_height()
|
||||
y = h//2 - total_h//2
|
||||
for line in lines:
|
||||
ts = self.font.render(line, True, CARD_TEXT)
|
||||
self.front.blit(ts, (w//2 - ts.get_width()//2, y))
|
||||
y += self.font.get_height()
|
||||
|
||||
def draw(self, screen: pygame.Surface):
|
||||
screen.blit(self.front if (self.is_revealed or self.is_matched) else self.back,
|
||||
(self.rect.x, self.rect.y))
|
||||
|
||||
def handle_click(self, pos) -> bool:
|
||||
if self.rect.collidepoint(pos) and not self.is_matched and not self.is_revealed:
|
||||
self.is_revealed = True
|
||||
return True
|
||||
return False
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Main Game
|
||||
# ----------------------------------------------------------
|
||||
def run_memory(level: str = "Europa", mode: str = "single"):
|
||||
"""
|
||||
level: 'Europa' | 'Amerika' | 'Asien'
|
||||
mode : 'single' (Zeit) | 'two' (Punkte, abwechselnd)
|
||||
"""
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((WINDOW_W, WINDOW_H))
|
||||
pygame.display.set_caption(f"Global Match – {level} ({'1 Spieler' if mode=='single' else '2 Spieler'})")
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
ui_font = pygame.font.SysFont(None, 32, bold=True)
|
||||
big_font = pygame.font.SysFont(None, 50, bold=True)
|
||||
card_font = pygame.font.SysFont(None, 28, bold=True)
|
||||
small_font = pygame.font.SysFont(None, 20, bold=True)
|
||||
|
||||
# Grid berechnen
|
||||
grid_w = WINDOW_W - 2 * PADDING
|
||||
grid_h = WINDOW_H - HUD_BAR_H - 2 * PADDING
|
||||
cell_w = (grid_w - (GRID_COLS - 1) * GAP) // GRID_COLS
|
||||
cell_h = (grid_h - (GRID_ROWS - 1) * GAP) // GRID_ROWS
|
||||
card_size = min(cell_w, cell_h)
|
||||
start_x = PADDING + (grid_w - (card_size * GRID_COLS + GAP * (GRID_COLS - 1))) // 2
|
||||
start_y = HUD_BAR_H + PADDING + (grid_h - (card_size * GRID_ROWS + GAP * (GRID_ROWS - 1))) // 2
|
||||
|
||||
# Karten erzeugen
|
||||
back_img = load_logo_scaled((card_size, card_size))
|
||||
payloads = pick_payloads(level, n_pairs=6)
|
||||
|
||||
cards: List[Card] = []
|
||||
k = 0
|
||||
for r in range(GRID_ROWS):
|
||||
for c in range(GRID_COLS):
|
||||
if k >= len(payloads):
|
||||
continue
|
||||
rect = pygame.Rect(start_x + c * (card_size + GAP),
|
||||
start_y + r * (card_size + GAP),
|
||||
card_size, card_size)
|
||||
cards.append(Card(rect, payloads[k], (card_font, small_font), back_img))
|
||||
k += 1
|
||||
|
||||
# Spielstatus
|
||||
revealed: List[Card] = []
|
||||
lock_until = 0
|
||||
total_matches = 0
|
||||
need_matches = len(payloads) // 2
|
||||
p_turn = 1
|
||||
score = {1: 0, 2: 0}
|
||||
time_left = SINGLEPLAYER_SECONDS * 1000 if mode == "single" else None
|
||||
end_text = None
|
||||
|
||||
# Loop
|
||||
while True:
|
||||
dt = clock.tick(FPS)
|
||||
now = pygame.time.get_ticks()
|
||||
|
||||
# Events
|
||||
for e in pygame.event.get():
|
||||
if e.type == pygame.QUIT:
|
||||
pygame.quit()
|
||||
if not self.deck:
|
||||
print("⚠️ No cards loaded, check text files.")
|
||||
sys.exit()
|
||||
if e.type == pygame.KEYDOWN and end_text:
|
||||
if e.key in (pygame.K_RETURN, pygame.K_SPACE):
|
||||
pygame.quit()
|
||||
return
|
||||
if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1 and not end_text:
|
||||
if now < lock_until:
|
||||
continue
|
||||
for card in cards:
|
||||
if card.handle_click(e.pos):
|
||||
revealed.append(card)
|
||||
if len(revealed) == 2:
|
||||
a, b = revealed
|
||||
# Match (gleiches Paar, aber unterschiedliche Art)
|
||||
if a.payload["pair"] == b.payload["pair"] and a.payload["kind"] != b.payload["kind"]:
|
||||
a.is_matched = b.is_matched = True
|
||||
revealed.clear()
|
||||
total_matches += 1
|
||||
if mode == "two":
|
||||
score[p_turn] += 1
|
||||
if total_matches == need_matches:
|
||||
if mode == "single":
|
||||
end_text = "Geschafft! Alle 6 Paare."
|
||||
else:
|
||||
if score[1] > score[2]:
|
||||
end_text = f"Spielende – Spieler 1 gewinnt ({score[1]}:{score[2]})"
|
||||
elif score[2] > score[1]:
|
||||
end_text = f"Spielende – Spieler 2 gewinnt ({score[2]}:{score[1]})"
|
||||
else:
|
||||
end_text = f"Unentschieden ({score[1]}:{score[2]})"
|
||||
else:
|
||||
lock_until = now + MISMATCH_DELAY_MS
|
||||
elif len(revealed) > 2:
|
||||
# Sicherheitsreset – nur die letzten 2 behalten
|
||||
for old in revealed[:-2]:
|
||||
old.is_revealed = False
|
||||
revealed = revealed[-2:]
|
||||
|
||||
# Timer (Singleplayer)
|
||||
if not end_text and mode == "single" and time_left is not None:
|
||||
time_left -= dt
|
||||
if time_left <= 0:
|
||||
time_left = 0
|
||||
end_text = "Zeit abgelaufen!"
|
||||
random.shuffle(self.deck)
|
||||
# Limit to selected pair count
|
||||
self.deck = self.deck[:self.pair_count]
|
||||
|
||||
# Mismatch zurückdrehen + Spielerwechsel
|
||||
if not end_text and len(revealed) == 2 and lock_until and now >= lock_until:
|
||||
a, b = revealed
|
||||
a.is_revealed = False
|
||||
b.is_revealed = False
|
||||
revealed.clear()
|
||||
lock_until = 0
|
||||
if mode == "two":
|
||||
p_turn = 2 if p_turn == 1 else 1
|
||||
def setup_game(self):
|
||||
self.cards = []
|
||||
self.pair_map = {}
|
||||
for country, capital in self.deck:
|
||||
self.cards.append(country)
|
||||
self.cards.append(capital)
|
||||
self.pair_map[country] = capital
|
||||
self.pair_map[capital] = country
|
||||
random.shuffle(self.cards)
|
||||
self.matched = [False] * len(self.cards)
|
||||
self.revealed = [False] * len(self.cards)
|
||||
self.total_pairs = len(self.deck)
|
||||
self.card_rects = []
|
||||
self.selected = []
|
||||
|
||||
# ----------------- Render -----------------
|
||||
cols = 4
|
||||
rows = (len(self.cards) + cols - 1) // cols
|
||||
margin = 10
|
||||
card_width = (SCREEN_WIDTH - (cols + 1) * margin) // cols
|
||||
card_height = (SCREEN_HEIGHT - (rows + 1) * margin - 100) // rows
|
||||
y_offset = 80
|
||||
|
||||
for i, _ in enumerate(self.cards):
|
||||
col = i % cols
|
||||
row = i // cols
|
||||
x = margin + col * (card_width + margin)
|
||||
y = y_offset + margin + row * (card_height + margin)
|
||||
rect = pygame.Rect(x, y, card_width, card_height)
|
||||
self.card_rects.append(rect)
|
||||
|
||||
# -------------------------------
|
||||
# Drawing Menus
|
||||
# -------------------------------
|
||||
def draw_menu(self, screen, title, options):
|
||||
screen.fill(BG_COLOR)
|
||||
title_text = self.font.render(title, True, (255, 255, 255))
|
||||
screen.blit(title_text, (SCREEN_WIDTH // 2 - title_text.get_width() // 2, 100))
|
||||
self.buttons = []
|
||||
|
||||
# HUD
|
||||
pygame.draw.rect(screen, (7, 42, 70), (0, 0, WINDOW_W, HUD_BAR_H))
|
||||
title = ui_font.render(f"Global Match – {level}", True, (255, 255, 255))
|
||||
screen.blit(title, (PADDING, HUD_BAR_H//2 - title.get_height()//2))
|
||||
|
||||
if mode == "single":
|
||||
tsec = (time_left // 1000) if time_left is not None else 0
|
||||
timer = ui_font.render(f"Zeit: {tsec}s", True, HIGHLIGHT)
|
||||
screen.blit(timer, (WINDOW_W - PADDING - timer.get_width(), HUD_BAR_H//2 - timer.get_height()//2))
|
||||
else:
|
||||
s = ui_font.render(f"P1: {score[1]} P2: {score[2]} Zug: P{p_turn}", True, HIGHLIGHT)
|
||||
screen.blit(s, (WINDOW_W - PADDING - s.get_width(), HUD_BAR_H//2 - s.get_height()//2))
|
||||
|
||||
# Karten
|
||||
for card in cards:
|
||||
card.draw(screen)
|
||||
|
||||
# Overlay / Ende
|
||||
if end_text:
|
||||
overlay = pygame.Surface((WINDOW_W, WINDOW_H), pygame.SRCALPHA)
|
||||
overlay.fill((0, 0, 0, 140))
|
||||
screen.blit(overlay, (0, 0))
|
||||
msg = big_font.render(end_text, True, (255, 255, 255))
|
||||
sub = ui_font.render("ENTER/SPACE zum Beenden", True, (240, 240, 240))
|
||||
screen.blit(msg, (WINDOW_W//2 - msg.get_width()//2, WINDOW_H//2 - 30))
|
||||
screen.blit(sub, (WINDOW_W//2 - sub.get_width()//2, WINDOW_H//2 + 20))
|
||||
|
||||
for i, option in enumerate(options):
|
||||
rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, 200 + i * 70, 300, 50)
|
||||
pygame.draw.rect(screen, (100, 100, 250), rect)
|
||||
pygame.draw.rect(screen, (255, 255, 255), rect, 2)
|
||||
text = self.font.render(option, True, (255, 255, 255))
|
||||
screen.blit(text, (rect.centerx - text.get_width() // 2, rect.centery - text.get_height() // 2))
|
||||
self.buttons.append((rect, option))
|
||||
pygame.display.flip()
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Direktstart (zu Testzwecken)
|
||||
# ----------------------------------------------------------
|
||||
def draw_game(self, screen):
|
||||
screen.fill(BG_COLOR)
|
||||
title = self.font.render(f"Player {self.current_player + 1}'s turn", True, (255, 255, 255))
|
||||
screen.blit(title, (20, 20))
|
||||
score_text = self.font.render(f"Scores: P1={self.scores[0]} P2={self.scores[1]}", True, (200, 200, 200))
|
||||
screen.blit(score_text, (20, 50))
|
||||
|
||||
for i, rect in enumerate(self.card_rects):
|
||||
if self.matched[i]:
|
||||
color = MATCH_COLOR
|
||||
elif self.revealed[i]:
|
||||
color = CARD_FRONT_COLOR
|
||||
else:
|
||||
color = CARD_BACK_COLOR
|
||||
pygame.draw.rect(screen, color, rect)
|
||||
pygame.draw.rect(screen, (0, 0, 0), rect, 2)
|
||||
if self.revealed[i] or self.matched[i]:
|
||||
text = self.font.render(self.cards[i], True, TEXT_COLOR)
|
||||
text_rect = text.get_rect(center=rect.center)
|
||||
screen.blit(text, text_rect)
|
||||
|
||||
if self.awaiting_confirmation:
|
||||
self.draw_confirmation_box(screen)
|
||||
pygame.display.flip()
|
||||
|
||||
def draw_confirmation_box(self, screen): #y-axis Box
|
||||
box_rect = pygame.Rect(SCREEN_WIDTH // 2 - 150, SCREEN_HEIGHT // 2 - 320, 300, 160)
|
||||
pygame.draw.rect(screen, (250, 250, 250), box_rect)
|
||||
pygame.draw.rect(screen, (0, 0, 0), box_rect, 3)
|
||||
text = self.font.render("Is that correct?", True, (0, 0, 0))
|
||||
screen.blit(text, (box_rect.centerx - text.get_width() // 2, box_rect.y + 20))
|
||||
|
||||
yes_rect = pygame.Rect(box_rect.x + 50, box_rect.y + 90, 80, 40)
|
||||
no_rect = pygame.Rect(box_rect.x + 170, box_rect.y + 90, 80, 40)
|
||||
pygame.draw.rect(screen, (0, 200, 0), yes_rect)
|
||||
pygame.draw.rect(screen, (200, 0, 0), no_rect)
|
||||
yes_text = self.font.render("Yes", True, (255, 255, 255))
|
||||
no_text = self.font.render("No", True, (255, 255, 255))
|
||||
screen.blit(yes_text, (yes_rect.centerx - yes_text.get_width() // 2, yes_rect.centery - yes_text.get_height() // 2))
|
||||
screen.blit(no_text, (no_rect.centerx - no_text.get_width() // 2, no_rect.centery - no_text.get_height() // 2))
|
||||
self.yes_rect, self.no_rect = yes_rect, no_rect
|
||||
|
||||
# -------------------------------
|
||||
# Handling Clicks
|
||||
# -------------------------------
|
||||
def handle_click(self, pos):
|
||||
if self.state in ["continent", "americas", "difficulty", "pairs"]:
|
||||
for rect, option in self.buttons:
|
||||
if rect.collidepoint(pos):
|
||||
if self.state == "continent":
|
||||
if option == "Americas":
|
||||
self.state = "americas"
|
||||
elif option == "All Continents":
|
||||
self.selected_continents = ["Europe", "Asia", "Africa", "Oceania", "North-America", "South-America"]
|
||||
self.state = "difficulty"
|
||||
else:
|
||||
self.selected_continents = [option]
|
||||
self.state = "difficulty"
|
||||
|
||||
elif self.state == "americas":
|
||||
if option == "North-America":
|
||||
self.selected_continents = ["North-America"]
|
||||
elif option == "South-America":
|
||||
self.selected_continents = ["South-America"]
|
||||
elif option == "Americas":
|
||||
self.selected_continents = ["North-America", "South-America"]
|
||||
self.state = "difficulty"
|
||||
|
||||
elif self.state == "difficulty":
|
||||
self.level = option
|
||||
self.state = "pairs"
|
||||
|
||||
elif self.state == "pairs":
|
||||
self.pair_count = int(option)
|
||||
self.prepare_deck()
|
||||
self.setup_game()
|
||||
self.state = "game"
|
||||
return
|
||||
|
||||
elif self.state == "game":
|
||||
if self.awaiting_confirmation:
|
||||
if self.yes_rect.collidepoint(pos):
|
||||
self.confirmation_result = "yes"
|
||||
elif self.no_rect.collidepoint(pos):
|
||||
self.confirmation_result = "no"
|
||||
return
|
||||
|
||||
for i, rect in enumerate(self.card_rects):
|
||||
if rect.collidepoint(pos) and not self.revealed[i] and not self.matched[i]:
|
||||
self.revealed[i] = True
|
||||
self.selected.append(i)
|
||||
return
|
||||
|
||||
# -------------------------------
|
||||
# Game Logic Most important
|
||||
# -------------------------------
|
||||
def check_selected(self):
|
||||
if self.state != "game":
|
||||
return
|
||||
|
||||
# Wenn zwei Karten ausgewählt wurden → prüfen
|
||||
if len(self.selected) == 2 and not self.awaiting_confirmation:
|
||||
a, b = self.selected
|
||||
is_match = self.pair_map.get(self.cards[a]) == self.cards[b]
|
||||
self.correct_answer_expected = "yes" if is_match else "no"
|
||||
self.awaiting_confirmation = True
|
||||
|
||||
# Wenn der Spieler im "Is that correct?"-Dialog geantwortet hat
|
||||
elif self.awaiting_confirmation and self.confirmation_result:
|
||||
a, b = self.selected
|
||||
expected = self.correct_answer_expected
|
||||
player_correct = self.confirmation_result == expected
|
||||
|
||||
if player_correct:
|
||||
# Spieler hat korrekt geantwortet
|
||||
if expected == "yes":
|
||||
# Richtiges Paar bestätigt
|
||||
self.matched[a] = self.matched[b] = True
|
||||
self.scores[self.current_player] += 1
|
||||
self.found_pairs += 1
|
||||
else:
|
||||
# "No" richtig bestätigt → kein Paar
|
||||
self.revealed[a] = self.revealed[b] = False
|
||||
else:
|
||||
# Spieler hat sich vertan → Karten umdrehen & Punkt abziehen
|
||||
self.scores[self.current_player] -= 1
|
||||
self.revealed[a] = self.revealed[b] = False
|
||||
|
||||
# Reset für nächsten Zug
|
||||
self.awaiting_confirmation = False
|
||||
self.confirmation_result = None
|
||||
self.selected = []
|
||||
self.current_player = 1 - self.current_player
|
||||
|
||||
# -------------------------------
|
||||
# Main Game Loop
|
||||
# -------------------------------
|
||||
def run(self):
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
pygame.display.set_caption("Country–Capital Memory Game")
|
||||
clock = pygame.time.Clock()
|
||||
self.font = pygame.font.SysFont(None, 32)
|
||||
|
||||
while self.running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
self.running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
||||
self.handle_click(event.pos)
|
||||
|
||||
if self.state == "continent":
|
||||
self.draw_menu(screen, "Select Continent", ["Europe", "Americas", "Asia", "Africa", "Oceania", "All Continents"])
|
||||
elif self.state == "americas":
|
||||
self.draw_menu(screen, "Select Region", ["North-America", "South-America", "Americas"])
|
||||
elif self.state == "difficulty":
|
||||
self.draw_menu(screen, "Select Difficulty", ["Easy", "Normal", "Hard"])
|
||||
elif self.state == "pairs":
|
||||
self.draw_menu(screen, "Select Number of Pairs", ["4", "6", "8", "10", "12"])
|
||||
elif self.state == "game":
|
||||
self.draw_game(screen)
|
||||
self.check_selected()
|
||||
if self.found_pairs == self.total_pairs:
|
||||
self.display_winner(screen)
|
||||
pygame.display.flip()
|
||||
pygame.time.wait(4000)
|
||||
self.running = False
|
||||
|
||||
clock.tick(FPS)
|
||||
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
|
||||
# -------------------------------
|
||||
# Winner Display
|
||||
# -------------------------------
|
||||
def display_winner(self, screen):
|
||||
if self.scores[0] > self.scores[1]:
|
||||
text = "🏆 Player 1 Wins!"
|
||||
elif self.scores[1] > self.scores[0]:
|
||||
text = "🏆 Player 2 Wins!"
|
||||
else:
|
||||
text = "🤝 Draw!"
|
||||
win_text = self.font.render(text, True, (255, 255, 0))
|
||||
rect = win_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
|
||||
screen.blit(win_text, rect)
|
||||
|
||||
def run_memory(players: int = 1):
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((900, 600))
|
||||
pygame.display.set_caption(f"Global Match – {players} Spieler")
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
running = True
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
|
||||
screen.fill((10, 42, 53))
|
||||
# ... dein Memory-Rendering / Logic ...
|
||||
pygame.display.flip()
|
||||
clock.tick(60)
|
||||
|
||||
pygame.quit()
|
||||
|
||||
# -------------------------------
|
||||
# Run the Game
|
||||
# -------------------------------
|
||||
if __name__ == "__main__":
|
||||
lvl = "Europa"
|
||||
md = "single"
|
||||
if len(sys.argv) >= 2:
|
||||
lvl = sys.argv[1]
|
||||
if len(sys.argv) >= 3:
|
||||
md = sys.argv[2]
|
||||
run_memory(level=lvl, mode=md)
|
||||
|
||||
game = MemoryGame()
|
||||
game.run()
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from global_match_memory import run_memory
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
@ -134,7 +134,7 @@ from global_match_memory import run_memory
|
||||
<div class="brand">
|
||||
<!-- Logo als Text – du kannst hier optional ein PNG/SVG einfügen -->
|
||||
<div class="logo" aria-hidden="true">
|
||||
<div class="logo-top">GLO
|
||||
<div class="logo-top">GL
|
||||
<svg width="52" height="52" viewBox="0 0 100 100" style="vertical-align:middle">
|
||||
<defs><radialGradient id="g" cx="50%" cy="35%" r="60%"><stop offset="0%" stop-color="#9ee7ef"/><stop offset="100%" stop-color="#127a8a"/></radialGradient></defs>
|
||||
<circle cx="50" cy="50" r="46" fill="url(#g)" stroke="#08303b" stroke-width="6"/>
|
||||
@ -181,3 +181,22 @@ from global_match_memory import run_memory
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
<!-- ... dein kompletter <head> & <body> wie bisher ... -->
|
||||
|
||||
<script>
|
||||
// Jahr im Footer
|
||||
document.getElementById('y').textContent = new Date().getFullYear();
|
||||
|
||||
// Start-Button → Backend ruft Pygame
|
||||
document.getElementById('startBtn').addEventListener('click', async () => {
|
||||
const players = document.querySelector('input[name="players"]:checked').value;
|
||||
try {
|
||||
const res = await fetch(`/start?players=${players}`);
|
||||
// Optional: kleine Info für Nutzer
|
||||
alert('Spiel wird gestartet! Schau nach dem Pygame-Fenster.');
|
||||
} catch (e) {
|
||||
alert('Konnte das Spiel nicht starten. Läuft der Server?');
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Loading…
x
Reference in New Issue
Block a user