import pygame
import sys

# --- 配置常量 ---
SCREEN_WIDTH, SCREEN_HEIGHT = 800, 600
FPS = 60
GRAVITY = 0.8
JUMP_STRENGTH = -15
MOVE_SPEED = 5

# 颜色定义
COLOR_BG = (107, 140, 255)      # 经典天空蓝
COLOR_GROUND = (200, 100, 50)   # 地面棕
COLOR_BRICK = (180, 80, 40)     # 砖块红
COLOR_COIN = (255, 215, 0)      # 金币黄
COLOR_MARIO = (255, 0, 0)       # 马里奥红
COLOR_ENEMY = (139, 69, 19)     # 敌人棕

pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pygame Mario Mini Demo")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 36)

# --- 基础类 ---
class Platform(pygame.sprite.Sprite):
    def __init__(self, x, y, w, h, color=COLOR_GROUND):
        super().__init__()
        self.image = pygame.Surface((w, h))
        self.image.fill(color)
        self.rect = self.image.get_rect(topleft=(x, y))

class Coin(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((20, 20), pygame.SRCALPHA)
        pygame.draw.circle(self.image, COLOR_COIN, (10, 10), 10)
        self.rect = self.image.get_rect(center=(x, y))

class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((30, 30))
        self.image.fill(COLOR_ENEMY)
        self.rect = self.image.get_rect(topleft=(x, y))
        self.speed = 2

    def update(self, platforms):
        self.rect.x += self.speed
        # 简单的边缘检测：如果脚下没地了或者撞墙就回头
        on_ground = False
        test_rect = self.rect.copy()
        test_rect.y += 5
        for p in platforms:
            if test_rect.colliderect(p.rect):
                on_ground = True
                break
        
        # 撞墙检测
        hit_wall = False
        for p in platforms:
            if self.rect.colliderect(p.rect) and self.rect.y + self.rect.height > p.rect.y + 5:
                hit_wall = True
                break

        if not on_ground or hit_wall:
            self.speed *= -1

# --- 玩家类 ---
class Player(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((30, 40))
        self.image.fill(COLOR_MARIO)
        self.rect = self.image.get_rect(topleft=(x, y))
        
        self.vel_y = 0
        self.on_ground = False
        self.score = 0
        self.facing_right = True

    def handle_input(self):
        keys = pygame.key.get_pressed()
        self.dx = 0
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.dx = -MOVE_SPEED
            self.facing_right = False
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.dx = MOVE_SPEED
            self.facing_right = True
        if (keys[pygame.K_SPACE] or keys[pygame.K_UP] or keys[pygame.K_w]) and self.on_ground:
            self.vel_y = JUMP_STRENGTH
            self.on_ground = False

    def update(self, platforms, coins, enemies):
        self.handle_input()

        # 水平移动与碰撞
        self.rect.x += self.dx
        for p in platforms:
            if self.rect.colliderect(p.rect):
                if self.dx > 0: self.rect.right = p.rect.left
                elif self.dx < 0: self.rect.left = p.rect.right

        # 垂直移动与碰撞
        self.vel_y += GRAVITY
        self.rect.y += self.vel_y
        self.on_ground = False
        
        for p in platforms:
            if self.rect.colliderect(p.rect):
                if self.vel_y > 0:  # 下落
                    self.rect.bottom = p.rect.top
                    self.vel_y = 0
                    self.on_ground = True
                elif self.vel_y < 0:  # 顶砖块
                    self.rect.top = p.rect.bottom
                    self.vel_y = 0
                    # 如果是普通砖块，可以加个动画或消失逻辑
                    if p.color == COLOR_BRICK:
                        p.kill() 

        # 吃金币
        collected = pygame.sprite.spritecollide(self, coins, True)
        self.score += len(collected) * 100

        # 踩敌人
        for enemy in enemies:
            if self.rect.colliderect(enemy.rect):
                if self.vel_y > 0 and self.rect.bottom < enemy.rect.centery:
                    enemy.kill()
                    self.vel_y = JUMP_STRENGTH / 2  # 踩完弹起
                    self.score += 200
                else:
                    # 碰到侧面或下面 -> 死亡重置
                    self.rect.topleft = (50, 400)
                    self.vel_y = 0
                    self.score = max(0, self.score - 500)

        # 掉出屏幕重置
        if self.rect.top > SCREEN_HEIGHT:
            self.rect.topleft = (50, 400)
            self.vel_y = 0

# --- 关卡构建 ---
def create_level():
    platforms = pygame.sprite.Group()
    coins = pygame.sprite.Group()
    enemies = pygame.sprite.Group()

    # 地面
    platforms.add(Platform(0, 550, 800, 50))
    
    # 平台
    platforms.add(Platform(200, 450, 100, 20, COLOR_BRICK))
    platforms.add(Platform(400, 350, 150, 20, COLOR_BRICK))
    platforms.add(Platform(100, 300, 80, 20, COLOR_BRICK))
    platforms.add(Platform(600, 450, 100, 20, COLOR_GROUND))

    # 金币
    coins.add(Coin(250, 410))
    coins.add(Coin(470, 310))
    coins.add(Coin(140, 260))

    # 敌人
    enemies.add(Enemy(300, 520))
    enemies.add(Enemy(620, 420))

    return platforms, coins, enemies

# --- 主循环 ---
def main():
    player = Player(50, 400)
    platforms, coins, enemies = create_level()
    all_sprites = pygame.sprite.Group(player, platforms, coins, enemies)

    while True:
        dt = clock.tick(FPS) / 1000.0
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit(); sys.exit()
            if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
                # 按 R 重置关卡
                player.__init__(50, 400)
                platforms.empty(); coins.empty(); enemies.empty()
                platforms, coins, enemies = create_level()
                all_sprites.empty()
                all_sprites.add(player, platforms, coins, enemies)

        # 更新
        enemies.update(platforms)
        player.update(platforms, coins, enemies)
        
        # 绘制
        screen.fill(COLOR_BG)
        all_sprites.draw(screen)
        
        # UI
        score_text = font.render(f"Score: {player.score}", True, (255, 255, 255))
        hint_text = font.render("R: Reset | Space: Jump", True, (255, 255, 255))
        screen.blit(score_text, (10, 10))
        screen.blit(hint_text, (SCREEN_WIDTH - 300, 10))

        pygame.display.flip()

if __name__ == "__main__":
    main()