import pyxel

# ============================================================
#  CITY QUEST  –  Paris · Venedig · New York
#  Steuerung:  P1 = WASD    P2 = Pfeiltasten
#
#  Pyxel-Palette:
#   0  BLACK    1  NIGHT    2  PURPLE   3  TEAL
#   4  BROWN    5  BLUE     6  LBLUE    7  WHITE
#   8  P1C(pink/rot)        9  P2C(orange/gold)
#  10  YELLOW  11  MINT    12  PERIWI  13  GRAY
#  14  PINK    15  SAND
# ============================================================

W, H   = 256, 144
FPS    = 60
GRAV   = 0.38
JUMP   = -7.8
SPEED  = 2.6

BLACK  = 0;  NIGHT  = 1;  PURPLE = 2;  TEAL   = 3
BROWN  = 4;  BLUE   = 5;  LBLUE  = 6;  WHITE  = 7
P1C    = 8;  P2C    = 9;  YELLOW = 10; MINT   = 11
PERIWI = 12; GRAY   = 13; PINK   = 14; SAND   = 15


# ============================================================
#  NEW YORK hat 3 ZONEN (zone wird nach x-Position bestimmt)
#  Zone 0: Central Park (grün, Tag)
#  Zone 1: Midtown / Times Square (bunt, Nacht)
#  Zone 2: Hudson River / Skyline-Nacht
# ============================================================
def ny_zone(world_x):
    if world_x < 700:    return 0   # Central Park
    elif world_x < 1500: return 1   # Times Square
    else:                return 2   # Skyline Nacht


# ============================================================
#  LEVEL-DEFINITIONEN
# ============================================================

def make_paris():
    return {
        "name":    "Paris",
        "sky":     LBLUE,
        "gnd_col": GRAY,
        "length":  2000,
        "goal_x":  1920,
        "platforms": [
            (190,110,50,6),(300,96,48,6),(400,80,52,6),(500,65,48,6),
            (600,50,52,6),(700,36,50,6),(800,50,48,6),(900,68,55,6),
            (990,88,52,6),(1090,104,52,6),(1185,86,55,6),(1295,70,50,6),
            (1390,88,55,6),(1490,106,52,6),(1595,83,55,6),(1695,68,50,6),
            (1795,88,55,6),
        ],
        "obstacles": [
            # Macarons – bunt, je andere Farbe durch Positions-Hash
            (255,113,12,14,"macaron"),(340,113,12,14,"macaron"),
            (430,113,12,14,"macaron"),(580,113,12,14,"macaron"),
            (670,113,12,14,"macaron"),(820,113,12,14,"macaron"),
            # Baguettes – lange Stangen (quer liegend als Hürde)
            (480,110,18,8,"baguette_h"),(730,108,18,8,"baguette_h"),
            (1100,110,18,8,"baguette_h"),(1500,110,18,8,"baguette_h"),
            # Croissants
            (960,112,14,10,"croissant"),(1060,112,14,10,"croissant"),
            (1400,112,14,10,"croissant"),(1600,112,14,10,"croissant"),
            # Blumentöpfe (Rue Crémieux)
            (280,112,10,16,"flowerpot"),(870,112,10,16,"flowerpot"),
            (1240,112,10,16,"flowerpot"),(1750,112,10,16,"flowerpot"),
            # Café-Stühle (Montmartre)
            (1160,110,13,18,"cafe_chair"),(1310,110,13,18,"cafe_chair"),
            (1700,110,13,18,"cafe_chair"),
            # Laternen
            (1148,70,5,46,"lantern"),(1558,70,5,46,"lantern"),
            # Weinflaschen auf Plattformen
            (500,58,6,12,"wine"),(700,29,6,12,"wine"),(1295,62,6,12,"wine"),
        ],
        "traps": [
            (460,128,32,16),(740,128,36,16),(1000,128,40,16),
            (1300,128,32,16),(1600,128,36,16),
        ],
    }


def make_venice():
    return {
        "name":    "Venedig",
        "sky":     BLUE,
        "gnd_col": PERIWI,
        "length":  2000,
        "goal_x":  1920,
        "platforms": [
            (150,112,70,6),(270,100,60,6),(380,88,55,6),(480,75,60,6),
            (580,88,55,6),(680,100,60,6),(780,85,70,6),(890,70,55,6),
            (990,88,60,6),(1090,105,55,6),(1190,88,60,6),(1300,72,55,6),
            (1400,90,60,6),(1510,108,55,6),(1610,85,60,6),(1720,70,55,6),
            (1820,90,60,6),
        ],
        "obstacles": [
            # Gondeln (groß, schwarze Form zum Drüberspringen)
            (310,108,26,10,"gondola"),(560,108,26,10,"gondola"),
            (960,108,26,10,"gondola"),(1350,108,26,10,"gondola"),
            (1650,108,26,10,"gondola"),
            # Gondoliere-Hut (flacher Strohhut)
            (430,110,14,8,"gondolier_hat"),(680,110,14,8,"gondolier_hat"),
            (840,110,14,8,"gondolier_hat"),(1150,110,14,8,"gondolier_hat"),
            (1480,110,14,8,"gondolier_hat"),(1780,110,14,8,"gondolier_hat"),
            # Karneval-Masken (bunt, aufwendig wie auf Foto)
            (500,103,14,12,"carnival_mask"),(760,103,14,12,"carnival_mask"),
            (1060,103,14,12,"carnival_mask"),(1260,103,14,12,"carnival_mask"),
            (1580,103,14,12,"carnival_mask"),
            # Karneval-Kostüm (stehend, breite Hürde)
            (1100,98,16,20,"carnival_costume"),(1700,98,16,20,"carnival_costume"),
            # Venezianische Laterne
            (900,86,5,22,"venice_lamp"),(1400,86,5,22,"venice_lamp"),
            # Masken auf Plattformen
            (680,92,14,12,"carnival_mask"),(1190,80,14,12,"carnival_mask"),
        ],
        "traps": [
            (230,120,38,24),(560,120,42,24),(870,120,45,24),
            (1160,120,42,24),(1470,120,50,24),(1760,120,38,24),
        ],
    }


def make_newyork():
    # Zone 0: Central Park (0–700)  → grüner Boden
    # Zone 1: Times Square (700–1500) → grauer Asphalt
    # Zone 2: Skyline/Hafen (1500–2200) → dunkler Asphalt
    return {
        "name":    "New York",
        "sky":     LBLUE,   # wird per Zone überschrieben im draw
        "gnd_col": TEAL,    # wird per Zone überschrieben
        "length":  2200,
        "goal_x":  2120,
        "platforms": [
            # Zone 0: Parkbänke / Brücken (grüne Plattformen)
            (160,112,60,6),(270,98,55,6),(370,80,60,6),(470,62,55,6),
            # Zone 1: Feuerleitern, Dächer
            (570,45,60,6),(670,62,55,6),(770,80,60,6),(870,98,60,6),
            (970,80,55,6),(1070,62,60,6),(1170,45,55,6),(1270,62,60,6),
            # Zone 2: Hochhaus-Vorsprünge
            (1370,80,55,6),(1470,95,60,6),(1570,75,55,6),(1680,58,60,6),
            (1790,78,55,6),(1900,95,60,6),(2000,75,60,6),
        ],
        "obstacles": [
            # Zone 0 (Central Park): Parkbänke, Hunde, Vögel
            (230,112,16,10,"park_bench"),(340,112,16,10,"park_bench"),
            (180,110,10,8,"pigeon"),(420,110,10,8,"pigeon"),
            (510,110,10,8,"pigeon"),
            # Zone 1 (Times Square): Taxis, Hotdogs, Hydranten, Pizza
            (620,112,18,10,"taxi"),(780,112,18,10,"taxi"),
            (960,112,18,10,"taxi"),(1150,112,18,10,"taxi"),
            (1320,112,18,10,"taxi"),
            (680,111,12,13,"pizza"),(840,111,12,13,"pizza"),
            (1020,111,12,13,"pizza"),(1240,111,12,13,"pizza"),
            (720,112,8,12,"hydrant"),(900,112,8,12,"hydrant"),
            (1100,112,8,12,"hydrant"),(1280,112,8,12,"hydrant"),
            (700,111,12,12,"burger"),(1070,111,12,12,"burger"),
            # Zone 2 (Skyline): Freiheitsfackeln, Trash, Taxis
            (1420,112,8,12,"hydrant"),(1620,112,8,12,"hydrant"),
            (1520,112,18,10,"taxi"),(1750,112,18,10,"taxi"),
            (1480,111,12,13,"pizza"),(1700,111,12,12,"burger"),
            (1850,112,8,10,"trash"),(2000,112,8,10,"trash"),
        ],
        "traps": [
            (410,128,30,16),(640,128,36,16),(920,128,40,16),
            (1200,128,35,16),(1500,128,38,16),(1800,128,35,16),
            (2050,128,32,16),
        ],
    }


