Ügyességi játékok programozása
Pythonnal és Pygame-mel

Chapter 11: Bitmapos grafika és hang

Szeretnénk bonyolultabb alakzatokkal foglalkozni, nem csak háromszöggel és körrel, ehhez viszont a programunknak szükséges lesz bitmapos grafikával dolgoznia. A bitmapos grafika lehet fotó vagy egy rajzprogrammal készített kép.

Azonban a grafika önmagában nem elég. Szükség lesz hangra is! Ez a fejezet azt mutatja be, hogyan tegyünk grafikát és hangot a játékunkba.

11.1 A program tárolása egy mappában

Videó: A projekt szervezett tárolása mappában

Azok a programok, amiket eddig gyártottunk csak egy fájlból álltak. Most szükségünk lesz zenére, képre, ami már több fájlt feltételez. Könnyen összekeverhetjük más programokhoz tartozó fájlokkal. Ahhoz, hogy mindent tisztán tartsunk, egy saját mappában kell kezelni az azonos programhoz tartozó fájlokat. Mielőtt még bármilyen projektet elkezdenénk, kattintsunk az új mappa gombra, és használjuk, majd tegyük bele az összes szükséges fájlt. ábra 11.1.

fig.create_a_folder
Figure 11.1: Új mappa létrehozása

11.2 Háttérkép beállítása

Videó: Projekt rendezése mappában

Kell egy háttérkép a játékodba? Keress egy képet, mint amilyen az ábrán 11.2. Ha online keresel egy böngészővel, akkor általában csak jobb kattintás a képen, mentés a számítógépre. Mentsd a mappába, amit a projekt számára most hoztál létre.

Bizonyosodj meg arról, hogy nem használsz jogosulatlanul képet. Egy egyszerű kereséssel vissza lehet keresni, ha más képét használod. A kurzus felénél tartasz, ne tedd kockára ezzel.

fig.background_image
Figure 11.2: Háttérkép

Bármilyen bittérképes kép, amit szeretnél használni, azt előbb formázd át a megfelelő méretre. Ne használj 5000x5000 pixeles képet egy nagy felbontású fényképezőből, és aztán töltsd be egy 800x600-s ablakba. Használj grafikus programot (MS Paint pl.) és méretezd át a képet a Python programodhoz megfelelőnek.

Egy kép betöltése egy egyszerű eljárás, és magába foglal mindössze pár sor kódot. Elég sok dolog történik ezzel az egy sor kóddal, amit el kell magyarázni. Szóval három részre kell osztani ezt a magyarázatot is. Az első verziója a load (betöltés) parancsunknak egy fájlt fog betölteni, amit saturn_family1.jpg-nek hívnak. Ennek a fájlnak ugyanabban a könyvtárban kell lennie, ahol a python programodnak is, máskülönben a számítógép nem fogja megtalálni.

pygame.image.load("saturn_family1.jpg")

Ez a kód be fog tölteni egy képet, de még nem tudunk hivatkozni rá, sem megtekinteni. Ehhez kell egy változó, amit a load() parancs visszaad. A következő betöltés parancsunkban csinálunk egy új változót, amit majd background_image-nek nevezünk el. Lásd alább a második verziót:

background_image = pygame.image.load("saturn_family1.jpg")

Végül, a képnek szüksége van arra, hogy olyan formába legyen konvertálva, amivel a Python könnyen tud dolgozni. Ehhez használjuk a .convert() parancsot, ami egy függvény. Ez a függvény egy eljárás az Image osztályon belül. Később még beszélünk az osztályokról, objektumokról és a metódusokról a 13-dik fejezetben.

Minden képet be kell tölteni hasonlóan ehhez a kódhoz. Ehhez annyit kell tenned, hogy megváltoztatod a változó nevét, és a betölteni kívánt fájlt.

background_image = pygame.image.load("saturn_family1.jpg").convert()

A kép betöltése a főprogram ciklusa előtt kell hogy történjen. Lehetséges ugyan, hogy betöltsük a főprogramba, amiáltal a program huszonpárszor meghívhatja a képet a lemezről (másodpercenként). Ez teljesen felesleges. Ez csak akkor szükséges, amikor a program éppen elindul.

A kép megjelenítéséhez használjuk a blit parancsot. Ez fogja a képet kiblittelni a képernyőre. Használtuk már ezt a parancsot, mikor szöveget jelenítettünk meg a játék képernyőjén az 5-s fejezetben.

