Kukkumine

Tegelikus elus toimuvaid liikumisi jäljendades tuleb mõnigikord ka kukkumist ehk vaba langemist järgi teha. Järgnevalt mõned näited, seletused ja soovitused selle kohta.

Ring ekraanil


Kukkumine kipub millegipärast vahel kergesti palliga seostuma. Pall aga teadaolevalt enamasti ringikujuline. Seetõttu tuletame meelde, kuidas sai ringi joonistada ekraanile. Ristküliku puhul piisas joonistamiseks ühest käsust. Ringi ja muude kujundite puhul aga tuleb joonistamist alustada käsuga beginPath(). Seejärel luua vajalikud kujundid. Ning lõpuks öelda stroke() või fill() vastavalt sellele, kas soovitakse näha vaid piirjooni või siis kogu kujund seest ära täita. Ning ringi joonistamiseks sobib kaare tegemise käsklus (arc). Määratakse, keskpunkt, raadius, kaare algnurk ja kaarepikkus radiaanides ning joonistamise suund. Ringi puhul võib alustada algusest (ehk nullkraadist), täisringiks on 2 piid ehk 2*Math.PI ning joonistamise suund pole tähtis, siin näites jätsime selle true-ks.


<!doctype html>
<html>
  <head>
    <title>Kukkumine</title>
        <script>
           var x=20, y=20, r=10, samm=0;
           function joonista(){
             var t=document.getElementById("tahvel");
                 var g=t.getContext("2d");
                 g.clearRect(0, 0, t.width, t.height);
                 g.strokeStyle="red";
                 g.beginPath()
                 g.arc(x, y, r, 0, 2*Math.PI, true);
                 g.stroke()
           }

        </script>
  </head>
  <body onload="joonista()">
      <canvas id="tahvel" width="300" height="200"  
                  style="background-color:yellow"></canvas><br />

  </body>
</html>




Ühtlane kukkumine


Ülalt alla liikumine toimub sarnaste arvutuste tulemusena nagu ennist vaadatud vasakult paremale liikumine - vaid muuta tuleb y-koordinaati. Algusfunktsioonis küsitakse ligipääs tahvlile ja temale joonistamiseks vajalikule graafilisele kontekstile (muutujad t ja g). Käsklus


             setInterval('liigu()', 100);

teatab, et funktsioon liigu() tuleb käivitada iga 100 millisekundi tagant, ehk siis 10 korda sekundis. Seda ooteaega saab katsetada ja muuta, aga 100 on osutunud suhteliselt kuldseks keskteeks. Pikem ooteaeg näib juba silmale viivitusena. Lühema aja puhul aga ei pruugi seade suuta enne pilti korralikult valmis joonistada.


<!doctype html>
<html>
  <head>
    <title>Kukkumine</title>
        <script>
           var x=20, y=20, r=10, ysamm=1;
           var t, g; //tahvel, graafiline kontekst
           
           function algus(){
             t=document.getElementById("tahvel");
             g=t.getContext("2d");
             setInterval('liigu()', 100);
           }
           
           function joonista(){
             g.clearRect(0, 0, t.width, t.height);
             g.strokeStyle="red";
             g.beginPath()
             g.arc(x, y, r, 0, 2*Math.PI, true);
             g.stroke()
           }
           
           function liigu(){
             y=y+ysamm;
             joonista();
           }

        </script>
  </head>
  <body onload="algus()">
      <canvas id="tahvel" width="300" height="200"  
                  style="background-color:yellow"></canvas><br />

  </body>
</html>



Ülesandeid


* Tee näide läbi. Muuda ringi suurust ja kukkumise kiirust

* Pane kukkuma mitme joonistuskäsuga loodud kujund - nt pall, millele paar täppi peale joonistatud.

* Kujundi suurust ja kukkumise kiirust saab all olevas tekstiväljas muuta.



Kiirenev kukkumine


