Arcade-pelien ohjelmointi
Pythonilla ja Pygamella

Chapter 11: Bittikarttagrafiikka ja äänet

Lisätäksemme peleihimme vaativampia kuvioita kuin aiemmin esillä olleita ympyröitä ja suorakulmioita, meidän on otettava käyttöön bittikartta grafiikka. Bittikarttagrafiikkaa voidaan luoda ja tallentaa eri piirto- ja kuvankäsittelyohjelmilla.

Pelkillä bittikarttakuvilla emme mielenkiintoista peliä saa tehtyä, vaan tärvitsemme myös ääniä. Tässä kappaleessa opimme lisäämään peliin grafiikkaa ja ääniä.

11.1 Ohjelman tallentaminen kansioon

Video: Organizing a project in a folder

Tähän mennessä tehdyt ohjelmat ovat olleet yhteen tiedostoon tallennettuja kokonaisuuksia. Nyt, kuun liitääme mukaan ääniä ja grafiikkaa, koostuvat ohjelmamme useammasta tiedostosta. Näin saamme helposti nämä tiedostot yhdistettyä muihinkin ohjelmiimme. Tapa, jolla saamme kaikki tiedostot pidettyä hallinnassa ja erillään, on tallentaa nämä tiedostot omiin kansioihinsa (hakemistoihin). Ennen kuin aloitat uutta projektia, luo “uusi kansio” ja käytä tätä kansiota tiedostojesi tallennuspaikkana. Katso kuvaa 11.1.

fig.create_a_folder
Figure 11.1: Creating a new folder

11.2 Taustakuvan asettaminen

Video: Organizing a project in a folder

Pitäisikö peliisi saada taustakuva? Etsi esimerkiksi kuvan 11.2 kaltainen kuva. Jos haet kuvaa netistä selaimella, niin saat hiiren oikealla painikkeella pikavalikon 'Tallenna kuva' komennolla tallennettua kuvan kansioosi. Tallenna se siis äsken luotuun kansioon.

Kuvien käytössä sinun tulee olla tarkkana tekijänoikeuksista! Googlen 'reverse-image search' haulla voi tekijä tarkistaa kuviensa luvatonta kopiointia, joten älä saata itseäsi noloon tilanteeseen ja käytä tekijänoikeussuojattua materiaalia ilman lupaa. NEtistä löytyy kyllä luvallistakin materiaalia todella paljon.

fig.background_image
Figure 11.2: Background Image

Bittikarttakuvien resoluutio pitää ennen peliin liittämistä muokata sopivaksi. älä siis käytä suoraan talentamaasi 5000x5000 pixelin kuvaa, jokia on otettu korkearesoluutioisella kameralla. Tätä kuvaa ei voi ladata ikkunaan, jonka koko on vain 800x600. Kuvakokoa pitää siis muokata kuvankäsittelyohjelmalla (vaikkapa Paint soveltuu, mutta parempiakin löytyy, Paint.net jne.). Kuvaa voi vaatia myös rajausta eli 'croppaamista' ennen kuin sitä voidaan käyttää Python ohjelmassa.

Kuvan lataaminen on yksinkertaisa. Se vaatii vain yhden rivin koodia. Tuon yhden rivin komennolla kuitenkin 'tapahtuu' melko paljon erilaisia asioita, joten selitys on syytä jakaa kolmeen osaan. Ensimmäinen versiomme load komento lataa tiedoston nimeltään saturn_family1.jpg. Tämän kuvatiedoston tulee olla samassa kansiossa python ohjelmakoodin kanssa. Ellei se ole, niin ohjelma ei löydä tiedostoa:

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

Tämä koodi lataa kuvan, mutta emme saa kuvaa näkyviin, kun kuvaan ei voida 'viitata'! Tarvitsemme siis muuttujan, jonka arvoksi kuvatiedoston lataus asetetaan. Tässä siis kuvan latausfunktio load() palauttaa arvon, johon viitataan. Seuraavassa esimerkissä load komennossa on mukana muuttuja background_image. Katso esimerkin toista versiota:

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

