import pyxel
import random
import math

# ── CONSTANTS ──────────────────────────────────────────────
W, H      = 240, 180
RL, RR    = 35, 205
RW        = RR - RL
LW        = RW // 4
LANES     = [RL + LW*i + LW//2 for i in range(4)]
SPD       = 2           # base progress & road scroll per frame
RACE_LEN  = 5000        # progress to finish
BASE_Y    = H - 45      # screen Y when tied
SLIP_MAX  = 55          # frames for slipstream
MAX_VX    = 3.0         # max lateral speed
ACCEL     = 0.6         # lateral acceleration

# Die Ziellinie liegt FEST bei Y=16 auf dem Screen.
# Sie wird erst angezeigt wenn ein Spieler nahe genug ist (progress >= RACE_LEN).
# Gewinn: Auto-Y muss diese Linie erreichen UND progress >= RACE_LEN.
FIN_Y     = 16

# Palette
BG=1; RD=0; LN=13; C1=12; C2=8; YL=10; OR=9; PU=2; WH=7; TE=11


# ── SOUNDS ─────────────────────────────────────────────────
def _init_sounds():
    # Sound 0: Crash / Stun
    pyxel.sound(0).set(
        notes  = "c1 c1 r  r",
        tones  = "n  n  n  n",
        volumes= "7  5  3  0",
        effects= "n  n  n  n",
        speed  = 6
    )
    # Sound 1: Speed-Pad — aufsteigender Sweep
    pyxel.sound(1).set(
        notes  = "c3 e3 g3 c4",
        tones  = "s  s  s  s",
        volumes= "4  5  6  7",
        effects= "n  n  n  f",
        speed  = 5
    )
    # Sound 2: Windschatten-Boost aktiviert
    pyxel.sound(2).set(
        notes  = "g3 g3 b3 r",
        tones  = "p  p  p  p",
        volumes= "6  7  7  0",
        effects= "n  n  f  n",
        speed  = 4
    )


class App:
    def __init__(self):
        pyxel.init(W, H, title="NEON DASH", fps=30)
        _init_sounds()
        self.keys = [
            (pyxel.KEY_A,    pyxel.KEY_D,    pyxel.KEY_W),
            (pyxel.KEY_LEFT, pyxel.KEY_RIGHT, pyxel.KEY_UP),
        ]
        self._full_reset()
        pyxel.run(self.update, self.draw)

    def _full_reset(self):
        self.state    = "title"
        self.offset   = 0
        self.obs      = []      # [x, y, type, hit, vx]
        self.pads     = []      # [x, y, vx, anim]
        self.sparks   = []      # [x, y, vx, vy, life, col]
        self.ocd      = 25
        self.pcd      = 40
        self.ftimer   = 0
        self.winner   = None
        self.show_fin = False
        self.fin_y    = float(-40)  # Ziellinie: startet oben ausserhalb, scrollt rein
        self.cdown    = 3
        self.ctimer   = 35
        # idx: 0=x 1=y 2=vx 3=progress 4=stun 5=inv 6=boost 7=slip 8=srdy 9=alive 10=fin
        self.p = [
            [float(RL+RW*0.33), float(BASE_Y), 0.0, 0.0, 0, 0, 0, 0, False, True, False],
            [float(RL+RW*0.67), float(BASE_Y), 0.0, 0.0, 0, 0, 0, 0, False, True, False],
        ]

    # ── UPDATE ─────────────────────────────────────────────
    def update(self):
        st = self.state
        if st == "title":
            if pyxel.btnp(pyxel.KEY_SPACE) or pyxel.btnp(pyxel.KEY_RETURN):
                self._full_reset()
                self.state  = "countdown"
                self.cdown  = 3
                self.ctimer = 35
        elif st == "countdown":
            self.offset = (self.offset + SPD) % 30
            self.ctimer -= 1
            if self.ctimer <= 0:
                self.cdown -= 1
                self.ctimer = 35 if self.cdown > 0 else 20
                if self.cdown < 0:
                    self.state = "race"
        elif st == "race":
            self._update_race()
        elif st == "finish":
            self.ftimer += 1
            if pyxel.btnp(pyxel.KEY_SPACE) or pyxel.btnp(pyxel.KEY_RETURN):
                self.state = "title"

    # ── RACE ───────────────────────────────────────────────
    def _update_race(self):
        self.offset = (self.offset + SPD) % 30

        lead = max(self.p[0][3], self.p[1][3])

        # Ziellinie: einmal spawnen wenn 85% erreicht, dann runterscrollen
        if lead >= RACE_LEN * 0.85 and not self.show_fin:
            self.show_fin = True
            self.fin_y    = -20.0
        if self.show_fin:
            self.fin_y += SPD   # scrollt nach unten wie ein Hindernis

        d = min(lead / RACE_LEN, 1.0)

        # Spawn obstacles — NICHT mehr nach Ziellinie
        self.ocd -= 1
        if self.ocd <= 0 and not self.show_fin:
            used  = {round(o[0]) for o in self.obs if o[1] < 40}
            cands = [l for l in LANES if round(l) not in used] or list(LANES)
            obs_vx = random.choice([-1, 1]) * (0.5 + d * 1.5)
            self.obs.append([float(random.choice(cands)), -12.0,
                             random.choice([0, 0, 1, 2]), False, obs_vx])
            self.ocd = max(18, 28 - int(d*10)) + random.randint(-2, 2)

        # Spawn speed pads — NICHT mehr nach Ziellinie
        self.pcd -= 1
        if self.pcd <= 0 and not self.show_fin:
            lane  = random.randint(0, 3)
            drift = random.choice([-1, 1]) * (0.5 + d * 1.0)
            self.pads.append([float(LANES[lane]), -14.0, drift, 0])
            self.pcd = max(25, 42 - int(d*14))

        # Scroll & move objects
        for o in self.obs:
            o[1] += SPD
            o[0] += o[4]
            if o[0] < RL + 8:  o[0] = RL + 8;  o[4] = abs(o[4])
            if o[0] > RR - 8:  o[0] = RR - 8;  o[4] = -abs(o[4])

        for pad in self.pads:
            pad[1] += SPD
            pad[3]  = (pad[3] + 1) % 20
            pad[0] += pad[2]
            if pad[0] < RL + 8:  pad[0] = RL + 8;  pad[2] = abs(pad[2])
            if pad[0] > RR - 8:  pad[0] = RR - 8;  pad[2] = -abs(pad[2])

        self.obs  = [o   for o   in self.obs  if o[1]   < H + 20]
        self.pads = [pad for pad in self.pads if pad[1] < H + 20]

        # Sparks
        live = []
        for s in self.sparks:
            s[0] += s[2]; s[1] += s[3]; s[3] += 0.3; s[4] -= 1
            if s[4] > 0: live.append(s)
        self.sparks = live[:20]

        # Players
        for i in range(2):
            if self.p[i][9] and not self.p[i][10]:
                self._update_player(i)

        self._update_y()

        # ── ZIELLINIE-CHECK ────────────────────────────────
        # Gewinn wenn Auto die scrollende Ziellinie von unten erreicht
        if self.show_fin:
            for idx, p in enumerate(self.p):
                if not p[9] or p[10]: continue
                if p[1] <= self.fin_y + 12:
                    p[10] = True
                    if self.winner is None:
                        self.winner = idx
                        self.state  = "finish"
                        self.ftimer = 0
                        # Feuerwerk-Sparks beim Zieleinlauf
                        for _ in range(30):
                            self.sparks.append([
                                float(p[0]), float(p[1]),
                                random.uniform(-4.0, 4.0),
                                random.uniform(-5.0, -0.5),
                                random.randint(15, 30),
                                random.choice([C1, C2, YL, WH, TE])
                            ])

        # Einer fiel aus dem Screen → anderer gewinnt
        if self.winner is not None and self.state == "race":
            self.state  = "finish"
            self.ftimer = 0

    # ── PLAYER ─────────────────────────────────────────────
    def _update_player(self, i):
        p   = self.p[i]
        opp = self.p[1 - i]
        kl, kr, ksw = self.keys[i]

        # Lateral movement (original speeds from alte Version)
        if p[4] <= 0:
            if   pyxel.btn(kl): p[2] = max(p[2] - ACCEL, -MAX_VX)
            elif pyxel.btn(kr): p[2] = min(p[2] + ACCEL,  MAX_VX)
            else:               p[2] *= 0.72

        p[0] = max(RL + 6, min(RR - 6, p[0] + p[2]))

        # Progress
        if p[4] > 0:           # stunned
            p[4] -= 1
            p[2] *= 0.50
            p[3]  = max(0.0, p[3] - 3.0)
        elif p[6] > 0:         # boosting
            p[6] -= 1
            p[3] += SPD + 5
        else:
            p[3] += SPD

        if p[5] > 0:
            p[5] -= 1

        # Obstacle hit → Sound 0
        if p[5] <= 0:
            for o in self.obs:
                if not o[3] and abs(p[0]-o[0]) < 10 and abs(p[1]-o[1]) < 12:
                    o[3] = True
                    p[4] = 28; p[6] = 0; p[5] = 55
                    self._spark(p[0], p[1], OR, 5)
                    pyxel.play(0, 0, resume=False)
                    break

        # Speed pad → Sound 1
        j = 0
        while j < len(self.pads):
            pad = self.pads[j]
            if abs(p[0]-pad[0]) < 12 and abs(p[1]-pad[1]) < 14:
                if p[6] <= 0:
                    p[6] = 35
                    self._spark(p[0], p[1], YL, 6)
                    pyxel.play(1, 1, resume=False)
                self.pads.pop(j)
            else:
                j += 1

        # Slipstream (aus alter Version: dy bis 60, dx bis 22)
        dx      = abs(p[0] - opp[0])
        dy      = p[1] - opp[1]
        in_slip = (6 < dy < 60 and dx < 22 and opp[9])
        if in_slip:
            p[7] = min(p[7] + 1, SLIP_MAX)
        else:
            p[7] = max(p[7] - 1, 0)

        if p[7] >= SLIP_MAX and not p[8]:
            p[8] = True

        # Windschatten-Boost aktivieren → Teleport + Sound 2
        if p[8] and p[4] <= 0 and pyxel.btnp(ksw):
            p[7] = 0; p[8] = False; p[6] = 40
            p[0] = opp[0]
            p[1] = opp[1] + 18
            p[3] = max(p[3], opp[3] - 40)
            self._spark(p[0], p[1], YL, 10)
            pyxel.play(2, 2, resume=False)

    # ── Y POSITIONS ────────────────────────────────────────
    def _update_y(self):
        p0, p1 = self.p[0], self.p[1]
        delta  = p0[3] - p1[3]
        spread = min(abs(delta) * 0.055, 120)   # bis zu 120px Abstand möglich

        if delta >= 0:
            p0[1] = BASE_Y - spread
            p1[1] = BASE_Y + spread
        else:
            p1[1] = BASE_Y - spread
            p0[1] = BASE_Y + spread

        # Out of screen → Tod
        for idx, p in enumerate(self.p):
            if p[1] > H + 10 and p[9]:
                p[9] = False
                if self.winner is None:
                    self.winner = 1 - idx

    def _spark(self, x, y, col, n):
        for _ in range(n):
            self.sparks.append([float(x), float(y),
                                random.uniform(-2.0, 2.0),
                                random.uniform(-2.5, 0.3),
                                random.randint(6, 12), col])

    # ═══════════════════════════════════════════════════════
    # DRAW
    # ═══════════════════════════════════════════════════════
    def draw(self):
        pyxel.cls(BG)
        self._draw_road()
        st = self.state
        if st == "title":
            self._draw_title()
        elif st == "countdown":
            self._draw_cars(); self._draw_cdown()
        elif st == "race":
            if self.show_fin: self._draw_finline()
            self._draw_pads(); self._draw_obs()
            self._draw_sparks(); self._draw_cars()
            self._draw_hud(); self._draw_progbar()
        elif st == "finish":
            self._draw_finline()
            self._draw_cars(); self._draw_sparks()
            self._draw_progbar(); self._draw_finish()

    def _draw_road(self):
        pyxel.rect(RL, 0, RW, H, RD)
        seg = 20
        for i in range(H // seg + 2):
            yy = (i*seg + int(self.offset*1.5)) % (H+seg) - seg
            c  = 8 if i % 2 == 0 else WH
            pyxel.rect(RL-6, yy, 6, seg, c)
            pyxel.rect(RR,   yy, 6, seg, c)
        dash, gap = 10, 8
        cyc = dash + gap
        for ln in range(1, 4):
            lx = RL + LW * ln
            for i in range(H // cyc + 2):
                yy = (i*cyc + int(self.offset)) % (H+cyc) - cyc
                pyxel.rect(lx, yy, 1, dash, LN)
        pyxel.line(RL, 0, RL, H, TE)
        pyxel.line(RR, 0, RR, H, TE)

    def _draw_finline(self):
        # Ziellinie an ihrer aktuellen scroll-Position zeichnen
        fy   = int(self.fin_y)
        tile = 8
        for ci in range(RW // tile + 1):
            for ri in range(2):
                tx = RL + ci * tile
                ty = fy + ri * tile
                if 0 <= ty < H:
                    pyxel.rect(tx, ty, tile, tile,
                               WH if (ci+ri) % 2 == 0 else RD)
        if 0 <= fy < H:
            pyxel.line(RL, fy,          RR, fy,          YL)
        if 0 <= fy + tile*2 < H:
            pyxel.line(RL, fy + tile*2, RR, fy + tile*2, YL)
        if 0 <= fy + 5 < H:
            pyxel.text(RL + RW//2 - 8, fy + 5, "ZIEL!", YL)

    def _draw_pads(self):
        for pad in self.pads:
            x, y = int(pad[0]), int(pad[1])
            c = YL if (pad[3] // 4) % 2 == 0 else WH
            pyxel.tri(x, y-10, x-8, y+2, x+8, y+2, c)
            pyxel.rect(x-5, y+2, 10, 7, c)

    def _draw_obs(self):
        # Keine Pfeile — nur Hindernisse
        for o in self.obs:
            x, y = int(o[0]), int(o[1])
            if o[2] == 0:
                pyxel.tri(x, y-7, x-5, y+5, x+5, y+5, OR)
                pyxel.rect(x-5, y+2, 10, 2, WH)
            elif o[2] == 1:
                pyxel.rect(x-8, y-3, 16, 6, PU)
                pyxel.rect(x-5, y-4, 10, 8, PU)
            else:
                pyxel.rect(x-7, y-4, 14, 8, OR)
                pyxel.rect(x-5, y-4,  4, 8, RD)
                pyxel.rect(x+1, y-4,  4, 8, RD)

    def _draw_sparks(self):
        for s in self.sparks:
            pyxel.pset(int(s[0]), int(s[1]),
                       s[5] if s[4] % 4 < 2 else WH)

    def _draw_cars(self):
        for i, p in enumerate(self.p):
            if not p[9]: continue
            x, y = int(p[0]), int(p[1])
            col  = C1 if i == 0 else C2
            inv, stun, boost, srdy = p[5], p[4], p[6], p[8]

            if inv > 0 and stun <= 0 and (inv // 3) % 2 == 1: continue
            if stun > 0 and (stun // 3) % 2 == 1: continue

            if boost > 0:
                fl = 8 + (pyxel.frame_count % 3) * 3
                pyxel.rect(x-3, y+8,  6,  fl,   YL)
                pyxel.rect(x-1, y+10, 2, fl+4,  WH)
                fc = YL if (pyxel.frame_count // 2) % 2 == 0 else WH
                pyxel.text(x-10, y-20, "BOOST!", fc)

            if srdy and (pyxel.frame_count // 4) % 2 == 0:
                pyxel.rectb(x-6, y-10, 12, 20, YL)

            pyxel.rect(x-4, y-8, 8, 16, col)
            pyxel.rect(x-3, y-7, 6,  4, 6)
            pyxel.rect(x-3, y-8, 6,  1, WH)
            pyxel.rect(x-6, y-6, 3, 5, RD)
            pyxel.rect(x+3, y-6, 3, 5, RD)
            pyxel.rect(x-6, y+2, 3, 5, RD)
            pyxel.rect(x+3, y+2, 3, 5, RD)
            pyxel.pset(x-3, y-8, YL)
            pyxel.pset(x+2, y-8, YL)

            if stun > 0:
                pyxel.text(x-8, y-20, "STUN!", OR)

            # Windschatten-Ladebalken unter dem Auto
            slip_pct = p[7] / SLIP_MAX
            if slip_pct > 0.1:
                bar_w = int(slip_pct * 12)
                pyxel.rect(x-6, y+10, 12, 2, 1)
                pyxel.rect(x-6, y+10, bar_w, 2, TE)

    def _draw_hud(self):
        bh = 38; by = H - 52
        for i, p in enumerate(self.p):
            bx = 2 if i == 0 else W - 8
            pyxel.rect(bx, by, 6, bh, 1)
            fill = int((p[7] / SLIP_MAX) * bh)
            if fill > 0:
                fc = WH if p[8] else (C1 if i == 0 else C2)
                pyxel.rect(bx, by+bh-fill, 6, fill, fc)
            pyxel.rectb(bx, by, 6, bh, C1 if i == 0 else C2)
            pyxel.text(bx if i == 0 else bx-1, by+bh+2,
                       "P"+str(i+1), C1 if i == 0 else C2)
            if p[8]:
                pyxel.text(bx, by-8, "W" if i == 0 else "^", WH)
            if p[5] > 0 and p[4] <= 0 and (p[5]//5) % 2 == 0:
                pyxel.text(bx-2, by-16, "SAFE", TE)

    def _draw_progbar(self):
        # Minimap: vertikaler Balken rechts
        bx, by0, bh = W-18, 8, H-16
        # Hintergrund
        pyxel.rect(bx, by0, 6, bh, 1)
        pyxel.rectb(bx, by0, 6, bh, LN)

        # Ziellinie in der Minimap (oben = Ziel)
        pyxel.rect(bx-2, by0, 10, 3, YL)
        # Kleines Schachbrettmuster
        for ci in range(5):
            c = WH if ci % 2 == 0 else RD
            pyxel.pset(bx - 2 + ci*2, by0 + 1, c)
            pyxel.pset(bx - 2 + ci*2 + 1, by0, c)

        # "ZIEL" Label
        pyxel.text(bx - 8, by0 - 6, "ZIEL", YL)

        # Start-Markierung unten
        pyxel.rect(bx-1, by0+bh-3, 8, 3, 6)
        pyxel.text(bx-6, by0+bh+1, "START", 6)

        # Spieler-Marker
        for i, p in enumerate(self.p):
            if not p[9] and not p[10]: continue
            pct = min(p[3] / RACE_LEN, 1.0)
            py  = int(by0 + bh - 3 - pct * (bh - 6))
            col = C1 if i == 0 else C2
            # Dreieck-Marker (kleiner Pfeil nach links/rechts)
            if i == 0:
                pyxel.tri(bx-3, py, bx, py-2, bx, py+2, col)
            else:
                pyxel.tri(bx+9, py, bx+6, py-2, bx+6, py+2, col)
            pyxel.text(bx+1, py-2, str(i+1), RD)

    def _draw_cdown(self):
        cx, cy = W//2, H//2
        if self.cdown > 0:
            pyxel.text(cx-2, cy-4, str(self.cdown),
                       C1 if self.cdown == 1 else WH)
        else:
            pyxel.text(cx-6, cy-4, "GO!", TE)

    # ── TITELBILDSCHIRM (aus v3) ────────────────────────────
    def _draw_title(self):
        fc = pyxel.frame_count

        # Animierte Straße im Hintergrund
        pyxel.rect(RL, 0, RW, H, RD)
        seg = 20
        off = (fc * 3) % (seg * 2)
        for i in range(H // seg + 3):
            yy = (i*seg + off) % (H + seg*2) - seg
            c  = 8 if i % 2 == 0 else WH
            pyxel.rect(RL-6, yy, 6, seg, c)
            pyxel.rect(RR,   yy, 6, seg, c)
        dash, gap = 10, 8; cyc = dash + gap
        for ln in range(1, 4):
            lx = RL + LW * ln
            for i in range(H // cyc + 3):
                yy = (i*cyc + off) % (H+cyc*2) - cyc
                pyxel.rect(lx, yy, 1, dash, LN)
        pyxel.line(RL, 0, RL, H, TE)
        pyxel.line(RR, 0, RR, H, TE)

        # Titel-Panel
        pyxel.rect(14, 8, W-28, 74, BG)
        pyxel.rectb(14, 8, W-28, 74, TE)
        pyxel.rectb(15, 9, W-30, 72, LN)

        tc = C1 if (fc // 6) % 2 == 0 else WH
        tx = W//2 - 38
        pyxel.text(tx,   14, "N E O N", tc)
        pyxel.text(tx+1, 14, "N E O N", tc)
        pyxel.text(tx,   22, "D A S H", C2)
        pyxel.text(tx+1, 22, "D A S H", C2)
        pyxel.text(W//2-28, 32, "DOUBLE  DRIFT", YL)

        pyxel.line(20, 44, W-20, 44, LN)

        pyxel.text(16,       48, "P1",            C1)
        pyxel.text(16,       56, "A / D  bewegen",WH)
        pyxel.text(16,       63, "W      Boost",  YL)
        pyxel.text(W//2+4,   48, "P2",            C2)
        pyxel.text(W//2+4,   56, " bewegen",   WH)
        pyxel.text(W//2+4,   63, "^   Boost",     YL)

        pyxel.line(20, 73, W-20, 73, LN)

        # Demo-Autos
        ax    = (fc * 2) % (W + 20) - 10
        bx    = W - ax
        car_y = 95
        fl    = 6 + (fc % 3) * 2
        pyxel.rect(ax-4, car_y-8, 8, 16, C1)
        pyxel.rect(ax-3, car_y-7, 6,  4, 6)
        pyxel.pset(ax-3, car_y-8, YL); pyxel.pset(ax+2, car_y-8, YL)
        pyxel.rect(ax-3, car_y+8, 6, fl, YL)
        pyxel.rect(bx-4, car_y-8, 8, 16, C2)
        pyxel.rect(bx-3, car_y-7, 6,  4, 6)
        pyxel.pset(bx-3, car_y-8, YL); pyxel.pset(bx+2, car_y-8, YL)
        pyxel.rect(bx-3, car_y+8, 6, fl, YL)

        # Info-Leiste
        pyxel.rect(14, H-28, W-28, 20, BG)
        pyxel.rectb(14, H-28, W-28, 20, TE)
        pyxel.text(18, H-24, "Windschatten -> Teleport+Boost", WH)
        pyxel.text(18, H-16, "Hindernis=STUN   Pfeile=SPEED",  OR)

        if (fc // 10) % 2 == 0:
            sw = len(">>> SPACE = START <<<") * 4
            pyxel.text(W//2 - sw//2, H - 6, ">>> SPACE = START <<<", YL)

    def _draw_finish(self):
        ft  = self.ftimer
        fc  = pyxel.frame_count
        col = C1 if self.winner == 0 else C2

        # Phase 1 (0-40): Feuerwerk explodiert über dem Screen
        if ft < 60:
            for _ in range(6):
                fx = random.randint(RL + 10, RR - 10)
                fy = random.randint(10, H - 30)
                rc = random.choice([C1, C2, YL, WH, TE, OR])
                for angle in range(0, 360, 45):
                    rad = math.radians(angle)
                    ex  = fx + int(math.cos(rad) * random.randint(2, 8))
                    ey  = fy + int(math.sin(rad) * random.randint(2, 8))
                    if 0 <= ex < W and 0 <= ey < H:
                        pyxel.pset(ex, ey, rc)

        # Phase 2 (20+): Panel fährt von oben rein
        panel_target_y = H // 2 - 32
        panel_y = max(panel_target_y, H // 2 - 32 - max(0, ft - 15) * 6)
        panel_y = min(H, panel_y)   # Startet ausserhalb unten nicht nötig, von oben:
        # Panel gleitet von oben rein
        slide = max(0, ft - 10)
        panel_y = max(panel_target_y, -64 + slide * 8)
        panel_y = min(panel_target_y, panel_y)

        if ft >= 10:
            pw, ph = W - 40, 64
            px = 20
            py = panel_y

            # Schatten
            pyxel.rect(px+3, py+3, pw, ph, 0)
            # Hauptpanel
            pyxel.rect(px, py, pw, ph, BG)
            # Farbiger Rand in Siegerfarbe
            pyxel.rectb(px,   py,   pw,   ph,   col)
            pyxel.rectb(px+1, py+1, pw-2, ph-2, WH)

            # Flackernde Siegerfarbe oben als Leiste
            bar_col = col if (fc // 3) % 2 == 0 else YL
            pyxel.rect(px+2, py+2, pw-4, 8, bar_col)

            # "SPIELER X" mit Bounce-Effekt
            if self.winner is not None:
                lbl = "SPIELER  " + str(self.winner + 1)
                bounce = int(abs(math.sin(ft * 0.15)) * 3)
                lx = px + pw//2 - len(lbl) * 2
                pyxel.text(lx,   py + 14 - bounce, lbl, col)
                pyxel.text(lx+1, py + 14 - bounce, lbl, col)  # fett

            # "GEWINNT!!" gross
            gw = "GEWINNT!!"
            gx = px + pw//2 - len(gw) * 2
            pyxel.text(gx,   py + 24, gw, WH)
            pyxel.text(gx+1, py + 24, gw, WH)

            # Laufende Sterne
            star_offset = (fc * 2) % (pw - 4)
            stars = "* * * * * * * * * * * * *"
            star_x = px + 2 + star_offset - len(stars) * 4
            pyxel.text(star_x,              py + 38, stars, YL)
            pyxel.text(star_x + len(stars)*4+4, py + 38, stars, YL)

            # Restart-Hinweis
            if ft > 40 and (fc // 10) % 2 == 0:
                rt = "SPACE = NOCHMAL"
                pyxel.text(px + pw//2 - len(rt)*2, py + 50, rt, LN)


App()