You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Pygame中创建Scene类实例时出现1帧黑屏的问题求助

Pygame中创建Scene类实例时出现1帧黑屏的问题求助

大家好,我在开发Pygame游戏时碰到了一个头疼的小问题:每次切换场景,屏幕都会闪过1帧黑屏。我把所有界面/菜单都设计成了Scene类的实例,游戏循环里检测到按钮点击后,就会调用对应的函数来定义新场景的组件并创建Scene实例完成切换。

经过一系列测试(加了不少等待命令排查),我定位到问题出在创建Scene实例的代码行上——比如切换到战斗场景时的这行:

combatscreen = Scene("combatscreen", settings["resolution"]["x"], settings["resolution"]["y"], [50, 50, 50], [atkbtn, backbtn])

但我完全摸不着头脑:这行代码只是创建实例,根本没有调用任何显示更新的方法,为什么会导致黑屏呢?

以下是能复现这个问题的完整代码:

import pygame
import sys
import types
import json

pygame.init()

with open("settings.json") as file:
    settings = json.load(file)

class Scene:
    all_scenes = []
    def __init__(self, name, sizex, sizey, bgcolor, buttons=[], textboxes=[]):
        self.name = name
        self.sizex = sizex
        self.sizey = sizey
        self.bgcolor = bgcolor
        self.buttons = buttons
        self.textboxes = textboxes
        self.active = False
        Scene.all_scenes.append(self)
        self.surface = pygame.display.set_mode(size=[sizex, sizey])

class Button:
    def __init__(self, dest, destargs, posx, posy, width, height, text, color=[200,200,200], textcolor=[0,0,0], textsize=40):
        self.dest = dest
        self.destargs = destargs
        self.posx = posx
        self.posy = posy
        self.width = width
        self.height = height
        self.text = text
        self.color = color
        self.textcolor = textcolor
        self.textsize = textsize

    def btnclick(self, prev_scene):
        mpos = pygame.mouse.get_pos()
        clicks = pygame.mouse.get_just_released()
        btnbounds = pygame.draw.rect(self.surface, self.color, (self.posx, self.posy, self.width, self.height))
        # Checks if LMB was clicked within the bounds of the button
        if btnbounds.collidepoint(mpos):
            if clicks[0]:
                if isinstance(self.dest, types.FunctionType):
                    # Deactivates current scene and runs the function to define and activate the destination scene
                    prev_scene.active = False
                    self.dest()
                else:
                    pass

    def btnrender(self):
        mpos = pygame.mouse.get_pos()
        btnrect = pygame.draw.rect(self.surface, self.color, (self.posx, self.posy, self.width, self.height))
        if btnrect.collidepoint(mpos):
            # Makes the button lighter when hovered
            self.color[0] += 20
            self.color[1] += 20
            self.color[2] += 20
            pygame.draw.rect(self.surface, self.color, (self.posx, self.posy, self.width, self.height))
            # Resets button color
            self.color[0] -= 20
            self.color[1] -= 20
            self.color[2] -= 20
        btnlabel = pygame.font.Font(filename="Assets\\Fonts\\Adhynatha.otf", size=self.textsize).render(self.text, antialias=True, color=self.textcolor)
        labelrect = btnlabel.get_rect(center=(self.posx+(self.width/2), self.posy+(self.height/2)))
        self.surface.blit(btnlabel, labelrect)

def gameloop():
    scene = None
    while True:
        # Find which scene is active
        for i in Scene.all_scenes:
            if i.active:
                scene = i
        # Apply the active scene's surface to the buttons
        for i in scene.buttons:
            i.surface = scene.surface
        # Set the background color and render buttons
        scene.surface.fill(scene.bgcolor)
        for i in scene.buttons:
            i.btnrender()
        # Update the screen and restart the loop
        pygame.display.flip()
        # Pump the event queue
        for event in pygame.event.get():
            # Game close check
            if event.type == pygame.QUIT:
                sys.exit()
                pygame.quit()
        # Check if a button has been clicked this frame
        for i in scene.buttons:
            i.btnclick(scene)
        pygame.time.Clock().tick(60)

def startscreen():
    startbtn = Button(combatscreen, None, 100, 100, 300, 100, "Start", [30, 30, 30], "white")
    cnfgbtn = Button("settingsmenu", None, settings["resolution"]["x"]-400, 100, 300, 100, "Settings", [30, 30, 30], "white")
    # PROBLEM LINE
    startscreen = Scene("startscreen", settings["resolution"]["x"], settings["resolution"]["y"], [100, 100, 100], [startbtn, cnfgbtn])
    startscreen.active = True

def combatscreen():
    atkbtn = Button("attack_select", None, 100, 500, 300, 100, "Combat", [100, 100, 100], textcolor="red")
    backbtn = Button(startscreen, None, settings["resolution"]["x"]-100, 0, 100, 50, "Back", textsize=20, textcolor="Black")
    # PROBLEM LINE
    combatscreen = Scene("combatscreen", settings["resolution"]["x"], settings["resolution"]["y"], [50, 50, 50], [atkbtn, backbtn])
    combatscreen.active = True

startscreen()
gameloop()

我已经尝试过调整游戏循环里各种事件的执行顺序,但因为问题根源似乎在单独函数里的实例创建步骤,这些调整完全没起作用。有没有朋友能帮我分析下原因,或者给出解决思路?

内容来源于stack exchange

火山引擎 最新活动