动画在Pyglet使用图象区域

时间:2016-12-06 07:06:41

标签: python animation pyglet

import pyglet
from pyglet.window import Window, mouse, gl
from pyglet.image.codecs.png import PNGImageDecoder




window = pyglet.window.Window(
                790, 640,
              resizable=False,                                                  # Make sure it is not resizable
              caption="Something",                                     # Caption of window
              config=pyglet.gl.Config(double_buffer=True),                      # Avoids flickers
              vsync=False)

kitten = pyglet.image.load('bar.png', decoder=PNGImageDecoder())
image_part = kitten.get_region(x=0, y=0, width=400, height=40)
ball = pyglet.sprite.Sprite(image_part, x=50, y=20+50)
ball.scale = 0.25

image = kitten.get_region(x=0, y=40, width=400, height=40)
lol = pyglet.sprite.Sprite(image, x=50, y=30+50)
lol.scale = 0.25

a = kitten.get_region(x=0, y=80, width=200, height=40)
ab = pyglet.sprite.Sprite(a, x=50, y=40+50)
ab.scale = 0.25

def update(self, dt):
   on_draw()

@window.event
def on_draw():
    window.clear()
    pyglet.gl.glClearColor(255,255,255,255)
    lol.draw()
    ball.draw()
    ab.draw()

def update(dt):
    on_draw()   
pyglet.clock.schedule_interval(update, 1/60)


pyglet.app.run()

我正在尝试制作排序算法的2D动画,并且不知道如何为图像区域设置动画。 当运行这段代码时,它在屏幕上给出了三个静态条,我只需要切换它们的pplaces ..! 谢谢你的帮助

2 个答案:

答案 0 :(得分:1)

您只是永远不会更新lol.x = <new pos> 这应该在以后的更新中完成:

def update(dt):
    ball.x += 10

大多数情况下,您不必担心更新图形,但在on_draw()中,您可能需要通过以下方式更新屏幕:

def on_draw():
    window.clear()
    lol.draw()
    window.flip()

正如有人指出的那样,命名两个函数def update()将导致后一个函数替换第一个函数。

由于您正在使用精灵,我想我会给你一个整洁的小精灵课,它可能比静态图像更适合你。

import pyglet
from pyglet.gl import *

class Bar(pyglet.sprite.Sprite):
    def __init__(self, width=20, height=200, color="#C2C2C2", x=0, y=0):
        # == Must generate a texture before initialization of Sprite()
        self.texture = self.gen_solid_img(width, height, color)

        super(Bar, self).__init__(self.texture)

        self.y = y
        self.x = x

    def gen_solid_img(self, width, height, c, alpha=255):
        c = c.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)
        c = (r,g,b,int(alpha))
        return pyglet.image.SolidColorImagePattern(c).create_image(width,height)

    def draw_border(self, color=(0.2, 0.2, 0.2, 0.5)):
        self.draw_line((self.x, self.y), (self.x, self.y+self.height), color)
        self.draw_line((self.x, self.y+self.height), (self.x+self.width, self.y+self.height), color)
        self.draw_line((self.x+self.width, self.y+self.height), (self.x+self.width, self.y), color)
        self.draw_line((self.x+self.width, self.y), (self.x, self.y), color)

使用它的一个例子是替换:

kitten = pyglet.image.load('bar.png', decoder=PNGImageDecoder())
image_part = kitten.get_region(x=0, y=0, width=400, height=40)
ball = pyglet.sprite.Sprite(image_part, x=50, y=20+50)
ball.scale = 0.25

使用:

ball = Bar(x=0, y=0, width=400, height=40)

我还建议从装饰器切换到继承的类结构,以便在代码增长时更容易处理每个对象。

基本类骨架如下所示:

import pyglet
from pyglet.gl import *

key = pyglet.window.key

class main(pyglet.window.Window):
    def __init__ (self):
        super(main, self).__init__(800, 600, fullscreen = False, vsync=False)
        self.x, self.y = 0, 0

        self.bg = pyglet.sprite.Sprite(pyglet.image.load('background.jpg'))
        self.sprites = {}
        self.alive = 1

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC] is pressed
            self.alive = 0

    def render(self):
        self.clear()
        self.bg.draw()

        for sprite_name, sprite_obj in self.sprites.items():
            sprite_obj.draw()

        self.flip()

    def run(self):
        while self.alive == 1:
            self.render()

            # -----------> This is key <----------
            # This is what replaces pyglet.app.run()
            # but is required for the GUI to not freeze
            #
            event = self.dispatch_events()

