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

为何我的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)

问题分析与修复

核心问题

  1. 小行星状态被反复重置:asteroid_animation_state函数每次调用都会重新加载图片、初始化asteroid_index为0、重置asteroid_rect到顶部,导致小行星永远无法正常下落,位置被不断拉回初始点。
  2. 图片被缩至不可见:pygame.transform.rotozoom的缩放参数设为0,会将小行星图片缩成0尺寸,完全无法显示。
  3. 未定义变量报错:animation_state和player_control函数中使用的event变量未传入,运行时会抛出NameError。
  4. 重复加载资源:函数内每次循环都加载小行星图片,严重拖慢性能。

修复方案

  1. 将小行星资源加载移到全局,仅初始化一次。
  2. 将小行星的状态变量(asteroid_index、asteroid_rect)设为全局,避免每次调用函数时重置。
  3. 修正rotozoom的缩放因子(比如设为1,保持原尺寸)。
  4. 将event变量作为参数传入需要使用它的函数。
  5. 调整小行星的重置逻辑,只有当它完全移出屏幕后才重新生成位置。

修复后的完整代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:48:22