import pygame
import random
import sys

pygame.init()

# 窗口设置
WIDTH, HEIGHT = 900, 650
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("目标练习 - 反应速度训练")
clock = pygame.time.Clock()

# 中文字体兼容
try:
    font_big = pygame.font.Font("C:/Windows/Fonts/simhei.ttf", 42)
    font_mid = pygame.font.Font("C:/Windows/Fonts/simhei.ttf", 28)
    font_small = pygame.font.Font("C:/Windows/Fonts/simhei.ttf", 20)
except:
    font_big = pygame.font.SysFont("microsoftyahei", 42)
    font_mid = pygame.font.SysFont("microsoftyahei", 28)
    font_small = pygame.font.SysFont("microsoftyahei", 20)

# 游戏常量
GAME_DURATION = 30  # 单局时长（秒）
INIT_RADIUS = 40    # 初始目标半径
MIN_RADIUS = 15     # 最小目标半径
BG_COLOR = (240, 248, 255)
BAR_COLOR = (220, 230, 240)

# 游戏状态
STATE_MENU = 0
STATE_PLAYING = 1
STATE_OVER = 2

class TargetGame:
    def __init__(self):
        self.state = STATE_MENU
        self.score = 0
        self.total_clicks = 0
        self.hit_count = 0
        self.high_score = 0
        self.time_left = GAME_DURATION
        self.start_ticks = 0
        
        # 目标属性
        self.target_radius = INIT_RADIUS
        self.target_pos = (WIDTH//2, HEIGHT//2)
        self.target_color = (231, 76, 60)
        self.target_spawn_time = 0
        
        # 反应时间统计
        self.reaction_times = []
        
        # 点击特效列表
        self.effects = []

    def spawn_target(self):
        """生成新目标"""
        margin = self.target_radius + 20
        self.target_pos = (
            random.randint(margin, WIDTH - margin),
            random.randint(100 + margin, HEIGHT - margin)
        )
        self.target_color = (
            random.randint(200, 255),
            random.randint(50, 150),
            random.randint(50, 150)
        )
        self.target_spawn_time = pygame.time.get_ticks()
        
        # 难度递增：每得5分，目标缩小2像素
        shrink = (self.score // 5) * 2
        self.target_radius = max(MIN_RADIUS, INIT_RADIUS - shrink)

    def handle_click(self, pos):
        """处理鼠标点击"""
        if self.state != STATE_PLAYING:
            return
        
        self.total_clicks += 1
        mx, my = pos
        dx = mx - self.target_pos[0]
        dy = my - self.target_pos[1]
        distance = (dx**2 + dy**2) ** 0.5
        
        if distance <= self.target_radius:
            # 命中
            self.hit_count += 1
            self.score += 1
            # 记录反应时间（毫秒）
            react = pygame.time.get_ticks() - self.target_spawn_time
            self.reaction_times.append(react)
            # 添加点击特效
            self.effects.append([mx, my, self.target_radius, 255])
            self.spawn_target()
        else:
            # 未命中也添加特效
            self.effects.append([mx, my, 20, 180])

    def update_effects(self):
        """更新点击特效"""
        for e in self.effects[:]:
            e[2] += 2   # 半径扩大
            e[3] -= 8   # 透明度降低
            if e[3] <= 0:
                self.effects.remove(e)

    def update(self):
        """游戏主更新"""
        if self.state == STATE_PLAYING:
            elapsed = (pygame.time.get_ticks() - self.start_ticks) // 1000
            self.time_left = max(0, GAME_DURATION - elapsed)
            
            if self.time_left == 0:
                self.state = STATE_OVER
                if self.score > self.high_score:
                    self.high_score = self.score
        
        self.update_effects()

    def draw(self):
        """绘制画面"""
        screen.fill(BG_COLOR)
        
        # 顶部信息栏
        pygame.draw.rect(screen, BAR_COLOR, (0, 0, WIDTH, 90))
        pygame.draw.line(screen, (180, 190, 200), (0, 90), (WIDTH, 90), 2)
        
        # 顶部数据
        score_text = font_mid.render(f"得分: {self.score}", True, (44, 62, 80))
        time_text = font_mid.render(f"时间: {self.time_left}s", True, (231, 76, 60))
        high_text = font_small.render(f"最高分: {self.high_score}", True, (100, 120, 140))
        
        screen.blit(score_text, (30, 25))
        screen.blit(time_text, (WIDTH//2 - 70, 25))
        screen.blit(high_text, (WIDTH - 150, 35))
        
        if self.state == STATE_MENU:
            # 开始界面
            title = font_big.render("🎯 目标反应训练", True, (44, 62, 80))
            tip1 = font_mid.render("点击随机出现的圆点，测试你的反应速度", True, (80, 100, 120))
            tip2 = font_mid.render("按 空格键 开始游戏", True, (52, 73, 94))
            tip3 = font_small.render(f"单局时长 {GAME_DURATION} 秒 · 目标会逐渐缩小", True, (120, 140, 160))
            
            screen.blit(title, (WIDTH//2 - title.get_width()//2, HEIGHT//2 - 100))
            screen.blit(tip1, (WIDTH//2 - tip1.get_width()//2, HEIGHT//2 - 20))
            screen.blit(tip2, (WIDTH//2 - tip2.get_width()//2, HEIGHT//2 + 50))
            screen.blit(tip3, (WIDTH//2 - tip3.get_width()//2, HEIGHT//2 + 100))
        
        elif self.state == STATE_PLAYING:
            # 绘制目标
            pygame.draw.circle(screen, self.target_color, self.target_pos, self.target_radius)
            pygame.draw.circle(screen, (255,255,255), self.target_pos, self.target_radius//3)
            
            # 绘制点击特效
            for x, y, r, alpha in self.effects:
                s = pygame.Surface((r*2, r*2), pygame.SRCALPHA)
                pygame.draw.circle(s, (255, 255, 255, alpha), (r, r), r, 2)
                screen.blit(s, (x - r, y - r))
        
        elif self.state == STATE_OVER:
            # 结算界面
            title = font_big.render("游戏结束", True, (44, 62, 80))
            screen.blit(title, (WIDTH//2 - title.get_width()//2, 140))
            
            # 计算统计数据
            hit_rate = (self.hit_count / self.total_clicks * 100) if self.total_clicks > 0 else 0
            avg_react = sum(self.reaction_times)/len(self.reaction_times) if self.reaction_times else 0
            
            stats = [
                f"最终得分: {self.score} 个目标",
                f"总点击数: {self.total_clicks} 次",
                f"命中率: {hit_rate:.1f}%",
                f"平均反应时间: {avg_react:.0f} 毫秒"
            ]
            
            for i, line in enumerate(stats):
                text = font_mid.render(line, True, (52, 73, 94))
                screen.blit(text, (WIDTH//2 - text.get_width()//2, 220 + i * 50))
            
            tip = font_small.render("按 空格键 再来一局", True, (120, 140, 160))
            screen.blit(tip, (WIDTH//2 - tip.get_width()//2, HEIGHT - 80))
        
        pygame.display.flip()

    def start_game(self):
        """开始新一局"""
        self.state = STATE_PLAYING
        self.score = 0
        self.total_clicks = 0
        self.hit_count = 0
        self.reaction_times.clear()
        self.effects.clear()
        self.target_radius = INIT_RADIUS
        self.start_ticks = pygame.time.get_ticks()
        self.spawn_target()

def main():
    game = TargetGame()
    running = True
    
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                game.handle_click(event.pos)
            
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    if game.state in (STATE_MENU, STATE_OVER):
                        game.start_game()
        
        game.update()
        game.draw()
        clock.tick(60)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()