Reputation: 13
I am creating a cellular automata with a grid, but when I try to give the cell a color I get an error. If i remove the "('c3B', (255,0,0))"
everything works.
def on_draw(self):
self.clear()
self.predatorAndPrey.draw()
And here is the function:
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))
)
Here is the Error:
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
Upvotes: 1
Views: 1524
Reputation: 23490
Since my comment apparently made sense, here's a detailed explanation of why it works, with a example of how to use it properly.
The function draw_indexed()
is a way to draw primitives in a indexed ordered. A primitive can be anything supported under the pyglet.gl
context, in this case GL_QUADS
. The GL_QUAD
object requires at least one thing, and that's the cordinates of all the primitives four corners. You supply them in square_cords
, and they come in pairs of two (X,Y) * 4
corners (total of 8 items).
Optionally, you can supply color information to the GL_QUAD
object. This instructs the rendering process what color each corner should be mapped against. In your case, you've chosen to send along the color information.
All this is based on two things: v2i
meaning vertext
information, 2
components per vertex (meaning 2D space) and the data supplied is of type i
(integer).
The color follows a similar meaning/definition. where c3B
means c
for color, 3
means 3 items per data blob (RGB in this case) and is of type B
(unsigned int). But the color is "tricky", since it is heavily tied together to the number of vertex definitions earlier in v2i
. Meaning the color is tied to each pair (corner) in your QUAD. If it was a line, it would be tied to start and end of the line. And in a dot, it would be a single color definition since a dot only has one element of (x,y)
to it. But it's always tied to the number of definitions expected in the primitive - so again - your quad has 4 definitions/corners - so you'll need 4 color pairs.
So you will need to multiply your color definition (255, 0, 0)
as many times as you have corners. (255, 0, 0)
because you used 3B
. And you have 4 corners, so (255, 0, 0) * 4
. The easiest way to achieve this - would be to do (255,0,0) * int(len(square_cords)/2)
. The /2
is because there's 2 pairs per corner in square_cords
(x,y) - but you only want to count the amount of corners not positions. I hope that makes sense.
So, as a practical example, here's a piece of code illustrating how this ties together and hopefully this will have taught you something about vertexes, color and how the GL_***
context expects certain things to be/behave. Best of luck to you.
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()
Upvotes: 2
Reputation: 33
I have never used the Pyglet but have you tried to just add a last 0 for alpha: (255,0,0,0)? Reading the documentation it looks like it is needed.
Upvotes: 0