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

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

W pierwszej części poradnika opisałem jak stworzyć podstawy silnika 3D który będzie w stanie wygenerować trójwymiarowy sześcian, jednak bez możliwości poruszania się taki statyczny obraz zapewne nie był zbyt imponujący. Dlatego w tej część zajmiemy się mechanizmami kontroli kamery.
Zacznijmy od dodania do naszego konstruktora box3d dwóch zdarzeń związanych z klawiaturę:
stage.addEventListener(KeyboardEvent.KEY_DOWN,eventKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP,eventKeyUp);
(Nie zapomnij zaimportować flash.events.KeyboardEvent!)
Nasłuchiwacze zostały powiązane z wartością stage ponieważ w przypadku innych obiektów trzeba byłoby najpierw ustawić na nich "focus" co na razie jest nam kompletnie nie przydatne i stage w zupełności wystarczy. W każdym razie, musimy jeszcze stworzyć funkcje obsługujące owe zdarzenia:
private function eventKeyDown(e:KeyboardEvent):void {

}
private function eventKeyUp(e:KeyboardEvent):void {

}
W tym momencie sugerował bym dopisać do którejś z nich linijkę trace(e.keyCode); by upewnić się, że Flash poprawnie przechwytuje naciśnięte klawisze.
W następny kroku zajmiemy się już właściwym wyłapywaniem klawiszy i tłumaczeniem ich na odpowiedni ruch kamerą, i choć całość można byłoby załatwić pisząc po prostu:
if(e.keyCode == Keyboard.LEFT) cx -= 20;
else if(e.keyCode == Keyboard.RIGHT) cx += 20;
Takie rozwiązanie jest niestety nie tylko ograniczające ale w dodatku niezbyt płynne. Dlatego w naszym silniku zastosujemy nieco bardziej zaawansowaną metodę opartą o operacje bitowe - tylko za nim ją opisze, dodaj do klasy nową zmienną: var key:Number = 0; której używać będziemy w następujący sposób:
private function eventKeyDown(e:KeyboardEvent):void {
	switch(e.keyCode) {
		case Keyboard.UP:
			key = key | 0x00000f;
			break;
		case Keyboard.DOWN:
			key = key | 0x0000f0;
			break;
		case Keyboard.LEFT:
			key = key | 0x000f00;
			break;
		case Keyboard.RIGHT:
			key = key | 0x00f000;
			break;
	}
}
(Nie zapomnij importować flash.ui.Keyboard!)
Okej, musze przyznać, że na pierwszy rzut oka wygląda to trochę bez sensu (szczególnie dla osób które nie miały styczności z operacjami bitowymi lub liczbami szesnastkowymi), ale za parę chwil wszystko stanie się jasne. Owy kod przypisuje pewne wartości do zmiennej key zależnie od wciśniętego klawisza - wciskając klawisze strzałek "do góry" i "w lewo" key będzie mieć wartość "0x000f0f". Rezultat ten otrzymujemy poprzez operacje bitowe na liczbach szesnastkowych, a więc dla przykładu jeśli weźmiemy liczby "0x000f00" oraz "0x00000f" i wykonamy na nich operację | (OR) dostaniemy "0x000f0f". Ta kreska | jest znana jako bitowe "lub" i przypomina w pewnych sytuacjach dodawanie - 100|1 da wynik 101 (więcej informacji znajdziesz w dokumentacji ActionScript'a). W każdym razie, dla nas ważne jest tylko to, że key będzie przypominał trochę jakby listwę ze światełkami gdzie 0 = zgaszona lampka (klawisz nie jest wciśnięty) a f = zapalona lampka (klawisz jest wciśnięty). 0x00ffff = wszystkie klawisze wciśnięte, 0x00f00f0 = tylko klawisz w dół i w prawo, 0x000000 = żaden klawisz nie jest wciśnięty itd.
Jednak sam eventKeyDown służy nam jedynie do zapalania światełek. Do pełnego obrazu brakuje nam jeszcze przeciwnej funkcji czyli:
private function eventKeyUp(e:KeyboardEvent):void {
	switch(e.keyCode) {
		case Keyboard.UP:
			key = key ^ 0x00000f;
			break;
		case Keyboard.DOWN:
			key = key ^ 0x0000f0;
			break;
		case Keyboard.LEFT:
			key = key ^ 0x000f00;
			break;
		case Keyboard.RIGHT:
			key = key ^ 0x00f000;
			break;
	}
}
W tym wypadku bitowe ^ (XOR) działa trochę jak odejmowanie, a więc operacja " 0x000f0f ^ 0x00000f" zwróci "0x000f00".
Najgorsze za nami, teraz już mamy w pełni funkcjonalną zmienną key która sygnalizuje nam jakie klawisze są w użyciu i pozostaje nam jedynie przetłumaczyć je na ruch kamery. W tym celu przejdź do funkcji render (utworzyliśmy ją w poprzedniej część poradnika) i przed linijką graphics.clear(); dopisz:
switch(key) {
	case 0x00000f: // ^
		cz += 20;
	break;
	case 0x0000f0: // v
		cz -= 20;
		break;
	case 0x000f00: // <
		cx -= 20;
		break;
	case 0x00f000: // >
		cx += 20;
		break;
}
To już prawie koniec. Skompiluj aplikacje i sprawdź czy wszystko działa poprawnie. Jeśli wcześniej próbowałeś poruszać kamerą bezpośrednio z poziomu eventKeyDown i eventKeyUp na pewno zauważyłeś teraz poprawę (a jeśli nie, proponuję powrót do owego rozwiązania i porównanie z aktualnym).
W każdym razie, została jeszcze jedna mała rzecz - poruszanie się po skosie. Używanie dwóch klawiszy naraz ustala wartość key na liczbę którą nasz switch(key) nie obsługuje, dlatego na koniec musimy go jeszcze rozbudować o cztery dodatkowe warunki:
	case 0x000f0f:
		cz += 20;
		cx -= 20;
		break;
	case 0x00f00f:
		cz += 20;
		cx += 20;
		break;
	case 0x000ff0:
		cz -= 20;
		cx -= 20;
		break;
	case 0x00f0f0:
		cz -= 20;
		cx += 20;
		break;
I tyle. W razie czego całą klasę można pobrać stąd: box3d_2.zip
A sama aplikacja zobaczyć tutaj: box3d.swf

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