35
Wstęp Elementy skladowe Calość Programowanie gier 2D Podstawowe koncepcje Filip Sobalski 30.03.2011 Filip Sobalski Programowanie gier 2D

2D sprite engine - basic concepts

Embed Size (px)

Citation preview

Page 1: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

Programowanie gier 2DPodstawowe koncepcje

Filip Sobalski

30.03.2011

Filip Sobalski Programowanie gier 2D

Page 2: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

Wszystko to iluzja

Cel: Jak oszukać gracza?Jak uzyskać efekt, który będzie zgodny z wyobrażeniami graczanajmniejszym nakładem obliczeń i pamięci.

Czyli...Wszystkie chwyty dozwolone – liczy się tylko efekt.

Filip Sobalski Programowanie gier 2D

Page 3: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

Duszki i inne potworności

Sprite

W dosłownym tłumaczeniu znaczy „duszek”. Podstawowy elementgraficzny, czyli - w skrócie - obrazek, który zmienia położenie. W nowychimplementacjach to będzie obiekt zawierający także wszystkie informacjeo postaci, potworku czy innym elemencie gry.

Sprite Engine

Odpowiada za rysowanie Sprite’ów, zwykle także za ich animację,detekcję kolizji, etc... Kiedyś implementowany sprzętowo, teraznajczęściej przez oprogramowanie.

Filip Sobalski Programowanie gier 2D

Page 4: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Grafika

1 Wstęp

2 Elementy składoweGrafikaRuchDetekcja kolizji

3 Całość

Filip Sobalski Programowanie gier 2D

Page 5: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Bit blit

Bit-blitting

Blokowy (vide: scanlines) transfer danych z obrazka źródłowego dodocelowego (zwykle bufor graficzny) często z użyciem operatorarastrowego (ROP). ROP to nic innego jak operator bitowy - AND, OR,XOR.

Zwykle użyjemy do tego biblioteki korzystającej wyłącznie z CPU (np.SDL) lub zlecimy rysowanie wyspecjalizowanemu sprzętowi (np.OpenGL).

Filip Sobalski Programowanie gier 2D

Page 6: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Przezroczystość

maskowanieNajpierw rysujemy 1-bitową maskę z operacją AND a potem w tymsamym miejscu rysujemy właściwy obrazek z operacją OR. Danypiksel może być przezroczysty lub nie.

colorkeyUżywane przy grafice z paletą. Wybieramy indeks palety, który mabyć przezroczysty i każdy piksel źródłowy o tej wartości jestignorowany przy blitting’u.

alpha blendingDziś to najczęściej stosowane rozwiązanie. ROP zastępujemyoperatorem matematycznym mieszającym kolory z uwzględnieniemdodatkowego kanału alpha.

Filip Sobalski Programowanie gier 2D

Page 7: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Przezroczystość - maskowanie

Rysunek: 1-bitowa maska

Rysunek: rezultat poszczególnych kroków maskowania

Filip Sobalski Programowanie gier 2D

Page 8: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Przezroczystość - colorkey

Rysunek: sprite przygotowany do metody colorkey

Uwaga!

Stratna kompresja w przypadku sprite’ów i masek to zło!

Filip Sobalski Programowanie gier 2D

Page 9: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Przezroczystość - alpha blending

Mieszamy składowe piksli w proporcjach określonych przez kanał alfa.

s - piksel źródłowyd - piksel docelowy

k ∈ {R,G ,B}dk , sk , sA ∈ [0, 1]

blended componentk = dk × (1− sA) + sk × sA

Filip Sobalski Programowanie gier 2D

Page 10: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Kolejność rysowania - warstwy

Stała ilość warstw - dla każdej warstwy osobna lista sprite’ówDowolna ilość warstw - nr warstwy przypisany do sprite’aSortujemy co klatkę. [stabilny algorytm sortowania]Każdego nowego sprite’a wstawiamy w odpowiednie miejsce. [a’lainsertion sort]

Filip Sobalski Programowanie gier 2D

Page 11: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Viewport clipping

Viewport

Zwykle zdefiniowany przez położenie bezwzględne (w układzie wsp.świata) i wymiary; określa, który fragment sceny widać na ekranie.

Rysujemy tylko te sprite’y, których aktualne obrazki nakładają się na naszviewport. Wygodnie tutaj zastosować bounding box ale o tym później.

Położenie pod którym narysujemy sprite’a to prostu różnica wektorowajego położenia i położenia viewportu. Warto jednak wyróżnić sprite’yktórych położenie będziemy definiować względem viewportu - użytecznedo wyświetlania punktacji, ilości naboi etc.

Uwaga

