Pyglet绘制具有颜色的基元

时间:2019-03-10 11:15:51

标签: python colors primitive pyglet

我正在创建带有网格的细胞自动机,但是当我尝试为细胞赋予颜色时,会出现错误。如果我移除"('c3B', (255,0,0))",一切正常。

def on_draw(self):
    self.clear()
    self.predatorAndPrey.draw()

这是函数:

    def draw(self):
    for row in range(0, self.grid_height):
        for col in range(0, self.grid_width):
            square_cords = (
                row * self.cell_size, col * self.cell_size,
                row * self.cell_size, col * self.cell_size + self.cell_size,
                row * self.cell_size + self.cell_size, col * self.cell_size + self.cell_size,
                row * self.cell_size + self.cell_size, col * self.cell_size
            )
            if self.cells[row][col][0] == 1:

                pyglet.graphics.draw_indexed(4, pyglet.gl.GL_QUADS,
                                             [0,1,2,3],
                                             ('v2i', square_cords),
                                             ('c3B', (255,0,0))
                                             )

这是错误:

File "E:/Python/Cellular Automata/Predator and Prey/Cellular Automata.py", line 23, in on_draw
    self.predatorAndPrey.draw()
  File "E:\Python\Cellular Automata\Predator and Prey\predator_and_prey.py", line 39, in draw
    ('c3B', (255,0,0))
  File "E:\Python\Cellular Automata\venv\lib\site-packages\pyglet\graphics\__init__.py", line 230, in draw_indexed
    'Data for %s is incorrect length' % format
AssertionError: Data for c3B is incorrect length

2 个答案:

答案 0 :(得分:0)

我从未使用过Pyglet,但您是否尝试过为alpha添加最后一个0:(255,0,0,0)? 阅读文档似乎很必要。

答案 1 :(得分:0)

由于我的评论显然是有道理的,因此,这里有一个解释为何起作用的详细说明,并举例说明了如何正确使用它。

函数draw_indexed()是一种以索引顺序绘制基元的方法。原语可以是pyglet.gl上下文支持的任何内容,在这种情况下为GL_QUADSGL_QUAD对象至少需要一件事情,那就是所有图元的四个角的坐标。您在square_cords中提供它们,它们成对出现在两个(X,Y) * 4角(总共 8 个项目)中。

(可选)您可以向GL_QUAD对象提供颜色信息。这指示渲染过程应映射每个角的颜色。在您的情况下,您已选择发送颜色信息。

所有这些基于两件事:v2i表示vertext信息,每个顶点2个分量(表示2D空间),提供的数据类型为i(整数)。

颜色遵循类似的含义/定义。其中c3B表示颜色的c3表示每个数据blob(在这种情况下为RGB)3个项目,类型为B(无符号int)。但是颜色是“ tricky” ,因为颜色与v2i前面的顶点定义数目紧密地联系在一起。这意味着颜色与QUAD中的每一对(角)相关。如果是一行,它将与行的开头和结尾相关联。在一个点中,这将是一个单一的颜色定义,因为一个点只有一个(x,y)元素。但这始终与基元中预期的定义数量有关-同样,您的四边形有4个定义/角-因此您将需要4对颜色。

因此,您需要将颜色定义(255, 0, 0)乘以有角的次数。 (255, 0, 0),因为您使用了3B。而且您有 4个角,所以(255, 0, 0) * 4。实现此目的的最简单方法是进行(255,0,0) * int(len(square_cords)/2)/2是因为square_cords(x,y)中每个角有2对-但是您只想计算角的数量而不是位置。我希望这是有道理的。

因此,作为一个实际示例,这是一段代码,说明如何将它们联系在一起,并希望这会教给您一些有关顶点,颜色以及GL_***上下文如何期望某些行为的知识。祝您好运。

from pyglet import *
from pyglet.gl import *

key = pyglet.window.key

class main(pyglet.window.Window):
    def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
        super(main, self).__init__(width, height, *args, **kwargs)
        self.x, self.y = 0, 0

        self.keys = {}

        self.mouse_x = 0
        self.mouse_y = 0

        self.cell_size = 20

        self.alive = 1

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_mouse_motion(self, x, y, dx, dy):
        self.mouse_x = x

    def on_key_release(self, symbol, modifiers):
        try:
            del self.keys[symbol]
        except:
            pass

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

        self.keys[symbol] = True

    def render(self):
        self.clear()

        square_cords = (
            self.cell_size, self.cell_size,
            self.cell_size, self.cell_size + self.cell_size,
            self.cell_size + self.cell_size, self.cell_size + self.cell_size,
            self.cell_size + self.cell_size, self.cell_size
        )

        color_pairs = (255,0,0) * int(len(square_cords)/2)

        pyglet.graphics.draw_indexed(4, pyglet.gl.GL_QUADS,
                                        [0,1,2,3],
                                        ('v2i', square_cords),
                                        ('c3B', color_pairs)
        )

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

if __name__ == '__main__':
    x = main()
    x.run()