Nedílnou součástí prakticky všech multimediálních aplikací a samozřejmě také her je čtení stavu vstupních zařízení, tj. především klávesnice, myši, joysticků či dotykové obrazovky. I tuto oblast je možné pokrýt funkcemi z knihovny Pyglet. V dnešním článku se zaměříme na popis práce s klávesnicí, což není zdaleka tak triviální, jak by se mohlo na první pohled zdát.

Obsah

1. Multimediální knihovna Pyglet: práce se vstupními zařízeními

2. Událost on_key_press

3. Událost on_key_release

4. První demonstrační příklad: zachycení události stisku a puštění klávesy

5. Modifikátory (Shift, Control, Alt atd.)

6. Druhý demonstrační příklad: test modifikátorů bez rozlišení, zda se nachází na levé či pravé straně klávesnice

7. Třetí demonstrační příklad: vizuální zobrazení stisku kláves Shift a Control

8. Pole se stavy všech kláves

9. Čtvrtý demonstrační příklad: využití pole se stavy všech kláves

10. Událost on_text aneb detekce napsaných (Unicode) znaků

11. Pátý demonstrační příklad: použití události typu on_text

12. Problematika pohybu v textu a její řešení: událost typu on_text_motion

13. Šestý demonstrační příklad: využití události on_text_motion

14. Sedmý demonstrační příklad: událost on_text_motion a pohyb spritu ve scéně

15. Repositář s demonstračními příklady

16. Odkazy na Internetu

1. Multimediální knihovna Pyglet: práce se vstupními zařízeními

V knihovně Pyglet existuje podpora pro několik typů vstupních zařízení. V první řadě se pochopitelně jedná o klávesnici a myš (popř. touchpad), což jsou dnes standardní zařízení dostupná na desktopech i noteboocích. Kromě toho jsou však podporována i další zařízení, zejména joysticky, různé typy pedálů, volanty, dotykové obrazovky atd. Pro přístup k těmto zařízením se používají buď specializované callback funkce nebo je nutné použít modul pyglet.input. Dnes se budeme převážně zabývat popisem způsobu práce s klávesnicí, což ve skutečnosti není v oblasti her a multimediálních aplikací zdaleka tak triviální, jak by se mohlo na první pohled zdát, na rozdíl od běžných (řekněme kancelářských) aplikací s GUI či CLI, které používají klávesnici buď pro vstup znaků (textu) či pro ovládání uživatelského rozhraní.

2. Událost on_key_press

Základní callback funkcí, která se používá při práci s klávesnicí, je funkce nazvaná on_key_press. Tato funkce musí být přes anotaci @jméno_proměnné_reprezentující_okno.event navázána na vybrané okno. Jinými slovy to znamená, že je možné pro každé okno používat odlišnou callback funkci (na druhou stranu mají typicky hry jen jediné okno zobrazené v režimu fullscreen, což celou situaci zjednodušuje). Tato callback funkce se zavolá ve chvíli, kdy je stisknuta nějaká klávesa. Funkci se předávají dva parametry – konstanta reprezentující stisknutou klávesu (kód klávesy) a další konstanta, která je složena z příznakových bitů přiřazených každému modifikátoru (což typicky bývají klávesy Shift, Control, Alt atd.). Nejjednodušší podoba této funkce tedy může vypadat následovně:

@window.event
def on_key_press(symbol, modifiers):
    pass

Důležité upozornění: na PC a navíc jen u některých kláves odpovídá hodnota parametru symbol ASCII kódu stisknuté klávesy, ovšem není dobré se na toto chování spoléhat. Namísto toho je nutné pro porovnání používat konstanty pyglet.window.key.JMÉNO_KLÁVESY. Taktéž se může stát, že symbol obsahuje zdánlivě zcela nesmyslnou (vysokou) hodnotu. To nastává ve chvíli, kdy je stisknuta nějaká multimediální klávesa, klávesa Fn na některých noteboocích, klávesa s akcentovaným znakem u národních klávesnic atd.