Tavaelu jälgides saab kõrgemalt kukkudes kätte suurema kiiruse. Ehk siis kiirus kukkumise ajal kasvab. Mingist suurusest hakkab kiirust piirama õhutakistus, aga lihtsamate arvutuste juures ka füüsikaõpikus jäetakse õhutakistus välja. Väliolukorda üsna täpselt saaks jäljendada, kui arvestada, mitu ekraanipunkti vastab ühele meetrile looduses ning siis vastavalt esemed ja raskuskiirendus paika ajada. Lihtsamal juhul aga võib kukkumissammule igal ringil veidi otsa liita, et sammu pikkus suureneks. Ning sobivat tulemust saab juba silma järgi hinnata. Siin näites said kõigepealt üles muutujad sammu ja kiirenduse kohta


           var ysamm=1, ykiirendus=0.4;

Liikumisfunktsioonis kõigepealt suurendatakse sammu kiirenduse jagu ning siis liigutakse igrekiga sammu jagu allapoole.


           ysamm=ysamm+ykiirendus;
           y=y+ysamm;

Kood tervikuna


<!doctype html>
<html>
  <head>
    <title>Kukkumine</title>
        <script>
           var x=20, y=20, r=10;
           var ysamm=1, ykiirendus=0.4;
           var t, g; //tahvel, graafiline kontekst
           
           function algus(){
             t=document.getElementById("tahvel");
                 g=t.getContext("2d");
                 setInterval('liigu()', 100);
           }
           
           function joonista(){
                 g.clearRect(0, 0, t.width, t.height);
                 g.strokeStyle="red";
                 g.beginPath()
                 g.arc(x, y, r, 0, 2*Math.PI, true);
                 g.stroke()
           }
           
           function liigu(){
             ysamm=ysamm+ykiirendus;
             y=y+ysamm;
             joonista();
           }

        </script>
  </head>
  <body onload="algus()">
      <canvas id="tahvel" width="300" height="200"  
                  style="background-color:yellow"></canvas><br />

  </body>
</html>

Ülesandeid


* Pane näide käima, katseta erinevaid algseid sammu pikkusi ja kiirenduse väärtusi

* Katseta liikumist negatiivse sammu korral

* Määra algul kiirendus ja samm nulliks. Käivita kukkumine nupuvajutuse peale.

* Kiirendust ning palli suurust saab tekstiväljas määrata.



Kukkumiskoha määramine hiirega


Liikumist jällegi mugavam ekraanil juhatada hiirega. Siin näites leitakse kõigepealt hiire asukoht tahvli suhtes (muutujad hx ja hy) ning pärast paigutatakse ring vastavale kohale. Vajalik on samuti ysamm'u ehk allakukkumiskiiruse määramine nulliks, sest muul juhul jätkaks pall hiirevajutuse kohast endise kiirusega kukkumist ning varsti poleks teda ekraanil võimalik enam kuigivõrd jälgida.


           function hiirAlla(e){
             var tahvlikoht=t.getBoundingClientRect();
             var hx=e.clientX-tahvlikoht.left;
             var hy=e.clientY-tahvlikoht.top;
             x=hx;
             y=hy;
             ysamm=0;
           }


Kui nüüd nõndamoodi toimetada, siis igal hiire vajutamise korral hüppab sinna pall ja asub sealt vaikselt alla kukkuma. Kood tervikuna.




<!doctype html>
<html>
  <head>
    <title>Kukkumine</title>
        <script>
           var x=20, y=20, r=10;
           var ysamm=1, ykiirendus=0.4;
           var t, g; //tahvel, graafiline kontekst
           
           function algus(){
                 t=document.getElementById("tahvel");
                 g=t.getContext("2d");
                 setInterval('liigu()', 100);
           }
           
           function joonista(){
                 g.clearRect(0, 0, t.width, t.height);
                 g.strokeStyle="red";
                 g.beginPath()
                 g.arc(x, y, r, 0, 2*Math.PI, true);
                 g.stroke()
           }
           
           function liigu(){
             ysamm=ysamm+ykiirendus;
             y=y+ysamm;
             joonista();
           }

           function hiirAlla(e){
             var tahvlikoht=t.getBoundingClientRect();
             var hx=e.clientX-tahvlikoht.left;
             var hy=e.clientY-tahvlikoht.top;
             x=hx;
             y=hy;
             ysamm=0;
           }
        </script>
  </head>
  <body onload="algus()">
      <canvas id="tahvel" width="300" height="200"  
                  style="background-color:yellow"
                          onmousedown="hiirAlla(event)"></canvas><br />

  </body>
