Fő tartalom
Programozás
Tantárgy/kurzus: Programozás > 5. témakör
7. lecke: Rezgések- Rezgés amplitúdó és periódus
- Feladat: Szivárvány lépcsőjáró
- Rezgések szögsebességgel
- Feladat: Űrhajó utazás
- Hullámok
- Feladat: Sok hullám
- Trigonometria és erők: az inga
- Feladat: Ingabáb
- Rugóerők
- Projekt: Hullámzó, csúszó, körkörösen mozgó lények
© 2023 Khan AcademyFelhasználási feltételekAdatkezelési tájékoztatóSüti figyelmeztetés
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.frameCount | frameCount / rezgésidő | TWO_PI * frameCount / rezgésidő |
---|---|---|
0 | 0 | 0 |
60 | 0.5 | PI |
120 | 1 | TWO_PI |
240 | 2 | 2 * 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.