Fő tartalom
Programozás
Tantárgy/kurzus: Programozás > 5. témakör
4. lecke: A vektorok- Bevezetés a vektorokba
- Feladat: Vektor bolyongó
- Még több vektor matematika
- Feladat: Fénykard
- Vektor hossza és a normalizálás
- Feladat: Vektor hosszának megjelenítése
- Vektormozgás
- Feladat: Fékező autó
- Statikus függvények vagy példány metódusok?
- Feladat: Statikus függvények
- Interaktív vektormozgás
- Feladat: Egérpiszkálás
- Projekt: Számítógépes lények
© 2023 Khan AcademyFelhasználási feltételekAdatkezelési tájékoztatóSüti figyelmeztetés
Bevezetés a vektorokba
Ezzel a tananyaggal az a célunk, hogy megfigyeljük a körülöttünk levő világot, és ügyes megoldást találjunk a jelenségek számítógépes szimulációjára. Azzal kezdjük, hogy megvizsgáljuk a fizika alaptörvényeit - hogyan esik le az alma a fáról, hogyan mozog az inga a levegőben, hogyan forog a Föld a Nap körül, és így tovább. Minden, amiről beszélni fogunk, a mozgás programozásának alapvető építőkövét használja — a vektort.
A vektor szónak különböző jelentései vannak. Vector volt a neve a kaliforniai Sacramentóban az 1980-as években alakult új hullám zenekarnak. Ez a neve a Kellog's által Kanadában gyártott reggeli gabonapehelynek. A járványügy területén a vektor egy fertőző ágenst hordozó, annak átvitelét megvalósító élőlény, ami átviszi a fertőzést az egyik gazdaélőlényről a másikra. A C++ programnyelvben a vektor (std::vector) dinamikusan átméretezhető adatstruktúra implementációja. Bár az összes fenti definíció érdekes, nem ezeket keressük. Amire szükségünk van, az az euklideszi térben (a görög matematikusról, Euklidészről nevezték el) az irányított szakasz fogalma. Amikor „vektorról” beszélünk, akkor ennek a jelentése egy olyan szakasz, amit a hosszán túl az iránya is jellemez.
A vektort nyíllal szokták ábrázolni; az irányt a nyíl hegye mutatja, míg a hosszt a nyíl hossza jelöli.
A fenti ábrán az A pontból B pontba mutató nyíllal ábrázoltuk a vektort, amivel azt akartuk megmutatni, hogy hogyan lehet eljutni az A pontból B-be.
Miért érdemes vektort használni?
Mielőtt belemerülünk a vektorok rejtelmeibe, nézzünk meg egy alapprogramot, amely megmutatja, miért foglalkozzunk egyáltalán vektorokkal. Ha megcsináltad a Khan Academy bevezető JS kurzusát, akkor már megtanultad, hogyan kell egy egyszerű pattogó labda programot írni. (A programban található megjegyzések: 1. sor: Dan Shiffman, natureofcode.com példája alapján; 11. sor: A sebesség függvényében mozgatjuk a labdát; 15. sor: Ellenőrizzük, hogy visszapattan-e; 25. sor: Megjelenítjük a labdát az (x;y) pontban.)
A fenti példa világa nagyon egyszerű – egy üres háttér előtt egy kör alakú forma (egy „labda”) mozog. A labdának vannak tulajdonságai, amit a programban változók képviselnek.
Pozíció | Sebesség |
---|---|
x és y | xspeed és yspeed |
Bonyolultabb programban sokkal több változónk lehetne:
Gyorsulás | Cél helyzete | Szél | Súrlódás |
---|---|---|---|
xacceleration és yacceleration | xtarget és ytarget | xwind és ywind | xfriction és yfriction |
Látjuk, hogy minden fogalomhoz (szél, pozíció, gyorsulás, stb.) két változóra van szükségünk. És ez még csak a kétdimenziós világ. A 3D világában három változó kell:
x
, y
, z
, xSpeed
, ySpeed
, zSpeed
és így tovább.Mennyivel kellemesebb lenne, ha kevesebb változóra lenne szükség, és ezáltal egyszerűsödne a program!
E helyett:
var x = 5;
var y = 10;
var xSpeed;
var ySpeed;
Lehetne csak két változónk, ahol mindkét változó kétdimenziós, vektorszerű objektum lenne:
var position;
var speed;
Ezzel az első lépéssel még semmi újat nem tudunk csinálni. Csupán azzal, hogy vektorszerű objektumokat használunk változónak, még nem varázsoljuk át programunkat a fizikai világ szimulációjává. Viszont egyszerűsíti a kódot, és lehetővé teszi, hogy a mozgás programozása során ismétlődően előforduló egyszerű matematikai műveletekhez függvényeket állíts elő.
A vektorok bevezetésekor két dimenziót fogunk használni. A példák mind elég könnyen kiterjesztetők három dimenzióra (és a használt objektum, —
PVector
— három dimenziót enged meg.) Azonban könnyebb két dimenzióval kezdeni.PVector
használata a programban
Úgy is gondolhatunk a vektorra, mint két pont közötti különbség. Képzeld el, hogyan magyaráznád el valakinek, hogyan juthat el az egyik pontból a másikba!
Íme néhány vektor, és azok lehetséges fordítása:
| (-15, 3) | Sétálj 15 lépést nyugatra; fordulj el és sétálj három lépést észak felé! |
| (3, 4) | Sétálj három lépést nyugatra; fordulj el és sétálj négy lépést észak felé! |
| (2, -1) | Sétálj két lépést nyugatra; fordulj el és sétálj egy lépést dél felé! |
Ilyet már valószínűleg csináltál, amikor mozgást programoztál. Az animáció minden képkockájához (azaz a ProcessingJS minden draw() ciklusában) a kép minden objektumát utasítod, hogy elmozduljon adott számú pixellel vízszintes irányba, és valahány pixellel függőleges irányba.
Minden képkocka esetében:
új pozíció = sebesség a jelenlegi pozícióból kiindulva
Ha a sebesség egy vektor (két pont közötti különbség), akkor mi a pozíció? Az is egy vektor? Technikai értelemben érvelhetünk azzal, hogy a pozíció nem vektor, mivel az nem azt írja le, hogy hogyan juthatunk el az egyik pontból a másik pontba – egyszerűen a tér egy pontját írja le.
De egy helyzetet úgy is meghatározhatunk, hogy leírjuk azt az utat, ami az origóból a pozícióba vezet. Tehát egy helyzetet meghatározhatunk úgy is, mint egy vektor, ami az origó és a pozíció közötti különbséget írja le.
Vizsgáljuk meg a háttérben levő pozíció és sebesség adatokat! A pattogó labda példában az alábbi adataink voltak:
Pozíció | Sebesség |
---|---|
x és y | xSpeed és ySpeed |
Figyeld meg, hogyan tároljuk minkét esetben az adatokat – két lebegőpontos szám, egy
x
és egy y
. Ha nekünk kellene megírni egy vektor osztályt, egy egészen alapvető dolgot csinálnánk:var Vector = function(x, y) {
this.x = x;
this.y = y;
};
Alapjaiban a
PVector
csupán egy kényelmes módja két (vagy, mint a 3D példákban látni fogjuk, három) érték tárolásának.Úgyhogy ebből …
var x = 100;
var y = 100;
var xSpeed = 1;
var ySpeed = 3.3;
ez lesz …
var position = new PVector(100,100);
var velocity = new PVector(1,3.3);
Most, hogy van két vektor objektumunk (position és velocity), implementálni tudjuk a mozgás algoritmusát—position = position + velocity. Az 1,1. példában, még vektorok nélkül, ezt írtuk:
x = x + xSpeed;
y = y + ySpeed;
Egy ideális világban ezt írhatnánk:
position = position + velocity;
JavaScriptben viszont az összeadás + művelete az elemi adattípusok számára (számok és sztringek) van fenntartva. Vannak olyan programozási nyelvek, ahol megengedett az operátorok esetében a „túlterhelés, vagy kiterjesztés” (overloading: azonos néven, de különböző paraméterlistával több függvény létrehozása), de a JavaScriptben ez nem megengedett. Szerencsére a
PVector
objektum tartalmaz a szokásos matematikai műveleteket megvalósító metódusokat, mint például az add()
. Vektor összeadás
Mielőtt tovább vizsgálnánk a
PVector
objektumot és annak add()
metódusát, vegyük szemügyre a vektorok összeadását és jelölésrendszerét, ahogy azt a matematikai és fizikai tankönyvek tárgyalják. A vektorokat általában vagy félkövér betűkkel jelölik, vagy egy nyíl van felül. Ebben a tananyagban a vektor és a skalár megkülönböztetésére a nyilas jelölést fogjuk használni (a skalár egy érték, mint például egy egész szám vagy egy lebegőpontos érték):
- Vektor: u, with, vector, on top
- Skalár: x
Tegyük fel, hogy van két vektorunk:
Mindkét vektornak két komponense van, egy
x
és egy y
. A két vektor összeadásakor egyszerűen összeadjuk a két x
-et és a két y
-t.Azaz:
így is írható:
Ezután helyettesítve
u
-t és v
-t a megfelelő értékekkel az 1,6. ábrán, ezt kapjuk: ami ezt jelenti:
Végül ezt is írjuk fel vektor formában:
Most, hogy megértettük, hogyan kell két vektort összeadni, megnézzük, hogyan valósították meg két vektor összeadását a
PVector
objektumban. Írjunk egy add()
metódust, ami paraméterként átvesz egy másik PVector
objektumot, és egyszerűen összeadja az x és y komponenseket!var Vector = function(x, y) {
this.x = x;
this.y = y;
};
Vector.prototype.add = function(v) {
this.y = this.y + v.y;
this.x = this.x + v.x;
};
Most, hogy már látod, hogyan van megírva a
PVector
add()
metódusa, visszatérhetünk a pattogó labda példánkhoz és az ottani pozíció + sebesség algoritmushoz, és használhatjuk a vektor-összeadást:position.add(velocity);
Most már készen állunk arra, hogy újraírjuk a pattogó labda példát
PVector
objektumot használva. Figyeld meg a két kód közötti különbségeket! (A programban található megjegyzések: 1. sor: Dan Shiffman, natureofcode.com példája alapján; 11. sor: Még mindig időnként hivatkozni kell a PVektor egyes komponenseire. Ezt a pont jelölési konvenció használatával tehetjük meg: location.x, velocity.y, stb.)Figyeljünk meg a fenti átírással kapcsolatban egy fontos tényezőt: bár
PVector
objektumokat használunk két érték – az x és y pozíció, valamint az x és y sebesség – leírására, gyakran hivatkoznunk kell az egyes PVector
objektumok x és y komponenseire külön-külön. Ha egy objektumot rajzolunk a ProcessingJS-ben, nem írhatunk ilyen kódot: ellipse(position, 16, 16);
Az
ellipse()
függvény nem fogad el PVector
adattípusú paramétert. Elipszist csak két skaláris x és y koordinátával rajzolhatunk. Úgyhogy le kell ásni a PVector
objektumba, és elő kell bányászni az x és y tulajdonságokat az objektumorientált programozás pontjelölési konvenciója szerint:ellipse(position.x, position.y, 16, 16);
Ugyanez a probléma merül fel akkor, amikor azt vizsgáljuk, hogy a kör elérte-e az ablak szélét, és hozzá kell férnünk a
position
és velocity
vektorok tulajdonságaihoz.if ((position.x > width) || (position.x < 0)) {
velocity.x = velocity.x * -1;
}
Most kicsit csalódott lehetsz. Végül is a program megváltoztatása első látásra az eredetinél bonyolultabbá tette azt. Ez egy teljesen ésszerű és helytálló kritika, de fontos megérteni, hogy egyenlőre még nem mélyültünk el a vektorok használata által kínált lehetőségekben. Az egyszerű pattogó labda példája és a vektorösszeadás használata csak az első lépés.
Ahogy előrehaladunk a többszörös objektumok és többszörös erőhatások
összetettebb világa felé (amit nemsokára megismerünk), a
PVector
előnyei világossá válnak. Csak így tovább!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.