</html>



Ülesandeid


* Pane näide tööle, muuda palli värvi ja suurust.

* Iga järgmise hiirevajutuse peale läheb pall veidi väiksemaks.

* Joonista tahvli alumine pool siniseks. Kui pall on jõudnud allapoole veepiiri, siis hakkab ta vaikselt väiksemaks minema.

* Veepiirist allpool jaguneb pall kaheks ning kumbki tükk hakkab kukkudes vaikselt vähenema.

* Vee all palli kiirus on aeglasem ja ei muutu.




Peatumine servas


Nagu niisama liikumise juures, nii ka kukkumise puhul on vahel hea, kui kokkupandud kujundid meie tahtmata silmapiirilt ei kao. Taas tuleb kontrollida, et soovitav järgmine asukoht oleks lubatud ala sees, vaid siis liigutakse edasi. Ning tulevikule mõeldes on lisatud muutuja ka x-suunalise liikumise tarbeks. Lihtsalt kuna xsamm on parajasti 0, siis kukutakse otse alla. Kui juhtub, et uus leitud asukoht satuks tahvlilt välja, siis pannakse x ja y-sammud nulliks.


           function liigu(){
                ysamm=ysamm+ykiirendus;
                if(kasSees(x+xsamm, y+ysamm)){
                   x=x+xsamm;
                   y=y+ysamm;                
                 } else {
                   xsamm=0; ysamm=0;
                 }
                 joonista();
           }


Ringi peatamise võimega kood tervikuna:


<!doctype html>
<html>
  <head>
    <title>Kukkumine</title>
        <script>
           var x=20, y=20, r=10;
           var ysamm=1, xsamm=0, ykiirendus=0.4;
           var t, g; //tahvel, graafiline kontekst
           
           function algus(){
             t=document.getElementById("tahvel");
                 g=t.getContext("2d");
                 setInterval('liigu()', 100);
           }
           
           function joonista(){
                 g.clearRect(0, 0, t.width, t.height);
                 g.strokeStyle="red";
                 g.beginPath()
                 g.arc(x, y, r, 0, 2*Math.PI, true);
                 g.stroke()
           }
           
           function liigu(){
                ysamm=ysamm+ykiirendus;
                if(kasSees(x+xsamm, y+ysamm)){
                   x=x+xsamm;
                   y=y+ysamm;                
                 } else {
                   xsamm=0; ysamm=0;
                 }
                 joonista();
           }

           function kasSees(uusX, uusY){
             if(uusX-r<0){return false;}
                 if(uusX+r>t.width){return false;}
             if(uusY-r<0){return false;}
                 if(uusY+r>t.height){return false;}
                 return true;
           }

           function hiirAlla(e){
             var tahvlikoht=t.getBoundingClientRect();
             var hx=e.clientX-tahvlikoht.left;
             var hy=e.clientY-tahvlikoht.top;
             x=hx;
             y=hy;
             ysamm=0;
           }
        </script>
  </head>
  <body onload="algus()">
      <canvas id="tahvel" width="300" height="200"  
                  style="background-color:yellow"
                          onmousedown="hiirAlla(event)"></canvas><br />

  </body>
</html>




Ülesandeid


* Katseta näidet, muuda palli värvi, joonista seest täis.

* Tõmba ekraanile maapinda tähistav joon, jäta pall selle juures seisma.

* Maapinnani jõudnud pall hakkab uuesti ülevalt kukkuma.

* Ülevalt uue kukkumise asukoht valitakse juhuslikult.



Palli loopimine


