Ich finde meinen Logik Fehler nicht...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
njnnjn
User
Beiträge: 3
Registriert: Mittwoch 3. Juni 2026, 15:09

Hallo,

ich bin recht frisch in Python eingestiegen. Ich habe ein Buch für Anfänger durchgearbeitet und arbeite viel mit google KI. Dabei lasse ich mir nicht nur Code generieren, sondern auch erklären warum, wieso und weshalb. Nach den üblichen Hallo Welt und Galgenraten versuche ich mich mit Unterstützung der KI an einen clone eines mir damals sehr wichtigen und tollen Spiel. Der Plan ist erstmal muss alles laufen, dann kommt die Grafik, dann das balancing.
Ich habe derzeit einen Denkfehler und trotz KI komme ich nicht weiter. Ich erforsche einen Orbiter, möchte ihn bauen und anschließend starten. erst dann sind meine Raumschiffe verfügbar. Aber das will nicht so recht. Könnte mir da jemand bitte weiter helfen? Ich weiß nicht wie das mit dem Code läuft hier im Forum. Darf ich den einfach posten in diesem Tread?
LG

PS Linux Mint Debian Edition, einfaches office Notebook und Python 3 falls das wichtig ist.
Sirius3
User
Beiträge: 18413
Registriert: Sonntag 21. Oktober 2012, 17:20

Ja, Du darfst Den Code einfach posten. In Code-Tags </>.
njnnjn
User
Beiträge: 3
Registriert: Mittwoch 3. Juni 2026, 15:09

Super, dann mache ich das mal...
< import pygame
import sys

pygame.init()
pygame.font.init()

SCREEN_WIDTH, SCREEN_HEIGHT = 1280, 720
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Breed96 - Linux Port v7.0 (Multi-Tab Core)")
clock = pygame.time.Clock()

# Amiga-Farbpalette
COLOR_DESERT, COLOR_TEXT, COLOR_UI_BG = (194, 131, 62), (255, 255, 255), (30, 30, 40)
COLOR_GRID, COLOR_RED, COLOR_GOLD, COLOR_HIGHLIGHT, COLOR_GREY = (174, 111, 42), (220, 50, 50), (255, 215, 0), (0, 255, 255), (120, 120, 130)

COLOR_DOME, COLOR_MINE, COLOR_POWER, COLOR_ROAD = (0, 200, 100), (60, 60, 80), (220, 180, 0), (100, 65, 35)
COLOR_HOUSE, COLOR_INDUSTRY, COLOR_SHOP, COLOR_LAB = (180, 60, 160), (230, 90, 40), (0, 160, 220), (150, 0, 250)
COLOR_OBS, COLOR_YARD = (0, 255, 180), (200, 50, 50)

# ==============================================================================
# SPIELVARIABLEN & GLOBALE WIRTSCHAFT
# ==============================================================================
resources = {"Nahrung": 200, "Erz": 300, "Energie": 200, "Forschung": 0}
unlocked_techs = {"Observatorium": False, "Werft": False, "Orbiter_Erforscht": False, "Orbiter_Gebaut": False}

# Wichtig: Die Kernvariablen für das Wirtschaftssystem müssen hier stehen!
citizens = 50 # Start-Einwohner
tax_rate = 10 # Steuersatz in Prozent

# Neuer Schiffsspeicher für deine zukünftige Flotte
fleet = {
"Leichter Gleiter": {"count": 0, "cost": {"Erz": 150, "Energie": 50}, "desc": "Schneller Abfangjäger"},
"Schwerer Gleiter": {"count": 0, "cost": {"Erz": 300, "Energie": 100}, "desc": "Schwerer Sektor-Schutz"},
"Transportschiff": {"count": 0, "cost": {"Erz": 400, "Energie": 150}, "desc": "Handel & Logistik"},
"Abbauschiff": {"count": 0, "cost": {"Erz": 350, "Energie": 200}, "desc": "Erntet Asteroiden ab"},
"Kolonieschiff": {"count": 0, "cost": {"Erz": 800, "Energie": 400}, "desc": "Bereit für fernen Planeten"},
"Schlachtkreuzer": {"count": 0, "cost": {"Erz": 1200, "Energie": 600},"desc": "Das ultimative Flaggschiff"}
}

# Asteroiden- & Event-System Variablen
asteroid_timer = 0
asteroid_discovered = False
asteroid_ore_left = 0
space_log = "ORBITAL-STATION AKTIV. Warte auf Orbiter-Start..."

# Menüsteuerung und Runden-Taktung
current_mode, game_state, tick_counter = 1, "PLAYING", 0
current_tab = "MAP" # Mögliche Tabs: MAP, ECONOMY, RESEARCH, SPACE

# Neuer Schiffsspeicher für deine Flotte
fleet = {
"Leichter Gleiter": {"count": 0, "cost": {"Erz": 150, "Energie": 50}, "desc": "Schneller Abfangjäger"},
"Schwerer Gleiter": {"count": 0, "cost": {"Erz": 300, "Energie": 100}, "desc": "Schwerer Sektor-Schutz"},
"Transportschiff": {"count": 0, "cost": {"Erz": 400, "Energie": 150}, "desc": "Handel & Logistik"},
"Abbauschiff": {"count": 0, "cost": {"Erz": 350, "Energie": 200}, "desc": "Erntet Asteroiden ab"},
"Kolonieschiff": {"count": 0, "cost": {"Erz": 800, "Energie": 400}, "desc": "Bereit für fernen Planeten"},
"Schlachtkreuzer": {"count": 0, "cost": {"Erz": 1200, "Energie": 600},"desc": "Das ultimative Flaggschiff"}
}

# Asteroiden- & Event-System
asteroid_timer = 0
asteroid_discovered = False
asteroid_ore_left = 0
space_log = "ORBITAL-STATION AKTIV. Warte auf Orbiter-Start..."
# Gebäudespeicher
buildings = {
1: {"name": "Kuppel", "list": [], "cost": {"N": 20, "E": 40, "P": 10}, "color": COLOR_DOME},
2: {"name": "Erzmine", "list": [], "cost": {"N": 40, "E": 20, "P": 20}, "color": COLOR_MINE},
3: {"name": "Kraftwerk", "list": [], "cost": {"N": 10, "E": 60, "P": 0}, "color": COLOR_POWER},
4: {"name": "Strasse", "list": [], "cost": {"N": 0, "E": 5, "P": 0}, "color": COLOR_ROAD},
5: {"name": "Wohnhaus", "list": [], "cost": {"N": 10, "E": 30, "P": 15}, "color": COLOR_HOUSE},
6: {"name": "Industrie", "list": [], "cost": {"N": 30, "E": 80, "P": 30}, "color": COLOR_INDUSTRY},
7: {"name": "Mall", "list": [], "cost": {"N": 50, "E": 100, "P": 25}, "color": COLOR_SHOP},
8: {"name": "Forschung", "list": [], "cost": {"N": 40, "E": 150, "P": 40}, "color": COLOR_LAB},
9: {"name": "Observat.", "list": [], "cost": {"N": 60, "E": 200, "P": 60}, "color": COLOR_OBS},
10: {"name": "Werft", "list": [], "cost": {"N": 100, "E": 400, "P": 100}, "color": COLOR_YARD}
}

