Ga naar hoofdinhoud

8.10 Pymunk: een botsing detecteren

De bal stuitert op de vloer, maar hoe weet je wanneer dat gebeurt? Bijvoorbeeld om een geluid af te spelen of een score te verhogen? Dat doe je met een collision handler.

Collision types

Elke Shape in pymunk krijgt een collision_type. Dit is een nummer dat je zelf kiest:

bal_shape.collision_type = 1
vloer_shape.collision_type = 2

Een collision handler koppelen

Met space.add_collision_handler() koppel je een functie aan de botsing tussen twee collision types:

def bal_raakt_vloer(arbiter, space, data):
print("Bots!")
return True

handler = space.add_collision_handler(1, 2)
handler.begin = bal_raakt_vloer
  • De functie bal_raakt_vloer wordt aangeroepen zodra collision_type 1 (de bal) collision_type 2 (de vloer) raakt.
  • return True betekent dat de botsing normaal doorgaat (de bal stuitert).
  • handler.begin wordt aangeroepen op het moment dat de botsing begint.

Het volledige programma

import pygame
import pymunk

pygame.init()

scherm = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
font = pygame.font.SysFont("arial", 40)

space = pymunk.Space()
space.gravity = (0, 500)

# Bal (collision_type = 1)
bal_body = pymunk.Body(1, pymunk.moment_for_circle(1, 0, 20))
bal_body.position = (400, 50)
bal_shape = pymunk.Circle(bal_body, 20)
bal_shape.elasticity = 0.8
bal_shape.collision_type = 1
space.add(bal_body, bal_shape)

# Vloer (collision_type = 2)
vloer_body = pymunk.Body(body_type=pymunk.Body.STATIC)
vloer_shape = pymunk.Segment(vloer_body, (0, 550), (800, 550), 5)
vloer_shape.elasticity = 0.8
vloer_shape.collision_type = 2
space.add(vloer_body, vloer_shape)

# Collision handler
aantal_botsingen = 0

def bal_raakt_vloer(arbiter, space, data):
global aantal_botsingen
aantal_botsingen = aantal_botsingen + 1
return True

handler = space.add_collision_handler(1, 2)
handler.begin = bal_raakt_vloer

actief = True

while actief:
for event in pygame.event.get():
if event.type == pygame.QUIT:
actief = False

space.step(1 / 60)

scherm.fill((30, 30, 30))

bal_x = int(bal_body.position.x)
bal_y = int(bal_body.position.y)
pygame.draw.circle(scherm, (0, 200, 255), (bal_x, bal_y), 20)
pygame.draw.line(scherm, (255, 255, 255), (0, 550), (800, 550), 5)

tekst = font.render("Botsingen: " + str(aantal_botsingen), True, (255, 255, 255))
scherm.blit(tekst, (10, 10))

pygame.display.flip()
clock.tick(60)

pygame.quit()

Elke keer dat de bal de vloer raakt, gaat aantal_botsingen omhoog en wordt dit op het scherm getoond.

Opdracht 8.10.a: Kleur veranderen bij botsing

Pas het programma aan zodat de bal van kleur verandert elke keer als hij de vloer raakt. Wissel bijvoorbeeld tussen blauw en rood.

Klik hier voor een tip!

Maak een globale variabele kleur en verander die in de collision handler functie.

Klik hier voor de oplossing!

Voeg bovenaan toe:

kleur = (0, 200, 255)

Pas de collision handler aan:

def bal_raakt_vloer(arbiter, space, data):
global kleur
if kleur == (0, 200, 255):
kleur = (255, 0, 0)
else:
kleur = (0, 200, 255)
return True

En gebruik kleur bij het tekenen:

    pygame.draw.circle(scherm, kleur, (bal_x, bal_y), 20)