import pygame
import sys
import random

pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("搭积木模拟器 – More Blocks + Mouse Wheel")
clock = pygame.time.Clock()
FPS = 60

# ==================== COLOURS ====================
WHITE        = (255,255,255)
BLACK        = (0,0,0)
GRAY         = (180,180,180)
GROUND_COLOR = (100,60,20)

PALETTE = [
    (220,60,60),    # red
    (60,180,60),    # green
    (60,100,220),   # blue
    (240,180,50),   # orange
    (160,50,160),   # purple
    (240,120,80),   # coral
    (100,200,200),  # cyan
    (255,120,200),  # pink
]

# ==================== SHAPES ====================
SHAPE_DEFS = {
    'Square':      [(-30,-30,60,60)],
    'Tall':        [(-20,-45,40,90)],
    'Wide':        [(-45,-20,90,40)],
    'Triangle':    [(-30,-30,60,60)],
    'L-Shape':     [(-30,-30,30,90), (0,20,30,30)],
    'J-Shape':     [(0,-30,30,90), (-30,20,30,30)],
    'T-Shape':     [(-30,-30,90,30), (0,0,30,30)],
    'S-Shape':     [(-30,-30,60,30), (0,0,60,30)],
    'Z-Shape':     [(0,-30,60,30), (-30,0,60,30)],
    'Cross':       [(-15,-45,30,90), (-45,-15,90,30)],
    'Circle':      [(-30,-30,60,60)],
}

SHAPE_NAMES = list(SHAPE_DEFS.keys())

# ==================== PHYSICS ====================
GRAVITY = 0.8
GROUND_Y = HEIGHT - 60

# ==================== BLOCK CLASS ====================
class Block:
    def __init__(self, x, y, shape_name, color):
        self.shape_name = shape_name
        self.color = color
        self.x = x
        self.y = y
        self.vy = 0.0
        self.landed = False

        self.sub_rects = SHAPE_DEFS[shape_name]
        min_x = min(r[0] for r in self.sub_rects)
        min_y = min(r[1] for r in self.sub_rects)
        max_x = max(r[0] + r[2] for r in self.sub_rects)
        max_y = max(r[1] + r[3] for r in self.sub_rects)
        self.bbox_w = max_x - min_x
        self.bbox_h = max_y - min_y
        self.bbox_off_x = min_x
        self.bbox_off_y = min_y

    def rect(self):
        left = self.x + self.bbox_off_x
        top = self.y + self.bbox_off_y
        return pygame.Rect(left, top, self.bbox_w, self.bbox_h)

    def update(self, blocks):
        if self.landed:
            return
        self.vy += GRAVITY
        new_y = self.y + self.vy

        if new_y + self.bbox_off_y + self.bbox_h >= GROUND_Y:
            self.y = GROUND_Y - self.bbox_h - self.bbox_off_y
            self.vy = 0
            self.landed = True
            return

        temp_rect = self.rect().copy()
        temp_rect.y = int(new_y + self.bbox_off_y)
        for other in blocks:
            if other is self or not other.landed:
                continue
            if temp_rect.colliderect(other.rect()):
                self.y = other.rect().top - self.bbox_h - self.bbox_off_y
                self.vy = 0
                self.landed = True
                return

        self.y = new_y

    def draw(self, surface):
        for r in self.sub_rects:
            x = self.x + r[0]
            y = self.y + r[1]
            w = r[2]
            h = r[3]
            rect = pygame.Rect(x, y, w, h)
            if self.shape_name == 'Triangle':
                x1, y1 = self.x, self.y - 30
                x2, y2 = self.x - 30, self.y + 30
                x3, y3 = self.x + 30, self.y + 30
                pygame.draw.polygon(surface, self.color, [(x1,y1), (x2,y2), (x3,y3)])
                pygame.draw.polygon(surface, BLACK, [(x1,y1), (x2,y2), (x3,y3)], 2)
                break
            elif self.shape_name == 'Circle':
                pygame.draw.ellipse(surface, self.color, rect)
                pygame.draw.ellipse(surface, BLACK, rect, 2)
            else:
                pygame.draw.rect(surface, self.color, rect)
                pygame.draw.rect(surface, BLACK, rect, 2)

