2. Background#

De achtergrond van het spel houden we in eerste instantie heel eenvoudig: hij bestaat uit twee horizontale balken, waarvan de bovenste de lucht voorstelt en de onderste de grond.

../_images/background.png

Tekenen in Pygame Zero#

Om de twee horizontale balken te tekenen hebben we geen sprites nodig, we kunnen ze gewoon met Pygame Zero tekenen. In de documentatie van Pygame Zero kun je lezen dat de volgende tekenfuncties beschikbaar zijn:

  • screen.draw.line()

  • screen.draw.circle()

  • screen.draw.filled_circle()

  • screen.draw.rect()

  • screen.draw.filled_rect()

  • screen.draw.text()

  • screen.draw.textbox()

Voor de blauwe en groene balk in onze achtergrond, hebben we de functie screen.draw.filled_rect() nodig (rect slaat op rectangle, rechthoek). Bij het aanroepen van deze functie geef je een Rect mee en een kleur. Een Rect is een object dat de positie en afmetingen van een rechthoek bevat. Je kunt een Rect maken met de functie Rect(left, top, width, height) of Rect((left, top), (width, height)). Klinkt ingewikkeld, maar probeer het eens uit met de volgende code in endlessrunner.py:

endlessrunner.py#
 1# Vensterinstellingen
 2WIDTH = 800
 3HEIGHT = 600
 4TITLE = 'Endless Runner'
 5
 6# Functie draw()
 7def draw():
 8   sky_rect = Rect(0, 0, 800, 400)
 9   screen.draw.filled_rect(sky_rect, 'deepskyblue')
10
11# Functie update()
12def update():
13   pass

In regel 8 maken we een rechthoek waarvan de linkerbovenhoek op (0, 0) ligt en die een breedte en hoogte heeft van 800 en 400 pixels. Deze rechthoek noemen we sky_rect. Vervolgens tekenen we deze rechthoek met de kleur 'deepskyblue' in regel 9. Als je dit programma uitvoert, zie je een blauwe rechthoek die het bovenste deel van het venster vult.

Het keyword pass

In regel 13 zie je in de update() functie het keyword pass. Dit is een Python keyword dat aangeeft dat er niets hoeft te gebeuren. Het is handig om pass te gebruiken als je een functie of een codeblok nog niet wilt invullen, maar wel alvast wilt definiëren. Als je pass niet zou gebruiken, zou je een foutmelding krijgen omdat Python verwacht dat er iets in de functie staat.

Een voordeel van het alvast definiëren van de update() functie is, dat Pygame Zero het venster ververst wanneer dat nodig is. Soms komt het namelijk voor dat bij aanvang van het spel een deel van het venster zich buiten je scherm bevindt. Wanneer je het venster dan versleept zodat het geheel zichtbaar is, wordt het venster niet automatisch ververst. Door de update() functie alvast te definiëren, wordt het venster wél ververst en zie je de volledige inhoud van het venster.

Opdracht 01

Maak zelf een rechthoek voor de grond. Noem deze ground_rect en teken hem met de kleur 'darkolivegreen4'. Zorg ervoor dat de rechthoek precies onder de blauwe rechthoek in het venster past.

Kleuren in Pygame

In Pygame Zero kun je kleuren aangeven met namen, zoals 'deepskyblue' en 'darkolivegreen4'. Dit zijn namen die Pygame Zero herkent. Je kunt ook kleuren aangeven met RGB-waarden. Dit zijn tuples van drie getallen tussen 0 en 255 die de hoeveelheid rood (R), groen (G) en blauw (B) in een kleur aangeven. Bijvoorbeeld (255, 0, 0) is rood, (0, 255, 0) is groen en (0, 0, 255) is blauw. Vaak is het echter gemakkelijker om de naam van een kleur te gebruiken.

Ben je nieuwsgierig naar de kleurennamen die Pygame Zero herkent, kijk dan eens op de site van pygame.org.

Een aparte functie voor de background#

Wanneer we straks nog meer elementen van het spel gaan tekenen, wordt de draw() functie steeds langer en mogelijk onoverzichtelijker. Daarom is het handig de code voor het tekenen van de achtergrond in een aparte functie onder te brengen. Zo houden we het overzichtelijk.

Opdracht 02

Maak een nieuwe functie met de naam draw_background(). Verplaats de code voor het tekenen van de lucht en de grond uit de draw() functie naar de nieuwe functie. Roep de nieuwe functie aan in de draw() functie. Als je het goed hebt gedaan, zie je geen verschil in het venster.

Oplossing
endlessrunner.py#
 1# Vensterinstellingen
 2WIDTH = 800
 3HEIGHT = 600
 4TITLE = 'Endless Runner'
 5
 6# Functie draw_background()
 7def draw_background():
 8   sky_rect = Rect(0, 0, 800, 400)
 9   screen.draw.filled_rect(sky_rect, 'deepskyblue')
10   ground_rect = Rect(0, 400, 800, 200)
11   screen.draw.filled_rect(ground_rect, 'darkolivegreen4')
12
13# Functie draw()
14def draw():
15   draw_background()
16
17# Functie update()
18def update():
19   pass

Variabele horizon#

Op dit moment zijn de afmetingen van de horizontale balken hard coded. Dat wil zeggen dat de waarden 800, 400 en 200 direct in de code staan. Als we later de afmetingen van de balken willen aanpassen, moeten we dat op meerdere plaatsen in de code doen. Dat is niet handig en bovendien foutgevoelig. Het is beter hiervoor variabelen te gebruiken.

De afmetingen van de twee rechthoeken zijn nu als volgt geprogrammeerd:

sky_rect = Rect(0, 0, 800, 400)
ground_rect = Rect(0, 400, 800, 200)

De hoogte van sky_rect is 400 pixels. Je zou dus kunnen zeggen dat de horizon op 400 pixels vanaf de bovenkant van het venster ligt. We gaan deze positie van de horizon vastleggen in een constante met de naam HORIZON. Een constante is een variabele waarvan de waarde niet verandert tijdens de uitvoering van het programma. In Python is het de gewoonte de naam van een constante in hoofdletters te schrijven. De vensterinstellingen WIDTH, HEIGHT en TITLE zijn ook constanten.

endlessrunner.py#
1# Vensterinstellingen
2WIDTH = 800
3HEIGHT = 600
4TITLE = 'Endless Runner'
5
6# Constanten
7HORIZON = 400
8
9# overige code weggelaten
Opdracht 03

Wijzig de code voor het maken van de rechthoeken sky_rect en ground_rect zodat:

  • de breedte van de rechthoeken wordt bepaald door de constante WIDTH;

  • de hoogte van de rechthoeken wordt bepaald door de constanten HEIGHT en HORIZON. Let op: ook de positie van de onderste rechthoek is afhankelijk van HORIZON!

In de afmetingen van sky_rect en ground_rect mag naast de constanten WIDTH, HEIGHT en HORIZON alleen het getal 0 voorkomen.

Controleer of de achtergrond nog steeds correct wordt getekend.

Bekijk de oplossingen pas nadat je zelf een oplossing hebt gevonden, of als je er na vijf minuten (niet minder!) nog niet bent uitgekomen.

Oplossing voor sky_rect
sky_rect = Rect(0, 0, WIDTH, HORIZON)
Oplossing voor ground_rect
ground_rect = Rect(0, HORIZON, WIDTH, HEIGHT - HORIZON)

Nu je de positie van de horizon in een constante hebt gedefinieerd, kun je die eenvoudig wijzigen. Probeer maar eens verschillende waarden voor HORIZON uit. Als je de waarde van HORIZON verandert, verandert de positie van de horizon in het venster.