Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use pyglet within a class

In all the tutorials on the web I've seen with Pyglet, it doesnt seems that any of them have used classes to contain the pyglet.window.Window instance. For example, most tutorials seem to go something like

import pyglet

game_window = pyglet.window.Window()

@game_window.event
def on_draw():
    #dostuff

while __name__ == "__main__":
    pyglet.app.run()

I'm having trouble restructuring this code into a class. My code which is intended to do so, is here:

import pyglet
from pyglet.gl import *
from Board import Board

class Frontend:
    def __init__(self,xs, ys):
        self.GameInstance = Board(xs,ys)
        self.GameWindow = pyglet.window.Window(width=512, height=512,visible=False)

    @GameWindow.event
    def on_draw(self):
        self.GameWindow.clear()

f = Frontend()

When I run this code, I get the following error:

Traceback (most recent call last):
  File "C:/Users/PycharmProjects/Nothing/2048/Frontend.py", line 7, in <module>
    class Frontend:
  File "C:/Users/PycharmProjects/Nothing/2048/Frontend.py", line 13, in Frontend
    @GameWindow.event
NameError: name 'GameWindow' is not defined

When I replace @GameWindow.event with @self.GameWindow.event in an attempt to resolve the NameError I get:

Traceback (most recent call last):
    File "C:/Users/PycharmProjects/Nothing/2048/Frontend.py", line 7, in <module>
    class Frontend:
    File "C:/Users/PycharmProjects/Nothing/2048/Frontend.py", line 13, in Frontend
    @self.GameWindow.event
NameError: name 'self' is not defined

Which i expect. However, I'm not sure why this code isnt working - can someone explain why and how to fix it?

like image 486
pipsqueaker117 Avatar asked Jul 08 '14 18:07

pipsqueaker117


2 Answers

You can inherit from Window. This should work:

class Frontend(pyglet.window.Window):
    def __init__(self, xs, ys):
        self.GameInstance = Board(xs,ys)
        super().__init__(width=512, height=512,visible=False)

    def on_draw(self):
        self.clear()

Your code is not working because you can not reference the instance of the Frontend class outside the methods. If you will have only one instance of the Frontend class you can do something like:

class Frontend:
    window = pyglet.window.Window()
    def __init__(self):
        ...
    @window.event
    def on_draw():
        ...
like image 132
ragezor Avatar answered Sep 17 '22 22:09

ragezor


As I've commented on ragezor's answer, the pyglet docs recommend inheritance.

But another option may be to separate the event handling logic in its own class, as an EventDispatcher: http://pyglet.org/doc-current/programming_guide/events.html#creating-your-own-event-dispatcher

Personally, if I knew would only have one Frontend instance, I would question the necessity of having a class. But that's a whole can of worms. Thought I'd give you another nice option, at least, you can't go wrong inheriting from Window though, especially if all your events are Window-related.

A third idea (fourth I guess since ragezor gave you two options):

class Frontend:

def __init__(self,xs, ys):
    self.GameInstance = Board(xs,ys)
    self.GameWindow = pyglet.window.Window(width=512, height=512,visible=False)

    self.on_draw = self.GameWindow.event(self.on_draw)

def on_draw(self):
    self.GameWindow.clear()

In other words, apply the @GameWindow.event decorator manually.

One last thing, don't use camelcase for attributes, it goes against PEP8 convention and confused me for a second while editing this code. Call it game_window instead.

like image 43
ontologist Avatar answered Sep 21 '22 22:09

ontologist