K symbolům kláves lze přistupovat například takto:

Konstanta Klávesa
pyglet.window.key.A klávesa A
pyglet.window.key._1 klávesa 1 (nutno použít podtržítko, neboť 1 není identifikátor)
pyglet.window.key.NUM_1 klávesa 1 na numerickém bloku
pyglet.window.key.SPACE mezerník
pyglet.window.key.ENTER Enter/Return na hlavním bloku
pyglet.window.key.RETURN dtto
pyglet.window.key.NUM_ENTER Enter/Return na numerickém bloku
pyglet.window.key.UP kurzorová šipka
pyglet.window.key.DOWN kurzorová šipka
pyglet.window.key.LEFT kurzorová šipka
pyglet.window.key.RIGHT kurzorová šipka
pyglet.window.key.HOME další klávesy pro pohyb kurzoru
pyglet.window.key.END další klávesy pro pohyb kurzoru
pyglet.window.key.PAGEUP další klávesy pro pohyb kurzoru
pyglet.window.key.PAGEDOWN další klávesy pro pohyb kurzoru
pyglet.window.key.F1 klávesa F1

Poznámka: rozlišení mezi znakem „A“ a „a“ je nutné řešit programově testem stisknutých modifikátorů (zde konkrétně Shift), protože se do callback funkcí stále bude předávat jen symbol pyglet.window.key.A (žádný symbol pyglet.window.key.a ani neexistuje).

3. Událost on_key_release

Opakem callback funkce on_key_press je funkce on_key_release, které se při jejím zavolání předají stejné parametry, tedy kód puštěné klávesy a případné modifikátory:

@window.event
def on_key_release(symbol, modifiers):
    pass

Tuto funkci je nutné použít pro zjištění, zda a kdy je klávesa puštěna, a to z toho důvodu, že dvojice callback funkcí on_key_press + on_key_release neberou do úvahy automatické opakování stisknutých kláves. To jinými slovy znamená, že když dojde ke stisku klávesy, jejím podržení (řekněme deset sekund) a puštění, zavolá se funkce on_key_press jen jedenkrát (při stisku, tedy ihned na začátku) a on_key_release taktéž jedenkrát (po puštění).

4. První demonstrační příklad: zachycení události stisku a puštění klávesy

Použití callback funkcí on_key_press a on_key_release si ukážeme v dnešním prvním demonstračním příkladu, v němž je nejdříve vytvořeno okno a následně textové návěští použité pro výpis zpráv:

def create_window(width, height):
    return pyglet.window.Window(width=width,
                                height=height,
                                caption="Pyglet library")


def create_label():
    return pyglet.text.Label("Event:",
                             font_size=18,
                             x=window.width//4,
                             y=window.height//2,
                             anchor_x='left',
                             anchor_y='center')


window = create_window(640, 480)
label = create_label()

Následně jsou obě callback funkce zaregistrovány:

@window.event
def on_key_press(symbol, modifiers):
    display_key_event(symbol, modifiers, "pressed")


@window.event
def on_key_release(symbol, modifiers):
    display_key_event(symbol, modifiers, "released")

Při každém stisku klávesy či jejím puštění se do okna (přes textové návěští) vypíše symbol stisknuté/puštěné klávesy.

def display_key_event(symbol, modifiers, action):
    text = format("Event: key with code %d %s" % (symbol, action))
    label.text = text
    print(symbol)
    on_draw()

Obrázek 1: Událost vyvolaná puštěním klávesy A.

Úplný zdrojový kód prvního demonstračního příkladu vypadá takto:

#!/usr/bin/env python

import pyglet


def create_window(width, height):
    return pyglet.window.Window(width=width,
                                height=height,
                                caption="Pyglet library")


def create_label():
    return pyglet.text.Label("Event:",
                             font_size=18,
                             x=window.width//4,
                             y=window.height//2,
                             anchor_x='left',
                             anchor_y='center')


window = create_window(640, 480)
label = create_label()


