Ha ezt az üzenetet látod, az annak a jele, hogy külső anyagok nem töltődnek be hibátlanul a honlapunkra.

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

Fő tartalom

Rezgés amplitúdó és periódus

Remélem, elkápráztattalak! Az „Elfordulás” fejezetben a trigonometria hatékony felhasználását láttuk: a tangensét (egy szög kiszámítására) és a szinusz-koszinusz függvényekét (a poláris koordinátákról a Descartes-féle koordinátára való átváltáshoz). Itt akár elégedetten meg is állhatnánk. De nem fogunk. Ez még csak a kezdet. A szinusz és koszinusz többet tud matematikai képleteknél és derékszögű háromszögeknél.
Nézzük meg az y=sin(x) függvény görbéjét:
Láthatod, hogy a szinusz függvény egy egyenletes görbe, ami -1 és 1 között hullámzik. Az ilyen viselkedést rezgőmozgásnak hívják, ami két pont közötti periodikus mozgást jelent. Ha megpendítesz egy gitárhúrt, meglendítesz egy ingát, ugrálóboton pattogsz – ezek mind rezgőmozgások.
Így nagy örömünkre felfedezhetjük, hogy ProcessingJSben szimulálni tudunk rezgőmozgást úgy, hogy a szinusz függvény eredményét hozzárendeljük a tárgy helyzetéhez. Figyeld meg, hogy ez ugyanaz az eljárás, mint amit a Zaj fejezetben alkalmaztunk a Perlin zaj esetében.
Kezdjük egy nagyon egyszerű alaphelyzettel! Az a cél, hogy a kör a rajzvászon jobb- és bal oldala között mozogjon.
Ez egyszerű harmonikus rezgőmozgás (vagy ha nagyon tudományosak akarunk lenni, „egy tárgy szinuszos periodicitással végzett mozgása”) néven ismert. A program egyszerű, de mielőtt belemerülünk a kódolásba, ismerkedjünk meg a rezgőmozgással (és a hullámokkal) kapcsolatos terminológiával!
Az egyszerű harmonikus rezgőmozgás alkalmazható a helyzet bármely összetevőjére (esetünkben az x-re) az idő függvényeként az alábbi két tulajdonság segítségével:
  • Amplitúdó: A mozgás központjától a két végállapot között mért távolság
  • Rezgésidő: Egy teljes rezgési ciklus lefutásához szükséges idő hossza
Ha megnézzük a fenti szinuszgörbe ábráját, látjuk, hogy az amplitúdó értéke 1, és a rezgésidő TWO_PI; a szinusz függvény értéke soha nem haladja meg az 1-et, vagy csökken -1 alá; és minden TWO_PI radián (vagy 360 fok) után a hullám megismétlődik.
Mi az amplitúdó és a rezgésidő a mi ProcessingJS világunkban? Az amplitúdót könnyű pixelben mérni. Egy 200 pixel széles rajzvászon esetén a középponttól 100 pixelnyit haladnánk jobbra és 100 pixelnyit balra. Ezért:
// Amplitúdó pixelben mérve
var amplitude = 100;
A rezgésidő a ciklus lefutásához szükséges idő hossza, de mit jelent az idő a ProcessingJs világában? Persze mondhatjuk, hogy azt szeretném, hogy a kör teljes rezgésciklusa 3 másodperc alatt fusson le. Ehhez figyelhetnénk az eltelt milliszekundumokat a programban (a millis() függvény segítségével), megalkotva egy kifinomult algoritmust a valós idejű rezgőmozgás megvalósításához.
Van egy másik lehetőségünk. Kihasználhatjuk azt a tényt, hogy a ProcessingJsben létezik a „képkocka" fogalma, és alapértelmezés szerint a program 30 „képkocka/másodperc" sebességre törekszik, A ProcessingJS rendelkezésünkre bocsájtja a frameCount változót, ami megmutatja, hogy pillanatnyilag hanyadik képkockánál tartunk, és a frameRate() függvényt, amivel megváltoztathatjuk a másodpercenkénti képkockaváltás sebességét. Az alapértelmezett sebesség 30 FPS, ami megfelelő sebesség ahhoz, hogy az emberi agy sima átmenetes animációt érzékeljen, de néha nagy segítség a képkockaváltási sebesség lelassítása, például hibakereséskor.
Dönthetünk úgy is, hogy a rezgésidőt (period) a képkockaváltás sebességére alapozzuk, mivel az, mint ahogy láttuk, szorosan kapcsolódik a valódi időhöz – mondhatjuk, hogy az rezgőmozgás 30, 50 vagy 1000 képkockánként ismétlődjön.
// A rezgésidőt képkockákban számoljuk (az animáció időegysége)
var period = 120;
Ha megvan az amplitúdó és a rezgésidő , akkor itt az ideje, hogy megírjuk azt a függvényt, ami kiszámolja nekünk x értékét az idő függvényében, ahol az időt helyettesítjük a képkocka számláló aktuális értékével.
var x = amplitude * sin(TWO_PI * frameCount / period);
Boncolgassuk még egy kicsit a fenti képletet, hogy megértsük az összetevőket! Az első lesz a legegyszerűbb. A szinusz függvény eredményét megszorozzuk az amplitúdóval. Azt már tudjuk, hogy a szinusz függvény -1 és +1 között változik. Ha vesszük ezt az értéket, és megszorozzuk az amplitúdóval, akkor a kívánt értéket fogjuk kapni: egy olyan értéket, ami -amplitúdó és +amplitúdó között változik. (Megfigyelheted, hogy itt használhatnánk a ProcessingJS map() függvényét is a szinusz függvény eredményének a kívánt intervallumra való transzformálásához.)
Most vizsgáljuk meg azt, ami a szinusz függvényen belül van:
TWO_PI * frameCount / period
Itt mi történik? Kezdjük azzal, amit már tudunk. Tudjuk, hogy a szinusz 2*PI radiánonként ismétlődik—azaz 0-nál indul, és ismétlődik 2*PI-nél, 4*PI-nél, 6*PI-nél, stb. Ha a rezgésidő 120 képkocka,, akkor azt szeretnénk, hogy a rezgőmozgás ismétlődjön, amikor a frameCount értéke 120, 240, 360 stb. Tulajdonképpen az egyetlen változó a frameCount, 0-nál indul, és innen számol felfelé. Nézzük meg a képlet eredményét ezekkel az értékekkel.
frameCountframeCount / rezgésidőTWO_PI * frameCount / rezgésidő
000
600.5PI
1201TWO_PI
24022 * TWO_PI (vagy 4 * PI)
etc.  
A frameCount osztva a rezgésidővel megmondja, hogy eddig hány ciklus ment le – félig múlt el az első ciklus? Két cikluson vagyunk túl? Azáltal, hogy ezt a számot megszorozzuk TWO_PI-vel, megkapjuk a kívánt eredményt, mivel TWO_PI az a mennyiség radiánban, amennyi ahhoz kell, hogy egy teljes ciklus lefusson.
Mindent összeraktunk egy programba, ami a kör x helyzetét mozgatja 100 pixel amplitúdóval és 120 képkockányi rezgésidővel. (A programban található megjegyzések: 1. sor: Dan Shiffman, natureofcode.com példája alapján; 5. sor: rezgésidő hossza képkockaváltások számával megadva; 6. sor: pixelben; 14-15. sor: A vízszintes pozíció számítása a harmonikus rezgőmozgás képlete alapján.)
Még egy fogalmat meg kell említenünk: a frekvenciát, ami az időegység alatti ciklusok számát jelenti. A frekvencia értéke egyenlő 1 osztva a rezgésidővel. Ha a rezgésidő 120 képkocka, akkor egy képkocka alatt a ciklus 1/120-ad része hajtódik végre, ebből következik, hogy a frekvencia = 1/120 ciklus/képkocka. A fenti példában azt választottuk, hogy a rezgőmozgás sebességét a rezgésidővel definiáljuk, ezért nem volt szükségünk a frekvencia változóra.
Figyeld meg, hogy a fenti példában a szinusz függvényt használtuk (sin() ProcessingJSben), de ugyanaz a gondolatmenet érvényes a koszinusz függvényre is! A rezgésidő mindkét esetben ugyanaz, a fő különbség abban rejlik, hogy az amplitúdó kezdőértéke 1 és nem 0.
Ez a „Természetes szimulációk" tananyag a Daniel Shiffman által készített „The Nature of Code” alapján készült, a Creative Commons Attribution-NonCommercial 3.0 Unported License szerint.

Szeretnél részt venni a beszélgetésben?

Még nincs hozzászólás.
Tudsz angolul? Kattints ide, ha meg szeretnéd nézni, milyen beszélgetések folynak a Khan Academy angol nyelvű oldalán.