简体   繁体   中英

How do you draw simple shapes in Pyglet?

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!

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

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:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM