PROGRAMMING
RETRO
PLATFORMER
Piccola storia sulla programmazione dei platformer 2D
Dagli 8bit a Unity
GAME OVER - Milano - 19/09/2015
Autore: Paolo Cattaneo (Raven TravelStudios)
Perché il platformer?
• Saltare = AZIONE !
• Gravità + piattaforma + salto = sensazione
immediata di mondo definito
• Non è mai passato veramente di moda (ricorrenze di
questi giorni)
• Target trasversale
• Base fortemente estendibile
Le radici
• 1979: Frogger - introduce il concetto di "saltare su
una piattaforma".
• 1980: Space Panic - vista laterale, scale, gravità.
(Anticipa Lode Runner come gameplay).
• 1981: Donkey Kong - Primo gioco dove si può
saltare. Codifica lo stereotipo classico.
(Anticipa Jump Bug di 6 mesi).
• 1982: Q*Bert - Prima estensione isometrica.
(Space Panic)
Jump Bug
(Alpha Denshi
1981)
Primo platform
con scrolling
multidirezionale
Definire il mondo di gioco:
Tecniche
• Tile Map
(Statisticamente la maggioranza dei
platform)
• Vettoriale
(Braid)
• BitMask
(Turrican, Worms ...)
*gli esempi sono verosimili
TILEMAP
• E' come SUPER MARIO MAKER !
• Lo schermo di gioco è composto da caselline quadrate della
stessa dimensione.
• I dati del livello sono contenuti in una mappa di byte "in scala".
• Con delle proprietà offset possiamo simulare inclinazioni e
pendenze ("slopes").
• La tile non solo come terreno ma anche oggetto (nel senso di
OOP)
Super
Mario
Bros.
Rockman
I dati del livello sono contenuti in
una mappa di byte "in scala".
• CCCCCCCC
CCCCCCCC
CCCCCCCC
CCCPPPCC
CCCCCCCC
GGGGGGGG
GGGGGGGG
Vantaggi
• Relazione diretta tra coordinate sullo schermo e
coordinate sulla mappa
(pointMappa = pointScreen / TileSize)
• Editing dei livelli facile e veloce
• Facile da implementare, molto flessibile ed
estendibile
• Fornisce molte scorciatoie per velocizzare i calcoli
Con degli offset di disegno possiamo
simulare inclinazioni e pendenze.
La scenetta iniziale di Donkey
Kong mostra il funzionamento
degli offset: il livello viene caricato
con il classico meccanismo delle
tile, ma alcune di esse sono
posizionate con un allineamento
verticale diverso per creare le
pendenze. Notare che le tile con
l'offset non sono fisicamente
inclinate ma mantengono lo
stesso piano orizzontale.
La tile non solo come terreno ma
anche oggetto (nel senso di OOP)
Gli RPG a caselle come
la saga di Ultima furono
tra i primissimi giochi
ad utilizzare il concetto
di tile come oggetto
con proprietà, metodi
ed eventi.
Due Grandi Applicazioni.
I muretti di SMB possono essere usati
per uccidere mostri, essere distrutti e
fare spazio, prendere bonus nuovi, ecc.
Nel capolavoro di Fukio Mitsuji ogni tile
del livello "dirige" la bolla con cui collide.
L'uso delle bolle è polivalente.
TileMap e telecamera
VETTORIALE
• Molta più libertà nel creare forme irregolari del
terreno
• Calcoli basati sulla trigonometria
• Dati del livello salvati come insieme di punti definiti
e asset da caricare
• Insidie da evitare (salto oltre le pendenze)
Pac Land
(namco 1984)
Inaugura lo
standard della
decade
successiva
collisioni
vettoriali..?
Calcoli basati su trigonometria
• La hitbox andrà a intersecare il
quadrato delimitato dai vertici D
ed E.
• Inclinazione = (E.y - D.y) / (E.x D.x));
• P = D.y + (Inclinazione * dX);
• P è il punto y sulla pendenza in
relazione a dX
Gestire il salto in modo da non
eccedere la linea di collisione in
fase ascendente.
Willow
(Capcom
1989)
BITMASK
• Ogni sprite terreno ha una controparte in b/n che
ne definisce i bounds
• Bad performance !!!!!!!1!1!!!!!!!111one!1one!!!!!!!!!
• Molto precisa ma noiosa da implementare
• Permette features più spettacolari, tipo overlay e
distruzione delle texture stesse
Routine
iterazione
per pixel
perfect
collision
Due Grandi Applicazioni
Creare Il Motore Fisico
• Imho in questo genere programmarlo da zero è la
cosa migliore (no engine precotti).
Box2D è vostro nemico.
• Gravità e movimenti del player.
• Il salto: analogico, direzionabile, air drag, fisso.
• Collisioni col mondo di gioco.
• Applicare tolleranze per il giocatore.
GRAVITA' E MOVIMENTI
• Gravità = velocita.Y + accelerazione.Y
dove accelerazione.Y aumenta ad ogni tick fino al suo
massimo valore.
• Viene spesso usato un booleano (IsOnGround) per
determinare se applicare la gravità o meno.
• Movimento.X = velocita.X + accelerazione.X dove
accelerazione.X aumenta ad ogni tick fino al suo massimo
valore.
GRAVITA' E MOVIMENTI
• Il modo in cui viene utilizzata accelerazione.X determina il
rapporto di frizione con il terreno.
• Se accelerazione.X segue la direzione dello stick, il player
subirà uno slittamento quando invertirà la direzione (alla
Super Mario Bros.)
• Se accelerazione.X può essere solo positiva, si utilizza una
variabile di direzione -1/+1 da moltiplicare al calcolo del
movimento.
• E' utile tenere una seconda variabile per memorizzare la
direzione in cui si è rivolti per motivi grafici (es.
Implementare un moonwalking, Salto ad arco fisso dove ci
si può girare e sparare)
IL SALTO DIREZIONABILE
• ANALOGICO: viene commisurato
alla pressione del tasto
• Movimento.Y =
(velocita.Y + accelerazione.Y)
+ jumpPushed;
sotto una certa soglia di
accelerazione.Y, jumpPushed è
un fattore > 0 se il tasto salto è
premuto, se no vale 0.
ESEMPIO : SONIC CD
• Massima accelerazione.X = 0.09375f
• Massima velocita.X = 6f
• Massima accelerazione.Y = 0.21873f
• Massima velocita.Y = 16f
AIR DRAG
• E' responsabile del controllo "in aria" del player.
• Di solito interviene quando il salto è in prossimità
del suo apice.
• Di solito tende a rallentare il player.
• Esempio da Sonic:
if (speed.Y < 0 && speed.Y is > -4)
if (ABS(speed.X ) >= 0.125)
speed.X = speed.X * 0.96875;
IL SALTO NON DIREZIONABILE
• Non è il default, va
programmato
appositamente in
quanto la gestione
dei tre movimenti
base (dx, sx, salto)
configura in
automatico il salto
direzionabile.
IL SALTO NON DIREZIONABILE
• Mentre nel salto direzionabile lo stato vale fino
all'apice e poi il player torna in balia della gravità, nel
salto non direzionabile lo stato è valido (e bloccato)
finchè il player non riceve uno stimolo esterno all'input
(tocca terra, viene colpito, ecc.)
• Ha il grande vantaggio di facilitare le azioni coadiuvate
al salto senza che il player debba più preoccuparsi di
tenere lo stick premuto nella direzione desiderata.
• Il valore di spinta del salto parte negativo (fase
ascensionale) per terminare positivo (fase
discendente) - Quindi su Unity è il tendenzialmente il
contrario.
Dragon
Buster
(namco
1984)
Primo gioco
con doppio
salto
COLLISIONI COL MONDO DI
GIOCO
• TileMap: Di solito si definisce
una serie di punti attorno al
perimetro dell'hitbox e si
confrontano con le tile adiacenti
(facili da trovare grazie al
rapporto screen/mappa)
(foto: McKids)
COLLISIONI COL MONDO DI
GIOCO
• TileMap: Ogni tipo di tile è
codificato con le sue proprietà
definite nel programma.
Nell'esempio:
H = Right Slope Tile =
sottotabella di 16x16 offset.
(vedere slide 9)
(foto: McKids)
COLLISIONI COL MONDO DI
GIOCO
• Vettoriale : slide 18
• BitMask : slide 22
TOLLERANZE PER IL GIOCATORE
• Effetto "trasporto" sulla piattaforma superiore.
• In fase di atterraggio, extra collisione anticipata
sul terreno per un nuovo eventuale salto
immediato.
• Extra time quando si cade per accettare l'input di
salto.
PIATTAFORMA MOBILE
• Se si muove orizzontalmente, la position.X del
player è sincronizzata a quella della piattaforma,
più l'aggiunta del movimento.X del player.
• Se si muove verticalmente, la position.Y del player
è sincronizzata a quella della piattaforma.
ANIMAZIONI RESIDUE
• Esempio tipico: esplosioni delle hit.
• Classe Manager con pool di classi "animazione".
• Quando c'è bisogno di un'animazione residua, viene
passata l'animazione al Manager che la include nel
pool, la renderizza e a fotogrammi finiti la disattiva.
BEST PRATICES
• In questo genere, la risposta all'input è più
importante dell'animazione.
• The way: Splatterhouse inverte l'animazione in
tempo reale se il player cambia direzione con lo
stick.
• Prince Of Persia e Dark Souls seguono la regola
opposta.
BEST PRATICES
• Regolate bene durata, altezza e gravità del salto in
modo che siano temporizzate con gli ostacoli mobili da
saltare.
Basarsi su quelli fissi non è sufficiente.
• Sincronizzate bene le piattaforme mobili in modo che si
incontrino spesso. Viceversa è facile snervare il player.
• Evitate i "salti della fede".
• Allo stesso modo, lasciate sempre sufficiente margine
di schermo per far sì che i nemici siano visibili in tempo
dal player.
BEST PRATICES
• Usare sempre le ENUM per gli stati a numero
chiuso.
• Legare sempre il tick come fattore moltiplicativo
dei calcoli.
• Usare sempre i pool di oggetti, non istanziare mai
nel game cycle.
• Evitare LINQ e seek di ogni genere, il Binary Search
è il metodo di ricerca più veloce per un elenco di
oggetti.
BEST PRATICES
• Se si usa un linguaggio con garbage collector,
attenzione a non generare spazzatura
involontariamente. Profilare sempre il codice
perché alcune operazioni tipo il boxing generano
garbage in automatico.
• Preferire dove possibile i reference type e le struct
(vengono allocate nello stack) ai strong type e alle
classi. E in ogni caso invocare sempre i distruttori
(sono problemi che poi vengono fuori quando fate i
porting su device meno indulgenti dei PC).
BREVE CENNI SU UNITY
• Non adatto di suo ai 2D retro platformer ma ormai "ce
tocca".
• NON usare rigidbody o altro tipo di fisica rigida.
• Sfruttare i collider (si trovano 1000 esempi) come nuovo
sistema di collisione che sostituisce i precedenti.
• Camera ortografica, coordinate OpenGL (0,0 = Bottom Left).
• Pixel per Unit : 1
LINK UTILI
http://games.greggman.com/game/programming_m_c__kids/
http://gamasutra.com/blogs/YoannPignole/20140103/207987/Plat
former_controls_how_to_avoid_limpness_and_rigidity_feelings.p
hp
http://higherorderfun.com/blog/2012/05/20/the-guide-toimplementing-2d-platformers/
http://info.sonicretro.org/SPG:Jumping
Scarica

PROGRAMMING RETRO PLATFORMER