Lopuksi, kuva pitää konvertoida Pygamen ymmärtämään muotoon, jolloin kuvaa on helpompi käsitellä ohjelmassa. Lisätään koodiin .convert() joka kutsuu funktiota, joka konvertoi kuvan Pythonille sopivaksi. Funktio .convert() on tarkemmin ilmaistuna Image luokan metodi. Puhutaan luokista, objekteista ja metodeista sekä funktioista tarkemmiin kappaleessa 12.

Kaikki kuvat pitää ladata alla olevan esimerkin mukaisella tavalla. Käytä vain eri nimiä muuttujaan ja ladattavaan tiedostoon.

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

Kuvatiedostojen lataaminen pitää tehdä ennen ohjeman pääsilmukan aloitusta. Vaikka kuvan lataaminen ohjelman pääsilmukassa onkin mahdollista, hidastuu koneen toiminta todella paljon, koska kuvaa ladataan silmukassa useita kertoja sekunnissa kiintolevyltä/massamuistilta. Tämä on siis hidasta ja ennen kaikkea tarpeetonta, koska kuvien lataaminen tehdään kerran ohjelman käynnistyksen yhteydessä.

Kuvan näyttämiseen on blit komento. Tämä “blittaa” kuvan paloina näytölle. Käytimme tätä komentoa aiemmin kappaleessa 5 tekstin näyttämisen yhteydessä peli-ikkunassa.

blit komento on itse asiassa screen muuttujan metodi, joten komennon kirjoittaminen pitää aloittaa screen.blit. Seuraavaksi 'välitämme' kuvan blit-metodille. Tämä komento pitää suorittaa silmukan sisällä, niin kuva piirretään jokaisessa freimissä. Katso alla olevaa esimerkkiä:

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

Tämä koodi 'blittaa' kuvan background_image näytölle aloittaen pisteestä (0, 0).

11.3 Kuvan siirtäminen

Video: Moving an Image

Seuraavaksi lataamme kuvan ja liikutamme sitä näytöllä. Aloitetaan yhksinkertaisella oranssilla avaruusaluksen kuvalla. Voit ladata tämän ja paljon muita kuvia täältä http://kenney.nl/. Katso kuvaa 11.3. Voit ladata kuvan materiaalin nettisivulta tai voit etsiä haluamasi .gif tai .png kuvan, joka sopii mustaan tai valkoiseen taustaan. älä käytä .jpg kuvaa.

fig.player_image
Figure 11.3: Player image

Kuvan lataamiseen käytetään samanlaista komentoa kuin edellä käytimme taustakuvan lataamiseen. Tässä tapauksessa oletan, että kuva on tallennettu nimellä player.png.

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

Ohjelman pääsilmukan sisällä saadaan luettua hiiren koordinaattien arvot. Käytetään näitä arvoja blit funktiossa, jolloin saadaan määrättyä kuvan piirtopaikka.

# Luetaan hiiren sijainnin koordinaatit ja palautetaan arvo 
# kahden numeroarvon listana
player_position = pygame.mouse.get_pos()
x = player_position[0]
y = player_position[1]

# Kopioidaan kuva näytölle
screen.blit(player_image, [x, y])

Tästä seuraa pieni ongelma. Avaruusaluksessa on musta taustaväri. Joten, jos kuva piirretään kuten seuraavassa ohjelmassa on esitetty 11.4.

fig.nontrans_background

Kuvassa oleva neliömainen musta tausta häiritsee, joten siitä on päästävä eroon. Tämä tausta voidaan poistaa ohjelmassa tekemällä taustaväristä läpinäkyvä ,“transparent”. Tämä voidaan tehdä heti kuvan lataamisen jälkeen. Seuraava koodi tekee mustasta väristä läpinäkyvän. (oletetaan, että BLACK on määritelty muuttujaksi).

player_image.set_colorkey(BLACK)

Tämän pitäisi toimia kaikilla .gif ja .png tyyppisillä tiedostoilla sekä useimmilla .jpg kuvilla. jpeg kuvatiedostomuoto on hyvä valokuvien esittämiseen, mutta se herkästi muuttaa kuvan osaksi algoritmia, jolloin se koko muuttuu pienemmäksi. Kuvatiedostot .gif ja .png ovat myös pakattuja, mutta algoritmi ei näissä tiedostotyypeissä muuta kuvan kokoa. bmp-kuvatiedostoja ei pakata ollenkaan ja seurauksena onkin valtavankokoiset tiedostot. Koska .jpg tiedoston käsittely algoritmissa on tiedostoa muokkaava, saattaa jotkin taustavärit muuttua eivätkä ole täysin alkuperäisen kaltaisia. Kuvassa 11.5 avaruusalus on tallennettu jpeg-muodossa valoiseen taustaan. Valkoinen väri ei kuitenkaan ole täsmälleen valkoinen eli (255, 255, 255), mutta lähellä oikeaa.

