【问题标题】:Make intro screen with pyglet使用 pyglet 制作介绍屏幕
【发布时间】:2015-03-07 20:56:17
【问题描述】:

我正在尝试使用 pyglet 制作一个简单的游戏,它必须包含一个介绍屏幕。不幸的是,事实证明这比我预期的要困难。

以下代码是我正在尝试做的更简单的版本。

import pyglet
from game import intro

game_window = pyglet.window.Window(800, 600)
intro.play(game_window)

@game_window.event
def on_draw():
    game_window.clear()

    main_batch.draw()

def update(dt):
    running = True

if __name__ == '__main__':
    pyglet.clock.schedule_interval(update, 1/120.0)

    main_batch = pyglet.graphics.Batch()
    score_label = pyglet.text.Label(text = 'RUNNING GAME', x = 400, y = 200, batch=main_batch)

    pyglet.app.run()

其中 game/intro.py 有以下内容:

import pyglet
from time import sleep

def play(game_window):
    game_window.clear()

    studio = pyglet.text.Label('foo studios', font_size=36, font_name='Arial', x=400, y=300)
    studio.draw()

    sleep(5)

这会打开一个窗口(介绍窗口)并等待 5 秒钟,之后会出现消息“RUNNING GAME”,但不会出现“foo studios”消息。

显然我做错了什么。

我对 pyglet 不是很有经验,但我设法让游戏运行起来(需要一些调整,但基本上已经完成)。我只需要介绍屏幕。

如果有人知道制作介绍屏幕的好方法(仅使用文本,我现在不需要任何音乐动画),我将不胜感激。