def display_key_event(symbol, modifiers, action):
    text = format("Event: key with code %d %s" % (symbol, action))
    label.text = text
    print(symbol)
    on_draw()


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


@window.event
def on_key_press(symbol, modifiers):
    display_key_event(symbol, modifiers, "pressed")


@window.event
def on_key_release(symbol, modifiers):
    display_key_event(symbol, modifiers, "released")


pyglet.app.run()

5. Modifikátory (Shift, Control, Alt atd.)

V předchozích kapitolách jsme se zmínili o druhém parametru předávaném do funkcí on_key_press a on_key_release. Tento parametr je reprezentován celým číslem, jehož jednotlivé bity určují, které modifikátory jsou stisknuty současně s danou klávesou. Rozpoznány mohou být následující modifikátory (ovšem pochopitelně zdaleka ne všechny příslušné klávesy naleznete na jedné klávesnici):

Modifikátor Poznámka
MOD_SHIFT
MOD_CTRL
MOD_ALT není na Mac OS X
MOD_WINDOWS není na Mac OS X
MOD_COMMAND pouze na Mac OS X
MOD_OPTION pouze na Mac OS X
MOD_CAPSLOCK
MOD_NUMLOCK
MOD_SCROLLLOCK
MOD_ACCEL může nahradit buď MOD_CTRL nebo MOD_COMMAND

Na většině klávesnic nalezneme klávesy Shift, Ctrl/Control a Alt, takže test na stisk těchto kláves (společně s další klávesou) může vypadat například takto:

@window.event
def on_key_press(symbol, modifiers):
    if modifiers & pyglet.window.key.MOD_SHIFT:
        foo()
    if modifiers & pyglet.window.key.MOD_CTRL:
        bar()
    if modifiers & pyglet.window.key.MOD_ALT:
        baz()

6. Druhý demonstrační příklad: test modifikátorů bez rozlišení, zda se nachází na levé či pravé straně klávesnice

Ve druhém demonstračním příkladu je ukázán jeden ze způsobů otestování stisku základních modifikátorů Shift, Ctrl/Control a Alt. Do příkladu bylo přidáno další návěští (label), do kterého jsou vypisovány informace o tom, které modifikátory jsou stisknuty:

def create_label2():
    return pyglet.text.Label("Modifiers:",
                             font_size=16,
                             x=window.width//4,
                             y=window.height//2 - 32,
                             anchor_x='left',
                             anchor_y='center')

Vzhledem k tomu, že modifikátory lze stlačit současně, musí logika aplikace vypadat takto:

def display_key_event(symbol, modifiers, action):
    text = format("Event: key with code %d %s" % (symbol, action))
    label1.text = text
    text = "Modifiers: "

    if modifiers & pyglet.window.key.MOD_SHIFT:
        text = text + "Shift "
    if modifiers & pyglet.window.key.MOD_CTRL:
        text = text + "Ctrl "
    if modifiers & pyglet.window.key.MOD_ALT:
        text = text + "Alt "

    label2.text = text

    on_draw()

Obrázek 2: Modifikátor Shift současně změnil vlastní kód stisknuté klávesy (použito je CZ_QWERTY rozložení).

Úplný zdrojový kód druhého demonstračního příkladu vypadá následovně:

#!/usr/bin/env python

import pyglet


def create_window(width, height):
    return pyglet.window.Window(width=width,
                                height=height,
                                caption="Pyglet library")


def create_label1():
    return pyglet.text.Label("Event:",
                             font_size=18,
                             x=window.width//4,
                             y=window.height//2,
                             anchor_x='left',
                             anchor_y='center')


def create_label2():
    return pyglet.text.Label("Modifiers:",
                             font_size=16,
                             x=window.width//4,
                             y=window.height//2 - 32,
                             anchor_x='left',
                             anchor_y='center')


window = create_window(640, 480)
label1 = create_label1()
label2 = create_label2()