A blit parancs egy metódus, ami screen változót használ, szóval a parancsunkat egy screen.blit-tel kell kezdeni. Azután, hagyni kell, hogy a képet valahol megjelenítse. Ennek a parancsnak a cikluson belül kell elhangoznia, így a kép frame-enként lesz kiralyzolva. Lásd alább:

screen.blit(background_image, [0, 0])

Ez a kód kirajzolja a képet, amit a background_image tartalmaz a képernyőre, a (0,0) kezdőpontra.

11.3 Kép mozgatása

Videó: Kép mozgatása

Most már szeretnénk betölteni és mozgatni egy képet a képernyőn. Egy egyszerű narancssárga űrhajóval kezdjük. Ezt és még sok mást is elérhetsz innen: http://kenney.nl/. Lásd ábra 11.3. A hajó képe letölthető a könyv weboldaláról, vagy használhatsz bármilyen gifet vagy png-t amit szeretnél, vagy fekete-fehér hátteret. De ne használj jpg-t.

fig.player_image
Figure 11.3: Játékos képe

Ahhoz, hogy betöltsük a képet, szükségünk van ugyanarra a parancsra, amit használtunk már a háttérnél. Ebben az esetben, azt javaslom, hogy a fájlt mentsük el player.png néven.

player_image = pygame.image.load("player.png").convert()

A főprogramon belül, az egér koordinátákat visszanyerjük, és odaadjuk egy másik blit függvénynek, hogy azok alapján rajzolja ki a képet:

# Fogjuk a jelenlegi egér pozíciót. Ez két számnak a listáját adja vissza.

player_position = pygame.mouse.get_pos()
x = player_position[0]
y = player_position[1]

# Képet a képernyőre másol
screen.blit(player_image, [x, y])

Ez rávilágít egy problémára. A kép egy űrhajó, egyszínű fekete háttérrel. Szóval, amikor a képet kirajzoljuk, akkor a program így jeleníti meg: 11.4.

fig.nontrans_background

Mi csak az űrhajót akarjuk, a hátterére nincs szükségünk. Dehát minden képünk téglalap, hogyan lehetne ebből csak a szükséges képet megjeleníteni? Ehhez meg kell mondani a programnak, hogy legyen egy szín átlátszó, vagy transzparens, és ne jelenítse meg. Ez betöltés után azonnal végrehajtódik. Az alábbi fogja a feketét átlátszóvá tenni (a BLACK már definiálva lett változóként):

player_image.set_colorkey(BLACK)

Ez mindaddig működni fog, amíg a kép gif, vagy png kiterjesztésű. Nem a legjobban fog működni jpg-n. A jpg formátum ugyanis nagyszerű arra, hogy fényképeket tároljon, de átalakítja a képet egy algoritmussal azért, hogy az kisebb legyen. A gif és png fájlok szintén össze vannak sűrítve, de az algoritmus, amit ehhez használnak, nem változtatja meg a képet. A bmp fájl nincs összetömörítve sehogy sem és az eredmény egy óriási fájl. A jpg formátum megváltoztatja a formáját, ami azt jelenti, hogy nem minden fekete hátteret tüntet el a program. Az alábbi ábrán 11.5 az űrhajó jpg-ként lett elmentve, fehér háttérrel. A fehér szín a hajó körül nem tűnt el teljesen (255,255,255), csak majdnem. Majdnem jó a megoldás.

fig.jpeg_artifacts
Figure 11.5: JPEG-vé tömörített kép

Ha egy képet veszel, ami áttetsző, akkor válassz gif-t vagy png-t. Ezek a legjobb formátumok a művész grafika típusú képekhez. A fotók lehetnek jpg-k. Jegyezd meg azt is, hogy nem lehetséges a jpg kiterjesztését úgy megváltoztatni, hogy átnevezed png-re. Továbbra is jpg marad, mégha másképp hívod is. Ehhez egy grafikus program kell, hogy a formátum konverziója meglegyen. De ha már jpg formátumú, és át lett konvertálva png-vé, nem lesz tökéletes akkor sem.

Itt van három hely, ahol ingyen képeket találhatsz a programodhoz:
OpenGameArt.Org
HasGraphics.com
Kenney.nl

11.4 Hangok

Videó: Hangok

