Reputation: 73
I'm trying to make a Towers of Hanoi program with Pyglet, but I'm having trouble drawing rectangles. Here is my code:
import pyglet
width, height = 500, 500
window = pyglet.window.Window(width, height)
rectR = pyglet.image.SolidColorImagePattern(color=(255, 0, 0, 1))
rectG = pyglet.image.SolidColorImagePattern(color=(0, 255, 0, 1))
rectB = pyglet.image.SolidColorImagePattern(color=(0, 0, 255, 1))
rectW = pyglet.image.SolidColorImagePattern(color=(255, 255, 255, 1))
column_img = rectW.create_image(20, 40)
disk7_img = rectR.create_image(140, 20)
disk5_img = rectG.create_image(100, 20)
disk3_img = rectB.create_image(60, 20)
def center_images(images):
for image in images:
image.anchor_x = image.width/2
image.anchor_y = image.height/2
center_images([column_img, disk7_img, disk5_img, disk3_img])
class Sprite:
def __init__(self, img, x=0, y=0):
self.img, self.x, self.y = img, x, y
class Column(Sprite):
def __init__(self, x, y, disk_codes):
super(Column, self).__init__(column_img, x=x, y=y)
disks = []
for disk_code in disk_codes:
disks.append(Disk(disk_code))
self.disks = sorted(disks, key= lambda disk: disk.img.width)
top = 0
for i, disk in enumerate(self.disks):
self.disks[i].x = self.x
self.disks[i].y = self.y - self.img.height/2 + top + disk.img.height/2
top += disk.img.height
def draw(self):
self.img.blit(self.x, self.y)
for disk in self.disks:
disk.img.blit(disk.x, disk.y)
class Disk(Sprite):
def __init__(self, code):
if code == 'R':
super(Disk, self).__init__(disk7_img)
elif code == 'G':
super(Disk, self).__init__(disk5_img)
elif code == 'B':
super(Disk, self).__init__(disk3_img)
else:
raise ValueError('Invalid disk code')
column = Column(100, 100, ['R', 'G', 'B'])
@window.event
def on_draw():
window.clear()
column.draw()
pyglet.app.run()
This isn't the full program, just the part that will draw the sprites for the columns and disks. For now, it's completely static. However, whenever I try to run it, I get an error at the 'blit' function that's supposed to draw the rectangles. Here is the error:
Traceback (most recent call last):
File "hanoi.py", line 63, in <module>
pyglet.app.run()
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/app/__init__.py", line 107, in run
event_loop.run()
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/app/base.py", line 170, in run
self._run()
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/app/base.py", line 182, in _run
timeout = self.idle()
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/app/base.py", line 309, in idle
window.dispatch_event('on_draw')
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/window/__init__.py", line 1320, in dispatch_event
if EventDispatcher.dispatch_event(self, *args) != False:
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/event.py", line 408, in dispatch_event
if handler(*args):
File "hanoi.py", line 61, in on_draw
column.draw()
File "hanoi.py", line 41, in draw
self.img.blit(self.x, self.y)
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/image/__init__.py", line 901, in blit
self.get_texture().blit(x, y, z, width, height)
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/image/__init__.py", line 832, in get_texture
self._current_texture = self.create_texture(Texture, rectangle, force_rectangle)
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/image/__init__.py", line 825, in create_texture
self.anchor_x, self.anchor_y, 0, None)
File "/Users/thomasfaulhaber/miniconda3/envs/hanoi/lib/python3.6/site-packages/pyglet/image/__init__.py", line 996, in blit_to_texture
data)
ctypes.ArgumentError: argument 3: <class 'TypeError'>: wrong type
I don't know what to try. I got started with Pyglet yesterday so I'm very new. Please forgive me if the answer is obvious. Thanks!
Upvotes: 2
Views: 2618
Reputation: 23500
I know the question isn't that old, but pyglet has since this question got posted added something called pyglet.shapes
which allows for creating Rectangle(x, y, w, h, color)
pretty easily. A complete example would be:
import pyglet
from pyglet import shapes
window = pyglet.window.Window(500, 500)
batch = pyglet.graphics.Batch()
red_sequare = shapes.Rectangle(150, 240, 200, 20, color=(255, 55, 55), batch=batch)
green_sequare = shapes.Rectangle(175, 220, 150, 20, color=(55, 255, 55), batch=batch)
blue_sequare = shapes.Rectangle(200, 200, 100, 20, color=(55, 55, 255), batch=batch)
@window.event
def on_draw():
window.clear()
batch.draw()
pyglet.app.run()
Which would produce:
Upvotes: 2
Reputation: 211277
the anchor of the image has to be integral. You have to use the floor division operator (//
) rather than the division operator (/
) when you compute anchor_x
respectively anchor_y
:
(See Binary arithmetic operations)
def center_images(images):
for image in images:
image.anchor_x = image.width // 2
image.anchor_y = image.height // 2
center_images([column_img, disk7_img, disk5_img, disk3_img])
Upvotes: 2