我希望赏金能吸引一个懂一件事的人
关于PyGame的内部工作原理(我尝试查看
源代码。。有很多),可以告诉我这是不是真的
与threading.py的存在有关,或者如果有一些实践
我可以避免
一般来说
以防止这种情况发生在其他
PyGame项目。
我为当
obj.kill()
被调用。
def make_explosion(obj, func):
def inner(*args, **kwargs):
newX, newY = obj.x, obj.y
newBoom = Explosion(newX, newY)
allqueue.add(newBoom) #an instance of pygame.sprite.Group
return func(*args, **kwargs)
return inner
它获取对象的x和y坐标,然后创建
Explosion
在这些坐标处,将其添加到
allqueue
我用它来确保一切
update
d,并最终返回其包装的函数-在本例中,
obj.kill
.
obj.kill()
是一个
pygame.sprite.Sprite
方法,该方法将对象从
sprite.Group
它所属的。
然后,在创建
Enemy
.
newEnemy = Enemy()
##other code to add new AI, point valuesâ¦eventually, the following happens:
newEnemy.kill = make_explosion(newEnemy, newEnemy.kill)
当我运行游戏时,爆炸出现在随机的地方,而不是物体实际x和y坐标附近的任何地方。有趣的是,它甚至不像是发生在物体的原点(x,y),甚至在它们在屏幕上短暂存在期间所走过的路径上或附近(我很擅长自己的游戏,不是吹牛),所以我觉得我必须排除在包装方法时分配x和y的可能性。
有点漫无目的,我四处乱逛,把代码改成了这样:
def make_explosion(obj, func):
def inner(*args, **kwargs):
allqueue.add(Explosion(obj.x, obj.y))
return func(*args, **kwargs)
return inner
此更改使其“按预期”工作——当对象
self.kill()
方法时,爆炸将出现在正确的坐标上。
我不明白的是
为什么?
这有效!特别是考虑到PyGame的文档,其中指出
kill()
不一定要删除对象;它只是从它所属的所有组中删除它。
从…起
https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Sprite.kill
--
基尔()
从所有组中移除精灵kill()->没有一个
精灵将从包含它的所有组中移除。这不会改变
关于雪碧的状态。可以继续
调用此方法后使用Sprite,包括添加它
到组。
所以,尽管我无意中找到了问题的解决方案,但我实际上根本不明白。为什么它会这样?
编辑:根据早期的一些评论,我试图在不使用PyGame库的情况下重现类似的情况,但我无法做到这一点。
Par示例:
>>> class A(object):
... def __init__(self, x, y):
... self.x = x
... self.y = y
... def go(self):
... self.x += 1
... self.y += 2
... print "-go-"
... def stop(self):
... print "-stop-"
... print "(%d, %d)" % (self.x, self.y)
... def update(self):
... self.go()
... if self.x + self.y > 200:
... self.stop()
>>> Stick = A(15, 15)
>>> Stick.go()
-go-
>>> Stick.update()
-go-
>>> Stick.x
17
>>> Stick.y
19
>>> def whereat(x, y):
... print "I find myself at (%d, %d)." % (x, y)
...
>>> def wrap(obj, func):
... def inner(*args, **kwargs):
... newX, newY = obj.x, obj.y
... whereat(newX, newY)
... return func(*args, **kwargs)
... return inner
...
>>> Stick.update = wrap(Stick, Stick.update)
>>> Stick.update()
I find myself at (17, 19).
-go-
>>> Stick.update()
I find myself at (18, 21).
-go-
>>> Stick.update()
I find myself at (19, 23).
-go-
所以,我马上注意到
whereat()
正在呼叫
之前
坐标的变化
Stick.go()
所以它使用
x
和
y
就在递增之前,但这很好;我可以很容易地更改包装,直到
go()
被调用。这个问题不像我的PyGame项目中那样出现在这里;爆炸甚至不是“相邻的敌人”,它们会出现在各种各样的随机位置,而不是精灵先前的(x,y)坐标(如果有,我可能根本没有注意到问题!)。
更新:
在一条用户评论让我感到疑惑后,我在网上搜索了一下
cProfile
在所讨论的项目上,瞧,PyGame肯定利用了
threading.py
不幸的是,同一个互联网不足以准确地告诉我
怎样
PyGame使用
螺纹.py
,所以显然我需要了解线程是如何工作的。Oi.:)
在读了一点PyGame源代码之后(bleh),我发现了一个模块,它似乎可以仲裁PyGame何时以及为什么产生线程。从我对线程所知甚少的情况来看,这可能会导致类似种族状况的情况;没有为包装器执行“及时”定义x,因此它(
爆炸
对象)在错误的位置结束。我看到在一个不同的项目中出现了其他错误,这对数学来说有点重;这些更像是核心转储,但它们通常涉及
pulse
无法获取事件,或等待事件超时,或类似情况(我确实有一个v.long堆栈跟踪,以防任何人睡眠困难)。
最后,我怀疑这是我可以通过坚持某些实践来避免的,但我不知道这些实践实际上会是什么
是
,我不知道如何阻止PyGame仲裁哪些进程获得了自己的线程,而这比不这样做更糟糕。如果有一个统一的理论来解释这一切,我肯定很想知道。