Hoofdstuk 4 Javalogo
4.3 Interactie
4.3.1. Tekst op een applet
Je hebt al gezien hoe je tekeningen met Javalogo kunt maken. Je kunt ook tekst bij zo'n tekening plaatsen.
De opdracht daarvoor is:
schrijf("tekst");
Als je bijvoorbeeld een vierkant wilt tekenen, en je wilt het woord vierkant er onder hebben, dan kan dat als volgt:
(We geven alleen de methode tekenprogramma, de header enz. moet je zelf even toevoegen.
void tekenprogramma()
{
penAan();
for (int i=1;i<=4;i++)
{
vooruit(40);rechts(90);
}
penUit();
stap(0,-50); schrijf("vierkant");
}
Je kunt het lettertype enz. van de tekst ook nog aangeven. Dan wordt het wel iets ingewikkelder.
De opdracht daarvoor is:
schrijf("tekst", lettertype);
Maar dat lettertype moet je nog op een bepaalde manier aangeven.
- Je moet bovenaan, op de regel na import logotekenap.*;, invoeren:
import java.awt.Font;
Er is namelijk een submap met de naam awt van de map waarin Java geïnstalleerd is, en in die map awt zit een klasse
met de naam Font. En die klasse bavat de definities van de lettertypen, en die worden dan ingelezen.
- Het lettertype moet in een variabele worden opgeslagen, en die variabele moet je declareren.
Dat gebeurt meestal op de eerste regel van de body van de klasse, dus na de regel public class Programmanaam extends TekenApplet
Daar tik je de volgende opdracht in: Font f;
- In de methode initialiseer moet je aangeven welk lettertype enz. je wilt gebruiken.
Daar zet je bijvoorbeeld de volgende opdracht neer: f=new Font("Dialog",Font.BOLD, 25);
Achter Font staan drie dingen (dat noem je de argumenten):
- eerst de naam van het lettertype
(je kunt niet alle lettertypen in Java gebruiken, maar TimesRoman, Courier, Dialog en Serif kun je in ieder geval gebruiken)
- dan Font.PLAIN (=normaal) of
Font.BOLD (=vet) of Font.ITALIC (=cursief) of Font.BOLD + Font.ITALIC (= vet en cursief)
- dan de lettergrootte.
Als je bijvoorbeeld een vierkant wilt tekenen, en je wilt het woord vierkant er met grote letters en cursief onder hebben,
dan kan dat als volgt:
import logotekenap.*;
import java.awt.Font;
public class Opdracht1 extends TekenApplet
{
Font f;
public void initialiseer()
{
f=new Font("TimesRoman",Font.ITALIC,50);
}
public void tekenprogramma()
{
for (int i=1;i<=4;i++)
{
vooruit(40);rechts(90);
}
penUit();
stap(0,-50);
schrijf("vierkant",f);
}
}
Probeer het maar eens uit.
4.3.2. Animaties
Je kunt met Javalogo ook gemakkelijk bewegende beelden maken, een animatie wordt dat genoemd.
Een bewegend beeld bestaat eigenlijk (net als een film) uit heel veel tekeningen, die snel na elkaar getoond worden.
Als je een animatie wilt maken, bijvoorbeeld een draaiend vierkant, dan doe je dat op de volgende manier:
- In de methode initialiseer zet je de opdracht:
maakAnimatieMogelijk();
Die opdracht zorgt er voor dat er een knop boven de tekening verschijnt waar animatie op staat, en als je daar op
klikt gebeurt er iets.
- Je moet een methode met de naam animatie toevoegen.
En die methode ziet er als volgt uit:
public void animatie()
{ while( animatieLopend() )
{ h=h+1; // Dit kan ook een andere opdracht zijn
tekenOpnieuw();
}
}
Dit betekent het volgende:
while( animatieLopend() ) betekent:
Zolang de animatieknop is ingedrukt (dat wil zeggen: als er op de knop met het woord animatie is geklikt rekenen we dat
de animatieknop is ingedrukt, en als er voor de tweede keer op die knop geklikt wordt is hij niet meer ingedrukt) wordt de programmacode,
die er tussen accolades op volgt, uitgevoerd.
h = h +1; :
h is de naam van de variabele, die wordt gebruikt voor de hoek waarover de tekening gedraaid is.
En h = h +1; heeft tot gevolg dat er één graad bij die hoek wordt opgeteld.
tekenOpnieuw(); :
Deze opdracht heeft tot gevolg dat de methode tekenprogramma opnieuw wordt uitgevoerd, dus dat de tekening opnieuw wordt gemaakt,
maar nu een graad extra gedraaid.
En zo gaat dat steeds door. De snelheid waarmee de tekeningen elkaar opvolgen heb je zelf niet in de hand, dat wordt door Java bepaald.
Toch kun je de snelheid, waarmee de tekening draait, wel beïnvloeden.
Want als je in plaats van h = h + 1; de opdracht h = h + 2; geeft, dan wordt de figuur steeds twee graden gedraaid.
En dan draait de tekening eigenlijk twee keer zo snel.
Ent als je in plaats van h = h + 1; de opdracht h = h + 0.1; geeft, dan wordt er steeds over 0,1 graad gedraaid. En dan
gaat het dus veel langzamer.
(in dat geval moet je er wel voor zorgen dat de variabele h als kommagetal wordt gedeclareerd, dus de declaratie wordt dan
double h=0;
- In de methode tekenprogramma is de eerste opdracht:
rechts(h);
Dat heeft tot gevolg dat de tekening over de hoek h draait.
Als je niet wilt dat de tekening draait, maar bijvoorbeeld naar rechts schuift, dan kun je daar de opdracht
stap(h,0);
neerzetten (voorafgegaan door penUit();, anders wordt de verschuiving door een lijntje aangegeven)
Of met de opdracht stap(0,h); schuift de tekening omhoog.
Met die opdracht kun je dus bepalen wat er gebeurt. Je kunt de figuur ook linksom laten draaien, of in een andere richting laten verschuiven.
Je kunt ook laten draaien en verschuiven tegelijk.
- De variabele h moet wel gedeclareerd worden, en die moet in het begin de waarde 0 krijgen.
Dat doe je in de eerste regel van de body van de klasse, daar zet je de volgende opdracht neer:
int h = 0;
Het programma voor een draaiend vierkant ziet er dus zo uit, proberen maar!
import logotekenap.*;
public class Opdracht1 extends TekenApplet
{ int h=0;
public void initialiseer()
{ maakAnimatieMogelijk(); }
public void tekenprogramma()
{ rechts(h);vierkant(200); }
public void vierkant(int z)
{ vulAan("groen");
for (int i=1;i<=4;i++) {vooruit(z);rechts(90);}
vulUit();
}
public void animatie()
{ while( animatieLopend() )
{ h=h+1;
tekenOpnieuw();
}
}
}
Je kunt ook twee of meer figuren tegelijk laten draaien.
Tenminste, het lijkt alsof ze tegelijk draaien.
Je laat dan twee of meer figuren achter elkaar tekenen, en die worden, na over een bepaalde hoek gedraaid te zijn, steeds weer getekend.
In onderstaand programma wordt, door de opdrachten rechts(h);vierkant(200); in de methode
tekenprogramma een vierkant getekend dat over hoek h gedraaid is.
Door de opdracht vooruit(200); loopt de cursor naar het hoekpunt rechtsonder (in de
beginstand).
En door de opdrachten rechts(2*h);vierkant(50); wordt bij dat hoekpunt een kleiner vierkant
getekend (met zijde 50) dat over de hoek 2*h gedraaid is.
Door de animatie draait het grote vierkant, en het kleinere vierkant draait twee keer zo snel om een hoekpunt van het grote.
Probeer het maar eens uit.
import logotekenap.*;
public class Opdracht1 extends TekenApplet
{ int h=0;
public void initialiseer()
{ maakAnimatieMogelijk(); }
public void tekenprogramma()
{ rechts(h);vierkant(200);
vooruit(200);rechts(2*h);vierkant(50); }
public void vierkant(int z)
{ vulAan("groen");
for (int i=1;i<=4;i++) {vooruit(z);rechts(90);}
vulUit();
}
public void animatie()
{ while( animatieLopend() )
{ h=h+1;
tekenOpnieuw();
}
}
}
Opgaven. Maak nu opgave 1 van opgaven 4.3 (JavaLogo)
4.3.3. Voorwaardelijke opdracht
Je hebt bij de vorige opdracht misschien gemerkt, dat als je het vierkant laat verschuiven, het na een poosje uit beeld verdwijnt.
Als het vierkant te veel naar rechts verschuift verdwijnt het uit beeld.
Je kunt er voor zorgen dat dat niet gebeurt. Je kunt er bijvoorbeeld voor zorgen dat het vierkant blijft staan als het aan de rand
komt. Of dat het dan weer naar links verschuift, en dat het steeds heen en weer gaat.
In de methode animatie staat nu de opdracht h = h + 1
Als de methode tekenprogramma begint met de opdracht stap(h,0) dan heeft dat tot gevolg dat de figuur steeds 1 mm
opschuift.
Maar als h te groot wordt, als h bijvoorbeeld groter dan 250 is, dan past de figuur er niet meer op.
Als je de opdracht h = h + 1 vervangt door het volgende:
if (h < 250) { h = h + 1 }
dan zal de figuur alleen opschuiven als h kleiner dan 250 is, en anders gebeurt er niets, dus dan blijft de figuur staan.
Als je wilt dat de figuur heen en weer gaat, dan heb je nog een extra variabele nodig.
Je hebt een variabele nodig die onthoudt of de figuur naar rechts moet bewegen of naar links.
Die variabele zouden we richting kunnen noemen, en we zouden kunnen afspreken dat als de figuur naar rechts beweegt richting
de waarde 1 heeft, en als de figuur naar links beweegt richting de waarde -1 heeft.
Als h te groot wordt, als h bijvoorbeeld groter dan 250 is, dan moet de figuur van richting veranderen. Dan moet hij naar links
gaan, dus vanaf dat moment geldt dat richting de waarde -1 heeft.
Als h te klein wordt, als h bijvoorbeeld kleiner dan -250 is, dan moet de figuur ook van richting veranderen. Dan moet hij weer naar
rechts gaan, dus vanaf dat moment geldt dat richting de waarde 1 heeft.
Als de figuur naar rechts gaat, dus als richting de waarde 1 heeft, dan moet er bij h één worden opgeteld.
En anders gaat de figuur naar links, en dan moet er van h één worden afgetrokken.
Dat kun je zo programmeren in de methode animatie:
{if (h>250) { richting=-1;}
if (h<-250) { richting=1;}
if (richting = = 1) { h=h+1;} else { h=h-1;}
tekenOpnieuw();
Denk er om:
Als de richting 1 is dan ............ en anders ............ programmeer je zo:
if (richting = = 1) { ............ } else { ............ }
Denk om de dubbele = ( in richting = = 1), na een if-opdracht!
Denk er ook om dat je de variabele richting moet declareren, en dat hij bij de start de waarde 1 moet
krijgen omdat de figuur eerst naar rechts moet bewegen.
Het totale programma ziet er dan zo uit, proberen maar!
import logotekenap.*;
public class Opdracht2 extends TekenApplet
{ int h=0;
int richting=1;
public void initialiseer()
{ maakAnimatieMogelijk(); }
public void tekenprogramma()
{ penUit();stap(h,0);vierkant(200); }
public void vierkant(int z)
{ vulAan("groen");
for (int i=1;i<=4;i++) {vooruit(z);rechts(90);}
vulUit();
}
public void animatie()
{ while( animatieLopend() )
{ if (h>250) { richting=-1;}
if (h<-250) { richting=1;}
if (richting==1) { h=h+1;} else { h=h-1;}
tekenOpnieuw();
}
}
}
Opgaven. Maak nu opgave 2 van opgaven 4.3 (JavaLogo)
4.3.4. Invoervariabelen
Tot nu toe hebben we de figuren in Javalogo steeds met vaste afmetingen gemaakt.
Je kunt er ook voor zorgen dat er, terwijl het programma loopt, kan worden aangegeven wat de afmetingen moeten zijn.
En dat daarna de figuur met de ingevoerde afmetingen wordt getekend.
Als je wilt kunnen invoeren wat de afmetingen zijn, dan moet je met een zogenaamde invoervariabele
werken.
Stel je voor dat je een vierkant wilt laten tekenen, en dat er met behulp van een invoervariabele kan worden aangegeven wat
de zijde van het vierkant is, dan kun je er voor zorgen dat die invoervariabele er uitziet zoals hieronder:
Dan kun je een getal in het invulvakje intypen, of je kunt het getal veranderen door op de pijltjes te klikken.
Een invoervariabele is dus een hele andere variabele dan we totnutoe gebruikt hebben.
Een variabele kan een getal zijn (gehele getallen: int, of kommagetallen: double), het kan ook een woord
zijn (in Java wordt dat een String genoemd).
Maar een variabele kan ook een figuur zijn waar je iets mee kunt doen, bijvoorbeeld een invulvakje met pijltjes, en een woord erboven
(dat is dus een InvoerVariabele).
Zo'n variabele wordt in het algemeen een object genoemd.
En Java wordt daarom ook wel een object-geöriënteerde programmeertaal genoemd.
Als je zo'n invoervariabele gebruikt in je programma, dan moet je die ook declareren.
Dat doe je bijvoorbeeld als eerste opdracht in de body van de klasse, dus zo:
InvoerVariabele v;
Verder moet het programma precies weten hoe die invoer-figuur er uit ziet, het object moet gemaakt worden.
Dat doe je bijvoorbeeld als eerste opdracht in de body van de methode initialiseer, en wel zo:
v = new InvoerVariabele ("zijde", 1, 250, 100);
Dit noem je een constructor.
Een constructor bevat altijd het woordje new, en daarachter nog eens de naam van het object.
Dan wordt er een nieuw object gemaakt.
Achter new Invoervariabele staan tussen de haakjes vier argumenten.
- Het eerste woord, in dit geval zijde verschijnt boven het invulvak.
- Het tweede argument, een getal, geeft aan wat de kleinste waarde van het invulvak mag zijn.
- Het derde argument, een getal, geeft aan wat de grootste waarde van het invulvak mag zijn.
- Het vierde argument, een getal, geeft aan wat er bij de start in het invulvak zal staan.
Als je die opdracht hebt gegeven, dan wordt het object in het werkgeheugen gemaakt, maar het verschijnt nog niet op het scherm.
Daarvoor moet je nog een speciale opdracht geven, namelijk:
maakZichtbaar(v);
Je moet ook nog een variabele gebruiken voor de zijde, die noemen we hier maar z.
En z moet de waarde krijgen die in het invoervak is ingevoerd.
Je moet nog een aantal dingen intikken om er voor te zorgen dat het programma doet wat je wilt.
Alles op een rijtje:
-
Op de eerste regel na de header van het programma zet je:
int z;
InvoerVariabele v;
Hiermee worden de variabelen gedeclareerd.
-
In de methode initialiseer zet je de opdrachten:
v = new InvoerVariabele ("zijde", 1, 250, 100);
maakZichtbaar(v);
z=100;
Die opdrachten zorgen er dus voor dat er een invoervak verschijnt, en dat z de startwaarde 100 krijgt.
- Je moet een methode met de naam invoerVarActie(InvoerVariabele iv) toevoegen.
En die methode ziet er als volgt uit:
public void invoerVarActie(InvoerVariabele iv)
{ z = v.geefWaarde();
tekenOpnieuw();
}
}
Deze methode wordt automatisch uitgevoerd als er iets in het invoervak is ingevoerd.
De variabele z krijgt dan de waarde die is ingevoerd in het invulvak, dat is een gevolg van de opdracht:
z = v.geefWaarde();
En de opdracht tekenOpnieuw(); heeft tot gevolg dat de methode tekenprogramma opnieuw wordt
uitgevoerd, dus dat de tekening opnieuw wordt gemaakt, maar nu met de nieuwe waarde van z.
- Je moet er wel voor zorgen dat in de methode tekenprogramma een vierkant wordt getekend waarvan de zijde niet met
een vast getal wordt aangegeven, maar met de variabele z
Hierboven is vermeld dat de methode invoerVarActie(InvoerVariabele iv) automatisch wordt uitgevoerd als er iets in het invoervak
is ingevoerd.
Zo'n methode wordt een event handler genoemd.
De computer controleert steeds of er iets gebeurt met het invoervak, en als dat zo is dan wordt de methode uitgevoerd.
Deze methode bepaalt dus hoe er gehandeld moet worden bij een bepaalde gebeurtenis (engels: event), daarom heet het event handler.
Het programma, waarin je de grootte van de zijde zelf in kunt voeren ziet er dus uit zoals hier onder, proberen maar!
import logotekenap.*;
public class Opdracht3 extends TekenApplet
{ int z;
InvoerVariabele v;
public void initialiseer()
{ v = new InvoerVariabele("zijde", 1 ,250 , 100);
maakZichtbaar(v);
z=100;
}
public void tekenprogramma()
{ vulAan("groen");
for (int i=1;i<=4;i++) {vooruit(z);rechts(90);}
vulUit();
}
public void invoerVarActie(InvoerVariabele iv)
{ z = v.geefWaarde();
tekenOpnieuw();
}
}
Opgaven. Maak nu opgave 3 van opgaven 4.3 (JavaLogo)
4.3.5. Meer invoervariabelen en schuifinvoervariabelen
We gaan nu een programma maken waarin drie invoervariabelen voorkomen.
We gaan een programma maken, waarin je de hoeveelheid rood, groen en blauw aan kunt geven, en waarbij je dan de mengkleur
krijgt te zien.
We moeten dus een invoervariabele hebben voor de hoeveelheid rood, en één voor de hoeveelheid groen,
en één voor de hoeveelheid blauw.
En ook integer-variabelen, voor die hoeveelheden.
Dan moet je dus de volgende dingen programmeren:
- Je moet de invoervariabelen eerst declareren, en ook de integer-variabelen.
Dat doe je in de eerste regels van de body van de klasse:
InvoerVariabele invoerrood;
InvoerVariabele invoergroen;
InvoerVariabele invoerblauw;
int r;
int g;
int b;
- Verder moeten de invoervariabelen gemaakt worden, en ze moeten zichtbaar worden.
En de variabelen r, g en b moeten beginwaarden krijgen (dat kun je trouwens ook tegelijk met de declaratie doen).
Dat doe je in de eerste opdrachten van de body van de methode initialiseer:
invoerrood = new InvoerVariabele("rood", 0 ,255 , 100);
maakZichtbaar(invoerrood);
invoergroen = new InvoerVariabele("groen", 0 ,255 , 100);
maakZichtbaar(invoergroen);
invoerblauw = new InvoerVariabele("blauw", 0 ,255 , 100);
maakZichtbaar(invoerblauw);
r=100;
g=100;
b=100;
-
Je moet een methode met de naam invoerVarActie(InvoerVariabele v) toevoegen.
Deze methode geldt voor alle invoervakken tegelijk.
Deze methode wordt automatisch uitgevoerd als er iets in één van de invoervakken is ingevoerd.
Maar wat er dan moet gebeuren hangt er wel van af in welk van de drie invoervakken iets is ingevoerd.
Als de invoervariabele de rode was, dan moet r de waarde van dat invoervak krijgen.
Dat programmeer je zo:
if (v==invoerrood) {r = invoerrood.geefWaarde();}
Je gebruikt de letter v omdat dat de letter is die gebruikt wordt voor de parameter van de invoervariabele, die staat tussen de
haakjes achter de naam van de methode).
Als de invoervariabele de groene was, dan moet g de waarde van dat invoervak krijgen.
Dat programmeer je zo:
if (v==invoergroen) {g = invoergroen.geefWaarde();}
En voor de blauwe krijg je dan natuurlijk:
if (v==invoerblauw) {b = invoerblauw.geefWaarde();}
Verder moet de opdracht tekenOpnieuw(); worden toegevoegd.
Die opdracht heeft tot gevolg dat de methode tekenprogramma opnieuw wordt
uitgevoerd, dus dat de tekening opnieuw wordt gemaakt, maar nu met de nieuwe waarden van r, g en b.
- Je moet er voor zorgen dat in de methode tekenprogramma een vierkant wordt getekend, die wordt ingekleurd
met de opdrachten vulAan(r,g,b); en vulUit;
In plaats van invoervariabelen kun je ook zogenaamde schuifinvoervariabelen gebruiken.
Dan kun je de invoer wijzigen door te schuiven, in plaats van met pijltjes.
Je krijgt dan een figuur zoals hier onder.
Je moet bij de code gewoon overal het woordje Schuif voor invoervariabele zetten, het werkt verder net zo.
Het complete programma m.b.v. schuifinvoervariabelen volgt hier onder.
import logotekenap.*;
public class Opdracht4 extends TekenApplet
{ int r=100;
int g=100;
int b=100;
SchuifInvoerVariabele invoerrood;
SchuifInvoerVariabele invoergroen;
SchuifInvoerVariabele invoerblauw;
public void initialiseer()
{ invoerrood = new SchuifInvoerVariabele("rood",0,255,100);
maakZichtbaar(invoerrood);
invoergroen = new SchuifInvoerVariabele("groen",0,255,100);
maakZichtbaar(invoergroen);
invoerblauw = new SchuifInvoerVariabele("blauw",0,255,100);
maakZichtbaar(invoerblauw);
}
public void tekenprogramma()
{ penAan();
vulAan(r,g,b);
for (int i=1;i<=4;i++) {vooruit(200);rechts(90);}
vulUit();
}
public void schuifInvoerVarActie(SchuifInvoerVariabele v)
{ if (v==invoerrood) {r = invoerrood.geefWaarde();}
if (v==invoergroen) {g = invoergroen.geefWaarde();}
if (v==invoerblauw) {b = invoerblauw.geefWaarde();}
tekenOpnieuw();
}
}
Hieronder kun je het programma uitproberen, je kunt de rgb-kleuren instellen met behulp van de rode schuifjes.
Opgaven. Maak nu opgave 4 van opgaven 4.3 (JavaLogo)
4.3.6. Slepen met de muis
Je kunt er ook voor zorgen dat een figuur versleept kan worden met de muis.
De computer moet dan steeds controleren of er iets met de muis gebeurt.
En als de muis wordt versleept, dan moet hij iets doen, en daarvoor moet een event handler geprogrammeerd worden.
Als je er voor wilt zorgen dat je een figuur met de muis kunt verslepen, dan doe je dat op de volgende manier:
- In de methode initialiseer zet je de opdracht:
maakMuisActieMogelijk();
Die opdracht zorgt er voor dat de computer steeds controleert of er misschien iets met de muis gebeurt. En als er iets met de muis
wordt gedaan onderneemt hij een bepaalde actie. En welke actie, dat lees je bij het volgende punt.
- Je moet een methode met de naam muisSleepActie() toevoegen.
En die methode ziet er als volgt uit:
public void muisSleepActie()
{ x = x + geefSleepdx();
y = y + geefSleepdy();
tekenOpnieuw();
}
Dit betekent het volgende:
x is de naam van de variabele, die wordt gebruikt om aan te geven hoeveel de figuur in de x-richting verschoven moet worden.
y is de naam van de variabele, die wordt gebruikt om aan te geven hoeveel de figuur in de y-richting verschoven moet worden.
x = x + geefSleepdx();
heeft tot gevolg dat er bij de waarde van x zoveel wordt opgeteld als aangegeven met de muis.
geefSleepdx(); is namelijk het aantal mm. waarover de muis in de x-richting is bewogen.
Hetzelfde gebeurt natuurlijk met de y-richting.
En de opdracht tekenOpnieuw(); heeft tot gevolg dat de methode tekenprogramma opnieuw wordt
uitgevoerd, dus dat de tekening opnieuw wordt gemaakt, maar op een andere plaats.
- In de methode tekenprogramma is de eerste opdracht:
penUit(); stap(x,y);
Met die opdracht zorg je er voor dat de figuur x naar rechts en y naar boven verschuift (of naar links en/of beneden bij negatieve
waarden van x en/of y).
- De variabelen x en y moeten wel gedeclareerd worden, en die moeten in het begin de waarde 0 krijgen.
Dat doe je in de eerste regel van de body van de klasse, daar zet je de volgende opdrachten neer:
double x = 0;
double y = 0;
Het programma, waarmee je een vierkant kunt verslepen, ziet er dus uit zoals hier onder, proberen maar!
import logotekenap.*;
public class Opdracht5 extends TekenApplet
{ double x=0;
double y=0;
public void initialiseer()
{ maakMuisActieMogelijk();
}
public void tekenprogramma()
{ penUit(); stap(x,y);
penAan("groen");
vulAan("groen");
for (int i=1;i<=4;i++) {vooruit(200);rechts(90);}
vulUit();
}
public void muisSleepActie()
{ x = x + geefSleepdx();
y = y + geefSleepdy();
tekenOpnieuw();
}
}
Opgaven. Maak nu opgave 5 van opgaven 4.3 (JavaLogo)
4.3.7 Driedimensionale figuren.
Je kunt met JavaLogo ook driedimensionale figuren tekenen. Daar zijn speciale tekenopdrachten voor.
Dan moet je wel de klasse TekenApplet3D importeren, want die klasse bevat de methoden voor het 3D-tekenen.
In de drie-dimensionale ruimte heb je drie coördinaatassen, een x-as, een y-as en een z-as.
In JavaLogo wijst de x-as naar rechts (net zo als in het platte vlak), de y-as wijst naar boven (ook net zo als in het platte vlak),
en de z-as staat loodrecht op het vlak van tekening en wijst naar achteren.
Je kunt onder andere de volgende 3D-opdrachten gebruiken:
stapx(100) | de turtle gaat 100 mm. in de x-richting (naar rechts), en tekent daarbij een lijntje
| stapy(-50) | de turtle gaat 50 mm. in de y-richting (naar beneden, door
de min), en tekent daarbij een lijntje
| stapz(100) | de turtle gaat 100 mm. in de z-richting (naar achteren),
en tekent daarbij een lijntje
| stap(40, 50, 80) | de turtle gaat 40 mm. in de x-richting,
50 mm. in de y-richting, en 80 mm. in de z-richting en tekent daarbij een lijntje van beginpunt naar eindpunt
| xdraai(90) | de turtle draait 90 graden om de x-as. De positieve y-as draait
daarbij naar de positieve z-as
| ydraai(60) | de turtle draait 60 graden om de y-as.
| zdraai(100) | de turtle draait 100 graden om de z-as.
| vooruit(40) | de turtle gaat 40 mm vooruit, in de richting
waarin de turtle wijst.
| penAan(); | de pen wordt op het papier gezet
| vulAan("rood"); | zelfde als bij tweedimensionaal tekenen
|
Als je bijvoorbeeld een kubus met een zijde van 100 mm wilt laten tekenen, dan ga je alle zijvlakken apart laten tekenen (en
eventueel inkleuren).
- De opdrachten, die je moet geven om het voorvlak te tekenen, zijn de volgende:
stapy(100); stapx(100); stapy(-100); stapx(-100);
Kijk maar in de figuur hieronder wat er gebeurt.
- Wil je de figuur ook nog inkleuren dan moet je nog twee opdrachten toevoegen, net zo als bij tweedimensionaal tekenen.
De opdrachten, die je moet geven om het voorvlak te tekenen en in te kleuren, zijn als volgt:
vulAan("rood");
stapy(100); stapx(100); stapy(-100); stapx(-100);
vulUit();
- Bij het inkleuren moet je er om denken dat een vlak twee kanten heeft, een binnenkant en een buitenkant.
Er wordt bij de inkleur-opdracht maar één kant ingekleurd, en de volgorde van de stappen bij het tekenen bepaalt welke
kant gekleurd wordt. Welke kant dat is kun je bepalen met de omgedraaide kurketrekkerregel (of linksdraaiende schroef):
Als je een linksdraaiende schroef draait in de tekenrichting, dan gaat die schroef in een bepaalde richting.
En de zijkant die correspondeert met die richting wordt ingekleurd.
Als je dus bij een bepaald zijvlak merkt dat het niet wordt ingekleurd, dan moet je de volgorde van de tekenopdrachten omdraaien!
De opdrachten, die je moet geven om ook de binnenkant van het voorvlak in te kleuren (dat is vooral belangrijk als het voorvlak wordt
opengeklapt, zie verderop), zijn als volgt:
vulAan("rood");
stapx(100); stapy(100); stapx(-100); stapy(-100);
vulUit();
-
De opdrachten, die je moet geven om het benedenvlak te tekenen, zijn de volgende:
stapx(100); stapz(100); stapx(-100); stapz(-100);
Kijk maar in de figuur hieronder om het te controleren:
- Je moet er ook om denken dat, als je een kubus tekent, je het assenstelsel een beetje moet draaien.
Je moet bijvoorbeeld beginnen met de opdrachten xdraai(30); ydraai(30);.
Als je dat niet doet dan zie je alleen het voorvlak van de kubus (dus een vierkant) omdat je er recht tegen aan kijkt.
- Je kunt de kubus ook laten draaien. Dan moet je voor een animatie kiezen, en dan laat je bijvoorbeeld om de y-as draaien.
Je begint dan de teken-methode met de opdracht draaiy(h), en in de animatie-methode zet je h = h + 1
Het programma, waarmee je een kubus tekent en laat draaien, ziet er dus uit zoals hier onder, proberen maar!
(zorg er wel voor dat je in de map classes, die bij de opdracht hoort, nog een map met de naam logotekenap3d plaatst,
met een aantal bestanden.
Die bestanden kun je downloaden door te klikken op logotekenap3d.zip downloaden
Dat bestand moet je uitpakken en de inhoud ervan moet je in een submap van de map classes (die op
zijn beurt weer een submap van de opdrachtenmap is), die je logotekenap3d moet noemen, zetten.)
import logotekenap3d.*;
public class Kubus extends TekenApplet3D
{
int h=30;
public void initialiseer()
{
maakAnimatieMogelijk();
}
public void tekenprogramma()
{ xdraai(30); ydraai(h);
//voorvlak
vulAan("oranje");
stapy(100);stapx(100);stapy(-100);stapx(-100);
vulUit();
//benedenvlak
vulAan("blauw");
stapx(100);stapz(100);stapx(-100);stapz(-100);
vulUit();
//linkervlak
vulAan("groen");
stapz(100);stapy(100);stapz(-100);stapy(-100);
vulUit();
//tussenstap naar rechts
stapx(100);
//rechtervlak
vulAan("geel");
stapy(100);stapz(100);stapy(-100);stapz(-100);
vulUit();
//tussenstap naar achteren
stapz(100);
//achtervlak
vulAan("zwart");
stapy(100);stapx(-100);stapy(-100);stapx(100);
vulUit();
//tussenstap naar boven
stapy(100);
//bovenvlak
vulAan("rood");
stapz(-100);stapx(-100);stapz(100);stapx(100);
vulUit();
}
public void animatie()
{ while( animatieLopend() )
{ h=h+1;
tekenOpnieuw();
}
}
}
En als je dit programma uitvoert dan kun je een driedimensionale kubus laten draaien!
Opgaven. Maak nu opgave 6 en 7 van opgaven 4.3 (JavaLogo)
4.3.8. Reageren op klikken met de muis
Je hebt in paragraaf 6 gezien hoe je er voor kunt zorgen dat een figuur versleept kan worden met de muis.
Het maakte bij dat programma niets uit waar je klikte met de muis, voordat je ging verslepen.
Je kunt er ook voor zorgen dat het wel uitmaakt waar je klikt als je begint met het verslepen van de muis.
Je kunt er bijvoorbeeld voor zorgen dat, als je op het bovenvlak van de kubus klikt, en je versleept de muis, het bovenvlak gaat
draaien. Dan lijkt het net alsof het deksel van de kubus open gaat.
En als je bijvoorbeeld op het voorvlak klikt, en je versleept de muis, het voorvlak gaat draaien.
Als je er voor wilt zorgen dat er, bij het verslepen van de muis, iets gebeurt dat afhangt van de plaats van de muiscursor op het moment
dat er werd geklikt, dan moet je daar een aantal dingen voor regelen.
- Je moet er voor zorgen dat het programma de vlakken, die belangrijk zijn voor het klikken, kan herkennen.
Ze moeten een naam krijgen, en dat kan met behulp van een bepaald type variabele: Polygon
In het programma van deze paragraaf werken we met twee vlakken, die noemen we vlak1 (dat is het voorvlak) en vlak2 (dat is het bovenvlak)
- Je zorgt er voor dat het programma weet welke naam bij welk vlak hoort door, na het inkleuren van het bepaalde vlak (dus na de opdracht
vulUit() ), de opdracht vlak1 = geefVlak() (als je het vlak de naam vlak1 geeft,
die naam mag je zelf bedenken) te geven.
- De variabele Polygon, en de methode geefVlak() (en de methode contains(x,y) die nog volgt), mag je alleen gebruiken als je de
klasse Polygon importeert. Daarom moet bovenin het programma de opdracht import
java.awt.Polygon; worden toegevoegd.
- Verder moet het programma weten of er op vlak1 geklikt is, of op vlak2, of op vlak3, of op geen van allen.
Daarvoor gebruik je weer een ander type variabele: boolean.
Zo'n variabele kan maar twee waarden hebben: true en false (dus waar en niet waar).
In het programma van deze paragraaf werken we met twee van zulke variabelen, die noemen we gekliktop1 (die heeft de waarde true
als er met de muis op vlak1 is geklikt) en gekliktop2 (die heeft de waarde true
als er met de muis op vlak2 is geklikt)
- Je moet er ook nog voor zorgen dat deze variabelen de juiste waarde krijgen, dat moet m.b.v. een bepaalde methode gebeuren.
Die methode zorgt er voor dat de computer steeds controleert of er misschien met de muis geklikt is. En als er op de muis
wordt geklikt dan onderneemt hij een bepaalde actie.
Die methode heeft de naam muisDrukActie()
En die methode ziet er als volgt uit:
public void muisDrukActie()
{ int x = geefDrukx();
int y = geefDruky();
gekliktop1 = vlak1.contains(x,y);
gekliktop2 = vlak2.contains(x,y);
}
Dit betekent het volgende:-
De opdracht int x = geefDrukx();
heeft tot gevolg dat x de waarde krijgt van de x-coördinaat van de muiscursor, op het moment dat er geklikt wordt.
De opdracht int y = geefDruky(); zal dan wel duidelijk zijn.
-
En de opdracht gekliktop1 = vlak1.contains(x,y); heeft tot gevolg dat de
variabele gekliktop1 de waarde true krijgt als er op vlak1 werd geklikt.
De opdracht gekliktop2 = vlak2.contains(x,y); heeft dan natuurlijk tot gevolg dat de
variabele gekliktop2 de waarde true krijgt als er op vlak2 werd geklikt.
- En afhankelijk van de waarden van gekliktop1 en gekliktop2 wordt er in de methode
muisSleepActie() bepaald wat er bij het verslepen gebeurt.
Het volledige programma is hieronder afgedrukt.
Hierbij nog wat uitleg.
- In regel 2 staat de opdracht import java.awt.Polygon;.
Dit moet er bij als je de variabele Polygon, en de methoden geefVlak() en contains(x,y) wilt gebruiken.
- In de regels 6 en 7 worden de variabelen hoek1 en hoek2 gedeclareerd. Dat zijn de hoeken die aangeven
hoeveel de twee vlakken gedraaid moeten worden.
In het begin zijn ze nog niet gedraaid, dus ze moeten de beginwaarde 0 krijgen.
- In de regels 8en 9 worden de variabelen gekliktop1 en gekliktop2 gedeclareerd. Die zijn van het type
boolean, ze kunnen alleen true of false zijn.
In het begin is nog nergens op geklikt, dus ze moeten de beginwaarde false krijgen.
- In de regels 10 en 11 worden de vlakken vlak1 en vlak2 gedeclareerd. Dat zijn de vlakken die gedraaid kunnen
worden.
- In regel 12 wordt het getal s gedeclareerd. Dat is de afstand waarover de kubus naar rechts wordt verschoven.
-
In de methode initialiseer zet je de opdracht (zie regel 17):
maakMuisActieMogelijk();
Die opdracht zorgt er voor dat de computer steeds controleert of er misschien iets met de muis gebeurt. En als er iets met de muis
wordt gedaan onderneemt hij een bepaalde actie. Hij voert dan de methode muisDrukActie() en/of
de methode muisSleepActie() uit.
- In regel 33 staat de opdracht vlak1 = geefVlak()
Die opdracht heeft tot gevolg dat het programma weet waar het vlak met de naam vlak1 ligt. Dat is namelijk het vlak
dat hij daarvoor heeft ingekleurd, daarom ook volgt die opdracht direkt op de opdracht vulUit()
Op dezelfde manier weet het programma na regel 93 wat vlak2 is.
- Vanaf regel 105 is de methode muisDrukActie() toegevoegd.
De opdrachten int x = geefDrukx(); en int y = geefDruky();
zorgen er voor dat het programma weet waar geklikt is met de muis.
De opdracht op regel 108: gekliktop1 = vlak1.contains(x,y); heeft tot gevolg dat de variabele
gekliktop1 de waarde true heeft als er op vlak1 geklikt is.
Regel 109 zal dan wel duidelijk zijn.
- Vanaf regel 112 volgt de methode muisSleepActie()
Op regel 113 staat de opdracht if (gekliktop1) {hoek1 = hoek1 - geefSleepdy();}
Als er op vlak1 geklikt is dan wordt er iets bij hoek1 opgeteld, namelijk - geefSleepdy().
Dat is de afstand, die met de muis gesleept is in de y-richting.
Als je het voorvlak over de x-as wilt draaien zul je de muis naar beneden verschuiven, vandaar dat alleen naar de versleping in
de y-richting wordt gekeken.
En er staat een min voor, omdat als je de muis naar beneden verschuift, geefSleepdy() negatief is.
En - geefSleepdy() is dan positief, dus dan wordt er iets bij de hoek opgeteld.
Regel 114 zal dan wel duidelijk zijn.
En dan volgt de opdracht tekenOpnieuw();, die er voor zorgt dat de tekening opnieuw wordt gemaakt, eventueel met de
gedraaide vlakken.
-
Op regel 25 staan eerst de opdrachten stapx(-100);stapz(-100);. Die staan er alleen om er voor
te zorgen dat de kubus bij de start niet precies in het midden staat maar een beetje links van het midden en iets naar beneden.
stapx(s);. Die zogt er voor dat de kubus in zijn geheel over de afstand s
naar rechts wordt verschoven, en hoe groot s is wordt bepaald door de schuifvariabele.
-
Op regel 28 t/m 37 staan de opdrachten om het gedraaide voorvlak te tekenen.
Eerst wordt de opdracht xdraai(hoek1); (zie regel 29) uitgevoerd.
Dus er wordt gedraaid over hoek1, en hoe groot die hoek1 is wordt bepaald door de verschuiving met de muis.
En daarna wordt het voorvlak getekend, maar gedraaid door de opdracht op regel 29.
Je moet het voorvlak aan beide kanten kleuren, want anders verdwijnt het vlak op een gegeven moment als het gedraaid wordt.
Dat komt doordat je de binnenkant van het vlak niet ziet, als alleen de buitenkant van het vlak ingekleurd is.
Wil je dat het steeds zichtbaar blijft als het draait, dan moet je er voor zorgen dat ook de binnenkant ingekleurd wordt.
Dat gaat op dezelfde manier als de buitenkant, maar de volgorde van tekenen moet je omdraaien want die volgorde bepaalt
welke kant van het vlak wordt ingekleurd.
Dat gebeurt in de regels 35 tot en met 37.
-
Op regel 40 staat de opdracht xdraai(-hoek1);.
Voordat de rest van de kubus wordt getekend wordt er eerst teruggedraaid. Anders zou de hele kubus worden gedraaid,
en dat is niet de bedoeling.
-
Op regel 88 t/m 97 staan de opdrachten om het gedraaide bovenvlak te tekenen.
Dat gaat net zo als het gedraaide voorvlak, dat zal wel duidelijk zijn.
Het programma, waarmee een kubus wordt getekend, en waarmee je het bovenvlak en het voorvlak kunt laten draaien door er op
te klikken en de muis te verslepen, ziet er uit zoals hieronder, proberen maar! Je kunt het ook naar rechts verslepen.
Hieronder kun je het programma uitproberen. Klik op het voorvlak of het bovenvlak en sleep met de muis, het vlak draait!.
Ook kun je de kubus naar rechts slepen door het rode schuifje te verslepen.
Opgaven. Probeer bovenstaand programma uit.
|