Vallende stenen

0 Wat gaan we leren

We gaan nog een projectje maken met Thonny (uit de vorige les) en bij dit project gaan we gebruik maken van de standaard Python library:

pgzero

Weet je nog hoe je een pacakge installeert in Thonny?

Yep, Tools - Manage Packages en dan pgzero zoeken en installeren.

1 Teken speler en steen

In deze les gaan we de speler en één vallende steen tekenen.

We beginnen met een eenvoudige versie: een blokje onderaan dat je straks kunt besturen, en een steen die we straks laten vallen.

Wat gaan we doen?

We tekenen een rechthoek voor de speler en een rechthoek voor de steen.

We gebruiken vaste posities om de eerste versie werkend te krijgen.

🔰 Code

import pgzrun

WIDTH = 800
HEIGHT = 600

# Speler onderaan het scherm
player_x = 400
player_y = 550
player_width = 80
player_height = 20

# Vallende steen bovenaan
rock_x = 300
rock_y = 0
rock_size = 40

def draw():
    screen.clear()
    screen.draw.filled_rect(Rect((player_x, player_y), (player_width, player_height)), "blue")
    screen.draw.filled_rect(Rect((rock_x, rock_y), (rock_size, rock_size)), "gray")

pgzrun.go()

ℹ️ Uitleg

🛠️ Opdracht

💡 Extra uitdaging

📤 Inleveren

  1. Maak een screenshot waarop je de speler en minstens één steen ziet (waarbij je de plaats van de steen dus hebt aangepast).

2 Speler bewegen

In deze les gaan we de speler besturen met de pijltjestoetsen.

De speler beweegt alleen naar links en rechts, en mag niet buiten het scherm gaan.

Wat gaan we doen?

We bewerken de update()-functie om de x-positie van de speler aan te passen als je op pijltjes drukt.

We voegen een maximale en minimale positie toe zodat de speler niet van het scherm glijdt.

🔰 Code

import pgzrun

WIDTH = 800
HEIGHT = 600

player_x = 400
player_y = 550
player_width = 80
player_height = 20
player_speed = 5

rock_x = 300
rock_y = 0
rock_size = 40

def draw():
    screen.clear()
    screen.draw.filled_rect(Rect((player_x, player_y), (player_width, player_height)), "blue")
    screen.draw.filled_rect(Rect((rock_x, rock_y), (rock_size, rock_size)), "gray")

def update():
    global player_x

    if keyboard.left:
        player_x -= player_speed
    if keyboard.right:
        player_x += player_speed

    # Speler binnen scherm houden
    if player_x < 0:
        player_x = 30
    if player_x > WIDTH - player_width:
        player_x = WIDTH - player_width

pgzrun.go()

ℹ️ Uitleg

🛠️ Opdracht

Tip: bij welke if wordt gekeken of de speler tegen de linkerkant van het scherm aan zit?

💡 Extra uitdaging

📤 Inleveren

  1. Leg in eigen woorden uit hoe de player_speed de snelheid van het spel veranderd.
  2. Leg uit waarom de speler aan de linkerkant van het scherm 'stuitert' en wat heb je aangepast om dit te voorkomen?

3 Steen laten vallen

In deze les gaan we de steen automatisch laten vallen.

Zodra de steen de onderkant van het scherm bereikt, verschijnt hij opnieuw bovenaan op een willekeurige plek.

Wat gaan we doen?

We voegen een rock_speed toe en laten de y-positie van de steen langzaam toenemen in update().

We controleren of de steen het scherm uit valt, en zetten hem dan opnieuw bovenaan met een willekeurige x-positie.

🔰 Code

import pgzrun
import random

WIDTH = 800
HEIGHT = 600

player_x = 400
player_y = 550
player_width = 80
player_height = 20
player_speed = 5

rock_x = random.randint(0, WIDTH - 40)
rock_y = 0
rock_size = 40
rock_speed = 3

def draw():
    screen.clear()
    screen.draw.filled_rect(Rect((player_x, player_y), (player_width, player_height)), "blue")
    screen.draw.filled_rect(Rect((rock_x, rock_y), (rock_size, rock_size)), "gray")