def display_key_event(symbol, modifiers, action):
    text = format("Event: key with code %d %s" % (symbol, action))
    label1.text = text
    text = "Modifiers: "

    if modifiers & pyglet.window.key.MOD_SHIFT:
        text = text + "Shift "
    if modifiers & pyglet.window.key.MOD_CTRL:
        text = text + "Ctrl "
    if modifiers & pyglet.window.key.MOD_ALT:
        text = text + "Alt "

    label2.text = text

    on_draw()
    print(symbol, modifiers)


@window.event
def on_draw():
    window.clear()
    label1.draw()
    label2.draw()


@window.event
def on_key_press(symbol, modifiers):
    display_key_event(symbol, modifiers, "pressed")


@window.event
def on_key_release(symbol, modifiers):
    display_key_event(symbol, modifiers, "released")


pyglet.app.run()

7. Třetí demonstrační příklad: vizuální zobrazení stisku kláves Shift a Control

Třetí demonstrační příklad je již složitější, protože v něm rozlišujeme stisk modifikátoru na levé či naopak na pravé straně klávesnice (většina klávesnic totiž všechny tři základní modifikátory zdvojuje, i když pravý Alt bývá popsán odlišně). Nyní však nebudeme testovat přímo parametr modifiers, protože ten neumí toto rozlišení provést, ale musíme reagovat přímo na stisk příslušné klávesy. Nejprimitivnější řešení může vypadat takto:

def display_key_event(symbol, modifiers, new_color):
    if symbol == pyglet.window.key.LCTRL:
        foo()
    elif symbol == pyglet.window.key.RCTRL:
        bar()
    elif symbol == pyglet.window.key.LSHIFT:
        baz()
    elif symbol == pyglet.window.key.RSHIFT:
        xyzzy()

Obrázek 3: Žádná kombinace kláves Ctrl či Shift není stisknuta.

Vykreslení stavu modifikátorů je nyní provedeno odlišně, protože do okna zobrazíme popisky kláves a budeme měnit jejich barvu. Implicitní barva nestlačené klávesy je šedá:

def create_gray_label(text, x, y, anchor_x, anchor_y):
    return pyglet.text.Label(text,
                             font_size=36,
                             x=x,
                             y=y,
                             anchor_x=anchor_x,
                             anchor_y=anchor_y,
                             color=GRAY)

Změna barvy příslušného návěští se provede snadno – stisk klávesy změní pozadí na červenou, puštění pak zpět na šedou:

GRAY = (128, 128, 128, 255)
RED = (255, 128, 128, 255)

def display_key_event(symbol, modifiers, new_color):
    if symbol == pyglet.window.key.LCTRL:
        label_left_control.color = new_color
    elif symbol == pyglet.window.key.RCTRL:
        label_right_control.color = new_color
    elif symbol == pyglet.window.key.LSHIFT:
        label_left_shift.color = new_color
    elif symbol == pyglet.window.key.RSHIFT:
        label_right_shift.color = new_color
    on_draw()


@window.event
def on_key_press(symbol, modifiers):
    display_key_event(symbol, modifiers, RED)


@window.event
def on_key_release(symbol, modifiers):
    display_key_event(symbol, modifiers, GRAY)

Obrázek 4: Je stlačen levý Control a současně i pravý Shift.

Úplný zdrojový kód třetího demonstračního příkladu vypadá následovně:

#!/usr/bin/env python

import pyglet


GRAY = (128, 128, 128, 255)
RED = (255, 128, 128, 255)


def create_window(width, height):
    return pyglet.window.Window(width=width,
                                height=height,
                                caption="Pyglet library")


def create_gray_label(text, x, y, anchor_x, anchor_y):
    return pyglet.text.Label(text,
                             font_size=36,
                             x=x,
                             y=y,
                             anchor_x=anchor_x,
                             anchor_y=anchor_y,
                             color=GRAY)


def create_label_left_control():
    return create_gray_label('Ctrl', 10, 10, 'left', 'bottom')


def create_label_right_control():
    return create_gray_label('Ctrl', window.width-10, 10, 'right', 'bottom')