fig.jpeg_artifacts
Figure 11.5: JPEG Compression Artifacts

Jos käytät läpinäkyvää kuvaa, niin valitse silloin .gif tai .png tyyppisiä tiedostoja. Nämä toimivat parhaiten objekteissa. Valokuvien pitäisi olla .jpg -tyyppisiä. Muistathan, että kuvatiedoston tyyppiä ei voi vaihtaa vain muuttamalla tiedostopäätettä, vaan tiedoston tallennustyyppi pitää konvertoida toiseen tyyppiin kuvankäsittelyohjelmassa.

Seuraavista nettiosoitteista voit löytää kuvia omaan peliisi:
Kenney.nl
OpenGameArt.org
HasGraphics.com

11.4 äänet

Video: Sounds

Tässä kappaleessa luomme hiiren klikkaamisella aktivoituvan laseräänen. Tämä äänitiedosto löytyy Kenney.nl -sivustolta ja voit ladata sen myös tästä:
ProgramArcadeGames.com/python_examples/en/laser5.ogg

Kuten kuvat, niin myös äänitiedostot pitää ladata ennen käyttöä. Tämä pitää tehdä kerran ennen phjelman pääsilmukkaa. Seuraavassa komennossa ladataan äänitiedosto ja luodaan sille muuttuja click_sound käsittelyä varten:

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

äänitiedosto voidaan toistaa seuraavalla komennolla:

click_sound.play()

Mutta mihin kohtaan tämä komento laitetaan? Jos se laitetaan pääohjelmasilmukkaan, toistetaan se 20 kertaa sekunnissa. Ei siis toimi. Tarvitsemme `triggerin.” Jos jokin tapahtuma toteutuu niin toistamme äänitiedoston. Esimerkiksi sopiva tapahtuma olisi käyttäjän klikkaus hiiren painikkeella. Tämä on seuraavassa koodiesimerkissä:

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

Pakkaamattomat ääniitiedostot ovat .wav tyyppisiä. 'Wavit' ovat tiedostokooltaan suurempia kuin monet muut äänitiedostotyypit, koska muut tiedostot ovat (yleensä) pakattuja jollakin algoritmilla. Tällainen on myös suosittu .mp3 tiedosto, vaikkakin se ei ole kaikkiin ohjelmiin sopiva johtuen rajoitetuista patenteista. Toinen tiedosto muoto, joka on patenttivapaa, on OGG Vorbis tiedostomuoto ja sen tunnistaa päätteestä .ogg.

Pygame ei toista kaikkia .wav tiedostoja, jotka netistä ladataan. Toimimattomia tiedostoja voit yrittää muokata Audacity-editorilla, joka löytyy vaikkapa tästä: Audacity. Muunna toimimaton tiedosto Audacitylla ogg vorbis muotoon. Tämä äänitiedostotyyppi on luotettava ja toimiva vaihtoehto Pygame-peleihin.

Jos haluat luoda peliisi taustamusiikin, niin katso seuraava on-line esimerkki:
ProgramArcadeGames.com/en/python_examples/f.php?file=background_music.py

Olethan tietoinen, että et voi jakaa peliohjelmia, joissa on tekijänoikeudella suojattua ääntä ja musiikkia. Vaikkapa ainoastaan videoesitys pelistäsi, jossa on 'kopiraitti' -musiikkia on laiton levitettäväksi YouTubessa.

Seuraavilta nettisivuilta voit ladata vapaasti musiikkia ohjelmiisi:
OpenGameArt.org
www.freesound.org

11.5 Full Listing

"""
 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 Review

11.6.1 Multiple Choice Quiz

Klikkaa tästä monivalintatehtävään.

11.6.2 Short Answer Worksheet

Klikkaa tästä kappaleen kertaustehtäviin.

11.6.3 Lab

Klikkaa tästä ohjelmointitehtäviin.


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