import pyxel
import math

# === EINSTELLUNGEN ===
WIDTH = 160
HEIGHT = 120
TILE = 8
SPEED = 0.8
ROT_SPEED = 0.07
BULLET_SPEED = 3.0
MAX_HP = 3
SHOOT_COOLDOWN = 20

# === KARTE (Waende) ===
# 1 = Wand, 0 = frei
TILEMAP = [
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1],
    [1,0,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0,1],
    [1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0,1],
    [1,0,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,1,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
]

def wall_at(tx, ty):
    if tx < 0 or ty < 0 or tx >= 20 or ty >= 15:
        return True
    return TILEMAP[ty][tx] == 1


class Tank:
    def __init__(self, x, y, angle, color_body, color_barrel):
        self.x = float(x)
        self.y = float(y)
        self.angle = float(angle)
        self.color_body = color_body
        self.color_barrel = color_barrel
        self.hp = MAX_HP
        self.cooldown = 0
        self.alive = True

    def move(self, forward, backward, turn_left, turn_right):
        if not self.alive:
            return
        if turn_left:
            self.angle -= ROT_SPEED
        if turn_right:
            self.angle += ROT_SPEED

        dx, dy = 0.0, 0.0
        if forward:
            dx = math.cos(self.angle) * SPEED
            dy = math.sin(self.angle) * SPEED
        if backward:
            dx = -math.cos(self.angle) * SPEED * 0.6
            dy = -math.sin(self.angle) * SPEED * 0.6

        nx, ny = self.x + dx, self.y + dy
        r = 3.5

        blocked = False
        for cx, cy in [(nx-r, ny-r), (nx+r, ny-r), (nx-r, ny+r), (nx+r, ny+r)]:
            if wall_at(int(cx // TILE), int(cy // TILE)):
                blocked = True
                break

        if not blocked:
            self.x = max(r, min(WIDTH - r, nx))
            self.y = max(r, min(HEIGHT - r, ny))

    def shoot(self, bullets, owner):
        if not self.alive or self.cooldown > 0:
            return
        bx = self.x + math.cos(self.angle) * 5
        by = self.y + math.sin(self.angle) * 5
        bullets.append(Bullet(bx, by, self.angle, owner))
        self.cooldown = SHOOT_COOLDOWN

    def update_cooldown(self):
        if self.cooldown > 0:
            self.cooldown -= 1

    def draw(self):
        if not self.alive:
            return
        px, py = int(self.x), int(self.y)
        cx = math.cos(self.angle)
        cy = math.sin(self.angle)
        rx = -math.sin(self.angle)
        ry = math.cos(self.angle)

        # Koerper zeichnen
        for ddx in range(-4, 5):
            for ddy in range(-3, 4):
                wx = px + int(ddx * cx + ddy * rx)
                wy = py + int(ddx * cy + ddy * ry)
                if 0 <= wx < WIDTH and 0 <= wy < HEIGHT:
                    pyxel.pset(wx, wy, self.color_body)

        # Kanone zeichnen
        for i in range(2, 7):
            bx2 = px + int(i * cx)
            by2 = py + int(i * cy)
            bx2b = px + int(i * cx + rx)
            by2b = py + int(i * cy + ry)
            if 0 <= bx2 < WIDTH and 0 <= by2 < HEIGHT:
                pyxel.pset(bx2, by2, self.color_barrel)
            if 0 <= bx2b < WIDTH and 0 <= by2b < HEIGHT:
                pyxel.pset(bx2b, by2b, self.color_barrel)

    def draw_hp(self, x, y):
        pyxel.rect(x, y, MAX_HP * 6, 3, 1)
        pyxel.rect(x, y, self.hp * 6, 3, self.color_body)


class Bullet:
    def __init__(self, x, y, angle, owner):
        self.x = float(x)
        self.y = float(y)
        self.vx = math.cos(angle) * BULLET_SPEED
        self.vy = math.sin(angle) * BULLET_SPEED
        self.owner = owner
        self.active = True
        self.life = 80

    def update(self):
        if not self.active:
            return
        self.x += self.vx
        self.y += self.vy
        self.life -= 1
        if self.life <= 0:
            self.active = False
            return
        if wall_at(int(self.x // TILE), int(self.y // TILE)):
            self.active = False

    def draw(self):
        if self.active:
            color = 11 if self.owner == 1 else 9
            ix, iy = int(self.x), int(self.y)
            if 0 <= ix < WIDTH and 0 <= iy < HEIGHT:
                pyxel.pset(ix, iy, color)
            if 0 <= ix+1 < WIDTH and 0 <= iy < HEIGHT:
                pyxel.pset(ix+1, iy, color)


class App:
    def __init__(self):
        pyxel.init(WIDTH, HEIGHT, title="Tank Battle", fps=30)
        self.score1 = 0
        self.score2 = 0
        self.state = "menu"
        self.winner = ""
        self.reset_round()

    def reset_round(self):
        self.tank1 = Tank(20, 60, 0.0, 11, 3)
        self.tank2 = Tank(140, 60, math.pi, 9, 4)
        self.bullets = []

    def update(self):
        if self.state == "menu":
            if pyxel.btnp(pyxel.KEY_RETURN) or pyxel.btnp(pyxel.KEY_SPACE):
                self.state = "playing"

        elif self.state == "playing":
            # Spieler 1: WASD + F
            self.tank1.move(
                pyxel.btn(pyxel.KEY_W),
                pyxel.btn(pyxel.KEY_S),
                pyxel.btn(pyxel.KEY_A),
                pyxel.btn(pyxel.KEY_D),
            )
            if pyxel.btn(pyxel.KEY_F):
                self.tank1.shoot(self.bullets, 1)
            self.tank1.update_cooldown()

            # Spieler 2: Pfeiltasten + L
            self.tank2.move(
                pyxel.btn(pyxel.KEY_UP),
                pyxel.btn(pyxel.KEY_DOWN),
                pyxel.btn(pyxel.KEY_LEFT),
                pyxel.btn(pyxel.KEY_RIGHT),
            )
            if pyxel.btn(pyxel.KEY_L):
                self.tank2.shoot(self.bullets, 2)
            self.tank2.update_cooldown()

            # Projektile aktualisieren und Treffer pruefen
            for b in self.bullets:
                b.update()
                if not b.active:
                    continue
                target = self.tank2 if b.owner == 1 else self.tank1
                if target.alive:
                    dx = b.x - target.x
                    dy = b.y - target.y
                    if math.sqrt(dx*dx + dy*dy) < 5:
                        target.hp -= 1
                        b.active = False
                        if target.hp <= 0:
                            target.alive = False

            self.bullets = [b for b in self.bullets if b.active]

            # Sieg pruefen
            if not self.tank1.alive:
                self.score2 += 1
                self.winner = "Spieler 2"
                self.state = "gameover"
            elif not self.tank2.alive:
                self.score1 += 1
                self.winner = "Spieler 1"
                self.state = "gameover"

        elif self.state == "gameover":
            if pyxel.btnp(pyxel.KEY_RETURN) or pyxel.btnp(pyxel.KEY_SPACE):
                self.reset_round()
                self.state = "playing"
            if pyxel.btnp(pyxel.KEY_Q):
                pyxel.quit()

    def draw(self):
        pyxel.cls(0)

        if self.state == "menu":
            pyxel.text(44, 45, "TANK BATTLE", 11)
            pyxel.text(30, 58, "2 Spieler - gleiche Tastatur", 7)
            pyxel.text(28, 72, "ENTER / SPACE zum Starten", 6)
            pyxel.text(18, 85, "S1: WASD + F    S2: Pfeile + L", 5)

        elif self.state == "playing":
            # Karte zeichnen
            for ty in range(15):
                for tx in range(20):
                    if TILEMAP[ty][tx] == 1:
                        pyxel.rect(tx*TILE, ty*TILE, TILE, TILE, 5)
                        pyxel.line(tx*TILE, ty*TILE, (tx+1)*TILE-1, ty*TILE, 6)

            # Projektile und Tanks zeichnen
            for b in self.bullets:
                b.draw()
            self.tank1.draw()
            self.tank2.draw()

            # HUD: HP-Balken und Punkte
            pyxel.text(2, 2, "S1", 11)
            self.tank1.draw_hp(12, 2)

            score_txt = str(self.score1) + " : " + str(self.score2)
            pyxel.text(WIDTH//2 - len(score_txt)*2, 2, score_txt, 7)

            pyxel.text(WIDTH - 28, 2, "S2", 9)
            self.tank2.draw_hp(WIDTH - 20, 2)

        elif self.state == "gameover":
            msg = self.winner + " GEWINNT!"
            pyxel.text(WIDTH//2 - len(msg)*2, 48, msg, 10)
            score_txt = "Score: " + str(self.score1) + " : " + str(self.score2)
            pyxel.text(WIDTH//2 - len(score_txt)*2, 62, score_txt, 7)
            pyxel.text(26, 78, "ENTER = Weiter    Q = Beenden", 6)

    def run(self):
        pyxel.run(self.update, self.draw)


App().run()