Strona wykorzystuje ciasteczka by usprawnić komfort z jej korzystania. Korzystając ze strony akceptujesz naszą Politykę Ciasteczek. X

Silnik 3D dla początkujących III [zaawansowany]

W poprzednich częściach tego poradnika poświęconemu tworzeniu bardzo minimalistycznego silnika 3D wspomniałem jak stworzyć iluzję perspektywy oraz jak płynnie poruszać kamerą. Tym razem zajmiemy się obrotem widoku. Będzie to już ostatni rozdział tego poradnika gdyż dalsze zagłębianie się w temacie wymagać będzie znajomości bardziej zaawansowanych zagadnień, a wtedy już po prostu lepiej wziąć się za "prawdziwy" silnik (jak np. Alternativa3D lub Away3D). Do tego najnowsza wersja Flash'a z numerem 11 rozstała rozszerzona o akcelerację 3D co oznacza, że nic nie stoi na przeszkodzie by napisać w ActionScript gry na miarę naszych czasów jak Crysis albo Gears of War (szczególnie, że Adobe zaprezentowało Unreal Engine 3 działający we Flash'u).
No ale na to przyjdzie jeszcze czas, na razie zajmijmy się tą rotacją.

1. Za nim przejdę do konkretów do klasy utworzonej w poprzednich rozdziałach dopiszemy dwie stałe oraz jedną zmienną:

const SPEED:Number = 20;
const ROTATION:Number = Math.PI/16;
var a:Number = 0;
SPEED będzie prędkością poruszania się kamery, a ROTATION prędkością obrotu. Zmienna a posłuży do przechowywania aktualnego kąta obrotu.

2. Pamiętasz gdzie znajduje się kod odpowiedzialny za transformacje informacji 3D na 2D? Zmodyfikujemy go nieco by uwzględniał rotacje widoku:

var nx:Number;
var nz:Number;
var rx:Number;
var rz:Number;
var bx2:Array = new Array(bx.length);
var by2:Array = new Array(by.length);
var i:Number = 0;
while(i<bz.length) {
	nx = cx-bx[i];
	nz = cz-bz[i];
	rx = cx+( nx*Math.cos(-a) )-( nz*Math.sin(-a) );
	rz = cz+( nx*Math.sin(-a) )+( nz*Math.cos(-a) );
	bx2[i] = vw+( ((cx-rx) / (cz-rz) )*vw);
	by2[i] = vh+( ((cy-by[i]) / (cz-rz) )*vh);
	++i;
}
Właściwie różnica nie jest duża, dodałem jedynie parę zmiennych dla przejrzystości oraz wzór na obrót (wzdłuż osi Y, czyli tak samo jak w każdej grze FPS). Jeśli matematyka nie jest ci obca prawdopodobnie nie znajdziesz tutaj nic szokującego. W skrócie z każdego punktu wyliczany jest wektor przesunięcia (na przykładzie x: nx = cx-bx[i];), który następnie poddawany jest obrotowi (( nx*Math.cos(-a) )-( nz*Math.sin(-a) );) i ustawiany na nową pozycję ( rx = cx+...). Nowy punkt trafia do znanej nam już transformacji z 3D do 2D.

3. Teraz pozostaje nam jeszcze tylko zmodyfikować sposób poruszania się kamery tak aby korzystała ona z rotacji. W tym celu wrócimy do kodu odpowiedzialnego za przetwarzanie informacji o wciśniętych klawiszach na komendy w aplikacji, czyli switch(key). Przy okazji to również dobry moment by go trochę uprościć - stary kod w całości zastąp tym:

switch(key&0x0000ff) {
case 0x00000f:
		cz += Math.cos(-a)*SPEED;
		cx += Math.sin(-a)*SPEED;
	break;
	case 0x0000f0:
		cz -= Math.cos(-a)*SPEED;
		cx -= Math.sin(-a)*SPEED;
		break;
}
switch(key&0x00ff00) {
	case 0x000f00:
	a += ROTATION;
		break;
	case 0x00f000:
		a -= ROTATION;
		break;
}
W poprzedniej wersji switch sprawdzał wszystkie możliwe kombinacje zmiennej key, podczas gdy tutaj pierwszy switch wyciąga z key stan jedynie klawiszy góra i dół (0x000f0f&0x0000ff da w rezultacie 0x00000f a więc informacja o wciśniętym klawiszu lewo, 0x000f00, zostanie pominięta), a drugi klawiszy lewo i prawo.
Okej, więc teraz lepiej rozróżniamy wciśnięte klawisze, ale co właściwie się tutaj dzieje? Zaczynając od końca: klawisze lewo i prawo odpowiedzialne są za zmianę kąta obrotu, podczas gdy góra i dół za poruszanie się do przodu i do tyłu. Oczywiście teraz gdy mamy do czynienia z rotacją, definicja "do przodu" cały czas się zmienia stąd też potrzeba wykorzystania funkcji cos i sin które w tym przypadku wyliczają dla nas wektor przesunięcia zależny od aktualnego kąta.

4. Czas sprawdzić czy wszystko działa. Efekt końcowy powinien wyglądać mniej więcej tak :
(Poruszanie się na strzałkach)


A cała klasa do ściągnięcia jest tutaj: box3d_rot.zip

Imię:
Komentarz:
Potwierdz kod z obrazka:confirm image