为何我的Pygame障碍物精灵(小行星)无法在屏幕上显示?
问题:小行星精灵无法显示并下落
我希望作为障碍物的小行星精灵从屏幕顶部下落至底部,但精灵始终无法在屏幕上显示,还未添加小行星碰撞、重力相关的代码。曾尝试使用Sprite类,但觉得过于复杂,因此未采用,代码如下:
from sys import exit from random import randint def animation_state(): global player_surface, player_index, player_rect player_index += 0.15 if player_index >= len(player_right_walk): player_index = 0 if LEFT == True: player_surface = player_left_walk[int(player_index)] elif RIGHT == True: player_surface = player_right_walk[int(player_index)] if LEFT == False and RIGHT == False: player_surface = pygame.image.load('graphics/dino_idle_right.png').convert_alpha() if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT: player_surface = pygame.image.load('graphics/dino_idle_left.png').convert_alpha() elif event.key == pygame.K_RIGHT: player_surface = pygame.image.load('graphics/dino_idle_right.png').convert_alpha() screen.blit(player_surface,player_rect) def player_control(): global LEFT, RIGHT player_velocity = 0 player_gravity = 0 player_gravity += 3 player_rect.y += player_gravity if player_rect.bottom >= 500: player_rect.bottom = 500 keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: player_velocity -= 6 LEFT = True RIGHT = False if player_rect.x < -50: player_rect.x = 800 elif keys[pygame.K_RIGHT]: player_velocity += 6 LEFT = False RIGHT = True if player_rect.x > 800: player_rect.x = -50 if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT or pygame.K_RIGHT: player_velocity = 0 player_rect.x += player_velocity def display_score(): current_time = int(pygame.time.get_ticks() / 1000) - start_time score_surface = font.render('Score: ' + str(current_time),False,(64,64,64)) score_rect = score_surface.get_rect(center = (375, 30)) screen.blit(score_surface, score_rect) return current_time def game_over_screen(): player_stand = pygame.image.load('graphics/dino_stand.png').convert_alpha() player_stand = pygame.transform.rotozoom(player_stand,0,4).convert_alpha() player_stand_rect = player_stand.get_rect(center = (375,280)) game_name = font.render('Personal Project Game', False, (111,196,169)) game_name_rect = game_name.get_rect(center = (375,100)) game_message = font.render('Press Space to start',False, 'Black') game_message_rect = game_message.get_rect(center = (375, 500)) screen.blit(background_surface,(0,0)) screen.blit(player_stand,player_stand_rect) screen.blit(game_name,game_name_rect) screen.blit(game_message,game_message_rect) def asteroid_animation_state(): global asteroid_surface, asteroid_index, asteroid_rect asteroid_1 = pygame.image.load('graphics/asteroid_1.png').convert_alpha() asteroid_1 = pygame.transform.rotozoom(asteroid_1,-45,0) asteroid_2 = pygame.image.load('graphics/asteroid_2.png').convert_alpha() asteroid_2 = pygame.transform.rotozoom(asteroid_2,-45,0) asteroid_frames = [asteroid_1,asteroid_2] asteroid_index = 0 asteroid_surface = asteroid_frames[asteroid_index] asteroid_rect = asteroid_surface.get_rect(midtop = (randint(0,751),-20)) asteroid_index += 0.1 if asteroid_index >= len(asteroid_frames): asteroid_index = 0 asteroid_surface = asteroid_frames[int(asteroid_index)] asteroid_rect.bottom += 10 if asteroid_rect.bottom >=600: asteroid_rect.bottom = -20 screen.blit(asteroid_surface,asteroid_rect) pygame.init() pygame.display.set_caption('Escape Extinction') screen = pygame.display.set_mode((750,563)) clock = pygame.time.Clock() LEFT = False RIGHT = False start_time = 0 score = 0 font = pygame.font.Font('fonts/atari-font-full-version/atari_full.ttf', 25) player_right_1 = pygame.image.load('graphics/dino_1_right.png').convert_alpha() player_right_2 = pygame.image.load('graphics/dino_2_right.png').convert_alpha() player_right_3 = pygame.image.load('graphics/dino_3_right.png').convert_alpha() player_right_4 = pygame.image.load('graphics/dino_4_right.png').convert_alpha() player_left_1 = pygame.image.load('graphics/dino_1_left.png').convert_alpha() player_left_2 = pygame.image.load('graphics/dino_2_left.png').convert_alpha() player_left_3 = pygame.image.load('graphics/dino_3_left.png').convert_alpha() player_left_4 = pygame.image.load('graphics/dino_4_left.png').convert_alpha() player_right_walk = [player_right_1,player_right_2,player_right_3,player_right_4] player_left_walk = [player_left_1,player_left_2,player_left_3,player_left_4] player_index = 0 #player_surface_right = player_right_walk[player_index] #player_surface_left = player_left_walk[player_index] player_surface = player_right_walk[player_index] player_rect = player_surface.get_rect(midbottom = (375,300)) background_surface = pygame.image.load('graphics/jumperbackground.png').convert() ground_surface = pygame.image.load('graphics/grass.png').convert() #obstacle_timer = pygame.USEREVENT + 1 #pygame.time.set_timer(obstacle_timer,1400) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() #if event.type == obstacle_timer: # obstacle.add(Asteroid('asteroid')) screen.blit(background_surface,(0,0)) screen.blit(ground_surface,(0,480)) player_control() animation_state() display_score() asteroid_animation_state() pygame.display.update() clock.tick(60)
问题分析与修复
核心问题
- 小行星状态被反复重置:
asteroid_animation_state函数每次调用都会重新加载图片、初始化asteroid_index为0、重置asteroid_rect到顶部,导致小行星永远无法正常下落,位置被不断拉回初始点。 - 图片被缩至不可见:
pygame.transform.rotozoom的缩放参数设为0,会将小行星图片缩成0尺寸,完全无法显示。 - 未定义变量报错:
animation_state和player_control函数中使用的event变量未传入,运行时会抛出NameError。 - 重复加载资源:函数内每次循环都加载小行星图片,严重拖慢性能。
修复方案
- 将小行星资源加载移到全局,仅初始化一次。
- 将小行星的状态变量(
asteroid_index、asteroid_rect)设为全局,避免每次调用函数时重置。 - 修正
rotozoom的缩放因子(比如设为1,保持原尺寸)。 - 将
event变量作为参数传入需要使用它的函数。 - 调整小行星的重置逻辑,只有当它完全移出屏幕后才重新生成位置。
修复后的完整代码
from sys import exit from random import randint import pygame # 补充导入pygame,原代码漏写 # 全局初始化小行星资源 asteroid_1 = pygame.image.load('graphics/asteroid_1.png').convert_alpha() asteroid_1 = pygame.transform.rotozoom(asteroid_1, -45, 1) # 缩放因子改为1 asteroid_2 = pygame.image.load('graphics/asteroid_2.png').convert_alpha() asteroid_2 = pygame.transform.rotozoom(asteroid_2, -45, 1) asteroid_frames = [asteroid_1, asteroid_2] asteroid_index = 0 asteroid_surface = asteroid_frames[asteroid_index] asteroid_rect = asteroid_surface.get_rect(midtop=(randint(0, 751), -20)) def animation_state(event): # 传入event参数 global player_surface, player_index, player_rect player_index += 0.15 if player_index >= len(player_right_walk): player_index = 0 if LEFT: player_surface = player_left_walk[int(player_index)] elif RIGHT: player_surface = player_right_walk[int(player_index)] else: player_surface = pygame.image.load('graphics/dino_idle_right.png').convert_alpha() if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT: player_surface = pygame.image.load('graphics/dino_idle_left.png').convert_alpha() elif event.key == pygame.K_RIGHT: player_surface = pygame.image.load('graphics/dino_idle_right.png').convert_alpha() screen.blit(player_surface, player_rect) def player_control(event): # 传入event参数 global LEFT, RIGHT player_velocity = 0 player_gravity = 0 player_gravity += 3 player_rect.y += player_gravity if player_rect.bottom >= 500: player_rect.bottom = 500 keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: player_velocity -= 6 LEFT = True RIGHT = False if player_rect.x < -50: player_rect.x = 800 elif keys[pygame.K_RIGHT]: player_velocity += 6 LEFT = False RIGHT = True if player_rect.x > 800: player_rect.x = -50 else: LEFT = False RIGHT = False # 修正:松开方向键时重置状态 if event.type == pygame.KEYUP: if event.key in (pygame.K_LEFT, pygame.K_RIGHT): player_velocity = 0 player_rect.x += player_velocity def display_score(): current_time = int(pygame.time.get_ticks() / 1000) - start_time score_surface = font.render('Score: ' + str(current_time), False, (64,64,64)) score_rect = score_surface.get_rect(center=(375, 30)) screen.blit(score_surface, score_rect) return current_time def game_over_screen(): player_stand = pygame.image.load('graphics/dino_stand.png').convert_alpha() player_stand = pygame.transform.rotozoom(player_stand, 0, 4).convert_alpha() player_stand_rect = player_stand.get_rect(center=(375,280)) game_name = font.render('Personal Project Game', False, (111,196,169)) game_name_rect = game_name.get_rect(center=(375,100)) game_message = font.render('Press Space to start', False, 'Black') game_message_rect = game_message.get_rect(center=(375, 500)) screen.blit(background_surface,(0,0)) screen.blit(player_stand,player_stand_rect) screen.blit(game_name,game_name_rect) screen.blit(game_message,game_message_rect) def asteroid_animation_state(): global asteroid_surface, asteroid_index, asteroid_rect # 更新动画帧 asteroid_index += 0.1 if asteroid_index >= len(asteroid_frames): asteroid_index = 0 asteroid_surface = asteroid_frames[int(asteroid_index)] # 移动小行星 asteroid_rect.y += 10 # 直接修改y坐标,更直观 # 小行星完全移出屏幕后重置位置 if asteroid_rect.top > 563: asteroid_rect = asteroid_surface.get_rect(midtop=(randint(0, 751), -20)) screen.blit(asteroid_surface, asteroid_rect) # 初始化pygame pygame.init() pygame.display.set_caption('Escape Extinction') screen = pygame.display.set_mode((750,563)) clock = pygame.time.Clock() LEFT = False RIGHT = False start_time = int(pygame.time.get_ticks() / 1000) # 初始化开始时间 score = 0 font = pygame.font.Font('fonts/atari-font-full-version/atari_full.ttf', 25) # 加载玩家资源 player_right_1 = pygame.image.load('graphics/dino_1_right.png').convert_alpha() player_right_2 = pygame.image.load('graphics/dino_2_right.png').convert_alpha() player_right_3 = pygame.image.load('graphics/dino_3_right.png').convert_alpha() player_right_4 = pygame.image.load('graphics/dino_4_right.png').convert_alpha() player_left_1 = pygame.image.load('graphics/dino_1_left.png').convert_alpha() player_left_2 = pygame.image.load('graphics/dino_2_left.png').convert_alpha() player_left_3 = pygame.image.load('graphics/dino_3_left.png').convert_alpha() player_left_4 = pygame.image.load('graphics/dino_4_left.png').convert_alpha() player_right_walk = [player_right_1,player_right_2,player_right_3,player_right_4] player_left_walk = [player_left_1,player_left_2,player_left_3,player_left_4] player_index = 0 player_surface = player_right_walk[player_index] player_rect = player_surface.get_rect(midbottom=(375, 500)) # 修正初始位置到地面 # 加载背景资源 background_surface = pygame.image.load('graphics/jumperbackground.png').convert() ground_surface = pygame.image.load('graphics/grass.png').convert() while True: # 初始化默认事件,避免函数报错 dummy_event = pygame.event.Event(pygame.NOEVENT) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() # 补充exit,避免pygame.quit后代码继续执行 dummy_event = event # 保存当前事件 screen.blit(background_surface,(0,0)) screen.blit(ground_surface,(0,480)) player_control(dummy_event) animation_state(dummy_event) display_score() asteroid_animation_state() pygame.display.update() clock.tick(60)
内容的提问来源于stack exchange,提问作者Rohit Sangishetty
相关产品推荐
相关产品推荐