【问题讨论】:

    标签: python pyglet


    【解决方案1】:

    您最好创建基于 pyglet.sprite.Sprite 的类并将这些对象用作“窗口”或“屏幕”。

    感觉就像我将这段代码粘贴到任何地方但使用它,并在“defrender()”中放置您当时希望呈现的不同“场景”/“windows”。

    import pyglet
    from time import time, sleep
    
    class Window(pyglet.window.Window):
        def __init__(self, refreshrate):
            super(Window, self).__init__(vsync = False)
            self.frames = 0
            self.framerate = pyglet.text.Label(text='Unknown', font_name='Verdana', font_size=8, x=10, y=10, color=(255,255,255,255))
            self.last = time()
            self.alive = 1
            self.refreshrate = refreshrate
    
        def on_draw(self):
            self.render()
    
        def render(self):
            self.clear()
            if time() - self.last >= 1:
                self.framerate.text = str(self.frames)
                self.frames = 0
                self.last = time()
            else:
                self.frames += 1
            self.framerate.draw()
            self.flip()
    
        def on_close(self):
            self.alive = 0
    
        def run(self):
            while self.alive:
                self.render()
                event = self.dispatch_events() # <-- This is the event queue
                sleep(1.0/self.refreshrate)
    
    win = Window(23) # set the fps
    win.run()
    

    你有一个渲染函数,它每秒清除和翻转整个图形内存 X 次,并且你在 render 函数中决定哪些对象包含在该渲染层中。

    试试看是否有帮助。


    这是一个使用上述示例的示例,它由 3 部分组成: * 一个主窗口 *一个介绍屏幕 * 一个菜单屏幕

    您可以忽略class Spr()def convert_hashColor_to_RGBA(),这些只是帮助函数,以避免进一步重复代码。

    我也会继续标记实际做事的重要位,其余的只是启动代码或定位的事情。

    import pyglet
    from time import time, sleep
    
    __WIDTH__ = 800
    __HEIGHT__ = 600
    
    def convert_hashColor_to_RGBA(color):
        if '#' in color:
            c = color.lstrip("#")
            c = max(6-len(c),0)*"0" + c
            r = int(c[:2], 16)
            g = int(c[2:4], 16)
            b = int(c[4:], 16)
            color = (r,g,b,255)
        return color
    
    class Spr(pyglet.sprite.Sprite):
        def __init__(self, texture=None, width=__WIDTH__, height=__HEIGHT__, color='#000000', x=0, y=0):
            if texture is None:
                self.texture = pyglet.image.SolidColorImagePattern(convert_hashColor_to_RGBA(color)).create_image(width,height)
            else:
                self.texture = texture
            super(Spr, self).__init__(self.texture)
    
            ## Normally, objects in graphics have their anchor in the bottom left corner.
            ## This means that all X and Y cordinates relate to the bottom left corner of
            ## your object as positioned from the bottom left corner of your application-screen.
            ##
            ## We can override this and move the anchor to the WIDTH/2 (aka center of the image).
            ## And since Spr is a class only ment for generating a background-image to your "intro screen" etc
            ## This only affects this class aka the background, so the background gets positioned by it's center.
            self.image.anchor_x = self.image.width / 2
            self.image.anchor_y = self.image.height / 2
    
            ## And this sets the position.
            self.x = x
            self.y = y
    
        def _draw(self):
            self.draw()
    
    ## IntoScreen is a class that inherits a background, the background is Spr (our custom background-image class)
    ## IntoScreen contains 1 label, and it will change it's text after 2 seconds of being shown.
    ## That's all it does.
    class IntroScreen(Spr):
        def __init__(self, texture=None, width=300, height = 150, x = 10, y = 10, color='#000000'):
            super(IntroScreen, self).__init__(texture, width=width, height=height, x=x, y=y, color=color)
    
            self.intro_text = pyglet.text.Label('Running game', font_size=8, font_name=('Verdana', 'Calibri', 'Arial'), x=x, y=y, multiline=False, width=width, height=height, color=(100, 100, 100, 255), anchor_x='center')
            self.has_been_visible_since = time()
    
        def _draw(self): # <-- Important, this is the function that is called from the main window.render() function. The built-in rendering function of pyglet is called .draw() so we create a manual one that's called _draw() that in turn does stuff + calls draw(). This is just so we can add on to the functionality of Pyglet.
            self.draw()
            self.intro_text.draw()
            if time() - 2 > self.has_been_visible_since:
                self.intro_text.text = 'foo studios'
    
    ## Then we have a MenuScreen (with a red background)
    ## Note that the RED color comes not from this class because the default is black #000000
    ## the color is set when calling/instanciating this class further down.
    ##
    ## But all this does, is show a "menu" (aka a text saying it's the menu..)
    class MenuScreen(Spr):
        def __init__(self, texture=None, width=300, height = 150, x = 10, y = 10, color='#000000'):
            super(MenuScreen, self).__init__(texture, width=width, height=height, x=x, y=y, color=color)
    
            self.screen_text = pyglet.text.Label('Main menu screen', font_size=8, font_name=('Verdana', 'Calibri', 'Arial'), x=x, y=y+height/2-20, multiline=False, width=300, height=height, color=(100, 100, 100, 255), anchor_x='center')
    
        def _draw(self):
            self.draw()
            self.screen_text.draw()
    
    ## This is the actual window, the game, the glory universe that is graphics.
    ## It will be blank, so you need to set up what should be visible when and where.
    ##
    ## I've creates two classes which can act as "screens" (intro, game, menu etc)
    ## And we'll initate the Window class with the IntroScreen() and show that for a
    ## total of 5 seconds, after 5 seconds we will swap it out for a MenuScreeen().
    ##
    ## All this magic is done in __init__() and render(). All the other functions are basically
    ## just "there" and executes black magic for your convencience.
    class Window(pyglet.window.Window):
        def __init__(self, refreshrate):
            super(Window, self).__init__(vsync = False)
            self.alive = 1
            self.refreshrate = refreshrate
    
            self.currentScreen = IntroScreen(x=320, y=__HEIGHT__/2, width=50)  # <-- Important
            self.screen_has_been_shown_since = time()
    
        def on_draw(self):
            self.render()
    
        def on_key_down(self, symbol, mod):
            print('Keyboard down:', symbol) # <-- Important
    
        def render(self):
            self.clear()
    
            if time() - 5 > self.screen_has_been_shown_since and type(self.currentScreen) is not MenuScreen:  # <-- Important
                self.currentScreen = MenuScreen(x=320, y=__HEIGHT__-210, color='#FF0000') # <-- Important, here we switch screen (after 5 seconds)
    
            self.currentScreen._draw() # <-- Important, draws the current screen
            self.flip()
    
        def on_close(self):
            self.alive = 0
    
        def run(self):
            while self.alive:
                self.render()
                event = self.dispatch_events()
                sleep(1.0/self.refreshrate)
    
    win = Window(23) # set the fps
    win.run()
    

    【讨论】:

    • 您好 Torxed,谢谢您的回复。我是制作 GUI 或游戏的新手。我正在开发的这款游戏应该是一款简单的太空游戏,可以作为朋友的生日贺卡。我只需要在游戏开始前让一些文本在屏幕上消失。因此,尽管从长远来看,您的解决方案似乎是最好的,但对于我所需要的而言,它可能有点矫枉过正。有没有办法在不过多更改代码的情况下实现这一点?干杯:)
    • @jmm 嗨,我的荣幸!我的建议是,你应该把尽可能多的例子放在一起。因为在图形方面的第一课是它从来没有你想象的那么容易。上面是您在评论中请求的示例,在“游戏”开始之前出现和消失的文本,在这种情况下只是一个菜单。游戏本身你必须编程,但我留下了一点关于如何实现键盘事件的面包屑。另外,如果您只想做一些非常基本的事情,请考虑更改为pygame。 Pyglet 是为了性能和自定义
    • ... 和自定义应用程序(例如,按钮形状上的自定义图形等)。 Pyglet 非常多才多艺,它也被构建为像任何东西一样动态。您可以将事物相互嵌套并构建自定义事件触发器,并且.. 天空(阅读:您的机器)是 Pyglet 的限制。 您可以做简单的应用程序,但大多数情况下它是为了做更大的事情。
    猜你喜欢
    • 1970-01-01
    • 2021-10-25
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多