# Pyxel Studio

import pyxel
import random
import math
WIDTH = 160
HEIGHT = 120

class Game:
   def __init__(self):
       pyxel.init(WIDTH, HEIGHT, title="Space Fight")
       self.highscore = 0
       self.stars = [[random.randint(0, WIDTH), random.randint(0, HEIGHT), random.random()] for _ in range(60)]
       self.state = "menu"
       self.reset_game(first=True)
       pyxel.run(self.update, self.draw)
   def reset_game(self, first=False):
       self.player_x = WIDTH // 2 - 6
       self.player_y = HEIGHT - 18
       self.player_speed = 2
       self.speed_timer = 0
       self.bullets = []
       self.enemies = []
       self.powerups = []
       self.boss = None
       self.boss_enemy_kills = 0
       self.level = 1
       self.score = 0
       self.lives = 3
       self.base_enemy_speed = 1
       self.base_spawn_time = 90
       self.enemy_timer = 0
       self.powerup_timer = 0
       self.boss_triggered = set()
       # Neu: aktuelle Dimension
       self.world = "space"
       if not first:
           self.state = "game"
   def overlap(self, x1, y1, w1, h1, x2, y2, w2, h2):
       return x1 < x2 + w2 and x1 + w1 > x2 and y1 < y2 + h2 and y1 + h1 > y2
   def toggle_world(self):
       if self.world == "space":
           self.world = "ocean"
           pyxel.title("Ocean Fight")
       else:
           self.world = "space"
           pyxel.title("Space Fight")
   # ---------------- SPACE / OCEAN SKINS ----------------
   def draw_player(self, x, y):
       if self.world == "space":
           flame = 10 if pyxel.frame_count % 6 < 3 else 9
           pyxel.tri(x + 6, y + 13, x + 4, y + 16, x + 8, y + 16, flame)
           pyxel.tri(x + 6, y, x + 1, y + 10, x + 11, y + 10, 12)
           pyxel.rect(x + 4, y + 4, 4, 7, 6)
           pyxel.pset(x + 6, y + 3, 7)
           pyxel.pset(x + 5, y + 8, 1)
           pyxel.pset(x + 7, y + 8, 1)
       else:
           # Nemo-artiger Fisch
           swim = 9 if pyxel.frame_count % 8 < 4 else 10
           pyxel.tri(x + 1, y + 8, x - 3, y + 4, x - 3, y + 12, swim)   # Schwanz
           pyxel.circ(x + 6, y + 8, 5, 8)                               # Körper
           pyxel.rect(x + 4, y + 3, 2, 10, 7)                           # Streifen
           pyxel.rect(x + 7, y + 3, 2, 10, 7)
           pyxel.tri(x + 6, y + 4, x + 8, y + 1, x + 9, y + 5, 9)      # Flosse oben
           pyxel.tri(x + 6, y + 11, x + 8, y + 14, x + 9, y + 10, 9)   # Flosse unten
           pyxel.pset(x + 9, y + 7, 7)                                  # Auge
           pyxel.pset(x + 10, y + 7, 1)
   def draw_bullet(self, x, y):
       if self.world == "space":
           pyxel.rect(x, y, 2, 4, 10)
           pyxel.pset(x, y, 7)
           pyxel.pset(x + 1, y, 7)
       else:
           # Seestern-Schuss
           c = 10 if pyxel.frame_count % 6 < 3 else 9
           pyxel.pset(x + 1, y, c)
           pyxel.pset(x, y + 1, c)
           pyxel.pset(x + 1, y + 1, 7)
           pyxel.pset(x + 2, y + 1, c)
           pyxel.pset(x + 1, y + 2, c)
   def draw_enemy(self, e):
       x, y, t = int(e["x"]), int(e["y"]), e["type"]
       if self.world == "space":
           if t == "normal":
               pyxel.tri(x + 5, y + 8, x + 1, y + 1, x + 9, y + 1, 8)
               pyxel.rect(x + 3, y + 2, 4, 4, 14)
               pyxel.pset(x + 4, y + 4, 7)
               pyxel.pset(x + 6, y + 4, 7)
           elif t == "tank":
               pyxel.rect(x + 1, y + 1, 10, 7, 5)
               pyxel.rect(x + 3, y, 6, 3, 13)
               pyxel.pset(x + 4, y + 4, 7)
               pyxel.pset(x + 7, y + 4, 7)
               pyxel.rect(x, y + 6, 12, 2, 1)
           else:  # zigzag
               c = 11 if pyxel.frame_count % 8 < 4 else 10
               pyxel.tri(x + 5, y, x, y + 7, x + 10, y + 7, c)
               pyxel.rect(x + 3, y + 2, 4, 3, 2)
               pyxel.pset(x + 5, y + 3, 7)
       else:
           if t == "normal":
               # kleine Krake
               pyxel.circ(x + 6, y + 4, 4, 5)
               pyxel.pset(x + 4, y + 3, 7)
               pyxel.pset(x + 7, y + 3, 7)
               for i in range(4):
                   pyxel.line(x + 2 + i * 2, y + 7, x + 1 + i * 2, y + 10, 13)
           elif t == "tank":
               # Kugelfisch
               pyxel.circ(x + 6, y + 5, 5, 6)
               pyxel.pset(x + 4, y + 4, 7)
               pyxel.pset(x + 7, y + 4, 7)
               pyxel.pset(x + 1, y + 5, 10)
               pyxel.pset(x + 11, y + 5, 10)
               pyxel.pset(x + 3, y + 1, 10)
               pyxel.pset(x + 8, y + 1, 10)
               pyxel.pset(x + 3, y + 9, 10)
               pyxel.pset(x + 8, y + 9, 10)
           else:
               # Qualle
               c = 12 if pyxel.frame_count % 8 < 4 else 6
               pyxel.circ(x + 5, y + 4, 4, c)
               pyxel.rect(x + 1, y + 4, 9, 3, c)
               pyxel.pset(x + 4, y + 4, 7)
               pyxel.pset(x + 6, y + 4, 7)
               pyxel.line(x + 2, y + 7, x + 1, y + 10, 13)
               pyxel.line(x + 5, y + 7, x + 5, y + 11, 13)
               pyxel.line(x + 8, y + 7, x + 9, y + 10, 13)
   def draw_powerup(self, p):
       x, y = int(p["x"]), int(p["y"])
       if p["type"] == "life":
           if self.world == "space":
               self.draw_heart(x, y)
           else:
               self.draw_shell(x, y)
       elif p["type"] == "speed":
           if self.world == "space":
               c = 10 if pyxel.frame_count % 6 < 3 else 9
               pyxel.tri(x + 3, y, x, y + 5, x + 4, y + 5, c)
               pyxel.tri(x + 4, y + 3, x + 7, y + 3, x + 3, y + 8, c)
           else:
               self.draw_fin_boost(x, y)
       elif p["type"] == "portal":
           self.draw_portal(x, y)
   def draw_heart(self, x, y):
       pyxel.pset(x + 2, y + 1, 8)
       pyxel.pset(x + 5, y + 1, 8)
       pyxel.rect(x + 1, y + 2, 2, 2, 8)
       pyxel.rect(x + 4, y + 2, 2, 2, 8)
       pyxel.rect(x + 2, y + 3, 3, 2, 8)
       pyxel.tri(x + 1, y + 4, x + 6, y + 4, x + 3, y + 8, 8)
       pyxel.pset(x + 2, y + 2, 7)
   def draw_shell(self, x, y):
       pyxel.circ(x + 4, y + 4, 4, 7)
       pyxel.line(x + 4, y, x + 4, y + 8, 6)
       pyxel.line(x + 2, y + 1, x + 2, y + 7, 6)
       pyxel.line(x + 6, y + 1, x + 6, y + 7, 6)
   def draw_fin_boost(self, x, y):
       c = 10 if pyxel.frame_count % 6 < 3 else 9
       pyxel.tri(x, y + 4, x + 7, y, x + 7, y + 8, c)
       pyxel.line(x + 2, y + 4, x + 6, y + 4, 7)
   def draw_portal(self, x, y):
       # Blaues Ozean-Material / Dimensionsportal
       pulse = pyxel.frame_count % 12
       outer = 12 if pulse < 6 else 6
       inner = 1 if pulse < 6 else 7
       pyxel.circ(x + 5, y + 5, 5, outer)
       pyxel.circ(x + 5, y + 5, 3, inner)
       pyxel.pset(x + 3, y + 2, 7)
       pyxel.pset(x + 7, y + 3, 7)
       pyxel.pset(x + 2, y + 6, 6)
       pyxel.pset(x + 8, y + 7, 12)
       pyxel.line(x + 1, y + 5, x + 9, y + 5, 12)
       pyxel.line(x + 5, y + 1, x + 5, y + 9, 6)
   def draw_boss(self):
       if not self.boss:
           return
       x, y = int(self.boss["x"]), int(self.boss["y"])
       blink = 8 if pyxel.frame_count % 10 < 5 else 14
       if self.world == "space":
           if self.boss["stage"] == 1:
               pyxel.rect(x + 4, y + 4, 24, 10, 5)
               pyxel.rect(x + 8, y, 16, 6, 13)
               pyxel.tri(x, y + 10, x + 6, y + 5, x + 6, y + 15, 8)
               pyxel.tri(x + 32, y + 10, x + 26, y + 5, x + 26, y + 15, 8)
               pyxel.rect(x + 2, y + 14, 28, 4, 1)
               pyxel.pset(x + 11, y + 7, blink)
               pyxel.pset(x + 21, y + 7, blink)
               pyxel.rect(x + 14, y + 10, 4, 3, 7)
           elif self.boss["stage"] == 2:
               pyxel.rect(x + 3, y + 5, 26, 11, 2)
               pyxel.rect(x + 8, y + 1, 16, 6, 9)
               pyxel.tri(x, y + 12, x + 6, y + 6, x + 6, y + 18, 11)
               pyxel.tri(x + 32, y + 12, x + 26, y + 6, x + 26, y + 18, 11)
               pyxel.rect(x + 1, y + 15, 30, 3, 5)
               pyxel.pset(x + 10, y + 8, blink)
               pyxel.pset(x + 21, y + 8, blink)
               pyxel.rect(x + 14, y + 10, 5, 3, 7)
               pyxel.rect(x + 6, y + 17, 4, 2, 8)
               pyxel.rect(x + 22, y + 17, 4, 2, 8)
           else:
               pyxel.rect(x + 2, y + 5, 28, 12, 1)
               pyxel.rect(x + 7, y, 18, 7, 8)
               pyxel.tri(x, y + 12, x + 7, y + 4, x + 7, y + 19, 10)
               pyxel.tri(x + 32, y + 12, x + 25, y + 4, x + 25, y + 19, 10)
               pyxel.rect(x + 4, y + 16, 24, 3, 13)
               pyxel.pset(x + 10, y + 8, blink)
               pyxel.pset(x + 21, y + 8, blink)
               pyxel.rect(x + 13, y + 10, 6, 4, 7)
               pyxel.rect(x + 5, y + 6, 3, 6, 14)
               pyxel.rect(x + 24, y + 6, 3, 6, 14)
           pyxel.text(10, 4, f"BOSS {self.boss['stage']}", 7)
       else:
           # Ozeanboss = Riesenkraake
           if self.boss["stage"] == 1:
               body_col = 5
           elif self.boss["stage"] == 2:
               body_col = 12
           else:
               body_col = 2
           pyxel.circ(x + 16, y + 10, 9, body_col)
           pyxel.pset(x + 12, y + 8, 7 if pyxel.frame_count % 10 < 5 else 10)
           pyxel.pset(x + 19, y + 8, 7 if pyxel.frame_count % 10 < 5 else 10)
           for i in range(6):
               offset = i * 5
               wave = int(math.sin((pyxel.frame_count + i * 5) * 0.15) * 2)
               pyxel.line(x + 4 + offset, y + 16, x + 3 + offset + wave, y + 23, 13)
               pyxel.line(x + 3 + offset + wave, y + 23, x + 2 + offset - wave, y + 29, 13)
           pyxel.text(10, 4, f"KRAKE {self.boss['stage']}", 7)
       pyxel.rect(35, 5, 90, 4, 1)
       pyxel.rect(35, 5, int(90 * self.boss["hp"] / self.boss["max_hp"]), 4, 8)
   def spawn_boss(self, stage):
       if stage == 1:
           self.boss = {
               "stage": 1,
               "x": WIDTH // 2 - 16,
               "y": 8,
               "hp": 34,
               "max_hp": 34,
               "dir": 1,
               "timer": 0,
               "speed": 1.2,
               "spawn_rate": 55
           }
       elif stage == 2:
           self.boss = {
               "stage": 2,
               "x": WIDTH // 2 - 16,
               "y": 8,
               "hp": 48,
               "max_hp": 48,
               "dir": 1,
               "timer": 0,
               "speed": 1.7,
               "spawn_rate": 42
           }
       elif stage == 3:
           self.boss = {
               "stage": 3,
               "x": WIDTH // 2 - 16,
               "y": 8,
               "hp": 62,
               "max_hp": 62,
               "dir": 1,
               "timer": 0,
               "speed": 2.1,
               "spawn_rate": 34
           }
       self.boss_enemy_kills = 0
   # ---------------- UPDATE ----------------
   def update(self):
       # Hintergrundpartikel
       for star in self.stars:
           if self.world == "space":
               star[1] += 0.3 + star[2] * 0.8
               if star[1] > HEIGHT:
                   star[0] = random.randint(0, WIDTH)
                   star[1] = 0
           else:
               star[1] -= 0.3 + star[2] * 0.8
               if star[1] < 0:
                   star[0] = random.randint(0, WIDTH)
                   star[1] = HEIGHT
       if self.state != "game":
           if pyxel.btnp(pyxel.KEY_S):
               self.reset_game()
           return
       # Boss-Schwellen
       if not self.boss:
           if self.score >= 240 and 240 not in self.boss_triggered:
               self.spawn_boss(3)
               self.boss_triggered.add(240)
           elif self.score >= 180 and 180 not in self.boss_triggered:
               self.spawn_boss(3)
               self.boss_triggered.add(180)
           elif self.score >= 110 and 110 not in self.boss_triggered:
               self.spawn_boss(2)
               self.boss_triggered.add(110)
           elif self.score >= 40 and 40 not in self.boss_triggered:
               self.spawn_boss(1)
               self.boss_triggered.add(40)
       # Bewegung
       if pyxel.btn(pyxel.KEY_LEFT):
           self.player_x -= self.player_speed
       if pyxel.btn(pyxel.KEY_RIGHT):
           self.player_x += self.player_speed
       self.player_x = max(0, min(self.player_x, WIDTH - 12))
       # Schießen
       if pyxel.btnp(pyxel.KEY_SPACE):
           self.bullets.append([self.player_x + 5, self.player_y])
       for b in self.bullets:
           b[1] -= 4
       self.bullets = [b for b in self.bullets if b[1] > -5]
       # Normale Gegner nur wenn kein Boss da ist
       if not self.boss:
           if self.score < 50:
               spawn_time = max(60, self.base_spawn_time - (self.level - 1) * 4)
           elif self.score < 150:
               spawn_time = 58
           else:
               spawn_time = 54
           self.enemy_timer += 1
           if self.enemy_timer >= spawn_time:
               x = random.randint(10, WIDTH - 20)
               r = random.random()
               if self.level <= 2:
                   etype = "normal"
               elif self.level <= 4:
                   etype = "tank" if r < 0.25 else "normal"
               else:
                   if r < 0.20:
                       etype = "tank"
                   elif r < 0.50:
                       etype = "zigzag"
                   else:
                       etype = "normal"
               self.enemies.append({
                   "x": float(x),
                   "y": 0.0,
                   "type": etype,
                   "hp": 2 if etype == "tank" else 1,
                   "t": 0.0,
                   "from_boss": False
               })
               self.enemy_timer = 0
       # Powerups + Portal
       self.powerup_timer += 1
       if self.powerup_timer > 260:
           r = random.random()
           if r < 0.14:
               ptype = "life"
           elif r < 0.88:
               ptype = "speed"
           else:
               ptype = "portal"
           self.powerups.append({
               "x": random.randint(10, WIDTH - 20),
               "y": 0.0,
               "type": ptype
           })
           self.powerup_timer = 0
       # Gegner bewegen
       if self.score < 50:
           spd = 1.2 + self.level * 0.08
       elif self.score < 150:
           spd = 1.6
       else:
           spd = 1.8
       for e in self.enemies:
           if e["type"] == "zigzag":
               e["t"] += 0.18
               e["x"] += math.sin(e["t"]) * 1.5
               e["x"] = max(0, min(e["x"], WIDTH - 10))
           e["y"] += spd
       # Boss bewegen und Gegner erzeugen
       if self.boss:
           self.boss["timer"] += 1
           if self.boss["stage"] == 1:
               self.boss["x"] += self.boss["dir"] * self.boss["speed"]
               if self.boss["x"] < 4 or self.boss["x"] > WIDTH - 36:
                   self.boss["dir"] *= -1
           elif self.boss["stage"] == 2:
               self.boss["x"] += self.boss["dir"] * self.boss["speed"]
               if self.boss["x"] < 2 or self.boss["x"] > WIDTH - 34:
                   self.boss["dir"] *= -1
           elif self.boss["stage"] == 3:
               self.boss["x"] += self.boss["dir"] * self.boss["speed"]
               self.boss["y"] = 8 + math.sin(self.boss["timer"] * 0.08) * 3
               if self.boss["x"] < 2 or self.boss["x"] > WIDTH - 34:
                   self.boss["dir"] *= -1
           if self.boss["timer"] % self.boss["spawn_rate"] == 0:
               etype = random.choice(["normal", "zigzag"])
               if self.boss["stage"] == 3 and random.random() < 0.25:
                   etype = "tank"
               self.enemies.append({
                   "x": self.boss["x"] + 16,
                   "y": self.boss["y"] + 18,
                   "type": etype,
                   "hp": 2 if etype == "tank" else 1,
                   "t": 0.0,
                   "from_boss": True
               })
       for p in self.powerups:
           p["y"] += 1.5
       # Kugeln treffen Gegner
       for e in self.enemies[:]:
           for b in self.bullets[:]:
               if self.overlap(b[0], b[1], 2, 4, e["x"], e["y"], 12, 9):
                   e["hp"] -= 1
                   self.bullets.remove(b)
                   if e["hp"] <= 0:
                       self.enemies.remove(e)
                       self.score += 1
                       if e.get("from_boss", False):
                           self.boss_enemy_kills += 1
                       if self.score % 10 == 0:
                           self.level += 1
                   break
       # Kugeln treffen Boss
       if self.boss:
           for b in self.bullets[:]:
               if self.overlap(b[0], b[1], 2, 4, self.boss["x"], self.boss["y"], 32, 20):
                   self.bullets.remove(b)
                   self.boss["hp"] -= 1
                   if self.boss["hp"] <= 0:
                       self.score += 10 + self.boss_enemy_kills
                       self.boss = None
                       self.boss_enemy_kills = 0
                       break
       # Spieler trifft Gegner
       for e in self.enemies[:]:
           if self.overlap(self.player_x, self.player_y, 12, 16, e["x"], e["y"], 12, 9):
               self.enemies.remove(e)
               self.lives -= 1
       # Spieler trifft Boss
       if self.boss and self.overlap(self.player_x, self.player_y, 12, 16, self.boss["x"], self.boss["y"], 32, 20):
           self.lives = 0
       # Powerups / Portal einsammeln
       for p in self.powerups[:]:
           if self.overlap(self.player_x, self.player_y, 12, 16, p["x"], p["y"], 10, 10):
               self.powerups.remove(p)
               if p["type"] == "life" and self.lives < 5:
                   self.lives += 1
               elif p["type"] == "speed":
                   self.player_speed = 4
                   self.speed_timer = 300
               elif p["type"] == "portal":
                   self.toggle_world()
       if self.speed_timer > 0:
           self.speed_timer -= 1
           if self.speed_timer == 0:
               self.player_speed = 2
       for e in self.enemies[:]:
           if e["y"] > HEIGHT:
               self.enemies.remove(e)
               self.lives -= 1
       self.powerups = [p for p in self.powerups if p["y"] < HEIGHT]
       if self.lives <= 0:
           if self.score > self.highscore:
               self.highscore = self.score
           self.state = "gameover"
   # ---------------- DRAW ----------------
   def draw(self):
       if self.world == "space":
           pyxel.cls(0)
           for star in self.stars:
               col = 1 if star[2] < 0.33 else 5 if star[2] < 0.66 else 6
               pyxel.pset(int(star[0]), int(star[1]), col)
       else:
           pyxel.cls(1)
           for star in self.stars:
               col = 7 if star[2] < 0.33 else 6 if star[2] < 0.66 else 12
               pyxel.pset(int(star[0]), int(star[1]), col)
           # Ozeanboden / Korallen
           pyxel.rect(0, HEIGHT - 8, WIDTH, 8, 3)
           for i in range(0, WIDTH, 16):
               pyxel.line(i + 2, HEIGHT - 8, i + 5, HEIGHT - 14, 11)
               pyxel.line(i + 8, HEIGHT - 8, i + 10, HEIGHT - 13, 5)
       if self.state != "game":
           if self.world == "space":
               pyxel.text(54, 34, "SPACE FIGHT", 12)
           else:
               pyxel.text(54, 34, "OCEAN FIGHT", 10)
           pyxel.text(44, 52, f"HIGHSCORE {self.highscore}", 10)
           if self.state == "gameover":
               pyxel.text(58, 66, f"SCORE {self.score}", 7)
           pyxel.text(41, 84, "PRESS S TO START", 11)
           return
       self.draw_player(self.player_x, self.player_y)
       for b in self.bullets:
           self.draw_bullet(int(b[0]), int(b[1]))
       for e in self.enemies:
           self.draw_enemy(e)
       for p in self.powerups:
           self.draw_powerup(p)
       if self.boss:
           self.draw_boss()
       pyxel.text(5, 5, f"Score:{self.score}", 7)
       pyxel.text(5, 14, f"Level:{self.level}", 11)
       pyxel.text(5, 23, f"High:{self.highscore}", 10)
       for i in range(self.lives):
           if self.world == "space":
               self.draw_heart(WIDTH - 10 - i * 10, 4)
           else:
               self.draw_shell(WIDTH - 10 - i * 10, 4)
       if self.speed_timer > 0:
           if self.world == "space":
               pyxel.text(5, 32, "SPEED!", 10)
           else:
               pyxel.text(5, 32, "SWIM!", 10)

Game()