def create_label_left_shift():
    return create_gray_label('Shift', 10, 60, 'left', 'bottom')


def create_label_right_shift():
    return create_gray_label('Shift', window.width-10, 60, 'right', 'bottom')


window = create_window(640, 480)
label_left_control = create_label_left_control()
label_right_control = create_label_right_control()
label_left_shift = create_label_left_shift()
label_right_shift = create_label_right_shift()


def display_key_event(symbol, modifiers, new_color):
    if symbol == pyglet.window.key.LCTRL:
        label_left_control.color = new_color
    elif symbol == pyglet.window.key.RCTRL:
        label_right_control.color = new_color
    elif symbol == pyglet.window.key.LSHIFT:
        label_left_shift.color = new_color
    elif symbol == pyglet.window.key.RSHIFT:
        label_right_shift.color = new_color
    on_draw()


@window.event
def on_draw():
    window.clear()
    label_left_control.draw()
    label_right_control.draw()
    label_left_shift.draw()
    label_right_shift.draw()


@window.event
def on_key_press(symbol, modifiers):
    display_key_event(symbol, modifiers, RED)


@window.event
def on_key_release(symbol, modifiers):
    display_key_event(symbol, modifiers, GRAY)


pyglet.app.run()

8. Pole se stavy všech kláves

V předchozím programovém kódu jsme si museli sami hlídat, které klávesy (z těch, které nás zajímají) byly stisknuty a které naopak nikoli. To vede k nutnosti použití stavových proměnných či atributů. Vzhledem k tomu, že se tato činnost ve hrách používá prakticky pořád, nabízí knihovna Pyglet zjednodušení celého procesu – k dispozici je pole obsahující příznaky stisku všech kláves na klávesnici. Příznaky se nastavují (z pohledu programátora) zcela automaticky. Konfigurace se provede takto: nejdříve se musí vytvořit okno, pro něhož klávesy zachytáváme a následně se registruje „KeyStateHandler“:

window = create_window(640, 480)
 
keys = pyglet.window.key.KeyStateHandler()
window.push_handlers(keys)

Nyní máme k dispozici objekt keys použitelný následujícím způsobem kdekoli v kódu:

if keys[pyglet.window.key.A]:
    ...

if keys[pyglet.window.key.F1]:
    ...

if keys[pyglet.window.key._1]:
    ...

if keys[pyglet.window.key.LCTRL]:
    label_left_control.color = RED
else:
    label_left_control.color = GRAY

if keys[pyglet.window.key.RCTRL]:
    label_right_control.color = RED
else:
    label_right_control.color = GRAY

Velkou předností je, že nemusíme používat žádné callback funkce ani si pamatovat stav stisknutých kláves. Tyto operace se sice stále provádí, ale interně knihovnou Pyglet.

Obrázek 5: Není stisknut ani levý ani pravý Control/Ctrl.

9. Čtvrtý demonstrační příklad: využití pole se stavy všech kláves

Ve čtvrtém demonstračním příkladu je ukázáno, jakým způsobem je možné velmi snadno otestovat stav dvou modifikátorů – levé a pravé klávesy Ctrl/Control. To může být užitečné například ve hrách typu pinball atd. Naprosto stejným postupem samozřejmě můžete pracovat i se všemi dalšími klávesami:

#!/usr/bin/env python

import pyglet


GRAY = (128, 128, 128, 255)
RED = (255, 128, 128, 255)


def create_window(width, height):
    return pyglet.window.Window(width=width,
                                height=height,
                                caption="Pyglet library")


def create_gray_label(text, x, y, anchor_x, anchor_y):
    return pyglet.text.Label(text,
                             font_size=36,
                             x=x,
                             y=y,
                             anchor_x=anchor_x,
                             anchor_y=anchor_y,
                             color=GRAY)


def create_label_left_control():
    return create_gray_label('Ctrl', 10, 10, 'left', 'bottom')


