V dnešní části seriálu o programovacích jazycích i o knihovnách a frameworcích vhodných pro výuku programování popř. pro výuku základů počítačové grafiky, si ukážeme, jakým způsobem se v knihovně Pygame může detekovat kolize dvou či více spritů. To je velmi důležitá operace, s níž se setkáme v prakticky každé 2D hře.
Obsah
1. Programovací jazyky a knihovny určené pro výuku základů počítačové grafiky: detekce kolize spritů
2. Použití funkce pygame.sprite.spritecollide pro detekci kolize spritů
3. Zdrojový kód demonstračního příkladu pygame20: základní detekce kolize spritů
4. Vylepšení předchozího kódu: detekce hráče se sebou samým je ignorována
5. Zdrojový kód demonstračního příkladu pygame21
6. Zvýraznění spritu, s nímž došlo ke kolizi
7. Zdrojový kód demonstračního příkladu pygame22: vysvícení spritů
8. Kolize se sprity, které nemají čtvercový či obdélníkový tvar
9. Zdrojový kód demonstračního příkladu pygame23: špatně vypočtená kolize kruhových spritů
10. Zdrojový kód demonstračního příkladu pygame24: použití korektní detekce kolize
11. Obsah následující části seriálu
12. Repositář se zdrojovými kódy všech dnešních demonstračních příkladů
13. Funkce použité v dnešních demonstračních příkladech
1. Programovací jazyky a knihovny určené pro výuku základů počítačové grafiky: detekce kolize spritů
V předchozí části seriálu o systémech, knihovnách a jazycích vhodných pro výuku programování počítačové grafiky, jsme se seznámili s tím, jakým způsobem lze v knihovně Pygame pracovat s takzvanými sprity, tj. s rastrovými obrázky, s nimiž je možné pohybovat po celé dvourozměrné scéně. Sprity samozřejmě mohou úplně či částečně překreslit pozadí vytvářené scény, mohou se v případě potřeby navzájem překrývat, při překrytí lze aplikovat již dříve popsanou průhlednost apod.
Obrázek 1: Sprity použité ve známé herní sérii Sonic the Hedgehog.
Ovšem zbývá nám vyřešit ještě jeden relativně závažný problém úzce související se sprity – v mnoha aplikacích (především v počítačových hrách) je nutné nějakým způsobem zareagovat ve chvíli, kdy dojde ke kolizi či k překryvu dvou spritů. Představme si například hru Pac-Man, která musí adekvátně reagovat při srážce hlavního hrdiny s duchem, zareagovat na sežrání bodu (což je taktéž srážka spritu/spritů) apod. I tyto případy, které byly v minulosti řešeny už na úrovni příslušného hardware (video čipu), jsou samozřejmě v knihovně Pygame relativně jednoduše vyřešitelné, což ostatně uvidíme v navazujících kapitolách.
Obrázek 2: Starší varianta hry Pac-Man, zde pro osmibitovou herní konzoli Atari 2600.
2. Použití funkce pygame.sprite.spritecollide pro detekci kolize spritů
Připomeňme si, že každý sprite je v knihovně Pygame charakterizován svým rastrovým obrázkem, dále pak rozměry (šířka×výška) a taktéž pozicí v dvourozměrné scéně. Obě poslední hodnoty, tj. jak rozměry, tak i pozice spritu ve scéně, jsou uloženy v jediné datové struktuře typu rect. Test, zda došlo ke kolizi dvou spritů, lze tedy v nejjednodušším případě realizovat testem na protnutí dvou obdélníků charakterizovaných již zmíněnou strukturou rect. Aby nebylo nutné kód pro detekci kolizí spritů psát neustále znovu, lze využít funkci pygame.sprite.spritecollide(). Tato funkce akceptuje tři nebo čtyři parametry (čtvrtý parametr je totiž nepovinný):
- sprite – sprite, pro nějž se zjišťuje potenciální kolize s ostatními sprity.
- group – skupina spritů, s nimiž může první sprite kolidovat (kolize mezi jednotlivými sprity ve skupině se však nezjišťuje).
- dokill – pokud je tento parametr nastavený na pravdivostní hodnotu True, je kolidující sprite ze skupiny odstraněn. V opačném případě nedojde k žádné změně v předané skupině.
- collided – v případě, že je tento parametr specifikován, musí se jednat o funkci, které se předají dva sprity a funkce vrátí hodnotu True, pokud dojde k jejich kolizi.
Funkce pygame.sprite.spritecollide() vrátí seznam obsahující ty sprity ze skupiny group, které kolidují s prvním spritem předaným v parametru sprite. Sprity samozřejmě nejsou do tohoto seznamu kopírovány, ale je použita jen reference na ně (což nám umožňuje provádět operace nad původními objekty).
Obrázek 3: Povšimněte si počitadla kolizí zobrazeného v titulku okna tohoto demonstračního příkladu (jednička zde znamená, že hráč koliduje sám se sebou, což je jeden z nedostatků dále popsaného příkladu).
3. Zdrojový kód demonstračního příkladu pygame20: základní detekce kolize spritů
V dnešním prvním demonstračním příkladu (v celkovém pořadí se však jedná už o příklad dvacátý) je ukázáno použití výše zmíněné funkce pygame.sprite.spritecollide(). Celý program je založen na kódu, s nímž jsme se již seznámili minule, ovšem došlo k přidání několika nepohyblivých spritů a taktéž funkce check_collisions(). V této periodicky volané funkci se zjistí, zda došlo ke kolizi hráče (resp. přesněji řečeno spritu reprezentujícího hráče) s některým dalším spritem. Následně se do titulkového pruhu okna vypíše celkový počet kolizí, který se velmi snadno vypočítá z délky seznamu, který funkce pygame.sprite.spritecollide() vrátí. Počet kolizí bude o jedničku vyšší, a to z toho důvodu, že samotný hráč je taktéž přidán do skupiny sprite_group (a každý sprite samozřejmě koliduje sám se sebou). Podívejme se nyní na výpis celého zdrojového kódu tohoto demonstračního příkladu:
#!/usr/bin/python
# vim: set fileencoding=utf-8
# Demonstrační příklady využívající knihovnu Pygame
# Příklad číslo 20: použití spritů, pohyblivý sprite
import pygame, sys, os, math
# Nutno importovat kvůli konstantám QUIT atd.
from pygame.locals import *
# Velikost okna aplikace
WIDTH = 320
HEIGHT = 240
# Třída představující sprite zobrazený jako jednobarevný čtverec.
class BlockySprite(pygame.sprite.Sprite):
# Konstruktor
def __init__(self, color, size, x, y):
# Nejprve je nutné zavolat konstruktor předka,
# tj. konstruktor třídy pygame.sprite.Sprite:
pygame.sprite.Sprite.__init__(self)
# Vytvoření obrázku představujícího vizuální obraz spritu:
self.image = pygame.Surface([size,size])
self.image.fill(color)
# Vytvoření obalového obdélníku
# (velikost se získá z rozměru obrázku)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Počáteční rychlost spritu
self.speed_x = 0
self.speed_y = 0
# Inicializace knihovny Pygame
pygame.init()
clock = pygame.time.Clock()
# Vytvoření okna pro vykreslování
display = pygame.display.set_mode([WIDTH, HEIGHT])
# Nastavení titulku okna
pygame.display.set_caption('Pygame test #20')
# Konstanty s n-ticemi představujícími základní barvy
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GRAY = (128, 128, 128)
# Objekt sdružující všechny sprity
all_sprites = pygame.sprite.Group()
# Vytvoření několika typů spritů
# barva x y velikost
wall1 = BlockySprite(GRAY, 50, 10, 10)
wall2 = BlockySprite(GRAY, 15, 100, 100)
wall3 = BlockySprite(GRAY, 15, 100, 150)
wall4 = BlockySprite(GRAY, 15, 200, 100)
wall5 = BlockySprite(GRAY, 15, 200, 150)
player = BlockySprite(RED, 25, WIDTH/2-12, HEIGHT/2-12)
# Přidání několika dalších spritů do seznamu
# (jen jeden sprite - ten poslední - bude ve skutečnosti pohyblivý)
all_sprites.add(wall1)
all_sprites.add(wall2)
all_sprites.add(wall3)
all_sprites.add(wall4)
all_sprites.add(wall5)
all_sprites.add(player)
# Posun všech spritů ve skupině na základě jejich rychlosti
def move_sprites(sprite_group, playground_width, playground_height):
for sprite in sprite_group:
# Posun spritu
sprite.rect.x = sprite.rect.x + sprite.speed_x
sprite.rect.y = sprite.rect.y + sprite.speed_y
# Kontrola, zda sprite nenarazil do okrajů okna
if sprite.rect.x </gc 0:
sprite.rect.x = 0
sprite.speed_x = 0
if sprite.rect.x + sprite.rect.width >/gc playground_width:
sprite.rect.x = playground_width - sprite.rect.width
sprite.speed_x = 0
if sprite.rect.y </gc 0:
sprite.rect.y = 0
sprite.speed_y = 0
if sprite.rect.y + sprite.rect.height >/gc playground_height:
sprite.rect.y = playground_height - sprite.rect.height
sprite.speed_y = 0
# Vykreslení celé scény na obrazovku
def draw_scene(display, background_color, sprite_group):
# Vyplnění plochy okna černou barvou
display.fill(background_color)
# Vykreslení celé skupiny spritů do bufferu
sprite_group.draw(display)
# Obnovení obsahu obrazovky (překlopení zadního a předního bufferu)
pygame.display.update()
# Zjistí kolize spritu se "stěnami" (nepohyblivými sprity)
def check_collisions(player, sprite_group):
# Vytvoření seznamu spritů, které kolidují s hráčem
hit_list = pygame.sprite.spritecollide(player, sprite_group, False)
collisions = len(hit_list)
# Přenastavení titulku okna
pygame.display.set_caption('Pygame test #20: collisions ' + str(collisions))
# Hlavní herní smyčka
while True:
# Načtení a zpracování všech událostí z fronty
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# Stiskem kurzorových kláves je možné měnit směr pohybu spritu
elif event.key == pygame.K_LEFT:
player.speed_x = -3
elif event.key == pygame.K_RIGHT:
player.speed_x = +3
elif event.key == pygame.K_UP:
player.speed_y = -3
elif event.key == pygame.K_DOWN:
player.speed_y = +3
if event.type == KEYUP:
# Puštění kurzorových kláves vede k zastavení pohybu spritu
if event.key == pygame.K_LEFT:
player.speed_x = 0
elif event.key == pygame.K_RIGHT:
player.speed_x = 0
elif event.key == pygame.K_UP:
player.speed_y = 0
elif event.key == pygame.K_DOWN:
player.speed_y = 0
move_sprites(all_sprites, display.get_width(), display.get_height())
check_collisions(player, all_sprites)
draw_scene(display, BLACK, all_sprites)
clock.tick(20)
# finito
Obrázek 4: Kolize hráče s jiným (nepohyblivým) spritem. Počitadlo zde dosáhlo hodnoty 2.
4. Vylepšení předchozího kódu: detekce hráče se sebou samým je ignorována
Předchozí příklad trpěl jednou nectností při výpočtu kolizí, která by v praxi komplikovala způsob dalšího použití seznamu spritů, jež kolidují s hráčem. Vzhledem k tomu, že sprite představující samotného hráče je součástí seznamu všech spritů, je vždy detekována minimálně jedna kolize, a to konkrétně kolize hráče se sebou samým. Aby se tomuto nedostatku předešlo, je možné vytvořit dva seznamy spritů, přičemž první seznam bude obsahovat všechny sprity a druhý seznam všechny sprity kromě samotného hráče. První seznam bude používán pro vykreslování, druhý pak pouze pro detekci kolizí. Podívejme se nyní, jak tuto změnu realizovat.
Nejprve vytvoříme všechny sprity. Ve skutečnosti ani nepotřebujeme reference na sprity ukládat do samostatných proměnných, je to však přehlednější:
# Vytvoření několika typů spritů
# barva x y velikost
wall1 = BlockySprite(GRAY, 50, 10, 10)
wall2 = BlockySprite(GRAY, 15, 100, 100)
wall3 = BlockySprite(GRAY, 15, 100, 150)
wall4 = BlockySprite(GRAY, 15, 200, 100)
wall5 = BlockySprite(GRAY, 15, 200, 150)
player = BlockySprite(RED, 25, WIDTH/2-12, HEIGHT/2-12)
Dále vytvoříme seznam všech spritů, tj. jak nepohyblivých spritů, tak i samotného hráče:
# Objekt sdružující všechny sprity
all_sprites = pygame.sprite.Group()
# Přidání několika dalších spritů do seznamu
# (jen jeden sprite - ten poslední - bude ve skutečnosti pohyblivý)
all_sprites.add(wall1)
all_sprites.add(wall2)
all_sprites.add(wall3)
all_sprites.add(wall4)
all_sprites.add(wall5)
all_sprites.add(player)
Dále vytvoříme seznam všech spritů, ovšem bez hráče:
# Objekt sdružující všechny sprity kromě hráče
all_sprites_but_player = pygame.sprite.Group()
# Seznam všech nepohyblivých spritů
all_sprites_but_player.add(wall1)
all_sprites_but_player.add(wall2)
all_sprites_but_player.add(wall3)
all_sprites_but_player.add(wall4)
all_sprites_but_player.add(wall5)
Kolize se budou testovat mezi hráčem (player) a druhým seznamem (all_sprites_but_player):
check_collisions(player, all_sprites_but_player)
Obrázek 5: Úprava programového kódu: prozatím nedošlo ke kolizi hráče s jiným (nepohyblivým) spritem, počitadlo tedy správně ukazuje hodnotu 0.
5. Zdrojový kód demonstračního příkladu pygame21
Úprava předchozího programového kódu způsobem naznačeným v předchozí kapitole vedla ke vzniku nového příkladu, jehož úplný zdrojový kód je vypsán pod tímto odstavcem. Povšimněte si zejména způsobu manipulace s datovými strukturami uloženými v proměnných all_sprites a all_sprites_but_player:
#!/usr/bin/python
# vim: set fileencoding=utf-8
# Demonstrační příklady využívající knihovnu Pygame
# Příklad číslo 21: použití spritů, pohyblivý sprite
import pygame, sys, os, math
# Nutno importovat kvůli konstantám QUIT atd.
from pygame.locals import *
# Velikost okna aplikace
WIDTH = 320
HEIGHT = 240
# Třída představující sprite zobrazený jako jednobarevný čtverec.
class BlockySprite(pygame.sprite.Sprite):
# Konstruktor
def __init__(self, color, size, x, y):
# Nejprve je nutné zavolat konstruktor předka,
# tj. konstruktor třídy pygame.sprite.Sprite:
pygame.sprite.Sprite.__init__(self)
# Vytvoření obrázku představujícího vizuální obraz spritu:
self.image = pygame.Surface([size,size])
self.image.fill(color)
# Vytvoření obalového obdélníku
# (velikost se získá z rozměru obrázku)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Počáteční rychlost spritu
self.speed_x = 0
self.speed_y = 0
# Inicializace knihovny Pygame
pygame.init()
clock = pygame.time.Clock()
# Vytvoření okna pro vykreslování
display = pygame.display.set_mode([WIDTH, HEIGHT])
# Nastavení titulku okna
pygame.display.set_caption('Pygame test #21')
# Konstanty s n-ticemi představujícími základní barvy
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GRAY = (128, 128, 128)
# Objekt sdružující všechny sprity
all_sprites = pygame.sprite.Group()
# Objekt sdružující všechny sprity kromě hráče
all_sprites_but_player = pygame.sprite.Group()
# Vytvoření několika typů spritů
# barva x y velikost
wall1 = BlockySprite(GRAY, 50, 10, 10)
wall2 = BlockySprite(GRAY, 15, 100, 100)
wall3 = BlockySprite(GRAY, 15, 100, 150)
wall4 = BlockySprite(GRAY, 15, 200, 100)
wall5 = BlockySprite(GRAY, 15, 200, 150)
player = BlockySprite(RED, 25, WIDTH/2-12, HEIGHT/2-12)
# Přidání několika dalších spritů do seznamu
# (jen jeden sprite - ten poslední - bude ve skutečnosti pohyblivý)
all_sprites.add(wall1)
all_sprites.add(wall2)
all_sprites.add(wall3)
all_sprites.add(wall4)
all_sprites.add(wall5)
all_sprites.add(player)
# Seznam všech nepohyblivých spritů
all_sprites_but_player.add(wall1)
all_sprites_but_player.add(wall2)
all_sprites_but_player.add(wall3)
all_sprites_but_player.add(wall4)
all_sprites_but_player.add(wall5)
# Posun všech spritů ve skupině na základě jejich rychlosti
def move_sprites(sprite_group, playground_width, playground_height):
for sprite in sprite_group:
# Posun spritu
sprite.rect.x = sprite.rect.x + sprite.speed_x
sprite.rect.y = sprite.rect.y + sprite.speed_y
# Kontrola, zda sprite nenarazil do okrajů okna
if sprite.rect.x </gc 0:
sprite.rect.x = 0
sprite.speed_x = 0
if sprite.rect.x + sprite.rect.width >/gc playground_width:
sprite.rect.x = playground_width - sprite.rect.width
sprite.speed_x = 0
if sprite.rect.y </gc 0:
sprite.rect.y = 0
sprite.speed_y = 0
if sprite.rect.y + sprite.rect.height >/gc playground_height:
sprite.rect.y = playground_height - sprite.rect.height
sprite.speed_y = 0
# Vykreslení celé scény na obrazovku
def draw_scene(display, background_color, sprite_group):
# Vyplnění plochy okna černou barvou
display.fill(background_color)
# Vykreslení celé skupiny spritů do bufferu
sprite_group.draw(display)
# Obnovení obsahu obrazovky (překlopení zadního a předního bufferu)
pygame.display.update()
# Zjistí kolize spritu se "stěnami" (nepohyblivými sprity)
def check_collisions(player, sprite_group):
# Vytvoření seznamu spritů, které kolidují s hráčem
hit_list = pygame.sprite.spritecollide(player, sprite_group, False)
collisions = len(hit_list)
# Přenastavení titulku okna
pygame.display.set_caption('Pygame test #21: collisions ' + str(collisions))
# Hlavní herní smyčka
while True:
# Načtení a zpracování všech událostí z fronty
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# Stiskem kurzorových kláves je možné měnit směr pohybu spritu
elif event.key == pygame.K_LEFT:
player.speed_x = -3
elif event.key == pygame.K_RIGHT:
player.speed_x = +3
elif event.key == pygame.K_UP:
player.speed_y = -3
elif event.key == pygame.K_DOWN:
player.speed_y = +3
if event.type == KEYUP:
# Puštění kurzorových kláves vede k zastavení pohybu spritu
if event.key == pygame.K_LEFT:
player.speed_x = 0
elif event.key == pygame.K_RIGHT:
player.speed_x = 0
elif event.key == pygame.K_UP:
player.speed_y = 0
elif event.key == pygame.K_DOWN:
player.speed_y = 0
move_sprites(all_sprites, display.get_width(), display.get_height())
check_collisions(player, all_sprites_but_player)
draw_scene(display, BLACK, all_sprites)
clock.tick(20)
# finito
Obrázek 6: Kolize hráče s jiným (nepohyblivým) spritem, počitadlo správně ukazuje hodnotu 1.
6. Zvýraznění spritu, s nímž došlo ke kolizi
Výše uvedený příklad nyní upravíme takovým způsobem, aby se sprite, s níž hráč koliduje, vybarvil, a tím pádem i ve vykreslované 2D scéně zvýraznil. Výchozí barva spritů bude nastavena na světle šedou, barva spritu, do něhož narazí hráč, pak na barvu žlutou. Úprava programového kódu je ve skutečnosti velmi jednoduchá. Nejprve je nutné doplnit třídu BlockySprite o dvě nové metody pojmenované yellowColor() a grayColor(). Tyto metody po svém zavolání jednoduše vybarví celou plochu spritu zadanou barvou. Nejedná se sice o nejrychlejší řešení, ale prozatím je dostatečně rychlé i pro spuštění příkladu na (relativně) pomalém Raspberry Pi:
# Třída představující sprite zobrazený jako jednobarevný čtverec.
class BlockySprite(pygame.sprite.Sprite):
...
...
...
# Nastavení barvy spritu, který kolidoval s hráčem
def yellowColor(self):
self.image.fill(YELLOW)
# Nastavení barvy spritu, který nekolidoval s hráčem
def grayColor(self):
self.image.fill(GRAY)
O změnu barvy těch spritů, které kolidují s hráčem, se postará uživatelská funkce nazvaná change_colors(). Této funkci se předá seznam všech spritů a taktéž seznam spritů, s nimiž došlo ke kolizi. Na základě obsahu těchto dvou seznamů se každý sprite vybarví šedou nebo žlutou barvou:
# Změna barvy spritu na základě kolize s hráčem
def change_colors(sprite_group, hit_list):
# Projít všemi sprity ze skupiny, kterou detekovala kolizní funkce
for sprite in sprite_group:
if sprite in hit_list:
sprite.yellowColor()
else:
sprite.grayColor()
Obrázek 7: Prozatím nenastala kolize hráče s jiným (nepohyblivým) spritem.
Obrázek 8: Kolize hráče s jiným (nepohyblivým) spritem.
Obrázek 9: Kolize hráče s více (konkrétně se dvěma) sprity.
7. Zdrojový kód demonstračního příkladu pygame22: vysvícení spritů
Princip popsaný v šesté kapitole nyní budeme aplikovat v uceleném programovém kódu, který je kompletně vypsán pod tímto odstavcem:
#!/usr/bin/python
# vim: set fileencoding=utf-8
# Demonstrační příklady využívající knihovnu Pygame
# Příklad číslo 22: použití spritů, pohyblivý sprite
import pygame, sys, os, math
# Nutno importovat kvůli konstantám QUIT atd.
from pygame.locals import *
# Velikost okna aplikace
WIDTH = 320
HEIGHT = 240
# Třída představující sprite zobrazený jako jednobarevný čtverec.
class BlockySprite(pygame.sprite.Sprite):
# Konstruktor
def __init__(self, color, size, x, y):
# Nejprve je nutné zavolat konstruktor předka,
# tj. konstruktor třídy pygame.sprite.Sprite:
pygame.sprite.Sprite.__init__(self)
# Vytvoření obrázku představujícího vizuální obraz spritu:
self.image = pygame.Surface([size,size])
self.image.fill(color)
# Vytvoření obalového obdélníku
# (velikost se získá z rozměru obrázku)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Počáteční rychlost spritu
self.speed_x = 0
self.speed_y = 0
# Nastavení barvy spritu, který kolidoval s hráčem
def yellowColor(self):
self.image.fill(YELLOW)
# Nastavení barvy spritu, který nekolidoval s hráčem
def grayColor(self):
self.image.fill(GRAY)
# Inicializace knihovny Pygame
pygame.init()
clock = pygame.time.Clock()
# Vytvoření okna pro vykreslování
display = pygame.display.set_mode([WIDTH, HEIGHT])
# Nastavení titulku okna
pygame.display.set_caption('Pygame test #22')
# Konstanty s n-ticemi představujícími základní barvy
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GRAY = (128, 128, 128)
YELLOW = (255, 255, 0)
# Objekt sdružující všechny sprity
all_sprites = pygame.sprite.Group()
# Objekt sdružující všechny sprity kromě hráče
all_sprites_but_player = pygame.sprite.Group()
# Vytvoření několika typů spritů
# barva x y velikost
wall1 = BlockySprite(GRAY, 50, 10, 10)
wall2 = BlockySprite(GRAY, 15, 100, 100)
wall3 = BlockySprite(GRAY, 15, 100, 150)
wall4 = BlockySprite(GRAY, 15, 200, 100)
wall5 = BlockySprite(GRAY, 15, 200, 150)
wall6 = BlockySprite(GRAY, 15, 150, 100)
wall7 = BlockySprite(GRAY, 15, 150, 150)
player = BlockySprite(RED, 40, WIDTH/2-20, HEIGHT/2-20)
# Přidání několika dalších spritů do seznamu
# (jen jeden sprite - ten poslední - bude ve skutečnosti pohyblivý)
all_sprites.add(wall1)
all_sprites.add(wall2)
all_sprites.add(wall3)
all_sprites.add(wall4)
all_sprites.add(wall5)
all_sprites.add(wall6)
all_sprites.add(wall7)
all_sprites.add(player)
# Seznam všech nepohyblivých spritů
all_sprites_but_player.add(wall1)
all_sprites_but_player.add(wall2)
all_sprites_but_player.add(wall3)
all_sprites_but_player.add(wall4)
all_sprites_but_player.add(wall5)
all_sprites_but_player.add(wall6)
all_sprites_but_player.add(wall7)
# Posun všech spritů ve skupině na základě jejich rychlosti
def move_sprites(sprite_group, playground_width, playground_height):
for sprite in sprite_group:
# Posun spritu
sprite.rect.x = sprite.rect.x + sprite.speed_x
sprite.rect.y = sprite.rect.y + sprite.speed_y
# Kontrola, zda sprite nenarazil do okrajů okna
if sprite.rect.x </gc 0:
sprite.rect.x = 0
sprite.speed_x = 0
if sprite.rect.x + sprite.rect.width >/gc playground_width:
sprite.rect.x = playground_width - sprite.rect.width
sprite.speed_x = 0
if sprite.rect.y </gc 0:
sprite.rect.y = 0
sprite.speed_y = 0
if sprite.rect.y + sprite.rect.height >/gc playground_height:
sprite.rect.y = playground_height - sprite.rect.height
sprite.speed_y = 0
# Vykreslení celé scény na obrazovku
def draw_scene(display, background_color, sprite_group):
# Vyplnění plochy okna černou barvou
display.fill(background_color)
# Vykreslení celé skupiny spritů do bufferu
sprite_group.draw(display)
# Obnovení obsahu obrazovky (překlopení zadního a předního bufferu)
pygame.display.update()
# Změna barvy spritu na základě kolize s hráčem
def change_colors(sprite_group, hit_list):
# Projít všemi sprity ze skupiny, kterou detekovala kolizní funkce
for sprite in sprite_group:
if sprite in hit_list:
sprite.yellowColor()
else:
sprite.grayColor()
# Zjistí kolize spritu se "stěnami" (nepohyblivými sprity)
def check_collisions(player, sprite_group):
# Vytvoření seznamu spritů, které kolidují s hráčem
hit_list = pygame.sprite.spritecollide(player, sprite_group, False)
# Změna barev kolidujících spritů
change_colors(sprite_group, hit_list)
collisions = len(hit_list)
# Přenastavení titulku okna
pygame.display.set_caption('Pygame test #22: collisions ' + str(collisions))
# Hlavní herní smyčka
while True:
# Načtení a zpracování všech událostí z fronty
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# Stiskem kurzorových kláves je možné měnit směr pohybu spritu
elif event.key == pygame.K_LEFT:
player.speed_x = -3
elif event.key == pygame.K_RIGHT:
player.speed_x = +3
elif event.key == pygame.K_UP:
player.speed_y = -3
elif event.key == pygame.K_DOWN:
player.speed_y = +3
if event.type == KEYUP:
# Puštění kurzorových kláves vede k zastavení pohybu spritu
if event.key == pygame.K_LEFT:
player.speed_x = 0
elif event.key == pygame.K_RIGHT:
player.speed_x = 0
elif event.key == pygame.K_UP:
player.speed_y = 0
elif event.key == pygame.K_DOWN:
player.speed_y = 0
move_sprites(all_sprites, display.get_width(), display.get_height())
check_collisions(player, all_sprites_but_player)
draw_scene(display, BLACK, all_sprites)
clock.tick(20)
# finito
Obrázek 10: Kolize hráče s více (konkrétně se čtyřmi) sprity.
8. Kolize se sprity, které nemají čtvercový či obdélníkový tvar
Tvary všech spritů, které jsme doposud ve všech demonstračních příkladech používali, byly čtvercové či obdélníkové, což znamená, že vizuální tvar spritu na obrazovce přesně odpovídal rozměrům spritů uložených v datové struktuře rect. V naprosté většině případů je však nutné v reálných aplikacích pracovat se sprity odlišných tvarů. V knihovně Pygame pro tyto případy existují dva další postupy, jak zjistit kolizi spritů jiných tvarů, než je čtverec nebo obdélník.
Obrázek 11: Kruhový sprite použitý v dalších příkladech.
Pokud se jedná o kruhové sprity, lze použít funkci pygame.sprite.collide_circle(), které se předají dva sprity a výsledkem je pravdivostní hodnota nastavená v závislosti na tom, zda se dvě kružnice, kterou oba sprity představují, překrývají či nikoli. Jak již víme z předchozího textu, je možné takovou callback funkci použít v pygame.sprite.spritecollide() (předává se ve čtvrtém parametru). Druhá užitečná funkce se jmenuje pygame.sprite.collide_mask() a použije se tehdy, pokud je zapotřebí vypočítat kolizi s přesností jednoho pixelu. Tato funkce je však nejpomalejší, proto je vhodné ji používat opravdu pouze ve chvíli, kdy je to kvůli tvarům spritů nezbytně nutné.
Obrázek 12: Druhý kruhový sprite použitý v dalších příkladech.
Obrázek 13: Barevně upravené druhý kruhový sprite, který je taktéž použitý v dalších příkladech.
9. Zdrojový kód demonstračního příkladu pygame23: špatně vypočtená kolize kruhových spritů
Podívejme se nejprve na příklad, v němž se sice používají kruhové sprity, ale výpočet kolize je prováděn „starým“ způsobem, tj. pouze na základě detekce překryvu obdélníků. Tento příklad se liší od předchozích příkladů v tom ohledu, že se obrázek spritu načte z externího souboru, zatímco dříve jsme sprity jednoduše vyplnili nějakou barvou. Kvůli tomu, že budeme potřebovat zvýraznit náraz hráče do dalších spritů, načteme pro každý sprite dva obrázky, které se budou pouze prohazovat, podobně jako jsme u předchozích příkladů sprity přebarvovali.
Načtení obrázků v konstruktoru třídy CircularSprite:
# Načtení obrázků, jeden pro normální sprite,
# druhý pro sprite, který koliduje s hráčem
self.normal_image = pygame.image.load("images/" + normal_image_name + ".png")
self.collision_image = pygame.image.load("images/" + collision_image_name + ".png")
# Vytvoření obrázku představujícího vizuální obraz spritu:
self.image = self.normal_image
Změna obrázků po detekci kolize je zajištěna dvojicí funkcí:
# Nastavení obrázku u spritu, který kolidoval s hráčem
def setCollisionImage(self):
self.image = self.collision_image
# Nastavení obrázku u spritu, který nekolidoval s hráčem
def setNormalImage(self):
self.image = self.normal_image
Vlastní reakce na detekci kolize:
# Změna obrázku spritu na základě kolize s hráčem
def change_sprite_image(sprite_group, hit_list):
# Projít všemi sprity ze skupiny, kterou detekovala kolizní funkce
for sprite in sprite_group:
if sprite in hit_list:
sprite.setCollisionImage()
else:
sprite.setNormalImage()
# Zjistí kolize spritu se "stěnami" (nepohyblivými sprity)
def check_collisions(player, sprite_group):
# Vytvoření seznamu spritů, které kolidují s hráčem
hit_list = pygame.sprite.spritecollide(player, sprite_group, False)
# Změna obrázků kolidujících spritů
change_sprite_image(sprite_group, hit_list)
collisions = len(hit_list)
# Přenastavení titulku okna
pygame.display.set_caption('Pygame test #23: collisions ' + str(collisions))
Obrázek 14: Uživatel může pohybovat spritem s obrázkem zeměkoule. Zde prozatím nedošlo k žádné kolizi s ostatními sprity.
Podívejme se nyní na úplný výpis zdrojového kódu tohoto příkladu:
#!/usr/bin/python
# vim: set fileencoding=utf-8
# Demonstrační příklady využívající knihovnu Pygame
# Příklad číslo 23: použití spritů, pohyblivý sprite,
# kolize, různé tvary kolidujících spritů
import pygame, sys, os, math
# Nutno importovat kvůli konstantám QUIT atd.
from pygame.locals import *
# Velikost okna aplikace
WIDTH = 320
HEIGHT = 240
# Třída představující sprite zobrazený jako jednobarevný čtverec.
class CircularSprite(pygame.sprite.Sprite):
# Konstruktor
def __init__(self, x, y, normal_image_name, collision_image_name):
# Nejprve je nutné zavolat konstruktor předka,
# tj. konstruktor třídy pygame.sprite.Sprite:
pygame.sprite.Sprite.__init__(self)
# Načtení obrázků, jeden pro normální sprite,
# druhý pro sprite, který koliduje s hráčem
self.normal_image = pygame.image.load("images/" + normal_image_name + ".png")
self.collision_image = pygame.image.load("images/" + collision_image_name + ".png")
# Vytvoření obrázku představujícího vizuální obraz spritu:
self.image = self.normal_image
#self.image.fill(color) - toto nyní nepoužijeme, pozůstatek z BlockySprite
# Vytvoření obalového obdélníku
# (velikost se získá z rozměru obrázku)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# Počáteční rychlost spritu
self.speed_x = 0
self.speed_y = 0
# Nastavení obrázku u spritu, který kolidoval s hráčem
def setCollisionImage(self):
self.image = self.collision_image
# Nastavení obrázku u spritu, který nekolidoval s hráčem
def setNormalImage(self):
self.image = self.normal_image
# Inicializace knihovny Pygame
pygame.init()
clock = pygame.time.Clock()
# Vytvoření okna pro vykreslování
display = pygame.display.set_mode([WIDTH, HEIGHT])
# Nastavení titulku okna
pygame.display.set_caption('Pygame test #23')
# Konstanty s n-ticemi představujícími základní barvy
BLACK = ( 0, 0, 0)
# Objekt sdružující všechny sprity
all_sprites = pygame.sprite.Group()
# Objekt sdružující všechny sprity kromě hráče
all_sprites_but_player = pygame.sprite.Group()
# Vytvoření několika typů spritů
# x y první obr. druhý obr.
wall1 = CircularSprite( 20, 40, "sprite3", "sprite2")
wall2 = CircularSprite( 20, 140, "sprite3", "sprite2")
wall3 = CircularSprite(220, 40, "sprite3", "sprite2")
wall4 = CircularSprite(220, 140, "sprite3", "sprite2")
wall5 = CircularSprite(120, 40, "sprite3", "sprite2")
wall6 = CircularSprite(120, 140, "sprite3", "sprite2")
player = CircularSprite(WIDTH/2-20, HEIGHT/2-20, "sprite1", "sprite1")
# Přidání několika dalších spritů do seznamu
# (jen jeden sprite - ten poslední - bude ve skutečnosti pohyblivý)
all_sprites.add(wall1)
all_sprites.add(wall2)
all_sprites.add(wall3)
all_sprites.add(wall4)
all_sprites.add(wall5)
all_sprites.add(wall6)
all_sprites.add(player)
# Seznam všech nepohyblivých spritů
all_sprites_but_player.add(wall1)
all_sprites_but_player.add(wall2)
all_sprites_but_player.add(wall3)
all_sprites_but_player.add(wall4)
all_sprites_but_player.add(wall5)
all_sprites_but_player.add(wall6)
# Posun všech spritů ve skupině na základě jejich rychlosti
def move_sprites(sprite_group, playground_width, playground_height):
for sprite in sprite_group:
# Posun spritu
sprite.rect.x = sprite.rect.x + sprite.speed_x
sprite.rect.y = sprite.rect.y + sprite.speed_y
# Kontrola, zda sprite nenarazil do okrajů okna
if sprite.rect.x </gc 0:
sprite.rect.x = 0
sprite.speed_x = 0
if sprite.rect.x + sprite.rect.width >/gc playground_width:
sprite.rect.x = playground_width - sprite.rect.width
sprite.speed_x = 0
if sprite.rect.y </gc 0:
sprite.rect.y = 0
sprite.speed_y = 0
if sprite.rect.y + sprite.rect.height >/gc playground_height:
sprite.rect.y = playground_height - sprite.rect.height
sprite.speed_y = 0
# Vykreslení celé scény na obrazovku
def draw_scene(display, background_color, sprite_group):
# Vyplnění plochy okna černou barvou
display.fill(background_color)
# Vykreslení celé skupiny spritů do bufferu
sprite_group.draw(display)
# Obnovení obsahu obrazovky (překlopení zadního a předního bufferu)
pygame.display.update()
# Změna obrázku spritu na základě kolize s hráčem
def change_sprite_image(sprite_group, hit_list):
# Projít všemi sprity ze skupiny, kterou detekovala kolizní funkce
for sprite in sprite_group:
if sprite in hit_list:
sprite.setCollisionImage()
else:
sprite.setNormalImage()
# Zjistí kolize spritu se "stěnami" (nepohyblivými sprity)
def check_collisions(player, sprite_group):
# Vytvoření seznamu spritů, které kolidují s hráčem
hit_list = pygame.sprite.spritecollide(player, sprite_group, False)
# Změna obrázků kolidujících spritů
change_sprite_image(sprite_group, hit_list)
collisions = len(hit_list)
# Přenastavení titulku okna
pygame.display.set_caption('Pygame test #23: collisions ' + str(collisions))
# Hlavní herní smyčka
while True:
# Načtení a zpracování všech událostí z fronty
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# Stiskem kurzorových kláves je možné měnit směr pohybu spritu
elif event.key == pygame.K_LEFT:
player.speed_x = -3
elif event.key == pygame.K_RIGHT:
player.speed_x = +3
elif event.key == pygame.K_UP:
player.speed_y = -3
elif event.key == pygame.K_DOWN:
player.speed_y = +3
if event.type == KEYUP:
# Puštění kurzorových kláves vede k zastavení pohybu spritu
if event.key == pygame.K_LEFT:
player.speed_x = 0
elif event.key == pygame.K_RIGHT:
player.speed_x = 0
elif event.key == pygame.K_UP:
player.speed_y = 0
elif event.key == pygame.K_DOWN:
player.speed_y = 0
move_sprites(all_sprites, display.get_width(), display.get_height())
check_collisions(player, all_sprites_but_player)
draw_scene(display, BLACK, all_sprites)
clock.tick(20)
# finito
Obrázek 15: Zde můžeme vidět problém: detekce kolize v případě, kdy se sice protnou obalové obdélníky spritů, ale nikoli jejich vybarvené pixely.
10. Zdrojový kód demonstračního příkladu pygame24: použití korektní detekce kolize
V dnešním posledním příkladu se již detekce kolize kruhových spritů provádí korektně. Je tomu tak z toho důvodu, že se u každého spritu pamatuje i jejich poloměr:
# Třída představující sprite zobrazený jako jednobarevný čtverec.
class CircularSprite(pygame.sprite.Sprite):
# Konstruktor
def __init__(self, x, y, radius, normal_image_name, collision_image_name):
...
...
...
# U kulatých spritů se nastavuje i poloměr
self.radius = radius
A dále se při detekci kolizí volá již výše zmíněná callback funkce pygame.sprite.collide_circle():
# Zjistí kolize spritu se "stěnami" (nepohyblivými sprity)
def check_collisions(player, sprite_group):
# Vytvoření seznamu spritů, které kolidují s hráčem
hit_list = pygame.sprite.spritecollide(player, sprite_group, False, pygame.sprite.collide_circle)
# Změna obrázků kolidujících spritů
change_sprite_image(sprite_group, hit_list)
collisions = len(hit_list)
# Přenastavení titulku okna
pygame.display.set_caption('Pygame test #24: collisions ' + str(collisions))
Opět se podívejme na výpis celého zdrojového kódu, z něhož budou všechny změny zřejmé:
#!/usr/bin/python
# vim: set fileencoding=utf-8
# Demonstrační příklady využívající knihovnu Pygame
# Příklad číslo 24: použití spritů, pohyblivý sprite,
# kolize, různé tvary kolidujících spritů
# kolize se korektně počítá pro kruhové sprity
import pygame, sys, os, math
# Nutno importovat kvůli konstantám QUIT atd.
from pygame.locals import *
# Velikost okna aplikace
WIDTH = 320
HEIGHT = 240
# Třída představující sprite zobrazený jako jednobarevný čtverec.
class CircularSprite(pygame.sprite.Sprite):
# Konstruktor
def __init__(self, x, y, radius, normal_image_name, collision_image_name):
# Nejprve je nutné zavolat konstruktor předka,
# tj. konstruktor třídy pygame.sprite.Sprite:
pygame.sprite.Sprite.__init__(self)
# Načtení obrázků, jeden pro normální sprite,
# druhý pro sprite, který koliduje s hráčem
self.normal_image = pygame.image.load("images/" + normal_image_name + ".png")
self.collision_image = pygame.image.load("images/" + collision_image_name + ".png")
# Vytvoření obrázku představujícího vizuální obraz spritu:
self.image = self.normal_image
#self.image.fill(color) - toto nyní nepoužijeme, pozůstatek z BlockySprite
# Vytvoření obalového obdélníku
# (velikost se získá z rozměru obrázku)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
# U kulatých spritů se nastavuje i poloměr
self.radius = radius
# Počáteční rychlost spritu
self.speed_x = 0
self.speed_y = 0
# Nastavení obrázku u spritu, který kolidoval s hráčem
def setCollisionImage(self):
self.image = self.collision_image
# Nastavení obrázku u spritu, který nekolidoval s hráčem
def setNormalImage(self):
self.image = self.normal_image
# Inicializace knihovny Pygame
pygame.init()
clock = pygame.time.Clock()
# Vytvoření okna pro vykreslování
display = pygame.display.set_mode([WIDTH, HEIGHT])
# Nastavení titulku okna
pygame.display.set_caption('Pygame test #24')
# Konstanty s n-ticemi představujícími základní barvy
BLACK = ( 0, 0, 0)
# Objekt sdružující všechny sprity
all_sprites = pygame.sprite.Group()
# Objekt sdružující všechny sprity kromě hráče
all_sprites_but_player = pygame.sprite.Group()
# Vytvoření několika typů spritů
# x y r první obr. druhý obr.
wall1 = CircularSprite( 20, 40, 31, "sprite3", "sprite2")
wall2 = CircularSprite( 20, 140, 31, "sprite3", "sprite2")
wall3 = CircularSprite(220, 40, 31, "sprite3", "sprite2")
wall4 = CircularSprite(220, 140, 31, "sprite3", "sprite2")
wall5 = CircularSprite(120, 40, 31, "sprite3", "sprite2")
wall6 = CircularSprite(120, 140, 31, "sprite3", "sprite2")
player = CircularSprite(WIDTH/2-20, HEIGHT/2-20, 22, "sprite1", "sprite1")
# Přidání několika dalších spritů do seznamu
# (jen jeden sprite - ten poslední - bude ve skutečnosti pohyblivý)
all_sprites.add(wall1)
all_sprites.add(wall2)
all_sprites.add(wall3)
all_sprites.add(wall4)
all_sprites.add(wall5)
all_sprites.add(wall6)
all_sprites.add(player)
# Seznam všech nepohyblivých spritů
all_sprites_but_player.add(wall1)
all_sprites_but_player.add(wall2)
all_sprites_but_player.add(wall3)
all_sprites_but_player.add(wall4)
all_sprites_but_player.add(wall5)
all_sprites_but_player.add(wall6)
# Posun všech spritů ve skupině na základě jejich rychlosti
def move_sprites(sprite_group, playground_width, playground_height):
for sprite in sprite_group:
# Posun spritu
sprite.rect.x = sprite.rect.x + sprite.speed_x
sprite.rect.y = sprite.rect.y + sprite.speed_y
# Kontrola, zda sprite nenarazil do okrajů okna
if sprite.rect.x </gc 0:
sprite.rect.x = 0
sprite.speed_x = 0
if sprite.rect.x + sprite.rect.width >/gc playground_width:
sprite.rect.x = playground_width - sprite.rect.width
sprite.speed_x = 0
if sprite.rect.y </gc 0:
sprite.rect.y = 0
sprite.speed_y = 0
if sprite.rect.y + sprite.rect.height >/gc playground_height:
sprite.rect.y = playground_height - sprite.rect.height
sprite.speed_y = 0
# Vykreslení celé scény na obrazovku
def draw_scene(display, background_color, sprite_group):
# Vyplnění plochy okna černou barvou
display.fill(background_color)
# Vykreslení celé skupiny spritů do bufferu
sprite_group.draw(display)
# Obnovení obsahu obrazovky (překlopení zadního a předního bufferu)
pygame.display.update()
# Změna obrázku spritu na základě kolize s hráčem
def change_sprite_image(sprite_group, hit_list):
# Projít všemi sprity ze skupiny, kterou detekovala kolizní funkce
for sprite in sprite_group:
if sprite in hit_list:
sprite.setCollisionImage()
else:
sprite.setNormalImage()
# Zjistí kolize spritu se "stěnami" (nepohyblivými sprity)
def check_collisions(player, sprite_group):
# Vytvoření seznamu spritů, které kolidují s hráčem
hit_list = pygame.sprite.spritecollide(player, sprite_group, False, pygame.sprite.collide_circle)
# Změna obrázků kolidujících spritů
change_sprite_image(sprite_group, hit_list)
collisions = len(hit_list)
# Přenastavení titulku okna
pygame.display.set_caption('Pygame test #24: collisions ' + str(collisions))
# Hlavní herní smyčka
while True:
# Načtení a zpracování všech událostí z fronty
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# Stiskem kurzorových kláves je možné měnit směr pohybu spritu
elif event.key == pygame.K_LEFT:
player.speed_x = -3
elif event.key == pygame.K_RIGHT:
player.speed_x = +3
elif event.key == pygame.K_UP:
player.speed_y = -3
elif event.key == pygame.K_DOWN:
player.speed_y = +3
if event.type == KEYUP:
# Puštění kurzorových kláves vede k zastavení pohybu spritu
if event.key == pygame.K_LEFT:
player.speed_x = 0
elif event.key == pygame.K_RIGHT:
player.speed_x = 0
elif event.key == pygame.K_UP:
player.speed_y = 0
elif event.key == pygame.K_DOWN:
player.speed_y = 0
move_sprites(all_sprites, display.get_width(), display.get_height())
check_collisions(player, all_sprites_but_player)
draw_scene(display, BLACK, all_sprites)
clock.tick(20)
# finito
Obrázek 16: Poslední demonstrační příklad ihned po svém spuštění.
11. Obsah následující části seriálu
V následující části seriálu o programovacích jazycích i o knihovnách a frameworcích vhodných pro výuku programování popř. pro výuku základů počítačové grafiky, se budeme zabývat možnostmi, které programátorům nabízí modul nazvaný pygame.transform. Jak již název tohoto modulu naznačuje, je možné s jeho využitím aplikovat afinní transformace na všechny objekty typu Surface, čehož je možné využít v mnoha (mnohdy velmi zajímavých) grafických efektech a dosáhnout tak i „3D“ vzhledu hry či grafického dema.
Obrázek 17: Poslední demonstrační příklad: obalové obdélníky spritů se sice překrývají, ale kolize nebyla detekována.
12. Repositář se zdrojovými kódy všech dnešních demonstračních příkladů
Všechny demonstrační příklady, s nimiž jsme se v dnešním článku seznámili, byly, podobně jako ve všech předchozích částech tohoto seriálu, uloženy do Git repositáře umístěného na GitHubu (https://github.com/tisnik/presentations). Poslední verze zdrojových kódů naleznete pod těmito odkazy:
# | Příklad | Zdrojový kód |
---|---|---|
1 | pygame20.py | https://github.com/tisnik/presentations/blob/master/pygame/pygame20.py |
2 | pygame21.py | https://github.com/tisnik/presentations/blob/master/pygame/pygame21.py |
3 | pygame22.py | https://github.com/tisnik/presentations/blob/master/pygame/pygame22.py |
4 | pygame23.py | https://github.com/tisnik/presentations/blob/master/pygame/pygame23.py |
5 | pygame24.py | https://github.com/tisnik/presentations/blob/master/pygame/pygame24.py |
Obrázek 18: Poslední demonstrační příklad: až nyní došlo ke kolizi.
13. Funkce použité v dnešních demonstračních příkladech
Opět si pro úplnost vypišme funkce a metody nabízené knihovnou Pygame, které jsme použili v dnešních demonstračních příkladech:
- pygame.init()
http://www.pygame.org/docs/ref/pygame.html#pygame.init - pygame.quit()
http://www.pygame.org/docs/ref/pygame.html#pygame.quit - pygame.display.set_mode()
http://www.pygame.org/docs/ref/display.html#pygame.display.set_mode - pygame.display.set_caption()
http://www.pygame.org/docs/ref/display.html#pygame.display.set_caption - pygame.display.quit()
http://www.pygame.org/docs/ref/display.html#pygame.display.quit - pygame.display.update()
http://www.pygame.org/docs/ref/display.html#pygame.display.update - pygame.event.get()
http://www.pygame.org/docs/ref/event.html#pygame.event.get - pygame.time.Clock()
http://www.pygame.org/docs/ref/time.html#pygame.time.Clock - pygame.time.Clock.tick()
http://www.pygame.org/docs/ref/time.html#pygame.time.Clock.tick - pygame.Surface()
http://www.pygame.org/docs/ref/surface.html - pygame.Surface.fill()
http://www.pygame.org/docs/ref/surface.html#pygame.Surface.fill - pygame.image.load()
http://www.pygame.org/docs/ref/image.html#pygame.image.load - pygame.Sprite.__init__()
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Sprite - pygame.sprite.Group()
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Group - pygame.sprite.Group.add()
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Group.add - pygame.sprite.Group.draw()
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Group.draw - pygame.sprite.spritecollide()
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.spritecollide - pygame.sprite.collide_circle()
http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.collide_circle
Obrázek 19: Sprity se mohou překrývat v jiném pořadí.
14. Odkazy na Internetu
- Program Arcade Games With Python And Pygame
http://programarcadegames.com/index.php?lang=en# - Program Arcade Games With Python And Pygame: Chapter 13: Introduction to Sprites:
http://programarcadegames.com/index.php?chapter=introduction_to_sprites# - Pygame.org
http://pygame.org/hifi.html - Pygame - instalační soubory pro různé operační systémy
http://pygame.org/download.shtml - Pygame: documentation
http://www.pygame.org/docs/ - Pygame Wiki: Getting Started
http://www.pygame.org/wiki/GettingStarted - Pygame Tutorials: Tutorials Basic
http://pygametutorials.wikidot.com/tutorials-basic - Pygame: Font class
http://www.pygame.org/docs/ref/font.html - Python.org (dokumentace k jazyku, odkazy na instalační soubory atd.)
https://www.python.org/ - How to Draw with Pygame on Your Raspberry Pi
http://www.dummies.com/how-to/content/how-to-draw-with-pygame-on-your-raspberry-pi.html - Bresenham's line algorithm
https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm - Xiaolin Wu's line algorithm
https://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm - Pyglet
https://pypi.python.org/pypi/pyglet/1.2.4 - Pyglet documentation
http://pythonhosted.org/pyglet/ - PyOpenGL
https://pypi.python.org/pypi/PyOpenGL/ - Computer font (Wikipedia)
https://en.wikipedia.org/wiki/Computer_font - TrueType (Wikipedia)
https://en.wikipedia.org/wiki/TrueType - SDL and Fonts
http://www.gamedev.net/page/resources/_/technical/game-programming/sdl--fonts-r1953 - SDL_ttf Documentation
http://www.libsdl.org/projects/SDL_ttf/docs/ - SDL_ttf 2.0 (není prozatím součástí SDLJava)
http://www.libsdl.org/projects/SDL_ttf/ - SDL_ttf doc
http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_frame.html - SDL 1.2 Documentation: SDL_Surface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html - SDL 1.2 Documentation: SDL_PixelFormat
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html - SDL 1.2 Documentation: SDL_LockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html - SDL 1.2 Documentation: SDL_UnlockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html - SDL 1.2 Documentation: SDL_LoadBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html - SDL 1.2 Documentation: SDL_SaveBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html - SDL 1.2 Documentation: SDL_BlitSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html - SDL 1.2 Documentation: SDL_VideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html - SDL 1.2 Documentation: SDL_GetVideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html - Graphical user interface (Wikipedia)
http://en.wikipedia.org/wiki/Graphical_user_interface - The Real History of the GUI
http://articles.sitepoint.com/article/real-history-gui - Computer-History: Xerox Alto
http://www.mr-gadget.de/apple/2004-01-15/computer-history-xerox-alto - bitsavers.org
http://www.bitsavers.org/ - Dokumenty k počítači Xerox Alto na bitsavers.org
http://www.bitsavers.org/pdf/xerox/alto/ - The ALTO Computer
http://www.maniacworld.com/alto-computer-video.html - Xerox Alto Operating System and Alto Applications
http://www.digibarn.com/collections/software/alto/index.html - Xerox Alto (Wikipedia)
http://en.wikipedia.org/wiki/Xerox_Alto - BitBLT routines (1975)
http://www.bitsavers.org/pdf/xerox/alto/BitBLT_Nov1975.pdf - BitBlt in Squeak
http://wiki.squeak.org/squeak/189 - Bitmaps, Device Contexts and BitBlt
http://www.winprog.org/tutorial/bitmaps.html - BitBlt Game Programming Tutorial
http://www.freevbcode.com/ShowCode.asp?ID=3677 - Bit blit (Wikipedia)
http://en.wikipedia.org/wiki/BitBLT - The Xerox Alto
http://toastytech.com/guis/alto3.html - History of the graphical user interface
http://en.wikipedia.org/wiki/History_of_the_graphical_user_interface - Domovská stránka systému LÖVE
http://love2d.org/ - Dokumentace k systému LÖVE
http://love2d.org/wiki/love - Domovská stránka programovacího jazyka Lua
http://www.lua.org/ - Seriál o programovacím jazyku Lua (root.cz):
http://www.root.cz/serialy/programovaci-jazyk-lua/ - Web o Lieru, Gusanos, GeneRally, Atari atd.
http://karelik.wz.cz/ - Web o Lieru, Gusanos
http://karelik.wz.cz/gusanos.php - GUSANOS
http://gusanos.sourceforge.net/ - GUSANOS Download
http://sourceforge.net/projects/gusanos/ - Lua
http://www.linuxexpres.cz/praxe/lua - Lua
http://cs.wikipedia.org/wiki/Lua - Lua (programming language)
http://en.wikipedia.org/wiki/Lua_(programming_language) - The Lua Programming Language
http://www.tiobe.com/index.php/paperinfo/tpci/Lua.html - Lua Programming Gems
http://www.lua.org/gems/ - LuaForge
http://luaforge.net/ - Forge project tree
http://luaforge.net/softwaremap/trove_list.php - SdlBasic home page
http://www.sdlbasic.altervista.org/main/ - SdlBasic examples
http://nitrofurano.linuxkafe.com/sdlbasic/ - SdlBasic na Wikipedii
http://en.wikipedia.org/wiki/SdlBasic - Simple DirectMedia Layer
http://en.wikipedia.org/wiki/Simple_DirectMedia_Layer - SDLBASIC – The high-level interpreter for all?
http://openbytes.wordpress.com/2008/11/08/sdlbasic-the-high-level-interpreter-for-all/ - FreeBasic home page
http://www.freebasic.net/ - FreeBASIC (Wikipedia EN)
https://en.wikipedia.org/wiki/FreeBASIC - FreeBASIC Wiki
http://www.freebasic.net/wiki/wikka.php?wakka=FBWiki - FreeBASIC Manual
http://www.freebasic.net/wiki/wikka.php?wakka=DocToc - FreeBASIC (Wikipedia CZ)
http://cs.wikipedia.org/wiki/FreeBASIC - The Griffon Legend
http://syn9.thingie.net/?table=griffonlegend - Seriál Letní škola programovacího jazyka Logo
http://www.root.cz/serialy/letni-skola-programovaciho-jazyka-logo/ - Scratch: oficiální stránka projektu
http://scratch.mit.edu/ - Scratch: galerie projektů vytvořených ve Scratchi
http://scratch.mit.edu/galleries/browse/newest - Scratch: nápověda
file:///usr/share/scratch/Help/en/index.html - Scratch: obrazovky nápovědy
file:///usr/share/scratch/Help/en/allscreens.html - Scratch (Wikipedie CZ)
http://cs.wikipedia.org/wiki/Scratch - Scratch (programming language)
http://en.wikipedia.org/wiki/Scratch_(programming_language) - Scratch Modification
http://wiki.scratch.mit.edu/wiki/Scratch_Modification - Scratch Lowers Resistance to Programming
http://www.wired.com/gadgetlab/2009/03/scratch-lowers/ - Snap!
http://snap.berkeley.edu/ - Prostředí Snap!
http://snap.berkeley.edu/snapsource/snap.html - Alternatives to Scratch
http://wiki.scratch.mit.edu/wiki/Alternatives_to_Scratch - Basic-256 home page
http://www.basic256.org/index_en - Basic-256 Language Documentation
http://doc.basic256.org/doku.php - Basic-256 Art Gallery
http://www.basic256.org/artgallery - Basic-256 Tutorial
http://www.basic256.org/tutorials - Why BASIC?
http://www.basic256.org/whybasic - A book to teach ANYBODY how to program a computer (using BASIC)
http://www.basicbook.org/ - BASIC Computer Games (published 1978) - Hammurabi
http://atariarchives.org/basicgames/showpage.php?page=78 - Hamurabi - zdrojový kód v BASICu
http://www.dunnington.u-net.com/public/basicgames/HMRABI