Я разрабатываю небольшую игру с пикетом. Разумеется, одним центральным элементом являются цветные прямоугольники. Сначала я сделал это, создав образы в памяти и blit()
их, которые отлично работали. После того, как вы заметили, насколько уродливые, обходные и неэффективные (да, я профилировал - ColorRect.draw()
занял значительное время и стал в 10 раз более эффективным благодаря этому изменению), я начал создавать списки вершин вместо pyglet.graphics.Batch
(я скопировал большую часть кода дословно из один из примеров). С тех пор я испытываю странное исключение в каком-то низкоуровневом коде OpenGL, в котором я не смог найти причину или воспроизвести надежно.pyglet.graphics: IndexError при создании массива ctypes
Нет никакого явного отношения к событиям геймплея - как и в случае, ничего исключительного не происходит непосредственно перед этим, или я постоянно его пропускаю. Поскольку ошибка происходит где-то глубоко в цикле событий, я не могу легко отследить, какое из них обновляет положение. Честно говоря, я в тупике. Таким образом, я буду следить за тем, что я узнал, и надеяться на какой-то экстрасенс.
Я пробовал это на Windows 7 32 бит (я могу обойти его в Ubuntu 11.10 в ближайшее время) с Python 3.2.2, с версией пиглета 043180b64260 (вытащенный из кода Goggle и построенный из источника, Версия 1.1.4 сложнее установить, так как она не запускается автоматически 2to3, хотя, похоже, она также готова к работе py3k). Вероятно, я обновлю последнюю версию меркурийской версии, но это всего лишь несколько коммитов, и изменения кажутся совершенно несвязанными.
Полные отслеживающая (цензура некоторых путей из принципа, но обратите внимание, что это в своем собственном 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_textures
(гдеself
- это объект окна). Соответствующий комментарий говорит, что этот блок кода выпускает текстуру, запланированную для удаления. Я не думаю, что я явно использую текстуры где угодно, но кто знает, что делает пиглет под капотом. Я предполагаю, что эти целые числа являются идентификаторами или чем-то вроде текстур, подлежащих уничтожению.gl.GLuint
- это псевдоним дляctypes.c_ulong
; Таким образом,(gl.GLuint * len(buffers))(*buffers)
создает массивulong
той же длины и содержимого- Я могу оценить одно и то же выражение в подсказке
pdb
без ошибок или повреждения данных.
Независимые эксперименты (вне virtualenv и без импорта pyglet) с ctypes показывает, что IndexError
возникает, если слишком много аргументов приведены в конструкторе массива. Это не имеет смысла, и эксперименты, и логика предполагают, что длина и аргумент count всегда должны совпадать.
- Есть ли другие случаи, когда это исключение может возникнуть? Может быть, это ошибка пеглета, или я неправильно использую библиотеку и пропустил соответствующее предупреждение?
- Будет ли код, который создает и поддерживает списки вершин, может быть использован для отладки? Вероятно, что-то не так. Я уже смотрел на него, но, поскольку у меня мало опыта работы с
pyglet.graphics
, это было ограниченным использованием. Просто оставьте комментарий, если вы хотите увидеть кодColorRect
. - Любые другие идеи, что может вызвать это?
Можете ли вы сделать shure, не используется многопоточность? Это может вызвать проблемы в 'base.py', если задействованы несколько потоков. «Буферы» могут быть изменены другим потоком, пока массив выделяется до того, как отдельные конструкторы GLuint будут запущены для его заполнения. Таким образом, 'len (buffer)' не будет соответствовать '(* buffers)' length. – dronus
@dronus Неожиданная идея! Я нигде не использую нити, и я сомневаюсь, что пиглет пытается работать параллельно. Но я проверю, '' _thread 'в sys.modules'. – delnan
@dronus Забудьте о '_thread', он, видимо, всегда импортируется (я проверил в сеансе свежего интерпретатора). 'threading' с другой стороны импортируется в моем коде, но не в сеансах интерпретатора. 'threading.enumerate' дает просто' [<_MainThread (MainThread, start 4256)>] 'хотя. Я добавлю утверждение, что это всегда верно, и исследуйте, кто импортировал 'threading'. – delnan