Flappy Bird AI开发问题:鸟扇动过快且下落时不旋转
问题修复方案
问题1:翅膀扇动过快
原因
bird_animation函数被两处重复调用:定时器事件触发一次,draw_window每帧又调用一次,导致图片切换频率翻倍。bird_animation同时负责切换索引和绘制,逻辑耦合引发重复绘制行为。
修复步骤
- 拆分
bird_animation功能:仅保留切换图片索引的逻辑,移除绘制代码。 - 移除定时器事件中的
bird.bird_animation(win)调用,仅在定时器触发时切换索引。 - 在
draw_window中根据当前索引绘制对应图片。
问题2:鸟下落时不旋转
原因
pygame.transform.rotozoom生成旋转后的新表面,但未保存该表面,也未用于绘制,相当于无效调用。move函数中self.bird_movement = 8是错误赋值,应改为累加重力(self.bird_movement += self.gravity),否则下落速度固定,旋转角度无法动态变化。- 未将旋转后的表面与矩形位置关联,绘制时仍使用原图片。
修复步骤
- 在Bird类中新增
rotated_img属性,保存旋转后的表面。 - 修改
move函数:移除错误的固定赋值,正确累加重力;计算动态旋转角度,生成并保存旋转后的表面;更新矩形位置以匹配旋转后的表面中心。 - 绘制时使用
rotated_img代替原图片。
完整修复后的代码
import pygame import neat import time import os import random import sys pygame.init() clock = pygame.time.Clock() # 屏幕尺寸变量 screen_width = 500 screen_height = 800 # 游戏图片资源 bird_imgs = [pygame.transform.scale2x(pygame.image.load(os.path.join('assets', 'yellowbird-upflap.png'))), pygame.transform.scale2x(pygame.image.load(os.path.join('assets', 'yellowbird-midflap.png'))), pygame.transform.scale2x(pygame.image.load(os.path.join('assets', 'yellowbird-downflap.png')))] bg_img = pygame.transform.scale2x(pygame.image.load(os.path.join('assets', 'background-day.png'))) # 鸟翅膀扇动定时器事件 birdflap = pygame.USEREVENT pygame.time.set_timer(birdflap, 200) class Bird: img = bird_imgs gravity = 0.25 max_rotation = 20 # 最大向上旋转角度 rotation_vel = 3 # 旋转速度 def __init__(self, x, y): self.x = x self.y = y self.bird_movement = 0 self.bird_index = 0 self.tilt = 0 # 当前倾斜角度 self.bird_rect = self.img[self.bird_index].get_rect(center=(self.x, self.y)) self.rotated_img = self.img[self.bird_index] # 保存旋转后的图片 def bird_animation(self): # 仅切换图片索引,不负责绘制 if self.bird_index < 2: self.bird_index += 1 else: self.bird_index = 0 def move(self): # 正确累加重力,模拟下落加速 self.bird_movement += self.gravity self.bird_rect.centery += self.bird_movement # 动态计算倾斜角度:上升时向上转,下落时向下转 if self.bird_movement < 0: self.tilt = min(self.tilt + self.rotation_vel, self.max_rotation) else: self.tilt = max(self.tilt - self.rotation_vel, -90) # 下落时最多向下转90度 # 生成旋转后的图片,并更新矩形位置保持中心不变 self.rotated_img = pygame.transform.rotozoom(self.img[self.bird_index], self.tilt, 1) self.bird_rect = self.rotated_img.get_rect(center=self.bird_rect.center) # 绘制窗口函数 def draw_window(win, bird): win.blit(bg_img, (0,0)) # 绘制旋转后的鸟图片 win.blit(bird.rotated_img, bird.bird_rect) pygame.display.update() # 游戏主函数 def main(): win = pygame.display.set_mode((screen_width, screen_height)) bird = Bird(200, 200) run = True while run: clock.tick(60) # 帧率控制放在循环内,确保生效 for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == birdflap: bird.bird_animation() # 仅切换图片索引 bird.move() draw_window(win, bird) pygame.quit() sys.exit() main()
额外优化说明
- 新增
max_rotation和rotation_vel控制旋转幅度与速度,让动画更贴近原版游戏效果。 - 将
clock.tick(60)移到主循环内部,确保帧率控制生效,避免游戏速度不稳定。 - 旋转后重新计算矩形位置,保证鸟的碰撞检测与显示位置一致。
内容的提问来源于stack exchange,提问作者Alec Smith
相关产品推荐
相关产品推荐

