Pyglet 中使用图像区域的动画

Animation In Pyglet using image region

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()

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

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

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

大多数时候您也不需要担心更新图形,但在 on_draw() 中您也可以通过以下方式请求更新屏幕:

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

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

既然你在使用精灵,我想我会给你一个整洁的小精灵 class 可能比静态图像更适合你。

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)

我还建议从装饰器切换到继承的 class 结构,这样随着代码的增长可以更轻松地处理每个对象。

一个基本的 class 骨架看起来像这样:

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()

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

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(...) 即可。

我还对您可以在哪里进行一些计算和四处移动发表了一些评论。

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

您必须更改 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()