Pyglet не рисует запланированную функцию

Итак, я полный новичок как в pyglet, так и в OpenGL, мне интересно, почему это не работает:

def DrawCircle(cx, cy, r, segments):

theta = 2*3.1415926/segments
c = math.cos(theta)
s = math.sin(theta)

x = r
y = 0

pyglet.gl.glBegin(pyglet.gl.GL_POLYGON)
pyglet.gl.glColor3f(0.05,0.2,0.9)
for counter in range(segments):
    pyglet.gl.glVertex2f(x+cx, y+cy)
    t = x
    x = c * x - s * y
    y = s * t + c * y
pyglet.gl.glEnd()

if __name__ == '__main__':
window = pyglet.window.Window(960,1010)
window.set_location(959,20)

@window.event
def on_draw():
    window.clear()

def update(dt):
    print(dt)
    DrawCircle(500,500,20,30)

pyglet.clock.schedule_once(update,0.6)    
pyglet.app.run()

Проще говоря, если я вызову DrawCircle из on_draw, он создаст именно такой круг, как хотелось бы. Если я запланирую это, ничего не будет нарисовано. Сам планировщик работает, потому что dt печатает в консоль. Я предполагаю, что on_draw устанавливает контекст или что-то, что позволяет ему рисовать, тогда как, когда я планирую его, контекст или, возможно, буфер неправильный. Любая помощь будет принята с благодарностью.


person user3573328    schedule 08.08.2014    source источник


Ответы (2)


Попробуйте добавить window.switch_to() перед вызовом отрисовки и window.flip() после функции обновления.

Хотя, как упоминалось в ответе msarch, вам следует избегать рисования функции обновления и позволить функции on_draw обрабатывать ее.

person ebbs    schedule 08.08.2014
comment
Хммм, я ранее пробовал window.switch_to() и, похоже, это не решило проблему. Чтобы уточнить, я просто тестирую с schedule_once... В конечном итоге я собираюсь написать базовый симулятор частиц и хочу неоднократно перерисовывать круг (который будет представлять частицу). Возможно, это сложный способ сделать это, но, учитывая, насколько простым будет конечный визуальный эффект, я подумал, что это не имеет значения. - person user3573328; 08.08.2014
comment
Если это двойная буферизация, вы также должны добавить window.flip() в конце функции обновления. - person ebbs; 08.08.2014
comment
Ага, я пробовал это, когда случайно пытался решить проблему, но я не подумал попробовать их вместе. Конечно, теперь я понимаю, почему все просто используют on_draw, потому что все равно все нужно перерисовывать, поскольку, насколько я могу судить, нет возможности простаивать в цикле обновления до следующего обновления. Во всяком случае, у меня есть лучшее представление о том, как теперь работает цикл событий и как обеспечить правильную буферизацию + контекст. - person user3573328; 08.08.2014

Вот правильный код:

import pyglet
import math

window = pyglet.window.Window(960,1010)
window.set_location( 50,50)

def DrawCircle(cx, cy, r, segments):

    theta = 2*3.1415926/segments
    c = math.cos(theta)
    s = math.sin(theta)

    x = r
    y = 0

    pyglet.gl.glColor3f(0.05,0.2,0.9)
    pyglet.gl.glBegin(pyglet.gl.GL_POLYGON)

    for counter in range(segments):
        pyglet.gl.glVertex2f(x+cx, y+cy)
        t = x
        x = c * x - s * y
        y = s * t + c * y

    pyglet.gl.glEnd()

@window.event
def on_draw():
    window.clear()
    DrawCircle(500,500,20,30)


if __name__ == '__main__':
    pyglet.app.run()

В Pyglet все рисунки обычно выполняются методом on_draw. Поскольку вы очищаете окно при каждой перерисовке, вам также приходится каждый раз рисовать свою фигуру.

Функция обновления не обязательно связана с отображением

Планирование один раз или с регулярным интервалом обычно используется для изменения различных параметров через регулярные промежутки времени (т.е.: x,y += dx,dy *dt для анимации).

см. http://pyglet.org/doc/api/pyglet.clock-module.html

person msarch    schedule 08.08.2014
comment
Как я сказал ниже, я намерен в конечном итоге сделать анимацию, постоянно перерисовывая круг. Возможно, мне было бы лучше использовать спрайт. В любом случае, чего я в конечном итоге хочу добиться, так это: начните рисовать клетку, в идеале ее не нужно будет постоянно перерисовывать. Затем добавьте внутрь клетки небольшой шарик, положение которого будет постоянно обновляться. Я не уверен, что понимаю обработчик событий, но я подумал, что поместить клетку в on_draw (что я уже сделал) и поместить круг в функцию обновления — вот как это делается. - person user3573328; 08.08.2014
comment
круг и клетка рисуются в каждом кадре с помощью on_draw(). Обновление координат кругов происходит с той скоростью, которую вы выбрали в другой функции, которую вы вызываете с помощью метода clock.schedule с указанной вами скоростью. - person msarch; 09.08.2014
comment
Да, я неправильно понял, что on_draw вызывается только в начале. Я понял, что был неправ, когда после реализации решения ebbs круг сразу исчез, так как снова был отправлен on_draw. В любом случае было полезно узнать, что on_draw делает в фоновом режиме в отношении перелистывания буфера и т.д. - person user3573328; 09.08.2014