Programowanie gier komputerowych Tomasz Martyn Wykład 4. Cykl produkcyjny wytwarzania gry (3): Prototypowanie gameplaya i UDK Kismet
Tworzenie logiki i mechaniki gry w UDK UnrealScript Językiem programowania w UDK, umożliwiającym m.in. tworzenie własnego typu gry, w szczególności implementowanie reguł logicznych oraz mechaniki gry, jest język UnrealScript. UnrealScript jest kompilowanym językiem obiektowym, przypominającym języki takie jak Java i C++ i bazującym na predefiniowanej hierarchii klas dostarczanych z UDK. U podłoża wielu z tych klas leży natywny kod C++ (niedostarczany wraz z darmową wersją UDK).
Tworzenie logiki i mechaniki gry w UDK Kismet Kismet jest wizualnym systemem programowania reguł logicznych, opisujących logikę i mechanikę gry. Programowanie polega na interaktywnym budowaniu grafów implikacji logicznych, opisujących zdarzenia, które mają miejsce podczas rozgrywki, oraz akcje, które należy wykonać po wystąpieniu tych zdarzeń, np.: Jeśli nastąpił respawn gracza, to: utwórz bota w danym miejscu na mapie, niech bot strzela do gracza przez 1 sec., po czym niech nie strzela przez 1 sec., po czym niech strzela przez 1 sec., po czy niech nie strzela przez 1 sec.,...
Tworzenie logiki i mechaniki gry w UDK Zalety Kismeta Dzięki zastosowanemu skryptowania wizualnego, znaczna część pracy mającej na celu zaimplementowanie reguł, logiki i mechaniki leżących u podstaw wytwarzanej gry, może być wykonywana przez Level designerów zamiast przez programistów. Skryptowanie wizualne wpływa zatem m.in. na zmniejszenie liczby potrzebnych interakcji level designerów z programistami, czego konsekwencją jest zwiększenie wydajności procesu prototypowania, tworzenia i testowania gameplaya.
Tworzenie logiki i mechaniki gry w UDK Kismet vs UnrealScript U podłoża bytów wykorzystywanych w Kismecie, leżą odpowiednie klasy UnrealScripta, zaś program utworzony w Kismecie przekłada się na odpowiedni kod unrealscriptowy. Rola programistów w zakresie tworzenia logiki gry może zostać w znacznej mierze ograniczona do tworzenia kodu odpowiedzialnego za zachowania (zdarzenia, akcje), które są na tyle specyficzne dla danej gry, że nie zostały jeszcze zaimplementowane, np: Jeśli postać znalazła się w obszarze promieniowania, to niech wyrośnie jej dodatkowa głowa w kształcie gąsiora do wina, po czym niech poszukuje ona winogron nawet w warunkach znacznego zagrożenia życia, powodowanych samobójczymi atakami eksplodujących ślimaków. Kod ten może by następnie przekazany w formie wizualnej, reprezentującej brakujące elementy Kismeta, level designerom.
Sekwencje W terminologii Kismeta, sekwencja to zbiór reguł postaci: zdarzenie akcje. Reguły wykonywane się niezależnie od siebie, tzn. wykonywanie ciągu akcji po wystąpieniu danego zdarzenia nie ma wpływu na możliwość uruchomienia innej reguły. Z każdym levelem skojarzona jest co najmniej jedna (być może pusta) sekwencja. Z kolei każda sekwencja może zostać podzielona na podsekwencje. Podsekwencje mogą reprezentować sobą pojedyncze reguły, ich zbiory, albo nawet wyróżnioną część reguły.
Obiekty składowe sekwencji (1) Podstawowymi elementami służącymi do budowania reguł są bloczki obiektów sekwencji (sequence objects): Events bloczki startowe reguł, reprezentujące zdarzenia, których zaistnienie podczas rozgrywki powoduje uruchomienie ciągu następujących po nich akcji; nie posiadają wejścia In, a jedynie wyjście Out, służce do przesłania sygnału uruchomieniowego do podłączonych do tego wyjścia bloczków; Actions bloczki reprezentujące akcje; posiadają wejścia In i Out, przez które przechodzi sygnał uruchomieniowy do następnych bloczków;
Obiekty składowe sekwencji (2) Conditions bloczki warunkowe, które uzależniają przekazanie sygnału wpływającego na wejście In na jedno ze swoich wyjść od spełnienia pewnego warunku; Variables kółeczka reprezentujące zmienne różnych typów standardowych (int, float, vector, bool,...), jak i również obiekty aktorów, listy obiektów aktorów oraz dane systemu animacji ramek kluczowych Matinee; Matinee bloczki uruchamiające animacje ruchu aktorów interpolacyjnych (InterpActor) w levelu, utworzonych za pomocą systemu Matinee.
Łączniki obiektu bloczka Obiekty bloczków mogą mieć następujące rodzaje łączników służących do połączenia z innymi obiektami składowymi sekwencji: wejścia sygnału uruchomieniowego - znajdujące się po lewej stronie bloczka, służące do łączenia z bloczkami poprzedzającymi; wyjścia sygnału uruchomieniowego znajdujące się po prawej stronie bloczka, służące do łączenia z bloczkami następnymi; łączniki zmiennych znajdujące się u dołu bloczka i służące do podłączania zmiennych określonych typów, przy czym występują: - łączniki zmiennych wejściowych w kształcie kwadracika, służące do przekazywania danych ze zmiennych do bloczka; - łączniki zmiennych wyjściowych w kształcie trójkącika, służące do przekazywania danych z bloczka do zmiennych; Typ dozwolonej zmiennej wyznaczony jest przez kolor łącznika tożsamy z kolorem symbolu kółeczka zmiennej, przy czym nie można podłączyć do łącznika zmiennej innego typu bez dokonania jawnego rzutowania.
Najprostsze przykłady Winda - mesh reagujący na kontakt z postacią Przycisk dwustanowy trigger uruchamiający animację Matinee, na przemian w przód i wstecz
Pętla Forever Reguły mogą zawierać nieskończone pętle, przy czym ich wykonywanie nie tamuje wykrycia zdarzeń i przepływu sygnału w pozostałych składowych sekwencji.
Pętla For Pętle For wykonywane skończoną liczbę razy można utworzyć przy wykorzystaniu bloczka Int Counter albo Float Counter (oba bloczki należą do kategorii obiektów Conditions).
Pętle While i Do-While Analogicznie można implementować pętle While i Do-While, umieszczając jeden z bloczków Conditions, odpowiedno, na początku, albo na końcu pętli.
Rodzaje zmiennych zmienne nieokreślone - niektóre obiekty aktorów nie istnieją podczas projektowania levela, np. postaci, które tworzone są dopiero podczas rozgrywki. Obiekty te w sekwencjach Kismeta reprezentowane są przez zmienne obiektów oznaczanych kółeczkami ze znakami zapytania, zaś ich wartości ustanawiane są dopiero w trakcie realizacji odpowiednich bloczków. zmienne losowe są to zmienne liczbowe typu Random Int i Random Float, których wartości są ustalane w sposób losowy z określonego zakresu przy każdym odwołaniu do tej zmiennej. zmienne globalne każdej ze zmiennych można nadać nazwę wypełniając pole właściwości Var Name i następnie odwoływać się do tej zmiennej na zasadach referencji z C++ przy wykorzystaniu zmiennych typu Named Variable. Dzięki temu: - ze zmiennej mogą korzystać różne reguły tego samego levela, w szczególności reguły podsekwencji (patrz Proceduralizm) - zmniejsza się liczba połączeń do tego samego kółeczka, co czyni sekwencje Kismeta bardziej czytelnymi.
Proceduralizm (1) Wykorzystanie funkcjonalności tzw. podsekwencji (subsequences) czyni możliwym stworzenie jednego bloczka zawierającego w sobie regułę, jej część lub nawet kilka reguł.
Proceduralizm (2) Bloczek podsekwencji reprezentuje w sensie funkcjonalnym to, co w sobie zawiera, i jego instancje mogą być wykorzystywane w regułach kismetowych na zasadach procedury.
Następny wykład: Kismet przykłady programowania