LEVELS = [make_paris(), make_venice(), make_newyork()]


# ============================================================
#  HINDERNISSE ZEICHNEN
# ============================================================
def draw_obstacle(ox, oy, ow, oh, typ, cx):
    x = int(ox - cx); y = int(oy)
    if x < -ow - 8 or x > W + ow:
        return

    # ─── PARIS ──────────────────────────────────────────────

    if typ == "macaron":
        # Macaron: zwei flache Halbkugeln mit cremiger Füllung
        mac_cols = [P1C, PINK, MINT, PURPLE, YELLOW, P2C, LBLUE, P2C]
        ci = (int(ox) // 80) % len(mac_cols)
        c1 = mac_cols[ci]
        c2 = mac_cols[(ci + 3) % len(mac_cols)]
        # obere Schale (gewölbt)
        pyxel.rect(x+2, y,   ow-4, 2, c1)   # Spitze
        pyxel.rect(x+1, y+2, ow-2, 2, c1)
        pyxel.rect(x,   y+4, ow,   3, c1)   # breiteste Stelle
        # Cremefüllung
        pyxel.rect(x,   y+7, ow,   2, WHITE)
        pyxel.line(x+1, y+8, x+ow-2, y+8, SAND)
        # untere Schale
        pyxel.rect(x,   y+9,  ow,   3, c2)
        pyxel.rect(x+1, y+12, ow-2, 2, c2)

    elif typ == "baguette_h":
        # Baguette quer liegend (als Hürde zum Drüberspringen)
        pyxel.rect(x,   y+3, ow, oh-6, P2C)     # goldbraun
        pyxel.rect(x,   y+3, ow, 2,    YELLOW)  # helle Oberkante
        pyxel.tri(x,    y+3, x+4, y+3, x+2, y,  YELLOW)  # linke Spitze
        pyxel.tri(x+ow-4, y+3, x+ow, y+3, x+ow-2, y, YELLOW)  # rechte Spitze
        # Einschnitte (typisch für Baguette)
        for si in range(3, ow-3, 5):
            pyxel.line(x+si, y+3, x+si+2, y+5, BROWN)

    elif typ == "croissant":
        # Croissant: goldbraune Halbmond-Form
        pyxel.rect(x+2, y,   ow-4, oh, P2C)
        pyxel.rect(x+1, y+2, ow-2, oh-2, P2C)
        pyxel.rect(x,   y+4, ow,   oh-6, P2C)
        pyxel.rect(x+1, y+1, ow-2, 2, YELLOW)  # Glanz
        # Spitzen
        pyxel.tri(x, y+4, x+3, y+oh, x, y+oh, BROWN)
        pyxel.tri(x+ow, y+4, x+ow-3, y+oh, x+ow, y+oh, BROWN)

    elif typ == "flowerpot":
        # Blumentopf (Rue Crémieux)
        pyxel.rect(x+1, y+7, ow-2, oh-7, BROWN)
        pyxel.rect(x,   y+8, ow,   oh-9, BROWN)
        pyxel.rect(x,   y+6, ow,   3,    P2C)    # Topfrand orange
        pyxel.rect(x+1, y+7, ow-2, 2, TEAL)      # Erde
        # Stängel
        pyxel.rect(x+ow//2, y+2, 1, 6, TEAL)
        pyxel.rect(x+ow//2-2, y+4, 1, 3, TEAL)   # Zweig
        # Blüte
        flcols = [P1C, PINK, YELLOW, MINT, PURPLE]
        fc = flcols[(int(ox) // 60) % len(flcols)]
        pyxel.rect(x+ow//2-2, y, 5, 3, fc)
        pyxel.rect(x+ow//2-3, y+1, 7, 2, fc)
        pyxel.pset(x+ow//2, y+1, YELLOW)

    elif typ == "cafe_chair":
        # Pariser Café-Stuhl (rot)
        pyxel.rect(x+1,    y+11, 2, oh-11, P1C)   # Bein links
        pyxel.rect(x+ow-3, y+11, 2, oh-11, P1C)   # Bein rechts
        pyxel.rect(x,      y+9,  ow, 3, P1C)       # Sitz
        pyxel.rect(x+1,    y,    ow-2, 11, P1C)    # Rückenlehne
        pyxel.rect(x+3,    y+2,  ow-6, 7,  PINK)   # Polster

    elif typ == "lantern":
        # Pariser Straßenlaterne
        pyxel.rect(x+2, y+6, 2, oh-8, BLACK)
        pyxel.rect(x-1, y+oh-7, 7, 2, BLACK)
        pyxel.rect(x-3, y+oh-14, 9, 7, BLACK)
        pyxel.rect(x-2, y+oh-13, 7, 5, YELLOW)
        pyxel.pset(x+1, y+oh-10, WHITE)
        pyxel.rect(x+1, y, 3, 8, BLACK)

    elif typ == "wine":
        pyxel.rect(x+1, y+3, 4, oh-5, PURPLE)
        pyxel.rect(x+2, y,   2, 4,    TEAL)
        pyxel.rect(x,   y+oh-5, 6, 5, PURPLE)
        pyxel.rect(x+1, y+oh-9, 4, 3, WHITE)
        pyxel.pset(x+2, y+oh-8, P2C)

    # ─── VENEDIG ─────────────────────────────────────────────

    elif typ == "gondola":
        # Schwarze Gondel – zum Drüberspringen
        # Rumpf
        pyxel.rect(x+2, y+4, ow-4, oh-4, BLACK)
        pyxel.rect(x+1, y+5, ow-2, oh-5, BLACK)
        pyxel.rect(x,   y+6, ow,   oh-7, BLACK)
        # Bug-Spitze (ferro)
        pyxel.tri(x, y+6, x+4, y+6, x+1, y+3, GRAY)
        pyxel.pset(x+1, y+3, WHITE)
        # Kabine
        pyxel.rect(x+ow//2-4, y, 8, oh-3, TEAL)
        pyxel.rect(x+ow//2-3, y+1, 6, oh-5, SAND)
        # Wasserlinie
        pyxel.line(x, y+6, x+ow, y+6, LBLUE)

    elif typ == "gondolier_hat":
        # Gondoliere-Strohhut (flach, typisch mit schwarzem Band)
        pyxel.rect(x+2, y,   ow-4, oh-4, SAND)    # Hutkopf
        pyxel.rect(x,   y+3, ow,   2,    SAND)    # Krempe
        pyxel.rect(x+1, y+1, ow-2, 2,    BLACK)   # schwarzes Band
        pyxel.line(x+2, y,   x+ow-3, y,  P2C)     # Glanzlicht

    elif typ == "carnival_mask":
        # Venezianische Karnevalsmaske (lila/gold wie auf Foto)
        mc = [PURPLE, P1C, MINT, P2C]
        mc_c = mc[(int(ox) // 70) % len(mc)]
        pyxel.rect(x,   y+1, ow, oh-2, mc_c)      # Maskenform
        pyxel.rect(x+1, y,   ow-2, oh, mc_c)
        # Augen (Schlitze)
        pyxel.rect(x+2, y+2, 3, 3, BLACK)
        pyxel.rect(x+ow-5, y+2, 3, 3, BLACK)
        # Goldene Verzierung
        pyxel.line(x, y, x+ow, y, YELLOW)
        pyxel.line(x, y+oh, x+ow, y+oh, YELLOW)
        pyxel.pset(x+ow//2, y+2, YELLOW)
        # Federn oben
        pyxel.rect(x+ow//2-1, y-4, 2, 4, PURPLE)
        pyxel.rect(x+ow//2+2, y-3, 2, 3, PINK)
        pyxel.rect(x+ow//2-4, y-3, 2, 3, MINT)

    elif typ == "carnival_costume":
        # Karneval-Kostüm (stehend, bunt)
        cc = [PURPLE, P1C, MINT]
        c = cc[(int(ox) // 80) % len(cc)]
        # Körper
        pyxel.rect(x+3, y+8,  ow-6, oh-8, c)
        # Hut
        pyxel.rect(x+1, y+2,  ow-2, 4, c)
        pyxel.rect(x+4, y,    ow-8, 4, c)
        # Kragen (Jabot)
        pyxel.rect(x+2, y+7,  ow-4, 3, WHITE)
        pyxel.tri(x+ow//2-2, y+10, x+ow//2+2, y+10, x+ow//2, y+14, WHITE)
        # Goldener Gürtel
        pyxel.rect(x+3, y+12, ow-6, 2, YELLOW)
        # Federn am Hut
        pyxel.rect(x+ow-4, y-3, 2, 5, PINK)
        pyxel.rect(x+ow-2, y-2, 2, 4, YELLOW)

    elif typ == "venice_lamp":
        pyxel.rect(x+1, y+5, 2, oh-6, TEAL)
        pyxel.circ(x+2, y+3, 4, YELLOW)
        pyxel.circ(x+2, y+3, 2, WHITE)
        pyxel.rect(x,   y+5, 5, 2, GRAY)

    # ─── NEW YORK ─────────────────────────────────────────────

    elif typ == "park_bench":
        # Central Park Parkbank
        pyxel.rect(x+1,    y+6, ow-2, oh-6, BROWN)  # Sitz
        pyxel.rect(x,      y+5, ow,   3,    BROWN)  # Sitzfläche
        pyxel.rect(x+1,    y,   ow-2, 6,    BROWN)  # Rückenlehne
        pyxel.rect(x+2,    y+1, ow-4, 4,    P2C)    # Holz-Streifen
        pyxel.rect(x,      y+oh-3, 3, 3, GRAY)      # Bein links
        pyxel.rect(x+ow-3, y+oh-3, 3, 3, GRAY)      # Bein rechts

    elif typ == "pigeon":
        # Taube (Central Park)
        pyxel.rect(x+2, y+2, ow-4, oh-4, GRAY)      # Körper
        pyxel.rect(x+1, y+3, ow-2, oh-5, GRAY)
        pyxel.rect(x+3, y,   4,    3,    GRAY)       # Kopf
        pyxel.pset(x+4, y+1, BLACK)                  # Auge
        pyxel.pset(x+3, y+3, SAND)                   # Schnabel
        # Flügel
        pyxel.line(x, y+4, x+3, y+3, WHITE)
        pyxel.line(x+ow-1, y+4, x+ow-3, y+3, WHITE)
        # Beine
        pyxel.line(x+3, y+oh-4, x+2, y+oh, GRAY)
        pyxel.line(x+6, y+oh-4, x+7, y+oh, GRAY)

    elif typ == "taxi":
        # Gelbes NYC Taxi
        pyxel.rect(x,      y+5, ow, oh-5, YELLOW)   # Körper unten
        pyxel.rect(x+2,    y+1, ow-4, oh-2, YELLOW) # Dach
        pyxel.rect(x+4,    y+2, ow-8, oh-6, LBLUE)  # Windschutzscheibe
        pyxel.rect(x+1,    y+oh-4, ow-2, 1, BROWN)  # Trennlinie
        pyxel.rect(x,      y+oh-3, 5, 3, BLACK)      # Rad L
        pyxel.rect(x+ow-5, y+oh-3, 5, 3, BLACK)      # Rad R
        pyxel.rect(x+1,    y+oh-2, 3, 2, GRAY)
        pyxel.rect(x+ow-4, y+oh-2, 3, 2, GRAY)
        pyxel.rect(x+ow//2-3, y-2, 7, 3, P1C)        # TAXI-Schild rot

    elif typ == "pizza":
        # Pizza-Slice (typisch NY)
        pyxel.tri(x,      y+oh, x+ow, y+oh, x+ow//2, y, P2C)   # Teig
        pyxel.tri(x+1,    y+oh-1, x+ow-1, y+oh-1, x+ow//2, y+2, P1C)  # Tomate
        # Käse-Flecken
        pyxel.pset(x+ow//2-2, y+oh-4, YELLOW)
        pyxel.pset(x+ow//2+2, y+oh-6, YELLOW)
        pyxel.pset(x+ow//2,   y+oh-3, YELLOW)
        # Rand
        pyxel.line(x, y+oh, x+ow, y+oh, SAND)

    elif typ == "burger":
        # Burger
        # Brötchen oben
        pyxel.rect(x+1, y,    ow-2, 4, P2C)
        pyxel.rect(x,   y+2,  ow,   3, P2C)
        # Salat
        pyxel.rect(x,   y+5,  ow,   2, MINT)
        # Fleisch
        pyxel.rect(x,   y+7,  ow,   3, BROWN)
        # Käse
        pyxel.rect(x,   y+10, ow,   2, YELLOW)
        # Brötchen unten
        pyxel.rect(x+1, y+12, ow-2, 2, P2C)

    elif typ == "hydrant":
        pyxel.rect(x+2, y+4, ow-4, oh-4, P1C)
        pyxel.rect(x+1, y+2, ow-2, 4, P1C)
        pyxel.rect(x+2, y,   ow-4, 4, P1C)
        pyxel.rect(x,   y+5, 2, 5, P1C)
        pyxel.rect(x+ow-2, y+5, 2, 5, P1C)
        pyxel.pset(x+ow//2, y+2, WHITE)

    elif typ == "trash":
        pyxel.rect(x+1, y+3, ow-2, oh-3, GRAY)
        pyxel.rect(x,   y+1, ow,   3,    BLACK)
        pyxel.line(x+3, y+5, x+3, y+oh-1, BLUE)
        pyxel.line(x+6, y+5, x+6, y+oh-1, BLUE)

    elif typ == "torch":
        pyxel.rect(x+1, y+5, 3, oh-5, SAND)
        pyxel.tri(x-1, y+6, x+5, y+6, x+2, y, YELLOW)
        pyxel.tri(x,   y+5, x+4, y+5, x+2, y+1, P2C)


# ============================================================
#  HINTERGRUENDE
# ============================================================

def draw_bg_paris(sx):
    # Fröhlicher Pariser Morgen: warmer heller Himmel
    pyxel.cls(LBLUE)

    # Sonne mit Strahlen (warm, wie auf Eiffelturm-Sonnenuntergangsfoto)
    pyxel.circ(30, 20, 12, YELLOW)
    pyxel.circ(30, 20, 8,  WHITE)
    # Sonnenstrahlen
    for ang_x, ang_y in [(-14,0),(14,0),(0,-14),(0,14),
                          (-10,-10),(10,-10),(-10,10),(10,10)]:
        pyxel.line(30+ang_x, 20+ang_y, 30+ang_x*2, 20+ang_y*2, YELLOW)

    # Wolken (fluffig weiß)
    for i in range(0, 4000, 280):
        cx = int(i - sx * 0.13) % (W + 140) - 70
        pyxel.rect(cx,    15, 48, 10, WHITE)
        pyxel.rect(cx+10, 10, 32, 11, WHITE)
        pyxel.rect(cx+26,  7, 22, 10, WHITE)
        pyxel.rect(cx+42, 13, 24, 9,  WHITE)

    # Bäume (Champs-Élysées / Parc)
    for i in range(0, 4000, 55):
        tx = int(i - sx * 0.45)
        if -10 < tx < W + 10:
            if (i // 55) % 3 == 0:  # nur jeden 3. Baum
                pyxel.rect(tx+4, H-16-22, 4, 15, BROWN)
                pyxel.rect(tx,   H-16-32, 12, 12, TEAL)
                pyxel.rect(tx+1, H-16-36, 10,  8, MINT)

    # ── BUNTE FASSADEN (Rue Crémieux + Montmartre) ────────
    facade_cols = [YELLOW, LBLUE, PINK, MINT, P2C, P1C, SAND, WHITE]
    trim_cols   = [BROWN,  BLUE,  P1C,  TEAL, BROWN, BROWN, GRAY, GRAY]

    for i in range(0, 4000, 30):
        bx = int(i - sx * 0.50)
        bh = 34 + (i % 24)
        bw = 28
        if -bw < bx < W + bw:
            fi  = (i // 30) % len(facade_cols)
            fc  = facade_cols[fi]
            tc  = trim_cols[fi]
            # Fassade
            pyxel.rect(bx, H-16-bh, bw, bh, fc)
            # Weiße Trennlinie zwischen Häusern
            pyxel.line(bx-1, H-16-bh, bx-1, H-16, WHITE)
            pyxel.line(bx+bw, H-16-bh, bx+bw, H-16, WHITE)
            # Dachgesims
            pyxel.rect(bx, H-16-bh, bw, 2, WHITE)
            # Mansarddach (grau)
            pyxel.rect(bx+2, H-18-bh, bw-4, 4, GRAY)
            # Schornstein
            pyxel.rect(bx+8, H-22-bh, 3, 5, GRAY)
            # Fenster (2 Reihen, weiße Rahmen)
            for wy in range(5, bh-8, 11):
                for wc in range(3, bw-3, 11):
                    # Fensterrahmen
                    pyxel.rect(bx+wc,   H-16-bh+wy,   7, 9, WHITE)
                    # Innen (blau = Himmelspiegelung)
                    pyxel.rect(bx+wc+1, H-16-bh+wy+1, 5, 7, LBLUE)
                    # Fensterläden (Farbe variiert)
                    pyxel.rect(bx+wc-2, H-16-bh+wy+1, 2, 7, tc)
                    pyxel.rect(bx+wc+7, H-16-bh+wy+1, 2, 7, tc)
            # Café-Markise (rotes Dach) bei jedem 4. Haus
            if (i // 30) % 4 == 0:
                pyxel.rect(bx-2, H-16-8, bw+4, 4, P1C)
                pyxel.line(bx-2, H-16-8, bx+bw+2, H-16-8, BROWN)
            # Blumentöpfe am Balkon
            if (i // 30) % 2 == 1:
                pyxel.rect(bx+3,  H-16-bh+bh-15, 5, 4, BROWN)
                pyxel.rect(bx+2,  H-16-bh+bh-18, 7, 4, P1C)
                pyxel.rect(bx+17, H-16-bh+bh-15, 5, 4, BROWN)
                pyxel.rect(bx+16, H-16-bh+bh-18, 7, 4, MINT)

    # ── SACRÉ-CŒUR (weiß, Kuppeln) ────────────────────────
    scx = int(1350 - sx * 0.36)
    if -90 < scx < W + 90:
        # Hügel
        pyxel.tri(scx-50, H-16, scx+50, H-16, scx, H-16-25, MINT)
        # Terrassenmauer
        pyxel.rect(scx-42, H-16-22, 84, 8, WHITE)
        pyxel.rect(scx-40, H-16-24, 80, 4, GRAY)
        # Hauptgebäude
        pyxel.rect(scx-30, H-16-55, 60, 35, WHITE)
        # Säulenreihe vorne
        for ci in range(-26, 27, 7):
            pyxel.rect(scx+ci, H-16-22, 3, 8, WHITE)
            pyxel.rect(scx+ci-1, H-16-23, 5, 2, GRAY)
        # Haupt-Kuppel (gestapelte Ringe)
        for r in range(0, 18, 2):
            ww = 18 - r
            pyxel.rect(scx-ww, H-16-55-r*2, ww*2, 3, WHITE)
        # Kuppel-Spitze
        pyxel.rect(scx-3, H-16-91, 6, 8, WHITE)
        pyxel.rect(scx-1, H-16-97, 2, 8, GRAY)    # Kreuz
        pyxel.rect(scx-3, H-16-93, 6, 1, GRAY)
        # Seitentürmchen
        pyxel.rect(scx-30, H-16-55, 10, 14, WHITE)
        pyxel.rect(scx+20, H-16-55, 10, 14, WHITE)
        for r2 in range(0, 8, 2):
            ww2 = 6-r2
            pyxel.rect(scx-25-ww2//2, H-16-69-r2*2, ww2, 2, WHITE)
            pyxel.rect(scx+25-ww2//2, H-16-69-r2*2, ww2, 2, WHITE)

    # ── EIFFELTURM (gelbbraun, im Hintergrund) ────────────
    tx = int(700 - sx * 0.26)
    if -35 < tx < W + 35:
        # Beine
        pyxel.tri(tx-12, H-16-8,  tx-4, H-16-8, tx-3, H-16-42, P2C)
        pyxel.tri(tx+12, H-16-8,  tx+4, H-16-8, tx+3, H-16-42, P2C)
        # Etage 1
        pyxel.rect(tx-5, H-16-46, 10, 3, P2C)
        # Mittelteil
        pyxel.tri(tx-5, H-16-46, tx+5, H-16-46, tx-2, H-16-70, P2C)
        pyxel.tri(tx+5, H-16-46, tx-5, H-16-46, tx+2, H-16-70, P2C)
        # Etage 2
        pyxel.rect(tx-3, H-16-72, 6, 2, P2C)
        # Spitze
        pyxel.tri(tx-3, H-16-72, tx+3, H-16-72, tx, H-16-88, P2C)
        pyxel.rect(tx,   H-16-88, 1, 6, GRAY)
        pyxel.pset(tx, H-16-88, YELLOW)
        # Gitterlinien
        for yy in range(H-16-85, H-16-46, 6):
            pyxel.line(tx-2, yy, tx+2, yy, YELLOW)


def draw_bg_venice(sx):
    # Venedig: warmer Abendhimmel (blau mit warmem Licht)
    pyxel.cls(BLUE)

    # Mond
    pyxel.circ(W-30, 14, 10, YELLOW)
    pyxel.circ(W-25, 11,  8, BLUE)    # Halbmond

    # Sterne
    for sx2, sy2 in [(20,6),(48,4),(85,10),(122,3),(162,7),(200,5),
                     (232,9),(38,19),(100,17),(155,21),(210,14),(248,19)]:
        pyxel.pset(sx2, sy2, WHITE)

    # Venezianische Palazzi (Ziegel-rot + warme Sand-Töne)
    pal_cols = [BROWN, SAND, P2C, BROWN, SAND]
    for i in range(0, 4000, 54):
        bx = int(i - sx * 0.47)
        bh = 32 + (i % 40)
        bw = 20 + (i % 12)
        if -bw < bx < W + bw:
            pc = pal_cols[(i // 54) % len(pal_cols)]
            pyxel.rect(bx, H-16-bh, bw, bh, pc)
            # Dachgesims
            pyxel.rect(bx-1, H-16-bh, bw+2, 2, SAND)
            # Venezianische Bogenfenster
            for wy in range(5, bh-6, 12):
                fw = bw // 2 - 2
                for fx2 in [bx+2, bx+bw//2+1]:
                    pyxel.rect(fx2, H-16-bh+wy+3, fw, 5, NIGHT)
                    # Spitzbogen
                    pyxel.tri(fx2, H-16-bh+wy+3,
                              fx2+fw, H-16-bh+wy+3,
                              fx2+fw//2, H-16-bh+wy, NIGHT)
                    pyxel.pset(fx2+fw//2, H-16-bh+wy+2, YELLOW)

    # Wasser mit Spiegelung
    for wy in range(H-28, H-16):
        col = PERIWI if wy % 2 == 0 else LBLUE
        pyxel.line(0, wy, W, wy, col)
    for i2 in range(0, W, 20):
        xi = int((i2 + sx*0.4) % W)
        pyxel.line(xi, H-24, xi+10, H-26, LBLUE)

    # ── RIALTO-BRÜCKE (weißer Bogen) ──────────────────────
    rx = int(700 - sx * 0.44)
    if -85 < rx < W + 85:
        # Hauptbogen
        for boff in range(-40, 41):
            ay = int(H-44 - 20*(1.0-(boff/40.0)**2))
            pyxel.line(rx+boff, ay, rx+boff, ay+2, WHITE)
        pyxel.rect(rx-40, H-44, 80, 5, WHITE)
        pyxel.rect(rx-40, H-39, 80, 3, GRAY)
        # Geländer
        pyxel.rect(rx-40, H-49, 80, 3, WHITE)
        for px2 in range(rx-38, rx+38, 5):
            pyxel.rect(px2, H-54, 2, 6, WHITE)
        # Gebäude auf Brücke
        pyxel.rect(rx-20, H-62, 40, 14, SAND)
        pyxel.rect(rx-18, H-64, 36,  3, WHITE)
        # Stützbögen
        pyxel.tri(rx-40, H-44, rx-26, H-44, rx-40, H-32, WHITE)
        pyxel.tri(rx+40, H-44, rx+26, H-44, rx+40, H-32, WHITE)

    # ── CAMPANILE (roter Ziegelturm) ──────────────────────
    cpx = int(1300 - sx * 0.42)
    if -22 < cpx < W + 22:
        pyxel.rect(cpx-7, H-16-82, 14, 66, BROWN)
        for by2 in range(H-82, H-16, 5):
            pyxel.line(cpx-7, by2, cpx+7, by2, P2C)
        pyxel.rect(cpx-9, H-16-82, 18, 13, WHITE)
        pyxel.rect(cpx-9, H-16-69, 18,  2, GRAY)
        pyxel.rect(cpx-6, H-16-80,  5,  9, NIGHT)
        pyxel.rect(cpx+1, H-16-80,  5,  9, NIGHT)
        pyxel.tri(cpx-9, H-16-82, cpx+9, H-16-82, cpx, H-16-108, TEAL)
        pyxel.rect(cpx-1, H-16-110, 2, 4, GRAY)
        pyxel.pset(cpx, H-16-110, YELLOW)

    # Gondeln im Hintergrund
    for gi in range(200, 2000, 350):
        gx = int(gi - sx * 0.3) % W
        if 0 < gx < W - 20:
            pyxel.rect(gx, H-24, 20, 5, BLACK)
            pyxel.tri(gx, H-24, gx+3, H-24, gx+1, H-27, GRAY)


def draw_bg_newyork(sx):
    # Zone bestimmen anhand der Kamera-Position
    world_mid = sx + W // 2
    zone = ny_zone(world_mid)
    fc = pyxel.frame_count

    if zone == 0:
        # ── ZONE 0: CENTRAL PARK (Taghimmel, grün) ──────────
        pyxel.cls(LBLUE)

        # Wolken
        for i in range(0, 4000, 240):
            cx = int(i - sx*0.14) % (W+120) - 60
            pyxel.rect(cx,    16, 42, 9, WHITE)
            pyxel.rect(cx+10, 11, 28, 10, WHITE)
            pyxel.rect(cx+26,  8, 18, 9, WHITE)

        # Grüne Wiesen (2 Schichten Grün)
        pyxel.rect(0, H-16-14, W, 14, TEAL)
        pyxel.rect(0, H-16-8,  W,  8, MINT)

        # Bäume (Central Park – dicht)
        for i in range(0, 4000, 32):
            tx = int(i - sx * 0.5)
            th = 20 + (i % 18)
            if -12 < tx < W + 12:
                pyxel.rect(tx+4, H-16-th-2, 4, th+2, BROWN)
                pyxel.rect(tx,   H-16-th-14, 12, 14, TEAL)
                pyxel.rect(tx+1, H-16-th-18, 10, 10, MINT)
                pyxel.rect(tx+3, H-16-th-22,  6,  6, TEAL)

        # Parkweg
        pyxel.rect(0, H-16-4, W, 4, SAND)
        for pi in range(0, W, 20):
            pyxel.line(pi, H-16-4, pi, H-16, GRAY)

        # See (blauer Fleck im Hintergrund)
        lake_x = int(600 - sx * 0.3)
        if -60 < lake_x < W + 20:
            pyxel.rect(lake_x, H-16-20, 80, 8, PERIWI)
            pyxel.rect(lake_x+4, H-16-18, 72, 5, LBLUE)

        # Skyline dahinter (klein, hell)
        for i in range(0, 4000, 40):
            bx2 = int(i - sx * 0.22)
            bh2 = 18 + (i % 22)
            bw2 = 10 + (i % 8)
            if -bw2 < bx2 < W + bw2:
                pyxel.rect(bx2, H-16-14-bh2, bw2, bh2, GRAY)
                for wf in range(3, bh2-3, 5):
                    for wg in range(2, bw2-2, 4):
                        pyxel.pset(bx2+wg, H-16-14-bh2+wf, LBLUE)

    elif zone == 1:
        # ── ZONE 1: TIMES SQUARE (Nacht, bunt) ──────────────
        pyxel.cls(NIGHT)

        # Wolkenkratzer
        for i in range(0, 4000, 42):
            bx = int(i - sx * 0.50)
            bh = 35 + (i % 60)
            bw = 10 + (i % 14)
            if -bw < bx < W + bw:
                pyxel.rect(bx, H-16-bh, bw, bh, BLACK)
                for wy in range(3, bh-3, 5):
                    for wx in range(2, bw-2, 4):
                        if (i+wy+wx) % 4 != 0:
                            pyxel.pset(bx+wx, H-16-bh+wy, YELLOW)
                pyxel.rect(bx+bw//2-1, H-16-bh-4, 2, 4, GRAY)

        # Times Square Reklamen (bunt, animiert mit frame_count)
        fc = pyxel.frame_count
        signs = [
            (150,  38, 14, 20), (200,  30, 14, 24), (240,  36, 14, 18),
            (600,  35, 14, 22), (650,  28, 14, 26), (700,  33, 14, 20),
            (1050, 36, 14, 22), (1100, 30, 14, 28), (1150, 38, 14, 18),
            (1500, 34, 14, 22), (1550, 28, 14, 24),
        ]
        scols = [P1C, YELLOW, MINT, P2C, PURPLE, PINK, LBLUE, P1C, YELLOW]
        for si, (wx, wy, ww, wh) in enumerate(signs):
            bsx = int(wx - sx * 0.5)
            if -ww < bsx < W + ww:
                c1 = scols[si % len(scols)]
                c2 = scols[(si+2) % len(scols)]
                # Alterniere Farbe mit frame_count
                c = c1 if (fc // 30 + si) % 2 == 0 else c2
                pyxel.rect(bsx, wy, ww, wh, c)
                pyxel.rectb(bsx, wy, ww, wh, WHITE)

        # Empire State Building
        etx = int(1050 - sx * 0.48)
        if -55 < etx < W + 55:
            pyxel.rect(etx-18, H-16-55, 36, 55, SAND)
            pyxel.rect(etx-13, H-16-72, 26, 20, SAND)
            pyxel.rect(etx-9,  H-16-85, 18, 16, SAND)
            pyxel.rect(etx-5,  H-16-96, 10, 13, SAND)
            pyxel.rect(etx-2,  H-16-108, 4, 14, GRAY)
            pyxel.rect(etx-1,  H-16-118, 2, 12, GRAY)
            pyxel.rect(etx,    H-16-126, 1, 10, GRAY)
            for wy in range(4, 52, 6):
                for wxx in range(-16, 16, 4):
                    pyxel.pset(etx+wxx, H-16-wy, YELLOW)
            col_esb = [P1C, MINT, YELLOW, P2C][(fc // 60) % 4]
            pyxel.pset(etx, H-16-126, col_esb)
            pyxel.pset(etx, H-16-124, col_esb)

    else:
        # ── ZONE 2: SKYLINE / HUDSON (Nacht, Wasser) ────────
        pyxel.cls(NIGHT)

        # Sterne
        for stx, sty in [(15,5),(40,3),(70,8),(100,4),(135,6),(165,3),
                         (195,7),(225,4),(248,9),(55,14),(120,17),(180,12)]:
            pyxel.pset(stx, sty, WHITE)

        # Skyline-Spiegelung im Wasser
        pyxel.rect(0, H-16-20, W, 20, NIGHT)
        for i in range(0, W, 2):
            pyxel.pset(i, H-16-18+((i*3+fc)%8)//4, YELLOW)

        # Wolkenkratzer mit bunten Lichtern
        for i in range(0, 4000, 38):
            bx = int(i - sx * 0.50)
            bh = 40 + (i % 68)
            bw = 10 + (i % 16)
            if -bw < bx < W + bw:
                pyxel.rect(bx, H-16-bh, bw, bh, BLACK)
                for wy in range(3, bh-3, 5):
                    for wx in range(2, bw-2, 4):
                        if (i+wy+wx) % 5 != 0:
                            pyxel.pset(bx+wx, H-16-bh+wy, YELLOW)
                pyxel.rect(bx+bw//2-1, H-16-bh-5, 2, 5, GRAY)

        # Freiheitsstatue
        stx = int(1780 - sx * 0.45)
        if -35 < stx < W + 35:
            pyxel.rect(stx-10, H-16-20, 20, 20, SAND)
            pyxel.rect(stx-8,  H-16-26, 16,  8, BROWN)
            pyxel.rect(stx-5,  H-16-46, 10, 22, TEAL)
            pyxel.rect(stx-7,  H-16-38, 14, 14, TEAL)
            pyxel.line(stx-5,  H-16-42, stx-5, H-16-28, MINT)
            pyxel.line(stx+3,  H-16-42, stx+3, H-16-28, MINT)
            pyxel.rect(stx-4,  H-16-54, 8, 10, TEAL)
            for ci in range(-3, 4, 2):
                pyxel.rect(stx+ci, H-16-60, 1, 6, TEAL)
            pyxel.rect(stx+5,  H-16-54, 3, 14, TEAL)
            pyxel.rect(stx+6,  H-16-64,  2, 12, SAND)
            pyxel.tri(stx+5, H-16-64, stx+9, H-16-64, stx+7, H-16-70, YELLOW)

        # Spiegelung im Wasser
        for wli in range(0, W, 22):
            xi = int((wli + sx*0.35) % W)
            pyxel.line(xi, H-22, xi+12, H-24, PERIWI)


# ============================================================
#  SPIELER
# ============================================================
class Player:
    def __init__(self, x, y, col, keys):
        self.sx, self.sy = x, y
        self.x = float(x); self.y = float(y)
        self.vx = 0.0; self.vy = 0.0
        self.w = 8; self.h = 11
        self.col = col; self.keys = keys
        self.on_gnd = False
        self.alive = True; self.done = False
        self.finish_f = 0; self.score = 0
        self.face_r = True; self.af = 0; self.at = 0

    def reset(self):
        self.x = float(self.sx); self.y = float(self.sy)
        self.vx = self.vy = 0.0
        self.on_gnd = False
        self.alive = True; self.done = False
        self.finish_f = 0
        self.face_r = True; self.af = self.at = 0

    def update(self, plats, traps, goal_x, cam_x):
        if not self.alive or self.done: return
        lk, rk, jk = self.keys
        if pyxel.btn(lk):
            self.vx = -SPEED; self.face_r = False
        elif pyxel.btn(rk):
            self.vx =  SPEED; self.face_r = True
        else:
            self.vx *= 0.72
        if pyxel.btnp(jk) and self.on_gnd:
            self.vy = JUMP
        self.vy = min(self.vy + GRAV, 9)
        self.x += self.vx
        self.x = max(cam_x, min(cam_x + W - self.w, self.x))
        self.y += self.vy
        self.on_gnd = False
        if self.y + self.h >= H - 16:
            self.y = H - 16 - self.h
            self.vy = 0; self.on_gnd = True
        for (px, py, pw, ph) in plats:
            if (self.x + self.w > px and self.x < px + pw and
                    self.vy >= 0 and
                    self.y + self.h >= py and
                    self.y + self.h <= py + ph + abs(self.vy) + 2):
                self.y = py - self.h
                self.vy = 0; self.on_gnd = True
        for (tx, ty, tw, th) in traps:
            if tw == 0: continue
            if (self.x + self.w > tx and self.x < tx + tw and
                    self.y + self.h >= ty):
                self.alive = False; return
        if self.x >= goal_x:
            self.done = True
            self.finish_f = pyxel.frame_count
        self.at += 1
        if abs(self.vx) > 0.4 and self.at % 7 == 0:
            self.af = (self.af + 1) % 4

    def draw(self, cam_x):
        if not self.alive: return
        x = int(self.x - cam_x); y = int(self.y)
        c = self.col; d = max(c-1, 0)

        # ── Körper ──
        pyxel.rect(x, y+4, self.w, self.h-4, c)
        # ── Kopf ──
        pyxel.rect(x+1, y, 6, 6, c)
        pyxel.rect(x+2, y+1, 4, 4, SAND)
        ex = x+5 if self.face_r else x+2
        pyxel.pset(ex, y+2, BLACK)

        # ── Beine mit 4-Frame-Laufzyklus + Sprungpose ──
        if not self.on_gnd:
            # Sprung: Beine angewinkelt nach oben
            if self.vy < 0:
                # Aufwärts: Beine nach oben gezogen
                pyxel.rect(x+1, y+11, 2, 2, d)   # Bein L kurz hoch
                pyxel.rect(x+5, y+11, 2, 2, d)   # Bein R kurz hoch
                pyxel.line(x+1, y+12, x,   y+10, d)  # Winkel L
                pyxel.line(x+6, y+12, x+7, y+10, d)  # Winkel R
            else:
                # Abwärts: Beine gestreckt nach unten
                pyxel.rect(x+1, y+11, 2, 4, d)
                pyxel.rect(x+5, y+11, 2, 4, d)
                pyxel.line(x+1, y+14, x,   y+16, d)  # Füße nach vorne
                pyxel.line(x+6, y+14, x+7, y+16, d)
        elif abs(self.vx) > 0.4:
            # Laufen: 4-Frame Zyklus
            f = self.af % 4
            if f == 0:
                # Schritt 1: L vorne, R hinten
                pyxel.line(x+2, y+11, x,   y+14, d)   # L Oberschenkel
                pyxel.line(x,   y+14, x+1, y+16, d)   # L Unterschenkel
                pyxel.line(x+5, y+11, x+6, y+14, d)   # R Oberschenkel
                pyxel.line(x+6, y+14, x+7, y+16, d)   # R Unterschenkel
            elif f == 1:
                # Schritt 2: beide Beine zusammen (Mittelpunkt)
                pyxel.line(x+2, y+11, x+2, y+14, d)
                pyxel.line(x+2, y+14, x+1, y+16, d)
                pyxel.line(x+5, y+11, x+5, y+14, d)
                pyxel.line(x+5, y+14, x+6, y+16, d)
            elif f == 2:
                # Schritt 3: R vorne, L hinten
                pyxel.line(x+2, y+11, x+1, y+14, d)
                pyxel.line(x+1, y+14, x,   y+16, d)
                pyxel.line(x+5, y+11, x+7, y+14, d)
                pyxel.line(x+7, y+14, x+8, y+16, d)
            else:
                # Schritt 4: beide zusammen
                pyxel.line(x+2, y+11, x+2, y+14, d)
                pyxel.line(x+2, y+14, x+1, y+16, d)
                pyxel.line(x+5, y+11, x+5, y+14, d)
                pyxel.line(x+5, y+14, x+6, y+16, d)
        else:
            # Stehen: gerade Beine
            pyxel.rect(x+1, y+11, 2, 4, c)
            pyxel.rect(x+5, y+11, 2, 4, c)

        if self.done:
            pyxel.text(x-4, y-10, "ZIEL!", YELLOW)


# ============================================================
#  MUSIK-SETUP  (Pyxel Sounds + Music)
#  Sounds 0-15 frei nutzbar, Music 0-7
#  Paris:    Music 0  (fröhlich, Akkordeon-Stil)
#  Venedig:  Music 1  (romantisch, langsam)
#  New York: Music 2  (jazzig, rhythmisch)
# ============================================================

# ============================================================
#  HAUPT-SPIEL
# ============================================================
class Game:
    def __init__(self):
        pyxel.init(W, H, title="City Quest", fps=FPS)
        self.state        = "menu"
        self.cur_level    = 0
        self.cam_x        = 0.0
        self.timer        = 0
        self.winner       = None
        self.p1 = Player(20, H-27, P1C,
                         (pyxel.KEY_A, pyxel.KEY_D, pyxel.KEY_W))
        self.p2 = Player(40, H-27, P2C,
                         (pyxel.KEY_LEFT, pyxel.KEY_RIGHT, pyxel.KEY_UP))
        pyxel.run(self.update, self.draw)

    def level(self): return LEVELS[self.cur_level]

    def start_round(self):
        self.cam_x = 0.0; self.timer = 0; self.winner = None
        self.p1.reset(); self.p2.reset()
        self.state = "playing"

    def update(self):
        if self.state == "menu":
            if pyxel.btnp(pyxel.KEY_RETURN) or pyxel.btnp(pyxel.KEY_SPACE):
                self.cur_level = 0
                self.p1.score = self.p2.score = 0
                self.start_round()

        elif self.state == "playing":
            self.timer += 1
            lv = self.level()
            self.p1.update(lv["platforms"], lv["traps"], lv["goal_x"], self.cam_x)
            self.p2.update(lv["platforms"], lv["traps"], lv["goal_x"], self.cam_x)
            lead = max(self.p1.x if self.p1.alive else 0,
                       self.p2.x if self.p2.alive else 0)
            tgt = lead - W * 0.38
            if tgt > self.cam_x:
                self.cam_x += (tgt - self.cam_x) * 0.09
            self.cam_x = max(0.0, self.cam_x)
            p1d = not self.p1.alive or self.p1.done
            p2d = not self.p2.alive or self.p2.done
            if p1d and p2d:
                if self.p1.done and self.p2.done:
                    w = 1 if self.p1.finish_f <= self.p2.finish_f else 2
                elif self.p1.done:  w = 1
                elif self.p2.done:  w = 2
                else:               w = 0
                self.winner = w
                if w == 1:   self.p1.score += 1
                elif w == 2: self.p2.score += 1
                self.state = "roundover"

        elif self.state == "roundover":
            if pyxel.btnp(pyxel.KEY_RETURN) or pyxel.btnp(pyxel.KEY_SPACE):
                self.cur_level = (self.cur_level + 1) % len(LEVELS)
                self.start_round()
            if pyxel.btnp(pyxel.KEY_ESCAPE):
                self.state = "menu"
                self.p1.score = self.p2.score = 0

    def draw(self):
        if self.state == "menu": self._draw_menu()
        else:
            self._draw_world()
            self._draw_ui()
            if self.state == "roundover": self._draw_roundover()

    def _draw_world(self):
        lv = self.level(); sx = self.cam_x; nm = lv["name"]
        if   nm == "Paris":   draw_bg_paris(sx)
        elif nm == "Venedig": draw_bg_venice(sx)
        else:                 draw_bg_newyork(sx)

        gnd_y = H - 16

        # Boden (NY: zonabhängig)
        if nm == "New York":
            zone = ny_zone(sx + W//2)
            gnd_c = TEAL if zone == 0 else GRAY
            pyxel.rect(0, gnd_y, W, 16, gnd_c)
            if zone == 0:
                # Parkweg
                pyxel.rect(0, gnd_y, W, 4, SAND)
                for i in range(0, W, 18): pyxel.line(i, gnd_y, i, H, BROWN)
            else:
                for i in range(0, W, 14): pyxel.line(i, gnd_y, i, H, NIGHT)
                # Straßenmarkierungen
                for i in range(0, W, 40):
                    pyxel.rect(i, gnd_y+6, 18, 2, YELLOW)
        elif nm == "Venedig":
            pyxel.rect(0, gnd_y, W, 16, PERIWI)
            pyxel.line(0, gnd_y, W, gnd_y, LBLUE)
            for i in range(0, W, 22):
                xi = int((i + sx*0.3) % W)
                pyxel.line(xi, gnd_y+5, xi+10, gnd_y+3, LBLUE)
        else:
            # Paris: buntes Pflaster
            pyxel.rect(0, gnd_y, W, 16, GRAY)
            pyxel.line(0, gnd_y, W, gnd_y, SAND)
            for i in range(0, W, 16): pyxel.line(i, gnd_y, i, H, TEAL)
            for j in range(gnd_y+4, H, 8): pyxel.line(0, j, W, j, TEAL)

        # Fallen
        for (tx, ty, tw, th) in lv["traps"]:
            if tw == 0: continue
            bx = int(tx - sx)
            if -tw < bx < W + tw:
                sky_c = lv["sky"]
                if nm == "New York":
                    zone = ny_zone(tx)
                    sky_c = LBLUE if zone == 0 else NIGHT
                pyxel.rect(bx, ty, tw, th+6, sky_c)
                if nm == "Venedig":
                    pyxel.rect(bx, ty+4, tw, th, PERIWI)
                    pyxel.line(bx+2, ty+6, bx+tw-2, ty+6, LBLUE)
                pyxel.line(bx, ty, bx, ty+th, BLACK)
                pyxel.line(bx+tw, ty, bx+tw, ty+th, BLACK)

        # Plattformen
        for (px, py, pw, ph) in lv["platforms"]:
            bx = int(px - sx)
            if -pw < bx < W + pw:
                if nm == "New York":
                    zone = ny_zone(px)
                    plt_c = TEAL if zone == 0 else GRAY
                    top_c = MINT if zone == 0 else BLUE
                else:
                    plt_c = GRAY
                    top_c = LBLUE if nm=="Paris" else PERIWI
                pyxel.rect(bx, py, pw, ph, plt_c)
                pyxel.rect(bx, py, pw, 2, top_c)
                pyxel.rect(bx, py+2, pw, 1, WHITE)

        # Hindernisse
        for (ox, oy, ow, oh, typ) in lv["obstacles"]:
            draw_obstacle(ox, oy, ow, oh, typ, sx)

        # Ziel
        gx = int(lv["goal_x"] - sx)
        if -20 < gx < W + 20:
            pyxel.rect(gx, H-72, 2, 56, BROWN)
            pyxel.tri(gx+2, H-72, gx+2, H-58, gx+18, H-65, P1C)
            pyxel.text(gx-6, H-82, "ZIEL", YELLOW)

        self.p1.draw(sx); self.p2.draw(sx)

    def _draw_ui(self):
        pyxel.rect(0, 0, W, 13, BLACK)
        pyxel.line(0, 13, W, 13, GRAY)
        pyxel.rect(2, 2, 5, 8, P1C)
        s1 = "TOT" if not self.p1.alive else ("ZIEL!" if self.p1.done else f"{self.p1.score} Globen")
        pyxel.text(9, 3, f"P1:{s1}", WHITE)
        pyxel.rect(W-40, 2, 5, 8, P2C)
        s2 = "TOT" if not self.p2.alive else ("ZIEL!" if self.p2.done else f"{self.p2.score} Globen")
        pyxel.text(W-34, 3, f"P2:{s2}", WHITE)
        nm = self.level()["name"]
        # Zonenname für NY
        if nm == "New York":
            zone_names = ["Central Park", "Times Square", "Skyline"]
            zone = ny_zone(self.cam_x + W//2)
            nm = zone_names[zone]
        pyxel.text(W//2 - len(nm)*2, 3, nm, YELLOW)
        secs = self.timer // FPS
        pyxel.text(W//2+24, 3, f"{secs:03d}s", MINT)
        lnum = f"Lvl {self.cur_level+1}/3"
        pyxel.text(W//2 - len(lnum)*2, H-8, lnum, GRAY)
        if self.timer < FPS*4:
            pyxel.text(2, H-8, "P1:WASD", P1C)
            pyxel.text(W-52, H-8, "P2:PFEILE", P2C)

    def _draw_menu(self):
        pyxel.cls(NIGHT)
        pyxel.rect(W//2-38, 8, 76, 16, BLACK)
        pyxel.rectb(W//2-38, 8, 76, 16, YELLOW)
        pyxel.text(W//2-26, 14, "CITY QUEST", YELLOW)
        pyxel.text(W//2-34, 26, "Das Stadtrennen!", WHITE)
        pyxel.line(22, 34, W-22, 34, GRAY)
        pyxel.text(10, 41, "3 Stadte, 3 Abenteuer:", MINT)
        pyxel.text(14, 50, "1. Paris   - Gassen, Macarons & Sacre-Coeur", P1C)
        pyxel.text(14, 58, "2. Venedig - Gondeln, Masken & Karneval",      P2C)
        pyxel.text(14, 66, "3. New York - Park / Times Sq / Skyline",      YELLOW)
        pyxel.line(22, 75, W-22, 75, GRAY)
        pyxel.rect(10, 81, 5, 8, P1C)
        pyxel.text(18, 83, "P1: A/D laufen    W = springen", WHITE)
        pyxel.rect(10, 93, 5, 8, P2C)
        pyxel.text(18, 95, "P2: Pfeile + Hoch = springen", WHITE)
        pyxel.line(22, 104, W-22, 104, GRAY)
        pyxel.text(14, 109, "Zuerst im Ziel: +1 Globus!", WHITE)
        pyxel.text(14, 118, "Locher & Wasser = sofort raus!", P1C)
        if (pyxel.frame_count // 22) % 2 == 0:
            pyxel.rect(W//2-46, H-16, 92, 10, BLACK)
            pyxel.text(W//2-44, H-14, "ENTER / SPACE = STARTEN", YELLOW)

    def _draw_roundover(self):
        for y in range(36, 112, 2):
            pyxel.line(0, y, W, y, BLACK)
        pyxel.rect(22, 38, W-44, 70, BLACK)
        pyxel.rectb(22, 38, W-44, 70, YELLOW)
        if self.winner == 0:
            pyxel.text(W//2-38, 52, "UNENTSCHIEDEN!", WHITE)
        elif self.winner == 1:
            pyxel.text(W//2-28, 48, "SPIELER 1", P1C)
            pyxel.text(W//2-18, 58, "GEWINNT!", YELLOW)
            pyxel.circ(W//2, 77, 8, TEAL)
            pyxel.circb(W//2, 77, 8, YELLOW)
            pyxel.line(W//2-8, 77, W//2+8, 77, YELLOW)
            pyxel.line(W//2, 69, W//2, 85, YELLOW)
        else:
            pyxel.text(W//2-28, 48, "SPIELER 2", P2C)
            pyxel.text(W//2-18, 58, "GEWINNT!", YELLOW)
            pyxel.circ(W//2, 77, 8, TEAL)
            pyxel.circb(W//2, 77, 8, YELLOW)
            pyxel.line(W//2-8, 77, W//2+8, 77, YELLOW)
            pyxel.line(W//2, 69, W//2, 85, YELLOW)
        next_nm = LEVELS[(self.cur_level+1) % len(LEVELS)]["name"]
        pyxel.text(W//2-32, 88, f"Weiter: {next_nm}!", MINT)
        pyxel.text(W//2-46, 98, "ENTER=Weiter   ESC=Menu", GRAY)
        pyxel.rect(0, H-14, W, 14, BLACK)
        pyxel.text(W//2-40, H-11,
                   f"P1:{self.p1.score} Globen   P2:{self.p2.score} Globen",
                   WHITE)


# ============================================================
Game()# Pyxel Studio

import pyxel