def create_label_right_control():
    return create_gray_label('Ctrl', window.width-10, 10, 'right', 'bottom')


window = create_window(640, 480)
keys = pyglet.window.key.KeyStateHandler()
window.push_handlers(keys)

label_left_control = create_label_left_control()
label_right_control = create_label_right_control()


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

    if keys[pyglet.window.key.LCTRL]:
        label_left_control.color = RED
    else:
        label_left_control.color = GRAY

    if keys[pyglet.window.key.RCTRL]:
        label_right_control.color = RED
    else:
        label_right_control.color = GRAY

    label_left_control.draw()
    label_right_control.draw()


pyglet.app.run()

Obrázek 6: Příklad po stisku pravé klávesy Control/Ctrl.

10. Událost on_text aneb detekce napsaných (Unicode) znaků

Ve chvíli, kdy je zapotřebí pracovat na úrovni jednotlivých znaků či dokonce celých textů, si již nevystačíme se symboly kláves definovanými v modulu pyglet.window.key. Je tomu tak z toho prostého důvodu, že by bylo nutné programově emulovat aktuální rozložení klávesnice (CZ, CZ_QWERTY a stovky dalších variant) a skládat z jednotlivých stisků kláves znaky. Ostatně stačí si jen uvědomit, kolika způsoby se zapisují znaky s českými nabodeníčky na CZ klávesnici (mrtvé klávesy atd.). Aby se zamezilo této neustále se opakující činnosti, nabízí knihovna Pyglet další callback funkci nazvanou on_text:

@window.event
def on_text(text):
    pass

Této callback funkci se obecně automaticky předává napsaný text, ale ve skutečnosti se prakticky vždy bude jednat o jediný znak.

Obrázek 7: Zápis znaku z původní ASCII.

Obrázek 8: Zápis znaku s tuzemským nabodeníčkem.

11. Pátý demonstrační příklad: použití události typu on_text

Použití výše zmíněné callback funkce on_text je ukázáno v dalším demonstračním příkladu, který na zápis znaku reaguje následujícím způsobem – vypíše znak do okna a současně i na standardní výstup:

@window.event
def on_text(text):
    text = format("Event: following text has been entered: '%s'" % text)
    label.text = text
    print(text)
    on_draw()

Úplný zdrojový kód pátého demonstračního příkladu vypadá následovně:

#!/usr/bin/env python

import pyglet


def create_window(width, height):
    return pyglet.window.Window(width=width,
                                height=height,
                                caption="Pyglet library")


def create_label():
    return pyglet.text.Label("Event:",
                             font_size=18,
                             x=10,
                             y=window.height//2,
                             anchor_x='left',
                             anchor_y='center')


window = create_window(640, 480)
label = create_label()


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


@window.event
def on_text(text):
    text = format("Event: following text has been entered: '%s'" % text)
    label.text = text
    print(text)
    on_draw()


pyglet.app.run()

12. Problematika pohybu v textu a její řešení: událost typu on_text_motion

Další problém, který je nutné nějakým způsobem vyřešit v těch aplikacích, které pracují s textem, je pohyb kurzoru v textu. Představit si můžeme například hru, do níž je možné zapsat jméno hráče nebo používat chat. Při pohybu kurzoru v textu uživatelé velmi často používají autorepeat, který je automaticky zpracován dnes již poslední callback funkcí nazvanou on_text_motion:

@window.event
def on_text_motion(motion):
    pass

V parametru motion je možné nalézt tyto hodnoty:

MOTION_UP
MOTION_DOWN
MOTION_LEFT
MOTION_RIGHT
MOTION_PREVIOUS_WORD
MOTION_NEXT_WORD
MOTION_BEGINNING_OF_LINE
MOTION_END_OF_LINE
MOTION_PREVIOUS_PAGE
MOTION_NEXT_PAGE
MOTION_BEGINNING_OF_FILE
MOTION_END_OF_FILE
MOTION_BACKSPACE
MOTION_DELETE