x = main()
x.run()

现在将这两个基于类的代码片段合并在一起,您应该看到如下内容:

import pyglet
from pyglet.gl import *

key = pyglet.window.key

class Bar(pyglet.sprite.Sprite):
    def __init__(self, width=20, height=200, color="#C2C2C2", x=0, y=0):
        # == Must generate a texture before initialization of Sprite()
        self.texture = self.gen_solid_img(width, height, color)

        super(Bar, self).__init__(self.texture)

        self.y = y
        self.x = x

    def gen_solid_img(self, width, height, c, alpha=255):
        c = c.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)
        c = (r,g,b,int(alpha))
        return pyglet.image.SolidColorImagePattern(c).create_image(width,height)

    def draw_border(self, color=(0.2, 0.2, 0.2, 0.5)):
        self.draw_line((self.x, self.y), (self.x, self.y+self.height), color)
        self.draw_line((self.x, self.y+self.height), (self.x+self.width, self.y+self.height), color)
        self.draw_line((self.x+self.width, self.y+self.height), (self.x+self.width, self.y), color)
        self.draw_line((self.x+self.width, self.y), (self.x, self.y), color)

class main(pyglet.window.Window):
    def __init__ (self):
        super(main, self).__init__(800, 600, fullscreen = False, vsync=False)
        self.x, self.y = 0, 0

        self.bg = pyglet.sprite.Sprite(pyglet.image.load('background.jpg'))
        self.sprites = {}
        self.sprites['ball'] = Bar()
        self.alive = 1

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC] is pressed
            self.alive = 0
        elif symbol == key.RIGHT: # [RightArrow] is pressed
            self.sprites['ball'].x += 10
        elif symbol == key.LEFT:
            self.sprites['ball'].x -= 10
        elif symbol == key.UP:
            self.sprites['ball'].y += 10
        elif symbol == key.DOWN:
            self.sprites['ball'].y -= 10

    def render(self):
        self.clear()
        self.bg.draw()

        ## == Do some calculations and moving around here maybe.
        ##    Unless you'll be using on_key_press() as I did here.

        for sprite_name, sprite_obj in self.sprites.items():
            sprite_obj.draw()

        self.flip()

    def run(self):
        while self.alive == 1:
            self.render()

            # -----------> This is key <----------
            # This is what replaces pyglet.app.run()
            # but is required for the GUI to not freeze
            #
            event = self.dispatch_events()

x = main()
x.run()

我已添加,以便您可以按任意箭头(向右,向左,向上,向下),以便在我在此处创建的简单栏中移动。

它支持颜色,没有图片,但很容易添加,只需替换self.texture = gen_solid_image(...)即可。

我还对你可以在哪里进行计算和四处走动做了一点评论。

不要尝试使用线程,只会让你的生活更加艰难。

答案 1 :(得分:0)

您必须更改update中的内容才能看到动画 - 即。你可以移动对象

简单的例子。

import pyglet

window = pyglet.window.WWindow(
                790, 640,
              resizable=False,                                                  # Make sure it is not resizable
              caption="Something",                                     # Caption of window
              config=pyglet.gl.Config(double_buffer=True),                      # Avoids flickers
              vsync=False)

image = pyglet.image.load('bar.png')

region = image.get_region(x=0, y=0, width=400, height=40)
ball = pyglet.sprite.Sprite(region, x=50, y=20+50)
ball.scale = 0.25

region = image.get_region(x=0, y=40, width=400, height=40)
lol = pyglet.sprite.Sprite(region, x=50, y=30+50)
lol.scale = 0.25

region = image.get_region(x=0, y=80, width=200, height=40)
ab = pyglet.sprite.Sprite(region, x=50, y=40+50)
ab.scale = 0.25

@window.event
def on_draw():
    window.clear()
    pyglet.gl.glClearColor(255, 255, 255, 255)
    ball.draw()
    lol.draw()
    ab.draw()

def update(dt):
    # change something
    ball.x += 1
    lol.y += 1
    ab.scale += 0.1

    #on_draw() # you don't need it - pyglet will do it

pyglet.clock.schedule_interval(update, 1/60)

pyglet.app.run()