W każdej klatce rysujemy wszystko od nowa. Można rysować tylko toco zmieniło się od ostatniej klatki, jednak dziś nie ma sensu stosować tejtechniki.

Filip Sobalski Programowanie gier 2D

Page 12: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Podwójne buforowanie

Podwójne buforowanie razem z synchronizacją pionową (v-sync)rozwiązuje problem tearing’u.

1 Narysuj w buforze off-screen scenę.

2 Zamień miejscami wartości wskaźników pokazujących na buforoff-screen i display.

3 Narysuj na ekranie bufor display w momencie kiedy monitor skończyłrysować poprzednią klatkę ale nie zaczął następnej.

W praktyce wszystkim zajmie się biblioteka. Nas interesuje buforoff-screen oraz musimy pamiętać o wywołaniu funkcji typu SwapBufferspo narysowaniu sceny.

Filip Sobalski Programowanie gier 2D

Page 13: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Ruch

1 Wstęp

2 Elementy składoweGrafikaRuchDetekcja kolizji

3 Całość

Filip Sobalski Programowanie gier 2D

Page 14: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Dyskretyzacja ruchu

Jak?Dlaczego nie ma już w obudowach przycisku turbo?

Lag

Czas w sekundach mierzony od ostatniej klatki.

Skalujemy wszystko przez lag.

Caveat

Nawet jeśli nie rysujemy z podpikslową precyzją wszystko trzymamy wefloat’ach! Obcinamy wtedy kiedy potrzebujemy int’a.

Filip Sobalski Programowanie gier 2D

Page 15: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Animacja

frame ← frame + animation speed × lag

Nie obcinamy części ułamkowych!

Zawijamy: (lub odbijamy w przypadku oscylacji)

i f ( f rame >= t o t a l f r a m e s )frame −= t o t a l f r a m e s ;

Filip Sobalski Programowanie gier 2D

Page 16: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Animacja - wyrównywanie klatek

Sposób nr 1Każda klatka (obrazek) animacji ma tę samą wielkość. Położenie sprite’aokreślamy względem stałego punktu obrazka (np. lewego-górnego rogu -[0, 0]).

Sposób nr 2Każda klatka animacji ma określony punkt względem którego będziemyją pozycjonować na ekranie - nazwijmy go grab point. Znajdujemy punktodniesienia na naszym animowanym obiekcie i jego pozycja w każdejklatce będzie stanowiła grab point.Sposób nr 2 jest rozszerzeniem sposobu nr 1.

Filip Sobalski Programowanie gier 2D

Page 17: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Grab point

Ten punkt będzie wydawał się stać w miejscu podczas animacji.

Rysunek: przykładowe umieszczenie gp

Gdzie rysujemy lewy-górny róg sprite’a?~sprite screen pos ← ~sprite pos − ~frame gp

Filip Sobalski Programowanie gier 2D

Page 18: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Przemieszczenie

Prędkość to nie problem...~sprite pos ← ~sprite pos + ~sprite velocity × lag

Co z przyśpieszeniem?~sprite velocity ← ~sprite velocity + ~sprite accelleration × lag

Przykład - grawitacja~sprite velocity ← ~sprite velocity + (0, gravity)× lag

Czy widać tutaj jakiś problem?

Filip Sobalski Programowanie gier 2D

Page 19: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Przybliżenie...

Rysunek: 10 FPS

Filip Sobalski Programowanie gier 2D

Page 20: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Przybliżenie... c.d.

Rysunek: 30 FPS

Filip Sobalski Programowanie gier 2D

Page 21: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Detekcja kolizji

1 Wstęp

2 Elementy składoweGrafikaRuchDetekcja kolizji

3 Całość

Filip Sobalski Programowanie gier 2D

Page 22: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Bounding box

Szybki test BB vs. BB

Często wystarczy jako jedyna metoda detekcji kolizji

Dobra metoda dla pierwszej fazy (pruning)

Kiepsko aproksymuje kształty.

Filip Sobalski Programowanie gier 2D

Page 23: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Bounding circle

Szybki test BC vs. BC i BB vs. BC

Dobrze nadaje się do aproksymacji tylko niektórych kształtów, np.pocisków

Dobra metoda dla pierwszej fazy

Filip Sobalski Programowanie gier 2D

Page 24: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Per-pixel collision test

Bardzo powolny test, nawet z bitmaską

Nienaturalny efekt

Ze skalowaniem i obrotem to koszmar

Tylko vs. per-pixel

Tylko do drugiej fazy

Filip Sobalski Programowanie gier 2D

Page 25: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Ograniczenie wielokątami wypukłymi

Relatywnie szybkie

Łatwo dowolnie przekształcić