Povšimněte si, že některé hodnoty odpovídají stiskům příslušných kláves, jiné různým kombinacím kláves.

Obrázek 9: Detekce stisku a držení šipky doleva.

13. Šestý demonstrační příklad: využití události on_text_motion

V šestém příkladu se detekuje stisk (a držení) kurzorové šipky doleva a doprava:

@window.event
def on_text_motion(motion):
    global x
    if motion == pyglet.window.key.MOTION_LEFT:
        label.text = "Motion: left"
    elif motion == pyglet.window.key.MOTION_RIGHT:
        label.text = "Motion: right"
    print(motion)
    on_draw()

Úplný zdrojový kód šestého demonstračního příkladu vypadá takto:

#!/usr/bin/env python

import pyglet


def create_window(width, height):
    return pyglet.window.Window(width=width,
                                height=height,
                                caption="Pyglet library")


def create_label():
    return pyglet.text.Label("Motion:",
                             font_size=18,
                             x=10,
                             y=window.height//2,
                             anchor_x='left',
                             anchor_y='center')


window = create_window(640, 480)
label = create_label()


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


@window.event
def on_text_motion(motion):
    global x
    if motion == pyglet.window.key.MOTION_LEFT:
        label.text = "Motion: left"
    elif motion == pyglet.window.key.MOTION_RIGHT:
        label.text = "Motion: right"
    print(motion)
    on_draw()


pyglet.app.run()

Obrázek 10: Pohyb spritu pomocí kurzorových šipek.

14. Sedmý demonstrační příklad: událost on_text_motion a pohyb spritu ve scéně

Poslední demonstrační příklad kombinuje několik technik, zejména pak detekci stisku (a držení) kurzorových kláves a taktéž zobrazení spritů. Po spuštění příkladu se zobrazí sprite, kterým lze na obrazovce pohybovat pomocí kurzorových šipek. Vykreslení spritu je primitivní:

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

Pohyb spritu je řešen v callback funkci on_text_motion:

@window.event
def on_text_motion(motion):
    global sprite
    if motion == pyglet.window.key.MOTION_LEFT:
        sprite.x -= sprite.step
    elif motion == pyglet.window.key.MOTION_RIGHT:
        sprite.x += sprite.step
    elif motion == pyglet.window.key.MOTION_UP:
        sprite.y += sprite.step
    elif motion == pyglet.window.key.MOTION_DOWN:
        sprite.y -= sprite.step
    on_draw()

Úplný zdrojový kód sedmého demonstračního příkladu vypadá takto:

#!/usr/bin/env python

import pyglet


def create_window(width, height):
    return pyglet.window.Window(width=width,
                                height=height,
                                caption="Pyglet library")


def make_sprite(filename, window):
    image_stream = open("gnome-globe.png", "rb")
    image = pyglet.image.load('gnome-globe.png', file=image_stream)

    sprite = pyglet.sprite.Sprite(image)
    # vycentrovani spritu
    sprite.x = window.width / 2 - image.width / 2
    sprite.y = window.height / 2 - image.height / 2
    sprite.step = 5
    return sprite


window = create_window(640, 480)
sprite = make_sprite("gnome-globe.png", window)


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


@window.event
def on_text_motion(motion):
    global sprite
    if motion == pyglet.window.key.MOTION_LEFT:
        sprite.x -= sprite.step
    elif motion == pyglet.window.key.MOTION_RIGHT:
        sprite.x += sprite.step
    elif motion == pyglet.window.key.MOTION_UP:
        sprite.y += sprite.step
    elif motion == pyglet.window.key.MOTION_DOWN:
        sprite.y -= sprite.step
    on_draw()


pyglet.app.run()

15. Repositář s demonstračními příklady

Všechny dnes popsané demonstrační příklady byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/presentations. Příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý repositář. Pro jejich spuštění je samozřejmě nutné mít nainstalovanou jak knihovnu Pyglet, tak i podpůrné grafické knihovny OpenGL a GLU (což se většinou provede automaticky v rámci instalace balíčku s Pygletem, viz též úvodní díl tohoto seriálu):

