我正在使用pygame构建一个简单的游戏并拥有以下主循环,其中mouse()
是捕获和处理鼠标事件的函数,keyboard()
用于键盘事件:
def mainLoop():
pygame.event.pump()
keyboard(pygame.key.get_pressed())
events = pygame.event.get()
mouse(events)
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
return False
return True
当玩家点击某个牌时,我有mouse()
调用的以下函数:
def objReach(obj, pos):
try:
path = obj.reach(pos, move=False) # A* (path-finding algorithm)
for step in path:
sleep(1.0/obj.speed)
objMove(obj, step)
except Exception as e:
sendMsg(str(e))
问题是,当对象走在路径上时(for
循环正在运行),鼠标事件不会被捕获,所以如果玩家在中间点击另一个磁贴,则什么都没有发生。我希望玩家能够改变路径。
我尝试在mainLoop
循环中使用for
,但它只是部分有效 - 它只捕获MOUSEBUTTONUP
事件,而不是UP和DOWN事件,这些都是确定如果玩家只是点击或拖放。这是澄清的mouse()
函数:
def mouse(events):
global clickPos
global releasePos
for event in events:
if event.type == MOUSEBUTTONDOWN:
clickPos = getPos(pygame.mouse.get_pos())
# getPos() transforms screen coordinates in game coordinates
elif event.type == MOUSEBUTTONUP:
releasePos = getPos(pygame.mouse.get_pos())
if event.button == MAIN_BUTTON:
# Simple click
if clickPos == releasePos:
if player.privilege > 1:
objMove(player, getPos(pygame.mouse.get_pos()))
else:
objReach(player, getPos(pygame.mouse.get_pos()))
# Drag and drop
else:
obj = player.place.matrix[clickPos[0]][clickPos[1]][-1]
objThrow(obj, clickPos, releasePos)
elif event.button == SECONDARY_BUTTON:
pass # TODO: ...
我不熟悉多线程,我不认为它应该与pygame一起使用,但这是我唯一能想到的。有什么想法吗?
答案 0 :(得分:2)
您可以尝试修改对象,使其具有类似objReach
列表的内容,而不是使用多线程并直接导致对象在obj
函数内移动并阻止主循环。它基本上充当一个队列,其中包含要移动到的每个位置的坐标。
然后,你要做的是当点击鼠标时,使用你的寻路算法找到对象应该走的路径并用它替换队列:
import time
def objReach(obj, pos):
try:
obj.path = obj.reach(pos, move=False) # A* (path-finding algorithm)
obj.last_move = time.time()
obj.move_after = 1 # move every 1 second.
except Exception as e:
sendMsg(str(e))
然后,在你的主循环中,每秒一次(使用某种计时器来跟踪1秒过去的时间),让你的对象弹出列表中的下一个坐标并移动到它。
它看起来像这样:
def mainLoop():
pygame.event.pump()
keyboard(pygame.key.get_pressed())
events = pygame.event.get()
mouse(events)
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
return False
if time.time() - obj.last_move > obj.move_after:
obj.last_move = time.time()
objMove(obj, obj.path.pop())
return True
这样,使对象移动的代码被重新定位到mainloop中,这样您仍然可以响应所有事件。
如果用户点击新图块,则会自动覆盖该路径,并且主循环将正确执行正确的操作。
如果您正确构建了代码,您甚至可以扩展游戏,以便它可以同时处理多个在磁贴上移动的对象,以不同的速度移动。