TypeError: unhashable type: 'list' In pyglet

TypeError: unhashable type: 'list' In pyglet

所以在受到 code bullet 的启发后尝试了 pyglet。最近我一直在用它创建许多小游戏和模拟。当前的游戏是一只飞扬的小鸟(很确定你们都玩过)。所以我今天的任务是用 pyglet 编写 flappybird。但是像往常一样,我遇到了一个问题,尽管因为我使用的是 pyglet,所以这个问题有很多问题和答案,但所有其他答案都没有用。 我为 flappy bird 编写的代码非常简单。我有 2 类 只鸟和烟斗,我使用批次和组渲染它们。这里:

import math, sys
import pyglet, random
from pyglet.window import key, mouse

window = pyglet.window.Window(width=335, height=540, caption="FLAPPY BIRD!")

batch = pyglet.graphics.Batch()
background = pyglet.graphics.OrderedGroup(0)
pipes = pyglet.graphics.OrderedGroup(1)
foreground = pyglet.graphics.OrderedGroup(2)
player = pyglet.graphics.OrderedGroup(3)

bg = pyglet.image.load("background.png")
background_1 = pyglet.sprite.Sprite(bg, 0, 0, batch=batch, group=background)
background_2 = pyglet.sprite.Sprite(bg, bg.width, 0, batch=batch, group=background)

base = pyglet.image.load("base.png")
base_1 = pyglet.sprite.Sprite(base, 0, 0, batch=batch, group=foreground)
base_2 = pyglet.sprite.Sprite(base, base.width, 0, batch=batch, group=foreground)

bird_image = pyglet.image.load("yellowbird-midflap.png")
bird_image.anchor_x = bird_image.width // 2
bird_image.anchor_y = bird_image.height // 2

class Bird:
    def __init__(self):
        self.charector = \
            pyglet.sprite.Sprite(bird_image, window.width * 0.2, window.height/2, batch=batch, group=player)
        self.y_speed = 0
        self.rotation_vel = 0
        self.alive = True
    
    def update(self):
        self.y_speed -= 0.6
        self.rotation_vel += 1
        self.charector.y += self.y_speed
        self.charector.rotation = min(self.rotation_vel, 90)
    
    def jump(self):
        self.y_speed = 7 * 1.5
        self.rotation_vel = -35

bird_image = pyglet.image.load("yellowbird-midflap.png")

class Pipe:
    tp = pyglet.image.load("down-pipe.png")
    bp = pyglet.image.load("pipe.png")
    
    def __init__(self):
        self.top_pipe = pyglet.sprite.Sprite(self.tp, x = window.width + 100, y = random.randint(325, 484), batch=batch, group=pipes)
        self.bottom_pipe = pyglet.sprite.Sprite(self.bp, x = window.width + 100, y = self.top_pipe.y - 125 - self.bp.height, batch=batch, group=pipes)
    
    def update(self):
        self.top_pipe.x -= 3
        self.bottom_pipe.x -= 3

bird = Bird()
pipes = [Pipe()]
time_created_pipe = 50

def update_char(dt):
    global time_created_pipe,  pipes

    if bird.alive:
        bird.update()
        for pipe in pipes:
            pipe.update()
            if pipe.top_pipe.x <= -100:
                pipes.remove(pipe)
            
        if time_created_pipe <= 0:
            time_created_pipe = 50
            pipes.append(Pipe())
        time_created_pipe -= 1


def update_bg(dt):
    if bird.alive:
        background_1.x -= 0.5
        background_2.x -= 0.5
        if background_1.x <= -bg.width:
            background_1.x = bg.width
        if background_2.x <= -bg.width:
            background_2.x = bg.width
        
        base_1.x -= 1.5
        base_2.x -= 1.5
        if base_1.x <= -base.width:
            base_1.x = base.width
        if base_2.x <= -base.width:
            base_2.x = base.width

@window.event
def on_mouse_press(x, y, button, modifiers):
    if button == mouse.LEFT:
        bird.jump()

@window.event
def on_draw():
    window.clear()
    batch.draw()

pyglet.clock.schedule_interval(update_char, 1/60)
pyglet.clock.schedule_interval(update_bg, 1/60)
pyglet.app.run()

但是第二个我 运行 代码发生了这种情况:

back (most recent call last):
File "c:\Users\Tejas&Shiva\OneDrive\Desktop\HTCODEATHON PYTHON PRACTICE\Day4\flappy bird.py", line 105, in <module>
    pyglet.app.run()
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\app\__init__.py", line 107, in run
    event_loop.run()
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\app\base.py", line 169, in run
    timeout = self.idle()
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\app\base.py", line 239, in idle
    redraw_all = self.clock.call_scheduled_functions(dt)
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\clock.py", line 292, in call_scheduled_functions
    item.func(now - item.last_ts, *item.args, **item.kwargs)
File "c:\Users\Tejas&Shiva\OneDrive\Desktop\HTCODEATHON PYTHON PRACTICE\Day4\flappy bird.py", line 73, in update_char
    pipes.append(Pipe())
File "c:\Users\Tejas&Shiva\OneDrive\Desktop\HTCODEATHON PYTHON PRACTICE\Day4\flappy bird.py", line 50, in __init__
    self.top_pipe = pyglet.sprite.Sprite(self.tp, x = window.width + 100, y = random.randint(325, 484), batch=batch, group=pipes)
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\sprite.py", line 246, in __init__
    self._create_vertex_list()
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\sprite.py", line 391, in _create_vertex_list
    self._vertex_list = self._batch.add(
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\graphics\__init__.py", line 366, in add
    domain = self._get_domain(False, mode, group, formats)
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\graphics\__init__.py", line 443, in _get_domain
    self._add_group(group)
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\graphics\__init__.py", line 468, in _add_group
    if group.parent not in self.group_map:
TypeError: unhashable type: 'list'

我猜是管道列表有问题,但不确定原因。有什么解决办法吗?

问题是名称 pipes 被使用了两次。 First 用于管道的 OrderedGroup。在该组中,添加了初始 pipe 批次:

pipes = pyglet.graphics.OrderedGroup(1)

然而,它随后被用于 pipes 的列表。原始组 pipes 被管道列表隐藏,创建新的 Pipe 对象失败:

pipes = [Pipe()]

组和列表使用不同的名称。重命名列表:

pipes_list = [Pipe()]
time_created_pipe = 50

def update_char(dt):
    global time_created_pipe, pipes_list

    if bird.alive:
        bird.update()
        for pipe in pipes_list:
            pipe.update()
            if pipe.top_pipe.x <= -100:
                pipes_list.remove(pipe)
            
        if time_created_pipe <= 0:
            time_created_pipe = 50
            pipes_list.append(Pipe())
        time_created_pipe -= 1