current_mode, game_state, tick_counter = 1, "PLAYING", 0
current_tab = "MAP" # Mögliche Tabs: MAP, ECONOMY, RESEARCH, SPACE

font = pygame.font.SysFont("Courier", 12, bold=True)
large_font = pygame.font.SysFont("Courier", 36, bold=True)

def has_road_connection(pos):
neighbors = [(pos[0] - 40, pos[1]), (pos[0] + 40, pos[1]), (pos[0], pos[1] - 40), (pos[0], pos[1] + 40)]
for n in neighbors:
if n in buildings[4]["list"]:
return True
return False

running = True
while running:
# --- 1. Event-Handling ---
for event in pygame.event.get():

# Fenster schließen
if event.type == pygame.QUIT:
running = False

# -----------------------------
# TASTATUREINGABEN
# -----------------------------
elif event.type == pygame.KEYDOWN:

# ESC = Spiel beenden
if event.key == pygame.K_ESCAPE:
running = False

# TAB-WECHSEL PER F-TASTEN
if game_state in ["PLAYING", "VICTORY"]:
if event.key == pygame.K_F1:
current_tab = "MAP"
elif event.key == pygame.K_F2:
current_tab = "ECONOMY"
elif event.key == pygame.K_F3:
current_tab = "RESEARCH"
elif event.key == pygame.K_F4:
current_tab = "SPACE"

# -----------------------------
# ECONOMY – Steuern ändern
# -----------------------------
if game_state == "PLAYING" and current_tab == "ECONOMY":
if event.key == pygame.K_UP and tax_rate < 30:
tax_rate += 1
elif event.key == pygame.K_DOWN and tax_rate > 0:
tax_rate -= 1

# -----------------------------
# MAP / SPACE – Aktionen
# -----------------------------
if game_state == "PLAYING":

# -----------------------------
# MAP – Bau-Modus
# -----------------------------
if current_tab == "MAP":
if pygame.K_1 <= event.key <= pygame.K_7:
current_mode = event.key - pygame.K_1 + 1
elif event.key == pygame.K_8:
current_mode = 8
elif event.key == pygame.K_9:
current_mode = 9
elif event.key == pygame.K_0:
current_mode = 10

# -----------------------------
# SPACE – Orbiter & Flotte
# -----------------------------
elif current_tab == "SPACE":

# 1. Orbiter erforschen (Taste F)
if (
event.key == pygame.K_f
and len(buildings[10]["list"]) > 0
and resources["Forschung"] >= 500
and not unlocked_techs["Orbiter_Erforscht"]
):
resources["Forschung"] -= 500
unlocked_techs["Orbiter_Erforscht"] = True
space_log = "Orbiter-Technologie erforscht! Baue ihn jetzt mit ."

# 2. Orbiter bauen (Taste B)
elif (
event.key == pygame.K_b
and unlocked_techs["Orbiter_Erforscht"]
and len(buildings[10]["list"]) > 0
and resources["Erz"] >= 800
and resources["Energie"] >= 400
and not unlocked_techs["Orbiter_Gebaut"]
):
resources["Erz"] -= 800
resources["Energie"] -= 400
unlocked_techs["Orbiter_Gebaut"] = True
space_log = "Orbiter gebaut! Starte ihn jetzt mit [S]."

# 3. Orbiter starten (Taste S)
elif (
event.key == pygame.K_s
and unlocked_techs["Orbiter_Gebaut"]
and len(buildings[10]["list"]) > 0
):
space_log = "ORBITER GESTARTET! Flottenkontrolle aktiviert."
game_state = "VICTORY"

# --- FLOTTE BAUEN (erst nach Orbiter-Start) ---
elif unlocked_techs["Orbiter_Gebaut"] and game_state == "VICTORY":

if event.key == pygame.K_a and resources["Erz"] >= 150 and resources["Energie"] >= 50:
resources["Erz"] -= 150
resources["Energie"] -= 50
fleet["Leichter Gleiter"]["count"] += 1
space_log = "Leichter Gleiter konstruiert."

elif event.key == pygame.K_b and resources["Erz"] >= 300 and resources["Energie"] >= 100:
resources["Erz"] -= 300
resources["Energie"] -= 100
fleet["Schwerer Gleiter"]["count"] += 1
space_log = "Schwerer Gleiter einsatzbereit."

elif event.key == pygame.K_c and resources["Erz"] >= 400 and resources["Energie"] >= 150:
resources["Erz"] -= 400
resources["Energie"] -= 150
fleet["Transportschiff"]["count"] += 1
space_log = "Transportschiff gestartet."

elif event.key == pygame.K_d and resources["Erz"] >= 350 and resources["Energie"] >= 200:
resources["Erz"] -= 350
resources["Energie"] -= 200
fleet["Abbauschiff"]["count"] += 1
space_log = "Abbauschiff bereit für Bergbau."

elif event.key == pygame.K_e and resources["Erz"] >= 800 and resources["Energie"] >= 400:
resources["Erz"] -= 800
resources["Energie"] -= 400
fleet["Kolonieschiff"]["count"] += 1
space_log = "Kolonieschiff im Orbit."

elif event.key == pygame.K_g and resources["Erz"] >= 1200 and resources["Energie"] >= 600:
resources["Erz"] -= 1200
resources["Energie"] -= 600
fleet["Schlachtkreuzer"]["count"] += 1
space_log = "Schlachtkreuzer der Core-Klasse online."

# -----------------------------
# Neustart bei Game Over
# -----------------------------
if game_state != "PLAYING" and event.key == pygame.K_SPACE:
resources = {"Nahrung": 200, "Erz": 300, "Energie": 200, "Forschung": 0}
unlocked_techs = {"Observatorium": False, "Werft": False, "Orbiter_Erforscht": False, "Orbiter_Gebaut": False}
citizens, tax_rate, current_tab = 50, 10, "MAP"
for m in buildings:
buildings[m]["list"] = []
game_state = "PLAYING"

# -----------------------------
# MAUS – Gebäude bauen
# -----------------------------
elif event.type == pygame.MOUSEBUTTONDOWN and game_state == "PLAYING":
if current_tab == "MAP":
mouse_x, mouse_y = pygame.mouse.get_pos()
if mouse_y < 520:

# Tech-Locks prüfen
if not (
(current_mode == 9 and not unlocked_techs["Observatorium"])
or (current_mode == 10 and not unlocked_techs["Werft"])
):
b_data = buildings[current_mode]

# Ressourcen prüfen
if (
resources["Nahrung"] >= b_data["cost"]["N"]
and resources["Erz"] >= b_data["cost"]["E"]
and resources["Energie"] >= b_data["cost"]["P"]
):
grid_x = (mouse_x // 40) * 40 + 20
grid_y = (mouse_y // 40) * 40 + 20
pos = (grid_x, grid_y)

occupied = any(pos in buildings[m]["list"] for m in buildings)
has_buildings = any(len(buildings[m]["list"]) > 0 for m in buildings)
adjacent_to_road = True if (current_mode == 4 or not has_buildings) else has_road_connection(pos)

if not occupied and adjacent_to_road:
resources["Nahrung"] -= b_data["cost"]["N"]
resources["Erz"] -= b_data["cost"]["E"]
resources["Energie"] -= b_data["cost"]["P"]
b_data["list"].append(pos)

# --- 2. Wirtschafts- & Forschungs-Logik (Sekundentakt) ---
if game_state == "PLAYING":
if resources["Forschung"] >= 100: unlocked_techs["Observatorium"] = True
if resources["Forschung"] >= 300: unlocked_techs["Werft"] = True

tick_counter += 1
if tick_counter >= 60:
tick_counter = 0

# Basis-Einkommen pro Sekunde
resources["Nahrung"] += 2; resources["Erz"] += 2; resources["Energie"] += 5

# Kuppeln (ID 1)
for pos in buildings[1]["list"]:
if has_road_connection(pos) or len(buildings[4]["list"]) == 0:
resources["Nahrung"] += 8
resources["Energie"] -= 2

# Erzminen (ID 2)
for pos in buildings[2]["list"]:
if has_road_connection(pos):
resources["Erz"] += 12
resources["Nahrung"] -= 4

# Kraftwerke (ID 3)
for pos in buildings[3]["list"]:
resources["Energie"] += 18

# Wohnhäuser (ID 5) & Steuersystem
max_citizens = len(buildings[5]["list"]) * 15 + 20
if citizens < max_citizens:
citizens += 2
elif citizens > max_citizens:
citizens = max_citizens

for pos in buildings[5]["list"]:
if has_road_connection(pos):
resources["Nahrung"] -= 3
resources["Erz"] += int(tax_rate / 5) # Bürger zahlen Steuern in Form von Erz-Guthaben
resources["Energie"] -= 1

# Industrie (ID 6)
for pos in buildings[6]["list"]:
if has_road_connection(pos):
resources["Erz"] += 35
resources["Energie"] -= 6
resources["Nahrung"] -= 2

# Malls (ID 7)
for pos in buildings[7]["list"]:
if has_road_connection(pos):
resources["Nahrung"] += 4
resources["Energie"] += 4
resources["Erz"] -= 1

# Labore (ID 8)
for pos in buildings[8]["list"]:
if has_road_connection(pos):
resources["Forschung"] += 15
resources["Energie"] -= 5

# Observatorien (ID 9)
for pos in buildings[9]["list"]:
if has_road_connection(pos):
resources["Forschung"] += 5
resources["Erz"] += 5
resources["Energie"] -= 8

# --- NEU: ASTEROIDEN-SUCHE DURCH OBSERVATORIEN ---
import random

if not asteroid_discovered and random.randint(1, 50) == 1:
asteroid_discovered = True
asteroid_ore_left = random.randint(800, 1500) # Zufällige Erzmenge
space_log = f"ASTEROID ENTDECKT! Ressourcen-Vorkommen: {asteroid_ore_left} Erz."

# --- NEU: AUTOMATISCHER ABBAU DURCH FLOTTE ---
if asteroid_discovered and fleet["Abbauschiff"]["count"] > 0:
# Jedes Schiff baut 15 Erz pro Sekunde ab
abbau_rate = fleet["Abbauschiff"]["count"] * 15

# Sicherstellen, dass wir nicht mehr abbauen, als da ist
if abbau_rate > asteroid_ore_left:
abbau_rate = asteroid_ore_left

asteroid_ore_left -= abbau_rate
resources["Erz"] += abbau_rate
space_log = f"Bergbau läuft... Asteroid verbleibend: {asteroid_ore_left} Erz."

# Wenn der Asteroid leer ist, wird er gelöscht
if asteroid_ore_left <= 0:
asteroid_discovered = False
space_log = "Asteroid vollständig abgebaut. Warte auf nächsten Scan..."

# Werften (ID 10)
for pos in buildings[10]["list"]:
if has_road_connection(pos):
resources["Erz"] -= 10
resources["Energie"] -= 10
# Game-Over-Check
if resources["Nahrung"] < 0 or resources["Erz"] < 0 or resources["Energie"] < 0:
game_state = "GAME_OVER"

# --- 3. Rendering (Zeichnen) ---
screen.fill(COLOR_DESERT)

if current_tab == "MAP":
# Raster zeichnen
for x in range(0, SCREEN_WIDTH, 40): pygame.draw.line(screen, COLOR_GRID, (x, 0), (x, 520))
for y in range(0, 520, 40): pygame.draw.line(screen, COLOR_GRID, (0, y), (SCREEN_WIDTH, y))

# Straßen zeichnen
for road in buildings[4]["list"]:
pygame.draw.rect(screen, COLOR_ROAD, (road[0]-20, road[1]-20, 40, 40))
pygame.draw.rect(screen, (80, 50, 25), (road[0]-20, road[1]-20, 40, 40), 1)

# Gebäude zeichnen
for dome in buildings[1]["list"]:
pygame.draw.circle(screen, COLOR_DOME, dome, 16)
pygame.draw.line(screen, COLOR_TEXT, dome, (dome[0], dome[1] - 22), 2)

for mine in buildings[2]["list"]:
pygame.draw.rect(screen, COLOR_MINE, (mine[0]-15, mine[1]-15, 30, 30))

for power in buildings[3]["list"]:
pygame.draw.polygon(screen, COLOR_POWER, [(power[0], power[1]-15), (power[0]-15, power[1]+15), (power[0]+15, power[1]+15)])

for house in buildings[5]["list"]:
pygame.draw.rect(screen, COLOR_HOUSE, (house[0]-14, house[1]-8, 28, 22))

for ind in buildings[6]["list"]:
pygame.draw.rect(screen, COLOR_INDUSTRY, (ind[0]-16, ind[1]-6, 32, 20))

for shop in buildings[7]["list"]:
pygame.draw.ellipse(screen, COLOR_SHOP, (shop[0]-18, shop[1]-12, 36, 24))

for lab in buildings[8]["list"]:
pygame.draw.rect(screen, COLOR_LAB, (lab[0]-15, lab[1]-15, 30, 30))
pygame.draw.circle(screen, COLOR_HIGHLIGHT, lab, 6)

for obs in buildings[9]["list"]:
pygame.draw.circle(screen, COLOR_OBS, obs, 14)
pygame.draw.line(screen, COLOR_TEXT, obs, (obs[0]+16, obs[1]-16), 4)

for yard in buildings[10]["list"]:
pygame.draw.rect(screen, COLOR_YARD, (yard[0]-18, yard[1]-18, 36, 36), 3)

# Rote Kreuze bei inaktiven Gebäuden (ohne Straße)
if len(buildings[4]["list"]) > 0:
for m in buildings:
for pos in buildings[m]["list"]:
if not has_road_connection(pos) and m != 4 and m != 1:
pygame.draw.line(screen, COLOR_RED, (pos[0]-10, pos[1]-10), (pos[0]+10, pos[1]+10), 2)
pygame.draw.line(screen, COLOR_RED, (pos[0]+10, pos[1]-10), (pos[0]-10, pos[1]+10), 2)

elif current_tab == "ECONOMY":
pygame.draw.rect(screen, (20, 20, 30), (40, 40, SCREEN_WIDTH-80, 440))
screen.blit(large_font.render("TAB 1: ZENTRALES WIRTSCHAFTS-TERMINAL", True, COLOR_HIGHLIGHT), (80, 70))
pygame.draw.line(screen, COLOR_TEXT, (80, 120), (SCREEN_WIDTH-80, 120), 2)

screen.blit(font.render(f"AKTUELLE BÜRGERANZAHL: {citizens} Kolonisten", True, COLOR_TEXT), (80, 160))
screen.blit(font.render(f"STEUERSATZ: {tax_rate}% (Pfeiltasten HOCH/RUNTER im Terminal zum Ändern)", True, COLOR_GOLD), (80, 190))
screen.blit(font.render("WOHNRAUM-KAPAZITÄT: " + str(len(buildings[5]["list"]) * 15 + 20) + " Plätze", True, COLOR_TEXT), (80, 220))
screen.blit(font.render("BÜRGER-STIMMUNG: STABIL / ZUFRIEDEN", True, COLOR_DOME), (80, 250))

pygame.draw.rect(screen, (40, 40, 60), (80, 320, 600, 100))
screen.blit(font.render("[LOG]: Kolonie wächst proportional zum freien Wohnraum.", True, COLOR_TEXT), (100, 340))
screen.blit(font.render("[LOG]: Höhere Steuern wandeln Wohnhäuser in Erz-Produzenten um.", True, COLOR_TEXT), (100, 370))

elif current_tab == "RESEARCH":
pygame.draw.rect(screen, (30, 20, 40), (40, 40, SCREEN_WIDTH-80, 440))
screen.blit(large_font.render("TAB 2: TECHNOLOGIE-DATENBANK", True, COLOR_LAB), (80, 70))
pygame.draw.line(screen, COLOR_TEXT, (80, 120), (SCREEN_WIDTH-80, 120), 2)

def draw_tech_node(name, points_req, x, y, unlocked):
col = COLOR_DOME if unlocked else COLOR_RED
pygame.draw.rect(screen, (50, 50, 70), (x, y, 220, 60), 2)
screen.blit(font.render(name, True, COLOR_TEXT), (x+10, y+15))
status = "FREIGESCHALTET" if unlocked else f"BENÖTIGT: {points_req} F"
screen.blit(font.render(status, True, col), (x+10, y+35))

draw_tech_node("1. GRUNDLAGEN-FORSCHUNG", 0, 80, 160, True)
draw_tech_node("2. OBSERVATORIUM", 100, 340, 160, unlocked_techs["Observatorium"])
draw_tech_node("3. RAUMSCHIPS-WERFT", 300, 600, 160, unlocked_techs["Werft"])
draw_tech_node("4. ORBITAL-ANTRIEB", 500, 860, 160, unlocked_techs["Orbiter_Erforscht"])

pygame.draw.line(screen, COLOR_GOLD, (300, 190), (340, 190), 2)
pygame.draw.line(screen, COLOR_GOLD, (560, 190), (600, 190), 2)
pygame.draw.line(screen, COLOR_GOLD, (820, 190), (860, 190), 2)

elif current_tab == "SPACE":
pygame.draw.rect(screen, (10, 25, 35), (40, 40, SCREEN_WIDTH-80, 440))
screen.blit(large_font.render("TAB 3: ORBITAL-KONTROLLE & OBSERVATORIUM", True, COLOR_OBS), (80, 70))
pygame.draw.line(screen, COLOR_TEXT, (80, 120), (SCREEN_WIDTH-80, 120), 2)

obs_count = len(buildings[9]["list"])
screen.blit(font.render(f"AKTIVE OBSERVATORIEN: {obs_count}", True, COLOR_TEXT), (80, 150))

if obs_count == 0:
screen.blit(font.render("WARNUNG: Baue ein Observatorium auf der Karte, um den Sektor zu scannen!", True, COLOR_RED), (80, 180))
else:
screen.blit(font.render("STATUS: Sektor-Scan läuft... Keine Piraten-Aktivität gemeldet.", True, COLOR_DOME), (80, 180))
pygame.draw.circle(screen, (0, 60, 40), (800, 280), 100, 2)
pygame.draw.line(screen, COLOR_OBS, (800, 280), (800, 180), 2)

yard_count = len(buildings[10]["list"])
screen.blit(font.render(f"RAUMSCHIFF-WERFTEN: {yard_count}", True, COLOR_TEXT), (80, 240))
if yard_count > 0:
status_text = "BEREIT FÜR BAU" if not unlocked_techs["Orbiter_Erforscht"] else "ORBITER BEREIT ZUM START!"
screen.blit(font.render(f"WERFT-STATUS: {status_text}", True, COLOR_HIGHLIGHT), (80, 270))

# --- ZENTRALES UI-PANEL UNTEN ---
pygame.draw.rect(screen, COLOR_UI_BG, (0, 520, SCREEN_WIDTH, 200))
pygame.draw.line(screen, COLOR_TEXT, (0, 520), (SCREEN_WIDTH, 520), 2)

# Ressourcen-Leiste
res_text = f"STATS -> NAHRUNG: {resources['Nahrung']} | ERZ: {resources['Erz']} | ENERGIE: {resources['Energie']} | FORSCHUNG: {resources['Forschung']}"
screen.blit(font.render(res_text, True, COLOR_TEXT), (40, 530))

# Tab-Auswahl-Buttons rendern
def draw_tab_btn(text, f_key, tab_id, x):
is_active = (current_tab == tab_id)
col = COLOR_HIGHLIGHT if is_active else COLOR_TEXT
screen.blit(font.render(f"[{f_key}] {text}", True, col), (x, 530))

draw_tab_btn("PLANET", "F1", "MAP", 650)
draw_tab_btn("WIRTSCHAFT", "F2", "ECONOMY", 800)
draw_tab_btn("FORSCHUNG", "F3", "RESEARCH", 950)
draw_tab_btn("WELTRAUM", "F4", "SPACE", 1100)

pygame.draw.line(screen, (60, 60, 80), (40, 550), (SCREEN_WIDTH-40, 550), 1)

# UI-Inhalt je nach Registerkarte
if current_tab == "MAP":
menu_y, available_modes = 560, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for i, m in enumerate(available_modes):
b = buildings[m]
x_pos = 40 + (i * 120)
locked = (m == 9 and not unlocked_techs["Observatorium"]) or (m == 10 and not unlocked_techs["Werft"])

text_color = COLOR_HIGHLIGHT if (current_mode == m) else (COLOR_GREY if locked else COLOR_TEXT)
key_char = "0" if m == 10 else str(m)

screen.blit(font.render(f"[{key_char}] {b['name']}", True, text_color), (x_pos, menu_y))
cost_text = "GESPERRT" if locked else f"N:{b['cost']['N']} E:{b['cost']['E']}"
screen.blit(font.render(cost_text, True, COLOR_RED if locked else COLOR_GOLD), (x_pos, menu_y + 16))
if not locked: pygame.draw.rect(screen, b["color"], (x_pos, menu_y + 32, 12, 12))

elif current_tab == "ECONOMY":
screen.blit(font.render("STEUER-STEUERUNG AKTIV. NUTZE DIE PFEILTASTEN IM TERMINAL.", True, COLOR_TEXT), (40, 570))
elif current_tab == "RESEARCH":
screen.blit(font.render(f"AKTUELLE FORSCHUNGSRATE: +{len(buildings[8]['list']) * 15 + len(buildings[9]['list']) * 5} PKT / SEK.", True, COLOR_LAB), (40, 570))
elif current_tab == "SPACE":
if not unlocked_techs["Orbiter_Erforscht"]:
screen.blit(font.render("ZIEL: Erforsche den Orbiter mit Taste [F] (Kosten: 500 Forschung)", True, COLOR_HIGHLIGHT), (40, 570))
else:
screen.blit(font.render("ZIEL: Starte den Orbiter ins All mit Taste [S] (Kosten: 500 Erz, 300 Energie)", True, COLOR_GOLD), (40, 570))
# Overlays bei Spielende oder Sieg
if game_state == "GAME_OVER":
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 220))
screen.blit(overlay, (0, 0))
screen.blit(large_font.render("KOLONIE KOLLABIERT! (RESSOURCEN IM MINUS)", True, COLOR_RED), (SCREEN_WIDTH // 2 - 400, 250))
screen.blit(font.render("Drücke LEERTASTE für einen Neustart.", True, COLOR_TEXT), (SCREEN_WIDTH // 2 - 120, 320))
elif game_state == "VICTORY":
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
overlay.fill((0, 30, 60, 230))
screen.blit(overlay, (0, 0))
screen.blit(large_font.render("ORBITER ERFOLGREICH GESTARTET! DU HAST GEWONNEN!", True, COLOR_HIGHLIGHT), (SCREEN_WIDTH // 2 - 500, 250))
screen.blit(font.render("Drücke LEERTASTE für eine neue Runde.", True, COLOR_TEXT), (SCREEN_WIDTH // 2 - 120, 320))

pygame.display.flip()
clock.tick(60)

pygame.quit()
sys.exit()
>
Benutzeravatar
sparrow
User
Beiträge: 4658
Registriert: Freitag 17. April 2009, 10:28

@njnnjn: Die ist sicher in der Vorschau aufgefallen, dass die Einrückung verloren geht. Wenn du Code postest, platziere den bitte zwischen Code-Tags. Die erscheinen automatisch, wenn du den </> Button drückst.

Zum Code und warum ich ihn mir nicht näher anschaue:

Dein gesamter Code steht auf Modulebene.
Auf Modulebene stehen nur Importe, Definitionen von Klassen und Funktionen, Definitionen von Konstanten und der Main Guard. Alles andere hätte sonst einen globalen status und gehört da weg.

Du arbeitest da die ganze Zeit auf globalen Variablen. Das tut man nicht.
Strukturiere deine Code durch Funktionen.
Funktionen erhalten alles, was sie zum arbeiten brauche, als Parameter und geben ihr Ergebnis per return zurück. Das sorgt für nachvollziehbare Abläufe und man verliert nicht den Überblick wo welche Variable benötigt und geändert wird. In dem Kauderwelsch hast du dich verfangen.
Es nützt also nicht, deinen Code einfach in eine Funktion zu packen. Der muss durch Funktionen aufgebrochen und strukturiert werden.

Naming ist wichtig.
Warum bürdest du einem Leser auf, zu verstehen was "N", "E", "P" sein soll? Der Leser bist auch du in 2 Tage, 2 Wochen oder 2 Jahren. Vergib vernünftige, sprechende Namen.

Benutze keine magischen Werte.
Was soll buildings[5] sein?
"buildings" deutet sogar darauf hin, dass du die grundsätzlichen Datenstrukturen noch nicht verstanden hast. Hast du hier versucht ein JavaScrip-Array nachzubauen?!
Warum gehst du hir den super umständlichen Weg eine dict mit einer Nummerierung als Key zu verwenden? Mal ganz abgesehen davon, dass sich das als Liste deutlich einfacher darstellen lassen würde, drängt sich hier ein dict mit "name" als Schlüssel regelrecht auf.

Ich würde auch nicht "current state" und "Stammdaten" mischen. Das tust du aber. Du packst irgendwie die Beschreibung und die aktuelle Anzahl von Gebäuden/Schiffen in eine Gott-Datenstruktur. Trenn' das ordentlich.

Mitten im Code verbergen sich Funktionsdefinitionen. Die gehören da sicher nicht hin.
Und auch da änderst du dann Werte außerhalb des Namensraumes der Funktion, weil du auf da nur auf dem globalen Zustand rumfrickelst.

Das wäre schon einmal eine deutliche Verbesserung und führt dich vielleicht auch bei deinem Problem weiter.
imonbln
User
Beiträge: 209
Registriert: Freitag 3. Dezember 2021, 17:07

Das mit den Code-Tags hat schon mal nicht geklappt. Was Sirius3 meinte, war, dass du auf „Vollständiger Editor“ klicken sollst, dann auf den Button „Code-Tags“ und dazwischen deinen Code posten. Einrückungen haben in Python eine wichtige Bedeutung, so ist es schwer zu lesen.

Generell was sofort ins Auge springt:

fleet ist zweimal definiert.

Tut es not, die Amiga-Farbpalette so kompakt zu schreiben? Wäre es nicht besser, jedem Tupel und Namen eine eigene Zeile zu geben? Das erhöht die Lesbarkeit – und Code wird öfter gelesen als geschrieben.

Du solltest nach dem Divide-et-Impera-Prinzip deinen Eventloop in sinnvolle Funktionen aufteilen. Der ist 448 Zeilen lang, das durchschaut keiner. Als Faustformel gilt: Alles, was mehr als eine Bildschirmlänge braucht, ist schwer zu verstehen.

Du solltest den Code nicht einfach so in eine Datei schreiben, sondern in eine main()-Funktion packen und diese dann gezielt aufrufen.

Man iteriert nicht manuell über Listen. Du machst das bei buildings – das sollten zwei ineinander geschachtelte Schleifen sein. Ich weiß zwar, dass die Aktionen in der for-Schleife leicht unterschiedlich sind, aber für so etwas gibt es Callables.

Was unter „FLOTTE Bauen“ steht, ist immer wieder das Gleiche. Das ist eine DRY-Verletzung (Don't Repeat Yourself) und schreit geradezu danach, in eine Funktion ausgelagert zu werden.

Ich würde für fleet kein Dictionary verwenden, das wiederum ein Dictionary referenziert. Da Dictionaries mutable (veränderlich) sind, würde ich das Value-Dict durch eine Dataclass ersetzen.

buildings ist ein Dictionary, das als Key einen One-based Integer (bei 1 beginnenden Index) verwendet. Das ist nicht sinnvoll, zumal der Entwickler sich merken muss, dass 4 Straßen sind und 10 eine Werft. Vermutlich wird der Code verständlicher, wenn das jetzige name-Attribut der Key für das Dictionary wird. Für die Values in dem Dictionary würde ich wieder eine Dataclass verwenden, aber das sehen andere vielleicht anders.
Benutzeravatar
__blackjack__
User
Beiträge: 14403
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Weniger magische Zahlen und Zeichenkette wäre auch mein Tipp. Wörterbücher die alle den gleichen Satz an Schlüsseln haben, sind eigentlich Objekte mit Attributen. Ich persönlich mag das externe `attrs`-Package lieber als die Datenklassen aus der Standardbibliothek.

Der Spielzustand sollte keine Zeichenkette sein, sondern eher ein `enum.Enum`-Objekt, damit man sich nicht unbemerkt vertippen kann, und an _einer_ Stelle im Programm alle möglichen Zustände sehen kann. Vielleicht sogar dokumentiert. Andererseits könnte man sich die Indirektion sparen wenn man den Spielzustand als Funktionen oder Klassen modellieren würde. Dann braucht man nicht den zusätzlichen Code der die Zustandsvariable auf eine Funktion abbildet, sondern kann einfach die aktuelle Funktion aufrufen.

Ähnlich der aktuelle Reiter, der als Zeichenkette geführt wird.

`unlocked_techs` könnte man als `enum.Flag` modellieren.

Auch Namen die zusammengehören, und einen gemeinsamen Präfix haben, können darauf hindeuten, das man eigentlich eine Klasse daraus machen sollte. Wie beispielsweise die `asteroid_*`-Namen, die zusammen den Asteroiden beschreiben, der bearbeitet wird. Das könnte man durch `current_asteroid` ersetzen, das entweder `None` oder ein `Asteroid`-Objekt mit den entsprechenden Attributen ist.
“The city's central computer told you? R2D2, you know better than to trust a strange computer!” — C3PO
njnnjn
User
Beiträge: 3
Registriert: Mittwoch 3. Juni 2026, 15:09

Hallo,
vielen Dank für das Feetback. Ja es gibt ne menge die ich noch nicht weiß. Ich hoffe es kommt alles mit der Zeit. Was den ersten Code angeht so habe ich tatsächlich gedacht es wäre so gewünscht. Ich hoffe ich habe euch richtig verstanden und poste hier mal das Ergebnis des neuen Code:

Code: Alles auswählen

import pygame
import sys
import random

pygame.init()
pygame.font.init()

SCREEN_WIDTH, SCREEN_HEIGHT = 1280, 720
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Breed96 - Linux Port v7.0")
clock = pygame.time.Clock()

# Farben
COLOR_DESERT, COLOR_TEXT, COLOR_UI_BG = (194, 131, 62), (255, 255, 255), (30, 30, 40)
COLOR_GRID, COLOR_RED, COLOR_GOLD, COLOR_HIGHLIGHT, COLOR_GREY = (174, 111, 42), (220, 50, 50), (255, 215, 0), (0, 255, 255), (120, 120, 130)
COLOR_DOME, COLOR_MINE, COLOR_POWER, COLOR_ROAD = (0, 200, 100), (60, 60, 80), (220, 180, 0), (100, 65, 35)
COLOR_HOUSE, COLOR_INDUSTRY, COLOR_SHOP, COLOR_LAB = (180, 60, 160), (230, 90, 40), (0, 160, 220), (150, 0, 250)
COLOR_OBS, COLOR_YARD = (0, 255, 180), (200, 50, 50)

# Spielvariablen
resources = {"Nahrung": 200, "Erz": 300, "Energie": 200, "Forschung": 0}
unlocked_techs = {"Observatorium": False, "Werft": False, "Orbiter_Erforscht": False, "Orbiter_Gebaut": False}
citizens, tax_rate = 50, 10

fleet = {
    "Leichter Gleiter": {"count": 0, "cost": {"Erz": 150, "Energie": 50}},
    "Schwerer Gleiter": {"count": 0, "cost": {"Erz": 300, "Energie": 100}},
    "Transportschiff": {"count": 0, "cost": {"Erz": 400, "Energie": 150}},
    "Abbauschiff": {"count": 0, "cost": {"Erz": 350, "Energie": 200}},
    "Kolonieschiff": {"count": 0, "cost": {"Erz": 800, "Energie": 400}},
    "Schlachtkreuzer": {"count": 0, "cost": {"Erz": 1200, "Energie": 600}}
}

asteroid_discovered, asteroid_ore_left = False, 0
space_log = "STATION AKTIV. Warte auf Orbiter..."
current_tab, game_state, tick_counter = "MAP", "PLAYING", 0
current_mode = 1

buildings = {
    1: {"name": "Kuppel", "list": [], "cost": {"N": 20, "E": 40, "P": 10}, "color": COLOR_DOME},
    2: {"name": "Erzmine", "list": [], "cost": {"N": 40, "E": 20, "P": 20}, "color": COLOR_MINE},
    3: {"name": "Kraftwerk", "list": [], "cost": {"N": 10, "E": 60, "P": 0}, "color": COLOR_POWER},
    4: {"name": "Strasse", "list": [], "cost": {"N": 0, "E": 5, "P": 0}, "color": COLOR_ROAD},
    5: {"name": "Wohnhaus", "list": [], "cost": {"N": 10, "E": 30, "P": 15}, "color": COLOR_HOUSE},
    6: {"name": "Industrie", "list": [], "cost": {"N": 30, "E": 80, "P": 30}, "color": COLOR_INDUSTRY},
    7: {"name": "Mall", "list": [], "cost": {"N": 50, "E": 100, "P": 25}, "color": COLOR_SHOP},
    8: {"name": "Forschung", "list": [], "cost": {"N": 40, "E": 150, "P": 40}, "color": COLOR_LAB},
    9: {"name": "Observat.", "list": [], "cost": {"N": 60, "E": 200, "P": 60}, "color": COLOR_OBS},
    10: {"name": "Werft", "list": [], "cost": {"N": 100, "E": 400, "P": 100}, "color": COLOR_YARD}
}

font = pygame.font.SysFont("Courier", 12, bold=True)
large_font = pygame.font.SysFont("Courier", 32, bold=True)

def has_road_connection(pos):
    neighbors = [(pos[0]-40, pos[1]), (pos[0]+40, pos[1]), (pos[0], pos[1]-40), (pos[0], pos[1]+40)]
    for n in neighbors:
        if n in buildings[4]["list"]: return True
    return False

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
            
            if game_state in ["PLAYING", "VICTORY"]:
                if event.key == pygame.K_F1: current_tab = "MAP"
                elif event.key == pygame.K_F2: current_tab = "ECONOMY"
                elif event.key == pygame.K_F3: current_tab = "RESEARCH"
                elif event.key == pygame.K_F4: current_tab = "SPACE"

            if game_state == "PLAYING" and current_tab == "ECONOMY":
                if event.key == pygame.K_UP and tax_rate < 30: tax_rate += 1
                elif event.key == pygame.K_DOWN and tax_rate > 0: tax_rate -= 1

            if game_state == "PLAYING":
                if current_tab == "MAP":
                    if pygame.K_1 <= event.key <= pygame.K_7: current_mode = event.key - pygame.K_1 + 1
                    elif event.key == pygame.K_8: current_mode = 8
                    elif event.key == pygame.K_9: current_mode = 9
                    elif event.key == pygame.K_0: current_mode = 10
                elif current_tab == "SPACE":
                    if event.key == pygame.K_f and len(buildings[10]["list"]) > 0 and resources["Forschung"] >= 500 and not unlocked_techs["Orbiter_Erforscht"]:
                        resources["Forschung"] -= 500
                        unlocked_techs["Orbiter_Erforscht"] = True
                        space_log = "Orbiter erforscht! Baue ihn mit [B]."
                    elif event.key == pygame.K_b and unlocked_techs["Orbiter_Erforscht"] and len(buildings[10]["list"]) > 0 and resources["Erz"] >= 800 and resources["Energie"] >= 400 and not unlocked_techs["Orbiter_Gebaut"]:
                        resources["Erz"] -= 800
                        resources["Energie"] -= 400
                        unlocked_techs["Orbiter_Gebaut"] = True
                        space_log = "Orbiter gebaut! Starte ihn mit [S]."
                    elif event.key == pygame.K_s and unlocked_techs["Orbiter_Gebaut"] and len(buildings[10]["list"]) > 0:
                        space_log = "ORBITER GESTARTET! Endlosmodus aktiv."
                    
                    if unlocked_techs["Orbiter_Gebaut"]:
                        if event.key == pygame.K_a and resources["Erz"] >= 150 and resources["Energie"] >= 50:
                            resources["Erz"] -= 150; resources["Energie"] -= 50; fleet["Leichter Gleiter"]["count"] += 1
                        elif event.key == pygame.K_b and resources["Erz"] >= 300 and resources["Energie"] >= 100:
                            resources["Erz"] -= 300; resources["Energie"] -= 100; fleet["Schwerer Gleiter"]["count"] += 1

            if game_state != "PLAYING" and event.key == pygame.K_SPACE:
                resources = {"Nahrung": 200, "Erz": 300, "Energie": 200, "Forschung": 0}
                unlocked_techs = {"Observatorium": False, "Werft": False, "Orbiter_Erforscht": False, "Orbiter_Gebaut": False}
                citizens, tax_rate, current_tab, game_state = 50, 10, "MAP", "PLAYING"
                for m in buildings: buildings[m]["list"] = []

        elif event.type == pygame.MOUSEBUTTONDOWN and game_state == "PLAYING" and current_tab == "MAP":
            mouse_x, mouse_y = pygame.mouse.get_pos()
            if mouse_y < 520:
                if not ((current_mode == 9 and not unlocked_techs["Observatorium"]) or (current_mode == 10 and not unlocked_techs["Werft"])):
                    b_data = buildings[current_mode]
                    if resources["Nahrung"] >= b_data["cost"]["N"] and resources["Erz"] >= b_data["cost"]["E"] and resources["Energie"] >= b_data["cost"]["P"]:
                        grid_x, grid_y = (mouse_x // 40) * 40 + 20, (mouse_y // 40) * 40 + 20
                        pos = (grid_x, grid_y)
                        occupied = any(pos in buildings[m]["list"] for m in buildings)
                        has_buildings = any(len(buildings[m]["list"]) > 0 for m in buildings)
                        adjacent_to_road = True if (current_mode == 4 or not has_buildings) else has_road_connection(pos)
                        if not occupied and adjacent_to_road:
                            resources["Nahrung"] -= b_data["cost"]["N"]
                            resources["Erz"] -= b_data["cost"]["E"]
                            resources["Energie"] -= b_data["cost"]["P"]
                            b_data["list"].append(pos)

    # Wirtschaftsticks
    if game_state == "PLAYING":
        if resources["Forschung"] >= 100: unlocked_techs["Observatorium"] = True
        if resources["Forschung"] >= 300: unlocked_techs["Werft"] = True
        tick_counter += 1
        if tick_counter >= 60:
            tick_counter = 0
            resources["Nahrung"] += 2; resources["Erz"] += 2; resources["Energie"] += 5
            
            resources["Nahrung"] += len(buildings[1]["list"]) * 8
            resources["Erz"] += len(buildings[2]["list"]) * 12
            resources["Energie"] += len(buildings[3]["list"]) * 18
            
            max_citizens = len(buildings[5]["list"]) * 15 + 20
            citizens = min(citizens + 2 if citizens < max_citizens else citizens, max_citizens)
            resources["Erz"] += len(buildings[5]["list"]) * int(tax_rate / 5)
            resources["Erz"] += len(buildings[6]["list"]) * 35
            resources["Forschung"] += len(buildings[8]["list"]) * 15 + len(buildings[9]["list"]) * 5
            
            if not asteroid_discovered and random.randint(1, 50) == 1:
                asteroid_discovered, asteroid_ore_left = True, random.randint(800, 1500)
                space_log = f"ASTEROID! Vorkommen: {asteroid_ore_left} Erz."
            
            if asteroid_discovered and fleet["Abbauschiff"]["count"] > 0:
                abbau = min(fleet["Abbauschiff"]["count"] * 15, asteroid_ore_left)
                asteroid_ore_left -= abbau; resources["Erz"] += abbau
                if asteroid_ore_left <= 0: asteroid_discovered = False
            
            if resources["Nahrung"] < 0 or resources["Erz"] < 0 or resources["Energie"] < 0: game_state = "GAME_OVER"

    # Rendering
    screen.fill(COLOR_DESERT)
    if current_tab == "MAP":
        for x in range(0, SCREEN_WIDTH, 40): pygame.draw.line(screen, COLOR_GRID, (x, 0), (x, 520))
        for y in range(0, 520, 40): pygame.draw.line(screen, COLOR_GRID, (0, y), (SCREEN_WIDTH, y))
        for r in buildings[4]["list"]: pygame.draw.rect(screen, COLOR_ROAD, (r[0]-20, r[1]-20, 40, 40))
        for d in buildings[1]["list"]: pygame.draw.circle(screen, COLOR_DOME, d, 16)
        for m in buildings[2]["list"]: pygame.draw.rect(screen, COLOR_MINE, (m[0]-15, m[1]-15, 30, 30))
        for p in buildings[3]["list"]: pygame.draw.polygon(screen, COLOR_POWER, [(p[0], p[1]-15), (p[0]-15, p[1]+15), (p[0]+15, p[1]+15)])
        for house in buildings[5]["list"]: pygame.draw.rect(screen, COLOR_HOUSE, (house[0]-14, house[1]-8, 28, 22))
        for i in buildings[6]["list"]: pygame.draw.rect(screen, COLOR_INDUSTRY, (i[0]-16, i[1]-6, 32, 20))
        for s in buildings[7]["list"]: pygame.draw.ellipse(screen, COLOR_SHOP, (s[0]-18, s[1]-12, 36, 24))
        for l in buildings[8]["list"]:
            pygame.draw.rect(screen, COLOR_LAB, (l[0]-15, l[1]-15, 30, 30))
            pygame.draw.circle(screen, COLOR_HIGHLIGHT, l, 6)
        for o in buildings[9]["list"]:
            pygame.draw.circle(screen, COLOR_OBS, o, 14)
            pygame.draw.line(screen, COLOR_TEXT, o, (o[0]+16, o[1]-16), 4)
        for y in buildings[10]["list"]: pygame.draw.rect(screen, COLOR_YARD, (y[0]-18, y[1]-18, 36, 36), 3)
    elif current_tab == "ECONOMY":
        pygame.draw.rect(screen, (20, 20, 30), (40, 40, SCREEN_WIDTH-80, 440))
        screen.blit(large_font.render("WIRTSCHAFTS-TERMINAL", True, COLOR_HIGHLIGHT), (80, 70))
        screen.blit(font.render(f"Kolonisten: {citizens} | Steuern: {tax_rate}% (Pfeiltasten)", True, COLOR_TEXT), (80, 160))
    elif current_tab == "RESEARCH":
        pygame.draw.rect(screen, (30, 20, 40), (40, 40, SCREEN_WIDTH-80, 440))
        screen.blit(large_font.render("TECHNOLOGIE-DATENBANK", True, COLOR_LAB), (80, 70))
        screen.blit(font.render(f"Observatorium: {unlocked_techs['Observatorium']} | Werft: {unlocked_techs['Werft']}", True, COLOR_TEXT), (80, 160))
    elif current_tab == "SPACE":
        pygame.draw.rect(screen, (10, 25, 35), (40, 40, SCREEN_WIDTH-80, 440))
        screen.blit(large_font.render("ORBITAL-KONTROLLE", True, COLOR_OBS), (80, 70))
        screen.blit(font.render(f"LOG: {space_log}", True, COLOR_GOLD), (80, 160))
        screen.blit(font.render(f"Gleiter L: {fleet['Leichter Gleiter']['count']} | Gleiter S: {fleet['Schwerer Gleiter']['count']}", True, COLOR_TEXT), (80, 200))

    # UI unten
    pygame.draw.rect(screen, COLOR_UI_BG, (0, 520, SCREEN_WIDTH, 200))
    res_text = f"NAHRUNG: {resources['Nahrung']} | ERZ: {resources['Erz']} | ENERGIE: {resources['Energie']} | FORSCHUNG: {resources['Forschung']} | TABs: F1-F4"
    screen.blit(font.render(res_text, True, COLOR_TEXT), (40, 530))
    if current_tab == "MAP":
        for i in range(1, 11):
            screen.blit(font.render(f"[{i%10}] {buildings[i]['name']}", True, COLOR_TEXT), (40 + ((i-1) * 120), 560))

    if game_state == "GAME_OVER":
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 220))
        screen.blit(overlay, (0, 0))
        screen.blit(large_font.render("KOLONIE KOLLABIERT! [LEERTASTE]", True, COLOR_RED), (400, 250))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()
Ich bin ganz offen für weitere Anmerkungen, nur so kann ich lernen.
LG
imonbln
User
Beiträge: 209
Registriert: Freitag 3. Dezember 2021, 17:07

Wie ich und andere schon geschrieben haben, solltest du dein Konzept überarbeiten. Ich empfehle Klassen; ob Datenklassen oder etwas anderes, spielt keine Rolle. Zum Beispiel würde ich eine Datenklasse für die Ressourcen implementieren, die ungefähr so aussieht. Die kann dann einfach zwei Ressourcen-Instanzen vergleichen, addieren oder subtrahieren.

Code: Alles auswählen

from dataclasses import dataclass
from typing import Self


@dataclass
class Resources:
    food: int = 0
    ore: int = 0
    energy: int = 0
    science: int = 0

    def __add__(self, other: "Resources") -> Self:
        if isinstance(other, Resources):
            return Resources(
                food=self.food + other.food,
                ore=self.ore + other.ore,
                energy=self.energy + other.energy,
                science=self.science + other.science
            )
        return NotImplemented

    def __iadd__(self, other: "Resources") -> Self:
        if isinstance(other, Resources):
            temp = self + other
            self.energy = temp.energy
            self.food = temp.food
            self.ore = temp.ore
            self.science = temp.science
            return self
        return NotImplemented

    def __sub__(self, other: "Resources") -> Self:
        if isinstance(other, Resources):
            return Resources(
                food=self.food - other.food,
                ore=self.ore - other.ore,
                energy=self.energy - other.energy,
                science=self.science - other.science
            )
        return NotImplemented

    def __isub__(self, other: "Resources") -> Self:
        if isinstance(other, Resources):
            temp = self - other
            self.energy = temp.energy
            self.food = temp.food
            self.ore = temp.ore
            self.science = temp.science
            return self
        return NotImplemented
    def __ge__(self, other: "Resources") -> bool:
        if isinstance(other, Resources):
            return (
                self.energy >= other.energy and
                self.food >= other.food and
                self.ore >= other.ore and
                self.science >= other.science
            )
        return NotImplemented

    def __le__(self, other: "Resources") -> bool:
        if isinstance(other, Resources):
            return (
                self.energy >= other.energy and
                self.food >= other.food and
                self.ore >= other.ore and
                self.science >= other.sicence
            )
        return NotImplemented


def main():
    player_resources = Resources(400, 400, 400, 0)
    gain_science = Resources(science=20)
    build_cost = Resources(140, 200, 0, 0)

    player_resources += gain_science
    print(f"Nach Einkommen: {player_resources}")

    if player_resources >= build_cost:
        player_resources -= build_cost
        print("Bau erfolgreich!")
    else:
        print("Nicht genug Ressourcen!")

    print(f"Ende: {player_resources}")


if __name__ == '__main__':
    main()

Dann kannst du zum Beispiel ein paar Schiff- und Spieler-Klassen erschaffen, in denen du alles bündelst und so weiter.

Code: Alles auswählen

#!/usr/bin/env python
from dataclasses import dataclass, field
from resources import Resources


@dataclass(frozen=True)
class Ship:
    name: str,
    costs: Resources


@dataclass
class Fleet:
    ships: dict[Ship, int] = field(default_factory=dict)

    def add_ship(self, ship: Ship) -> None:
        self.ships[ship] = self.ships.get(ship, 0) + 1

    def get_amount(self, ship: Ship) -> int:
        return self.ships.get(ship, 0)


SHIP_TYPES = (
        Ship("Leichter Gleiter", Resources(ore=150, energy=50)),
        Ship("Schwerer Gleiter", Resources(ore=300, energy=100)),
        Ship("Transportschiff", Resources(ore=400, energy=150)),
        Ship("Abbauschiff", Resources(ore=350, energy=200)),
        Ship("Kolonieschiff", Resources(ore=800, energy=400)),
        Ship("Schlachtkreuzer", Resources(ore=1200, energy=600)),
)

Code: Alles auswählen

from enum import Flag, auto
from resources import Resources
from ships import Ship, Fleet

class Tech(Flag):
    NONE = 0
    OBSERVATORY = auto()
    SHIPYARD = auto()
    ORBITER_RESEARCHED = auto()
    ORBITER_BUILT = auto()


class Player:

    def __init__(self):
        self.account = Resources(
                food=200,
                ore=300,
                energy= 200,
        )
        self.fleet = Fleet()
        self.citizens = 50
        self._tax_rate = 10
        self.unlocked_techs: Tech = Tech.NONE
        
    def build_a_ship(self, ship: Ship) -> bool:
        if self.account >= ship.costs:
            self.account -= ship.costs
            self.fleet.add_ship(ship)
            return True
        return False

    @property
    def tax_rate(self) -> int:
        return self._tax_rate

    @tax_rate.setter
    def tax_rate(self, value: int) -> None:
        """
        set the tax_rate and clipp value between 0-30
        """
        self.tax_rate = max(0, min(value, 30))

Übrigens ist bei den Gebäuden auch noch etwas im Argen. Die Kosten mit „N“, „E“ und „P“ abzukürzen, ist die Härte. In drei Jahren weißt du nicht mehr, ob „E“ für Energie oder Erz stand. Code sollte auf Lesbarkeit optimiert werden. Und Ein-Buchstaben-Variablen lassen sich auch supergut wiederfinden, wenn man mal nachsehen will, wo sie überall verwendet werden (wer Sarkasmus findet, darf ihn behalten).
Antworten