def update():
    global player_x, rock_y, rock_x, rock_size

    if keyboard.left:
        player_x -= player_speed
    if keyboard.right:
        player_x += player_speed

    if player_x < 0:
        player_x = 0
    if player_x > WIDTH - player_width:
        player_x = WIDTH - player_width

    # Steen laten vallen
    rock_y += rock_speed

    # Als de steen onderaan is, zet hem weer bovenaan met random x
    if rock_y > HEIGHT:
        rock_y = 0
        rock_x = random.randint(0, WIDTH - rock_size)

pgzrun.go()

ℹ️ Uitleg

🛠️ Opdracht

💡 Extra uitdaging

📤 Inleveren

  1. Leg uit hoe je ervoor hebt gezorgdt dat de steen telkens een ander grootte kijgt.

4 Botsing & Game Over

In deze les gaan we controleren of de speler de steen raakt.

Als er een botsing is, stopt het spel en verschijnt er de tekst “Game Over”.

Wat gaan we doen?

We maken een Rect van de speler en van de steen, en gebruiken colliderect() om te zien of ze elkaar raken.

We gebruiken een variabele game_over om te stoppen met het spel als er een botsing is.

🔰 Code

import pgzrun
import random
from pygame import Rect

WIDTH = 800
HEIGHT = 600

player_x = 400
player_y = 550
player_width = 80
player_height = 20
player_speed = 5

rock_x = random.randint(0, WIDTH - 40)
rock_y = 0
rock_size = 40
rock_speed = 3

game_over = False

def draw():
    screen.clear()
    if game_over:
        screen.draw.text("GAME OVER", center=(WIDTH // 2, HEIGHT // 2), fontsize=60, color="red")
        return

    screen.draw.filled_rect(Rect((player_x, player_y), (player_width, player_height)), "blue")
    screen.draw.filled_rect(Rect((rock_x, rock_y), (rock_size, rock_size)), "gray")

def update():
    global player_x, rock_y, rock_x, game_over

    if game_over:
        return

    if keyboard.left:
        player_x -= player_speed
    if keyboard.right:
        player_x += player_speed

    if player_x < 0:
        player_x = 0
    if player_x > WIDTH - player_width:
        player_x = WIDTH - player_width

    rock_y += rock_speed

    if rock_y > HEIGHT:
        rock_y = 0
        rock_x = random.randint(0, WIDTH - rock_size)

    # Botsing detecteren
    speler_rect = Rect(player_x, player_y, player_width, player_height)
    steen_rect = Rect(rock_x, rock_y, rock_size, rock_size)

    if speler_rect.colliderect(steen_rect):
        game_over = True

pgzrun.go()

ℹ️ Uitleg

🛠️ Opdracht

💡 Extra uitdaging

📤 Inleveren

  1. Leg eersts stap-voor-stap in he eigen woorden uit hoe er een botsing van de steen met de speler wordt gedetecteerd.
  2. Leg daarna stap-voor-stap, in eigen woorden uit wat er allemaal gebeurt als de steen tegen de speler aan komt. Verwijs daarbij naar de code.

5 Meerdere stenen & moeilijker maken

In deze les gaan we meerdere stenen tegelijk laten vallen.

Bovendien maakt het spel zichzelf moeilijker naarmate je langer speelt: de stenen vallen sneller.

Wat gaan we doen?

We maken een lijst van stenen, elk met hun eigen positie en snelheid.

We laten deze stenen vallen en bij een botsing stoppen we het spel.

We laten het spel steeds moeilijker worden door de snelheid te verhogen na een paar seconden.

🔰 Code

import pgzrun
import random
from pygame import Rect

WIDTH = 800
HEIGHT = 600

player_x = 400
player_y = 550
player_width = 80
player_height = 20
player_speed = 5

rocks = []
game_over = False
rock_timer = 0
rock_interval = 60  # frames
difficulty = 1.0

# Start met een paar stenen
for _ in range(3):
    x = random.randint(0, WIDTH - 40)
    speed = random.uniform(2, 4)
    rocks.append({"x": x, "y": 0, "size": 40, "speed": speed})

def draw():
    screen.clear()
    if game_over:
        screen.draw.text("GAME OVER", center=(WIDTH // 2, HEIGHT // 2), fontsize=60, color="red")
        return

    screen.draw.filled_rect(Rect((player_x, player_y), (player_width, player_height)), "blue")
    for rock in rocks:
        screen.draw.filled_rect(Rect((rock["x"], rock["y"]), (rock["size"], rock["size"])), "gray")

def update():
    global player_x, game_over, rock_timer, difficulty

    if game_over:
        return

    if keyboard.left:
        player_x -= player_speed
    if keyboard.right:
        player_x += player_speed

    player_x = max(0, min(WIDTH - player_width, player_x))

    speler_rect = Rect(player_x, player_y, player_width, player_height)

    for rock in rocks:
        rock["y"] += rock["speed"] * difficulty

        if rock["y"] > HEIGHT:
            rock["y"] = 0
            rock["x"] = random.randint(0, WIDTH - rock["size"])
            rock["speed"] = random.uniform(2, 5)

        rock_rect = Rect(rock["x"], rock["y"], rock["size"], rock["size"])
        if speler_rect.colliderect(rock_rect):
            game_over = True

    # Verhoog de moeilijkheid langzaam
    rock_timer += 1
    if rock_timer % 300 == 0:
        difficulty += 0.2

pgzrun.go()

ℹ️ Uitleg

🛠️ Opdracht

Tip: weet je nog dat je met random.randint(1,4) een getal tussen 1 en 4 kan genereren?

💡 Extra uitdaging

📤 Inleveren

  1. Lever je code (.py bestand) in.

**************************************************

6 Score, Reflectie & Uitbreiding

In deze les voeg je een score toe die laat zien hoelang je het hebt volgehouden.

Daarnaast kijk je terug op je eigen werk én kies je een uitbreiding om het spel leuker of moeilijker te maken.

Wat gaan we doen?

🔰 Toevoegingen aan bestaande code

score = 0  # bij de andere variabelen

def draw():
    screen.clear()
    if game_over:
        screen.draw.text("GAME OVER", center=(WIDTH // 2, HEIGHT // 2), fontsize=60, color="red")
        screen.draw.text(f"Score: {score}", center=(WIDTH // 2, HEIGHT // 2 + 50), fontsize=40, color="black")
        return
    ...
    screen.draw.text(f"Score: {score}", (10, 10), fontsize=40, color="black")

def update():
    global score
    if game_over:
        return
    ...
    score += 1

ℹ️ Uitleg

🧠 Reflectie

Beantwoord de volgende vragen onderaan je code als commentaar of in een apart document:

🎮 Uitbreiding (kies er één)

💡 Eigen idee?

Bedenk zelf een uitbreiding en probeer deze te maken. Schrijf kort op wat jouw idee is en hoe je het hebt aangepakt.

📤 Inleveren

🧠 Reflectieopdracht

Deze reflectieopdracht helpt je om stil te staan bij wat je hebt geleerd tijdens het programmeren van je spel.

Beantwoord de onderstaande vragen eerlijk en in je eigen woorden. Je mag je antwoorden inleveren via een apart document of onderaan je Python-bestand als commentaar zetten.

📋 Vragen

📤 Inleveren

Lever je reflectie in bij je docent via de afgesproken manier (document, upload of als commentaar in je code).

###

# Docenten

🎓 Docentenhandleiding 

📘 Overzicht

🎯 Leerdoelen

📚 Lesoverzicht

Les Onderwerp Nieuwe concepten
1 Speler en steen tekenen draw(), rechthoek tekenen, coördinaten
2 Speler beweegt update(), keyboard input, begrenzen
3 Steen valt en komt terug Beweging, random, logica
4 Botsing + Game Over Rect, colliderect(), boolean vlag
5 Meerdere stenen + moeilijkheid Lijsten, for-loops, moeilijkheidsschaal
6 Score, Reflectie & Uitbreiding Scorevariabele, draw.text(), vrije opdracht

⚠️ Valkuilen

🧠 Differentiatie

Voor snelle leerlingen

Voor langzamere leerlingen

📊 Beoordeling (optioneel)

Criterium Omschrijving Score (1-5)
Werkt het spel Geen fouten, spel werkt zoals bedoeld 🟩
Code is leesbaar Logische structuur, goede naamgeving 🟩
Uitbreiding toegevoegd Creatieve of technische aanvulling 🟩
Reflectie Antwoorden zijn volledig en met inzicht 🟩

💡 Tips voor in de les

🧰 Benodigdheden


Revision #12
Created 21 May 2025 20:39:46 by Max
Updated 5 June 2025 09:15:35 by Max