import pygame
import random
import sys

# 初始化
pygame.init()
W, H = 900, 600
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("植物大战僵尸 - 加强版")
clock = pygame.time.Clock()
FPS = 60

# 颜色
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
BROWN = (139,69,19)
BLACK = 0,0,0
WHITE = 255,255,255
GRAY = 100,100,100
CYAN = 0,255,255

# 网格
ROWS = 5
COLS = 9
CELL = 80
grid_x = 120
grid_y = 100

# 全局
sun_points = 100
selected = None
plants = []
zombies = []
bullets = []
suns = []
game_over = False

# 冷却
cd = {"peashooter":0, "sunflower":0, "wallnut":0, "icepea":0}
MAX_CD = 60

# 阳光
class Sun:
    def __init__(self,x,y,auto=False):
        self.x = x
        self.y = y
        self.vy = 1 if not auto else 0
        self.timer = 0
        self.rect = pygame.Rect(x-10,y-10,20,20)

    def update(self):
        self.y += self.vy
        self.timer += 1
        self.rect.center = (self.x,self.y)

    def draw(self):
        pygame.draw.circle(screen,YELLOW,(self.x,self.y),10)

# 子弹
class Bullet:
    def __init__(self,x,y,ice=False):
        self.x = x
        self.y = y
        self.speed = 6
        self.ice = ice
        self.rect = pygame.Rect(x,y,10,10)

    def update(self):
        self.x += self.speed
        self.rect.center = (self.x,self.y)

    def draw(self):
        c = CYAN if self.ice else BLUE
        pygame.draw.circle(screen,c,(self.x,self.y),5)

# 豌豆射手
class PeaShooter:
    cost = 50
    def __init__(self,r,c):
        self.r = r
        self.c = c
        self.x = grid_x + c*CELL + 40
        self.y = grid_y + r*CELL + 40
        self.hp = 100
        self.t = 0

    def update(self):
        self.t +=1
        if self.t >= 60:
            bullets.append(Bullet(self.x,self.y))
            self.t=0

    def draw(self):
        pygame.draw.circle(screen,GREEN,(self.x,self.y),25)
        pygame.draw.rect(screen,BROWN,(self.x-5,self.y+20,10,15))

# 向日葵
class Sunflower:
    cost = 25
    def __init__(self,r,c):
        self.r = r
        self.c = c
        self.x = grid_x + c*CELL +40
        self.y = grid_y + r*CELL +40
        self.hp = 100
        self.t = 0

    def update(self):
        self.t +=1
        if self.t >= 240:
            suns.append(Sun(self.x,self.y,auto=True))
            self.t=0

    def draw(self):
        pygame.draw.circle(screen,(255,200,0),(self.x,self.y),25)
        pygame.draw.rect(screen,BROWN,(self.x-5,self.y+20,10,15))

# 坚果
class Wallnut:
    cost = 75
    def __init__(self,r,c):
        self.r = r
        self.c = c
        self.x = grid_x + c*CELL +40
        self.y = grid_y + r*CELL +40
        self.hp = 300

    def draw(self):
        pygame.draw.circle(screen,(139,117,56),(self.x,self.y),30)

# 寒冰射手
class IcePea:
    cost = 75
    def __init__(self,r,c):
        self.r = r
        self.c = c
        self.x = grid_x + c*CELL +40
        self.y = grid_y + r*CELL +40
        self.hp = 100
        self.t = 0

    def update(self):
        self.t +=1
        if self.t >= 60:
            bullets.append(Bullet(self.x,self.y,ice=True))
            self.t=0

    def draw(self):
        pygame.draw.circle(screen,CYAN,(self.x,self.y),25)

# 僵尸
class Zombie:
    def __init__(self,row,strong=False):
        self.r = row
        self.x = W
        self.y = grid_y + row*CELL +40
        self.speed = 0.4
        self.hp = 100 if not strong else 200
        self.ice = False
        self.rect = pygame.Rect(0,0,50,50)

    def update(self):
        sp = self.speed*0.5 if self.ice else self.speed
        self.x -= sp
        self.rect.center = (self.x,self.y)

    def draw(self):
        color = RED if self.hp>50 else (200,0,0)
        pygame.draw.circle(screen,color,(self.x,self.y),25)
        if self.hp>=200:
            pygame.draw.rect(screen,(150,100,0),(self.x-15,self.y-35,30,20))

# 背景
def draw_bg():
    screen.fill((40,120,40))
    for r in range(ROWS):
        for c in range(COLS):
            x = grid_x + c*CELL
            y = grid_y + r*CELL
            pygame.draw.rect(screen,(60,140,60),(x,y,CELL-2,CELL-2),2)

# UI
def draw_ui():
    pygame.draw.rect(screen,(80,80,80),(0,0,W,80))
    font = pygame.font.Font(None,40)
    screen.blit(font.render(f"阳光: {sun_points}",True,YELLOW),(20,20))

    cards = [
        ("peashooter",GREEN,50,150),
        ("sunflower",(255,200,0),25,230),
        ("wallnut",(139,117,56),75,310),
        ("icepea",CYAN,75,390)
    ]

    for name,col,cost,x in cards:
        pygame.draw.rect(screen,WHITE,(x,10,70,60),2)
        pygame.draw.circle(screen,col,(x+35,40),20)
        screen.blit(font.render(str(cost),True,YELLOW),(x+25,45))
        if cd[name]>0:
            pygame.draw.rect(screen,(0,0,0,128),(x,10,70,60))

# 主逻辑
def main():
    global sun_points, selected, game_over
    spawn_zombie = 0
    spawn_sun = 0

    while True:
        clock.tick(FPS)
        if game_over:
            f = pygame.font.Font(None,100)
            screen.blit(f.render("游戏结束",True,RED),(300,250))
            pygame.display.flip()
            for e in pygame.event.get():
                if e.type == pygame.QUIT:pygame.quit();sys.exit()
            continue

        draw_bg()
        draw_ui()

        # 冷却
        for k in cd:
            if cd[k]>0:cd[k]-=1

        # 事件
        for e in pygame.event.get():
            if e.type == pygame.QUIT:pygame.quit();sys.exit()
            if e.type == pygame.MOUSEBUTTONDOWN:
                mx,my = pygame.mouse.get_pos()
                # 收集阳光
                for s in suns[:]:
                    if s.rect.collidepoint(mx,my):
                        suns.remove(s)
                        sun_points +=25
                # 选卡
                if 150<mx<220 and 10<70: selected="peashooter"
                if 230<mx<300 and 10<70: selected="sunflower"
                if 310<mx<380 and 10<70: selected="wallnut"
                if 390<mx<460 and 10<70: selected="icepea"
                # 种植
                c = (mx - grid_x)//CELL
                r = (my - grid_y)//CELL
                if 0<=r<ROWS and 0<=c<COLS and selected:
                    if cd[selected]>0:continue
                    occupied = any(p.r==r and p.c==c for p in plants)
                    if occupied:continue
                    # 种
                    if selected=="peashooter" and sun_points>=50:
                        plants.append(PeaShooter(r,c));sun_points-=50;cd[selected]=MAX_CD
                    if selected=="sunflower" and sun_points>=25:
                        plants.append(Sunflower(r,c));sun_points-=25;cd[selected]=MAX_CD
                    if selected=="wallnut" and sun_points>=75:
                        plants.append(Wallnut(r,c));sun_points-=75;cd[selected]=MAX_CD
                    if selected=="icepea" and sun_points>=75:
                        plants.append(IcePea(r,c));sun_points-=75;cd[selected]=MAX_CD
                    selected = None

        # 阳光生成
        spawn_sun +=1
        if spawn_sun >= 180:
            x = random.randint(grid_x, grid_x+COLS*CELL)
            suns.append(Sun(x,0))
            spawn_sun=0

        # 僵尸生成
        spawn_zombie +=1
        if spawn_zombie >= (240 if len(zombies)<3 else 120):
            zombies.append(Zombie(random.randint(0,4), strong=random.random()>0.6))
            spawn_zombie=0

        # 更新
        for s in suns[:]:
            s.update()
            if s.timer>300:suns.remove(s)
        for p in plants:
            p.update()
        for b in bullets[:]:
            b.update()
            if b.x>W:bullets.remove(b)
        for z in zombies[:]:
            z.update()
            if z.x < grid_x:game_over=True

        # 子弹打僵尸
        for b in bullets[:]:
            for z in zombies[:]:
                if b.rect.colliderect(z.rect):
                    z.hp -=25
                    if b.ice:z.ice=True
                    if b in bullets:bullets.remove(b)
                    if z.hp<=0 and z in zombies:zombies.remove(z)

        # 僵尸吃植物
        for z in zombies:
            for p in plants[:]:
                if z.r == p.r and abs(z.x - p.x)<50:
                    p.hp -=0.3
                    if p.hp<=0:plants.remove(p)

        # 绘制
        for s in suns:s.draw()
        for p in plants:p.draw()
        for b in bullets:b.draw()
        for z in zombies:z.draw()

        pygame.display.flip()

if __name__=="__main__":
    main()