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
相关产品推荐
相关产品推荐

