Professional Documents
Culture Documents
Tworzenie gier
Autor: Janusz Grzyb
ISBN: 978-83-246-1263-5
Wydawnictwo Helion
ul. Kociuszki 1c
44-100 Gliwice
tel. 032 230 98 63
e-mail: helion@helion.pl
Spis treci
Wstp .............................................................................................. 7
Rozdzia 1. Podstawy ....................................................................................... 11
Konfiguracja .................................................................................................................... 12
Profil ................................................................................................................................ 12
Najpopularniejsze pakiety opcjonalne ............................................................................. 13
Hello World ..................................................................................................................... 15
Wireless Toolkit .............................................................................................................. 17
Instalacja pakietu ....................................................................................................... 17
KToolbar ................................................................................................................... 19
Narzdzia specjalne ................................................................................................... 22
Ant ................................................................................................................................... 25
Instalacja .................................................................................................................... 26
Praca z Antem ........................................................................................................... 27
Tworzenie wersji dystrybucyjnej aplikacji ............................................................... 30
Antenna ............................................................................................................................ 32
Instalacja .................................................................................................................... 32
Nowa wersja skryptu wykorzystujemy Antenn .................................................. 33
WTKPREPROCESS i kompilacja warunkowa w Javie ........................................... 35
Podsumowanie ................................................................................................................. 37
Pytania kontrolne ............................................................................................................. 38
Zadania ............................................................................................................................ 38
Spis treci
Rozdzia 3.
Gry 3D w 2D
Wolfenstein
Jeszcze kilka lat temu, grajc na swojej Nokii 3310 w kultowego ju wa, za fantazj
uznabym, gdyby kto powiedzia mi wtedy, e za kilka lat na telefonach komrkowych
krlowa bd gry 3D. A jednak! Najnowsze telefony komrkowe maj ju tak due
moce obliczeniowe, e wiat gier 3D stan przed nimi otworem. Co wicej, niektre
urzdzenia mobilne maj ju wbudowane sprztowe akceleratory grafiki 3D. Najnowsze telefony komrkowe udostpniaj programistom interfejs Java Mobile 3D, uatwiajcy w zasadniczym stopniu proces tworzenia aplikacji korzystajcych z grafiki trjwymiarowej.
Czy mona jednak stworzy gr 3D na popularnych (czytaj: taszych) modelach telefonw? Okazuje si, e przy zastosowaniu pewnych trikw mona osign efekt trjwymiarowoci na telefonach o niskich mocach obliczeniowych nieposiadajcych dedykowanych ku temu API czy te sprztowej akceleracji. Z pomoc przychodzi nam metoda
raycastingu, znana z takich gier jak m.in. Wolfenstein3D, Doom i wiele innych tytuw
z pocztku lat 90.
W rozdziale tym:
dowiemy si, czym jest metoda raycastingu,
poznamy zasady dziaania algorytmu DDA rzucania promieni,
stworzymy symulacj spaceru po trjwymiarowym labiryncie, takim jak
Raycasting
wiat gry w metodzie raycastingu reprezentowany jest przez dwuwymiarow siatk, tak
jak ta pokazana na rysunku 3.1. Siatka ta przedstawia rzut z gry labiryntu, po ktrym
poruszaj si bohaterowie gry. W pamici komputera siatka ta moe by reprezentowana
78
Rysunek 3.1.
Reprezentacja
wiata gry w metodzie
raycastingu
przez dwuwymiarow tablic bajtw. Kade oczko siatki (element tablicy) okrela, czy
dany sektor (np. o rozmiarze 11 metr) jest pusty, czy stanowi cian labiryntu (a waciwie cztery ciany, gdy sektor ten przylega ciankami do czterech ssiednich
sektorw).
A oto przykad reprezentacji takiego wiata w pamici komputera:
int worldMap[][] = new int[][] {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1},
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1},
{1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1},
{1,0,0,0,1,1,1,0,0,0,0,0,0,0,1,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1},
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
79
Dziki sprytnemu trikowi moemy na paszczynie ekranu wygenerowa trjwymiarowy obraz tego, co widzi gracz umieszczony wewntrz labiryntu.
Dla uproszczenia przyjmijmy, e kt rozwarcia stoka kamery, przez ktr patrzymy,
jest rwny 90 stopni. Z punktu, w ktrym stoimy, prowadzimy 90 promieni (co 1 stopie), tak jak to jest pokazane na rysunku 3.2. (Dla czytelnoci na rysunku pokazano
tylko kilka takich promieni).
Rysunek 3.2.
Promienie rzucane
z punktu, w ktrym
znajduje si
obserwator
Dla kadego z tych promieni szukamy punktu, w ktrym promie po raz pierwszy
uderzy w cian labiryntu. Po znalezieniu kadego takiego punktu obliczamy jego odlego od punktu, w ktrym znajduje si obserwator. Odlego ta okrela, jak wysoko
na ekranie monitora bdzie mie fragment cianki, w ktr uderzy dany promie. Im
dalej nastpia kolizja ze ciank labiryntu, tym mniejszy powinien by pionowy pasek
przedstawiajcy ten fragment cianki na wywietlaczu telefonu. Wygenerowany na ekranie obraz bdzie mia szeroko 90 pikseli (kada kolumna odpowiada jednemu z dziewidziesiciu promieni) i wysoko zalen od przyjtego przez nas wspczynnika
proporcjonalnoci pomidzy wysokoci cianki a odlegoci od punktu kolizji z promieniem. Rysunek 3.3 przedstawia opisany sposb generacji obrazu na przykadzie kilku
promieni z rysunku 3.2.
Rysunek 3.3.
a)
b)
Na rysunku widzimy 4 przykadowe promienie. Pierwszy z nich biegnie pod ktem -45
stopni wzgldem kierunku, w ktrym patrzy gracz. Kolejne trzy promienie puszczane s
pod ktami odpowiednio: -45, -15, 15 i 45 stopni wzgldem obserwatora. Promienie
te uderzaj w ciany labiryntu w czterech rnych punktach. Odlegoci, w jakich uderzyy one w ciany labiryntu, pokazane s na rysunku 3.3a w postaci wykresu supkowego.
80
Rysunek 3.4. Widok labiryntu przy 8, 16, 32, 64 i 128 promieniach rzuconych z punktu obserwacji
81
82
Regua wnioskowania
Kolejne iteracje
Wiemy ju, jak wyznaczy drugi z kolei sektor, ktry przetnie rzucany promie. A jak
znale kolejne sektory, a do momentu, gdy promie natrafi na cian? Spjrzmy na
rysunek 3.6.
Znajc kt, pod jakim wypuszczony zosta promie, moemy obliczy odlegoci od
kolejnych przeci poziomych i pionowych linii wirtualnej siatki:
dk = 1/cos()
dl = 1/sin()
83
Rysunek 3.6.
Szukanie
kolejnych sektorw
odwiedzanych przez
rzucany promie
Na tym etapie znajdujemy si w drugim z kolei sektorze na trasie promienia. Zastanwmy si, jakie informacje posiadamy zaraz po wejciu do tego sektora. Po pierwsze,
wiemy, przez ktr ciank promie do niego wkracza. Po drugie, wiemy, jak drog
przeby promie do momentu przecicia tej cianki.
Gdybymy teraz znali odlego do kolejnego przecicia si promienia z lini pionow
i poziom wirtualnej siatki, moglibymy wyznaczy kolejny sektor na drodze promienia. Skorzystamy tutaj z wyprowadzonych wczeniej wzorw (dk oraz dl). Mamy do
rozwaenia dwa przypadki:
Jeli do sektora promie wbieg przecinajc ciank poziom, to odlego od przecicia cianki pionowej znamy, gdy wyliczylimy j dla poprzedniego sektora. Odlego od nastpnego przecicia z ciank poziom obliczymy, dodajc warto dl do
odlegoci, w jakiej nastpio poprzednie przecicie cianki poziomej. Zmienne decyzyjne l oraz k przyjm nastpujce wartoci:
k=k
l = l+dl
Jeli do sektora promie wbieg przecinajc ciank pionow, to odlego od przecicia cianki poziomej rwnie znamy, gdy wyliczylimy j dla poprzedniego sektora. Odlego od nastpnego przecicia z ciank pionow obliczymy, dodajc warto
dl do odlegoci, w jakiej nastpio poprzednie przecicie cianki pionowej.
k = k+dk
l=l
promienia;
gdy znamy ju kolejny sektor, sprawdzamy, czy jest on pusty. Jeli tak, wwczas
84
wsprzdnych globalnych,
wsprzdne lokalne (Xl, Yl) wzgldem tego sektora poprzez odcicie czci
Klasa Raycaster
Klasa Raycaster zawiera gwn cz naszej aplikacji zajmujcej si rysowaniem labiryntu. Oto jej kod:
package mypackage;
import javax.microedition.lcdui.*;
import java.util.*;
import java.lang.Math.*;
public class Raycaster extends Canvas {
85
86
87
distance = maxDistance-distance%maxDistance;
g.drawLine(x,screenHalfHeight - (int)(distance),
x,screenHalfHeight + (int)(distance));
x++;
W klasie Raycaster na samym pocztku definiujemy kilka poytecznych staych wykorzystywanych w algorytmie rzucania promieni:
screenHeight wysoko ekranu wyraona w pikselach,
screenWidth szeroko ekranu wyraona w pikselach,
maxDistance maksymalna odlego, na jak widzi obserwator,
halfViewAngle poowa kta rozwarcia stoka kamer.
Metoda Render()
Omwiony wczeniej algorytm DDA realizowany jest w metodzie Render(). Parametrami wejciowymi do metody s:
wektor kierunku, w ktrym spoglda gracz (0 360 stopni),
wsprzdne pooenia gracza (wsprzdne globalne),
kontekst graficzny.
88
Ptla for obejmujca cay kod wewntrz metody render() zapewnia, e wszystkie obliczenia powtarzane s dla kadego paska ekranu z osobna. W ten sposb realizowane
jest rzucanie promienia dla kadego kta z zakresu stoka widzenia kamery.
W pierwszym kroku znajdujemy wsprzdne sektora, w ktrym znajduje si gracz.
Przypomnijmy, e kady sektor to kwadrat o dugoci boku rwnym 1 metr. Poprzez
rzutowanie wsprzdnych globalnych pooenia gracza do wartoci typu int pozbywamy si ich czci uamkowej. Wartoci te (s to szukane wsprzdne sektora) zapamitujemy w zmiennych ceilPosX oraz ceilPosY.
Nastpnie obliczamy wartoci nastpujcych wspczynnikw: a, b, dk, dl, k, l. Ich znaczenie oraz sposb obliczenia ju omwilimy. Aby obliczy wspczynnik a, od jedynki
odejmujemy warto wsprzdnej lokalnej gracza w sektorze (wzdu osi x ukadu
wsprzdnych patrz rysunek 3.7). Podobnie postpujemy obliczajc wspczynnik b.
Zestaw tych szeciu wspczynnikw posuy dalej do obliczania odlegoci od kolejnych punktw przecicia si promienia z poziomymi i pionowymi liniami wirtualnej siatki
wyznaczajcej sektory.
W zalenoci od wartoci kta, pod jakim biegnie rzucany promie, inicjalizowane s
dwie zmienne decyzyjne:
stepX przyjmuje warto dodatni (promie biegnie w praw stron), dla wartoci
89
Kod w ptli powtarzany jest a do momentu, gdy stwierdzona zostanie kolizja promienia
ze ciank labiryntu. Gdy stwierdzona zostanie kolizja, w zmiennej distance zapamitywana jest odlego od punktu kolizji. W zmiennej leftHit zapamitywana jest informacja pozwalajca zastosowa proste cieniowanie cianek labiryntu. cianki rwnolege do osi Y ukadu wsprzdnych bd janiejsze od tych rwnolegych do osi X.
Po wykryciu kolizji promienia ze ciank wykonanie ptli While jest przerywane. Nastpnie obliczana jest dugo pionowego paska na ekranie odpowiadajcego promieniowi i obliczonej odlegoci od punktu kolizji. Pasek ten ostatecznie jest rysowany na
ekranie przy uyciu metody drawLine.
Klasa Player
Obiekt tej klasy reprezentuje gracza poruszajcego si po labiryncie. W prawdziwej
grze klasa ta zawieraaby midzy innymi takie informacje, jak: ilo ywotw, zdobyte punkty, ilo energii i wiele innych zalenych od typu gry. W naszym przykadzie
gracz opisany jest najprostszymi parametrami. S to:
pozycja na mapie,
orientacja (kt obrotu),
parametry ruchu prdko poruszania i prdko rotacji.
Klasa Player udostpnia take metody suce do manipulacji tymi parametrami. Metody
moveForward oraz moveBackward pozwalaj porusza si odpowiednio do przodu i w ty.
Metody te wykrywaj te ewentualne przeszkody (takie jak ciany labiryntu), stojce
na drodze gracza, i odpowiednio modyfikuj wektor ruchu. Funkcje rotateRight oraz
rotateLeft pozwalaj graczowi obraca si wok wasnej osi pionowej.
package hello;
public class Player
{
private Raycaster r;
private float posX;
private float posY;
private int angle = 90;
/** Konstrukcja obiektu gracza */
public Player(Raycaster _r) {
r = _r;
}
private int getSpeed() {
return 1;
}
90
{ return posX; }
{ return posY; }
Klasa midletu
Poniewa nasz przykad nie uywa adnych (!) zasobw (grafik, dwiku itp.), kod klasy
midletu wyglda nastpujco:
package mypackage;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
91
Odlego t uzyskamy take, mnoc odlego euklidesow przez kosinus kta pomidzy promieniem a wektorem kierunku obserwatora.
Kta tego nie znamy, ale moemy go atwo obliczy. Na podstawie rysunku 3.9 widzimy, e odejmujc od kta kt , uzyskamy szukany kt pomidzy promieniem a kierunkiem, w ktrym patrzy gracz. Kt to kt pomidzy rzucanym promieniem a osi
92
Rysunek 3.9.
Rzutowanie wektora
odlegoci na kierunek
obserwacji
Rysunek 3.10. Bdny oraz poprawny podzia paszczyzny ekranu przez rzucane promienie
93
Metoda dokadna
W dalszej czci tego rozdziau zajmiemy si rozwizaniem problemu prawidowego
podziau rzutni (ekranu) przez rzucane promienie.
W metodzie dokadnej obliczamy wsprzdne wektora kierunku promienia, ktry biegnie
przez okrelony pasek powierzchni ekranu. Zmiana ta pociga za sob modyfikacje oblicze pozostaych wielkoci uywanych przez algorytm uproszczony.
Prost utworzon przez dwa wektory prostopade do kierunku, w ktrym zwrcony jest
gracz, dzielimy na N rwnych odcinkw. Warto N okrela poziom rozdzielczo
ekranu, a tym samym liczb promieni, ktre bdziemy ledzi.
Obliczamy wektor prostopady do wektora kierunku obserwacji. Jego wsprzdne
wyraone s wzorem:
Rysunek 3.12.
Podzia paszczyzny
ekranu oraz
znajdowanie wektora
kierunku rzucanego
promienia
94
Mnoc ten wektor przez odpowiedni wielko skalarn z zakresu [1,1] uzyskamy
wektor n, jak na powyszym rysunku. Wektor ten wyznacza punkt paszczyzny ekranu,
przez ktry przebiega bdzie rzucany promie. Wektor kierunku promienia obliczamy,
dodajc do siebie wektor n i prostopady do niego wektor kierunku obserwacji v:
r
r r
r (rx , ry ) = v + n
95
Modyfikacji ulega take sposb obliczenia rzutu odlegoci na wektor kierunku, w ktrym
spoglda gracz. Kosinus kta potrzebny do znalezienia rzutu moemy obliczy w dwojaki sposb:
Po pierwsze, wyraa si on ilorazem dwch wielkoci: moduu rzutu wektora
r wyznaczajcego promie.
Zalenoci te opisa moemy nastpujcym wzorem:
cos( ) =
v
dist
= r
dist
r
96
97
distance = 30/distance;
g.drawLine(x,screenHalfHeight - (int)distance,
x,screenHalfHeight + (int)distance);
x++;
Podsumowanie
Technika raycastingu, ktr poznalimy w tym rozdziale, okazaa si krokiem milowym w wiecie gier komputerowych. Jest potwierdzeniem znanej tezy, e geniusz tkwi
w prostocie. Wykorzystujc tak prost funkcjonalno jak rysowanie linii oraz proste
obliczenia na paszczynie, stworzylimy wraenie trjwymiarowoci wiata opisanego
przez dwuwymiarow tablic znakw.
98
Technika ta, po raz pierwszy zastosowana przez Johna Carmacka w grze Wolfenstein,
lega u podstaw takich gier jak Doom i przyczynia si do byskawicznego rozwoju
gier 3D. Bez raycastingu gry komputerowe nie byyby w miejscu, w ktrym znalazy
si obecnie. Kady programista gier komputerowych powinien wic zna t technik,
bo to znaczcy fragment historii gier komputerowych.
W rozdziale zaprezentowalimy jedynie podstawy techniki raycastingu. Zachcamy
Czytelnika do dalszego zgbiania tajnikw tej metody. Przez dodanie tekstur, podogi,
sufitu i przeciwnikw moemy tworzy przepikne gry 3D, ktre w dodatku nie bd
wymaga najnowszych technologicznie telefonw.
Pytania kontrolne
1. Czemu generowanie obrazu 3D metod raycastingu zawdzicza tak du
efektywno?
2. Opisz zasad dziaania algorytmu DDA.
3. Wyprowad wzr na odlegoci od pierwszego przecicia promienia
globalnego?
5. Co to jest i dlaczego powstaje efekt rybiego oka w metodzie raycastingu?
Zadania
1. Zmodyfikuj przykad tak, aby ciany labiryntu mogy mie dowolny kolor.
2. Wprowad kolor podogi oraz dodaj niebo (to) nad labiryntem.
3. W rozdziale 5. omwiona zostaa metoda billboardingu wywietlania paskich