You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pygame开发点击圆圈游戏偶发卡顿、无法生成新位置问题求助

Pygame点击圆圈游戏问题修复方案

一、问题根因

无法生成新点位

  1. 点位生成逻辑只有50%触发概率:deletewhat = [True, False]随机取值为False时,不会生成新点位
  2. 无点位重置逻辑:旧点位被点击后spot1ready/spot2ready被设为False,没有机制重置状态或替换旧点位对象,点击完成后就没有可交互的新点位
  3. 无初始点位生成逻辑:进入游戏界面后需要等待最长1秒定时器触发才会首次生成点位,容易被误判为不生成点位

卡顿严重

  1. 无帧率控制:主循环无限制运行,CPU占用极高,长时间运行必然卡顿
  2. 大量低效的try-except逻辑:通过捕获NameError判断变量是否存在,运行开销远高于直接初始化变量后做判断
  3. 不必要的重复渲染:每帧都重新生成分数文本,只有分数变化时才需要重新渲染

二、修复后代码

import pygame
from pygame.font import SysFont
from pygame.display import flip
from random import randint, choice

# 状态变量
r = True
title = True
game = False

# 游戏数值
points = 0
# 调整点位生成概率为70%
refresh_prob = [True, True, False]
pointchoice = [1,1,1,2]

# 点位变量初始化,避免NameError
spot1 = None
spot2 = None
spot1_ready = False
spot2_ready = False

# 颜色定义
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (255,0,0)
YELLOW = (255,255,0)
GRAY = (20,20,20)

# Pygame初始化
pygame.init()
pygame.font.init()

# 自定义事件
refresh_spot = pygame.USEREVENT
# 每1.5秒刷新一次点位,频率更合理
pygame.time.set_timer(refresh_spot, 1500)

# 字体定义
titlefont = SysFont("Arial", 70)
headfont = SysFont("Arial", 20)
startfont = SysFont("Arial", 80)
pointsfont = SysFont("Arial", 25)

# 预渲染固定文本
titletext = titlefont.render("The Spot Spotter", False, BLACK)
headtext = headfont.render("Click the spots and earn points!", False, BLACK)
starttext = startfont.render("START", False, RED)
# 初始化分数文本
pointstext = pointsfont.render(f"Points: {points}", False, BLACK)

screen = pygame.display.set_mode((900,750))
# 帧率控制器
clock = pygame.time.Clock()

class Spot:
    def __init__(self, x, y, points):
        self.x = x
        self.y = y
        self.points = points
        self.spotcolor = WHITE if self.points == 1 else GRAY
        # 用pygame自带Rect做碰撞检测,更简单准确
        self.rect = pygame.Rect(x, y, 50, 50)

    def draw(self):
        pygame.draw.ellipse(screen, self.spotcolor, self.rect)

    def get_points(self):
        return self.points

while r:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            r = False
        # 点位刷新事件
        if event.type == refresh_spot and game:
            do_refresh = choice(refresh_prob)
            if do_refresh:
                # 生成新点位,替换旧点位
                spot1 = Spot(randint(20, 830), randint(20, 550), choice(pointchoice))
                spot1_ready = True
                spot2 = Spot(randint(20, 830), randint(20, 550), choice(pointchoice))
                spot2_ready = True
        # 鼠标点击事件
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouse_pos = pygame.mouse.get_pos()
            # 开始按钮点击判断
            if title:
                start_rect = pygame.Rect(200, 300, 550, 125)
                if start_rect.collidepoint(mouse_pos):
                    title = False
                    game = True
                    # 进入游戏立刻生成初始点位
                    spot1 = Spot(randint(20, 830), randint(20, 550), choice(pointchoice))
                    spot1_ready = True
                    spot2 = Spot(randint(20, 830), randint(20, 550), choice(pointchoice))
                    spot2_ready = True
            # 点位点击判断
            else:
                if spot1_ready and spot1.rect.collidepoint(mouse_pos):
                    spot1_ready = False
                    points += spot1.get_points()
                    # 分数变化时重新渲染分数文本
                    pointstext = pointsfont.render(f"Points: {points}", False, BLACK)
                if spot2_ready and spot2.rect.collidepoint(mouse_pos):
                    spot2_ready = False
                    points += spot2.get_points()
                    pointstext = pointsfont.render(f"Points: {points}", False, BLACK)

    # 标题页渲染
    if title:
        screen.fill(WHITE)
        screen.blit(titletext, (250, 0))
        screen.blit(headtext, (350, 100))
        pygame.draw.rect(screen, YELLOW, (200, 300, 550, 125))
        screen.blit(starttext, (375, 315))
        flip()
    # 游戏页渲染
    elif game:
        screen.fill(BLACK)
        pygame.draw.rect(screen, WHITE, (0, 600, 900, 150))
        screen.blit(pointstext, (20, 610))
        if spot1_ready:
            spot1.draw()
        if spot2_ready:
            spot2.draw()
        flip()
    # 限制帧率为60,降低CPU占用
    clock.tick(60)

pygame.quit()

三、后续优化建议

  • 用列表存储所有点位对象,不用单独定义spot1/spot2两个变量,后续要增加点位数量时更易扩展
  • 可以加点位消失倒计时,超过时间没点击的点位自动消失,提升游戏趣味性
  • 增加不同分值点位的大小、颜色区分,降低识别成本

内容的提问来源于stack exchange,提问作者Eery Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 01:48:00