Nüüdseks on juba piisavalt oskusi kogunenud, et midagi täiesti elavat ja usutavat kokku panna. Näitena palli heitmise rakendus, kus pall hakkab liikuma hiire poole. Mida kaugemal hiir on, seda kiiremini. Servade juures kontrollitakse, et pall sealt välja ei läheks. Kui serv ette tuleb, siis võetakse hoog maha. Kui võimalust, hakkab ta sellest kohast uuesti allapoole kukkuma. Kui alla jõudnud, siis peab lihtsalt jääma ootama, kuni hiirega uuesti vajutatakse ja pall liikuma meelitatakse.


Tehniliselt midagi väga eripärast võrreldes eelnenuga polegi. Mõlema koordinaadi puhul pannakse pall sammuma hiire suunas. Sammu pikkus võrdeline kaugusega hiirest.


             xsamm=(hx-x)*kiiruskoef;
             ysamm=(hy-y)*kiiruskoef;

Tulemusena aga valmib täiesti mitmekülgne palli heitmise rakendus, mida saab edaspidi mitmesuguste liikuvate mudelite juures kasutada.


<!doctype html>
<html>
  <head>
    <title>Kukkumine</title>
        <script>
           var x=20, y=20, r=10;
           var ysamm=1, xsamm=0, ykiirendus=0.4, kiiruskoef=0.1;
           var t, g; //tahvel, graafiline kontekst
           
           function algus(){
             t=document.getElementById("tahvel");
             g=t.getContext("2d");
             setInterval('liigu()', 100);
           }
           
           function joonista(){
                 g.clearRect(0, 0, t.width, t.height);
                 g.strokeStyle="red";
                 g.beginPath()
                 g.arc(x, y, r, 0, 2*Math.PI, true);
                 g.stroke()
           }
           
           function liigu(){
              ysamm=ysamm+ykiirendus;
              if(kasSees(x+xsamm, y+ysamm)){
                   x=x+xsamm;
                   y=y+ysamm;                
              } else {
                   xsamm=0; ysamm=0;
              }
               joonista();
           }
           function kasSees(uusX, uusY){
             if(uusX-r<0){return false;}
             if(uusX+r>t.width){return false;}
             if(uusY-r<0){return false;}
             if(uusY+r>t.height){return false;}
             return true;
           }

           function hiirAlla(e){
             var tahvlikoht=t.getBoundingClientRect();
             var hx=e.clientX-tahvlikoht.left;
             var hy=e.clientY-tahvlikoht.top;
             xsamm=(hx-x)*kiiruskoef;
             ysamm=(hy-y)*kiiruskoef;
           }
        </script>
  </head>
  <body onload="algus()">
      <canvas id="tahvel" width="300" height="200"  
                  style="background-color:yellow"
                          onmousedown="hiirAlla(event)"></canvas><br />

  </body>
</html>

Nagu piltidelt näha, saab nõnda panna palli oma asukohta muutma.




Ülesandeid


* Pane näide tööle. Muuda muuda kiiruskoefitsienti, jälgi, kuidas see mõjutab palli liikumist.

* Muuda y-suunalist kiirendust ja jälgi, kuidas see mõjutab palli kukkumist.


Täpsusviskamine


* Võta aluseks palli loopimise näide. Paiguta pall tahvli ühele poolele ning kast tahvli teisele poolele maha

* Kui pall õnnestub kasti sisse visata, siis muudab kast värvi

* Eraldi arvuga näidatakse, mitu korda on kasti tabatud. Pärast tabamist hüppab pall algkohta tagasi

* Kasutajad viskavad palli kordamööda. Loetakse, mitu korda on kummalgi pall kasti pihta läinud.


Hiirt jälitav pall


* Tutvu palli loopimise näitega. Eemalda raskuskiirendus

* Sammu arvutamine käivitatakse mitte hiire vajutamise, vaid hiire liigutamise peale (sündmus onmousemove). Pall võiks hakata hiire poole liikuma.

* Lisa süsteemi teine pall teiste algkoordinaatidega. Mõlemad pallid püüavad sarnase valemiga liikuda hiire poole.

* Teine pall ei püüa liikuda mitte hiire, vaid esimese palli poole. Nii võiks hiire liigutamise tulemusena tekkida hiire järgi pallidest ahel.