使用pyglet制作介绍屏幕

时间:2015-03-07 20:56:17

标签: python pyglet

我正在尝试用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不太熟悉,但我设法让游戏运行(需要一些调整,但它基本上完成了)。我需要的只是介绍屏幕。

如果有人知道做一个介绍屏幕的好方法(只是用文字,我现在不需要任何动画的动画),我将非常感激。

1 个答案:

答案 0 :(得分:0)

您最好根据例如pyglet.sprite.Sprite创建类,并将这些对象用作" windows"或"屏幕"。

感觉就像我在任何地方都粘贴了这个代码但是使用了这个代码,并且在" def render()`中放置了不同的"场景" /" 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()