3

我正在用 pyglet 开发一个小游戏。当然,其中一个核心是绘制彩色矩形。我最初是通过在内存中创建图像并blit()ing 来做到这一点的,效果很好。在注意到多么丑陋、迂回和低效(是的,我分析过——ColorRect.draw()花费了大量时间并且通过这个改变变得效率提高了 10 倍)之后,我开始创建顶点列表,而不是通过pyglet.graphics.Batch(我从其中一个逐字复制了大部分代码)例子)。从那时起,我在一些低级 OpenGL 代码中遇到了一个奇怪的异常,我无法找到原因或可靠地重现该异常。

与游戏事件没有明显的关系——例如,之前没有发生任何异常情况,或者我经常想念它。由于错误发生在事件循环的某个深处,我无法轻松追踪是哪个位置更新导致它。老实说,我很难过。因此,我将把我发现的东西全都抛在脑后,并希望有某种通灵者。

我已经使用 Python 3.2.2 在 Windows 7 32 位(我可能很快会在 Ubuntu 11.10 上尝试)使用 pyglet 修订版 043180b64260(从 Goggle Code 提取并从源代码构建,1.1.4 版本)进行了尝试更难安装,因为它不会自动运行 2to3,尽管它似乎同样支持 py3k)。接下来我可能会更新到最新的 mercurial 版本,但这只是几个提交,而且这些更改似乎完全不相关。

完整的回溯(审查了一些不符合原则的路径,但请注意它在它自己的 virtualenv 中):

Traceback (most recent call last):
  File "<my main file>", line 152, in <module>
    main()
  File "<my main file>", line 148, in main
    run()
  File "<my main file>", line 125, in run
    pyglet.app.run()
  File "<virtualenv>\Lib\site-packages\pyglet\app\__init__.py", line 123, in run
    event_loop.run()
  File "<virtualenv>\Lib\site-packages\pyglet\app\base.py", line 135, in run
    self._run_estimated()
  File "<virtualenv>\Lib\site-packages\pyglet\app\base.py", line 164, in _run_estimated
    timeout = self.idle()
  File "<virtualenv>\Lib\site-packages\pyglet\app\base.py", line 278, in idle
    window.switch_to()
  File "<virtualenv>\Lib\site-packages\pyglet\window\win32\__init__.py", line 305, in switch_to
    self.context.set_current()
  File "<virtualenv>\Lib\site-packages\pyglet\gl\win32.py", line 213, in set_current
    super(Win32Context, self).set_current()
  File "<virtualenv>\Lib\site-packages\pyglet\gl\base.py", line 320, in set_current
    buffers = (gl.GLuint * len(buffers))(*buffers)
IndexError: invalid index

运行事后分析(积极地逐步执行代码,直到它碰巧不可行,因为 FPS 从 60 下降到 7)pdb显示:

  • buffers是一个整数列表;我不知道这些代表什么或它们来自哪里,但它们是从一个名为self.object_space._doomed_texturesself窗口对象在哪里)的列表中提取的。相关的评论说这个代码块释放了计划删除的纹理。我认为我没有在任何地方明确使用纹理,但谁知道 pyglet 在引擎盖下做了什么。我假设这些整数是 ID 或要销毁的纹理。
  • gl.GLuintctypes.c_ulong;的别名 因此(gl.GLuint * len(buffers))(*buffers)创建了ulong一个长度和内容相同的数组
  • 我可以在pdb提示符下评估完全相同的表达式,而不会出现错误或数据损坏。

使用 ctypes 的独立实验(在 virtualenv 之外并且没有导入 pyglet)表明,IndexError如果给数组构造函数提供了太多参数,则会引发这种情况。这是没有意义的,实验和逻辑都表明长度和参数计数必须始终匹配。

  1. 还有其他可能发生此异常的情况吗?这可能是 pyglet 的错误,还是我滥用库并错过了相关的警告?
  2. 创建和维护顶点列表的代码在调试中是否有用?它可能有什么问题。我已经盯着它看了,但是由于我对 的经验很少pyglet.graphics,所以它的用处有限。如果您想查看ColorRect代码,请发表评论。
  3. 任何其他想法可能导致这种情况?
4

1 回答 1

0

提供一个真正相关的答案有点困难,因为没有提供代码,但从错误输出中我可以看到。

buffers = (gl.GLuint * len(buffers))(*buffers)

因此,如果我理解正确,您将 GLuint(4 字节)的大小与实际缓冲区长度(如果已初始化)相乘。也许这就是您的索引无效的原因,因为它太高了?

通常这是可以的,因为缓冲区是以字节为单位的,但你说它是一个整数列表?

希望能帮助到你

于 2012-03-08T07:50:31.637 回答