Příklad Odkaz
69_on_keypress.py https://github.com/tisnik/presentations/blob/master/pyglet/69_on_keypress.py
70_keyboard_modifiers.py https://github.com/tisnik/presentations/blob/master/pyglet/70_keyboard_modifiers.py
71_shift_ctrl_alt.py https://github.com/tisnik/presentations/blob/master/pyglet/71_shift_ctrl_alt.py
72_key_state.py https://github.com/tisnik/presentations/blob/master/pyglet/72_key_state.py
73_on_text.py https://github.com/tisnik/presentations/blob/master/pyglet/73_on_text.py
74_on_text_motion.py https://github.com/tisnik/presentations/blob/master/pyglet/74_on_text_motion.py
75_text_motion_cursor.py https://github.com/tisnik/presentations/blob/master/pyglet/75_text_motion_cursor.py

16. Odkazy na Internetu

  1. Class pyglet.graphics.vertexdomain.VertexList
    https://pythonhosted.org/pyglet/api/pyglet.graphics.vertexdomain.VertexList-class.html
  2. Class pyglet.graphics.vertexdomain.VertexDomain
    https://pythonhosted.org/pyglet/api/pyglet.graphics.vertexdomain.VertexDomain-class.html
  3. Pyglet: Module Hierarchy
    https://pythonhosted.org/pyglet/api/module-tree.html
  4. Learning Modern OpenGL
    https://www.codeproject.com/articles/771225/learning-modern-opengl
  5. OpenGL Utility Library
    https://en.wikipedia.org/wiki/OpenGL_Utility_Library
  6. GLU Specification
    https://www.opengl.org/registry/doc/glu1.3.pdf
  7. The Perlin noise math FAQ
    https://mzucker.github.io/html/perlin-noise-math-faq.html
  8. Perlin noise
    https://en.wikipedia.org/wiki/Perlin_noise
  9. Perlin Noise Generator (Python recipe)
    http://code.activestate.com/recipes/578470-perlin-noise-generator/
  10. Simplex noise demystified
    http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
  11. glTexEnv – příkaz OpenGL
    https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexEnv.xml
  12. glGetTexEnv – příkaz OpenGL
    https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetTexEnv.xml
  13. Pyglet Home Page
    https://bitbucket.org/pyglet/pyglet/wiki/Home
  14. Pyglet: dokumentace k verzi 1.2
    https://pyglet.readthedocs.io/en/pyglet-1.2-maintenance/
  15. Dokumentace k verzi 1.2 ve formátu PDF
    https://readthedocs.org/projects/pyglet/downloads/pdf/pyglet-1.2-maintenance/
  16. PyOpenGL
    http://pyopengl.sourceforge.net/
  17. The #! magic, details about the shebang/hash-bang mechanism on various Unix flavours
    https://www.in-ulm.de/~mascheck/various/shebang/
  18. Shebang (Unix)
    https://en.wikipedia.org/wiki/Shebang_%28Unix%29
  19. Domovská stránka systému LÖVE
    http://love2d.org/
  20. Simple DirectMedia Layer (home page)
    http://www.libsdl.org/
  21. Simple DirectMedia Layer (Wikipedia)
    https://en.wikipedia.org/wiki/Simple_DirectMedia_Layer
  22. Seriál Grafická knihovna OpenGL
    https://www.root.cz/serialy/graficka-knihovna-opengl/
  23. Pyglet event loop
    http://pyglet.readthedocs.io/en/latest/programming_guide/eventloop.html
  24. Decorators I: Introduction to Python Decorators
    http://www.artima.com/weblogs/viewpost.jsp?thread=240808
  25. 3D Programming in Python – Part 1
    https://greendalecs.wordpress.com/2012/04/21/3d-programming-in-python-part-1/
  26. A very basic Pyglet tutorial
    http://www.natan.termitnjak.net/tutorials/pyglet_basic.html
  27. Alpha blending
    https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending