Sessies

Kies een reeks hieronder. De Python-sessies bouwen games met Pygame. De Git-sessies leren je versiebeheer: van je eerste commit tot pull requests.

13 juni 2026, 13:30

Subsecties van Sessies

Python sessies

Tien sessies waarin je elke maand een compleet Pygame-spel bouwt. Elke sessie bevat een worksheet, een cheatsheet en startcode om te downloaden.

  • Sessie 1: Catch the Stars: Een ster valt, jij vangt hem. Je schrijft je eerste draw()/update() loop en beweegt een sprite met pijltjestoetsen.
  • Sessie 2: Dodge Meteors: Meteoren spawnen en vallen. Je houdt ze bij in een lijst, verwijdert ze als ze van het scherm af zijn en trekt een leven af bij elke botsing.
  • Sessie 3: Space Blaster: Vijanden zakken naar beneden, jij schiet ze neer. Je maakt kogels aan met SPATIE en detecteert collision met een loop over een lijst.
  • Sessie 4: Pong: Twee paddles, één bal. Je leert pygame.Rect, laat de bal stuiteren door de snelheid om te keren en houdt de score bij voor twee spelers.
  • Sessie 5: Breakout: Stenen kapotschieten met een stuiterende bal. Je voegt geluidseffecten toe met pygame.mixer en bouwt een win- en verlies-scherm.
  • Sessie 6: Platformer: Springen en vallen op platforms. Je simuleert zwaartekracht met een vel_y variabele en detecteert platformbotsingen met pygame.Rect.
  • Sessie 7: Bug Zapper: Bugs kruipen, jij schiet ze neer. Je schrijft je eerste klasse met __init__ en maakt een subklasse via overerving.
  • Sessie 8: Sky Highway: Een vliegend schip op een scrollende weg. Je spawnt obstakels van rechts en verhoogt de snelheid naarmate de score stijgt.
  • Sessie 9: Boss Battle: Een baas met HP-balk en aanvalsfases. Je bouwt een state machine die het schiet- en bewegingsgedrag per fase aanpast.
  • Sessie 10: Mijn Spel: Geen vaste opdracht. Jij kiest het genre en combineert alles wat je in negen sessies hebt geleerd in je eigen spel.
13 juni 2026, 13:30

Subsecties van Python sessies

Sessie 1: Catch the Stars

In deze sessie bouw je een mini-spel: een ster valt naar beneden en jij vangt hem op met een basket. Aan het einde van de sessie beweegt alles, houdt het spel bij hoeveel sterren je vangt, en heb je je eerste eigen game.

Wat je vandaag leert

  • Variabelen gebruiken om objecten te positioneren
  • De draw() functie: wat je elke frame tekent
  • De update() functie: wat er elke frame verandert
  • Toetsenbord-input: bewegen met pijltjestoetsen

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py in Thonny.
  3. Klik op de groene Run-knop. Je ziet een donkerblauw venster met een basket onderaan en een ster bovenaan, maar niks beweegt nog.
  4. Problemen? Kijk bij Thonny instellen.

Stap 1: Laat de ster vallen

De update() functie draait 60 keer per seconde. Alles wat je daarin zet, wordt dus 60 keer per seconde uitgevoerd. Dat is hoe beweging werkt in een game.

Op dit moment staat er alleen pass in update(). Dat betekent “doe niks”. Verwijder pass en voeg dit toe:

def update():
    star.y = star.y + 3

Klik op Run. De ster valt nu van boven naar beneden. Als hij het scherm uit valt, verdwijnt hij. Dat lossen we zo op.

Wat gebeurt hier? star.y is de verticale positie van de ster. Hoe groter y, hoe lager op het scherm. Door elke frame + 3 toe te voegen, zakt de ster steeds een beetje.

Het coördinatenstelsel: (0, 0) zit linksboven, niet linksonder zoals in wiskunde. x loopt naar rechts, y loopt naar beneden. De ster begint op y = 30 (bijna helemaal boven), de basket staat op y = 370 (bijna helemaal onder).

Coördinatenstelsel Pygame Zero: oorsprong linksboven, y loopt naar beneden

Beweeg je muis over het scherm hieronder om de coördinaten te zien:

Beweeg je muis over het scherm om de coördinaten te zien.

Wil je meer weten over hoe het scherm werkt? → Coördinaten uitgelegd

Pas de schuifbalken aan en kijk hoe actor.x en actor.y veranderen als de actor beweegt:

Stap 2: ✅ Basic: laat de basket bewegen

Tijd om de basket te besturen. Pygame Zero heeft een handige keyboard-variabele die bijhoudt welke toetsen ingedrukt zijn.

Voeg dit toe aan update(), na de regel over de ster:

def update():
    star.y = star.y + 3

    if keyboard.left:
        basket.x = basket.x - 5
    if keyboard.right:
        basket.x = basket.x + 5

Klik op Run en gebruik de pijltjestoetsen. De basket beweegt nu mee!

Tip (optioneel, telt als Stretch): Als je de basket te ver naar links of rechts beweegt, verdwijnt hij van het scherm. Kun jij een check toevoegen die dat voorkomt? Hint: gebruik WIDTH en vergelijk met basket.x.

Stap 3: ⭐ Stretch: vang de ster

Nu wil je dat er iets gebeurt als de basket de ster raakt. Daarvoor gebruik je colliderect. Die controleert of twee rechthoeken elkaar overlappen.

Voeg dit toe aan update():

    if star.colliderect(basket):
        star.y = 0

De ster springt terug naar boven als je hem vangt. Maar wat als je hem mist? Voeg ook dit toe:

    if star.y > HEIGHT:
        star.y = 0

Bonus: Laat de ster elke keer op een willekeurige plek terug verschijnen. Voeg bovenaan het bestand toe:

import random

Vervang dan star.y = 0 (op beide plekken) door:

        star.x = random.randint(20, WIDTH - 20)
        star.y = 0

Nu valt de ster steeds op een andere plek. Veel moeilijker te vangen!

Stap 4: 🔥 Expert: voeg een score toe

Een echte game houdt bij wat je scoort. Daarvoor heb je een variabele nodig die buiten de functies leeft: een globale variabele.

Hoe een variabele werkt: een doosje met een naam en een waarde

Klik op de knop hieronder om te zien hoe score verandert elke keer dat je een ster vangt:

Voeg dit toe bovenaan, buiten alle functies (na de regels over basket en star):

score = 0

In draw(), voeg toe:

    screen.draw.text(f"Score: {score}", topleft=(10, 10), color="white")

In update(), pas de catch-code aan zodat de score omhoog gaat:

    if star.colliderect(basket):
        global score
        score = score + 1
        star.x = random.randint(20, WIDTH - 20)
        star.y = 0

global score vertelt Python: “ik bedoel de score van buiten deze functie, niet een nieuwe lokale variabele.” Zonder die regel krijg je een foutmelding.

Klik op Run. De score staat linksboven en telt op elke keer dat je een ster vangt!

Showcase

Laat je spel zien aan een coach en een buddy. Vertel wat je gemaakt hebt: wat werkt, en wat je nog extra hebt toegevoegd.

Tot de volgende keer!

“Volgende keer: dingen die TERUGSLAAN. En ze gaan BOEM, met echt geluid.”

Neem mee naar huis

Probeer thuis één van deze uitbreidingen. Bij elke staat een code-hint om je op weg te helpen.

  1. Beperk levens — Voeg levens = 3 toe. Bij een misser (star.y > HEIGHT): levens -= 1. Stop het spel als levens == 0 met game_over = True en toon “Game Over” in draw().

  2. Willekeurige ster-kleur — Bij elke vangst: geef de ster een nieuwe kleur met random.randint(50, 255) voor rood, groen en blauw. Begin bij 50, niet bij 0 — anders is de ster soms zwart en onzichtbaar.

  3. Achtergrond — Teken vaste sterren op de achtergrond in draw() voor de score. Gebruik screen.draw.filled_circle(x, y, 2, "white") op 20 willekeurige posities. Zaai random.seed(42) zodat ze niet flikkeren.

  4. Tweede ster — Maak sterren = [star, Actor("star")]. Geef elke ster een eigen x. Werk ze allebei bij in update() en teken ze in draw().

  5. Hoge score — Houd high_score bij. Als score > high_score: high_score = score. Toon f"Beste: {high_score}" naast de score.

  6. Basket kleiner — Na elke 5 punten: basket.width = max(30, basket.width - 5). Zet basket.width terug bij herstart.

  7. Bom — Voeg een rode cirkel toe die af en toe valt. Gebruik een timer bom_timer en random.randint om te bepalen wanneer hij verschijnt. Als de basket de bom raakt: score -= 2.

  8. Moeilijkheidsgraad — Na elke 5 sterren: verhoog de valsnelheid met 1. Bouw een maximum in: max(3, star_snelheid).

Vastgelopen? Vraag het volgende dojo aan een coach, of probeer gewoon iets anders. Programmeren is doen.

Bekijk de cheatsheet voor deze sessie

20 juni 2026, 10:54

Sessie 2: Dodge Meteors

Je ruimteschip zweeft in de donkere ruimte terwijl meteoren van boven naar beneden komen. Ontwijk ze, of verlies een leven. Hoe langer je overleeft, hoe sneller ze gaan. En deze keer bouw je ook Dojo Defender: het grotere project dat elke sessie groeit.

Wat je vandaag leert

  • Lijsten gebruiken om meerdere objecten bij te houden
  • Objecten spawnen (aanmaken) en verwijderen
  • Levens bijhouden en een game-over scherm tonen
  • Dojo Defender: je eigen ruimteschip toevoegen aan het grotere project

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py.
  3. Klik op Run. Je ziet je ruimteschip onderaan, maar er vallen nog geen meteoren.
  4. Problemen? Kijk bij Thonny instellen.

Stap 1: Laat meteoren spawnen

Vul de functie spawn_meteor() in. Een meteoor is een Actor die bovenaan het scherm begint op een willekeurige x-positie:

import random

def spawn_meteor():
    rock = Actor('meteor')
    rock.x = random.randint(30, WIDTH - 30)
    rock.y = 0
    meteors.append(rock)

Roep de functie aan in update(), maar niet élke frame, anders wordt het scherm meteen volgestort. De update() functie draait 60 keer per seconde. Gebruik dat om een teller bij te houden:

Zie hieronder hoe snel een meteoor beweegt bij verschillende snelheden en hoeveel pixels dat per seconde is:

Gebruik een teller:

# bovenaan, buiten de functies:
timer = 0

def update():
    global timer
    timer += 1
    if timer % 60 == 0:   # elke seconde (60 frames)
        spawn_meteor()

Klik op Run. Na een seconde verschijnt de eerste meteoor, maar hij beweegt nog niet.

Stap 2: ✅ Basic: meteoren laten vallen en verdwijnen

Laat alle meteoren in de lijst zakken, en verwijder ze als ze het scherm uit vallen:

def update():
    global timer
    timer += 1
    if timer % 60 == 0:
        spawn_meteor()

    for rock in meteors[:]:      # [:] = kopie zodat je veilig kunt verwijderen
        rock.y += 4
        if rock.y > HEIGHT + 30:
            meteors.remove(rock)

Collision detecteren: Als een meteoor het schip raakt, verlies je een leven. Voeg dit toe in de loop:

        if rock.colliderect(ship):
            meteors.remove(rock)
            global lives
            lives -= 1
            if lives <= 0:
                # TODO: game over (stap 3)
                pass

Stap 3: ⭐ Stretch: game over en snelheid opvoeren

Game over: Voeg een variabele game_over = False toe bovenaan. Als lives == 0, zet game_over = True. In draw(), toon een tekst als game_over True is:

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

Stop het bewegen in update() als game_over True is:

def update():
    if game_over:
        return
    ...

Snelheid verhogen: Laat meteoren sneller gaan naarmate de score stijgt:

snelheid = 3 + score // 5   # elke 5 punten +1 snelheid
rock.y += snelheid

Stap 4: 🔥 Expert: score en meerdere meteoorgroottes

Score: Elke seconde dat je overleeft, +1 punt. Voeg global score toe en verhoog in update():

    if timer % 60 == 0:
        global score
        score += 1
        spawn_meteor()

Meerdere groottes: Maak kleine, middel en grote meteoren. Gebruik een schaal-variabele en pas de hitbox aan:

def spawn_meteor():
    rock = Actor('meteor')
    rock.x = random.randint(30, WIDTH - 30)
    rock.y = 0
    rock.schaal = random.choice([0.5, 1.0, 1.5])
    meteors.append(rock)

Kleinere meteoren bewegen sneller; grotere zijn moeilijker te ontwijken maar geven meer punten.

Dojo Defender

Download de Dojo Defender starter voor vandaag. Dit is de basis van het project dat elke sessie groeit. Voeg vandaag je ruimteschip toe en laat het bewegen met de pijltjestoetsen.

Was je er vorige keer niet bij? Geen probleem — download de oplossing van vorige keer en je kan meteen mee.

Het volledige Dojo Defender werkblad vind je op de Dojo Defender pagina.

Showcase

Laat je spel zien aan een coach en een buddy. Hoe lang overleef jij? Wie haalt de hoogste score?

Tot de volgende keer!

“Volgende keer: je eigen ruimteschip SCHIET TERUG. Vijanden in formatie, en jij blast ze weg.”

Neem mee naar huis

  1. Makkelijk: verander de achtergrondkleur naar dieppaars of donkergroen.
  2. Middel: voeg een geluid toe als een meteoor het schip raakt (sounds/hit.wav).
  3. Lastig: maak meteoren sneller naarmate er meer op het scherm zijn (niet alleen de score).
  4. Erg lastig: voeg power-ups toe: een gouden ster die je een extra leven geeft als je hem aanraakt.

Bekijk de cheatsheet voor deze sessie

1 juli 2026, 22:43

Sessie 3: Space Blaster

Vijanden staan in formatie bovenaan het scherm. Jij staat onderaan met een ruimteschip en één doel: ze allemaal uitschakelen voordat ze de bodem bereiken. Druk op SPATIE om te schieten, en mis niet.

Wat je vandaag leert

  • Kogels bijhouden in een lijst
  • Een kogel aanmaken als je op SPATIE drukt
  • Collision tussen kogels en vijanden
  • Game over als een vijand de bodem raakt

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py.
  3. Klik op Run. Je ziet het schip onderaan en 12 vijanden in een raster, maar niks beweegt en je kunt nog niet schieten.

Stap 1: Laat het schip bewegen

Het schip beweegt al met de pijltjestoetsen. Controleer de code in update(). Zorg dat het schip niet buiten het scherm gaat:

if keyboard.left and ship.x > 30:
    ship.x -= 5
if keyboard.right and ship.x < WIDTH - 30:
    ship.x += 5

Stap 2: ✅ Basic: schieten met SPATIE

Vul de functie shoot() in. Een kogel is een Actor die begint op de positie van het schip:

def shoot():
    kogel = Actor('bullet')
    kogel.x = ship.x
    kogel.y = ship.y - 20
    bullets.append(kogel)

Roep shoot() aan als de spatiebalk wordt ingedrukt. Gebruik on_key_down (Pgzero-stijl):

def on_key_down(key):
    if key == keys.SPACE:
        shoot()

Laat de kogels omhoog bewegen in update() en verwijder ze als ze het scherm uit gaan:

for kogel in bullets[:]:
    kogel.y -= 8
    if kogel.y < -10:
        bullets.remove(kogel)

Stap 3: ⭐ Stretch: vijanden raken

colliderect controleert of de rechthoekige hitbox van twee actors overlapt. Beweeg je muis over het scherm hieronder om te zien wanneer dat gebeurt:

Controleer in update() of een kogel een vijand raakt:

for kogel in bullets[:]:
    kogel.y -= 8
    if kogel.y < -10:
        bullets.remove(kogel)
        continue
    for vijand in enemies[:]:
        if kogel.colliderect(vijand):
            bullets.remove(kogel)
            enemies.remove(vijand)
            global score
            score += 10
            break

Win-conditie: Als enemies leeg is, heb je gewonnen:

    if not enemies:
        screen.draw.text("JE WINT!", center=(WIDTH/2, HEIGHT/2), color="yellow", fontsize=60)

Stap 4: 🔥 Expert: vijanden bewegen en game over

Laat de vijanden langzaam naar beneden komen. Gebruik een timer:

vijand_timer = 0

def update():
    global vijand_timer
    vijand_timer += 1
    if vijand_timer % 90 == 0:   # elke 1,5 seconde
        for vijand in enemies:
            vijand.y += 20

Game over als een vijand de bodem bereikt:

        for vijand in enemies:
            if vijand.y > HEIGHT - 30:
                global game_over
                game_over = True

Snellere schietfrequentie: Bouw een cooldown in zodat de ninja niet oneindig snel kan schieten:

shoot_cooldown = 0

def update():
    global shoot_cooldown
    if shoot_cooldown > 0:
        shoot_cooldown -= 1

def on_key_down(key):
    global shoot_cooldown
    if key == keys.SPACE and shoot_cooldown == 0:
        shoot()
        shoot_cooldown = 15

Showcase

Laat je spel zien aan een coach. Hoe snel maak jij alle vijanden weg? Vergelijk scores met een buddy.

Tot de volgende keer!

“Volgende keer: twee spelers, één bal: PONG. En je leert echte pygame zonder pgzrun.”

Neem mee naar huis

  1. Makkelijk: verander de kleur van de kogels of de vijanden.
  2. Middel: laat vijanden links en rechts bewegen (één richting per stap, keer om aan de rand).
  3. Lastig: voeg een second wave toe: als alle vijanden weg zijn, spawn een nieuwe rij die sneller daalt.
  4. Erg lastig: laat vijanden ook terugschieten: willekeurig een kogel omlaag sturen elke N frames.

Bekijk de cheatsheet voor deze sessie

Dojo Defender

Download de Dojo Defender starter voor vandaag.

Was je er vorige keer niet bij? Download de oplossing van sessie 1 en begin daarmee.

Het volledige werkblad: Dojo Defender Sessie 2.

1 juli 2026, 22:43

Sessie 4: Pong

Twee paddles, één bal: het klassieke Pong-spel. Maar er is een verrassing: deze sessie schrijf je het spel in echte pygame, zonder pgzrun. Je leert de game loop zelf Installeren. Dat is hoe de meeste echte games werken.

Wat je vandaag leert

  • De pygame game loop: events, update, draw
  • pygame.Rect voor rechthoeken en botsingen
  • Bal laten stuiteren (snelheid omkeren)
  • Score bijhouden voor twee spelers

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py.
  3. Klik op Run. Je ziet twee paddles en een gele bal in het midden, maar de bal beweegt nog niet.

Verschil met pgzrun: Er zijn geen draw() en update() functies meer. Alles zit in één while running: loop.

Stap 1: Laat de bal bewegen

Zoek de regels:

# bal.x += ball_dx  # zet dit aan als je klaar bent
# ball.y += ball_dy

Verwijder de # voor beide regels. Maar stel eerst een startsnelheid in. Zoek ball_dx, ball_dy = 0, 0 en verander naar:

ball_dx, ball_dy = 4, 4

Klik op Run. De bal beweegt nu, maar verdwijnt door de rand. Dat lossen we op in stap 2.

Stap 2: ✅ Basic: bal stuitert op muren en paddles

Voeg na ball.x += ball_dx en ball.y += ball_dy het volgende toe:

# Stuiteren op boven- en onderrand
if ball.top <= 0 or ball.bottom >= HEIGHT:
    ball_dy = -ball_dy

# Stuiteren op paddles
if ball.colliderect(left_paddle) or ball.colliderect(right_paddle):
    ball_dx = -ball_dx

De bal stuitert nu oneindig. Voeg ook grenzen toe voor de paddles zodat ze niet buiten het scherm gaan. Kijk naar de code die al in de starter staat.

Stap 3: ⭐ Stretch: score bijhouden

Als de bal links het scherm uitvalt, scoort de rechter speler. Als hij rechts uitvalt, scoort de linker:

# Bal uit links → rechts scoort
if ball.left <= 0:
    score_right += 1
    ball.center = (WIDTH // 2, HEIGHT // 2)
    ball_dx = 4

# Bal uit rechts → links scoort
if ball.right >= WIDTH:
    score_left += 1
    ball.center = (WIDTH // 2, HEIGHT // 2)
    ball_dx = -4

De score staat al in draw(). Controleer dat de variabelen kloppen.

Stap 4: 🔥 Expert: win-conditie en snelheid verhogen

Win bij 5 punten: Voeg een variabele won toe. Als een speler 5 bereikt, stop dan het spel:

if score_left >= 5:
    won = "Links wint!"
if score_right >= 5:
    won = "Rechts wint!"

Toon de winnaar op het scherm en stop de beweging.

Snelheid verhogen: Na elke rally wordt de bal een beetje sneller:

if ball.colliderect(left_paddle) or ball.colliderect(right_paddle):
    ball_dx = -ball_dx * 1.05   # 5% sneller
    ball_dy = ball_dy * 1.05

Bouw een maximum in: ball_dx = max(-12, min(12, ball_dx)).

Showcase

Speel een potje tegen een buddy. Eerste naar 5 punten wint. Laat het zien aan een coach.

Tot de volgende keer!

“Volgende keer: Breakout: de bal beukt stenen kapot. En er is GELUID.”

Neem mee naar huis

  1. Makkelijk: verander de kleur van de bal of de paddles.
  2. Middel: maak één paddle groter naarmate die speler verliest (handicap).
  3. Lastig: voeg een AI-tegenstander toe: de rechter paddle volgt automatisch de bal.
  4. Erg lastig: voeg power-ups toe: een item dat de bal verdubbelt of de paddle groter maakt.

Dojo Defender

Vandaag verhuist Dojo Defender naar echte Pygame! Download de starter. Was je er niet bij? Download de oplossing van sessie 2. Werkblad: Dojo Defender Sessie 3.


Bekijk de cheatsheet voor deze sessie

1 juli 2026, 22:43

Sessie 5: Breakout

Een bal kaatst heen en weer en beukt rijen gekleurde stenen kapot. Jij bestuurt de paddle om de bal in de lucht te houden. En deze keer hoor je het ook: er zijn geluidseffecten bij elke botsing.

Wat je vandaag leert

  • Geluid laden en afspelen met pygame.mixer
  • Botsingen met meerdere objecten (lijst van stenen)
  • De bal laten stuiteren in de juiste richting
  • Win- en verlies-scherm bouwen

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py.
  3. Klik op Run. Je ziet de paddle, de bal en de stenen. De bal beweegt al horizontaal maar niet verticaal. Dat ga jij aanpassen.

Stap 1: Laat de bal verticaal bewegen

Zoek deze regel in de starter:

ball_dx, ball_dy = 4, 0
# ball_dy = -4  ← verwijder de # om de bal te laten bewegen!

Verwijder de # voor ball_dy = -4. Nu heeft de bal een verticale snelheid. Voeg beweging toe in de game loop (zoek de update-sectie):

ball.x += ball_dx
ball.y += ball_dy

Klik op Run. De bal beweegt diagonaal maar verdwijnt door de randen.

Stap 2: ✅ Basic: bal stuitert op muren en paddle

Voeg stuiteren toe:

# Boven-, links- en rechtsrand
if ball.left <= 0 or ball.right >= WIDTH:
    ball_dx = -ball_dx
if ball.top <= 0:
    ball_dy = -ball_dy

# Paddle
if ball.colliderect(paddle):
    ball_dy = -ball_dy
    if snd_hit:
        snd_hit.play()

Levens: Als de bal de onderkant bereikt, verlies je een leven:

if ball.top > HEIGHT:
    levens -= 1
    # Reset bal bovenop de paddle
    ball.center = (paddle.centerx, paddle.top - BALL_SIZE)
    ball_dy = -4

Stap 3: ⭐ Stretch: stenen breken

Controleer collision met elke steen in de loop:

for steen in stenen[:]:
    if ball.colliderect(steen['rect']):
        stenen.remove(steen)
        ball_dy = -ball_dy
        score += 10
        if snd_hit:
            snd_hit.play()
        break  # slechts één steen per frame breken

Win-conditie: Als alle stenen weg zijn, heeft de ninja gewonnen. Toon een bericht:

if not stenen:
    # toon win-scherm

Stap 4: 🔥 Expert: levens, explosiegeluid en snelheid

Explosiegeluid als een steen breekt (gebruik snd_explode uit de starter):

if snd_explode:
    snd_explode.play()

Game over bij 0 levens: toon een scherm en stop de bal.

Snelheid verhogen naarmate er minder stenen overblijven:

snelheid_factor = 1 + (1 - len(stenen) / totaal_stenen) * 0.5
ball_dx_huidig = ball_dx * snelheid_factor

Nieuwe rij stenen als alles weg is: roep stenen = maak_stenen() opnieuw aan en verhoog de moeilijkheidsgraad.

Showcase

Wie haalt de meeste stenen weg? Vergelijk scores en laat je coach de hoogste streak zien.

Tot de volgende keer!

“Volgende keer: zwaartekracht. Jouw karakter valt, en jij moet hem laten springen op platforms.”

Neem mee naar huis

  1. Makkelijk: verander de kleuren van de stenen naar jouw favoriete kleuren.
  2. Middel: maak sommige stenen twee keer zo sterk (ze moeten tweemaal geraakt worden).
  3. Lastig: voeg een power-up toe die de paddle tijdelijk breder maakt.
  4. Erg lastig: voeg een tweede bal toe die spawnt als score > 50.

Bekijk de cheatsheet voor deze sessie

Dojo Defender

Dojo Defender krijgt een menu en nieuwe vijandtypes! Download de starter. Was je er niet bij? Download de oplossing van sessie 3. Werkblad: Dojo Defender Sessie 4.

1 juli 2026, 22:43

Sessie 6: Platformer

In deze sessie bouw je een micro-platformer. Je speler heeft zwaartekracht, kan springen, en verzamelt sterren op platforms. Je gebruikt voor het eerst pygame direct, zonder pgzrun, en voegt geluidseffecten toe met pygame.mixer.

Wat je vandaag leert

  • Zwaartekracht simuleren met een vel_y variabele
  • Springen door vel_y negatief te maken
  • Platformbotsingen detecteren met pygame.Rect
  • Items verzamelen (collision met sterren)
  • Geluiden afspelen met pygame.mixer

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py in Thonny.
  3. Klik op de groene Run-knop. Je ziet een venster met een speler, platforms en sterren, maar de speler valt nog niet.
  4. Problemen? Vraag een coach.

Stap 1: Zwaartekracht

In een platformer valt de speler continu naar beneden, tenzij hij op een platform staat. We simuleren dat met vel_y: een verticale snelheid die elke frame groter wordt door zwaartekracht.

Zoek de # STAP 1 comment in main.py en vervang de pass door:

# Zwaartekracht toepassen
vel_y += GRAVITY
player_rect.y += vel_y

# Controleer of speler op een platform staat
on_ground = False
for platform in platforms:
    if (player_rect.colliderect(platform) and vel_y > 0):
        player_rect.bottom = platform.top
        vel_y = 0
        on_ground = True

GRAVITY = 0.5 staat al bovenaan het bestand. Klik Run. De speler valt nu naar het dichtstbijzijnde platform en blijft daar staan.

Wat gebeurt hier? Elke frame wordt vel_y iets groter (de speler versnelt naar beneden). Als de speler een platform raakt terwijl hij naar beneden valt (vel_y > 0), zet je zijn onderkant (bottom) precies op de bovenkant van het platform en stop je de val (vel_y = 0).

Stap 2: ✅ Basic: springen

Een platformer zonder springen is maar half af. Druk op SPATIE om te springen: dat is niets anders dan vel_y plotseling negatief maken.

Zoek de # STAP 2 comment en voeg toe:

keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
    player_rect.x -= SPEED
if keys[pygame.K_RIGHT]:
    player_rect.x += SPEED

# Springen — alleen als je op de grond staat
if keys[pygame.K_SPACE] and on_ground:
    vel_y = -12

Klik Run en test:

  • Pijltjestoetsen: beweeg links/rechts
  • SPATIE: spring omhoog

Tip: Als de speling te hoog of te laag voelt, verander dan -12 in -10 (lager springen) of -15 (hoger springen).

Stap 3: ⭐ Stretch: sterren verzamelen

Laten we iets te verzamelen toevoegen. De starter heeft al een lijst stars met pygame.Rect-objecten. Jij schrijft de botsingsdetectie.

Zoek de # STAP 3 comment:

for star in stars[:]:  # [:] zodat je veilig kunt verwijderen tijdens het loopen
    if player_rect.colliderect(star):
        stars.remove(star)
        score += 1

En in de tekenfunctie (zoek # TEKEN STERREN):

for star in stars:
    pygame.draw.polygon(screen, YELLOW, star_points(star.centerx, star.centery, 12, 5))

star_points() is al gedefinieerd in de starter. Die berekent de punten van een 5-puntige ster.

Bovenaan het spel staat score = 0. Teken de score op het scherm (zoek # TEKEN SCORE):

score_surf = font.render(f"Sterren: {score}", True, WHITE)
screen.blit(score_surf, (10, 10))

Stap 4: 🔥 Expert: geluid en win-scherm

Nu voeg je een springgeluid toe en een win-scherm als alle sterren verzameld zijn.

Geluid laden (dit staat al klaar in de starter; controleer dat jump.wav in de sounds/ map zit):

pygame.mixer.init()
jump_snd = pygame.mixer.Sound("sounds/jump.wav")

Geluid afspelen bij springen: voeg toe aan de sprong-code:

if keys[pygame.K_SPACE] and on_ground:
    vel_y = -12
    jump_snd.play()

Win-scherm: voeg toe na de ster-loop:

if len(stars) == 0:
    win_surf = font.render("Gewonnen! Alle sterren verzameld!", True, YELLOW)
    screen.blit(win_surf, (WIDTH // 2 - win_surf.get_width() // 2, HEIGHT // 2))
    pygame.display.flip()
    pygame.time.wait(3000)
    running = False

Showcase

Laat je spel zien aan een coach en een buddy. Kun je alle sterren verzamelen voor de tijd om is?

Dojo Defender

De Dojo Defender snapshot van vandaag bouwt verder op sessie 5:

  • Parallax sterrenachtergrond — drie lagen sterren met eigen snelheid
  • Particle effects — uitlaatgassen, explosiepuin, vonkjes
  • Vernietigbare asteroïden — big → med → small → weg

Download de Dojo Defender starter of oplossing.

Tot de volgende keer!

“Volgende keer: klik op bugs en ZAP ze weg, met je eigen klassen.”

Neem mee naar huis

Probeer thuis één van deze uitbreidingen:

  1. Makkelijk: verander de kleur van de speler als hij in de lucht is.
  2. Middel: voeg een timer toe. De speler heeft 30 seconden om alle sterren te verzamelen.
  3. Lastig: voeg een vijand toe die heen en weer loopt op een platform; als de speler hem raakt, herstart het spel.
  4. Erg lastig: laat de speler dubbel springen (twee keer SPATIE voor een tweede sprong in de lucht).

Vastgelopen? Vraag het volgende dojo aan een coach, of probeer gewoon iets anders. Programmeren is doen.

Bekijk de cheatsheet voor deze sessie

1 juli 2026, 22:43

Sessie 7: Bug Zapper

Bugs vallen van boven naar beneden. Jij schiet omhoog om ze te raken. In deze sessie leer je OOP: je schrijft je eerste eigen klasse (Bug), en daarna twee subklassen: een die slingert en een die op je duikt. Klassen zijn de bouwstenen van bijna alle grote programma’s.

Wat je vandaag leert

  • Een klasse schrijven met __init__ en eigen methoden
  • Overerving: een subklasse die een bestaande klasse uitbreidt
  • Bullets (kogels) bijhouden in een lijst
  • Botsingsdetectie tussen kogels en bugs

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py in Thonny.
  3. Klik op Run. Je ziet een scherm met een speler onderaan, maar nog geen bugs en geen kogels.
  4. Problemen? Vraag een coach.

Stap 1: Bugs spawnen en schieten

De Bug-klasse

Zoek de # STAP 1 — BUG KLASSE comment en schrijf:

class Bug:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.alive = True

    def update(self):
        self.y += 2  # valt naar beneden

    def draw(self, screen):
        pygame.draw.circle(screen, GREEN, (int(self.x), int(self.y)), 15)
        # Ogen
        pygame.draw.circle(screen, BLACK, (int(self.x) - 5, int(self.y) - 4), 3)
        pygame.draw.circle(screen, BLACK, (int(self.x) + 5, int(self.y) - 4), 3)

Bugs laten spawnen: de starter heeft al een timer. Zoek # SPAWN BUG:

bugs.append(Bug(random.randint(30, WIDTH - 30), -20))

Schieten: zoek # SCHIET (dit staat in de event-loop bij K_SPACE):

bullets.append(pygame.Rect(player_x - 3, player_y - 20, 6, 12))

Update bullets elke frame (zoek # UPDATE BULLETS):

for b in bullets[:]:
    b.y -= 10
    if b.y < 0:
        bullets.remove(b)
pygame.draw.rect(screen, YELLOW, b)  # dit staat al klaar

Stap 2: ✅ Basic: bugs raken

Nu schrijf je de botsingsdetectie: als een kogel een bug raakt, sterft de bug.

Zoek # STAP 2 — BOTSING:

for bug in bugs[:]:
    bug.update()
    bug.draw(screen)
    if bug.y > HEIGHT + 20:
        bugs.remove(bug)
        continue
    bug_rect = pygame.Rect(bug.x - 15, bug.y - 15, 30, 30)
    for bullet in bullets[:]:
        if bullet.colliderect(bug_rect):
            bug.alive = False
            bullets.remove(bullet)
            score += 1
            break
    if not bug.alive:
        bugs.remove(bug)

Klik Run. Schiet op de bugs: ze verdwijnen bij een treffer!

Stap 3: ⭐ Stretch: SlingerBug

Nu maak je een subklasse: een Bug die heen en weer slingert.

import math

class SlingerBug(Bug):
    def __init__(self, x, y):
        super().__init__(x, y)
        self.start_x = x
        self.timer = 0

    def update(self):
        self.timer += 0.05
        self.x = self.start_x + math.sin(self.timer) * 60
        self.y += 1.5  # iets langzamer, maar moeilijker te raken

    def draw(self, screen):
        super().draw(screen)
        # Oranje cirkel eromheen als visuele aanwijzing
        pygame.draw.circle(screen, ORANGE, (int(self.x), int(self.y)), 18, 2)

Spawnen van SlingerBugs: voeg toe aan de spawn-code (bijv. elke 3e bug):

if random.random() < 0.3:
    bugs.append(SlingerBug(random.randint(30, WIDTH - 30), -20))
else:
    bugs.append(Bug(random.randint(30, WIDTH - 30), -20))

super().__init__(x, y) roept de __init__ van de ouderklas (Bug) aan, dus je hoeft self.x, self.y en self.alive niet opnieuw te schrijven.

Stap 4: 🔥 Expert: DuikBug

De DuikBug detecteert de positie van de speler en duikt er recht op af.

class DuikBug(Bug):
    def __init__(self, x, y, player_x_ref):
        super().__init__(x, y)
        self.player_x_ref = player_x_ref  # functie die huidige speler-x geeft
        self.speed_x = 0
        self.speed_y = 1

    def update(self):
        target_x = self.player_x_ref()
        dx = target_x - self.x
        dist = max(abs(dx), 1)
        self.x += dx / dist * 2
        self.y += 2.5

    def draw(self, screen):
        super().draw(screen)
        pygame.draw.circle(screen, RED, (int(self.x), int(self.y)), 18, 2)

Spawnen: gebruik een lambda om de speler-x door te geven:

bugs.append(DuikBug(random.randint(30, WIDTH - 30), -20, lambda: player_x))

Bonus: Teken een HP-balk. Start met lives = 3 en trek er één af als een bug de onderkant haalt.

Showcase

Laat je spel zien aan een coach en een buddy. Hoeveel bugs kun je neerzappen voor je levens op zijn?

Tot de volgende keer!

“Volgende keer: een oneindige weg in de lucht, en alles SCROLT voorbij.”

Neem mee naar huis

Probeer thuis één van deze uitbreidingen:

  1. Makkelijk: maak bugs groter of sneller naarmate de score oploopt.
  2. Middel: voeg een lives-systeem toe met 3 levens, en als een bug de onderkant haalt, verlies je er één.
  3. Lastig: schrijf een PantserbBug die 3 treffers nodig heeft voor hij sterft (gebruik een hp-attribuut).
  4. Erg lastig: voeg muisbesturing toe: de speler beweegt naar de muispositie en schiet automatisch elke 0,5 seconde.

Vastgelopen? Vraag het volgende dojo aan een coach, of probeer gewoon iets anders. Programmeren is doen.

Dojo Defender: Eindbaas

Deze sessie bouw je ook verder aan Dojo Defender. Je voegt een eindbaas (boss) toe die om de 5 waves verschijnt met 3 fases.

Bekijk de Dojo Defender sessie 6 voor de instructies.

De starter en oplossing staan klaar.


Bekijk de cheatsheet voor deze sessie

1 juli 2026, 22:43

Sessie 8: Sky Highway

Je schip vliegt door een eindeloze luchtweg. De achtergrond scrolt langs je heen, rode obstakels komen van rechts, en sterren geven punten. Hoe langer je overleeft, hoe sneller het wordt!

Wat je vandaag leert

  • Een scrollende achtergrond maken met een scroll_x variabele
  • Objecten spawnen die van rechts naar links bewegen
  • Botsingsdetectie met levens
  • Moeilijkheidsscaling: snelheid verhogen naarmate de score stijgt

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py in Thonny.
  3. Klik op Run. Je ziet een statisch scherm met een schip en een luchtachtergrond, maar niks beweegt nog.
  4. Problemen? Vraag een coach.

Stap 1: Achtergrond laten scrollen

Een scrollende achtergrond geeft de illusie van beweging. We tekenen de achtergrond twee keer naast elkaar en schuiven de positie elke frame op.

Zoek # STAP 1 en voeg toe:

# Beweeg achtergrond naar links
scroll_x -= speed
if scroll_x <= -WIDTH:
    scroll_x = 0

# Teken achtergrond twee keer
screen.blit(bg_image, (int(scroll_x), 0))
screen.blit(bg_image, (int(scroll_x) + WIDTH, 0))

scroll_x begint op 0 en wordt elke frame kleiner. Als het -WIDTH bereikt, springen we terug naar 0: een naadloze loop.

Klik Run. De lucht scrolt nu voorbij je schip!

Stap 2: ✅ Basic: obstakels en levens

Obstakels komen van rechts en bewegen naar links. Als je ze raakt, verlies je een leven.

Obstakels updaten (zoek # STAP 2):

for obs in obstacles[:]:
    obs.x -= speed
    if obs.x < -obs.width:
        obstacles.remove(obs)
    pygame.draw.rect(screen, RED, obs)
    # Botsing
    if ship_rect.colliderect(obs):
        obstacles.remove(obs)
        lives -= 1
        if lives <= 0:
            running = False

Levens tekenen:

for i in range(lives):
    pygame.draw.rect(screen, RED, (10 + i * 25, 10, 18, 18))

Obstakels spawnen (in de spawn-timer-event):

h = random.randint(40, 120)
obstacles.append(pygame.Rect(WIDTH, random.randint(50, HEIGHT - h - 50), 30, h))

Stap 3: ⭐ Stretch: sterren verzamelen

Sterren geven punten en verdwijnen als je ze raakt.

Zoek # STAP 3:

for star in stars[:]:
    star.x -= speed
    if star.x < -20:
        stars.remove(star)
        continue
    pygame.draw.circle(screen, YELLOW, star.center, 10)
    if ship_rect.colliderect(star):
        stars.remove(star)
        score += 1

# Score tekenen:
score_surf = font.render(f"Score: {score}", True, WHITE)
screen.blit(score_surf, (WIDTH - 120, 10))

Spawnen van sterren (in dezelfde spawn-timer, maar minder vaak):

if random.random() < 0.4:
    stars.append(pygame.Rect(WIDTH, random.randint(40, HEIGHT - 40), 20, 20))

Stap 4: 🔥 Expert: spawnen en snelheid schalen

Nu maak je de game steeds moeilijker naarmate de score stijgt.

Snelheid schalen (zoek # STAP 4):

speed = BASE_SPEED + score * 0.1

BASE_SPEED = 4 staat al bovenaan. Bij score 20 gaat alles dubbel zo snel!

Spawn-interval aanpassen: hoe hoger de score, hoe vaker nieuwe obstakels komen:

spawn_interval = max(500, 1800 - score * 30)  # min. 500ms
pygame.time.set_timer(SPAWN_EVENT, spawn_interval)

Game over scherm:

if not running:
    go_surf = font.render("GAME OVER", True, RED)
    screen.blit(go_surf, (WIDTH // 2 - go_surf.get_width() // 2, HEIGHT // 2 - 30))
    sc_surf = font.render(f"Score: {score}", True, WHITE)
    screen.blit(sc_surf, (WIDTH // 2 - sc_surf.get_width() // 2, HEIGHT // 2 + 10))
    pygame.display.flip()
    pygame.time.wait(3000)

Showcase

Laat je spel zien aan een coach en een buddy. Wie haalt de hoogste score?

Tot de volgende keer!

“Volgende keer: een baas die terugvecht, in DRIE fases.”

Neem mee naar huis

Probeer thuis één van deze uitbreidingen:

  1. Makkelijk: voeg een tweede soort obstakel toe (bijv. een blauw obstakel dat hoger of lager vliegt).
  2. Middel: voeg power-ups toe. Vang een groene capsule voor een tijdelijk schild (het schip kan 1 keer geraakt worden).
  3. Lastig: laat het schip omhoog en omlaag bewegen met de pijltjestoetsen én begrens het scherm zodat het schip er niet uit vliegt.
  4. Erg lastig: voeg parallax-scrolling toe: een tweede laag achtergrond (wolken) die langzamer scrolt dan de eerste laag.

Vastgelopen? Vraag het volgende dojo aan een coach, of probeer gewoon iets anders. Programmeren is doen.


Dojo Defender: Jouw eigen versie

Vandaag werk je ook verder aan Dojo Defender — maar niet met stap-voor-stap instructies. Jij kiest wat je bouwt.

Download de Dojo Defender starter — dit is de complete game met alles erop en eraan (schip, vijanden, asteroïden, waves, boss). Kies een feature uit de lijst, plan hem kort met een coach, en ga aan de slag.

👉 Alles over Dojo Defender vind je op de Dojo Defender pagina.


Bekijk de cheatsheet voor deze sessie

1 juli 2026, 22:43

Sessie 9: Boss Battle

De eindbaas wacht op je. Hij beweegt heen en weer, schiet kogels en wordt steeds gevaarlijker naarmate zijn HP daalt. Jij schiet terug, houdt zijn HP bij op een balk, en overleeft drie fasen. Dit is de moeilijkste sessie, en de meest bevredigende als je hem haalt.

Wat je vandaag leert

  • Een HP-balk tekenen op het scherm
  • Een state machine: de baas gedraagt zich anders per fase
  • De baas laten schieten met een kogeltimer
  • Fasen activeren op HP-drempelwaarden

Stap 0: Installeren

  1. Open Thonny.
  2. Download de starter via deze link, pak de ZIP uit en open main.py in Thonny.
  3. Klik op Run. Je ziet de baas bovenaan, jouw schip onderaan. Geen movement, geen kogels nog.
  4. Problemen? Vraag een coach.

Stap 1: Baas laten bewegen

De baas beweegt heen en weer over het scherm. Als hij de rand raakt, keert hij om.

Zoek # STAP 1 en voeg toe:

boss_rect.x += boss_speed

# Omdraaien bij de rand
if boss_rect.right >= WIDTH or boss_rect.left <= 0:
    boss_speed = -boss_speed

boss_speed = 3 staat al bovenaan. Klik Run: de baas dendert van links naar rechts!

Speler bewegen en schieten (zoek # SPELER):

keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_rect.left > 0:
    player_rect.x -= PLAYER_SPEED
if keys[pygame.K_RIGHT] and player_rect.right < WIDTH:
    player_rect.x += PLAYER_SPEED

# Schiet (zoek # SCHIET in event-loop):
player_bullets.append(pygame.Rect(player_rect.centerx - 3, player_rect.top - 15, 6, 15))

Stap 2: ✅ Basic: baas raken en HP-balk

Botsing speler-kogel met baas:

Zoek # STAP 2:

for b in player_bullets[:]:
    b.y -= 8
    if b.y < 0:
        player_bullets.remove(b)
        continue
    pygame.draw.rect(screen, YELLOW, b)
    if b.colliderect(boss_rect):
        player_bullets.remove(b)
        boss_hp -= 1
        if boss_hp <= 0:
            running = False  # speler wint!

HP-balk tekenen (zoek # HP BALK):

# Achtergrond van de balk
pygame.draw.rect(screen, DARK_RED, (10, 10, 300, 20))
# Gevulde balk op basis van huidige HP
breedte = int(300 * boss_hp / BOSS_MAX_HP)
pygame.draw.rect(screen, RED, (10, 10, breedte, 20))
# Label
hp_surf = font.render(f"Baas HP: {boss_hp}", True, WHITE)
screen.blit(hp_surf, (320, 10))

Klik Run. Schiet op de baas: de HP-balk slinkt!

Stap 3: ⭐ Stretch: baas schiet terug

De baas schiet elke N frames een kogel naar beneden.

Zoek # STAP 3:

boss_shoot_timer += 1
if boss_shoot_timer >= boss_shoot_interval:
    boss_shoot_timer = 0
    boss_bullets.append(pygame.Rect(boss_rect.centerx - 4, boss_rect.bottom, 8, 16))

Baas-kogels updaten:

for b in boss_bullets[:]:
    b.y += 6
    if b.y > HEIGHT:
        boss_bullets.remove(b)
        continue
    pygame.draw.rect(screen, ORANGE, b)
    if b.colliderect(player_rect):
        boss_bullets.remove(b)
        player_lives -= 1
        if player_lives <= 0:
            running = False

Teken player_lives als hartjes of rode blokjes onderaan het scherm.

Stap 4: 🔥 Expert: drie fases

Nu reageert de baas op zijn HP:

  • Fase 1 (HP 100 tot 50): normaal gedrag
  • Fase 2 (HP 50 tot 25): sneller bewegen, vaker schieten
  • Fase 3 (HP < 25): maximale snelheid, dubbele kogels

Zoek # STAP 4:

if boss_hp > 50:
    boss_phase = 1
    boss_speed_abs = 3
    boss_shoot_interval = 60
elif boss_hp > 25:
    boss_phase = 2
    boss_speed_abs = 5
    boss_shoot_interval = 35
else:
    boss_phase = 3
    boss_speed_abs = 7
    boss_shoot_interval = 20

# Pas de snelheid aan zonder de richting te wisselen:
boss_speed = boss_speed_abs * (1 if boss_speed > 0 else -1)

Fase 3: dubbele kogels (voeg toe in de shoot-code):

if boss_phase == 3:
    boss_bullets.append(pygame.Rect(boss_rect.left + 10, boss_rect.bottom, 8, 16))
    boss_bullets.append(pygame.Rect(boss_rect.right - 18, boss_rect.bottom, 8, 16))
else:
    boss_bullets.append(pygame.Rect(boss_rect.centerx - 4, boss_rect.bottom, 8, 16))

Win-scherm bij boss_hp <= 0:

screen.fill(BLACK)
win = font.render("BAAS VERSLAGEN!", True, YELLOW)
screen.blit(win, (WIDTH // 2 - win.get_width() // 2, HEIGHT // 2))
pygame.display.flip()
pygame.time.wait(3000)

Showcase

Laat je spel zien aan een coach en een buddy. Wie haalt fase 3 en overleeft?

Tot de volgende keer!

“Volgende keer: jouw eigen spel, van nul, helemaal jouw idee.”

Neem mee naar huis

Probeer thuis één van deze uitbreidingen:

  1. Makkelijk: verander de kleur van de baas per fase (groen → oranje → rood).
  2. Middel: voeg een score toe: hoe sneller je de baas verslaat, hoe meer punten.
  3. Lastig: laat de baas in fase 2 ook diagonale kogels schieten (schuin links en rechts).
  4. Erg lastig: voeg een tweede speler toe die mee kan doen met WASD-toetsen.

Vastgelopen? Vraag het volgende dojo aan een coach, of probeer gewoon iets anders. Programmeren is doen.

Bekijk de cheatsheet voor deze sessie

14 juni 2026, 13:39

Sessie 10: Mijn Spel

Dit is jouw sessie. Geen vaste stappen, geen verplichte mechanics. Jij beslist wat je bouwt, en vandaag maak je het.

Jouw spel, jouw regels

In negen sessies heb je geleerd:

  • Variabelen, functies en game loops
  • Toetsenbord- en muisinput
  • Sprites, collision detection en score
  • Geluid en animatie
  • Klassen en overerving
  • Scrollende achtergronden, spawnen en moeilijkheidsscaling
  • HP-balken, state machines en baas-AI

Al die bouwstenen liggen klaar. Vandaag combineer je ze in je eigen spel.

Kies je concept

Nog geen idee? Hier zijn wat genres om van te starten:

Dodge-game: wijk objecten uit die steeds sneller komen. Simpel maar verslavend.

Platformer: spring van platform naar platform, verzamel items, vermijd vijanden.

Shooter: schiet vijanden neer die van boven of van de zijkant komen.

Puzzelgame: schuif blokjes, verbind punten, of los een patroon op.

Racegame: ontwerp een parcours en beweeg zo snel mogelijk naar de finish.

Vertel een verhaal: geen score, geen levens. Laat de speler klikken en keuzes maken.

Je mag ook iets combineren: een shooter met puzzelelementen, een platformer met een baas aan het einde. Alles mag.

Plan je spel

Vóór je code schrijft, beantwoord deze drie vragen:

  1. Wat doet de speler? (bewegen, schieten, springen, klikken, …)
  2. Wat is het doel? (score halen, de baas verslaan, het einde bereiken, …)
  3. Wat maakt het moeilijk? (vijanden, obstakels, een timer, …)

Schrijf je antwoorden op een papiertje of in een comment bovenaan je code. Dit helpt je gefocust te blijven als je vastloopt.

Animatie: sprite wisselen per frame

Wil je een loopanimatie, een explosie of een knipperend object? Maak een lijst met afbeeldingsnamen en wissel actor.image elke N milliseconden. De demo hieronder laat zien hoe dat werkt: gebruik de schuifbalk om de snelheid aan te passen en de knop om te pauzeren:

In Python gebruik je dan een lijst met afbeeldingsnamen en een timer:

frames = ['lopen_1', 'lopen_2', 'lopen_3', 'lopen_4']
anim_timer = 0
FRAME_DUUR = 10   # frames (bij 60 fps = ~167 ms)

def update():
    global anim_timer
    anim_timer += 1
    speler.image = frames[(anim_timer // FRAME_DUUR) % len(frames)]

Aan de slag

Download de starter via deze link. De starter heeft:

  • Een werkende pygame game loop
  • Een lege draw()- en update()-sectie
  • Kleur-constanten en een lettertypevariabele klaar
  • Comments die aangeven waar je wat kunt plaatsen

Open main.py en begin met Stap 1 van je eigen plan. De cheatsheet op deze pagina heeft alle patronen van de vorige sessies bij de hand.

Vastgelopen? Vraag een coach. Beschrijf wat je wilt bereiken, niet alleen wat niet werkt. Dan kunnen we samen de beste aanpak bedenken.

Te snel klaar? Voeg geluid toe, maak een start-scherm, of voeg een tweede speler toe.

Showcase

Aan het einde van de sessie presenteert iedereen zijn spel. Je hoeft het niet af te hebben. Laat zien wat je gemaakt hebt en vertel:

  • Wat is het concept van je spel?
  • Welke techniek uit een vorige sessie heb je gebruikt?
  • Wat zou je nog willen toevoegen als je meer tijd had?

Wat nu?

CoderDojo stopt na tien sessies. Zelf bouwen stopt niet.

Blijf bouwen. Kleine projectjes leren je meer dan grote cursussen. Maak een spel voor je broer of zus, je huisdier, of gewoon voor jezelf.

Inspiratie nodig?

CoderDojo komt terug. Jij ook?

Blijf bouwen!

Je hebt in tien sessies een platformer, een shooter, een boss battle en meer gebouwd. Neem die code mee naar huis, open hem volgende week opnieuw, en voeg gewoon één ding toe. Dat is hoe programmeurs werken.

Bekijk de cheatsheet voor deze sessie

13 juni 2026, 13:30

Git sessies

Vijf sessies over Git en GitHub, van je eerste commit tot pull requests. Plus een bonus-sessie over Markdown, de taal waarin je notities en documentatie schrijft.

13 juni 2026, 13:30

Subsecties van Git sessies

Sessie 11: Git: Jouw code-geschiedenisboek

Stel je voor: je werkt drie uur aan je game. Je voegt een cool nieuw wapen toe. Maar… nu doet de rest van je game het niet meer. En je weet niet meer wat je precies veranderd hebt. Weg drie uur werk.

Git is de oplossing. Git onthoudt élke versie van je bestanden. Als een oneindige “undo”-knop die nooit vergeet wat je gedaan hebt.

In deze sessie installeer je Git, maak je je eerste repository en leg je voor altijd vast wat je doet: stap voor stap, versie voor versie. En het leuke: Git werkt niet alleen voor code. Ook voor notities, schoolverslagen en verhalen.

Wat is Git?

Git is een versiebeheersysteem. Het houdt bij wat jij verandert in je bestanden, wanneer je dat deed, en waarom. Elke keer dat je een stukje werk af hebt, maak je een commit: een foto van al je bestanden op dat moment.

Wat Git bijzonder maakt:

  • Elke versie is bewaard. Je kunt altijd terug naar een vorige commit als iets kapot gaat.
  • Je werkt lokaal. Git draait op jouw computer. Geen internet nodig.
  • Git is snel. Zelfs projecten met duizenden bestanden controleren in milliseconden.

Git is gemaakt door Linus Torvalds, dezelfde persoon die Linux bouwde. Hij had iets nodig om met duizenden programmeurs tegelijk aan de Linux-kernel te werken. In 2005 bouwde hij Git in een weekend. Vandaag gebruikt bijna elke ontwikkelaar ter wereld het.

Git is niet alleen voor code

Git is gebouwd voor broncode, maar het werkt met alle tekstbestanden. Een tekstbestand is elk bestand dat je met Kladblok of een simpele editor kunt openen en lezen: .py, .html, .css, .json, .txt, .csv, .md (Markdown), .yml, .toml, noem maar op.

Wat Git níet goed kan: binaire bestanden. Dat zijn bestanden die niet uit leesbare tekst bestaan: afbeeldingen (.png, .jpg), video’s (.mp4), gecompileerde programma’s (.exe), Word-documenten (.docx). Git kan ze wél bijhouden, maar het is trager en je kunt niet zien wát er precies veranderd is. Bij tekstbestanden toont git diff elke letter die je toevoegde of weghaalde. Bij een .png zegt Git alleen “dit bestand is gewijzigd”, maar niet wát er aan de afbeelding veranderde.

Markdown en notities

Veel notitie-apps van tegenwoordig gebruiken Markdown (.md-bestanden) om je documenten op te slaan. Denk aan:

  • Obsidian: je notities zijn gewoon .md-bestanden in een map op je computer
  • Notion: exporteert naar Markdown
  • Joplin: slaat alles op als Markdown
  • Typora, Zettlr, Logseq: allemaal Markdown-gebaseerd

Omdat Markdown-bestanden gewone tekstbestanden zijn, kun je er Git op loslaten. Je houdt de geschiedenis van je notities bij, je kunt terug naar een vorige versie van een document, en je kunt je notities delen via GitHub, precies zoals je met code doet.

Een map met Markdown-notities onder Git zetten is even simpel als een Python-project:

mkdir mijn-notities
cd mijn-notities
git init
echo "# Mijn Notities" > start.md
git add start.md
git commit -m "Eerste notitie: startpagina"

Vanaf dat moment bewaart Git elke wijziging aan je notities. Schrijf je een verslag voor school in Markdown? Commit elke paragraaf. Werk je aan wereldbouw voor een verhaal? Git onthoudt elke versie van je plot.

Wanneer Git wél en níet voor notities gebruiken

Wél Git gebruikenBeter iets anders
Notities in Markdown (.md)Notities in Word (.docx)
Configuratiebestanden (.json, .yml)Grote afbeeldingen of video’s bij je notities
Schrijfwerk: verslagen, verhalen, blogsRealtime samenwerking zoals Google Docs (daar is Git te traag voor)
Je CoderDojo-cheatsheetsWachtwoorden of persoonlijke dagboeken (tenzij private repo)

Kortom: alles wat tekst is, kun je in Git stoppen. Alles wat binair is, beter niet.

Waarom versiebeheer?

Zonder Git ziet je workflow er zo uit:

game.py
game_backup.py
game_backup2.py
game_final.py
game_final_echt.py
game_final_echt_nieuwe_wapens.py

Herkenbaar? Met Git heb je maar één bestand nodig: game.py. Git onthoudt de rest.

Wat versiebeheer je oplevert:

  • Nooit meer werk kwijt. Alles wat je commit, blijft bestaan. Altijd.
  • Begrijpen wat er gebeurd is. Je ziet exact welke regels je wanneer veranderde.
  • Experimenteren zonder risico. Maak een aparte kopie van je code (een branch), probeer iets geks, en gooi het weg als het niet werkt. Je originele code blijft intact.
  • Samenwerken. Meerdere mensen kunnen tegelijk aan hetzelfde project werken, zonder elkaars code te overschrijven.

Wat stop je NIET in Git?

Git is gemaakt voor tekstbestanden: bestanden die jij zelf schrijft: code, notities, configuratie. Er zijn dingen die je beter buiten Git houdt:

Stop wél in GitStop NIET in Git
Je Python-bestanden (.py)Wachtwoorden, API-sleutels, tokens
Afbeeldingen die je game gebruiktBestanden die je programma zelf maakt (.exe, .pyc)
Geluidsbestanden (.wav, .mp3)De __pycache__ map
Tekstbestanden, configuratieGrote bestanden (>50 MB) zoals video’s
Je README.mdInstellingen van jouw specifieke computer

Waarom geen wachtwoorden in Git? Omdat Git álles onthoudt, voor altijd. Zelfs als je later een wachtwoord verwijdert, zit het nog in de geschiedenis. Iedereen die jouw code ooit ziet, kan terugscrollen naar die commit. En als je code ooit op GitHub komt, staat je wachtwoord op het internet. Voor eeuwig.

Gebruik een .gitignore-bestand om Git te vertellen welke bestanden het moet negeren. Daar kom je zo meteen achter.

Stap 0: Git installeren

Windows

  1. Ga naar git-scm.com en download de Windows-installer.
  2. Dubbelklik het gedownloade bestand.
  3. Klik door de installatie. De standaardopties zijn prima.
  4. Belangrijk: kies bij het kiezen van de teksteditor Nano of Notepad++ (niet Vim, tenzij je Vim al kent).
  5. Open na de installatie Git Bash (zoek ernaar in het startmenu).

Mac

Open de Terminal (zoek naar “Terminal” in Spotlight) en typ:

git --version

Als Git niet geïnstalleerd is, vraagt macOS je om de developer tools te installeren. Klik op “Install”. Klaar.

Linux (Ubuntu/Debian)

sudo apt install git

Controleren of het werkt

Open een terminal (Git Bash op Windows) en typ:

git --version

Je ziet iets als git version 2.47.0. Dat betekent: Git staat klaar.

Stap 1: Vertel Git wie je bent

Git wil weten wie jij bent, zodat het jouw naam bij elke commit kan zetten. Dit doe je één keer, daarna onthoudt Git het.

git config --global user.name "Jouw Naam"
git config --global user.email "jouw@email.com"

Gebruik hetzelfde e-mailadres dat je straks voor GitHub gebruikt. Dat maakt koppelen makkelijker.

Tip: --global betekent: deze instelling geldt voor ál je Git-projecten. Je hoeft dit maar één keer te doen.

Stap 2: Je eerste repository maken

Een repository (of “repo”) is een map waar Git de versies bijhoudt. Laten we er één maken.

Maak eerst een nieuwe map voor je project:

mkdir mijn-eerste-git-project
cd mijn-eerste-git-project

Nu vertel je Git: “Deze map is een repository.”

git init

Je ziet: Initialized empty Git repository in .../mijn-eerste-git-project/.git/

Git heeft een verborgen map .git aangemaakt. Daar bewaart het álles: de geschiedenis, de commits, de configuratie. Raak die map nooit met de hand aan, want Git beheert hem zelf.

Stap 3: Je eerste bestand committen

Maak een bestand aan. Bijvoorbeeld een Python-bestand met één regel:

echo 'print("Hallo Git!")' > hallo.py

Nu vertel je Git: “Let op dit bestand.”

git add hallo.py

Met git add zet je bestanden in de staging area: een tussenstation. Je zegt tegen Git: “Deze wijzigingen wil ik in mijn volgende commit.”

Controleer wat er klaarstaat:

git status

Git toont:

On branch master
Changes to be committed:
  new file:   hallo.py

Nu komt de commit zelf:

git commit -m "Mijn eerste commit: hallo.py toegevoegd"

Wat gebeurt hier? -m staat voor “message”. De tekst tussen aanhalingstekens is je commit message: een korte uitleg van wat je veranderd hebt. Git heeft nu een permanente foto van je project gemaakt.

Goede commit messages: Schrijf in het Engels (dat is de afspraak in bijna alle projecten). Begin met een werkwoord: “Add”, “Fix”, “Update”. Hou het kort: maximaal 72 karakters.

Stap 4: Veranderingen bijhouden

Open hallo.py in een teksteditor. Verander de regel naar:

print("Hallo Git! Jij onthoudt mijn code.")

Sla het bestand op. Kijk nu wat Git ziet:

git status

Git weet dat hallo.py gewijzigd is. Maar wát is er precies veranderd?

git diff

git diff toont exact welke regels je toegevoegd (groen met +) en verwijderd (rood met -) hebt. Dit is één van de krachtigste dingen van Git: je ziet letterlijk wat er veranderd is, karakter voor karakter, sinds je laatste commit.

Commit de wijziging:

git add hallo.py
git commit -m "Update: begroeting uitgebreid"

Stap 5: Terug in de tijd

Dit is waar Git magisch wordt. Stel: je hebt spijt van je laatste wijziging. Je wilt terug naar de eerste versie.

Toon eerst alle commits:

git log --oneline

Je ziet zoiets:

a1b2c3d Update: begroeting uitgebreid
e4f5g6h Mijn eerste commit: hallo.py toegevoegd

Elke commit heeft een unieke code, een hash. Die lange code (verkort tot 7 karakters) identificeert exact die ene versie van je project.

Om te zien hoe hallo.py eruitzag in de eerste commit:

git show e4f5g6h:hallo.py

Daar is je originele print("Hallo Git!") weer.

Wil je écht terug in de tijd? Dat kan:

git checkout e4f5g6h -- hallo.py

Nu staat hallo.py weer zoals in je eerste commit. Controleer met cat hallo.py. Je ziet de oude versie. Maar maak je geen zorgen: je tweede commit is niet weg. Met git checkout master -- hallo.py ga je weer naar de nieuwste versie.

Stap 6: Wat níet in Git: .gitignore

Maak een bestand aan dat Git moet negeren:

echo "GEHEIM_WACHTWOORD=12345" > geheimen.txt

git status toont dit bestand nu als “untracked”. Git heeft het gezien, maar weet niet of je het wilt bijhouden. Je kunt het negeren met een .gitignore-bestand:

echo "geheimen.txt" > .gitignore

Nu git status opnieuw en geheimen.txt is verdwenen uit de lijst. Git negeert het. (Voeg .gitignore zelf wél toe aan Git met git add .gitignore en git commit, zodat anderen ook weten wat er genegeerd moet worden.)

Een goed .gitignore voor een Python-project:

# Python
__pycache__/
*.pyc
*.pyo

# Geheimen
*.env
secrets.txt

# Jouw editor
.vscode/
.idea/

Showcase

Laat aan een coach en een buddy zien:

  1. Je repository met minstens 3 commits.
  2. Het resultaat van git log --oneline: jouw commit-geschiedenis.
  3. Een git diff die toont wat je veranderd hebt.
  4. Je .gitignore-bestand.

Tot de volgende keer!

“Volgende keer: twee versies van je code tegelijk. Je werkt aan een nieuwe feature terwijl de oude versie gewoon blijft werken. Dat heet branches, en het is wat Git écht krachtig maakt.”

Neem mee naar huis

  1. Makkelijk: Maak een repository voor je notities. Zet een Markdown-bestand met wat je vandaag geleerd hebt in Git, en commit het.
  2. Middel: Verander iets in je code of notities, gebruik git diff om de wijziging te bekijken, en commit hem met een goede message.
  3. Lastig: Maak drie commits met verschillende wijzigingen. Gebruik git show om elke versie te bekijken. Gebruik git checkout om terug te gaan naar de eerste commit, en daarna weer naar de laatste.
  4. Erg lastig: Maak een Python-project met een goede .gitignore. Zorg dat __pycache__/ en .pyc-bestanden écht genegeerd worden (check met git status).

Vastgelopen? Vraag het volgende dojo aan een coach, of probeer gewoon iets anders. Programmeren is doen. Git leren is doen.

13 juni 2026, 13:30

Sessie 12: Git Branches: Parallelle universums voor je code

Vorige sessie leerde je commits maken: foto’s van je code op één tijdlijn. Alles netjes achter elkaar.

Maar wat als je een nieuw idee wil uitproberen? Een lasergun toevoegen aan je game, bijvoorbeeld. Je weet niet of het gaat werken. Je wil je werkende code niet kapot maken.

Daar zijn branches voor.

Een branch is een kopie van je code waar je vrij kunt experimenteren. Je hoofdcode (de master-branch) blijft veilig. Als je experiment werkt, plak je het terug in master. Werkt het niet? Je gooit de branch weg. Je master-branch heeft er nooit iets van gemerkt.

Noot: Op GitHub en in veel nieuwe projecten heet de hoofdbranch main in plaats van master. Dat is exact hetzelfde, alleen de naam is anders. In deze cursus gebruiken we master, maar als je online main tegenkomt, weet je dat het hetzelfde betekent.

Wat je vandaag leert

  • Wat een branch is en hoe Git branches intern opslaat
  • Branches aanmaken, wisselen en samenvoegen
  • Wat een merge conflict is en hoe je het oplost
  • Wanneer je wél en níet een branch moet gebruiken

Stap 0: Herhaling: waar sta je nu?

Open je terminal in het project van vorige sessie. Check waar je bent:

git status
git log --oneline

Je hebt een paar commits op master. Dit is je stabiele basis: hier ga je straks vanaf splitsen.

Stap 1: Je eerste branch

Je gaat een nieuwe feature toevoegen: een highscore.txt-bestand dat de hoogste score bijhoudt. Maar eerst maak je een branch:

git branch highscore-feature

Git heeft nu een nieuwe branch aangemaakt. Maar je staat nog steeds op master. Check welke branches er zijn:

git branch

Je ziet:

  highscore-feature
* master

Het sterretje bij master betekent: “hier sta je nu.” Wissel naar je nieuwe branch:

git switch highscore-feature

(Oudere Git-versies gebruiken git checkout highscore-feature. Beide werken.)

Nog een keer git branch: het sterretje staat nu bij highscore-feature. Alles wat je nu commit, gebeurt op deze branch. master blijft onaangeroerd.

Tip: Je kunt een branch aanmaken en er meteen naartoe switchen in één commando:

git switch -c mijn-nieuwe-branch

-c staat voor “create”. Dit is sneller en je vergeet nooit te switchen.

Stap 2: Werk doen op een branch

Maak een nieuw bestand aan:

echo "HIGHSCORE: 0" > highscore.txt

Commit je werk:

git add highscore.txt
git commit -m "Add highscore.txt met beginwaarde 0"

Voeg nog een bestand toe dat de highscore leest:

echo 'def lees_highscore():' > highscore_manager.py
echo '    with open("highscore.txt") as f:' >> highscore_manager.py
echo '        return int(f.read().split(": ")[1])' >> highscore_manager.py

Commit opnieuw:

git add highscore_manager.py
git commit -m "Add highscore_manager: functie om highscore te lezen"

Kijk nu naar je log:

git log --oneline

Je ziet al je commits van master, plus de twee nieuwe. Git onthoudt de hele keten.

Stap 3: Twee werelden tegelijk

Switch terug naar master:

git switch master

Kijk wat er hier is:

ls

highscore.txt en highscore_manager.py zijn… weg. Ze bestaan alleen op de highscore-feature-branch. Op master is alles nog precies zoals je het achterliet.

Dit is de magie van branches: twee (of meer) versies van je project, tegelijk op je computer, zonder dat ze elkaar in de weg zitten.

Switch nog eens heen en weer om het te voelen:

git switch highscore-feature   # bestanden zijn terug
git switch master                # bestanden zijn weer weg

Stap 4: Samenvoegen met git merge

Je highscore-feature werkt. Tijd om hem terug in master te zetten. Dit heet mergen.

Zorg dat je op master staat:

git switch master

Voeg de branch samen:

git merge highscore-feature

Git toont iets als Updating a1b2c3d..e4f5g6h en Fast-forward. Je highscore-feature-commits zijn nu onderdeel van master. Controleer:

ls
git log --oneline

highscore.txt en highscore_manager.py staan nu op master. Alle commits van de feature-branch zijn opgenomen in de geschiedenis.

Stap 5: Wat zijn merge conflicts?

Stel: je hebt op master iets veranderd in highscore.txt, bijvoorbeeld “HIGHSCORE: 100” in plaats van “HIGHSCORE: 0”. En tegelijkertijd heb je op een andere branch highscore.txt ook veranderd, naar “HIGHSCORE: 500”.

Als je nu probeert te mergen, weet Git niet welke versie de juiste is. Dat is een merge conflict. Git vraagt jóu om te beslissen.

Laten we het expres uitlokken.

Op master:

echo "HIGHSCORE: 100" > highscore.txt
git add highscore.txt
git commit -m "Update highscore naar 100 op master"

Maak een nieuwe branch en verander daar hetzelfde bestand:

git switch -c andere-highscore
echo "HIGHSCORE: 500" > highscore.txt
git add highscore.txt
git commit -m "Update highscore naar 500"

Switch terug naar master en probeer te mergen:

git switch master
git merge andere-highscore

Git zegt: CONFLICT (content): Merge conflict in highscore.txt. Open highscore.txt in je editor. Je ziet:

<<<<<<< HEAD
HIGHSCORE: 100
=======
HIGHSCORE: 500
>>>>>>> andere-highscore

Dit zijn de twee versies. HEAD is jouw master-versie. Daaronder staat de versie van andere-highscore. Jij kiest welke je houdt, of je combineert ze.

Verwijder de markers en kies één versie:

HIGHSCORE: 500

Sla het bestand op. Vertel Git dat het conflict is opgelost:

git add highscore.txt
git commit -m "Merge: highscore van andere-highscore gekozen"

Conflict opgelost. Git kan weer verder.

Stap 6: Branches opruimen

Je feature is gemerged. De branch heb je niet meer nodig:

git branch -d highscore-feature
git branch -d andere-highscore

-d staat voor “delete”. Git weigert een branch te verwijderen die nog niet gemerged is: dat is een veiligheidsklep. Als je écht weg wil gooien zonder mergen, gebruik je -D (hoofdletter). Maar wees daar voorzichtig mee.

Wanneer wél een branch, wanneer niet?

Wél een branchGéén branch
Nieuwe feature die tijd kostTypo in een comment fixen
Experiment waarvan je niet weet of het werktKleine bugfix van één regel
Iets dat je werkende code kan brekenJe werkt alleen en je wijziging is duidelijk
Je werkt samen met anderen(bij solo-werk is master vaak genoeg)

Vuistregel: Als je twijfelt, maak een branch. Een branch kost niks. Code kwijtraken wel.

Tips om vlot te werken met branches

  1. Houd branches kort. Een branch van 3 uur is prima. Een branch van 3 weken wordt een merge-nachtmerrie: hoe langer je wacht met mergen, hoe meer er intussen op master verandert, en hoe groter de kans op conflicts.
  2. Eén ding per branch. “Highscore toevoegen” is een goede branch. “Highscore, menu, en nieuwe levels toevoegen” is te veel: split het op.
  3. Merge vaak. Werk je feature af, merge hem meteen terug naar master. Kleine, frequente merges zijn makkelijker dan één groot monster-merge.
  4. Geef branches duidelijke namen. highscore-feature is goed. test123 of branch2 zijn slecht. Over een week weet je niet meer wat er in test123 zat.
  5. Check waar je bent voor je begint. git branch of git status vertelt je op welke branch je staat. Maak hier een gewoonte van, zodat je voorkomt dat je per ongeluk op master code schrijft die eigenlijk op een feature-branch hoort.

Showcase

Laat aan een coach en een buddy zien:

  1. git branch met minstens twee branches (waaronder master).
  2. Op elke branch een ander bestand of andere code.
  3. Switch heen en weer: de bestanden verschijnen en verdwijnen.
  4. Een succesvolle merge van een feature-branch in master.

Tot de volgende keer!

“Tot nu toe leeft al je code alleen op jouw laptop. Volgende keer zetten we hem online. Je maakt een GitHub-account, pusht je repository naar het internet, en je game is overal ter wereld te bekijken. En: je kunt samenwerken met anderen. GitHub: je code de wereld in.”

Neem mee naar huis

  1. Makkelijk: Maak een branch voor een kleine feature in een bestaand project. Commit je werk en merge hem terug.
  2. Middel: Creëer expres een merge conflict (twee branches die hetzelfde bestand wijzigen) en los het op.
  3. Lastig: Werk met drie branches tegelijk op hetzelfde project. Merge ze één voor één terug in master. Check na elke merge of alles nog werkt.
  4. Erg lastig: Maak een branch, commit drie wijzigingen, switch terug naar master, maak daar óók een wijziging in hetzelfde bestand, en merge de branch. Los het conflict zorgvuldig op en check met git log --graph hoe de geschiedenis eruitziet.
13 juni 2026, 13:30

Sessie 13: GitHub: Je code online, voor iedereen

Tot nu toe leeft al je code op jouw laptop. Handig voor jou, maar niemand anders kan erbij. En als je laptop crasht, ben je alles kwijt.

GitHub is een website waar je Git-repositories online zet. Het is een back-up, een portfolio, en een samenwerkingsplatform in één. Vandaag zet je jouw code op GitHub. Aan het einde van deze sessie kan iedereen met een internetverbinding jouw projecten bekijken, en jij die van hen.

Wat is GitHub?

GitHub is niet hetzelfde als Git. Git is het versiebeheersysteem dat op jouw computer draait. GitHub is een website (github.com) die Git-repositories host: een soort Google Drive voor code, maar dan met Git eronder.

Wat GitHub toevoegt aan Git:

  • Back-up in de cloud. Je code staat niet alleen lokaal. Laptop kapot? Je code overleeft.
  • Samenwerken. Meerdere mensen kunnen aan dezelfde repo werken. GitHub regelt wie wat mag.
  • Pull requests. Je vraagt toestemming om jouw wijzigingen in iemands project te stoppen, met discussie en review.
  • Issues. Bugs melden, features voorstellen, taken bijhouden: allemaal in je repo.
  • Portfolio. Je GitHub-profiel is je visitekaartje. Werkgevers kijken ernaar.

GitHub is niet de enige optie; er zijn alternatieven zoals GitLab en Bitbucket. Maar GitHub is de grootste, met meer dan 100 miljoen gebruikers. In deze sessies gebruiken we GitHub.

Stap 0: Een GitHub-account maken

  1. Open github.com in je browser.
  2. Klik op Sign up.
  3. Vul je e-mailadres in. Gebruik hetzelfde adres dat je in sessie 11 bij git config hebt ingesteld: dat scheelt gedoe.
  4. Kies een username. Dit wordt jouw identiteit op GitHub. Kies iets dat je over 5 jaar nog steeds leuk vindt. Je kunt je username later veranderen, maar oude links naar jouw profiel werken dan niet meer.
  5. Verifieer je account via de e-mail die GitHub stuurt.
  6. Kies het Free-abonnement. Alles wat je nodig hebt is gratis: onbeperkt publieke en private repositories.

Tip voor coaches: check of de ninjas toegang hebben tot hun e-mail tijdens de sessie. Sommige laptops staan niet ingelogd op webmail. Zorg voor een plan B: als e-mailverificatie niet lukt, kunnen ninjas GitHub later thuis verifiëren. De rest van de sessie werkt ook zonder verificatie.

Stap 1: Je eerste repository op GitHub

Je hebt een lokaal project op je computer (van sessie 11). Die ga je nu online zetten.

Op GitHub, klik rechtsboven op het + icoontje → New repository.

Vul in:

VeldWat je invult
Repository namemijn-eerste-git-project (zelfde als je lokale map)
Description“Mijn eerste Git-project (CoderDojo sessie 11)”
Public / PrivateKies Public: anderen mogen je code zien
Initialize with READMENIET aanvinken: je hebt al een lokaal project

Klik Create repository.

GitHub toont nu instructies. Kies het blok onder "…or push an existing repository from the command line". Kopieer die drie commando’s: die heb je zo nodig.

Stap 2: Je lokale repo koppelen aan GitHub

In je terminal (in je projectmap):

git remote add origin https://github.com/JOUW_USERNAME/mijn-eerste-git-project.git

Wat gebeurt hier? remote is een externe locatie waar jouw repo ook staat. origin is de naam die je die locatie geeft. “origin” is de standaardnaam voor je belangrijkste remote. Je kunt meerdere remotes hebben (bijvoorbeeld origin voor GitHub, backup voor GitLab), maar één is meestal genoeg.

Controleer of het gelukt is:

git remote -v

Je ziet:

origin  https://github.com/JOUW_USERNAME/mijn-eerste-git-project.git (fetch)
origin  https://github.com/JOUW_USERNAME/mijn-eerste-git-project.git (push)

fetch = hier haal je code vandaan. push = hier stuur je code naartoe. Meestal zijn die hetzelfde.

Stap 3: Je code online zetten met git push

Nu komt het moment: je lokale commits naar GitHub sturen.

git push -u origin master

push = stuur mijn commits naar de remote. -u origin master = “onthoud dat master op mijn computer hoort bij master op origin.” De volgende keer kun je gewoon git push typen, want Git onthoudt de koppeling.

GitHub vraagt om in te loggen. Dat kan op twee manieren:

  1. Via de browser: GitHub opent een browservenster, je klikt op “Authorize”. Klaar.
  2. Met een Personal Access Token: maak je aan via GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic). Geef de token een naam, vink repo aan, kopieer de token, en plak hem als wachtwoord in de terminal.

Voor ninjas: methode 1 (browser) is het makkelijkst. Als dat niet werkt, help dan met een token.

Na een succesvolle push, ververs je GitHub-pagina. Je bestanden staan er! Je hallo.py, je commit-geschiedenis: alles.

Stap 4: Wijzigingen pushen

Maak een wijziging lokaal:

echo 'print("GitHub is cool!")' >> hallo.py
git add hallo.py
git commit -m "Add GitHub enthusiasm"

Push naar GitHub:

git push

Je hoeft nu geen -u origin master meer, want Git weet de weg. Ververs GitHub: je nieuwe commit staat erbij.

Stap 5: Een nieuw project starten via GitHub

Dit is de omgekeerde route: je begint op GitHub en haalt het naar je computer.

Op GitHub: New repository. Noem hem python-spelletje. Vink dit keer wél Add a README file aan; GitHub maakt dan een repo met één bestand erin. Klik Create repository.

Nu haal je deze repo naar je computer. Dit heet clonen:

cd ~   # ga naar je home-map
git clone https://github.com/JOUW_USERNAME/python-spelletje.git

GitHub maakt een map python-spelletje aan met de README erin. En het is meteen een volwaardige Git-repository: de .git-map zit er al in. Je hoeft geen git init te doen.

cd python-spelletje
git log --oneline   # je ziet de eerste commit die GitHub voor je maakte

Nu kun je hier lokaal verder werken en je commits pushen naar GitHub, precies zoals in Stap 3 tot 4.

Stap 6: Wat als iemand anders ook wijzigingen maakt?

Stel: je hebt thuis aan python-spelletje gewerkt en gepusht. Nu ben je op de dojo-laptop en wil je verder. Je hebt de nieuwste versie nog niet.

git pull

git pull haalt de nieuwste commits van GitHub naar jouw computer. Het is twee acties in één: git fetch (ophalen) + git merge (samenvoegen met jouw lokale code).

Altijd git pull doen voor je begint met werken, anders loop je achter en krijg je merge conflicts.

Samenvatting van de workflow:

CommandoWat het doet
git pullHaal nieuwste versie op van GitHub
Werk aan je code, maak commits (git add, git commit)
git pushStuur jouw commits naar GitHub

Onthoud: pull voor je begint, push als je klaar bent.

Showcase

Laat aan een coach en een buddy zien:

  1. Je GitHub-profiel met minstens één repository.
  2. De commit-geschiedenis van je repo op GitHub (klik op “X commits” boven de bestandslijst).
  3. Een verse git push die net op GitHub is aangekomen.

Tot de volgende keer!

“Nu staat je code online. Maar wat zet je in een commit message? Hoe schrijf je een bericht dat over drie maanden nog steeds duidelijk is? En hoe werk je met een team zonder de boel te breken? Volgende keer: de professionele kant van Git: best practices die elke developer gebruikt.”

Neem mee naar huis

  1. Makkelijk: Push een bestaand lokaal project naar een nieuwe GitHub-repository.
  2. Middel: Maak 3 commits lokaal, push ze, en check op GitHub of ze allemaal zichtbaar zijn.
  3. Lastig: Clone een repo van GitHub, maak een wijziging, commit, en push terug.
  4. Erg lastig: Simuleer werken op twee computers: clone een repo, maak een commit en push. Ga naar een andere map, clone dezelfde repo opnieuw (alsof het een andere computer is), maak een andere commit, en probeer te pushen. Wat gebeurt er? Los het op met git pull.
13 juni 2026, 13:30

Sessie 14: Git Best Practices: Schrijf commits die je later nog snapt

Je kunt Git-commando’s typen. Je code staat op GitHub. Maar er is een verschil tussen “Git gebruiken” en “Git goed gebruiken.”

Deze sessie gaat over de gewoontes die ervaren developers elke dag toepassen. Geen nieuwe commando’s, wel scherpere regels. Aan het einde schrijf je commit messages waar je over een jaar nog iets aan hebt, en werk je met een branching-strategie die je project overzichtelijk houdt.

Wat je vandaag leert

  • Hoe je een commit message schrijft die iets zegt
  • Drie simpele regels voor branching
  • Wat git stash is en wanneer je het gebruikt
  • De pull-voor-je-pusht regel

Deel 1: Commit messages die iets zeggen

Een slechte commit message ziet er zo uit:

git commit -m "fix"
git commit -m "update"
git commit -m "dingen veranderd"

Over drie maanden kijk je terug. Wat was “fix”? Welke “dingen”? Je weet het niet meer. Je moet door de code spitten om te achterhalen wat er gebeurd is. Dat is tijdverspilling.

De goede commit message: 3 delen

Een professionele commit message heeft drie onderdelen:

1. Een korte samenvatting (max 72 karakters)

Schrijf in het Engels. Begin met een werkwoord in de tegenwoordige tijd. Dit heet “imperative mood”: alsof je een bevel geeft aan de codebase. Denk: “Add”, “Fix”, “Remove”, “Update”, “Refactor”.

Add highscore tracking
Fix star spawning off-screen
Remove unused collision code

2. Een lege regel

3. Een langere uitleg (optioneel, als het nodig is)

Add highscore tracking

Slaat de hoogste score op in highscore.txt. De score wordt
bijgewerkt na elke game-over. Het bestand wordt aangemaakt als
het nog niet bestaat.

Dit vervangt de oude methode waarbij de score alleen in het
geheugen stond en verloren ging bij afsluiten.

De uitgebreide uitleg vertelt waarom je iets veranderd hebt, niet alleen wát. De code zelf laat het “wat” al zien. Het “waarom” is wat je over drie maanden nodig hebt.

Commit message regels op een rij

Doe ditNiet dit
“Add player health bar”“added health bar thing”
“Fix collision detection on left wall”“fix”
“Remove debug print statements”“cleanup”
Max 72 karakters voor de titelEen heel verhaal in de titel
Tegenwoordige tijd, EngelsVerleden tijd (“added”, “fixed”)

Waarom Engels? Omdat bijna alle open source-projecten Engels gebruiken. Code is internationaal. Ook je Python-code schrijf je in het Engels (def calculate_score). Je commit messages volgen diezelfde taal.

Waarom tegenwoordige tijd? Een commit beschrijft wat deze wijziging dóet, niet wat jij gedaan hébt. “Add feature” (deze commit voegt een feature toe), niet “Added feature” (ik heb ooit een feature toegevoegd). Git zelf gebruikt ook tegenwoordige tijd: Merge branch 'feature', niet Merged.

Multi-line commits in de terminal

Je kunt een commit message over meerdere regels schrijven door de aanhalingstekens niet te sluiten:

git commit -m "Add highscore tracking

Slaat de hoogste score op in highscore.txt. Het bestand wordt
automatisch aangemaakt bij de eerste game-over."

Let op: je typt het sluitende aanhalingsteken pas op de laatste regel. Alles ertussen is onderdeel van je message.

Wanneer commit je?

Commit vaak. Commit klein.

Niet: drie uur werken, één enorme commit met 47 gewijzigde bestanden. Wel: elke 15 tot 30 minuten een commit, telkens als één logisch stukje af is.

Een vuistregel: als je commit message “en” bevat, is je commit te groot. “Add highscore tracking en fix menu bug en update sprites” → dit moeten drie aparte commits zijn.

Kleine commits maken het makkelijker om:

  • Te begrijpen wat er wanneer veranderd is
  • Eén specifieke wijziging terug te draaien zonder andere dingen kapot te maken
  • Merge conflicts op te lossen (kleine brokjes = minder conflicten)

Deel 2: Branching: drie simpele regels

Je weet al hóe je branches maakt (sessie 12). Nu: wannéér en waaróm.

Regel 1: master is altijd werkend

De master-branch is je etalage. Iemand die je repo cloned, moet je code kunnen runnen zonder foutmeldingen. master bevat nooit half-af werk.

Niet oké op master: code met # TODO: dit moet nog af, uitgecommentarieerde functies, experimenten die je “later nog fixet.”

Wel oké op master: werkende code. Punt.

Regel 2: Eén feature, één branch

Een branch doet precies één ding. Niet meer.

  • Goed: feature/player-health-bar
  • Slecht: feature/health-bar-and-menu-and-sound-effects

Als je tijdens het werken aan een feature denkt: “Oh, ik kan ook even die menu-bug fixen”: stop. Maak een nieuwe branch voor de bugfix. Merge die eerst. Ga dan verder met je feature.

Regel 3: Branches hebben een korte levensduur

Een branch die langer dan een paar dagen bestaat, wordt een probleem. master verandert intussen, en jouw branch raakt achterop. Hoe langer je wacht met mergen, hoe groter de kans op merge conflicts.

Merge je branch zodra de feature klaar is. Voor kleine dingen (een bugfix van 10 minuten): misschien heb je niet eens een aparte branch nodig.

Branch-naamgeving

Geef branches namen die je over een week nog begrijpt:

feature/highscore-tracking
bugfix/star-spawn-offscreen
experiment/particle-effects

De prefix (feature/, bugfix/, experiment/) vertelt meteen wat voor soort werk er in deze branch zit. Dit is een conventie, geen technische vereiste, maar het helpt.

Deel 3: Handige workflow-commando’s

git stash: werk opzij zetten

Stel: je bent bezig op een feature-branch. Je code is half af. Je wil even switchen naar master voor een snelle bugfix, maar je wil je half-affe werk niet committen. Daar is git stash voor:

git stash

Git bewaart al je wijzigingen tijdelijk en zet je working directory terug naar de laatste commit. Je kunt nu switchen, de bugfix doen, committen, en terugkomen:

git switch master
# ... bugfix doen, committen ...
git switch feature-branch
git stash pop

git stash pop haalt je opgeslagen wijzigingen terug. Alles staat weer zoals je het achterliet: half af, maar veilig bewaard.

git pull --rebase: een schonere geschiedenis

Normaal doet git pull een merge. Dat maakt een extra merge-commit aan. Soms wil je dat niet; je wil een rechte lijn van commits zonder vertakkingen.

git pull --rebase

Dit haalt de nieuwste commits op en zet jouw lokale commits erbovenop, alsof je ze ná de remote-commits gemaakt hebt. Het resultaat is een lineaire geschiedenis: geen merge-commits die alleen maar “Merge branch ‘master’” zeggen.

Let op: gebruik --rebase alleen op branches die jij alleen gebruikt. Bij gedeelde branches is gewoon git pull (merge) veiliger.

De pull-voor-je-pusht regel

Voordat je git push doet:

git pull

Altijd. Ook al denk je dat niemand anders gepusht heeft. Het kost één seconde en voorkomt dat GitHub je push weigert met “Updates were rejected because the remote contains work that you do not have locally.”

Deze regel geldt vooral als je samenwerkt. Als jij de enige bent die aan een repo werkt, is het risico kleiner, maar de gewoonte is goud waard.

Deel 4: De .gitignore die je altijd moet hebben

Elk project heeft bestanden die niet in Git horen. Je .gitignore is je eerste verdedigingslinie tegen per ongeluk wachtwoorden committen.

Minimale .gitignore voor een Python-project:

# Python
__pycache__/
*.pyc
*.pyo

# Virtual environment
venv/
.venv/

# Environment variables (bevat vaak wachtwoorden/keys)
.env

# Jouw editor
.vscode/
.idea/
*.swp
*.swo

# OS-bestanden
.DS_Store
Thumbs.db

Waarom __pycache__/ negeren? Dit zijn gecompileerde Python-bestanden die je programma automatisch aanmaakt. Ze zijn verschillend per Python-versie en per computer. Ze in Git stoppen geeft alleen maar ruis.

Waarom .env negeren? .env-bestanden bevatten vaak geheime sleutels, API-keys, database-wachtwoorden. Die mogen nooit, maar dan ook nooit in Git.

Showcase

Laat aan een coach en een buddy zien:

  1. Je laatste 5 commits, met goeie commit messages.
  2. Je .gitignore-bestand.
  3. Een branch-naam die de feature/prefix-conventie volgt.

Tot de volgende keer!

“Nu werk je professioneel met Git. Maar er is nog één concept dat élk team gebruikt: de pull request. Je code is klaar, maar voor hij in master komt, moet iemand anders hem goedkeuren. Hoe werkt dat? Volgende keer: pull requests, de review-muur waar élke wijziging doorheen moet.”

Neem mee naar huis

  1. Makkelijk: Herschrijf de commit messages van je laatste 5 commits. Gebruik de regels uit deze sessie.
  2. Middel: Maak een branch met de feature/-prefix, werk erin, merge hem terug, en verwijder hem. Doe hetzelfde voor een bugfix/-branch.
  3. Lastig: Gebruik git stash om half werk op te slaan, switch naar master, maak een snelle fix, push, en kom terug naar je feature met git stash pop.
  4. Erg lastig: Maak een situatie waar git pull faalt (clone je repo in twee mappen, maak in beide een andere commit, push de eerste, en probeer de tweede te pushen). Los het op: git pull, merge conflict fixen, en dan pas pushen.
13 juni 2026, 13:30

Sessie 15: Pull Requests: De voordeur van je project

Je hebt een feature gebouwd op een branch. Goeie commit messages, netjes gewerkt. Nu wil je je code in master zetten.

Je zou git merge kunnen doen en klaar. Maar in een team werkt dat niet. Iemand anders moet je code eerst bekijken: checken op fouten, op stijl, op dingen die je gemist hebt. Dát is een pull request.

Een pull request (PR) is een verzoek: “Haal mijn wijzigingen binnen.” Je opent hem op GitHub. Je teamgenoten bekijken je code, geven feedback. Jij past dingen aan. Pas als iedereen tevreden is, gaat de code naar master.

In deze sessie maak je je eerste pull request. Je reviewt die van een buddy. En je ervaart hoe écht teamwerk met Git voelt.

Wat je vandaag leert

  • Wat een pull request is en waarom teams het gebruiken
  • Een PR openen op GitHub
  • Je PR updaten na feedback
  • Een PR van iemand anders reviewen
  • Een PR mergen en de branch opruimen

Stap 0: Voorbereiding: werken in duo’s

Vandaag werk je samen met een buddy. Spreek af wie de auteur is (die de feature bouwt) en wie de reviewer is (die de PR bekijkt). Halverwege wissel je om.

De auteur heeft een GitHub-repo nodig waar de reviewer toegang toe heeft. De makkelijkste manier:

  1. De auteur maakt een repo aan op GitHub (public).
  2. De auteur gaat naar SettingsCollaboratorsAdd people.
  3. De auteur nodigt de reviewer uit met diens GitHub-username.
  4. De reviewer accepteert de uitnodiging (via e-mail of GitHub-notificaties).

Nu kunnen jullie allebei pushen naar dezelfde repo.

Alternatief (zonder collaborator-toegang): de reviewer forkt de repo van de auteur en opent een PR vanaf de fork naar het origineel. Maar vandaag houden we het simpel: directe collaborator-toegang.

Stap 1: Een feature-branch maken en pushen (auteur)

De auteur cloned de repo (als dat nog niet gebeurd is) en maakt een feature-branch:

git clone https://github.com/AUTEUR_USERNAME/ons-samenwerk-project.git
cd ons-samenwerk-project
git switch -c feature/groet-functie

Maak een nieuw bestand:

echo 'def groet(naam):' > groet.py
echo '    return f"Hallo {naam}!"' >> groet.py

Commit en push:

git add groet.py
git commit -m "Add groet functie

Retourneert een begroeting voor de opgegeven naam."
git push -u origin feature/groet-functie

Stap 2: Een pull request openen (auteur)

  1. Ga naar je repo op GitHub.
  2. GitHub toont nu een gele balk: “feature/groet-functie had recent pushes”: klik op Compare & pull request. (Als je de balk niet ziet: klik op het Pull requests-tabblad, dan New pull request, kies base: mastercompare: feature/groet-functie.)
  3. Schrijf een duidelijke titel: “Add groet functie”
  4. Schrijf een beschrijving. Een goede PR-beschrijving heeft drie delen:
## Wat

Een functie `groet(naam)` die een begroeting retourneert.

## Waarom

We hebben een herbruikbare begroeting nodig voor de
gebruikersinterface. Dit voorkomt dat we op meerdere plekken
dezelfde string moeten schrijven.

## Hoe testen

```python
from groet import groet
print(groet("CoderDojo"))  # "Hallo CoderDojo!"
5. Klik **Create pull request**.

Je PR staat nu open. Iedereen met toegang tot de repo kan hem zien. GitHub toont de diff: exact welke regels je hebt toegevoegd (groen) en verwijderd (rood).

## Stap 3: Een PR reviewen (reviewer)

De reviewer opent de PR op GitHub. Dit zijn de stappen van een review:

### 1. Lees de beschrijving

Begrijp je wat deze PR doet? Zo niet, vraag om verduidelijking.

### 2. Bekijk de diff

Klik op het **Files changed**-tabblad. GitHub toont elke gewijzigde regel. Kijk naar:

- **Werkt de code?** Zou je het zelf runnen als je het cloned?
- **Is de stijl consistent?** Dezelfde naamgevingsconventies als de rest van het project?
- **Zijn er fouten?** Typo's, ontbrekende imports, logische fouten?
- **Staan er geen geheimen in?** Wachtwoorden, API-keys, tokens?
- **Is het te begrijpen?** Kan iemand die deze code voor het eerst ziet, volgen wat er gebeurt?

### 3. Geef feedback

Klik op een regel om een comment toe te voegen. Wees specifiek:

**Goeie feedback:**
> In `groet.py` regel 2: wat gebeurt er als `naam` leeg is? Misschien een default-waarde toevoegen?

**Slechte feedback:**
> Dit is niet goed.

### 4. Dien je review in

Klik op **Review changes**. Je hebt drie opties:

- **Comment**: gewoon feedback, geen beslissing.
- **Approve**: de code is goed, mag gemerged worden.
- **Request changes**: er moet iets aangepast worden voor de PR gemerged kan worden.

Bij je eerste review: kies **Approve** als alles er goed uitziet, of **Request changes** als je iets wilt laten aanpassen.

## Stap 4: Feedback verwerken (auteur)

De reviewer heeft een comment achtergelaten. De auteur past de code aan:

```bash
# Zorg dat je op je feature-branch zit
git switch feature/groet-functie

Pas groet.py aan op basis van de feedback. Bijvoorbeeld:

def groet(naam="wereld"):
    return f"Hallo {naam}!"

Commit en push:

git add groet.py
git commit -m "Add default parameter to groet functie"
git push

De nieuwe commit verschijnt automatisch in de PR. De reviewer ziet de update en kan opnieuw kijken.

Stap 5: Mergen en opruimen

Als de reviewer Approved heeft, is het tijd om te mergen.

Op GitHub, in de PR, klik je op Merge pull request. Kies Create a merge commit (de standaardoptie). Klik Confirm merge.

De feature-branch is nu samengevoegd met master. Op GitHub kun je de branch verwijderen met de Delete branch-knop die verschijnt na het mergen.

Lokaal moet je ook opruimen:

git switch master
git pull                      # haal de merge op die net op GitHub gebeurd is
git branch -d feature/groet-functie   # verwijder de lokale branch

Je master is nu up-to-date. Je feature-branch is weg, lokaal én op GitHub. Klaar voor het volgende stuk werk.

De volledige PR-workflow op een rij

1. git switch -c feature/iets        ← Maak een feature-branch
2. Werk, commit, werk, commit
3. git push -u origin feature/iets   ← Push naar GitHub
4. Open een PR op GitHub             ← Vraag om review
5. Reviewer bekijkt, geeft feedback
6. Pas code aan, commit, push        ← Feedback verwerken
7. Reviewer approved
8. Merge de PR op GitHub             ← Code naar master
9. git switch master && git pull       ← Haal master lokaal bij
10. git branch -d feature/iets       ← Ruim de branch op

Een PR van iemand anders reviewen: hoe doe je dat goed?

Een review is niet: “Ziet er goed uit.” Een goeie review is specifiek, constructief en respectvol.

Vragen die je jezelf stelt tijdens een review:

  • Snap ik wat deze code doet? (Zo nee: vraag om betere comments of een duidelijkere beschrijving.)
  • Doet de code wat de PR-beschrijving belooft?
  • Kan dit simpeler?
  • Mist er iets? (Foutafhandeling, edge cases, documentatie)
  • Staan er geheimen, wachtwoorden of persoonlijke data in?
  • Volgt de code de stijl van de rest van het project?

Hoe geef je feedback:

Begin met wat goed is. Wees dan specifiek over wat beter kan. Eindig met een duidelijke conclusie.

Voorbeeld:

De functie werkt precies zoals beschreven. Twee suggesties:

  1. In regel 2: een default-waarde voor naam zou handig zijn.
  2. Overweeg een docstring toe te voegen die uitlegt wat de functie retourneert.

Verder ziet het er goed uit. Als je deze twee dingen aanpast, approve ik hem graag.

Showcase

Wissel van rol met je buddy en doe de hele workflow nog een keer: nu ben jij de reviewer.

Laat aan een coach zien:

  1. Een open pull request op GitHub met een beschrijving.
  2. Minstens één review-comment op een PR van je buddy.
  3. Een succesvol gemergede PR: de feature-code staat nu op master.

Tot de volgende keer!

Dit was de laatste Git-sessie. Wat je nu kunt:

  • Je code versiebeheren met Git (init, add, commit, log, diff)
  • Experimenteren op branches zonder master kapot te maken (branch, switch, merge)
  • Je code online delen via GitHub (push, pull, clone)
  • Professionele commit messages schrijven
  • Samenwerken via pull requests: openen én reviewen

Dit is niet “extra”. Dit is hoe developers élke dag werken. Of je nu games maakt, websites bouwt, of AI traint: Git en GitHub zijn de gereedschappen die je project beheersbaar houden. Gebruik ze.

Neem mee naar huis

  1. Makkelijk: Open een pull request voor een wijziging in een van je eigen projecten.
  2. Middel: Vraag een vriend of familielid om een GitHub-account te maken. Nodig ze uit als collaborator en laat ze een PR reviewen.
  3. Lastig: Draag bij aan een echt open source-project. Zoek op GitHub naar issues met het label good first issue. Fork de repo, maak een fix, en open een PR.
  4. Erg lastig: Bouw een klein project met twee anderen. Gebruik branches, pull requests en reviews. Werk alsof je in een professioneel team zit.
13 juni 2026, 13:30

Sessie 16: Markdown: Schrijf notities die eruitzien als het web

Je kent HTML misschien van het internet: <h1>, <p>, <a>. Maar voor notities en documentatie is HTML veel te veel typwerk. Daar is Markdown voor.

Markdown is een mini-taal die je in gewone tekst schrijft. Het ziet er leesbaar uit zónder dat je het eerst moet omzetten. En met één druk op de knop wordt het nette HTML: koppen, lijsten, links, tabellen.

In deze sessie leer je de hele basis van Markdown. Aan het einde schrijf je notities die er professioneel uitzien, op GitHub, in Obsidian, of in elk ander programma dat Markdown begrijpt.

Wat je vandaag leert

  • Koppen en alinea’s maken
  • Tekst opmaken: vet, cursief, doorstreept
  • Lijsten en opsommingen
  • Links naar andere pagina’s en websites
  • Afbeeldingen invoegen
  • Tabellen maken
  • Horizontale lijnen en codeblokken

Waarom Markdown?

Markdown is overal:

  • GitHub: elke repo heeft een README.md in Markdown. Issues, pull requests, wiki’s: allemaal Markdown.
  • Obsidian, Joplin, Logseq: notitie-apps die je documenten als .md-bestanden opslaan.
  • Discord, Slack, Reddit: ondersteunen Markdown voor snelle opmaak in berichten.
  • Hugo (deze website!): alle sessie-pagina’s die je hier ziet, zijn geschreven in Markdown.
  • Jupyter Notebooks: de tekst-cellen zijn Markdown.

Het grote voordeel: je schrijft gewone tekst. Geen ingewikkelde tags. En het resultaat is altijd leesbaar, ook als platte tekst.

Stap 0: Een Markdown-bestand maken

Markdown-bestanden eindigen op .md. Maak er één:

mkdir mijn-notities
cd mijn-notities
echo "# Mijn Eerste Notitie" > test.md

Je kunt .md-bestanden openen in elke teksteditor: Kladblok, VS Code, Thonny, Obsidian. VS Code heeft een ingebouwde preview: klik rechtsboven op het icoontje met het vergrootglas en het boek.

Stap 1: Koppen en alinea’s

Koppen maak je met #. Hoe meer #, hoe kleiner de kop:

# Dit is een titel (h1)

## Dit is een subtitel (h2)

### Dit is een kleinere kop (h3)

#### Nog kleiner (h4)

Een alinea maak je door gewoon tekst te typen. Een lege regel ertussen start een nieuwe alinea:

Dit is de eerste alinea. Die loopt gewoon door.

Dit is de tweede alinea. Omdat er een lege regel tussen zit.

Tip: één # gebruik je maar één keer per document: voor de titel. De rest begint bij ##.

Stap 2: Tekst opmaken

**Dit is vetgedrukt**

*Dit is cursief*

~~Dit is doorstreept~~

Je kunt ook **vet en *cursief* combineren** in dezelfde zin.

Het resultaat:

  • **vet** wordt vet
  • *cursief* wordt cursief
  • ~~doorstreept~~ wordt doorstreept

Let op: geen spaties tussen de sterretjes en de tekst. ** vet ** werkt niet. **vet** wel.

Sommige editors accepteren ook underscores: __vet__ en _cursief_. Maar sterretjes zijn de standaard: gebruik die.

Stap 3: Horizontale lijnen

Een horizontale lijn maak je met drie (of meer) streepjes:

---

Of met sterretjes:

***

Het resultaat is een lijn over de hele breedte. Gebruik het spaarzaam: één of twee per document is genoeg. Te veel lijnen maken je notities onoverzichtelijk.

Stap 4: Lijsten

Ongenummerde lijst

Gebruik -, * of +:

- Python
- Git
- Markdown
- GitHub

Je kunt lijsten nesten door in te springen (2 of 4 spaties):

- Programmeertalen
  - Python
  - JavaScript
- Versiebeheer
  - Git
  - GitHub

Genummerde lijst

1. Open Thonny
2. Schrijf je code
3. Klik op Run

Het maakt niet uit welke nummers je typt: Markdown nummert automatisch door. Dit:

1. Stap één
1. Stap twee
1. Stap drie

…geeft exact hetzelfde resultaat als 1, 2, 3. Handig als je later een stap wilt toevoegen zonder alles te hernummeren.

Checklist (GitHub-stijl)

- [x] Git installeren
- [x] Eerste commit maken
- [ ] Branches leren
- [ ] Pull request openen

[x] is afgevinkt, [ ] is open. Werkt in GitHub issues, pull requests, en veel notitie-apps.

[klik hier voor de CoderDojo-site](https://python.coderdojohasselt.be)

Het woord tussen [ ] is de klikbare tekst. De URL tussen ( ) is de bestemming.

[Bekijk sessie 11](11-git-intro/)

Dit linkt naar het bestand 11-git-intro/_index.md in dezelfde map.

<https://github.com>

Dit toont de URL als klikbare link, zonder aparte tekst.

Stap 6: Afbeeldingen

Een afbeelding is bijna hetzelfde als een link, maar met een ! ervoor:

![Een ster in Pygame Zero](/sessions/01-catch-the-stars/coordinaten.svg)

De tekst tussen [ ] is de alt-tekst: die verschijnt als de afbeelding niet laadt, of wordt voorgelezen door screenreaders.

Afbeeldingen en Git: Kleine afbeeldingen (SVG, kleine PNG’s) kun je in Git zetten. Grote afbeeldingen (>1 MB) en video’s beter niet, want die maken je repo traag.

Stap 7: Tabellen

| Commando | Wat het doet |
|----------|-------------|
| `git init` | Nieuwe repository maken |
| `git add` | Bestanden klaarzetten voor commit |
| `git commit` | Wijzigingen vastleggen |
| `git push` | Commits naar GitHub sturen |

De | tekens vormen de kolommen. De --- regel scheidt de kop van de data. De : in de scheidingsregel bepaalt uitlijning:

| Links uitgelijnd | Gecentreerd | Rechts uitgelijnd |
|:-----------------|:-----------:|------------------:|
| links            | midden      | rechts            |

Stap 8: Code en codeblokken

Inline code

Gebruik backticks voor korte stukjes code in een zin:

Gebruik `git status` om te zien wat er gewijzigd is.

Codeblokken

Voor meerdere regels code gebruik je drie backticks:

```python
def groet(naam):
    return f"Hallo {naam}!"
```

De taal (python) achter de eerste backticks geeft syntax highlighting. Dit werkt voor tientallen talen: bash, html, css, javascript, json, yaml, markdown.

Codeblok zonder taal

```
Dit is gewoon tekst
zonder syntax highlighting
```

Stap 9: Blockquotes

Gebruik > voor citaten of belangrijke opmerkingen:

> Git is geen back-up. Git is een tijdmachine.
> Iemand op het internet

Meerdere > regels achter elkaar vormen één blok. Een lege > regel start een nieuwe alinea binnen het citaat.

Stap 10: Alles samen: een echte README

Een goed README.md combineert alles wat je nu kent. Hier is een voorbeeld:

# Mijn Project

Een korte beschrijving van wat dit project doet.

## Installatie

```bash
git clone https://github.com/jouw-naam/mijn-project.git
cd mijn-project
```

## Gebruik

1. Open `main.py` in Thonny.
2. Klik op **Run**.
3. Kies een level en start.

## Wat je leert

- [x] Pygame Zero basis
- [x] Collision detection
- [ ] Highscore systeem
- [ ] Geluidseffecten

## Links

- [CoderDojo Hasselt](https://coderdojohasselt.be)
- [Broncode op GitHub](https://github.com/jouw-naam/mijn-project)

Cheatsheet

WatMarkdown
Kop niveau 1# Titel
Kop niveau 2## Subtitel
Kop niveau 3### Kleinere kop
Vet**vet**
Cursief*cursief*
Doorstreept~~doorstreept~~
Horizontale lijn--- of ***
Lijst (ongeordend)- item
Lijst (genummerd)1. item
Checklist- [ ] open item
Link[tekst](url)
Afbeelding![alt tekst](url)
Inline code`code`
Codeblok```taal
Citaat> citaat
Tabel| kolom | kolom |

Showcase

Laat aan een coach en een buddy zien:

  1. Een Markdown-document met minstens één kop, een lijst, een link en vetgedrukte tekst.
  2. Een tabel met minstens twee kolommen en drie rijen.
  3. Een checklist met afgevinkte en open items.

Tot de volgende keer!

Markdown is simpel, maar het is overal. Je README’s op GitHub, je notities in Obsidian, je documentatie: alles wordt leesbaarder met Markdown. Gebruik het. Overdrijf niet met opmaak. Goeie notities zijn helder, niet druk.

Neem mee naar huis

  1. Makkelijk: Schrijf een README.md voor je favoriete Python-project. Gebruik koppen, een lijst en een codeblok.
  2. Middel: Maak een notitie in Obsidian (of een andere Markdown-editor) over wat je deze maand geleerd hebt. Gebruik alle opmaak uit de cheatsheet minstens één keer.
  3. Lastig: Bouw een “cheatsheet”-pagina in Markdown voor een onderwerp naar keuze (Git-commando’s, Python syntax, wiskunde-formules). Gebruik tabellen en geneste lijsten.
  4. Erg lastig: Maak een Markdown-document met een geneste lijst die minstens drie niveaus diep gaat, een tabel met uitlijning, en een codeblok met syntax highlighting.