4.2 Gebeurtenissen bij een vorm
Hier bouw je op verder: 2.1 Links en rechts bewegen en Functies
Weet je dit niet meer zeker? Lees het terug voordat je verdergaat.
Je hebt al geleerd hoe je programma kan reageren op de gebruiker, bijvoorbeeld als die een toets indrukt. Maar wat als je wilt reageren op gebeurtenissen tussen vormen? Bijvoorbeeld, wat moet er gebeuren als twee objecten elkaar raken? Dat leer je hier.
Om een vorm vanzelf te laten bewegen, met x_speed, heb je fysica nodig. In 2.2 Soorten fysica heb je geleerd over de drie types fysica (dynamic, static, kinematic). Dat komt hier van pas.
Botsen kan elke vorm al, ook een tekst: daar stuitert een bal tegenaan. Wil je dat hij ergens doorheen gaat en je toch when_touching krijgt, maak die vorm dan een sensor.
Voor meer voorbeelden kun je altijd de cheatsheet raadplegen.
Opdracht 4.2.a: Reageren op een botsing
a) de basis
- Maak eerst zelf een blauwe bal, met als naam van de variabele
bal. - Maak daarna een batje met de naam
batjeen plaatst deze aan de rechterkant van het scherm.
Klik hier voor de oplossing.
b) Probeer nu het volgende:
- Laat de bal automatisch naar rechts bewegen
- Zorg dat de bal niet naar beneden valt
- Pas het batje aan zodat die ook niet valt en niet kan bewegen.
- Lukt het om de bal en het batje te laten botsen?
Klik hier voor een tip.
Gebruik start_physics() voor laten bewegen. De eigenschappen x_speed en obeys_gravity kunnen erg nuttig zijn.
Klik hier voor de oplossing.
import play
bal = play.new_circle(color="blue", radius=50)
bal.start_physics(can_move=True, obeys_gravity=False, stable=False, x_speed=40)
batje = play.new_box(x=300)
c) reageren op de botsing Voeg nu het volgende codefragment aan je code toe:
text = play.new_text('batje is niet aangeraakt', y=200, font_size=50)
@bal.when_stopped_touching(batje)
def weggekaatst():
text.words = 'bal is weggekaatst van batje'
De event-decorator
Wat is die regel met de @ ervoor?
De @... regel heet een event-decorator. Deze laat de functie die er direct onder staat één keer afgaan als de specifieke gebeurtenis plaatsvindt.
De algemene vorm is:
@vorm1.when_..._touching(vorm2)
def doe_iets():
# reactie op gebeurtenis
In ons voorbeeld:
@bal.when_stopped_touching(batje)
def weggekaatst():
text.words = 'bal is weggekaatst van batje'
Hier laat @bal.when_stopped_touching(batje) de functie weggekaatst één keer afgaan op het moment dat bal ophoudt batje te raken (dus precies bij de overgang van wel aanraken naar niet meer aanraken). De code binnen weggekaatst wordt dan uitgevoerd.
Let op:
- bal wijst hier naar de variabele
bal. Deze variabele wijst naar de gemaakte cirkel. - batje wijst hier naar de variabele
batje. Deze variabele wijst naar het gemaakte batje.
Als onze bal dus botst tegen ons batje en weer terugkaatst, vindt deze gebeurtenis plaats.
Een vorm raakt een muur
Niet alleen botsingen tussen vormen kun je detecteren — ook het raken van de rand van het scherm. Daarvoor gebruik je @vorm.when_touching_wall.
Zodra de bal een muur raakt, wordt hij rood. Net zoals @bal.when_touching(batje) werkt dit als een event-decorator — de functie wordt één keer uitgevoerd bij het raken.
Een specifieke muur kiezen
Vaak wil je weten welke muur de vorm raakt. Bijvoorbeeld bij Pong scoort de rechterspeler een punt als de bal de linkermuur raakt, en andersom. Daarvoor geef je wall=play.WallSide.LEFT (of RIGHT, TOP, BOTTOM) mee:
De bal wordt rood bij de linkermuur en groen bij de rechtermuur. Boven- en ondermuur veranderen niets.
Opdracht 4.2.b: Tel hoe vaak de bal stuitert
Pas de code hierboven aan zodat:
- Een tekst op het scherm bijhoudt hoe vaak de bal de bovenmuur raakt.
- Andere muren niet meetellen.
Klik hier voor een tip.
Gebruik play.WallSide.TOP, een global-variabele voor de teller (zie 4.5 Een score bijhouden), en play.new_text om de teller te tonen.