ArmA 2 - Przerywniki filmowe
Przerywniki filmowe. Bardzo ważna rzecz i nieodłączny element każdej bardziej zaawansowanej misji. Pozwalają bliżej przedstawić fabułę i postacie, w które przyjdzie nam się wcielić bądź z nimi współpracować. Mogą także służyć po prostu jako chwila oddechu po wykonaniu jakiegoś szczególnie trudnego zadania. Pokuszę się więc o stwierdzenie, że tworzenie cutscenek powinno być nieodłączną umiejętnością każdego szanującego się missionmakera.W niniejszym poradniku opiszę tworzenie przerywników filmowych za pomocą skryptu "camera.sqs" jest rzeczą bardzo mało skomplikowaną, wymagającą jedynie podstawowej wiedzy w dziedzinie skryptowania ArmA 2. Zakładam jednak, że nie wszyscy takową posiadają, więc postaram się krok po kroku przedstawić, co należy zrobić, by cieszyć się intrem w swojej misji.
Od razu muszę zaznaczyć, że metoda którą tu zaprezentuję nadaje się jedynie do tworzenia cutscenek podobnych do tych, które mogliśmy oglądać w Operation Flashpoint i pierwszej ArmA. Pół-interaktywne sceny z widokiem z oczu postaci, występujące w kampanii ArmA 2, to już zupełnie inna para butów - nie będę się nimi tu zajmował, jednak spróbuję pod koniec poradnika wyjaśnić pokrótce "o co tam idzie".
Na początek dobrze byłoby mieć jakąś misję, na której można by ćwiczyć moviemaking. Posłużę się tu misją przykładową, która w żadnym razie nie ma prawa konkurować do miana prawdziwej cutscenki.
Wchodzimy więc do edytora, odpalamy dowolną wyspę i przestawiamy w polu nad oknem "WYWIAD" z "Misja" na "Intro". Nie ma to wielkiego znaczenia, jednak chciałbym, by nie pojawiły się żadne komplikacje. Następnie wstawiamy gdzie nam się podoba, dwóch żołnierzy i pojazd, dajmy na to, UAZA. Nie ma większego znaczenia, w jakiej konfiguracji. Gdzieś niedaleko, na uboczu, wstawiamy jednostkę gracza, najlepiej cywila. Obu żołnierzy nazywamy, przykładowo, Q1 i Q2. UAZA nazywamy (cóż za zaskoczenie!) UAZ. Ostatnia rzecz - wstawiamy wyzwalacz. Kasujemy wartości dla osi (bo niepotrzebne), ustawiamy TYP na Koniec #1, a w warunku zamiast true wpisujemy finish. Wyzwalacz przyda przy zakończeniu intra. Zapisujemy misję, nazywając ją jakże oryginalnie, "test1".
Mamy więc już gotowe pole do tworzenia cutscenki. Zanim się do tego zabierzemy, należy jeszcze stworzyć odpowiedni plik skryptu, w którym stworzymy kamerę, będziemy wydawać jej polecenia, i nie tylko. W tym celu Alt-tabujemy się z Army 2 na pulpit (dla niekumatych - wciskamy ALT+TAB, co spowoduje wyjście na pulpit i wrzucenie gry na pasek zadań). Przechodzimy do folderu misji "test1", zakopanym gdzieś w Moje dokumenty/ArmA 2/missions. Odpalamy notatnik. Nic nie wpisując wykonujemy następującą operację - klikamy: plik -> zapisz jako, nazywamy plik Intro.sqs oraz w polu typ plików wybieramy "wszystkie pliki" i zapisujemy to w folderze misji.
Świetnie! Mamy pusty plik skryptu. A teraz wracamy z powrotem do ArmA 2.
Na potrzeby tworzenia cutscenki należy odpalić wspominany wcześniej skrypt "camera.sqs". Jest on integralną częścią A2, więc nie trzeba go ściągać ani nic z tych rzeczy. Po prostu wpisujemy jednej z postaci w inicjacji następujące polecenie - this exec "camera.sqs". Spowoduje to utworzenie ręcznie sterowanej kamery w miejscu tejże jednostki. Kamerą można dowolnie sterować, co pozwoli nam na dokładne kadrowanie ujęć. Zresztą nie musicie wierzyć mi na słowo - wciśnijcie przycisk "Podgląd" i przekonajcie się sami. Teraz uwaga - w trybie "Intro" kamera nie powinna mieć czarnych pasków u góry i u dołu, czyli tzw. cinemaborder. Jeśli jednak tam są, wpiszcie w inicjacji postaci jeszcze showcinemaborder false. Powinno pomóc.
A teraz zaczyna się zabawa. Poniżej przedstawiam klawiszologię "camery.sqs":
Klawisze WSAD, kursory, myszka - poruszanie w poziomie
Q i Z - poruszanie góra/dół
8, 4, 6, i 2 na klawiaturze numerycznej - obracanie kamery
+ i - na klawiaturze numerycznej - przybliżanie i oddalanie obrazu (zmiana FOV)
5 na klawiaturze numerycznej - ustawienie FOV na 0.700, czyli powrót do normalnego zbliżenia
SHIFT i klawisz odpowiadający za ruch - przyspieszenie kamery (taki sprint)
LPM - zapisanie pozycji kamery do schowka i do ArmA.rpt
RPM - wyłączenie skryptu
L - wyłączenie "krzyżaka" pośrodku ekranu
F - zablokowanie kamery na wycelowanym obiekcie
W tym miejscu warto poświęcić kilka chwil na zapoznanie i oswojenie się z kamerką. Kiedy już będziemy chcieli kontynuować, wciśnijmy Esc i nie wychodząc z odpalonej rozgrywki wróćmy na pulpit.
Same polecenia pozycji kamery niestety nie wystarczą by stworzyć intro. Odpalamy więc stworzony wcześniej skrypt Intro.sqs. Na razie jest pusty, lecz właśnie zaczynamy wypełniać go tekstem:
;==INTRO
TitleCut ["","BLACK IN", 4]
showcinemaborder false
_camera = "CAMERA" CamCreate [0,0,0]
_camera CameraEffect ["INTERNAL","BACK"]
A teraz objaśniam, co wykonują kolejne polecenia.
;==INTRO - jest to komentarz. Pamiętajmy, że linię komentarza w skrypcie zawsze zaczynamy znakiem średnika ( ; ). Nic nie robi - wstawiłem go tylko po to, by go wprowadzić.
TitleCut ["","BLACK IN", 4] - rozjaśnienie obrazu od maksymalnie czarnego do zera w ciągu czterech sekund. Przydatny efekt estetyczny.
showcinemaborder false - poruszone wyżej. Warto wpisać, tak na wszelki wypadek.
_camera = "CAMERA" CamCreate [0,0,0] - polecenie tworzy kamerę o nazwie _camera w punkcie [0,0,0]. Takie jej położenie jest nam do niczego niepotrzebne, ale za chwilę będziemy je zmieniać skryptem "camera.sqs".
_camera CameraEffect ["INTERNAL","BACK"] - dzięki temu po prostu uzyskujemy normalny obraz.
Dwa ostatnie polecenia są niezbędne, by stworzyć kamerę. Zapisujemy plik. Wracamy do A2.
Gdybyśmy teraz odpalili skrypt, moglibyśmy pooglądać sobie morskie fale i posłuchać ich szumu w miejscu o koordynatach [0,0,0]. Teraz trzeba skorzystać z "camery.sqs" i ustawić kamerę tam, gdzie trzeba. Zakładam, że dalej macie włączoną grę i odpalony skrypt "camera.sqs", więc przejdźmy od razu do jej ustawiania.
Otóż jest to rzecz banalna - ustawiamy kamerę gdzie chcemy, jak chcemy, tak byśmy mieli jak najładniejsze ujęcie. Powiedzmy - dla przykładu możemy wycelować w żołnierza Q1, tak by kadr objął go całego. Następnie wciskamy LPM[b] i już mamy odpowiednie dane w schowku.
Teraz wracamy do naszego skryptu [b]"Intro.sqs". Pod wpisanymi już poleceniami wklejamy z schowka dane położenia kamery. Powinny wyglądać podobnie do tych:
;=== 13:59:02
_camera camPrepareTarget [-81161.27,-48021.30,-7899.07]
_camera camPreparePos [4340.07,3229.94,1.14]
_camera camPrepareFOV 0.700
_camera camCommitPrepared 0
@camCommitted _camera
Jak pewnie zauważyliście, te dane są jednocześnie poleceniami dla kamery. Małe objaśnienie, mimo iż owe polecenia są chyba dość jasne:
;=== 13:59:02 - komentarz
_camera camPrepareTarget [-81161.27,-48021.30,-7899.07] - polecenie wycelowania kamery w miejsce o danych koordynatach.
_camera camPreparePos [4340.07,3229.94,1.14] - ustawienie kamery na danej pozycji
_camera camPrepareFOV 0.700 - zoom, czyli FOV
_camera camCommitPrepared 0 - bardzo ważne. Wartość liczbowa oznacza czas (w sekundach), w jakim kamera przemieści się z poprzedniej pozycji w tą, której dane są powyżej. Dla zera jest to oczywiście nagła zmiana miejsca. Polecenie to musi wystąpić, gdyż bez niego nic się nie stanie.
@camCommitted _camera - jest to warunek, a nie polecenie (warunki rozpoczynają się znakiem @ lub ?). Oznacza on, że skrypt może działać dalej, gdy kamera zrealizuje swój ruch. W tym wypadku polecenie jest zbędne (radzę usunąć), gdyż CamCommit = 0, ale gdyby było na przykład _camera camCommitPrepared 5, to skrypt ruszył by dalej po pięciu sekundach.
Jeśli teraz włączymy nasz skrypt "Intro.sqs", powinniśmy uzyskać poprawny obraz. Jednak jedno ujęcie to jeszcze nie przerywnik filmowy. Jedziemy więc dalej - wracamy do A2 i kadrujemy znowu. Tym razem zróbmy zbliżenie na twarz żołnierza. Możemy ruszyć kamerę kawałek do przodu i koniecznie należy zwiększyć FOV. Zawsze lepiej wygląda ujęcie dalej od celu, ale przy dużym zoomie niż odwrotnie. Oczywiście bez przesady - grafika może stracić na szczegółowości przy dużym oddaleniu. Kiedy zrobimy, co mamy zrobić i wkleimy nowe dane do skryptu, powinniśmy uzyskać w sumie coś takiego:
;==INTRO
TitleCut ["","BLACK IN", 4]
showcinemaborder false
_camera = "CAMERA" CamCreate [0,0,0]
_camera CameraEffect ["INTERNAL","BACK"]
;=== 13:59:02
_camera camPrepareTarget [-81161.27,-48021.30,-7899.07]
_camera camPreparePos [4340.07,3229.94,1.14]
_camera camPrepareFOV 0.700
_camera camCommitPrepared 0
;=== 14:11:33
_camera camPrepareTarget [-58186.34,-60568.88,44976.16]
_camera camPreparePos [4339.25,3229.22,1.10]
_camera camPrepareFOV 0.211
_camera camCommitPrepared 0
@camCommitted _camera
Będę nazywał kolejna ujęcia "godzinowo", czyli względem komentarza, który jest u góry poleceń. Jak widzicie, pozwoliłem sobie usunąć warunek w ujęciu 13:59. Mając taki skrypt uzyskamy jednakże tylko jeden obraz - ten drugi. Żeby wystąpiło płynne przejście z całej sylwetki żołnierza do jego twarzy, należy zmienić liczbę przy poleceniu _camera camCommitPrepared 0 w ujęciu 14:11 na jakąś inną, np. 7. Wtedy, co już wiemy, skrypt ruszy dalej po 7 sekundach (zresztą na razie i tak nie ruszy, bo dalej nic nie ma). Ale chwila - a jeśli chcemy by ruszył po 10 albo 15, ale zbliżenie ma trwać tyle samo, to co wtedy? Trzeba posłużyć się poleceniem zatrzymania działania skryptu. Nie jest to nic trudnego w osobnej linii, pod spodem, wpisujemy ~ a następnie odpowiednią liczbę, np. ~10. Po zmianach opisanych wyżej wygląda to tak:
;==INTRO
TitleCut ["","BLACK IN", 4]
showcinemaborder false
_camera = "CAMERA" CamCreate [0,0,0]
_camera CameraEffect ["INTERNAL","BACK"]
;=== 13:59:02
_camera camPrepareTarget [-81161.27,-48021.30,-7899.07]
_camera camPreparePos [4340.07,3229.94,1.14]
_camera camPrepareFOV 0.700
_camera camCommitPrepared 0
;=== 14:11:33
_camera camPrepareTarget [-58186.34,-60568.88,44976.16]
_camera camPreparePos [4339.25,3229.22,1.10]
_camera camPrepareFOV 0.211
_camera camCommitPrepared 7
~10
Mam nadzieję, że macie teraz już pojęcie, jak mniej więcej wygląda skrypt intra i jak się go tworzy. Jest to jednak dopiero początek. Powiedzmy, że chcemy, aby drugi żołnierz wszedł do UAZa i odjechał nim (jeśli zajdzie potrzeba - zmień teraz ich ustawienie, nie ruszaj jednak pierwszego żołdaka, którego filmowaliśmy). Zrobimy 2 ujęcia i wydamy odpowiednie polecenia. Powiedzmy - pierwszy kadr obejmuje sołdata i UAZ, następnie szybkie i płynne czterosekundowe przejście do drugiego kadru, który będzie wycelowany w UAZA, odjazd i za parę sekund ściemnienie i koniec.
Skrypt z trzecim już ujęciem będzie wyglądać tak:
;==INTRO
TitleCut ["","BLACK IN", 4]
showcinemaborder false
_camera = "CAMERA" CamCreate [0,0,0]
_camera CameraEffect ["INTERNAL","BACK"]
;=== 13:59:02
_camera camPrepareTarget [-81161.27,-48021.30,-7899.07]
_camera camPreparePos [4340.07,3229.94,1.14]
_camera camPrepareFOV 0.700
_camera camCommitPrepared 0
;=== 14:11:33
_camera camPrepareTarget [-58186.34,-60568.88,44976.16]
_camera camPreparePos [4339.25,3229.22,1.10]
_camera camPrepareFOV 0.211
_camera camCommitPrepared 7
~10
;=== 14:28:10
_camera camPrepareTarget [37237.31,95349.46,-20733.70]
_camera camPreparePos [4336.43,3227.45,1.78]
_camera camPrepareFOV 0.589
_camera camCommitPrepared 0
Teraz jak zmusić tego dziada, żeby łaskawie wsiadł do łazika? Wpisujemy następujące polecenia:
[Q2] OrderGetIn true - żeby AI raczyło łaskawie akceptować polecenia AssignAs...
Q2 AssignAsDriver UAZ - praktycznie wydaje jednostce rozkaz, by wsiadła do pojazdu UAZ na miejsce kierowcy (ale nie wsadza go tam!)
@Q2 In UAZ - warunek, kiedy Q2 będzie w pojeździe UAZ, skrypt ruszy dalej
Kiedy dzielny wojak Q2 będzie sadowił się w wozie, należy wprowadzić czwarte ujęcie. Proponuję tuż za pojazdem. Załóżmy jednak, że chcemy mieć pewność, że UAZ cały czas będzie znajdował się w polu widzenia. W takim wypadku kamera musi "śledzić" wóz. W poleceniu camPrepareTarget czwartego ujęcia zamiast pola liczbowego wpisujemy po prostu nazwę pojazdu. Oczywiście pamiętamy też o zmianie CamCommit. W sumie wygląda to tak:
;==INTRO
TitleCut ["","BLACK IN", 4]
showcinemaborder false
_camera = "CAMERA" CamCreate [0,0,0]
_camera CameraEffect ["INTERNAL","BACK"]
;=== 13:59:02
_camera camPrepareTarget [-81161.27,-48021.30,-7899.07]
_camera camPreparePos [4340.07,3229.94,1.14]
_camera camPrepareFOV 0.700
_camera camCommitPrepared 0
;=== 14:11:33
_camera camPrepareTarget [-58186.34,-60568.88,44976.16]
_camera camPreparePos [4339.25,3229.22,1.10]
_camera camPrepareFOV 0.211
_camera camCommitPrepared 7
~10
;=== 14:28:10
_camera camPrepareTarget [37237.31,95349.46,-20733.70]
_camera camPreparePos [4336.43,3227.45,1.78]
_camera camPrepareFOV 0.589
_camera camCommitPrepared 0
[Q2] OrderGetIn true
Q2 AssignAsDriver UAZ
@Q2 In UAZ
;=== 14:36:23
_camera camPrepareTarget UAZ
_camera camPreparePos [4344.19,3233.78,1.78]
_camera camPrepareFOV 0.306
_camera camCommitPrepared 4
@camCommitted _camera
Należy jeszcze wydać żołnierzowi polecenie ruchu gdzieś przed siebie. Żeby pojechał, musi jednak mieć gdzie. Niestety, nie wstawiliśmy żadnego punktu odniesienia. Wracamy do edytora i wrzucamy odpowiedni wyzwalacz kawał przed UAZem. W polu "nazwa" wpisujemy na przykład "pozycja". Teraz wystarczy tylko w naszym skrypcie wpisać (najlepiej pomiędzy camCommitPrepared a @camCommitted) polecenia (koniecznie w tej kolejności)
[Q2] SetSpeedMode "LIMITED" - zmiana szybkości poruszania się jednostki (po resztę odsyłam do ComRefu) na, w tym przypadku, ograniczoną. Jest to czysta kosmetyka, którą dodałem tylko po to, by uzmysłowić wam kolejność wydawania obu poleceń.
Q2 doMove GetPos pozycja - jak widać wydajemy rozkaz jednostce siedzące w pojeździe, a nie samemu pojazdowi. Q2 (teoretycznie - AI potrafi być bardzo... nieprzewidywalne w tej kwestii) bezzwłocznie ruszy do wyzwalacza "pozycja".
Dobra. Teraz czeka nas jeszcze zakończenie filmiku. Damy Q2 sześć sekund na odjazd z miejsca, po czym ściemnimy obraz, wywalimy kamerę i zakończymy misję. Następującymi poleceniami:
~2 - CamCommit wynosi cztery sekundy, więc dodajemy jeszcze dwie, żeby razem było sześć. Zresztą to chyba oczywiste.
TitleCut ["","BLACK OUT",3] - ściemniamy obraz w ciągu trzech sekund.
3 fadesound 0 - w ciągu trzech sekund ścisza dźwięk do zera. Przydatny efekt kosmetyczny.
~3 - czekamy, aż się ściemni do końca.
_camera CameraEffect ["TERMINATE","BACK"] - wyłączamy obraz z kamery.
CamDestroy _camera - usuwamy kamerę _camera.
finish = true - aktywujemy wstawiony na początku wyzwalacz (pamiętacie jeszcze początek?), co natychmiastowo kończy misję. UWAGA - należy najpierw skasować obraz i kamerę, inaczej zakończenie po prostu nie zadziała. Czyli ma być tak jak napisałem.
exit - kończy skrypt. W sumie niepotrzebne, gdyż misja już się zakończyła.
I voila - gotowe:
;==INTRO
TitleCut ["","BLACK IN", 4]
showcinemaborder false
_camera = "CAMERA" CamCreate [0,0,0]
_camera CameraEffect ["INTERNAL","BACK"]
;=== 13:59:02
_camera camPrepareTarget [-81161.27,-48021.30,-7899.07]
_camera camPreparePos [4340.07,3229.94,1.14]
_camera camPrepareFOV 0.700
_camera camCommitPrepared 0
;=== 14:11:33
_camera camPrepareTarget [-58186.34,-60568.88,44976.16]
_camera camPreparePos [4339.25,3229.22,1.10]
_camera camPrepareFOV 0.211
_camera camCommitPrepared 7
~10
;=== 14:28:10
_camera camPrepareTarget [37237.31,95349.46,-20733.70]
_camera camPreparePos [4336.43,3227.45,1.78]
_camera camPrepareFOV 0.589
_camera camCommitPrepared 0
[Q2] OrderGetIn true
Q2 AssignAsDriver UAZ
@Q2 In UAZ
;=== 14:36:23
_camera camPrepareTarget UAZ
_camera camPreparePos [4344.19,3233.78,1.78]
_camera camPrepareFOV 0.306
_camera camCommitPrepared 4
[Q2] SetSpeedMode "LIMITED"
Q2 doMove GetPos pozycja
@camCommitted _camera
~2
TitleCut ["","BLACK OUT",3]
3 fadesound 0
~3
_camera CameraEffect ["TERMINATE","BACK"]
CamDestroy _camera
finish = true
exit
Teraz tylko trzeba odpalić intro i cieszyć się jego oglądaniem. W tym celu zapisujemy plik "Intro.sqs" i wychodzimy z niego. Wracamy do edytora. W polu inicjacji tej jednostki, która miała wpisywane wcześniej polecenia, kasujemy wszystko i wrzucamy: [] exec "Intro.sqs". Następnie klikamy "Podgląd" i oglądamy.
I to by było na tyle. Mam nadzieję, że po przeczytaniu tego poradnika poznaliście podstawy tworzenia przerywników filmowych. Cała reszta - to już tylko dodawanie dźwięków, muzyki, zarządzanie poruszaniem się postaci (co czasem potrafi nieźle napsuć krwi) oraz reszta szczegółów. To już jednak wymaga po prostu podszkolenia się w wiedzy skryptowej.
Na koniec chciałbym pokrótce opisać przerywniki filmowe stosowane w ArmA 2. Otóż jest to po prostu wyłączenie HUD-a, zablokowanie kamery na FPP i stosowanie odpowiednich animacji oraz PPEffects. Z punktu widzenia missionmakera, żadna filozofia. Wystarczy mieć tylko animacje. A że stworzenie tychże jest raczej poza możliwościami scenowca a odpowiednie dopasowanie wymaga mnóstwa żmudnej roboty, to nie poruszałem tego tematu w niniejszym poradniku.