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

Pygame报错:cannot convert without pygame.display initialized 求助

问题描述

清理并重新整理代码后出现错误:Error: cannot convert without pygame.display initialized,检查后未发现明显问题,相关代码如下:

import pygame
import random
import math
import sys
from pygame.locals import *
from Start import start_screen


# Initialize Pygame and Display
screen_width, screen_height = 640, 480
pygame.init()
DISPLAY = pygame.display.set_mode((screen_width, screen_height), 0, 32)
font = pygame.font.Font("fonts/VLNL.ttf", 30)
pygame.display.set_caption("Der Sammler")

# Sounds - Start screen
flap_sound = pygame.mixer.Sound("sfx/flap.wav")
flap_sound.set_volume(0.2)
start_screen.show_start_screen()

clock = pygame.time.Clock()
scroll_speed = 5  # The speed at which the backgrounds scroll


# Game Settings
LETTER_SPAWN_RATE = 100
world_width = 640


# Function
def smooth_step(start, end, step):
    difference = end - start
    return start + difference * step


# Classes
class Letter(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load("gfx/letter.png")
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(screen_width - self.rect.width)
        self.rect.y = -self.rect.height  # Start off screen at the top
        self.speed = 2

    def update(self):
        self.rect.y += self.speed
        if (
            self.rect.bottom > screen_height
        ):  # If it has gone past the bottom of the screen.
            self.kill()  # Remove the sprite.


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.original_image = pygame.image.load("gfx/player.png")
        self.images = [
            self.original_image for _ in range(3)
        ]  # Add the images for animation. Here, we use the same image for simplicity.
        self.current_image = 0
        self.image = self.images[self.current_image]  # Set the initial image
        self.rect = self.image.get_rect()
        self.rect.center = (screen_width // 2, screen_height // 2)
        self.time = 0
        self.jumping = False
        self.velocity = pygame.Vector2(0, 0)
        self.acceleration = pygame.Vector2(0, 2)
        self.speed = 2
        self.direction = 1  # 1 for right, -1 for left
        self.pos = pygame.Vector2(screen_width // 2, screen_height // 2)

    def update(self):
        global score
        global scroll_speed, camera_x, camera_y
        keys = pygame.key.get_pressed()

        # Check player's position to decide if we should spawn a letter
        if (
            self.rect.top < screen_height // 2
        ):  # If player is at the top half of the screen.
            if (
                random.random() < 0.02
            ):  # Adjust this number to control frequency of letter spawns.
                new_letter = Letter()
                letters.add(new_letter)
                sprites.add(new_letter)

        self.rect.y += self.velocity.y

        # calculate the camera position and then clamp it to within the screen bounds
        camera_x = min(
            max(self.rect.centerx - screen_width //
                2, 0), world_width - screen_width
        )
        camera_y = min(
            max(self.rect.centery - screen_height // 2, 0), screen_height)

        # If player is on the ground and the spacebar is pressed, then jump.
        if keys[K_SPACE] and self.velocity.y >= 0:
            self.jumping = True
            self.velocity.y = -7  # Increase this value for a higher jump
            # Random horizontal velocity
            self.velocity.x = random.uniform(-5, 5)
            flap_sound.stop()
            flap_sound.play()
        else:
            self.velocity.y += self.acceleration.y
            self.velocity.x *= 0.9

        self.pos.y += self.velocity.y
        self.time += 0.04
        self.pos.x = (math.sin(self.time) + 1) / 2 * \
            (screen_width - self.rect.width)

        # Keep the player in the middle of the screen
        self.rect.center = (screen_width // 2, screen_height // 2)

        self.rect.y += self.velocity.y
        self.time += 0.04  # Adjust this value to change the speed of the oscillation
        self.rect.x = (math.sin(self.time) + 1) / 2 * \
            (screen_width - self.rect.width)

        # Make sure player does not go off the screen
        if self.pos.x < 0:
            self.pos.x = 0
            self.velocity.x = 0
        elif self.pos.x > screen_width:
            self.pos.x = screen_width
            self.velocity.x = 0

        if self.pos.y < 0:
            self.pos.y = 0
            self.velocity.y = 0

        self.pos.x += self.velocity.x
        self.pos.y += self.velocity.y

        self.rect.center = self.pos

        hit_letters = pygame.sprite.spritecollide(self, letters, True)
        for _ in hit_letters:
            score += 1

        # Flip the sprite
        self.image = pygame.transform.flip(
            self.original_image, self.direction == -1, False
        )

        # Only rotate the sprite when jumping
        if self.jumping:
            self.current_image += 1
            if self.current_image >= len(self.images):
                self.current_image = 0
            self.image = self.images[self.current_image]

            rotation_angle = self.velocity.y * 3  # Adjust this multiplier as needed
            self.image = pygame.transform.rotate(self.image, rotation_angle)

            target_velocity = pygame.Vector2(0, -10)
            step = 0.05
            self.velocity.x = smooth_step(
                self.velocity.x, target_velocity.x, step)
            self.velocity.y = smooth_step(
                self.velocity.y, target_velocity.y, step)

        self.rect = self.image.get_rect(
            center=self.rect.center
        )  # Keep the sprite at the same center position


# Images
bg = pygame.image.load("gfx/bg.png").convert_alpha()
bg2 = pygame.image.load("gfx/bg2.png").convert_alpha()
bg3 = pygame.image.load("gfx/bg3.png").convert_alpha()
letter2 = pygame.image.load("gfx/letter2.png").convert_alpha()
letter2 = pygame.transform.scale(letter2, (35, 35))


# Variables
score = 0
camera_x = 0
camera_y = 0
dt = 0
running = True
letter_counter = 0
bg_y = 0
bg2_y = -screen_height
bg3_y = -2 * screen_height


# Groups
player = Player()
letters = pygame.sprite.Group()  # This new group will contain all the letters
sprites = pygame.sprite.Group(player)


# Game Loop
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    dt = clock.tick(70) / 1000

    # Increase the counter each frame
    letter_counter += 1

    # Only spawn a letter if the counter has reached the spawn rate
    if letter_counter >= LETTER_SPAWN_RATE:
        new_letter = Letter()
        letters.add(new_letter)
        sprites.add(new_letter)
        letter_counter = 0  # Reset the counter

    # Scroll the backgrounds based on the player's direction
    scroll_speed = 200 * dt if player.velocity.y < 0 else -200 * dt
    bg_y += scroll_speed
    bg2_y += scroll_speed
    bg3_y += scroll_speed

    player.rect.x += player.velocity.x * dt
    player.rect.y += player.velocity.y * dt

    # Wrap the backgrounds when they go off the screen
    if bg_y >= screen_height:
        bg_y = bg3_y - screen_height
    elif bg_y < -screen_height:
        bg_y = bg2_y + screen_height

    if bg2_y >= screen_height:
        bg2_y = bg_y - screen_height
    elif bg2_y < -screen_height:
        bg2_y = bg3_y + screen_height

    if bg3_y >= screen_height:
        bg3_y = bg2_y - screen_height
    elif bg3_y < -screen_height:
        bg3_y = bg_y + screen_height

    DISPLAY.fill((0, 0, 0))  # clear the screen before drawing

    # Inside the game loop, replace the current blitting code with:
    DISPLAY.blit(bg, (0, bg_y))
    DISPLAY.blit(bg2, (0, bg2_y))
    DISPLAY.blit(bg3, (0, bg3_y))
    DISPLAY.blit(letter2, (90, 40))

    sprites.update()
    sprites.draw(DISPLAY)

    score_text = font.render(f"{score}", True, (0, 0, 0))
    # Draw the score at the top left of the screen
    DISPLAY.blit(score_text, (50, 50))

    pygame.display.update()
    clock.tick(70)

pygame.quit()
sys.exit()

input()
问题分析与解决方案

这个错误的核心是有代码在Pygame显示窗口初始化前,尝试执行依赖显示上下文的操作。具体问题和修复方法如下:

1. 核心问题点

你在代码开头就导入了from Start import start_screen,如果Start模块内部存在模块级别的图形操作(比如导入时自动加载图片、渲染字体),这些操作会在主程序的pygame.display.set_mode之前执行,直接触发错误。即使Start模块的图形操作都在show_start_screen函数里,导入时机过早也会存在潜在风险。

2. 修复步骤

步骤一:调整导入顺序

把from Start import start_screen移到显示窗口初始化完成后:

# Initialize Pygame and Display
screen_width, screen_height = 640, 480
pygame.init()
DISPLAY = pygame.display.set_mode((screen_width, screen_height), 0, 32)
font = pygame.font.Font("fonts/VLNL.ttf", 30)
pygame.display.set_caption("Der Sammler")

# 移到此处再导入start_screen
from Start import start_screen

# Sounds - Start screen
flap_sound = pygame.mixer.Sound("sfx/flap.wav")
flap_sound.set_volume(0.2)
start_screen.show_start_screen()

步骤二:检查Start.py内部逻辑

确保Start模块里所有图形相关操作(加载图片、渲染文本、pygame.transform调用等)都封装在函数内部,不要放在模块级别(也就是导入时自动执行的代码)。比如show_start_screen函数应该在被调用时才执行图形操作,而不是模块一导入就运行。

步骤三:统一资源加载时机

所有需要Pygame显示上下文的操作(比如pygame.image.load、pygame.font.Font),必须放在pygame.display.set_mode()调用之后执行。你的主程序里的资源加载(bg、player图片等)位置没问题,但要确保Start模块的资源加载也遵守这个规则。

额外优化建议

  • 避免在模块级别执行任何Pygame图形操作,尽量把所有初始化逻辑封装到函数中,在显示窗口创建完成后再调用。
  • 可以把Pygame的初始化流程(显示、字体、声音)集中放在代码最前端,确保上下文完全准备好后,再执行其他模块的调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:53:07