提问人:Rabinzel 提问时间:10/20/2021 最后编辑:DharmanRabinzel 更新时间:10/20/2021 访问量:248
在某些情况下,在两个不同的事件中更改一个字典会导致 KeyError(因为键事件的时间 + 由于 dt 导致的事件)
Changing one dictionary at two different events leads to KeyError in some cases (because of timing of key event + event due to dt)
问:
底部最后一个问题的副本: “我不知道如何解决这个错误。一个动作与时间相关,另一个动作与玩家输入相关。有人有想法吗?python 中是否有一些东西可以处理一个对象在不同时间从不同地点更改的情况?
我在 Pygame 中编写自己的俄罗斯方块。目前,我的目标是从这里重建游戏模式“生存”: https://jstris.jezevec10.com/?play=4 玩家需要尽可能长时间地生存,而每 1 秒就会在底部添加一条只有 1 个空闲位置的新线,并将游戏领域向顶部移动。
我的问题是,有一个 key.event,玩家掉落一个棋子并用该动作清除一行,另一方面,还有一个时间事件,每隔一秒就会随机添加一行到字段中。这两个事件都会更改字典中的值。通常,此代码有效,但是根据操作,代码会抛出错误的时间窗口非常小。
我的游戏的简短说明: 有一个网格(列表列表 10x20),其中每个元素都是 RGB 颜色 (0,0,0),每次都以黑色开头,并将填充当前掉落的棋子的信息(颜色)或底部的字段锁定棋子。网格将每帧绘制一次。已经放置的棋子存储在字典中。网格每次在绘制之前都会请求锁定部分的字典。
在这张图片中,您看到了原始游戏。此时,字段中已经添加了 6 行。 每条线都将在字段底部生成灰色,并带有一个自由的随机点。每次生成一行时,信息都会添加到我的“锁定”字典中 ( key = (x,y) : value = (153,153,153) ),并且一个函数将每个键中的 y 值更改 1 到顶部。 同时,如果玩家清除了一行(在这张图片中,它是从底部开始计数的第 6 行),则有一个函数会在“锁定”字典中删除该清除的行,并将所有大于该行的 y 值更改 1 到底部。
以下是两个函数:
def clear_rows(grid, locked): # (0,0) is at the top left, x increases right, y increases down
i = len(grid) - 1 # last row
rows_cleared = 0
while i > -1:
row = grid[i]
if BLACK not in row: #which means the row is full and can be cleared
i_new = i + rows_cleared
for j in range(len(row)):
del locked[(j, i_new)]
rows_cleared += 1
for key in sorted(list(locked), key=lambda x: x[1])[::-1]:
x_coord, y_coord = key
if y_coord < i_new:
new_key = (x_coord, y_coord + 1)
locked[new_key] = locked.pop(key)
i -= 1
else:
i -= 1
return rows_cleared
和
def survival_add_line(locked):
for key in sorted(list(locked)):
x, y = key
new_key = (x, y - 1)
locked[new_key] = locked.pop(key)
gap = random.randint(0,9)
for i in range(10):
if not i == gap:
locked[(i, 19)] = SURVIVAL_GRAY
这是我的主循环中的代码:
if level_time / 1000 >= 1:
survival_add_line(locked)
level_time = 0
if change_piece:
for pos in tetrimino_position:
locked[(pos[0], pos[1])] = current_piece.color
current_piece = next_pieces[0]
next_pieces.pop(0)
next_pieces.append(new_tetromino())
change_piece = False
cleared_lines += clear_rows(grid, locked)
我注意到这个错误只能发生在字段的最底部。如果我理解正确的话,当玩家在 survival_add_line() 已经被调用但在 change_piece 之前的那一刻掉落一个棋子时,就会发生这种情况。 Survival_add_line() 将每一行都移到顶部,然后 clear_row 函数想要删除最后一行(现在是倒数第二行),并且找不到最后一行中的键来删除 --> KeyError。
我不知道如何解决这个错误。一个动作与时间相关,另一个动作与玩家输入相关。 有人有想法吗? python 中是否有一些东西可以处理一个对象在不同时间从不同位置更改的情况?
答:
if/elif 块不是用 if 调用这两个语句,而是完成工作!(change_piece现在可以延迟 1 帧,但这对玩家来说并不明显)
代表提问者发布
评论