# ==================== GAME CLASS ====================
class Game:
    def __init__(self):
        self.blocks = []
        self.current_shape = 'Square'
        self.current_color_idx = 0
        self.font = pygame.font.Font(None, 28)

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit(); sys.exit()

            # ★ 新增鼠标滚轮切换形状 ★
            if event.type == pygame.MOUSEWHEEL:
                idx = SHAPE_NAMES.index(self.current_shape)
                if event.y > 0:         # 向上滚动 → 下一个形状
                    idx = (idx + 1) % len(SHAPE_NAMES)
                elif event.y < 0:       # 向下滚动 → 上一个形状
                    idx = (idx - 1) % len(SHAPE_NAMES)
                self.current_shape = SHAPE_NAMES[idx]

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit(); sys.exit()
                if event.key == pygame.K_r:            # 保留键盘 R 键（向前切换）
                    idx = SHAPE_NAMES.index(self.current_shape)
                    idx = (idx + 1) % len(SHAPE_NAMES)
                    self.current_shape = SHAPE_NAMES[idx]
                if event.key == pygame.K_SPACE:        # 随机形状
                    self.current_shape = SHAPE_NAMES[random.randint(0, len(SHAPE_NAMES)-1)]
                if event.key == pygame.K_c:            # 切换颜色
                    self.current_color_idx = (self.current_color_idx + 1) % len(PALETTE)

            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:   # 左键丢方块
                    mouse_x, _ = event.pos
                    color = PALETTE[self.current_color_idx]
                    block = Block(mouse_x, -50, self.current_shape, color)
                    self.blocks.append(block)
                elif event.button == 3: # 右键移除方块
                    mouse_x, mouse_y = event.pos
                    for block in reversed(self.blocks):
                        if block.rect().collidepoint(mouse_x, mouse_y):
                            self.blocks.remove(block)
                            break

    def update(self):
        for block in self.blocks:
            block.update(self.blocks)

    def draw(self):
        screen.fill((135, 206, 235))
        ground_rect = pygame.Rect(0, GROUND_Y, WIDTH, HEIGHT - GROUND_Y)
        pygame.draw.rect(screen, GROUND_COLOR, ground_rect)
        pygame.draw.line(screen, BLACK, (0, GROUND_Y), (WIDTH, GROUND_Y), 3)

        for block in self.blocks:
            block.draw(screen)

        # UI
        shape_text = self.font.render(f"Shape: {self.current_shape} (R/Wheel/Space)", True, WHITE)
        screen.blit(shape_text, (10, 10))
        col_text = self.font.render("Colour: C | Left=drop | Right=remove", True, WHITE)
        screen.blit(col_text, (10, 35))

        # Preview
        mouse_x, mouse_y = pygame.mouse.get_pos()
        if mouse_y < GROUND_Y - 30:
            preview_color = PALETTE[self.current_color_idx]
            preview_surf = pygame.Surface((120, 120), pygame.SRCALPHA)
            preview_surf.fill((0,0,0,0))
            cx, cy = 60, 60
            for r in SHAPE_DEFS[self.current_shape]:
                x = cx + r[0]
                y = cy + r[1]
                w = r[2]
                h = r[3]
                rect = pygame.Rect(x, y, w, h)
                if self.current_shape == 'Triangle':
                    x1, y1 = cx, cy-30
                    x2, y2 = cx-30, cy+30
                    x3, y3 = cx+30, cy+30
                    pygame.draw.polygon(preview_surf, (*preview_color, 180), [(x1,y1), (x2,y2), (x3,y3)])
                    break
                elif self.current_shape == 'Circle':
                    pygame.draw.ellipse(preview_surf, (*preview_color, 180), rect)
                else:
                    pygame.draw.rect(preview_surf, (*preview_color, 180), rect)
            screen.blit(preview_surf, (mouse_x - 60, mouse_y - 60))

        pygame.display.flip()

    def run(self):
        while True:
            dt = clock.tick(FPS)
            self.handle_events()
            self.update()
            self.draw()

if __name__ == "__main__":
    game = Game()
    game.run()