Tylko do drugiej fazy

Jak? Separating Axis Theorem

Filip Sobalski Programowanie gier 2D

Page 26: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Ograniczenie wielokątami

Co z wklęsłymi?

1 Podziel na trójkąty (tesselacja)

2 Zachłannie łącz z powrotem w wypukłe wielokąty.

3 Dla każdego wielokąta z otrzymanego zbioru wylicz bounding box idodaj kolejną fazę...

Filip Sobalski Programowanie gier 2D

Page 27: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Co robimy kiedy nastąpi kolizja?

Przewidujemy kolizję z wyprzedzeniem ;)

Cofamy do poprzedniej pozycji - kiepski efekt przy dużej prędkości

Cofamy się małymi kroczkami wzdłuż wektora przemieszczenia ażkolizja przestanie zachodzić

Jeśli metoda detekcji pozwala to liczymy wektor „zagłębienia” iodejmujego go od pozycji. (Wielokąty FTW!)

Filip Sobalski Programowanie gier 2D

Page 28: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Potencjalne problemy

Niski framerate i/lub duża prędkość - jeden sprite przeskoczy drugi.Nie ma dobrego rozwiązania. Można ruch pomiędzy klatkamisprowadzić do postaci ciągłej.Zakleszczenie:

1 Zmiana klatki animacji na „większą” w trakcie kolizji/zaraz pocofnięciu. (Częste przy teście per-pixel.)

2 Błędy zaokrągleń.3 Dwa sprite’y poruszające się na raz.

Specjalne przypadki - np. gracz spada na płaską powierzchnię czychodzi po niej, ślizganie się, etc.

Niska wydajność.

Filip Sobalski Programowanie gier 2D

Page 29: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Wydajność, wydajność, wydajność...

Naiwne podejście - sprawdzić każdy obiekt z każdym - nieakceptowalniepowolne przy dużej liczbie obiektów.Propozycje:

Wykluczyć z testów obiekty dla których detekcja kolizji nam jest niepotrzebna.

Podzielić obiekty na klasy i wykluczyć z testów pary klas, które napewno nie będą kolidować lub włączyć jedynie te pary, którychkolizja nas interesuje.

Indeksowanie przestrzenne - np. quadtrees (octrees w 3D), siatkaobszarów.

Przy skomplikowanych testach dodać więcej faz (ale nie za dużo!).

Liczyć przekształcenia tylko w ostatniej fazie.

Zrezygnować z powyższych sposobów detekcji kolizji jeśli specyfikagry na to pozwala. ;) (KISS)

Filip Sobalski Programowanie gier 2D

Page 30: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

GrafikaRuchDetekcja kolizji

Quadtree

Filip Sobalski Programowanie gier 2D

Page 31: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

Ograniczenie ilości FPS

Prosty sposób - sleep/delay w głównej pętli - nie skaluje się.

Uniwersalny sposób - sleep/delay adaptujący się do czasu wykonaniapętli

I zapewne wiele innych...

Filip Sobalski Programowanie gier 2D

Page 32: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

Adaptive Frame Limiter

void A d a p t i v e F r a m e L i m i t e r : : onFrame ( ){

f l o a t d i f f = ( 1 . 0 f / m maxFps ) − m lag ;f l o a t d e l a y = d i f f + 0 . 9 f ∗ m l a s t D e l a y ;

m l a s t D e l a y = d e l a y ;

i f ( d e l a y <= 0 . 0 f ) return ;

m pSystem−>d e l a y ( ( d e l a y ∗ 1000 .0 f ) ) ;}

Filip Sobalski Programowanie gier 2D

Page 33: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

Główna pętla

1 Wyczyść bufor graficzny

2 Uaktualnij stan wejścia

3 Uaktualnij timery synchroniczne

4 Wylicz nową pozycję sprite’ów + logika (+zaznacz sprite’y dousunięcia i zapisz te do dodania)

5 Sprawdź kolizje (+zaznacz sprite’y do usunięcia i zapisz te dododania)

6 Usuń zaznaczone sprite’y

7 Dodaj sprite’y w kolejce

8 Narysuj sprite’y

9 Podmień bufory (swap buffers)

10 Poczekaj chwilę aby ograniczyć FPS

Filip Sobalski Programowanie gier 2D

Page 34: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

Więcej?

1 Diagram klas

2 Jakaś demonstracja

3 Kompensujący timer synchroniczny

4 Podsystem wejścia

Filip Sobalski Programowanie gier 2D

Page 35: 2D sprite engine - basic concepts

WstępElementy składowe

Całość

...

Dziękuję za uwagę.

Filip Sobalski Programowanie gier 2D