Ebben a részben egy lézer hangot fogunk lejátszani, amikor az egérrel kattintanak. Ez a hang eredetileg Kenney.nl-ből van. Itt töltheted le a hangot:
ProgramArcadeGames.com/python_examples/en/laser5.ogg

Ahogyan a képek, a hangok is be kell töltődjenek, mielőtt használják. Ennek meg kell lennie még a főprogram előtt. A következő parancs betölti a hangfájlt és egy változót hoz létre, amivel a click_sound-vel tudunk hivatkozni:

click_sound = pygame.mixer.Sound("laser5.ogg")

A következő parancs segítségével játszhatjuk le a hangot:

click_sound.play()

De hová kell tenni ezt a parancsot? Ha főprogramba tesszük, akkor huszonpárszor játszuk majd le másodpercenként. Igazán idegesítő. Kell egy kioldó cselekvés. Valamely cselekvés beteljesedik, és akkor lejátszódik a hang. Például ez a hang le fog játszódni, amikor a felhasználó lenyomja az egérgombot, a következő kódban:

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        done = True
    elif event.type == pygame.MOUSEBUTTONDOWN:
        click_sound.play()

Az össze nem tömörített fájlok .wav-ra végződnek. Ezek a fájlok nagyobbak, mint más formátumok, mivel semmilyen algoritmus nem futott le, hogy kisebbé tegye őket. Azután ott van még a népszerű .mp3 formátum, habár ennek a formátumnak vannak szabadalmai, ami miatt némely alkalmazás nem szereti. Másik formátum, ami ingyenesen használható az az OGG Vorbis formátum és a .ogg-re végződik.

A Pygame nem játszik le minden .wav fájlt, amit az interneten találsz. Ha egy fájl nem működik, akkor próbáld meg használni az alábbi programot: Audacity. Ezzel képes leszel ogg-vobis fájllá konvertálni más fájlokat. Ez a fájl formátum kicsi és megbízható a pygame számára.

Amennyiben háttérzenét szeretnél a programodhoz, akkor nézd meg az online példákat:
ProgramArcadeGames.com/python_examples/f.php?file=background_music.py

Kérlek, jegyezd meg, hogy nem oszthatsz meg márkavédett zenét a programodban. Mégha csinálsz is egy programot, ami copyrightos zenével szól a háttérben a youtuberól, akkor is megtalálhatnak védett márka megsértése miatt.

Vannak jó helyek, ahol találhatsz ingyen zenét a programodhoz:
OpenGameArt.Org
www.freesound.org

11.5 Teljes lista

"""
 Sample Python/Pygame Programs
 Simpson College Computer Science
 http://programarcadegames.com/
 http://simpson.edu/computer-science/

 Explanation video: http://youtu.be/4YqIKncMJNs
 Explanation video: http://youtu.be/ONAK8VZIcI4
 Explanation video: http://youtu.be/_6c4o41BIms
"""

import pygame

# Define some colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

# Call this function so the Pygame library can initialize itself
pygame.init()

# Create an 800x600 sized screen
screen = pygame.display.set_mode([800, 600])

# This sets the name of the window
pygame.display.set_caption('CMSC 150 is cool')

clock = pygame.time.Clock()

# Before the loop, load the sounds:
click_sound = pygame.mixer.Sound("laser5.ogg")

# Set positions of graphics
background_position = [0, 0]

# Load and set up graphics.
background_image = pygame.image.load("saturn_family1.jpg").convert()
player_image = pygame.image.load("playerShip1_orange.png").convert()
player_image.set_colorkey(BLACK)

done = False

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        elif event.type == pygame.MOUSEBUTTONDOWN:
            click_sound.play()

    # Copy image to screen:
    screen.blit(background_image, background_position)

    # Get the current mouse position. This returns the position
    # as a list of two numbers.
    player_position = pygame.mouse.get_pos()
    x = player_position[0]
    y = player_position[1]

    # Copy image to screen:
    screen.blit(player_image, [x, y])

    pygame.display.flip()

    clock.tick(60)

pygame.quit()

11.6 Áttekintés

11.6.1 Kvízkérdések

Click here for a multiple-choice quiz.

11.6.2 Feladatlap

Click here for the chapter worksheet.

11.6.3 Labor feladat

Click here for the chapter lab.


You are not logged in. Log in here and track your progress.