Pygame开发点击圆圈游戏偶发卡顿、无法生成新位置问题求助
Pygame点击圆圈游戏问题修复方案
一、问题根因
无法生成新点位
- 点位生成逻辑只有50%触发概率:
deletewhat = [True, False]随机取值为False时,不会生成新点位 - 无点位重置逻辑:旧点位被点击后
spot1ready/spot2ready被设为False,没有机制重置状态或替换旧点位对象,点击完成后就没有可交互的新点位 - 无初始点位生成逻辑:进入游戏界面后需要等待最长1秒定时器触发才会首次生成点位,容易被误判为不生成点位
卡顿严重
- 无帧率控制:主循环无限制运行,CPU占用极高,长时间运行必然卡顿
- 大量低效的
try-except逻辑:通过捕获NameError判断变量是否存在,运行开销远高于直接初始化变量后做判断 - 不必要的重复渲染:每帧都重新生成分数文本,只有分数变化时才需要重新渲染
二、修复后代码
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
相关产品推荐
相关产品推荐

