08.09.2019 Views

Progettazione e Sviluppo di un Multiplayer Online Game su Reti Peer-to-Peer

Alma Mater Studiorum Universit`a degli Studi di Bologna Facolta` di Scienze Matematiche, Fisiche e Naturali Corso di Laurea in Scienze di Internet Tesi di Laurea in Laboratorio di Programmazione Internet

Alma Mater Studiorum Universit`a degli Studi di Bologna
Facolta` di Scienze Matematiche, Fisiche e Naturali
Corso di Laurea in Scienze di Internet
Tesi di Laurea in Laboratorio di Programmazione Internet

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Alma Mater Stu<strong>di</strong>orum<br />

Università degli Stu<strong>di</strong> <strong>di</strong> Bologna<br />

Facoltà <strong>di</strong> Scienze Matematiche, Fisiche e Naturali<br />

Corso <strong>di</strong> Laurea in Scienze <strong>di</strong> Internet<br />

Tesi <strong>di</strong> Laurea in Labora<strong>to</strong>rio <strong>di</strong> Programmazione Internet<br />

<strong>Progettazione</strong> e <strong>Sviluppo</strong> <strong>di</strong> <strong>un</strong><br />

<strong>Multiplayer</strong> <strong>Online</strong> <strong>Game</strong> <strong>su</strong><br />

<strong>Reti</strong> <strong>Peer</strong>-<strong>to</strong>-<strong>Peer</strong><br />

Can<strong>di</strong>da<strong>to</strong>:<br />

Fabrizio Zagaglia<br />

Rela<strong>to</strong>re:<br />

Chiar.mo Prof. Stefano Ferretti<br />

Anno Accademico 2009/2010 - Sessione III


De<strong>di</strong>co questa tesi alla mia famiglia<br />

i


ii


In<strong>di</strong>ce<br />

Introduzione<br />

v<br />

1 Sta<strong>to</strong> dell’arte 1<br />

1.1 S<strong>to</strong>ria dei MOGs . . . . . . . . . . . . . . . . . . . . . . . . . 1<br />

1.2 Architetture <strong>di</strong>stribuite per il <strong>su</strong>ppor<strong>to</strong> ai MOGs . . . . . . . . 4<br />

1.3 Sincronizzazione Temporale . . . . . . . . . . . . . . . . . . . 7<br />

1.4 Tecnologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />

2 Architettura Software 17<br />

2.1 Problematiche . . . . . . . . . . . . . . . . . . . . . . . . . . . 17<br />

2.2 Layer NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />

2.3 Layer P2P . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />

2.3.1 Modulo Time . . . . . . . . . . . . . . . . . . . . . . . 28<br />

2.4 Modulo SharedComponents . . . . . . . . . . . . . . . . . . . 30<br />

2.5 Layer Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />

2.6 Layer View . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39<br />

2.7 Esempi pratici . . . . . . . . . . . . . . . . . . . . . . . . . . . 43<br />

2.7.1 Movimen<strong>to</strong> <strong>di</strong> oggetti . . . . . . . . . . . . . . . . . . . 44<br />

2.7.2 Collisione tra oggetti . . . . . . . . . . . . . . . . . . . 52<br />

2.7.3 Creazione e <strong>di</strong>struzione <strong>di</strong> oggetti . . . . . . . . . . . . 62<br />

2.7.4 Connessione e Disconnessione dei Player . . . . . . . . 64<br />

3 Implementazione 67<br />

3.1 Introduzione Generale . . . . . . . . . . . . . . . . . . . . . . 67<br />

iii


iv<br />

INDICE<br />

3.2 Layer NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69<br />

3.2.1 Commands . . . . . . . . . . . . . . . . . . . . . . . . 74<br />

3.3 Layer P2P . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77<br />

3.3.1 Modulo Time . . . . . . . . . . . . . . . . . . . . . . . 80<br />

3.4 Modulo SharedComponents . . . . . . . . . . . . . . . . . . . 80<br />

3.5 Layer Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84<br />

3.6 Layer View . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87<br />

4 Analisi delle prestazioni 93<br />

5 Sviluppi futuri 99<br />

5.1 Anti-Cheating . . . . . . . . . . . . . . . . . . . . . . . . . . . 99<br />

5.1.1 Time Based Cheating . . . . . . . . . . . . . . . . . . . 104<br />

5.1.2 Space Based Cheating . . . . . . . . . . . . . . . . . . 105<br />

5.2 Ottimizzazione NET Layer . . . . . . . . . . . . . . . . . . . . 110<br />

5.3 Gestione utenti e MatchMaking . . . . . . . . . . . . . . . . . 112<br />

6 Conclusioni 117<br />

Ringraziamenti 125


Introduzione<br />

Astraendo da quelli che sono gli aspetti generali e multi<strong>di</strong>sciplinari che si<br />

possono in<strong>di</strong>viduare nel processo produttivo <strong>di</strong> <strong>un</strong> videogioco (si pensi agli<br />

elementi artistici, dalla grafica alla musica, o alla necessità <strong>di</strong> soli<strong>di</strong> sistemi<br />

economici e <strong>di</strong> marketing), dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista tecnico, tra le caratteristiche che<br />

contrad<strong>di</strong>stinguono maggiormente <strong>un</strong> software videolu<strong>di</strong>co, vi sono, da <strong>un</strong>a<br />

parte, la necessità <strong>di</strong> <strong>un</strong> feedback pressoché imme<strong>di</strong>a<strong>to</strong> alle azioni eseguite<br />

dal gioca<strong>to</strong>re, e, dall’altra, la forte interazione tra gli elementi che popolano<br />

l’ambiente <strong>di</strong> gioco.<br />

Questi aspetti implicano <strong>un</strong>a serie <strong>di</strong> problematiche che, nell’ambi<strong>to</strong> specifico<br />

dei giochi <strong>Multiplayer</strong> online, vengono in qualche modo amplificate:<br />

<strong>di</strong>ventano quin<strong>di</strong> necessarie soluzioni che, a livello <strong>di</strong> architettura hardware<br />

e software, <strong>di</strong>fferiscono da quelle richieste, ad esempio, da <strong>un</strong> videogioco Singleplayer.<br />

Un primo aspet<strong>to</strong> da analizzare è in<strong>di</strong>vidua<strong>to</strong> dalla scelta dell’architettura<br />

<strong>di</strong> rete, tipicamente tra il modello Client-Server ed il modello <strong>Peer</strong>-To-<strong>Peer</strong>.<br />

Entrambi hanno vantaggi e svantaggi e ri<strong>su</strong>ltano preferibili l’<strong>un</strong>o all’altro a<br />

seconda del contes<strong>to</strong>, <strong>di</strong>sponibilità hardware, tipologia e specifiche <strong>di</strong> gioco.<br />

Un sistema centralizza<strong>to</strong> Client-Server, da <strong>un</strong> la<strong>to</strong> sopperisce al problema<br />

<strong>di</strong> inconsistenza dei dati, dal momen<strong>to</strong> che è il Server stesso a mantenere lo<br />

sta<strong>to</strong> e a processare la logica <strong>di</strong> gioco, ma dall’altro ri<strong>su</strong>lta meno flessibile,<br />

v


vi CAPITOLO 0. INTRODUZIONE<br />

portabile e scalabile. Il Server inoltre rappresenta <strong>un</strong>o SPOF 1 .<br />

Con “consistenza” si intende la necessità <strong>di</strong> avere <strong>un</strong>o sta<strong>to</strong> <strong>di</strong> gioco defini<strong>to</strong><br />

da dati integri e valorizzati allo stesso modo <strong>su</strong> ogni singolo client, dove con<br />

“sta<strong>to</strong> <strong>di</strong> gioco” si intende <strong>un</strong>a rappresentazione, <strong>un</strong>a sorta <strong>di</strong> “istantanea”,<br />

dello sta<strong>to</strong> (posizione, rotazione, azioni, eventi, variabili, etc.) <strong>di</strong> ogni singolo<br />

elemen<strong>to</strong> presente nell’ambiente <strong>di</strong> gioco.<br />

In <strong>un</strong> sistema decentralizza<strong>to</strong> <strong>Peer</strong>-To-<strong>Peer</strong>, ogni nodo è paritetico e può<br />

f<strong>un</strong>gere quin<strong>di</strong> contemporaneamente sia da Client che da Server.<br />

Su ogni <strong>Peer</strong> è presente <strong>un</strong>a copia dello sta<strong>to</strong> <strong>di</strong> gioco, e nel caso <strong>di</strong> sistemi<br />

<strong>Peer</strong>-To-<strong>Peer</strong> “puri”, ogni <strong>Peer</strong> porterà avanti la logica <strong>di</strong> gioco basandosi<br />

<strong>su</strong>l proprio Data Layer, introducendo quin<strong>di</strong> problematiche <strong>di</strong> consistenza e<br />

sincronizzazione temporale.<br />

Senza ness<strong>un</strong> sistema <strong>di</strong> controllo, infatti, ogni <strong>Peer</strong>, specie in quelle situazioni<br />

ed in quegli eventi soggetti a processi alea<strong>to</strong>ri o notevolmente sensibili<br />

alla sincronizzazione temporale, può presentare <strong>un</strong>o sta<strong>to</strong> <strong>di</strong> gioco <strong>di</strong>fferente<br />

rispet<strong>to</strong> agli altri, e tale errore è destina<strong>to</strong> a propagarsi aggiornamen<strong>to</strong> dopo<br />

aggiornamen<strong>to</strong>, portando ad <strong>un</strong>a <strong>di</strong>vergenza dei ri<strong>su</strong>ltati potenzialmente<br />

mol<strong>to</strong> elevata (i.e. in <strong>un</strong> <strong>Peer</strong> la vit<strong>to</strong>ria è assegnata al Player A, mentre in<br />

<strong>un</strong> altro <strong>Peer</strong> la vit<strong>to</strong>ria è assegnata al Player B).<br />

Obiettivi <strong>di</strong> proget<strong>to</strong><br />

In questa tesi <strong>di</strong> proget<strong>to</strong> si é deciso <strong>di</strong> affrontare lo sviluppo <strong>di</strong> <strong>un</strong> videogioco<br />

<strong>Multiplayer</strong> basa<strong>to</strong> <strong>su</strong>ll’architettura <strong>Peer</strong>-<strong>to</strong>-<strong>Peer</strong>. La soluzione adottata,<br />

però, non è riconducibile al modello <strong>Peer</strong>-<strong>to</strong>-<strong>Peer</strong> “Puro”, in quan<strong>to</strong> i no<strong>di</strong><br />

non sono propriamente paritetici: ogni <strong>Peer</strong> infatti, pur conoscendo lo sta<strong>to</strong><br />

<strong>di</strong> gioco globale, ne gestirà <strong>di</strong>rettamente solo <strong>un</strong>a partizione, aggiornando <strong>di</strong><br />

1 Single point of failure, <strong>un</strong> generico elemen<strong>to</strong> il cui malf<strong>un</strong>zionamen<strong>to</strong> compromette<br />

l’intero sistema del quale fa parte.


vii<br />

fat<strong>to</strong> solo gli elementi <strong>di</strong> propria appartenenza.<br />

In ques<strong>to</strong> modo viene contenu<strong>to</strong> l’impat<strong>to</strong> del problema <strong>di</strong> consistenza,<br />

dal momen<strong>to</strong> che, desincronizzazioni temporali a parte, tutti gli stati <strong>di</strong> gioco<br />

convergeranno ad <strong>un</strong>o sta<strong>to</strong> virtualmente con<strong>di</strong>viso com<strong>un</strong>e. Rispet<strong>to</strong> al modello<br />

“Puro”, si è però anche più sensibili a problemi derivanti dal cheating 2<br />

e alla formazione <strong>di</strong> bottleneck at<strong>to</strong>rno all’insieme <strong>di</strong> dati gestiti da <strong>un</strong> <strong>Peer</strong><br />

poco performante. Il che significa l’eventuale implementazione <strong>di</strong> politiche<br />

<strong>di</strong> <strong>di</strong>stribuzione <strong>di</strong> calcolo mirate alla riduzione del contes<strong>to</strong> dei dati che appartengono<br />

ai no<strong>di</strong> computazionalmente più lenti o con maggiore latenza, in<br />

favore <strong>di</strong> quelli più performanti.<br />

Il gioco realizza<strong>to</strong> appartiene alla tipologia degli “Shooter 3D”, e prende<br />

sp<strong>un</strong><strong>to</strong>, sia dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista delle meccaniche <strong>di</strong> gioco che dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista<br />

dello stile grafico, da Spectre (si veda il capi<strong>to</strong>lo 1): ogni gioca<strong>to</strong>re controlla<br />

<strong>un</strong> proprio “Tank” ed è chiama<strong>to</strong> <strong>di</strong>struggere i “Tank” nemici controllati<br />

dagli altri gioca<strong>to</strong>ri.<br />

Nel prossimo capi<strong>to</strong>lo verranno introdotti quelli che sono i sistemi, le<br />

architetture e le tecnologie attualmente più utilizzate a seconda dei <strong>di</strong>versi<br />

contesti e delle <strong>di</strong>verse specifiche <strong>di</strong> gioco.<br />

Nei capi<strong>to</strong>li <strong>su</strong>ccessivi, invece, verranno analizzate nel dettaglio le fasi <strong>di</strong><br />

progettazione e le scelte implementative del proget<strong>to</strong> <strong>di</strong> tesi.<br />

2 Un sistema grazie al quale è possibile aggirare le regole <strong>di</strong> gioco traendone vantaggio


viii CAPITOLO 0. INTRODUZIONE<br />

Figura 1: Screenshots


Capi<strong>to</strong>lo 1<br />

Sta<strong>to</strong> dell’arte<br />

1.1 S<strong>to</strong>ria dei MOGs<br />

Il concet<strong>to</strong> <strong>di</strong> videogioco <strong>Multiplayer</strong> (<strong>Multiplayer</strong> <strong>Online</strong> <strong>Game</strong>, MOG)<br />

è muta<strong>to</strong> notevolmente nell’arco della <strong>su</strong>a evoluzione.<br />

Inizialmente era confina<strong>to</strong> ad <strong>un</strong>a rappresentazione testuale <strong>di</strong> wargames 1 ,<br />

gioca<strong>to</strong> via BBS 2 ed organizza<strong>to</strong> e gesti<strong>to</strong> da amministra<strong>to</strong>ri fisici che, manualmente,<br />

calcolavano lo sta<strong>to</strong> <strong>di</strong> gioco ri<strong>su</strong>ltante dalle richieste inoltrate<br />

dai gioca<strong>to</strong>ri, <strong>di</strong>stribuiti <strong>su</strong>l tut<strong>to</strong> il globo, ore o ad<strong>di</strong>rittura giorni prima.<br />

Pres<strong>to</strong> tale processo venne au<strong>to</strong>matizza<strong>to</strong>, dando via alla nascita dei<br />

MUD 3 .<br />

Parallelamente, se si estende il <strong>di</strong>scorso anche ai giochi “vi<strong>su</strong>ali” e realtime<br />

(in contrapposizione a quelli testuali), tale concet<strong>to</strong> è sta<strong>to</strong> dapprima<br />

1 Un gioco accostabile alla categoria dei giochi strategici, le cui regole sono mirate alla<br />

simulazione o alla rappresentazione <strong>di</strong> <strong>un</strong>o scenario <strong>di</strong> guerra, ed il cui scopo è in<strong>di</strong>vidua<strong>to</strong><br />

nella vit<strong>to</strong>ria <strong>di</strong> <strong>un</strong>a battaglia, raggi<strong>un</strong>ta attraverso determinate tattiche e strategie.<br />

2 Bulletin board system, <strong>un</strong> sistema software, utilizza<strong>to</strong> principalmente a cavallo tra gli<br />

anni ’80 e ’90, che permetteva <strong>di</strong> scambiare dati, da semplici messaggi <strong>di</strong> tes<strong>to</strong> ad interi<br />

file, attraverso la linea telefonica.<br />

3 Multi User D<strong>un</strong>geon, giochi <strong>di</strong> ruolo testuali multi-utente<br />

1


2 CAPITOLO 1. STATO DELL’ARTE<br />

confina<strong>to</strong> al singolo device fisico: due o più gioca<strong>to</strong>ri dovevano essere presenti<br />

fisicamente nella stanza per poter controllare il proprio personaggio e ricevere<br />

il feedback visivo e sonoro corrispondente alle proprie azioni. Si pensi<br />

ai Coin-op presenti nelle sale giochi, o allo stesso Pong, (Atari, 1972) che<br />

permetteva a due gioca<strong>to</strong>ri <strong>di</strong> sfidarsi (o cooperare) <strong>di</strong>rettamente <strong>su</strong>llo stesso<br />

device.<br />

La comparsa dei primi giochi <strong>Multiplayer</strong> online e real-time è da ricercare<br />

nell’ambi<strong>to</strong> <strong>un</strong>iversitario: Empire <strong>di</strong> John Daleske e Spasim <strong>di</strong> Jim Bowery<br />

sono tra i primi giochi multi-utente basati <strong>su</strong>l sitema PLATO. Si <strong>su</strong>sseguono,<br />

poi, numerose versioni <strong>di</strong> Empire ambientate nell’<strong>un</strong>iverso <strong>di</strong> Star Trek<br />

(Xtrek, Netrek, Decwars, WinTrek, etc.): queste si basavano <strong>su</strong>lla rappresentazione<br />

dello spazio bi<strong>di</strong>mensionale, in<strong>di</strong>vidua<strong>to</strong> da <strong>un</strong>a griglia nella quale era<br />

possibile spostare in tempo reale la propria nave nelle 8 <strong>di</strong>rezioni <strong>di</strong>sponibili.<br />

Particolarmente significativo dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista s<strong>to</strong>rico è sta<strong>to</strong> Maze War 4<br />

(1974), videogioco seminale che ha introdot<strong>to</strong> numerose <strong>di</strong>namiche <strong>di</strong> gameplay<br />

<strong>su</strong>ccessivamente riprese e tutt’ora presenti nella maggior parte dei ti<strong>to</strong>li<br />

videolu<strong>di</strong>ci o<strong>di</strong>erni. E’ considera<strong>to</strong> infatti il primo FPS 3D <strong>Multiplayer</strong>.<br />

L’avven<strong>to</strong> del Personal Computer incentivò la richiesta <strong>di</strong> <strong>un</strong> <strong>su</strong>ppor<strong>to</strong> al<br />

“NetPlay”, cioè <strong>un</strong>a modalità alternativa a quella classica Singleplayer, che<br />

consentisse <strong>di</strong> giocare in <strong>Multiplayer</strong> via LAN o Internet. Spectre (1991) per<br />

Apple Macin<strong>to</strong>sh fu tra i primi a dare cre<strong>di</strong><strong>to</strong> a tale richiesta, permettendo<br />

a 8 gioca<strong>to</strong>ri simultanei <strong>di</strong> scontrarsi in <strong>un</strong>’arena tri<strong>di</strong>mensionale vet<strong>to</strong>riale.<br />

Ma il p<strong>un</strong><strong>to</strong> <strong>di</strong> svolta più significativo è probabilmente rappresenta<strong>to</strong> da<br />

DooM (1993) <strong>di</strong> ID Software, che, grazie alla <strong>di</strong>stribuzione capillare <strong>di</strong> <strong>un</strong>a<br />

<strong>su</strong>a versione Shareware, <strong>di</strong>ventò popolare in brevissimo tempo. Concretizza<br />

alc<strong>un</strong>e idee legate al mutiplayer già presenti a livello embrionale in Maze War<br />

4 http://en.wikipe<strong>di</strong>a.org/wiki/Maze War


1.1. STORIA DEI MOGS 3<br />

e le fissa ad <strong>un</strong> nuovo standard qualitativo. Per <strong>di</strong>versi anni a seguire venne<br />

utilizza<strong>to</strong> come termine <strong>di</strong> paragone.<br />

E’ solo verso la fine degli anni ’90, parallelamente alla crescente <strong>di</strong>ffusione<br />

<strong>di</strong> Internet <strong>su</strong> larga scala, che iniziano a definirsi tipologie <strong>di</strong> gioco real-time<br />

esclusivamente orientate al <strong>Multiplayer</strong>: se qualche anno prima ques<strong>to</strong> aspet<strong>to</strong><br />

era spesso e volentieri relega<strong>to</strong> a rare modalità <strong>di</strong> gioco alternative a quella<br />

principale Singleplayer, da qui in poi entra prepotentemente tra le necessità<br />

più sentite dai gioca<strong>to</strong>ri PC, prima, e console poi.<br />

E’ il caso <strong>di</strong> FPS principalmente orientati al <strong>Multiplayer</strong> come Quake 3<br />

Arena (1999) <strong>di</strong> ID Software e Unreal Tournament (1999) <strong>di</strong> Epic <strong>Game</strong>s.<br />

In ques<strong>to</strong> periodo nasce ed inizia a prendere piede anche <strong>un</strong>o dei generi<br />

<strong>di</strong> gioco che ha caratterizza<strong>to</strong>, e monopolizza<strong>to</strong>, l’intero decennio ’00: è con<br />

Ultima <strong>Online</strong> (1997, Origin), infatti, che si inizia a parlare <strong>di</strong><br />

MMORPG 5 , <strong>di</strong> avatar e <strong>di</strong> mon<strong>di</strong> persistenti. L’apice del genere, in termini<br />

<strong>di</strong> popolarità (e quin<strong>di</strong> <strong>di</strong> ricavi economici) è sicuramente in<strong>di</strong>viduabile in<br />

World of Warcraft (2004, Blizzard).<br />

Tornano inoltre in auge tipologie <strong>di</strong> gioco più lente e visivamente astratte,<br />

in qualche modo <strong>di</strong>rettamente derivabili dalle prime forme testuali <strong>di</strong> wargame<br />

multigioca<strong>to</strong>re; videogiochi <strong>di</strong>rettamente giocabili da qualsiasi browser,<br />

che in parte ricalcano gli stilemi proposti dai MMORPG dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista<br />

delle meccaniche social e ad<strong>di</strong>ctive e che fanno della loro estrema accessibilità<br />

(basse richieste Hardware, ness<strong>un</strong> cos<strong>to</strong> d’ingresso o <strong>di</strong> abbonamen<strong>to</strong>)<br />

<strong>un</strong>o dei maggiori motivi <strong>di</strong> <strong>su</strong>ccesso. Tra questi si possono ricordare Ogame<br />

(<strong>Game</strong>forge, 2002), Travian (Travian <strong>Game</strong>s, 2005) e FarmVille (Zynga,<br />

2009). Quest’ultimo ha raggi<strong>un</strong><strong>to</strong> <strong>un</strong>’elevata popolarità utilizzando sinergica-<br />

5 <strong>Multiplayer</strong> <strong>Online</strong> Role-Playing <strong>Game</strong>, gioco <strong>di</strong> ruolo ambienta<strong>to</strong> <strong>su</strong> <strong>un</strong> mondo<br />

virtuale persistente


4 CAPITOLO 1. STATO DELL’ARTE<br />

mente la base d’utenza <strong>di</strong> Facebook come sistema <strong>di</strong> marketing e <strong>di</strong> <strong>di</strong>ffusione.<br />

1.2 Architetture <strong>di</strong>stribuite per il <strong>su</strong>ppor<strong>to</strong><br />

ai MOGs<br />

Tale eterogeneità non rende possibile l’affermarsi <strong>di</strong> soluzioni generiche<br />

ottimali per ogni tipologia <strong>di</strong> gioco, ogni tipo <strong>di</strong> architettura e <strong>di</strong> tecnologia: i<br />

requisiti ed i sistemi <strong>di</strong> sincronizzazione utilizzati per realizzare <strong>un</strong> RPG playby-post<br />

sono, ad esempio, notevolmente <strong>di</strong>fferenti rispet<strong>to</strong> a quelli utilizzati<br />

invece per sviluppare <strong>un</strong> FPS o <strong>un</strong> MMORPG.<br />

L’architettura Client-Server (Figura 1.1) in ambi<strong>to</strong> videolu<strong>di</strong>co è attualmente<br />

predominante: viene utilizzata in FPS <strong>Multiplayer</strong> come Quake o<br />

Unreal Tournament, o in MMORPG come Ultima <strong>Online</strong> o World of Warcraft.<br />

Nei primi la simulazione e l’aggiornamen<strong>to</strong> dello sta<strong>to</strong> <strong>di</strong> gioco sono<br />

a carico <strong>di</strong> <strong>un</strong> processo fisicamente esterno ai client. Poiché la durata delle<br />

partite <strong>di</strong> <strong>un</strong>o Shooter è piut<strong>to</strong>s<strong>to</strong> bassa (me<strong>di</strong>amente circa <strong>di</strong>eci minuti), e<br />

non è richies<strong>to</strong> ness<strong>un</strong> tipo <strong>di</strong> sistema <strong>di</strong> permanenza dei dati (se non a livello<br />

<strong>di</strong> statistiche esterne), i requisiti per “hostare” <strong>un</strong> server de<strong>di</strong>ca<strong>to</strong> sono tali<br />

da permettere la proliferazione <strong>di</strong> server non ufficiali gestiti <strong>di</strong>rettamente dai<br />

gioca<strong>to</strong>ri, sia in LAN che in Internet [Abrash 1996].<br />

Per quan<strong>to</strong> riguarda invece i generi <strong>di</strong> gioco ambientati in <strong>un</strong> mondo virtuale<br />

persistente, il numero <strong>di</strong> gioca<strong>to</strong>ri e <strong>di</strong> items da gestire a carico <strong>di</strong> ogni singolo<br />

server è notevolmente più al<strong>to</strong>, e dal momen<strong>to</strong> che il concet<strong>to</strong> <strong>di</strong> partita in<strong>di</strong>viduata<br />

da <strong>un</strong> inizio ed <strong>un</strong>a fine è assente, in favore <strong>di</strong> <strong>un</strong>’esperienza <strong>di</strong> gioco<br />

potenzialmente infinita, i requisiti Hardware per aggiornare e mantenere i<br />

dati relativi all’ambiente e alle entità che lo popolano sono tali da rendere<br />

necessaria l’esistenza <strong>di</strong> singoli server <strong>di</strong> gioco “ufficiali”.<br />

L’architettura <strong>Peer</strong>-To-<strong>Peer</strong> (Figura 1.2), anche se utilizzata in <strong>di</strong>versi<br />

ti<strong>to</strong>li, specialmente RTS (Warcraft II (Blizzard, 1995) o Demigod (Gas<br />

Powered <strong>Game</strong>s, 2009)), è invece meno <strong>di</strong>ffusa. Inoltre, mentre il modello


1.2. ARCHITETTURE DISTRIBUITE PER IL SUPPORTO AI<br />

MOGS 5<br />

Figura 1.1: Modello Client-Server: lo sta<strong>to</strong> <strong>di</strong> gioco comple<strong>to</strong> (esagono verde)<br />

è mantenu<strong>to</strong> e aggiorna<strong>to</strong> da <strong>un</strong> singolo Server centralizza<strong>to</strong>. Ogni Client<br />

è connesso esclusivamente al Server e mantiene <strong>un</strong>a propria visione dello<br />

sta<strong>to</strong> <strong>di</strong> gioco, tipicamente incompleta (quadra<strong>to</strong> verde), aggiornata grazie<br />

ai messaggi inviati, au<strong>to</strong>nomamente o come <strong>di</strong>retta conseguenza <strong>di</strong> <strong>un</strong> input<br />

esterno, dal Server (triangolo verde).


6 CAPITOLO 1. STATO DELL’ARTE<br />

Figura 1.2: Modello <strong>Peer</strong>-To-<strong>Peer</strong>: ogni <strong>Peer</strong>, connesso <strong>di</strong>rettamente o in<strong>di</strong>rettamente<br />

a tutti gli altri <strong>Peer</strong>, mantiene e aggiorna <strong>un</strong>a propria visione<br />

dello sta<strong>to</strong> <strong>di</strong> gioco comple<strong>to</strong> (esagono verde), secondo gli eventi ricevuti.


1.3. SINCRONIZZAZIONE TEMPORALE 7<br />

Client-Server segue <strong>un</strong>a serie <strong>di</strong> pattern architetturali ormai consolidati, rintracciabili<br />

nella maggior parte dei ti<strong>to</strong>li <strong>Multiplayer</strong>, ques<strong>to</strong> non accade per<br />

il modello <strong>Peer</strong>-To-<strong>Peer</strong>, che tendenzialmente vede approcci e scelte implementative<br />

<strong>di</strong>fferenti anche in tipologie <strong>di</strong> gioco relativamente simili.<br />

In Age of Empire, gioco strategico <strong>di</strong> Ensemble Stu<strong>di</strong>os (1997), è utilizzata<br />

<strong>un</strong>’architettura <strong>Peer</strong>-To-<strong>Peer</strong> ibrida, caratterizzata da <strong>un</strong> <strong>Peer</strong> appartente<br />

alla Membership, elet<strong>to</strong> “Host” che fa da “<strong>Game</strong> Master” e che si occupa<br />

<strong>di</strong> inizializzare la partita e gestire tutte le situazioni critiche e concorrenziali<br />

[Bettner 2001].<br />

Altri para<strong>di</strong>gmi ibri<strong>di</strong>, basati <strong>su</strong>l concet<strong>to</strong> <strong>di</strong> “regione” o <strong>di</strong> “area <strong>di</strong> interesse”,<br />

sono stati invece proposti per far fronte al problema <strong>di</strong> scalabilità<br />

in<strong>di</strong>vidua<strong>to</strong> nel modello Client-Server per quelle tipologie <strong>di</strong> gioco, come i<br />

MMOG, contrad<strong>di</strong>stinte da <strong>un</strong> eleva<strong>to</strong> numero <strong>di</strong> gioca<strong>to</strong>ri.<br />

Ad esempio in [Rhalibi 2005] viene <strong>di</strong>scussa <strong>un</strong>’architettura nella quale <strong>un</strong><br />

Server centrale controlla <strong>un</strong>a serie <strong>di</strong> “regioni” composte da singole reti <strong>Peer</strong>-<br />

To-<strong>Peer</strong> che fanno capo ad <strong>un</strong> proprio “Supernode”, e <strong>su</strong>d<strong>di</strong>vise in f<strong>un</strong>zione<br />

della loro posizione geografica all’interno dell’ambiente virtuale <strong>di</strong> gioco<br />

(Figura 1.3).<br />

In ultima analisi, i fat<strong>to</strong>ri che influenzano la scelta dell’architettura derivano<br />

da molteplici aspetti, dalla tipologia <strong>di</strong> gioco alla <strong>di</strong>sponibilità hardware.<br />

L’approccio <strong>Peer</strong>-To-<strong>Peer</strong> è tutt’ora meno <strong>di</strong>ffuso e standar<strong>di</strong>zza<strong>to</strong> rispet<strong>to</strong><br />

a quello centralizza<strong>to</strong> Client-Server, e spesso si presenta in veste “ibrida”,<br />

caratterizzata cioè da <strong>un</strong>a gerarchizzazione dei no<strong>di</strong> e dalla formazione <strong>di</strong><br />

“isole” centralizzate. Inoltre a <strong>su</strong>o <strong>su</strong>ppor<strong>to</strong>, tipicamente viene introdot<strong>to</strong> <strong>un</strong><br />

sistema Client-Server apposi<strong>to</strong> per la gestione delle lobby, il player <strong>di</strong>scovery<br />

ed il MatchMaking.<br />

1.3 Sincronizzazione Temporale<br />

In <strong>un</strong>’applicazione <strong>di</strong> rete non è possibile garantire la continua consistenza<br />

dei dati senza che vi sia <strong>un</strong>a qualche forma <strong>di</strong> sincronizzazione temporale:


8 CAPITOLO 1. STATO DELL’ARTE<br />

Figura 1.3: Modello ibrido propos<strong>to</strong> in [Rhalibi 2005] ed in [Luo 2010], e<br />

<strong>di</strong>scusso in [Due Billing 2006]


1.3. SINCRONIZZAZIONE TEMPORALE 9<br />

i dati che in<strong>di</strong>viduano lo sta<strong>to</strong> <strong>di</strong> <strong>un</strong> dominio, sono per definizione mutevoli,<br />

sono cioè destinati a cambiare valore nel corso del tempo.<br />

Senza <strong>un</strong>a corrispondenza tra <strong>un</strong> determina<strong>to</strong> da<strong>to</strong> e l’istante <strong>di</strong> tempo nel<br />

quale quest’ultimo as<strong>su</strong>me <strong>un</strong> determina<strong>to</strong> valore, l’informazione apportata<br />

perde <strong>di</strong> significa<strong>to</strong>.<br />

Nelle applicazioni real-time, tale aspet<strong>to</strong> è destina<strong>to</strong> ad avere <strong>un</strong> impat<strong>to</strong> considerevole,<br />

dal momen<strong>to</strong> che i cambi <strong>di</strong> sta<strong>to</strong> tipicamente avvengono con <strong>un</strong>a<br />

frequenza decisamente alta. Nell’ambi<strong>to</strong> videolu<strong>di</strong>co, inoltre, tra la sincronizzazione<br />

temporale e la sincronizzazione dello sta<strong>to</strong>, si instaura <strong>un</strong>a terza<br />

problematica: Il Cheating (si veda la sezione 5.1).<br />

Una situazione ideale <strong>di</strong> perfetta consistenza, nella quale ogni gioca<strong>to</strong>re vede<br />

esattamente lo stesso sta<strong>to</strong> <strong>di</strong> gioco globale allo stesso preciso istante <strong>di</strong> tempo<br />

assolu<strong>to</strong>, è fisiologicamente impossibile da realizzare causa latenza <strong>di</strong> rete.<br />

Per gestire la problematica <strong>di</strong> sincronizzazione è necessario valutare i termini<br />

<strong>di</strong> <strong>un</strong> compromesso tra la reattività <strong>di</strong> risposta e la consistenza ad <strong>un</strong><br />

determina<strong>to</strong> istante <strong>di</strong> tempo: <strong>un</strong> approccio “conservativo” è implementa<strong>to</strong><br />

in sistemi <strong>di</strong> sincronizzazione “S<strong>to</strong>p-And-Wait”, come il Lock-Step (Figura<br />

1.4) e la Bucket Synchronization (Figura 1.5), ed è caratterizza<strong>to</strong>, da <strong>un</strong>a<br />

parte da <strong>un</strong>a forte consistenza a livello temporale, poiché ogni azione viene<br />

processata solo quando questa è, teoricamente, conosciuta da tutti i <strong>Peer</strong><br />

appartenenti alla Membership, e, dall’altra, come <strong>di</strong>retta conseguenza, da <strong>un</strong><br />

tempo <strong>di</strong> reazione al<strong>to</strong>.<br />

Per ques<strong>to</strong> motivo, ques<strong>to</strong> genere <strong>di</strong> sincronizzazioni vengono utilizzate soprattut<strong>to</strong><br />

in quei giochi, come gli RTS, caratterizzati da <strong>un</strong> <strong>Game</strong>play relativamente<br />

len<strong>to</strong>.<br />

É possibile com<strong>un</strong>que sfruttarle anche in tipologie <strong>di</strong> gioco più “veloci”, attivandole<br />

solo in particolari contesti <strong>di</strong> concorrenza e all’interno della stessa<br />

area <strong>di</strong> interesse (ad esempio nella gestione <strong>di</strong> <strong>un</strong>a collisione tra due oggetti<br />

in avvicinamen<strong>to</strong>).


10 CAPITOLO 1. STATO DELL’ARTE<br />

Un approccio “ottimistico”, implementa<strong>to</strong> ad esempio della Time-Warp<br />

Synchronization, prevede invece <strong>un</strong>’ esecuzione degli eventi imme<strong>di</strong>ata: questi<br />

infatti saranno processati appena gi<strong>un</strong>ti a destinazione. Il vincolo temporale<br />

at<strong>to</strong> a garantire la consistenza, che nell’approccio “conservativo” è realizza<strong>to</strong><br />

me<strong>di</strong>ante fasi ed intervalli <strong>di</strong> tempo “bloccanti”, è qui invece rappresenta<strong>to</strong><br />

dal processo <strong>di</strong> “Roll-back”. Ad ogni even<strong>to</strong> viene infatti assegna<strong>to</strong> <strong>un</strong> Time-<br />

Stamp: quando <strong>un</strong> <strong>Peer</strong> riceve <strong>un</strong> even<strong>to</strong> contrassegna<strong>to</strong> da <strong>un</strong> TimeStamp<br />

meno recente rispet<strong>to</strong> a quello attuale, vengono prima cancellati tutti gli effetti<br />

scaturiti da eventi già processati riportanti <strong>un</strong> TimeStamp più recente,<br />

poi esegui<strong>to</strong> l’even<strong>to</strong> in questione, ed infine ri-processati quest’ultimi. Alc<strong>un</strong>i<br />

eventi possono però essere “correlati” tra loro: l’esistenza -o la non esistenza<strong>di</strong><br />

<strong>un</strong> even<strong>to</strong> “chiave” all’interno <strong>di</strong> <strong>un</strong>a “Correlation chain” può alterare o<br />

compromettere il significa<strong>to</strong> e la vali<strong>di</strong>tà degli eventi ad esso correlati: in<br />

altre parole, compromettere la consistenza dello sta<strong>to</strong> <strong>di</strong> gioco (Figura 1.6).<br />

Ques<strong>to</strong> tipo <strong>di</strong> sincronizzazioni permette <strong>di</strong> avere <strong>un</strong>a maggiore reattività <strong>di</strong><br />

interazione rispet<strong>to</strong> a quelle basate <strong>su</strong>ll’approccio “conservativo”, ma, per<br />

garantire l’esistenza <strong>di</strong> <strong>un</strong>a base dati <strong>su</strong>fficientemente ampia da permettere<br />

il recovery degli stati precedenti in fase <strong>di</strong> rollback, richiede tendenzialmente<br />

<strong>un</strong>a quantità <strong>di</strong> memoria più elevata.<br />

Per limitare ques<strong>to</strong> problema, si può intervenire eliminando gli eventi obsoleti,<br />

cioè quegli eventi, non correlati, ridondanti e sostituibili quin<strong>di</strong> da eventi<br />

più recenti che, partendo dal medesimo sta<strong>to</strong> iniziale, portano al medesimo<br />

sta<strong>to</strong> finale.


1.3. SINCRONIZZAZIONE TEMPORALE 11<br />

Figura 1.4: LockStep Synchronization. In ques<strong>to</strong> sistema <strong>di</strong> sincronizzazione,<br />

l’esecuzione degli eventi è volutamente ritardata. Un <strong>Peer</strong> non processerà<br />

ness<strong>un</strong> even<strong>to</strong> fino a quando tutti gli altri <strong>Peer</strong> appartenenti alla Membership<br />

non saranno “pronti” per passare allo step <strong>su</strong>ccessivo, ovvero fintan<strong>to</strong><br />

che non riceverà le loro intenzioni, sot<strong>to</strong>forma <strong>di</strong> even<strong>to</strong>. Lo si può associare<br />

ad <strong>un</strong> sistema a turni, nel quale ogni at<strong>to</strong>re è obbliga<strong>to</strong> ad eseguire la propria<br />

mossa (eventualmente nulla) prima <strong>di</strong> passare al turno <strong>su</strong>ccessivo.<br />

Per evitare che <strong>un</strong> <strong>Peer</strong> malevolo possa mo<strong>di</strong>ficare le proprie azioni in conseguenza<br />

alla ricezione degli eventi appartenenti agli altri <strong>Peer</strong>, ogni step viene<br />

<strong>di</strong>viso in due fasi: nella prima ogni <strong>Peer</strong> ann<strong>un</strong>cia <strong>un</strong>a propria “intenzione”,<br />

inviando, ad esempio, l’Hash dell’azione voluta a tutti gli altri <strong>Peer</strong> appartenenti<br />

alla Membership. L’“intenzione” non identifica <strong>un</strong>’azione, nel senso<br />

che dal <strong>su</strong>o valore non è possibile ricavare tramite inferenza la semantica<br />

dell’azione stessa. E’ solo nella seconda fase, infatti, che ogni <strong>Peer</strong> è tenu<strong>to</strong> a<br />

rivelare la propria azione, inviando, agli altri <strong>Peer</strong>, il relativo even<strong>to</strong>. Ques<strong>to</strong><br />

infine sarà esegui<strong>to</strong> solo se, applicando la f<strong>un</strong>zione inversa a quella utilizzata<br />

per ricavare l’“intenzione”, il valore ri<strong>su</strong>ltate sarà equivalente all’azione stessa.<br />

Rispet<strong>to</strong> alla Bucket Synchronization, ques<strong>to</strong> sistema da <strong>un</strong> la<strong>to</strong> argina<br />

il problema del Look Ahead Cheat (5.1), ma dall’altro ri<strong>su</strong>lta essere più sensibile<br />

alle variazioni <strong>di</strong> latezna (Jitter), poiché ogni step, ed ogni singola fase<br />

è in<strong>di</strong>viduata da <strong>un</strong> periodo <strong>di</strong> tempo variabile.


12 CAPITOLO 1. STATO DELL’ARTE<br />

Figura 1.5: Bucket Synchronization: nella Bucket Synchronization il tempo<br />

viene idealmente <strong>su</strong>d<strong>di</strong>viso in intervalli, “Bucket Intervals” (rettangoli grigi),<br />

<strong>di</strong> N millisecon<strong>di</strong> (rettangolo verde), calcolati in base al <strong>Peer</strong> più len<strong>to</strong>.<br />

Viene inoltre defini<strong>to</strong> <strong>un</strong> TimeSpan, “Delay” (rettangolo rosso), calcola<strong>to</strong> in<br />

base alla latenza più alta presente all’interno della Membership. Ogni <strong>Peer</strong><br />

assegna ad ogni singolo intervallo <strong>un</strong> “Bucket”, cioè <strong>un</strong> Buffer destina<strong>to</strong> a<br />

mantenere gli eventi in attesa <strong>di</strong> essere effettivamente eseguiti.<br />

Nell’intervallo I1, il <strong>Peer</strong> A genera <strong>un</strong> even<strong>to</strong> e lo invia <strong>di</strong> conseguenza agli<br />

altri <strong>Peer</strong> appartenenti alla Membership (<strong>Peer</strong> B). Localmente, però, tale<br />

even<strong>to</strong> non viene esegui<strong>to</strong> come conseguenza <strong>di</strong>retta della <strong>su</strong>a generazione:<br />

Verrà invece esegui<strong>to</strong> in I3, poiché quest’ultimo rappresenta il primo intervallo<br />

<strong>di</strong> tempo <strong>su</strong>ccessivo all’istante in<strong>di</strong>vidua<strong>to</strong> dalla somma temporale tra<br />

il momen<strong>to</strong> <strong>di</strong> generazione ed il periodo <strong>di</strong> “Delay”.<br />

Il <strong>Peer</strong> B, riceve l’even<strong>to</strong> in I2 ma, utilizzando il medesimo calcolo, sa che<br />

dovrà eseguirlo in I3. In entrambi i <strong>Peer</strong>, quin<strong>di</strong>, l’even<strong>to</strong> in questione verrà<br />

memorizza<strong>to</strong> nel Bucket relativo all’intervallo I3, e quin<strong>di</strong> esegui<strong>to</strong> a tempo<br />

debi<strong>to</strong>.


1.3. SINCRONIZZAZIONE TEMPORALE 13<br />

Figura 1.6: Time-Warp Synchronization: ogni even<strong>to</strong> è temporizza<strong>to</strong> tramite<br />

<strong>un</strong> TimeStamp e viene esegui<strong>to</strong> <strong>di</strong>rettamente al momen<strong>to</strong> della <strong>su</strong>a ricezione.<br />

Dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista del <strong>Peer</strong> B, la situazione mostrata in figura si configura<br />

nel modo seguente: Il <strong>Peer</strong> A genera <strong>un</strong> even<strong>to</strong> in TS 0, mentre il <strong>Peer</strong> C<br />

genera <strong>un</strong> even<strong>to</strong> in TS 2.<br />

In TS 4 l’even<strong>to</strong> <strong>di</strong> A gi<strong>un</strong>ge a B, e viene imme<strong>di</strong>atamente esegui<strong>to</strong>, mentre<br />

l’even<strong>to</strong> <strong>di</strong> C tarda ad arrivare.<br />

In TS 7 il <strong>Peer</strong> A invia <strong>un</strong> secondo even<strong>to</strong> che gi<strong>un</strong>ge a B in TS 8.<br />

Solo in TS 12 il <strong>Peer</strong> B riceve l’even<strong>to</strong> invia<strong>to</strong> da C in T 2.<br />

Il <strong>Peer</strong> B, però ha già esegui<strong>to</strong> il secondo even<strong>to</strong> proveniente da A (TS 7),<br />

quin<strong>di</strong> è costret<strong>to</strong> ad eseguire <strong>un</strong> Roll-back, poiché l’even<strong>to</strong> invia<strong>to</strong> dal <strong>Peer</strong> C<br />

deve essere esegui<strong>to</strong> prima, in quan<strong>to</strong> genera<strong>to</strong> ad <strong>un</strong> TimeStamp precedente.<br />

Elimina quin<strong>di</strong> gli effetti causati dal secondo messaggio <strong>di</strong> A me<strong>di</strong>ante <strong>un</strong><br />

“Anti-Message”, notifica<strong>to</strong> <strong>di</strong> conseguenza agli altri <strong>Peer</strong>. L’UnDo può essere<br />

implementa<strong>to</strong> ad esempio memorizzando lo sta<strong>to</strong> incrementale in <strong>un</strong>a “State<br />

queue”.


14 CAPITOLO 1. STATO DELL’ARTE<br />

1.4 Tecnologie<br />

Dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista dello sviluppo, il videogioco è <strong>un</strong> software complesso,<br />

e come tale si presta ad essere <strong>di</strong>viso in moduli separati, ogn<strong>un</strong>o de<strong>di</strong>ca<strong>to</strong> ad<br />

<strong>un</strong>a precisa f<strong>un</strong>zione.<br />

Escludendo il modulo che implementa le logiche <strong>di</strong> gioco, che è fisiologicamente<br />

<strong>di</strong>pendente dalle specifiche <strong>di</strong> gameplay, si possono in<strong>di</strong>viduare moduli,<br />

tipicamente generalizzabili, come il Renderer (o Engine 3D), utilizza<strong>to</strong> per<br />

<strong>di</strong>segnare <strong>su</strong> schermo gli oggetti tri<strong>di</strong>mensionali, l’Engine fisico, utilizza<strong>to</strong><br />

invece per simulare il movimen<strong>to</strong>, le collisioni e le relative risposte o l’Engine<br />

<strong>di</strong> rete (Networking Engine o “NetCode”), de<strong>di</strong>ca<strong>to</strong> alla connessione e alla<br />

sincronizzazione dello sta<strong>to</strong> <strong>di</strong> gioco.<br />

Dal momen<strong>to</strong> che le f<strong>un</strong>zioni <strong>su</strong>pportate da tali moduli sono piut<strong>to</strong>s<strong>to</strong> generiche<br />

e “gamelogic independent”, <strong>di</strong>versi Team e Software House rilasciano<br />

pubblicamente le versioni dei propri Engines, opport<strong>un</strong>amente aggiornati secondo<br />

gli ultimi standard qualitativi. In ques<strong>to</strong> modo è possibile sviluppare<br />

videogiochi astraendo da <strong>un</strong>a vasta gamma <strong>di</strong> aspetti inerenti al game development,<br />

evitando quin<strong>di</strong> <strong>di</strong> dover reimplementare complesse componenti<br />

software già esistenti, e risolverne le problematiche annesse.<br />

Per quan<strong>to</strong> riguarda gli Engines 3D, spesso questi sono accompagnati da<br />

mo<strong>to</strong>ri <strong>di</strong> gioco e Tools <strong>di</strong> <strong>su</strong>ppor<strong>to</strong>: attualmente a livello <strong>di</strong> software Open<br />

Source, gli Engines grafici più utilizzati sono Ogre3D 6 che si presenta come<br />

Renderer multipiattaforma basa<strong>to</strong> <strong>su</strong> <strong>un</strong>o scenegraph a no<strong>di</strong>, e Irrlicht 7 ,<br />

simile al primo quan<strong>to</strong> a features <strong>di</strong> base ma pre<strong>di</strong>spos<strong>to</strong> al <strong>su</strong>ppor<strong>to</strong> <strong>di</strong> caratteristiche<br />

tipiche <strong>di</strong> <strong>un</strong> <strong>Game</strong> Engine quali la gestione input, dell’au<strong>di</strong>o e<br />

della fisica.<br />

6 Object-Oriented Graphics Rendering Engine, http://www.ogre3d.org<br />

7 http://irrlicht.sourceforge.net


1.4. TECNOLOGIE 15<br />

In molte realtà, però, si mira alla realizzazione <strong>di</strong> mo<strong>to</strong>ri e <strong>to</strong>ols meno<br />

“general purpose” e più orientati a quelle che sono le features particolari richieste<br />

dalle specifiche <strong>di</strong> gioco. Tra questi ve ne sono alc<strong>un</strong>i appositamente<br />

sviluppati in modo da lasciare <strong>un</strong> grado <strong>di</strong> libertà tale da poter essere riutilizzati,<br />

<strong>su</strong>ccessivamente, per la realizzazione <strong>di</strong> nuovi ti<strong>to</strong>li, eventualmente<br />

anche sviluppati da terze parti. Tra questi vi sono l’id Tech <strong>di</strong> ID Software,<br />

famoso per essere sta<strong>to</strong> utilizza<strong>to</strong> come tecnologia <strong>di</strong> base per realizzare le<br />

serie <strong>di</strong> DooM e <strong>di</strong> Quake ed ormai gi<strong>un</strong><strong>to</strong> alla <strong>su</strong>a quinta versione, l’Unreal<br />

Technology, <strong>di</strong> Epic <strong>Game</strong>s, utilizza<strong>to</strong> invece per la serie Unreal e per numerosi<br />

altri ti<strong>to</strong>li per PC e console, ed il CryEngine, attualmente utilizza<strong>to</strong><br />

esclusivamente per la serie Crysis ma tecnicamente ancora all’avanguar<strong>di</strong>a.<br />

Da qualche anno, inoltre, è aumentata la richiesta <strong>di</strong> Middleware crossplatform<br />

a basso cos<strong>to</strong> che, oltre all’Engine 3D, offrano ambienti integranti<br />

E<strong>di</strong><strong>to</strong>rs, Tools, Engines <strong>di</strong> gioco, Engines fisici, <strong>su</strong>ppor<strong>to</strong> au<strong>di</strong>o e gestione<br />

degli input: Unity3D 8 ne è <strong>un</strong> esempio. Altrettan<strong>to</strong> vali<strong>di</strong> sono Shiva 3D 9<br />

e l’UDK 10 .<br />

Un <strong>di</strong>scorso analogo lo si può fare per quan<strong>to</strong> riguarda i moduli relativi<br />

alla gestione <strong>di</strong> rete:<br />

RakNet 11 è <strong>un</strong> <strong>Game</strong> Networking Engine crossplatform che oltre a features<br />

base a livello <strong>di</strong> com<strong>un</strong>icazione (NAT P<strong>un</strong>chthrough, or<strong>di</strong>namen<strong>to</strong> messaggi,<br />

serializzazione e generazione pacchetti) e a livello applicazione Object<br />

replication e chiamate remote, offre <strong>un</strong>a serie <strong>di</strong> f<strong>un</strong>zioni aggi<strong>un</strong>tive come la<br />

gestione utenti, gestione lobby, stanze e matchmaking. Supporta sia il modello<br />

Client-Server che quello <strong>Peer</strong>-To-<strong>Peer</strong>.<br />

8 http://<strong>un</strong>ity3d.com<br />

9 http://www.s<strong>to</strong>netrip.com<br />

10 Unreal Development Kit, http://www.udk.com<br />

11 http://www.jenkinssoftware.com


16 CAPITOLO 1. STATO DELL’ARTE<br />

SmartFoxServer 12 , è <strong>un</strong> ambiente integra<strong>to</strong> con caratteristiche simili a<br />

RakNet ma orientate maggiormente verso la semplificazione <strong>di</strong> utilizzo: la<strong>to</strong><br />

Server infatti <strong>di</strong>spone <strong>di</strong> <strong>un</strong>a notevole quantità <strong>di</strong> strumenti <strong>di</strong> amministrazione<br />

per la gestione utenti, mentre la<strong>to</strong> Client mette a <strong>di</strong>sposizione <strong>un</strong>a serie<br />

<strong>di</strong> API per migliorarne l’integrazione.<br />

Altre librerie invece omet<strong>to</strong>no appositamente alc<strong>un</strong>e features <strong>di</strong> più al<strong>to</strong><br />

livello, in favore <strong>di</strong> <strong>un</strong>a maggiore flessibilità <strong>di</strong> implementazione la<strong>to</strong> utente:<br />

Zoidcom 13 , ad esempio, fornisce sistemi <strong>di</strong> Object replication e sincronizzazione<br />

degli stati, ma non <strong>su</strong>pporta features legate alla gestione delle partite e<br />

dei gioca<strong>to</strong>ri. Enet 14 , invece, fornisce solamente <strong>un</strong> leggero ma robus<strong>to</strong> Layer<br />

<strong>di</strong> com<strong>un</strong>icazione basa<strong>to</strong> <strong>su</strong>l pro<strong>to</strong>collo UDP.<br />

12 http://www.smartfoxserver.com<br />

13 http://www.zoidcom.com<br />

14 http://enet.bespin.org


Capi<strong>to</strong>lo 2<br />

Architettura Software<br />

2.1 Problematiche<br />

L’esigenza <strong>di</strong> <strong>un</strong> elevata reattività <strong>di</strong> risposta (logica e visiva) ai coman<strong>di</strong><br />

del gioca<strong>to</strong>re è sentita in quantità <strong>di</strong>fferente a seconda della tipologia <strong>di</strong> gioco:<br />

In <strong>un</strong> gioco Arcade 1 , ad esempio, il Timespan 2 tra l’input “meccanico”<br />

dell’utente ed il relativo feedback visivo deve essere estremamente ridot<strong>to</strong> (si<br />

pensi al movimen<strong>to</strong> del personaggio controlla<strong>to</strong> dal gioca<strong>to</strong>re in <strong>un</strong> FPS 3 ),<br />

mentre in <strong>un</strong> gioco TBS 4 tut<strong>to</strong> ques<strong>to</strong> non è necessario, dal momen<strong>to</strong> che i<br />

coman<strong>di</strong> impartiti dal gioca<strong>to</strong>re verranno eseguiti solo alla fine <strong>di</strong> <strong>un</strong> turno<br />

che può durare anche <strong>di</strong>versi minuti.<br />

Queste <strong>di</strong>fferenze influenzano non solo il design degli algoritmi e delle<br />

strutture dati relativi alla logica specifica del gameplay 5 , ma anche alc<strong>un</strong>e<br />

scelte progettuali <strong>su</strong>l design del <strong>Game</strong> Engine 6 :<br />

1 Un videogioco caratterizza<strong>to</strong> da <strong>di</strong>namiche rapide, imme<strong>di</strong>ate, e con ridotte pretese <strong>di</strong><br />

realismo<br />

2 Lasso <strong>di</strong> tempo<br />

3 First-person shooter, Sparatut<strong>to</strong> in prima persona<br />

4 Turn-based strategy, Gioco strategico a turni<br />

5 Regole e <strong>di</strong>namiche logiche e d’interazione che contrad<strong>di</strong>stinguono il gioco<br />

6 Genericamente è inteso come l’insieme dei sistemi software che gestiscono il rendering,<br />

le animazioni, la logica, le collisioni, la scena, l’intelligenza artificiale, au<strong>di</strong>o, input ed il<br />

17


18 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Riprendendo l’esempio precedente, e limitando il contes<strong>to</strong> ai soli giochi offline,<br />

al fine <strong>di</strong> realizzare <strong>un</strong> semplice gioco Arcade può non essere necessaria<br />

<strong>un</strong>a forte separazione tra il Layer logico (Business Layer) ed il Layer <strong>di</strong> vi<strong>su</strong>alizzazione<br />

(Presentation Layer): lo spostamen<strong>to</strong> <strong>di</strong> <strong>un</strong>o Sprite 7 che ne simula<br />

il movimen<strong>to</strong> <strong>su</strong> schermo, può essere realizza<strong>to</strong> mo<strong>di</strong>ficando <strong>di</strong>rettamente le<br />

variabili relative alla posizione <strong>di</strong> <strong>di</strong>segno dello stesso, come imme<strong>di</strong>ata conseguenza<br />

dell’input dell’utente.<br />

In <strong>un</strong> TBS, invece, i due Layer tendono ad essere <strong>di</strong>saccoppiati in modo<br />

naturale, portando il Layer <strong>di</strong> vi<strong>su</strong>alizzazione ad essere <strong>un</strong>a mera rappresentazione<br />

dei dati logici che, in ultima analisi, sono gli <strong>un</strong>ici deten<strong>to</strong>ri dello<br />

sta<strong>to</strong> attuale <strong>di</strong> gioco.<br />

Se però si estende l’esempio ampliandolo ai giochi online, allora anche per<br />

<strong>un</strong> gioco Arcade sarà opport<strong>un</strong>o seguire <strong>un</strong> pattern Three-tier 8 o MVC-like 9 ,<br />

dal momen<strong>to</strong> che avere <strong>un</strong> Layer logico separa<strong>to</strong> semplifica l’identificazione,<br />

la ricerca, l’accesso e quin<strong>di</strong> la sincronizzazione dello sta<strong>to</strong> <strong>di</strong> gioco. Non<br />

solo: In ques<strong>to</strong> contes<strong>to</strong> nascono problematiche relative alla latenza <strong>di</strong> rete,<br />

specialmente proprio in quelle tipologie <strong>di</strong> gioco che richiedono contemporaneamente<br />

massima reattività e massima consistenza.<br />

Idealmente, quin<strong>di</strong>, anche quelle azioni che normalmente, in architetture Singleplayer<br />

oriented, producono <strong>un</strong> feedback <strong>di</strong>ret<strong>to</strong>, come lo spostamen<strong>to</strong> <strong>di</strong><br />

<strong>un</strong> elemen<strong>to</strong> grafico in conseguenza ad <strong>un</strong>o specifico input, devono qui essere<br />

processate attraverso <strong>di</strong>versi Layer prima <strong>di</strong> essere eseguite, eventualmente<br />

anche con <strong>un</strong> apposi<strong>to</strong> ritardo introdot<strong>to</strong> volutamente da alc<strong>un</strong>i sistemi<br />

<strong>di</strong> sincronizzazione (si veda la sezione 4). Per alc<strong>un</strong>e tipologie <strong>di</strong> gameplay,<br />

però, tale ritardo finisce con l’impattare negativamente <strong>su</strong>ll’esperienza <strong>di</strong> gionetworking<br />

7 Un qualsiasi elemen<strong>to</strong> grafico, statico o <strong>di</strong>namico, che compone la scena <strong>di</strong> gioco<br />

8 Architettura software caratterizzata da tre moduli: Interfaccia Utente, Logica<br />

F<strong>un</strong>zionale e Dati<br />

9 Model-View-Controller, <strong>un</strong> pattern architetturale che vede separati i concetti <strong>di</strong> Model:<br />

il sistema <strong>di</strong> accesso ai dati, View: Il sistema <strong>di</strong> vi<strong>su</strong>alizzazione dati, ed il Controller: Il<br />

sistema <strong>di</strong> mo<strong>di</strong>fica dei dati


2.1. PROBLEMATICHE 19<br />

co, rendendo necessaria l’implementazione <strong>di</strong> sistemi <strong>di</strong> interpolazione e <strong>di</strong><br />

Pre<strong>di</strong>ction che ne attenuino gli effetti <strong>di</strong> latenza percepiti dall’utente (2.7.1).<br />

Laddove ques<strong>to</strong> non bastasse, è possibile, uscendo però dal design propos<strong>to</strong><br />

dalla pipeline illustrata precedentemente, parallelizzare tale esecuzione<br />

processandola imme<strong>di</strong>atamente in <strong>un</strong> contes<strong>to</strong> locale, e, <strong>su</strong>ccessivamente interpolandone<br />

gli effetti ri<strong>su</strong>ltanti dall’esecuzione remota.<br />

Astraendo dall’architettura <strong>di</strong> rete utilizzata, quello che si mira ad avere<br />

è <strong>un</strong>o sta<strong>to</strong> <strong>di</strong> gioco “con<strong>di</strong>viso” da tutti gli at<strong>to</strong>ri partecipanti alla rete:<br />

In <strong>un</strong> sistema Client-Server lo sta<strong>to</strong> <strong>di</strong> gioco è mantenu<strong>to</strong> dal Server, ma <strong>un</strong>a<br />

<strong>su</strong>a copia, tipicamente meno estesa e dettagliata, è presente com<strong>un</strong>que <strong>su</strong><br />

ogni singolo Client. Ques<strong>to</strong> accade specialmente in quelle tipologie <strong>di</strong> gioco<br />

che richiedono continui accessi al da<strong>to</strong>, poiché accedere <strong>di</strong>rettamente ai Layer<br />

Business (o Data) del Server sarebbe deleterio in termini <strong>di</strong> performance, <strong>di</strong><br />

sicurezza e, in ultima analisi, <strong>di</strong> design.<br />

A maggior ragione, in <strong>un</strong> sistema <strong>Peer</strong>-<strong>to</strong>-<strong>Peer</strong> lo sta<strong>to</strong> <strong>di</strong> gioco deve risiedere<br />

<strong>su</strong> ogni nodo, e ques<strong>to</strong> introduce problematiche <strong>di</strong> sincronizzazione dello sta<strong>to</strong><br />

<strong>di</strong> gioco, rendendo necessaria l’implementazione <strong>di</strong> politiche atte a garantirne<br />

la consistenza. Su ogni nodo infatti risiede <strong>un</strong>a copia dello sta<strong>to</strong> <strong>di</strong> gioco <strong>su</strong>l<br />

quale vengono operate mo<strong>di</strong>fiche in modo in<strong>di</strong>pendente a seconda degli eventi<br />

ricevuti da altri no<strong>di</strong> in relazione alla logica <strong>di</strong> gioco implementata.<br />

Se la politica <strong>di</strong> sincronizzazione adottata prevede la possibilità <strong>di</strong> eseguire<br />

dei Rollback, tale copià può anche essere mantenuta <strong>su</strong> più istanze, mirate<br />

a fornire <strong>un</strong>a sorta <strong>di</strong> backup dal quale attingere in caso <strong>di</strong> Rollback le informazioni<br />

necessarie a ripristinare lo sta<strong>to</strong> precedente (si veda Figura 1.6).<br />

Come anticipa<strong>to</strong> nell’introduzione, per l’implementazione del proget<strong>to</strong> <strong>di</strong><br />

tesi si è scel<strong>to</strong> <strong>di</strong> limitare l’inconsistenza utilizzando <strong>un</strong> approccio che sot<strong>to</strong><br />

alc<strong>un</strong>i aspetti si <strong>di</strong>scosta da <strong>un</strong>’architettura <strong>Peer</strong>-To-<strong>Peer</strong> “pura”.<br />

Il sistema <strong>di</strong> sincronizzazione utilizza<strong>to</strong> pre<strong>di</strong>lige <strong>un</strong>a politica più “State-<br />

Driven” che “Event-Driven”: Infatti ogni nodo non sarà perfettamente pa-


20 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

ritetico: manterrà <strong>un</strong>a <strong>su</strong>a visione del Data Layer, ma opererà solo <strong>su</strong> <strong>un</strong><br />

limita<strong>to</strong> numero <strong>di</strong> dati <strong>di</strong> <strong>su</strong>a appartenenza.<br />

Ques<strong>to</strong> approccio coinciderà con <strong>un</strong> Data Layer nel quale ogni singola<br />

informazione a<strong>to</strong>mica è <strong>di</strong> proprietà <strong>di</strong> <strong>un</strong> generico “Owner”, ed è quin<strong>di</strong><br />

vincolata da <strong>un</strong>a serie <strong>di</strong> regole che ne garantiscono i permessi esclusivi <strong>di</strong><br />

creazione, mo<strong>di</strong>fica e <strong>di</strong>struzione. Nella fattispecie l’Owner coinciderà con i<br />

concetti <strong>di</strong> Player e <strong>di</strong> <strong>Peer</strong>.<br />

Quest’ultimo è concretizza<strong>to</strong> nel Layer de<strong>di</strong>ca<strong>to</strong> alla gestione della Membership<br />

dei no<strong>di</strong> che partecipano alla rete. Oltre a garantire la mutua conoscenza<br />

tra i <strong>di</strong>versi <strong>Peer</strong>, astrae il Layer NET sot<strong>to</strong>stante, de<strong>di</strong>ca<strong>to</strong> alla com<strong>un</strong>icazione<br />

<strong>di</strong> rete vera e propria.<br />

Rias<strong>su</strong>mendo, il software sarà compos<strong>to</strong> da i seguenti Layer e Moduli:<br />

• Layer View (Presentation Layer): De<strong>di</strong>ca<strong>to</strong> alla rappresentazione vi<strong>su</strong>ale<br />

dello sta<strong>to</strong> logico. Oltre agli aspetti prettamente grafici, impropriamente<br />

include i moduli de<strong>di</strong>cati alla gestione della fisica, dell’au<strong>di</strong>o<br />

e degli input.<br />

• Layer Logic (Business Layer): De<strong>di</strong>ca<strong>to</strong> all’implementazione delle meccaniche<br />

<strong>di</strong> gioco. Sostanzialmente mo<strong>di</strong>fica il Layer Data a seconda<br />

degli Input che gi<strong>un</strong>gono dal Layer View facendo riferimen<strong>to</strong> alle regole<br />

<strong>di</strong> gioco.<br />

• Modulo SharedComponents (Data Layer e Consistenza): Mantiene lo<br />

sta<strong>to</strong> <strong>di</strong> gioco. Espone <strong>un</strong> Manager in grado <strong>di</strong> creare, mo<strong>di</strong>ficare e <strong>di</strong>struggere<br />

i propri componenti, e <strong>di</strong> mantenere <strong>un</strong>a copia dei componenti<br />

creati dai Manager appartenenti agli altri <strong>Peer</strong>.<br />

• Layer P2P (Membership): De<strong>di</strong>ca<strong>to</strong> alla gestione della Membership.<br />

Astrae l’interfaccia del Layer NET sot<strong>to</strong>stante.<br />

• Layer NET (Comm<strong>un</strong>ication): Espone <strong>un</strong>’interfaccia che consente la<br />

com<strong>un</strong>icazione tra N generici endpoints.


2.2. LAYER NET 21<br />

Questa separazione <strong>di</strong> Layer e le loro caratteristiche sono state progettate<br />

per avere <strong>un</strong> sistema il più possibile generico, modulare, e, specialmente nel<br />

Layer inferiori, “gamelogic independent”.<br />

La tipologia <strong>di</strong> gioco scelta per il proget<strong>to</strong> <strong>di</strong> tesi, è identificabile all’interno<br />

della categoria degli “Shooter <strong>Game</strong>s”, che presenta <strong>un</strong> <strong>Game</strong>play dalle<br />

logiche relativamente semplici ed in<strong>di</strong>viduate da <strong>un</strong>a serie <strong>di</strong> elementi caratteristici<br />

del genere: La triade <strong>di</strong> elementi fondamentali <strong>di</strong> <strong>un</strong>o “Shooter” è<br />

formata dal concet<strong>to</strong> <strong>di</strong> “Protagonista”, che può essere sia <strong>un</strong> elemen<strong>to</strong> antropomorfo<br />

(<strong>un</strong> solda<strong>to</strong>) che <strong>un</strong> elemen<strong>to</strong> meccanico (<strong>un</strong>a navetta spaziale)<br />

controlla<strong>to</strong> <strong>di</strong>rettamente dal gioca<strong>to</strong>re; dal concet<strong>to</strong> <strong>di</strong> “Nemico”, che può essere<br />

<strong>un</strong> elemen<strong>to</strong> controlla<strong>to</strong> dalla CPU o <strong>di</strong>rettamente da <strong>un</strong> altro gioca<strong>to</strong>re,<br />

e da <strong>un</strong>’entità in grado <strong>di</strong> apportare danno al “Nemico” conseguentemente<br />

ad <strong>un</strong>a azione ad opera del “Protagonista”, o viceversa.<br />

La scelta è ricaduta <strong>su</strong> ques<strong>to</strong> genere <strong>di</strong> gioco poiché, nella <strong>su</strong>a semplicità,<br />

presenta implicitamente tutta <strong>un</strong>a serie <strong>di</strong> problematiche com<strong>un</strong>i alla<br />

maggior parte delle tipologie <strong>di</strong> gioco, ovvero la creazione e <strong>di</strong>struzione <strong>di</strong><br />

oggetti grafici, la gestione del loro spostamen<strong>to</strong> e delle eventuali collisioni.<br />

Di segui<strong>to</strong> verrà analizza<strong>to</strong> ogni singolo Layer nel dettaglio, lasciando<br />

però gli aspetti prettamente implementativi al prossimo capi<strong>to</strong>lo.<br />

2.2 Layer NET<br />

Ques<strong>to</strong> modulo è necessario per fornire <strong>un</strong>a astrazione <strong>di</strong> quella che è la<br />

com<strong>un</strong>icazione <strong>di</strong> rete a più basso livello. Quest’ultima infatti può <strong>di</strong>fferire<br />

mol<strong>to</strong> da implementazione a implementazione, a partire dal pro<strong>to</strong>collo <strong>di</strong><br />

com<strong>un</strong>icazione fino alla struttura dei singoli pacchetti, mentre i Layer sovrastanti<br />

necessitano <strong>di</strong> <strong>un</strong>’interfaccia astratta e trasparente in ques<strong>to</strong> senso. A<br />

ques<strong>to</strong> proposi<strong>to</strong>, il Layer espone, tramite <strong>un</strong>’interfaccia, i concetti <strong>di</strong> “Node”


22 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

e <strong>di</strong> “Link”. Un “Node” è sostanzialmente <strong>un</strong> endpoint <strong>di</strong> com<strong>un</strong>icazione,<br />

mentre <strong>un</strong> “Link” è <strong>un</strong>a rappresentazione del canale ci com<strong>un</strong>icazione tra<br />

due endpoints.<br />

In <strong>un</strong> contes<strong>to</strong> <strong>Peer</strong>-To-<strong>Peer</strong> forma<strong>to</strong> da N no<strong>di</strong>, significa che ogni “Node”<br />

possiede N-1 “Link”, <strong>un</strong>o per ogni nodo appartenente alla rete (escluso se<br />

stesso).<br />

Da <strong>un</strong> p<strong>un</strong><strong>to</strong> <strong>di</strong> vista più vicino all’implementazione vera e propria, sia il<br />

“Node” che il “Link” sono considerati “NetElement”, ovvero elementi identificabili<br />

tramite <strong>un</strong> “NetID”, costrui<strong>to</strong> in base all’in<strong>di</strong>rizzo IP e alla porta<br />

<strong>di</strong> ascol<strong>to</strong>.<br />

Quando si vuole connettere <strong>un</strong> nodo A ad <strong>un</strong> nodo B in ascol<strong>to</strong>, in A viene<br />

crea<strong>to</strong> <strong>un</strong> Link identifica<strong>to</strong> dal NetID <strong>di</strong> B. Quando B riceve la richiesta<br />

<strong>di</strong> connessione, può ricavare l’in<strong>di</strong>rizzo IP <strong>di</strong> A, ma non la porta <strong>su</strong>lla quale<br />

sta ascoltando.<br />

Inizia quin<strong>di</strong> <strong>un</strong>a fase <strong>di</strong> Handshaking, eseguita a livello applicazione, nella<br />

quale i due no<strong>di</strong> si scambiano i propri NetID, identificando gli at<strong>to</strong>ri e consolidando<br />

così la connessione.<br />

La fase <strong>di</strong> Handshaking inizia appena <strong>un</strong> nodo (A) riceve la connessione <strong>di</strong><br />

<strong>un</strong> secondo nodo (B).<br />

Il primo step vede A inviare il comando NET “HandShakeBegin” a B.<br />

Quando B riceve tale comando, risponderà inviando ad A il comando NET<br />

“HandShakeResponse” contenente il proprio NetID.<br />

L’ultimo step vede infine A confermare a B l’avvenu<strong>to</strong> riconoscimen<strong>to</strong> tramite<br />

il comando NET “HandShakeEnd”.<br />

Una volta terminata questa fase (Figura 2.1), entrambi i no<strong>di</strong> possono iniziare<br />

a scambiarsi i messaggi inoltrati dai rispettivi Layer <strong>su</strong>periori.


2.2. LAYER NET 23<br />

Figura 2.1: Fase <strong>di</strong> connessione tra due no<strong>di</strong> e relativo Handshaking, esegui<strong>to</strong><br />

all’interno del Layer NET


24 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

2.3 Layer P2P<br />

Una prima f<strong>un</strong>zione <strong>di</strong> ques<strong>to</strong> Layer è quello <strong>di</strong> astrarre quello sot<strong>to</strong>stante<br />

con <strong>un</strong>a serie <strong>di</strong> f<strong>un</strong>zioni <strong>di</strong> al<strong>to</strong> livello che permet<strong>to</strong>no la com<strong>un</strong>icazione tra<br />

i no<strong>di</strong> secondo <strong>un</strong>a logica <strong>Peer</strong>-To-<strong>Peer</strong> senza conoscerne la specifica implementazione.<br />

Ad esempio la f<strong>un</strong>zione “BroadCast(messaggio)” si preoccuperà<br />

<strong>di</strong> inviare lo stesso messaggio, attraverso il Layer NET, a tutti i <strong>Peer</strong> conosciuti.<br />

La seconda f<strong>un</strong>zione <strong>di</strong> ques<strong>to</strong> Layer è quella <strong>di</strong> garantire la conoscenza reciproca<br />

tra i <strong>di</strong>versi <strong>Peer</strong>: ogni <strong>Peer</strong> infatti contiene <strong>un</strong>a lista <strong>di</strong> ’NetID’ relativi<br />

ai <strong>Peer</strong> con i quali ri<strong>su</strong>lta già connesso.<br />

Supponendo <strong>di</strong> avere 5 <strong>Peer</strong>, A, B ,C , D ed E, e che siano già connessi<br />

tra loro secondo lo schema seguente (Figura 2.2): (A-B) , (C-D) , E<br />

Figura 2.2: Organizzazione delle connessioni all’istante T1<br />

• Il <strong>Peer</strong> A ha nella <strong>su</strong>a lista <strong>di</strong> <strong>Peer</strong> conosciuti il NetID <strong>di</strong> B (ed il<br />

proprio)<br />

• Il <strong>Peer</strong> B ha nella <strong>su</strong>a lista <strong>di</strong> <strong>Peer</strong> conosciuti il NetID <strong>di</strong> A (ed il<br />

proprio)<br />

• Il <strong>Peer</strong> C ha nella <strong>su</strong>a lista <strong>di</strong> <strong>Peer</strong> conosciuti il NetID <strong>di</strong> D (ed il<br />

proprio)<br />

• Il <strong>Peer</strong> D ha nella <strong>su</strong>a lista <strong>di</strong> <strong>Peer</strong> conosciuti il NetID <strong>di</strong> C (ed il<br />

proprio)


2.3. LAYER P2P 25<br />

• Il <strong>Peer</strong> E ha nella <strong>su</strong>a lista <strong>di</strong> <strong>Peer</strong> conosciuti solo il proprio NetID<br />

Quando E si connette al <strong>Peer</strong> D, teoricamente entrerebbe a far parte della<br />

rete formata dai <strong>Peer</strong> C,D ed E. Ma E non è a corrente dell’esistenza del<br />

<strong>Peer</strong> C, e viceversa, C non è a corrente dell’esistenza <strong>di</strong> E.<br />

Per ovviare a ques<strong>to</strong> problema, <strong>un</strong>a volta terminata la fase <strong>di</strong> HandShaking<br />

(a carico del Layer NET) tra i rispettivi no<strong>di</strong> <strong>di</strong> D ed E, viene avviata <strong>un</strong>a<br />

seconda fase a carico del Layer P2P, nella quale i <strong>Peer</strong> appena connessi, si<br />

scambiano tutti i NetID <strong>di</strong> loro conoscenza. In ques<strong>to</strong> modo grazie a D, C<br />

conoscerà E, vi si connetterà, e <strong>di</strong> conseguenza E conoscerà D, chiudendo <strong>di</strong><br />

fat<strong>to</strong> la sot<strong>to</strong>rete (C-D-E) (Figura 2.3).<br />

Figura 2.3: Organizzazione delle connessioni all’istante T2<br />

Quando C si connette a B, B notificherà l’esistenza <strong>di</strong> C ad A che vi si<br />

connetterà a <strong>su</strong>a volta. Allo stesso modo, C riferirà a D ed E dell’esistenza<br />

<strong>di</strong> B e quin<strong>di</strong> <strong>di</strong> A. Infine D ed E si connetteranno entrambi ad A e B<br />

(Figura 2.4).<br />

Figura 2.4: Organizzazione delle connessioni all’istante T3<br />

In (Figura 2.5) sono mostrate le fasi <strong>di</strong> connessione tra due <strong>Peer</strong>, sia del<br />

Layer NET che del Layer P2P A e B.


26 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Figura 2.5: Fasi preliminari <strong>di</strong> connessione tra due <strong>Peer</strong><br />

Ad <strong>un</strong> istante T0, il <strong>Peer</strong> B si connette al <strong>Peer</strong> A.<br />

All’istante imme<strong>di</strong>atamente <strong>su</strong>ccessivo, nel contes<strong>to</strong> dell Layer NET, avviene<br />

la fase <strong>di</strong> HandShaking.<br />

Quando questa termina, nel contes<strong>to</strong> del Layer P2P, si attiva la fase <strong>di</strong> interscambio<br />

dei NetID conosciuti. In ques<strong>to</strong> caso B conosce solo B (se stesso)<br />

ed A conosce solo A (se stesso).<br />

B invierà quin<strong>di</strong> ad A il comando P2P “Add<strong>Peer</strong>” parametrizza<strong>to</strong> con il<br />

proprio NetID. A farà lo stesso, inviando a B il comando P2P “Add<strong>Peer</strong>”<br />

parametrizza<strong>to</strong> con il proprio NetID.<br />

Quando A riceverà il comando P2P “Add<strong>Peer</strong>” contenente il NetID <strong>di</strong> B,<br />

controllerà che ques<strong>to</strong> non sia già presente nella propria lista dei <strong>Peer</strong> conosciuti:<br />

nel caso non sia effettivamente presente, aprirà au<strong>to</strong>maticamente <strong>un</strong>a<br />

connessione verso il NetID appena ricevu<strong>to</strong>.<br />

Non è ques<strong>to</strong> il caso, dal momen<strong>to</strong> che i <strong>Peer</strong> sono solo due, ed entrambi si<br />

conoscono a vicenda <strong>di</strong>rettamente dalla fase <strong>di</strong> HandShaking.


2.3. LAYER P2P 27<br />

Se però nell’esempio viene introdotta <strong>un</strong>a seconda sot<strong>to</strong>rete formata dai <strong>Peer</strong><br />

C e D (Figura 2.6), questa fase as<strong>su</strong>me maggior concretezza: in T1, il <strong>Peer</strong><br />

C si connette al <strong>Peer</strong> B, ed in T2 viene attivata la fase <strong>di</strong> scambio NetID,<br />

implementata tramite il comando P2P “Add<strong>Peer</strong>” (freccia in arancione):<br />

Figura 2.6: Fasi preliminari <strong>di</strong> connessione tra due sot<strong>to</strong>reti composte<br />

ciasc<strong>un</strong>a da due <strong>Peer</strong><br />

Il <strong>Peer</strong> C ha, nella lista <strong>di</strong> <strong>Peer</strong> conosciuti, se stesso ed il <strong>Peer</strong> D. Pertan<strong>to</strong><br />

invierà a B due coman<strong>di</strong> P2P “Add<strong>Peer</strong>”; il primo parametrizza<strong>to</strong> con il<br />

proprio NetID, ed il secondo parametrizza<strong>to</strong> con il NetID <strong>di</strong> D.<br />

Quando il primo comando “Add<strong>Peer</strong>” gi<strong>un</strong>gerà al <strong>Peer</strong> B, quest’ultimo controllerà<br />

che il NetID contenu<strong>to</strong> come parametro del comando stesso, non sia


28 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

già presente nella propria lista <strong>di</strong> <strong>Peer</strong> conosciuti.<br />

In ques<strong>to</strong> caso B è già a conoscenza dell’esistenza <strong>di</strong> C, dal momen<strong>to</strong> che la<br />

connessione è avvenuta proprio tra B e C.<br />

Quando però arriva il secondo comando “Add<strong>Peer</strong>”, parametrizza<strong>to</strong> con il<br />

NetID <strong>di</strong> D, il <strong>Peer</strong> B, controllando nella propria lista <strong>di</strong> <strong>Peer</strong> conosciuti, si<br />

accorge <strong>di</strong> non conoscere il <strong>Peer</strong> identifica<strong>to</strong> dal NetID <strong>di</strong> D. A ques<strong>to</strong> p<strong>un</strong><strong>to</strong>,<br />

quin<strong>di</strong>, Il <strong>Peer</strong> B si connetterà al NetID <strong>di</strong> D per includerlo tra i propri <strong>Peer</strong><br />

conosciuti.<br />

Si attiva quin<strong>di</strong> <strong>un</strong>a propagazione “a catena” che terminerà solo <strong>un</strong>a volta<br />

che tutte le liste <strong>di</strong> <strong>Peer</strong> conosciuti coincideranno tra loro.<br />

2.3.1 Modulo Time<br />

All’interno del Layer P2P, è presente <strong>un</strong> sot<strong>to</strong>-modulo che si occupa della<br />

gestione del Timing, mira<strong>to</strong> a garantire <strong>un</strong>a visione temporale con<strong>di</strong>visa.<br />

Una volta terminata la fase <strong>di</strong> consolidamen<strong>to</strong> della Membership, inizia<br />

<strong>un</strong>a fase parallela e prol<strong>un</strong>gata nel tempo: ogni <strong>Peer</strong> notificherà a tutti gli<br />

altri <strong>Peer</strong> conosciuti, quello che è il valore del proprio TimeStamp <strong>di</strong> sistema<br />

attraverso il comando TimeSync.<br />

Quando <strong>un</strong> <strong>Peer</strong> A riceverà <strong>un</strong> comando TimeSync da <strong>un</strong> <strong>Peer</strong> B, calcolerà<br />

il delta tra il TimeStamp in esso contenu<strong>to</strong> ed il proprio, e lo memorizzerà<br />

in <strong>un</strong>’apposita lista in<strong>di</strong>cizzata per NetID. Il valore del delta deve inoltre<br />

comprendere <strong>un</strong> TimeSpan che compensi il fat<strong>to</strong>re Lag: viene infatti aggi<strong>un</strong><strong>to</strong><br />

<strong>un</strong> lasso temporale calcola<strong>to</strong> in base al tempo <strong>di</strong> latenza tra la richiesta<br />

TimeSync e la relativa risposta.<br />

Dal momen<strong>to</strong> che questa fase viene reiterata (dopo <strong>un</strong> determina<strong>to</strong> periodo<br />

<strong>di</strong> tempo viene infatti esegui<strong>to</strong> nuovamente <strong>un</strong> BroadCast <strong>di</strong> TimeSync),<br />

ogni <strong>Peer</strong> conoscerà con <strong>un</strong>a <strong>di</strong>screta precisione il fat<strong>to</strong>re <strong>di</strong> conversione del<br />

TimeSpan <strong>di</strong> tutti gli altri <strong>Peer</strong>, rispet<strong>to</strong> al proprio.


2.3. LAYER P2P 29<br />

Ques<strong>to</strong> modulo, quin<strong>di</strong>, permette <strong>di</strong> convertire in maniera del tut<strong>to</strong> trasparente<br />

il TimeStamp del mittente, che viene appeso a tutti i coman<strong>di</strong> del Layer<br />

Logic, utilizzando come base <strong>di</strong> conversione il proprio TimeStamp.<br />

Non vi è quin<strong>di</strong> <strong>un</strong> sistema <strong>di</strong> Master Clock assolu<strong>to</strong>, associa<strong>to</strong> ad <strong>un</strong> <strong>Peer</strong><br />

elet<strong>to</strong> tale, ad <strong>un</strong>a risorsa esterna alla Membership od <strong>un</strong> sistema centralizza<strong>to</strong><br />

Client-Server, come accade per il più accura<strong>to</strong> NTP 10 , ma <strong>un</strong> sistema<br />

basa<strong>to</strong> <strong>su</strong>lla conversione <strong>di</strong> TimeSpan relativi, simile a quan<strong>to</strong> avviene nella<br />

la conversione <strong>di</strong> orari provenienti da fusi orari <strong>di</strong>fferenti (Figura 2.7 e<br />

Figura 2.8).<br />

Figura 2.7: I <strong>Peer</strong> A e B inviano il proprio TimeStamp a C, che ne memorizza<br />

il TimeSpan rispet<strong>to</strong> al proprio<br />

Ques<strong>to</strong> sistema ri<strong>su</strong>lta essere sogget<strong>to</strong> a problemi derivanti dalla variazione<br />

<strong>di</strong> latenza (Jitter) tra i <strong>di</strong>versi <strong>Peer</strong>: i delta sono infatti destinati a <strong>su</strong>bire<br />

oscillazioni ad ogni aggiornamen<strong>to</strong>, rendendo la stima temporale piut<strong>to</strong>s<strong>to</strong><br />

approssimativa.<br />

L’accuratezza richiesta nelle applicazioni real-time, specialmente nelle situazioni<br />

concorrenziali, viene qui mitigata dal sistema implementa<strong>to</strong> nel Modulo<br />

SharedComponents (sezione 2.4): Grazie a quest’ultimo non si possono presentare<br />

casi <strong>di</strong> inconsistenza dello sta<strong>to</strong> <strong>di</strong> gioco dovuti al margine <strong>di</strong> errore<br />

10 Network Time Pro<strong>to</strong>col


30 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Figura 2.8: Quando arriva <strong>un</strong> comando o <strong>un</strong> even<strong>to</strong> temporizza<strong>to</strong> dal <strong>Peer</strong><br />

A secondo il <strong>su</strong>o sistema <strong>di</strong> riferimen<strong>to</strong>, al <strong>Peer</strong> C, quest’ultimo converte il<br />

TimeStamp secondo il delta precedentemente memorizza<strong>to</strong><br />

temporale relativamente eleva<strong>to</strong>, poichè situazioni temporalmente sensibili<br />

(ad esempio <strong>un</strong>a collisione con <strong>un</strong> proiettile) per le quali due peer mo<strong>di</strong>ficano<br />

la stessa risorsa sono opport<strong>un</strong>amente vincolate dal modulo in questione:<br />

l’assenza <strong>di</strong> <strong>un</strong> qualche tipo <strong>di</strong> sincronizzazione temporale (4), anche se non<br />

impatta <strong>su</strong>lla consistenza dello sta<strong>to</strong> <strong>di</strong> gioco, tende a penalizzare notevolmente<br />

l’esperienza <strong>di</strong> gioco dei <strong>Peer</strong> con alta latenza (si veda Figura 2.28 ed<br />

il capi<strong>to</strong>lo 4).<br />

2.4 Modulo SharedComponents<br />

Ques<strong>to</strong> modulo fornisce la base per il Data Layer, ed è completamente<br />

<strong>di</strong>saccoppia<strong>to</strong> dai Layer precedenti (NET e P2P): si presenta come <strong>un</strong> piccolo<br />

Framework de<strong>di</strong>ca<strong>to</strong> alla rappresentazione <strong>di</strong> <strong>un</strong>a sorta <strong>di</strong> “memoria” <strong>di</strong> al<strong>to</strong><br />

livello <strong>su</strong>lla quale memorizzare lo sta<strong>to</strong> <strong>di</strong> gioco (Figura 2.9), riprendendo in<br />

parte l’idea delle Distributed Hash Table (DHT).<br />

Si basa <strong>su</strong>l concet<strong>to</strong> <strong>di</strong> componente, inteso come il minimo elemen<strong>to</strong> in<br />

grado <strong>di</strong> apportare informazione <strong>su</strong>llo sta<strong>to</strong> <strong>di</strong> gioco:


2.4. MODULO SHAREDCOMPONENTS 31<br />

Il p<strong>un</strong>teggio <strong>di</strong> <strong>un</strong> gioca<strong>to</strong>re, ad esempio, può essere vis<strong>to</strong> come <strong>un</strong> componente,<br />

così come la posizione del <strong>su</strong>o personaggio all’interno dell’ambiente <strong>di</strong><br />

gioco.<br />

La stessa posizione, a <strong>su</strong>a volta è composta da 3 sot<strong>to</strong>-componenti (X, Y e<br />

Z ) secondo il Composite Pattern 11<br />

I componenti che riescono a rappresentare informazioni a<strong>to</strong>miche, senza<br />

doversi appoggiare a sot<strong>to</strong>-componenti, sono da considerarsi “leaf”, e sono<br />

tipicamente quei componenti che emulano variabili Value Type (ad esempio<br />

il componenti “Int” , “Float” o “String”).<br />

Tutti gli altri componenti (come app<strong>un</strong><strong>to</strong> la posizione del personaggio, che<br />

sarà concretizzata da <strong>un</strong> componente <strong>di</strong> tipo “Vec<strong>to</strong>r3”) sono aggregati, <strong>di</strong>retti<br />

o in<strong>di</strong>retti, <strong>di</strong> quest’ultimi.<br />

Ogni componente soggiace a precise regole che ne consen<strong>to</strong>no <strong>un</strong>a facile<br />

gestione non solo all’interno del modulo stesso, ma specialmente se quest’ultimo<br />

viene utilizza<strong>to</strong> come Data Layer all’interno <strong>di</strong> <strong>un</strong>’applicazione <strong>di</strong><br />

rete:<br />

• Ogni componente (parent) può essere compos<strong>to</strong> da altri componenti<br />

(child)<br />

• Ogni componente deve essere genera<strong>to</strong> da <strong>un</strong> apposi<strong>to</strong> Fac<strong>to</strong>ry 12 (identifica<strong>to</strong><br />

da <strong>un</strong> nome), e non può essere istanzia<strong>to</strong> in modo in<strong>di</strong>pendente.<br />

• Ogni componente è identifica<strong>to</strong> da <strong>un</strong> ID “globale” genera<strong>to</strong> dallo stesso<br />

Fac<strong>to</strong>ry al momen<strong>to</strong> della creazione.<br />

11 Uno dei Pattern fondamentali defini<strong>to</strong> dalla gang of four caratterizza<strong>to</strong> dalla definizione<br />

<strong>di</strong> <strong>un</strong> ogget<strong>to</strong> me<strong>di</strong>ante la composizione <strong>di</strong> altri oggetti (a formare <strong>un</strong>a struttura ad<br />

albero).<br />

12 Secondo l’omonimo pattern creazionale, con Fac<strong>to</strong>ry si intende <strong>un</strong> elemen<strong>to</strong> che<br />

incap<strong>su</strong>la al <strong>su</strong>o interno i processi coinvolti nella creazione <strong>di</strong> oggetti.


32 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

• Ogni componente può avere <strong>un</strong> ID “locale”, se child <strong>di</strong> <strong>un</strong> parent, che<br />

ne identifica la chiave con la quale il parent accederà al child.<br />

• Ogni componente appartiene ad <strong>un</strong> “Type” che ne identifica il tipo<br />

(“Int”, “Float” ,“String” , “Vec<strong>to</strong>r3” , “Object3D”, etc)<br />

• Ogni componente ha <strong>un</strong> valore serializzabile.<br />

• Ogni componente è caratterizza<strong>to</strong> da <strong>un</strong> TimeStamp <strong>di</strong> creazione/mo<strong>di</strong>fica<br />

In ques<strong>to</strong> modo è possibile modellare qualsiasi tipo <strong>di</strong> informazione, non<br />

solo dati relativi agli elementi <strong>di</strong> gioco, ma anche eventi, messaggi e sot<strong>to</strong>stati,<br />

ed identificarla quin<strong>di</strong> <strong>un</strong>ivocamente.<br />

Figura 2.9: Schema dei concetti esposti dal modulo SharedCompontes. I<br />

componenti verde chiaro rappresentano i componenti generati dal Fac<strong>to</strong>ry A,<br />

mentre i componenti verde scuro quelli generati da altri Fac<strong>to</strong>ry.<br />

Il Fac<strong>to</strong>ry <strong>di</strong>spone <strong>di</strong> <strong>di</strong>versi sistemi <strong>di</strong> creazione <strong>di</strong> Componenti:<br />

Il primo, quello <strong>di</strong>ret<strong>to</strong>, istanzia <strong>un</strong> ogget<strong>to</strong> componente e lo “marchia” come


2.4. MODULO SHAREDCOMPONENTS 33<br />

appartenente al proprio Manager. Ques<strong>to</strong> sistema viene utilizza<strong>to</strong> quando da<br />

<strong>un</strong> Layer esterno si vuole creare <strong>un</strong> nuovo componente all’interno del proprio<br />

contes<strong>to</strong>, specificandone solo il tipo ed eventualmente il valore <strong>di</strong> default.<br />

Il secondo invece viene utilizza<strong>to</strong> per istanziare “copie” <strong>di</strong> componenti appartenenti<br />

ad altri Fac<strong>to</strong>ry, eventualmente associati ad altri <strong>Peer</strong> (associazione<br />

che verrà implementata nel prossimo Layer Logic): il componente così crea<strong>to</strong><br />

non sarà <strong>di</strong> proprietà del Fac<strong>to</strong>ry, e non sarà “marchia<strong>to</strong>” come tale, dal<br />

momen<strong>to</strong> che possiede già l’identificativo assegna<strong>to</strong>gli dal Fac<strong>to</strong>ry originale.<br />

Il terzo permette <strong>di</strong> aggi<strong>un</strong>gere <strong>un</strong> generico componente come “sot<strong>to</strong>-componente”<br />

<strong>di</strong> <strong>un</strong> componente già esistente all’interno del contes<strong>to</strong>.<br />

E’ importante notare quin<strong>di</strong> come, all’interno del modulo SharedComponents,<br />

la lista dei componenti non sia popolata necessariamente da componenti<br />

generati dal “proprio” Fac<strong>to</strong>ry.<br />

Se ad esempio si vogliono modellare le informazioni che caratterizzano <strong>un</strong><br />

ogget<strong>to</strong> tri<strong>di</strong>mensionale, si possono utilizzare i seguenti componenti secondo<br />

la gerarchia proposta in Figura 2.10:<br />

Il componente <strong>di</strong> tipo Object3D è caratterizza<strong>to</strong> da due sot<strong>to</strong>-componenti,<br />

rispettivamente identificati dal LocalID “Position” e “Rotation” (non è sta<strong>to</strong><br />

inseri<strong>to</strong> <strong>un</strong> componente relativo al valore <strong>di</strong> Scaling dell’ogget<strong>to</strong> perché è <strong>un</strong><br />

parametro lega<strong>to</strong> maggiormente al Layer VIEW ed eventualmente può essere<br />

com<strong>un</strong>que incluso estendendo ques<strong>to</strong> componente). Entrambi sono componenti<br />

<strong>di</strong> tipo Vec<strong>to</strong>r3 che, come illustra<strong>to</strong> precedentemente, è compos<strong>to</strong> a <strong>su</strong>a<br />

volta dai componenti <strong>di</strong> tipo Float, “X ”,“Y ” e“Z ”.<br />

Un componente non “leaf” viene considera<strong>to</strong> “ready” solo quando tutti<br />

i <strong>su</strong>oi componenti sono stati istanziati e ri<strong>su</strong>ltano “ready” a loro volta: <strong>un</strong><br />

Object3D, quin<strong>di</strong>, non sarà considera<strong>to</strong> “ready” fintan<strong>to</strong> che non lo saranno<br />

i <strong>su</strong>oi due Vec<strong>to</strong>r3 “Position” e “Rotation”;


34 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Figura 2.10: tassonomia dei sot<strong>to</strong>-componenti che, aggregati, realizzano <strong>un</strong><br />

componente <strong>di</strong> tipo Object3D<br />

Questa “frammentazione” dell’informazione ri<strong>su</strong>lta mol<strong>to</strong> comoda specialmente<br />

se la si pensa contestualizzata all’interno <strong>di</strong> <strong>un</strong>’applicazione <strong>di</strong> rete,<br />

come emergerà nel prossimo capi<strong>to</strong>lo.<br />

I coman<strong>di</strong> principali a carico <strong>di</strong> ques<strong>to</strong> Layer sono:<br />

• CreateComponent: Crea <strong>un</strong> componente tramite il Fac<strong>to</strong>ry utilizzando<br />

il sistema <strong>di</strong> “copia” <strong>di</strong> componenti appartenenti ad altri Fac<strong>to</strong>ry, in<br />

quan<strong>to</strong> si pre<strong>su</strong>me che, dal momen<strong>to</strong> che tale comando è gi<strong>un</strong><strong>to</strong> da<br />

<strong>un</strong>’altro contes<strong>to</strong>, il componente da creare appartenga a quest’ultimo.<br />

• UpdateComponent: Aggiorna <strong>un</strong> componente secondo il valore serializza<strong>to</strong><br />

contenu<strong>to</strong> come parametro<br />

• DestroyComponent: Distrugge <strong>un</strong> componente.<br />

• ActivateComponent: Attiva, cioè mo<strong>di</strong>fica l’attribu<strong>to</strong> “ready” <strong>di</strong> <strong>un</strong><br />

componente.


2.5. LAYER LOGIC 35<br />

È presente, inoltre, <strong>un</strong> sistema <strong>di</strong> Messaging tra i <strong>di</strong>versi componenti:<br />

ogni componente infatti può implementare il me<strong>to</strong>do ExecMessage(), e, a<br />

seconda <strong>di</strong> quan<strong>to</strong> riporta<strong>to</strong> come parametro, comportarsi <strong>di</strong> conseguenza.<br />

2.5 Layer Logic<br />

In ques<strong>to</strong> Layer prende forma il contes<strong>to</strong> logico: legando il concet<strong>to</strong> <strong>di</strong><br />

<strong>Peer</strong> espos<strong>to</strong> dal Layer P2P con il Fac<strong>to</strong>ry del DataLayer espos<strong>to</strong> dal modulo<br />

SharedComponents nasce l’idea <strong>di</strong> <strong>un</strong> contes<strong>to</strong> <strong>di</strong> dati appartenenti al singolo<br />

<strong>Peer</strong>.<br />

Ogni componente crea<strong>to</strong> <strong>di</strong>rettamente dal Fac<strong>to</strong>ry ri<strong>su</strong>lterà “lega<strong>to</strong>” al relativo<br />

<strong>Peer</strong>, e <strong>di</strong> conseguenza potrà essere mo<strong>di</strong>fica<strong>to</strong> o <strong>di</strong>strut<strong>to</strong> solo da<br />

quest’ultimo.<br />

A ques<strong>to</strong> Layer, inoltre, è delegata <strong>un</strong>’altra f<strong>un</strong>zione fondamentale, senza<br />

la quale l’utilità del modulo P2P e del modulo SharedComponents sarebbe fine<br />

a se stessa: rimane in ascol<strong>to</strong> delle notifiche (creazione/mo<strong>di</strong>fica/<strong>di</strong>struzione<br />

componenti) in uscita dal modulo SharedComponents, preoccupandosi poi <strong>di</strong><br />

inoltrarle al Layer P2P che, me<strong>di</strong>ante il Layer NET, le segnalerà a <strong>su</strong>a volta<br />

a tutti i <strong>Peer</strong> conosciuti.<br />

Ques<strong>to</strong> porta sostanzialmente ad avere lo stesso DataLayer (cioè popola<strong>to</strong><br />

dagli gli stessi componenti) <strong>su</strong> ogni <strong>Peer</strong>, e le regole che definiscono i permessi<br />

<strong>di</strong> creazione/mo<strong>di</strong>fica/<strong>di</strong>struzione garantiscono la consistenza, dal momen<strong>to</strong><br />

che ogni componente può cambiare <strong>di</strong> sta<strong>to</strong> solo tramite il <strong>su</strong>o <strong>Peer</strong> ’Owner’.<br />

Quando <strong>un</strong> <strong>Peer</strong> A si connette ad <strong>un</strong> <strong>Peer</strong> B, dopo le fasi <strong>di</strong> HandShaking<br />

(Layer NET) e <strong>di</strong> scambio NetID (Layer P2P), A invierà preventivamente a<br />

B i componenti serializzati <strong>di</strong> <strong>su</strong>a proprietà presenti nel proprio SharedComponents,<br />

e B farà lo stesso.<br />

Quando i componenti serializzati <strong>di</strong> A arrivano a B, il Fac<strong>to</strong>ry <strong>di</strong> quest’ultimo<br />

creerà <strong>di</strong> fat<strong>to</strong> <strong>un</strong>a “copia” del Data Layer <strong>di</strong> A (Object Replication).


36 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Figura 2.11: Due Player che non si sono ancora connessi tra loro. Notare<br />

come il Layer Logic utilizzi il Layer P2P ed il modulo SharedComponents<br />

per concretizzare il “contes<strong>to</strong>” logico. Notare inoltre come il contenu<strong>to</strong> del<br />

Data Layer sia <strong>di</strong>fferente tra i due Player.<br />

Figura 2.12: Layer NET: I due Player si connet<strong>to</strong>no e avviano la fase <strong>di</strong><br />

HandShaking.<br />

Figura 2.13: Layer P2P: I due Player si scambiano i NetID conosciuti.


2.5. LAYER LOGIC 37<br />

Figura 2.14: Layer Logic: I due Player si scambiano il contenu<strong>to</strong> corrente dei<br />

propri Data Layer. Notare come, conclusa questa fase, il contenu<strong>to</strong> dei due<br />

Data Layer ri<strong>su</strong>lti identico.<br />

Una volta che i due Player si sono scambiati il contenu<strong>to</strong> dei rispettivi<br />

Data Layer, sono pronti per inviarsi messaggi relativi alla logica <strong>di</strong> gioco.<br />

Ad esempio, quando il personaggio controlla<strong>to</strong> dal Player A, connesso ad<br />

<strong>un</strong> Player B, spara <strong>un</strong> proiettile, crea <strong>di</strong> fat<strong>to</strong> <strong>un</strong> componente logico <strong>di</strong> tipo<br />

“Bullet”. Il componente “Bullet” estende MovingObject3D, che a <strong>su</strong>a volta<br />

estende il componente Object3D.<br />

MovingObject3D ha gli stessi sot<strong>to</strong>-componenti <strong>di</strong> Object3D (Vec<strong>to</strong>r3 Position<br />

e Vec<strong>to</strong>r3 Rotation), con l’aggi<strong>un</strong>ta <strong>di</strong> altri due nuovi sot<strong>to</strong>-componenti:<br />

Un Vec<strong>to</strong>r3 NextPosition ed <strong>un</strong> String NextTimeStamp. Il primo (NextPosition)<br />

in<strong>di</strong>ca la posizione dell’ogget<strong>to</strong> 3D attesa per l’istante <strong>di</strong> tempo espresso<br />

dal secondo (NextTimeStamp).<br />

La nuova istanza del componente <strong>di</strong> tipo Bullet viene creata all’interno del<br />

contes<strong>to</strong> logico <strong>di</strong> A, attraverso il <strong>su</strong>o Fac<strong>to</strong>ry e deposita<strong>to</strong> nel proprio Data<br />

Layer.<br />

In ques<strong>to</strong> momen<strong>to</strong> i Data Layer <strong>di</strong> A e B sono desincronizzati, dal momen<strong>to</strong><br />

che l’istanza del componente Bullet è presente solo nel Data Layer <strong>di</strong> A.<br />

Quando avviene <strong>un</strong>a creazione <strong>di</strong>retta <strong>di</strong> ques<strong>to</strong> tipo, il modulo SharedComponents<br />

notifica ai Layer in ascol<strong>to</strong> (il Layer Logic, ad esempio) l’avvenuta<br />

creazione del nuovo componente.


38 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Il Layer Logic quin<strong>di</strong> esegue <strong>un</strong> BroadCast esteso a tutti i <strong>Peer</strong> conosciuti<br />

inviando il comando CreateComponent appositamente parametrizza<strong>to</strong> per la<br />

descrizione del componente Bullet.<br />

Ogni comando <strong>di</strong> ques<strong>to</strong> Layer viene marca<strong>to</strong> con l’attuale TimeStamp<br />

espos<strong>to</strong> dal sot<strong>to</strong>-modulo Time del Layer P2P.<br />

In ques<strong>to</strong> modo si possono implementare controlli basati <strong>su</strong>l tempo: quando<br />

<strong>un</strong> comando gesti<strong>to</strong> dal Layer Logic viene ricevu<strong>to</strong> da <strong>un</strong> Nodo, ques<strong>to</strong> viene<br />

inseri<strong>to</strong> in <strong>un</strong>a lista <strong>di</strong> esecuzione, ed esegui<strong>to</strong> solo all’iterazione <strong>su</strong>ccessiva, o,<br />

nel caso <strong>di</strong> coman<strong>di</strong> esplicitamente temporizzati, solo quando il TimeStamp<br />

del <strong>Peer</strong> destinatario sarà maggiore o uguale a quello presente all’interno del<br />

comando stesso (opport<strong>un</strong>amente converti<strong>to</strong> in modo au<strong>to</strong>matico dal sot<strong>to</strong>modulo<br />

Time del Layer P2P).<br />

Ques<strong>to</strong> tipo <strong>di</strong> controlli viene effettua<strong>to</strong> in <strong>un</strong> sot<strong>to</strong>-modulo compos<strong>to</strong> da<br />

<strong>un</strong>a serie <strong>di</strong> Filtri che intervengono tra la ricezione del comando e la <strong>su</strong>a<br />

esecuzione. Uno <strong>di</strong> questi filtri controlla l’Obsolescence dei coman<strong>di</strong> UpdateComponent:<br />

Può capitare infatti <strong>di</strong> ricevere due messaggi UpdateComponent <strong>di</strong> <strong>un</strong>o stesso<br />

componente riportanti valori <strong>di</strong>fferenti. In ques<strong>to</strong> caso viene confronta<strong>to</strong><br />

il TimeStamp che accompagna entrambi i messaggi, ed elimina<strong>to</strong> l’Update-<br />

Component temporalmente più vecchio.<br />

Escludendo situazioni <strong>di</strong> estrema congestione, si tratta com<strong>un</strong>que <strong>di</strong> <strong>un</strong>’evenienza<br />

abbastanza rara, in quan<strong>to</strong> due UpdateComponent <strong>di</strong> <strong>un</strong>o stesso<br />

componente possono essere inviati solo dal medesimo <strong>Peer</strong>, e quest’ultimo tipicamente<br />

effettua aggiornamenti <strong>di</strong> componente con <strong>un</strong>a frequenza più bassa<br />

rispet<strong>to</strong> a quella <strong>di</strong> esecuzione.<br />

Ques<strong>to</strong> Layer inoltre mette a <strong>di</strong>sposizione <strong>un</strong>’interfaccia che permette <strong>di</strong><br />

inviare messaggi sia ai propri componenti che a quelli appartenenti agli altri<br />

<strong>Peer</strong>, utilizzando il sistema <strong>di</strong> Messaging del modulo SharedComponents.


2.6. LAYER VIEW 39<br />

2.6 Layer View<br />

A causa <strong>di</strong> alc<strong>un</strong>e scelte implementative, esposte nel prossimo capi<strong>to</strong>lo,<br />

il Layer View si presenta come <strong>un</strong> insieme <strong>di</strong> moduli che gestiscono i <strong>di</strong>versi<br />

aspetti <strong>di</strong> gioco non ancora affrontati nei Layer sot<strong>to</strong>stanti.<br />

Qui risiede il sot<strong>to</strong>-modulo Renderer, fondamentale per la rappresentazione<br />

e vi<strong>su</strong>alizzazione dello sta<strong>to</strong> <strong>di</strong> gioco; ma vi si possono anche trovare<br />

sot<strong>to</strong>-moduli non prettamente de<strong>di</strong>cati all’aspet<strong>to</strong> visivo: il modulo Au<strong>di</strong>o,<br />

il modulo che gestisce l’Input utente, il modulo che gestisce i movimenti, le<br />

animazioni, la fisica e le collisioni.<br />

Si tratta <strong>di</strong> <strong>un</strong>o stra<strong>to</strong> piut<strong>to</strong>s<strong>to</strong> eterogeneo, quin<strong>di</strong>, che deve il <strong>su</strong>o nome più<br />

alle similitu<strong>di</strong>ni con il Layer View del pattern MVC, che alla <strong>su</strong>a f<strong>un</strong>zione<br />

vera e propria.<br />

Così come il Layer Logic introduceva il concet<strong>to</strong> <strong>di</strong> “Contes<strong>to</strong> logico”, ques<strong>to</strong><br />

Layer introduce il concet<strong>to</strong> <strong>di</strong> “Contes<strong>to</strong> vi<strong>su</strong>ale” concretizza<strong>to</strong> in quello che,<br />

nell’architettura <strong>di</strong> <strong>un</strong> <strong>Game</strong> Engine, viene com<strong>un</strong>emente chiama<strong>to</strong> Scene-<br />

Graph.<br />

Con SceneGraph si intende quella struttura dati che contiene i riferimenti a<br />

tutti gli elementi grafici presenti nell’ambiente <strong>di</strong> gioco (Scene).<br />

Può anche essere implementata come Array o Plain List, ma tipicamente viene<br />

realizzata me<strong>di</strong>ante <strong>un</strong>a struttura ad albero, dal momen<strong>to</strong> che, quest’ultima,<br />

<strong>to</strong>rna particolarmente comoda per la propagazione delle trasformazioni<br />

geometriche per tutti quegli elementi grafici che in qualche modo sono legati<br />

tra loro da <strong>un</strong>a precisa gerarchia.<br />

Ques<strong>to</strong> tipo <strong>di</strong> struttura, inoltre, è perfetta per au<strong>to</strong>matizzare il processo<br />

<strong>di</strong> sincronizzazione tra il DataLayer, espos<strong>to</strong> dal Layer Logic, ed il Layer<br />

View.<br />

Tale processo “legge” il contenu<strong>to</strong> del Data Layer e ci costruisce sopra la<br />

scena 3D a seconda dei componenti presenti in esso.<br />

Chiaramente non tutti i componenti si possono convertire au<strong>to</strong>maticamente<br />

in oggetti grafici. Un componente <strong>di</strong> tipo Int, ad esempio, non può


40 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

essere converti<strong>to</strong> <strong>di</strong>rettamente, dal momen<strong>to</strong> che si tratta <strong>di</strong> <strong>un</strong> tipo <strong>di</strong> variabile<br />

troppo generico, e non è possibile quin<strong>di</strong> accostarlo sempre ad <strong>un</strong> <strong>un</strong>ico<br />

tipo <strong>di</strong> elemen<strong>to</strong> grafico: in <strong>un</strong> FPS, sia il valore dell’HP 13 che il numero <strong>di</strong><br />

m<strong>un</strong>izioni <strong>di</strong>sponibili sono rappresentati nel Data Layer attraverso componenti<br />

<strong>di</strong> tipo Int, ma a livello grafico possono essere vi<strong>su</strong>alizzati in maniera<br />

del tut<strong>to</strong> <strong>di</strong>fferente tra loro.<br />

Quin<strong>di</strong>, per ques<strong>to</strong> tipo <strong>di</strong> componenti, è necessario creare manualmente gli<br />

elementi vi<strong>su</strong>ali ed implementare <strong>un</strong>a logica <strong>di</strong> sincronizzazione con il rispettivo<br />

componente del Data Layer (<strong>di</strong> soli<strong>to</strong> me<strong>di</strong>ante sistemi che utilizzano<br />

l’Observer Pattern).<br />

Esis<strong>to</strong>no però alc<strong>un</strong>i componenti che possono essere inseriti in <strong>un</strong> logica<br />

<strong>di</strong> au<strong>to</strong>mazione <strong>di</strong> tale processo. È il caso dei componenti <strong>di</strong> tipo Object3D<br />

e dei <strong>su</strong>oi derivati.<br />

Un componente <strong>di</strong> tipo Object3D verrà trasforma<strong>to</strong> in <strong>un</strong> ogget<strong>to</strong> grafico<br />

<strong>di</strong> tipo Object3D. Allo stesso modo <strong>un</strong> componente <strong>di</strong> tipo Bullet (si veda<br />

esempi precedenti) verrà trasforma<strong>to</strong> in <strong>un</strong> ogget<strong>to</strong> grafico <strong>di</strong> tipo Bullet.<br />

In generale ogni componente tagga<strong>to</strong>, a livello <strong>di</strong> definizione <strong>di</strong> classe, con<br />

il tag “View”, quando esiste <strong>un</strong>a corrispondenza 1-a-1 tra componente Data<br />

Layer e classe View, soggiace a ques<strong>to</strong> tipo <strong>di</strong> au<strong>to</strong>matismo: basterà infatti<br />

creare <strong>un</strong> componente logico per vederlo apparire <strong>su</strong> schermo all’iterazione<br />

<strong>su</strong>ccessiva (Figura 2.15).<br />

Il Layer View non si limita solo a rappresentare il contenu<strong>to</strong> del Layer<br />

Logic e del Data Layer, operando quin<strong>di</strong> in sola lettura, ma, anzi, è da qui<br />

che tipicamente vengono lanciate le operazioni <strong>di</strong> scrittura e aggiornamen<strong>to</strong><br />

dei componenti logici:<br />

Ad ogni elemen<strong>to</strong> grafico genera<strong>to</strong> au<strong>to</strong>maticamente dal contes<strong>to</strong> vi<strong>su</strong>ale, viene<br />

“applicata” <strong>un</strong>’istanza <strong>di</strong> <strong>un</strong>a classe, estesa da “ComponentScript” che ne<br />

definisce il comportamen<strong>to</strong>.<br />

13 Health Point, p<strong>un</strong>ti vita / p<strong>un</strong>ti ferita. Unità <strong>di</strong> mi<strong>su</strong>ra che rappresenta lo sta<strong>to</strong> <strong>di</strong><br />

salute o il danno <strong>su</strong>bi<strong>to</strong> dal protagonista in molte tipologie <strong>di</strong> gioco


2.6. LAYER VIEW 41<br />

Figura 2.15: Il contes<strong>to</strong> vi<strong>su</strong>ale istanzia au<strong>to</strong>maticamente elementi grafici in<br />

relazione ai componenti presenti nel Data Layer


42 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

“ComponentScript” è <strong>un</strong>a classe base per l’implementazione della logica e<br />

delle <strong>di</strong>namiche <strong>di</strong> aggiornamen<strong>to</strong> dei componenti; a <strong>su</strong>a volta ere<strong>di</strong>ta dalla<br />

classe Behavior, e permette <strong>di</strong> definire le classiche fasi <strong>di</strong> “Inizializzazione”,<br />

“Aggiornamen<strong>to</strong>” e “Distruzione”. La <strong>su</strong>a peculiarità è quella <strong>di</strong> consentire<br />

<strong>un</strong>a separazione formale <strong>di</strong> quelle quelle che sono le azioni e gli aggiornamenti<br />

da eseguire in ogni singola fase a seconda che si tratti <strong>di</strong> <strong>un</strong> componente<br />

appartenente al proprio <strong>Peer</strong> o meno.<br />

Ad ogni “ComponentScript” viene associa<strong>to</strong> il GlobalID del componente <strong>di</strong><br />

cui si vuole definirne la logica <strong>di</strong> aggiornamen<strong>to</strong>.<br />

Ad esempio, Il componente logico <strong>di</strong> tipo “Character” (esteso da “Object3D”)<br />

identifica lo sta<strong>to</strong> del personaggio comanda<strong>to</strong> dal gioca<strong>to</strong>re. Ques<strong>to</strong><br />

viene tradot<strong>to</strong> au<strong>to</strong>maticamente nel rispettivo elemen<strong>to</strong> grafico, ma le<br />

politiche <strong>di</strong> aggiornamen<strong>to</strong> e sincronizzazione vengono definite dalla classe<br />

“CharacterScript”, estesa app<strong>un</strong><strong>to</strong> da “ComponentScript”.<br />

Qui, a seconda della proprietà del componente, CharacterScript esegue due<br />

me<strong>to</strong><strong>di</strong> <strong>di</strong>stinti. Per la fase <strong>di</strong> Update, ad esempio, il <strong>Peer</strong> “Owner” eseguirà<br />

il me<strong>to</strong>do “Update Writer”, mentre tutti gli altri eseguiranno il me<strong>to</strong>do “Update<br />

Reader”.<br />

Siano <strong>Peer</strong> “A” e <strong>Peer</strong> “B” due <strong>Peer</strong> connessi e sincronizzati a livello <strong>di</strong><br />

Data Layer, e sia il componente “A 12 ” <strong>di</strong> tipo “Character” il componente<br />

che identifica lo sta<strong>to</strong> relativo al personaggio controlla<strong>to</strong> dal Player “A”, il<br />

“ComponentScript” applica<strong>to</strong> alla relativa istanza grafica si dovrà comportare<br />

in modo <strong>di</strong>fferente nel contes<strong>to</strong> View dei due <strong>Peer</strong>.<br />

Su <strong>Peer</strong> “A”, infatti, dovrà aggiornare le coor<strong>di</strong>nate dell’ogget<strong>to</strong> 3D a seconda<br />

degli input del gioca<strong>to</strong>re (ad esempio, <strong>su</strong> pressione dei tasti <strong>di</strong>rezionali, o<br />

W-A-S-D, verrà mosso l’ogget<strong>to</strong>), e, a intervalli <strong>di</strong> tempo prefissati, scrivere<br />

le <strong>su</strong>e attuali coor<strong>di</strong>nate all’interno del rispettivo componente logico.<br />

Su <strong>Peer</strong> “B”, invece, dovrà leggere il valore delle coor<strong>di</strong>nate valorizzate nel rispettivo<br />

componente logico, ed interpolarle con le coor<strong>di</strong>nate dell’ogget<strong>to</strong>3D<br />

del contes<strong>to</strong> View (Figura 2.16).


2.7. ESEMPI PRATICI 43<br />

Figura 2.16: Il contes<strong>to</strong> vi<strong>su</strong>ale istanzia au<strong>to</strong>maticamente elementi grafici in<br />

relazione ai componenti presenti nel Data Layer<br />

L’aggiornamen<strong>to</strong> delle coor<strong>di</strong>nate del componente <strong>di</strong> tipo “Character”<br />

può essere effettua<strong>to</strong> in <strong>di</strong>versi mo<strong>di</strong>. Come evidenzia<strong>to</strong> nel capi<strong>to</strong>lo relativo<br />

al modulo SharedComponents, è possibile mo<strong>di</strong>ficare l’intero componente<br />

compos<strong>to</strong>, alc<strong>un</strong>i <strong>su</strong>oi sot<strong>to</strong>-componenti, o ad<strong>di</strong>rittura ogni singolo componente<br />

“leaf”: ad esempio, se il Character grafico si muove l<strong>un</strong>go la sola asse<br />

X, invece <strong>di</strong> aggiornare l’intero componente, conviene aggiornare il singolo<br />

componente “X” appartenente al <strong>su</strong>o sot<strong>to</strong>-componente “Position”.<br />

Allo stesso modo, se il Character grafico si muove senza ruotare, conviene<br />

aggiornare solo “Position” piut<strong>to</strong>s<strong>to</strong> che l’intero componente relativo al<br />

Character.<br />

2.7 Esempi pratici<br />

Al fine <strong>di</strong> completare la <strong>di</strong>ssertazione <strong>su</strong>ll’architettura software implementata,<br />

<strong>di</strong> segui<strong>to</strong> verranno proposti <strong>un</strong>a serie <strong>di</strong> casi che affrontano i problemi<br />

più com<strong>un</strong>i che ne derivano, e la relativa la soluzione adottata prendendo in<br />

esame ogni singolo Layer.


44 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

2.7.1 Movimen<strong>to</strong> <strong>di</strong> oggetti<br />

Il movimen<strong>to</strong> <strong>di</strong> elementi grafici in f<strong>un</strong>zione <strong>di</strong> <strong>un</strong> input utente è <strong>un</strong>o degli<br />

aspetti che contrad<strong>di</strong>stingue le applicazioni multime<strong>di</strong>ali interattive e, nella<br />

fattispecie, i videogiochi.<br />

Per ques<strong>to</strong> motivo è nata l’esigenza <strong>di</strong> estendere il componente “Object3D”,<br />

che <strong>di</strong> fat<strong>to</strong> è <strong>su</strong>fficiente per modellare le informazioni che caratterizzano<br />

oggetti 3D “statici”, in <strong>un</strong> apposi<strong>to</strong> componente “MovingObject3D” che consentisse<br />

la descrizione <strong>di</strong> <strong>un</strong> ogget<strong>to</strong> in movimen<strong>to</strong>.<br />

Ques<strong>to</strong> componente, come precedentemente illustra<strong>to</strong> nella sezione 2.5,<br />

è compos<strong>to</strong> dagli stessi sot<strong>to</strong>-componenti <strong>di</strong> “Object3D”, ma introduce due<br />

nuovi sot<strong>to</strong>-componenti: <strong>un</strong> componente <strong>di</strong> tipo Vec<strong>to</strong>r3 con LocalID “Next-<br />

Position” ed <strong>un</strong> componente <strong>di</strong> tipo String con LocalID “NextTimeStamp”.<br />

Il primo in<strong>di</strong>ca la posizione che as<strong>su</strong>merà l’ogget<strong>to</strong> all’istante <strong>di</strong> tempo in<strong>di</strong>ca<strong>to</strong><br />

dal secondo.<br />

E’ importante sot<strong>to</strong>lineare come, nel Layer View e nel Layer Logic (e Data<br />

Layer), le coor<strong>di</strong>nate della posizione <strong>di</strong> <strong>un</strong> ogget<strong>to</strong> in movimen<strong>to</strong> vengano<br />

campionate utilizzando intervalli <strong>di</strong> tempo <strong>di</strong>fferenti: nel Layer View si deve<br />

garantire l’illusione <strong>di</strong> movimen<strong>to</strong> “continuo”, e ques<strong>to</strong> avviene aggiornando<br />

ad ogni iterazione le coor<strong>di</strong>nate secondo <strong>un</strong> vet<strong>to</strong>re <strong>di</strong> “offset” calcola<strong>to</strong> in<br />

f<strong>un</strong>zione della velocità e del tempo trascorso tra il “frame” attuale e quello<br />

precedente. In quei casi in cui la velocità <strong>di</strong> movimen<strong>to</strong> è talmente alta da<br />

non consentire l’illusione <strong>di</strong> movimen<strong>to</strong>, spesso si interviene con effetti “Post<br />

Processing” quali l’“Onion Skinning” ed il “Motion Blur”.<br />

Nel Layer Logic invece la frequenza <strong>di</strong> aggiornamen<strong>to</strong> delle coor<strong>di</strong>nate<br />

può essere notevolmente più bassa, poiché le informazioni presenti nel Data<br />

Layer devono essere le minime in<strong>di</strong>spensabili a garantire la corretta interpretazione<br />

dello sta<strong>to</strong> <strong>di</strong> gioco <strong>su</strong> ogni <strong>Peer</strong>, astraendo, da <strong>un</strong>a parte, da quelle<br />

informazioni grafiche e decorative che non apportano cambiamenti sostanziali<br />

allo sta<strong>to</strong> <strong>di</strong> gioco, cercando, laddove possibile, <strong>di</strong> mantenere <strong>un</strong>a bassa


2.7. ESEMPI PRATICI 45<br />

frequenza <strong>di</strong> aggiornamen<strong>to</strong> (cioè intervalli <strong>di</strong> campionamen<strong>to</strong> relativamente<br />

l<strong>un</strong>ghi) dal momen<strong>to</strong> che questi devono essere ogni volta propagati <strong>su</strong> tutta<br />

la rete <strong>Peer</strong>-To-<strong>Peer</strong>, e dall’altra, da quelle informazioni che in qualche modo<br />

possono essere ricavate me<strong>di</strong>ante inferenza <strong>su</strong>lle informazioni presenti nel<br />

proprio Data Layer.<br />

Qui entrano in gioco sistemi <strong>di</strong> “pre<strong>di</strong>ction” e <strong>di</strong> interpolazione della posizione:<br />

il primo viene com<strong>un</strong>emente realizza<strong>to</strong> me<strong>di</strong>ante “Dead Reckoning”,<br />

cioè <strong>un</strong> algoritmo grazie al quale, utilizzando informazioni quali velocità e<br />

accelerazione, è possibile stimare la posizione che as<strong>su</strong>merà l’ogget<strong>to</strong> preso in<br />

esame al prossimo istante <strong>di</strong> tempo, conoscendo la posizione attuale o, ancora,<br />

stimare la posizione attuale conoscendo quella relativa all’istante <strong>di</strong> tempo<br />

precedente. Inversamente, è possibile ricavare la velocità <strong>di</strong> spostamen<strong>to</strong> (e<br />

quin<strong>di</strong> ogni singolo step da applicare la<strong>to</strong> View) se si è a conoscenza della<br />

posizione attuale e della posizione prevista ad <strong>un</strong> preciso prossimo istante <strong>di</strong><br />

tempo.<br />

Se si hanno a <strong>di</strong>sposizione questi dati è possibile applicarvi <strong>un</strong>’interpolazione<br />

in modo da ricavare gli step interme<strong>di</strong> tra la posizione all’istante <strong>di</strong><br />

tempo “Tn” e la posizione all’istante <strong>di</strong> tempo “Tn+1 ”. Questi step saranno<br />

più o meno ampi a seconda della velocità <strong>di</strong> spostamen<strong>to</strong> e dei millisecon<strong>di</strong><br />

trascorsi tra l’iterazione attuale e quella precedente.<br />

Le interpolazioni che vengono com<strong>un</strong>emente applicate sono l’interpolazione<br />

lineare e l’interpolazione spline. Per la prima sono <strong>su</strong>fficienti le informazioni<br />

che abbiamo deciso <strong>di</strong> includere nel componente MovingObject3D, anche se<br />

il ri<strong>su</strong>lta<strong>to</strong> non sempre sarà esteticamente apprezzabile , dal momen<strong>to</strong> che<br />

all’interno dello stesso intervallo il movimen<strong>to</strong> ri<strong>su</strong>lterà fluido, ma tra <strong>un</strong> intervallo<br />

e l’altro possono palesarsi repentini cambi <strong>di</strong> <strong>di</strong>rezione.<br />

Il secondo invece riduce ques<strong>to</strong> problema, ma necessita <strong>di</strong> maggiori informazioni<br />

(più p<strong>un</strong>ti interpolanti) e, in particolari tipi <strong>di</strong> movimen<strong>to</strong>, può presentare<br />

forti oscillazioni (fenomeno <strong>di</strong> Gibbs), <strong>di</strong>scostandosi quin<strong>di</strong> da quello<br />

che era il movimen<strong>to</strong> originale. Nel proget<strong>to</strong> <strong>di</strong> tesi si è scel<strong>to</strong> <strong>di</strong> utilizzare


46 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

l’interpolazione lineare.<br />

Per ridurre ulteriormente artefatti <strong>di</strong> ques<strong>to</strong> tipo, tale processo va esteso anche<br />

alla rotazione, utilizzando algoritmi interpolanti stu<strong>di</strong>ati appositamente<br />

per le rotazioni, come l’interpolazione sferica.<br />

Grazie al “Dead Reckoning”, quin<strong>di</strong>, si riduce la richiesta <strong>di</strong> banda per la<br />

notifica dei movimenti, ma contemporaneamente, dal momen<strong>to</strong> l’interpolazione<br />

viene effettuata dal Layer View <strong>di</strong> ogni singolo <strong>Peer</strong> in modo in<strong>di</strong>pendente,<br />

non viene garantita la consistenza dello sta<strong>to</strong> <strong>di</strong> gioco durante l’intera azione<br />

<strong>di</strong> movimen<strong>to</strong>, salvo la sincronizzazione apportata implicitamente dalla notifica<br />

dei singoli intervalli <strong>di</strong> tempo.<br />

Sorgono però i seguenti problemi:<br />

Quando <strong>un</strong> <strong>Peer</strong> “A” effettua il movimen<strong>to</strong> <strong>di</strong> <strong>un</strong> ogget<strong>to</strong> <strong>di</strong> <strong>su</strong>a appartenenza,<br />

<strong>di</strong>rettamente a carico del Layer View, ed invia, a precisi intervalli <strong>di</strong><br />

tempo, l’aggiornamen<strong>to</strong> del relativo componente logico al <strong>Peer</strong> “B” a lui connesso,<br />

<strong>su</strong>bentra <strong>un</strong> problema causa<strong>to</strong> dall’eventuale “Lag” tra “A” e “B”.<br />

L’aggiornamen<strong>to</strong> dello sta<strong>to</strong> del componente logico relativo all’ogget<strong>to</strong> in<br />

movimen<strong>to</strong>, arriverà a “B” dopo <strong>un</strong> cer<strong>to</strong> numero <strong>di</strong> millisecon<strong>di</strong> “N ”: significa<br />

che “B” inizierà il processo <strong>di</strong> movimen<strong>to</strong>, e quin<strong>di</strong> <strong>di</strong> interpolazione e<br />

“Dead Reckoning”, quando l’ogget<strong>to</strong> in “A” si è già sposta<strong>to</strong> <strong>di</strong> <strong>un</strong> vet<strong>to</strong>re<br />

pari alla velocità al millisecondo, moltiplicata per “N ”. Essendo com<strong>un</strong>e per<br />

entrambi il p<strong>un</strong><strong>to</strong> d’arrivo al medesimo istante <strong>di</strong> tempo, l’ogget<strong>to</strong> in “B”<br />

sarà costret<strong>to</strong> a muoversi più velocemente rispet<strong>to</strong> ad “A” per recuperare il<br />

ritardo accumula<strong>to</strong> con il Lag (Figura 2.17).<br />

Un altro problema frequente è caratterizza<strong>to</strong> da <strong>un</strong> fasti<strong>di</strong>oso effet<strong>to</strong> visivo<br />

che vede l’improvviso riposizionamen<strong>to</strong> dell’ogget<strong>to</strong> tra <strong>un</strong> istante <strong>di</strong><br />

aggiornamen<strong>to</strong> e quello <strong>su</strong>ccessivo, quando la posizione <strong>di</strong> destinazione prevista<br />

<strong>di</strong>fferisce da quella reale. Errori <strong>di</strong> arro<strong>to</strong>ndamen<strong>to</strong>, fat<strong>to</strong>ri non previsti<br />

(collisioni, attri<strong>to</strong>, etc) e desincronizzazioni temporali portano a ques<strong>to</strong> tipo<br />

<strong>di</strong> “Jumping” o <strong>di</strong> “Warping” (Figura 2.18 e Figura 2.19).<br />

Quando la <strong>di</strong>fferenza tra il p<strong>un</strong><strong>to</strong> <strong>di</strong> destinazione previs<strong>to</strong> e quello reale


2.7. ESEMPI PRATICI 47<br />

Figura 2.17: A T0 entrambi i <strong>Peer</strong> detengono <strong>un</strong>o sta<strong>to</strong> sincronizza<strong>to</strong>, e<br />

l’ogget<strong>to</strong> (sfera arancione) si trova alla medesima posizione.<br />

A T1 nel <strong>Peer</strong> A l’ogget<strong>to</strong> iniza a muoversi, ed invia la relativa notifica al<br />

<strong>Peer</strong> B.<br />

A T2 arriva la notifica al <strong>Peer</strong> B, che inizierà il proprio processo <strong>di</strong> movimen<strong>to</strong>.<br />

A T3 l’ogget<strong>to</strong> in A si trova più avanti rispet<strong>to</strong> alla controparte in B.<br />

A T4 l’ogget<strong>to</strong> in B deve muoversi più velocemente rispet<strong>to</strong> alla controparte<br />

in A, per compensare il ritardo.<br />

A T5 l’ogget<strong>to</strong> in A ha quasi raggi<strong>un</strong><strong>to</strong> il p<strong>un</strong><strong>to</strong> <strong>di</strong> destinazione.<br />

A T6, che coincide con l’istante <strong>di</strong> tempo previs<strong>to</strong> nella notifica <strong>di</strong> movimen<strong>to</strong>,<br />

entrambi gli oggetti sono gi<strong>un</strong>ti a destinazione.


48 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Figura 2.18: Ad ogni “istantanea” dello sta<strong>to</strong> dell’ogget<strong>to</strong> si presenta <strong>un</strong>a <strong>di</strong>fferenza<br />

<strong>di</strong> posizione (Jump) tra quella prevista come p<strong>un</strong><strong>to</strong> <strong>di</strong> destinazione<br />

nella istantanea precedente e quella riportata come p<strong>un</strong><strong>to</strong> <strong>di</strong> partenza nell’istantanea<br />

<strong>su</strong>ccessiva. Le frecce ver<strong>di</strong> in<strong>di</strong>cano la <strong>di</strong>rezione, le sfere arancioni<br />

solide in<strong>di</strong>cano il p<strong>un</strong><strong>to</strong> <strong>di</strong> partenza mentre quelle semitrasparenti in<strong>di</strong>cano<br />

il p<strong>un</strong><strong>to</strong> <strong>di</strong> destinazione. I p<strong>un</strong>ti blu rappresentano gli step effettuati<br />

dall’ogget<strong>to</strong> grafico vero e proprio.


2.7. ESEMPI PRATICI 49<br />

Figura 2.19: Una soluzione potrebbe essere quella <strong>di</strong> ignorare il p<strong>un</strong><strong>to</strong> <strong>di</strong> partenza<br />

dell’istantanea <strong>su</strong>ccessiva quando la <strong>di</strong>stanza tra ques<strong>to</strong> ed il p<strong>un</strong><strong>to</strong> <strong>di</strong><br />

destinazione dell’istantanea precedente è al <strong>di</strong> sot<strong>to</strong> <strong>di</strong> <strong>un</strong>a certa soglia. Dal<br />

momen<strong>to</strong> che l’ogget<strong>to</strong> è in movimen<strong>to</strong> e lo sarà anche nella prossima istantanea,<br />

si può evitare <strong>di</strong> riposizionarlo <strong>su</strong>l p<strong>un</strong><strong>to</strong> <strong>di</strong> partenza, che causerebbe<br />

antiestetici artefatti <strong>di</strong> Warping, lasciando continuare la <strong>su</strong>a corsa verso il<br />

prossimo p<strong>un</strong><strong>to</strong> <strong>di</strong> destinazione, calcolata rispet<strong>to</strong> la <strong>su</strong>a attuale posizione.


50 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

è troppo elevata, ri<strong>su</strong>lta <strong>di</strong>fficile compensare l’offset <strong>di</strong> spostamen<strong>to</strong>, e contemporaneamente<br />

garantire <strong>un</strong> movimen<strong>to</strong> naturale e continuo.<br />

Una soluzione è quella <strong>di</strong> intervenire <strong>su</strong>lla frequenza <strong>di</strong> sincronizzazione, eseguendo<br />

aggiornamenti <strong>su</strong>l DataLayer (quin<strong>di</strong> propagati au<strong>to</strong>maticamente <strong>su</strong><br />

tutti i <strong>Peer</strong> connessi) “eccezionali”, fuori cioè dalla logica <strong>di</strong> aggiornamen<strong>to</strong><br />

perio<strong>di</strong>co ad intervalli <strong>di</strong> tempo prefissati.<br />

Ques<strong>to</strong> genere <strong>di</strong> aggiornamenti “forzati” viene attua<strong>to</strong> in quelle situazioni<br />

critiche nelle quali la probabilità che il p<strong>un</strong><strong>to</strong> <strong>di</strong> destinazione previs<strong>to</strong><br />

nell’istantanea precedente sia <strong>di</strong>verso da quello che si va a prefigurare è mol<strong>to</strong><br />

elevata: cambi repentini <strong>di</strong> <strong>di</strong>rezione, cambiamenti <strong>di</strong> velocità, previsioni <strong>di</strong><br />

eventuali collisioni imminenti, o lo s<strong>to</strong>p improvviso dell’ogget<strong>to</strong> in questione,<br />

ricadono nella casistica delle situazioni critiche più com<strong>un</strong>i (Figura 2.20 e<br />

Figura 2.21).<br />

Figura 2.20: Anche se si evita <strong>di</strong> riposizionare l’ogget<strong>to</strong> in movimen<strong>to</strong> nella<br />

posizione <strong>di</strong> partenza proposta dall’istantanea <strong>di</strong> turno, quando la <strong>di</strong>fferenza<br />

è troppo elevata tra questa e quella <strong>di</strong> destinazione prevista nell’istantanea<br />

precedente, ri<strong>su</strong>lta <strong>di</strong>fficile mantenere il movimen<strong>to</strong> costante e continuo.


2.7. ESEMPI PRATICI 51<br />

Figura 2.21: Una soluzione può essere quella <strong>di</strong> broadcastare <strong>un</strong>a o più istantanee<br />

ausiliarie in quelle situazioni critiche nelle quali è mol<strong>to</strong> probabile che<br />

la destinazione prevista non sia più valida.<br />

Ques<strong>to</strong> tipo <strong>di</strong> soluzioni si basano però <strong>su</strong>ll’ass<strong>un</strong>zione che il l’ogget<strong>to</strong><br />

in questione sia in movimen<strong>to</strong> e rimanga tale: quando l’ogget<strong>to</strong> termina il<br />

proprio movimen<strong>to</strong>, passando dallo sta<strong>to</strong> “Moving” a quello <strong>di</strong> “S<strong>to</strong>pped”, il<br />

palesarsi <strong>di</strong> artefatti <strong>di</strong> minore entità è inevitabile, dal momen<strong>to</strong> che la posizione<br />

riportata in <strong>un</strong>’istantanea <strong>di</strong> <strong>un</strong> ogget<strong>to</strong> ormai fermo non può essere<br />

ignorata, poiché rappresenta l’attuale sta<strong>to</strong> dell’ogget<strong>to</strong> e ques<strong>to</strong> può anche<br />

non <strong>su</strong>bire più mo<strong>di</strong>fiche fino a fine partita: se non si riposizionasse l’ogget<strong>to</strong><br />

alle coor<strong>di</strong>nate specificate come p<strong>un</strong><strong>to</strong> <strong>di</strong> partenza, ques<strong>to</strong> rimarrebbe fermo<br />

in <strong>un</strong>a posizione che, visti i problemi sopra elencati, probabilmente <strong>di</strong>fferirebbe<br />

da quan<strong>to</strong> riporta<strong>to</strong> nel DataLayer del <strong>Peer</strong> “Owner”.<br />

Rias<strong>su</strong>mendo, da<strong>to</strong> <strong>un</strong> ogget<strong>to</strong> 3D non statico, ques<strong>to</strong> viene mosso nel<br />

contes<strong>to</strong> View dal <strong>su</strong>o <strong>Peer</strong> “Owner”; il relativo “ComponentScript” aggiornerà<br />

perio<strong>di</strong>camente il componente logico del Data Layer a cui è associa<strong>to</strong>.<br />

Di conseguenza i <strong>Peer</strong> “non Owner” appartenenti alla Membership riceveran-


52 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

no <strong>un</strong> aggiornamen<strong>to</strong> perio<strong>di</strong>co che mo<strong>di</strong>ficherà au<strong>to</strong>maticamente lo sta<strong>to</strong> dei<br />

componenti <strong>su</strong>i loro Data Layer. Ques<strong>to</strong> si ripercuoterà <strong>su</strong>i rispettivi Layer<br />

View, che, attraverso i “ComponentScript” associati ai rispettivi oggetti grafici,<br />

ne mo<strong>di</strong>ficheranno le coor<strong>di</strong>nate secondo <strong>un</strong>a politica <strong>di</strong> Dead Reckoning<br />

(Figura 2.22).<br />

2.7.2 Collisione tra oggetti<br />

La collisione tra elementi grafici è <strong>un</strong> altro aspet<strong>to</strong> caratteristico delle<br />

<strong>di</strong>namiche presenti nei videogiochi. Non solo, è anche <strong>un</strong>o degli aspetti più<br />

sensibili e influenti <strong>su</strong>l flusso <strong>di</strong> gioco, poiché questi possono rappresentare<br />

<strong>un</strong>a <strong>di</strong>scriminante tra la vit<strong>to</strong>ria e la sconfitta <strong>di</strong> <strong>un</strong>a partita.<br />

Ogni collisione è tipicamente composta da due fasi:“Detection” e “Response”.<br />

La prima fase si occupa <strong>di</strong> testare la presenza <strong>di</strong> eventuali collisioni tra i<br />

<strong>di</strong>versi oggetti che compongono la scena 3D, mentre la seconda si occupa <strong>di</strong><br />

calcolare la risposta, in termini <strong>di</strong> movimen<strong>to</strong> e rotazione, che tali oggetti<br />

devono compiere a segui<strong>to</strong> <strong>di</strong> <strong>un</strong>a collisione.<br />

La “Collision Detection” solitamente opera <strong>su</strong> <strong>un</strong>’approssimazione <strong>di</strong> quelli<br />

che sono i volumi occupati dalla geometria degli oggetti 3D, e solo raramente<br />

<strong>di</strong>rettamente <strong>su</strong>lla geometria poligonale dei singoli modelli.<br />

Tra le approssimazioni più com<strong>un</strong>i vi sono le collisioni “Sphere-Sphere”,“Sphere-<br />

Box” e “Box-Box”.<br />

La “Sphere-Sphere” è tendenzialmente la meno precisa ma anche la più semplice<br />

da realizzare e computazionalmente meno cos<strong>to</strong>sa. È implementata me<strong>di</strong>ante<br />

<strong>un</strong> test <strong>su</strong>lla <strong>di</strong>stanza tri<strong>di</strong>mensionale tra i due oggetti (Figura 2.23).<br />

“Sphere-Box”, invece, prevede <strong>un</strong> test <strong>di</strong> intersezione tra <strong>un</strong>a sfera ed <strong>un</strong><br />

“Bo<strong>un</strong><strong>di</strong>ngBox”, cioè <strong>un</strong>’approssimazione del volume del modello tri<strong>di</strong>mensionale<br />

in <strong>un</strong> parallelepipedo, calcola<strong>to</strong> in base ai vertici estremi del modello<br />

stesso per ogni asse. Se il test viene esegui<strong>to</strong> <strong>su</strong> <strong>un</strong> “Axis-Aligned Bo<strong>un</strong><strong>di</strong>ng<br />

Box” (AABB, ovvero <strong>un</strong> Bo<strong>un</strong><strong>di</strong>ngBox non orienta<strong>to</strong>) continua ad essere poco<br />

cos<strong>to</strong>so e <strong>di</strong> semplice implementazione (Figura 2.24).


2.7. ESEMPI PRATICI 53<br />

Figura 2.22: T0: Il Player A, l’“Owner” sposta l’ogget<strong>to</strong> <strong>di</strong>rettamente a livello<br />

View, e tramite il relativo ComponentScript stima la prossima posizione.<br />

Di conseguenza aggiorna il rispettivo componente <strong>di</strong> tipo “MovingObject3D”<br />

T1: Au<strong>to</strong>maticamente viene propaga<strong>to</strong> l’aggiornamen<strong>to</strong> al Player B.<br />

T2: Il ComponentScript in B applica il Dead Reckoning <strong>su</strong>l valore riporta<strong>to</strong><br />

nel componente appena aggiorna<strong>to</strong>.


54 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

La “Box-Box” invece testa l’intersezione tra due “Bo<strong>un</strong><strong>di</strong>ngBox” (Figura 2.25).<br />

Figura 2.23: Sphere-Sphere<br />

Figura 2.24: Sphere-Box<br />

Esis<strong>to</strong>no inoltre altri tipi <strong>di</strong> approssimazione che introducono nuovi volumi<br />

geometrici come il “Cylinder” (anch’esso poco cos<strong>to</strong>so), o <strong>un</strong>a composizione<br />

<strong>di</strong> tali (Con due “Sphere” ed <strong>un</strong> “Cylinder” sia ha <strong>un</strong>a “Cap<strong>su</strong>le”, particolarmente<br />

in<strong>di</strong>cata per la rappresentazione <strong>di</strong> oggetti antropomorfi).<br />

La “Collision Response” viene eseguita utilizzando i dati ricavati nel processo<br />

<strong>di</strong> “Collision Detection”: oltre ad informazioni geometriche <strong>di</strong> base,<br />

come le coor<strong>di</strong>nate del p<strong>un</strong><strong>to</strong> <strong>di</strong> intersezione, la <strong>su</strong>rface od il poligono colpi<strong>to</strong><br />

ed il <strong>su</strong>o vet<strong>to</strong>re normale, possono essere utilizzate informazioni aggi<strong>un</strong>tive


2.7. ESEMPI PRATICI 55<br />

Figura 2.25: Box-Box<br />

utilizzate dall’Engine fisico, come il tipo <strong>di</strong> materiale colpi<strong>to</strong>, la “Bo<strong>un</strong>ciness”,<br />

la <strong>su</strong>a “Densità’ e la massa degli oggetti coinvolti nella collisione.<br />

Ci sono poi <strong>un</strong>a serie <strong>di</strong> ottimizzazioni che operano <strong>su</strong>i dati presenti nello<br />

“SceneGraph”, atte ad evitare che vengano eseguiti test <strong>di</strong> “Collision Detection”<br />

inutilmente e tra tutti gli oggetti, anche quando la <strong>di</strong>stanza tra questi è<br />

notevole: spesso infatti viene esegui<strong>to</strong> <strong>un</strong> test mol<strong>to</strong> approssima<strong>to</strong> me<strong>di</strong>ante<br />

<strong>un</strong> “Sphere-Sphere” massimizza<strong>to</strong>, che “filtra” e raggruppa quegli oggetti che<br />

si trovano in prossimità reciproca, applicando quin<strong>di</strong> “Collision Detections”<br />

più precise solo a quest’ultimi.<br />

Nel caso <strong>di</strong> gran<strong>di</strong> spazi, inoltre, si tende a razionalizzare preventivamente la<br />

scena <strong>di</strong> gioco in strutture apposite come il “QuadTree”, che partizionano lo<br />

spazio in quadranti ricorsivi.<br />

Dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista implementativo, entrambe le fasi verranno gestite dall’“Engine<br />

fisico” presente nel Layer View. Ciò significa che, così come avviene per il<br />

movimen<strong>to</strong>, chi controlla ed eventualmente mo<strong>di</strong>fica la posizione dei singoli<br />

oggetti 3D risidede nel Layer View dei loro rispettivi <strong>Peer</strong> “Owner”.<br />

Siano due oggetti tri<strong>di</strong>mensionali, “Ogget<strong>to</strong> A” ed “Ogget<strong>to</strong> B” in collisione,<br />

appartenenti rispettivamente al <strong>Peer</strong> “A” e al <strong>Peer</strong> “B”, la “Collision<br />

Detection” verrà eseguita allo stesso modo in entrambi i <strong>Peer</strong>, ma il “Colli-


56 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

sion Response” <strong>su</strong> “Ogget<strong>to</strong> A” verrà gesti<strong>to</strong> esclusivamente dal <strong>Peer</strong> “A”,<br />

e, viceversa il “Collision Response” <strong>su</strong> “Ogget<strong>to</strong> B” verrà gesti<strong>to</strong> esclusivamente<br />

dal <strong>Peer</strong> “B”. Gli effetti delle “Collision Responses” <strong>su</strong>i componenti<br />

logici coinvolti, verranno poi imme<strong>di</strong>atamente inoltrati agli altri <strong>Peer</strong>, che<br />

sposteranno infine i rispettivi oggetti View <strong>di</strong> conseguenza.<br />

Esis<strong>to</strong>no però contesti nei quali la “Collision Response” non in<strong>di</strong>vidua<br />

<strong>un</strong>a risposta “fisica”, cioè trasformazioni <strong>di</strong> ro<strong>to</strong>traslazioneil il cui aggiornamen<strong>to</strong><br />

è a carico <strong>di</strong> MovingObjectScript, bensì in<strong>di</strong>vidua variazioni logiche<br />

che impattano <strong>su</strong>lle <strong>di</strong>namiche <strong>di</strong> gioco e <strong>su</strong>l valore <strong>di</strong> specifici componenti<br />

del Data Layer. Si pensi ad esempio alla collisione tra <strong>un</strong> Bullet ed <strong>un</strong> Character,<br />

o ancora tra <strong>un</strong> Character ed <strong>un</strong> “HealthPack”. Nel primo caso il<br />

Bullet non deve <strong>su</strong>bire <strong>un</strong>a risposta fisica, rimbalzare o deviare traiet<strong>to</strong>ria,<br />

ma <strong>di</strong>struggersi e decrementare i P<strong>un</strong>ti vita del Character colpi<strong>to</strong>; viceversa,<br />

nel secondo caso invece l’“HealthPack” deve <strong>di</strong>struggersi e incrementare<br />

i P<strong>un</strong>ti vita del Character colpi<strong>to</strong>.<br />

In entrambi i casi viene utilizza<strong>to</strong> il sistema <strong>di</strong> Messaging per la notifica<br />

della collisione: Poiché il componente che rappresenta i P<strong>un</strong>ti vita <strong>di</strong> <strong>un</strong><br />

Character può essere mo<strong>di</strong>fica<strong>to</strong> esclusivamente dal proprio Player “Owner”,<br />

mentre il Bullet (o l’HealthPack) tipicamente appartengono ad <strong>un</strong> Player <strong>di</strong>fferente,<br />

e dal momen<strong>to</strong> che si è scel<strong>to</strong> <strong>di</strong> gestire il “Collision Detection” tra<br />

oggetti <strong>di</strong> tipo Bullet e Characater solo all’interno ComponentScript associa<strong>to</strong><br />

agli oggetti del primo tipo, quest’ultimo deve “informare” dell’avvenuta<br />

collisione il Characater coinvol<strong>to</strong>, che, <strong>di</strong> conseguenza decrementerà il proprio<br />

sot<strong>to</strong>-componente de<strong>di</strong>ca<strong>to</strong> ai P<strong>un</strong>ti vita (Figura 2.27).<br />

Analogamente al movimen<strong>to</strong>, anche per quan<strong>to</strong> riguarda le collisioni esis<strong>to</strong>no<br />

dei problemi dovuti al Lag, arro<strong>to</strong>ndamenti dei valori interpolanti e<br />

alla frequenza <strong>di</strong> aggiornamen<strong>to</strong> dell’Engine fisico (Tick). Anzi, in qualche<br />

modo, quest’ultimi vengono proprio amplificati dall’instabilità degli algoritmi<br />

<strong>di</strong> interpolazione utilizzati nel processo <strong>di</strong> movimen<strong>to</strong>, e alla loro, seppur<br />

minima, <strong>di</strong>fferenza tra <strong>Peer</strong> e <strong>Peer</strong>.


2.7. ESEMPI PRATICI 57<br />

Figura 2.26: In T0 il Player A sposta il <strong>su</strong>o personaggio in <strong>di</strong>rezione del<br />

personaggio appartenente al Player B, e, viceversa, il Player B muove il <strong>su</strong>o<br />

personaggio verso il personaggio del Player A.<br />

In T1 Viene attutata la sincronizzazione del DataLayer, e <strong>di</strong> conseguenza<br />

ogn<strong>un</strong>o dei due Player, eseguirà, nel proprio LayerView, me<strong>di</strong>ante Dead Reckoning,<br />

il movimen<strong>to</strong> del personaggio appartenente all’altro <strong>Peer</strong>. Entrambi<br />

gli Engine fisici rileveranno <strong>un</strong>a collisione e, in T2, come risposta muoveranno<br />

i rispettivi personaggi nel verso oppos<strong>to</strong>.


58 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Figura 2.27: Il Layer View del Player A rileva <strong>un</strong>a collisione tra il proprio<br />

Bullet ed il Character appartenente al Player B. Come “Collision Response”<br />

logico, viene invia<strong>to</strong> <strong>un</strong> messaggio al componente del DataLayer che rappresenta<br />

il Character del Player B. Una volta ricevu<strong>to</strong>, all’interno del <strong>su</strong>o<br />

me<strong>to</strong>do ExecMessage(), verrà decrementa<strong>to</strong> il valore del sot<strong>to</strong>-componente<br />

HealthPoint <strong>di</strong> N p<strong>un</strong>ti, a seconda del tipo <strong>di</strong> Bullet.<br />

Tale mo<strong>di</strong>fica verrà notificata au<strong>to</strong>maticamente al Player A.<br />

Notare come Il Player A avrebbe com<strong>un</strong>que potu<strong>to</strong> inviare il messaggio anche<br />

alla propria copia del componente relativo al Character <strong>di</strong> B: il ri<strong>su</strong>lta<strong>to</strong><br />

sarebbe sta<strong>to</strong> imme<strong>di</strong>a<strong>to</strong>, ed il <strong>su</strong>ccessivo aggiornamen<strong>to</strong> proveniente da B<br />

ne avrebbe semplicemente sovrascrit<strong>to</strong> il valore senza mo<strong>di</strong>ficarne lo sta<strong>to</strong><br />

<strong>di</strong> gioco. (Entrambi infatti avrebbero riporta<strong>to</strong> lo stesso valore <strong>di</strong> HP decrementa<strong>to</strong>).<br />

Una <strong>di</strong>fferenza <strong>di</strong> valore, in ques<strong>to</strong> senso, potrebbe essere <strong>un</strong><br />

campanello d’allarme per <strong>un</strong> eventuale sistema Anti-Cheating.


2.7. ESEMPI PRATICI 59<br />

Può capitare infatti che <strong>un</strong> Bullet <strong>di</strong> <strong>un</strong> Player non rilevi la collisione con <strong>un</strong><br />

Character in movimen<strong>to</strong> appartenente ad <strong>un</strong> altro Player perchè <strong>un</strong>o dei due<br />

(o entrambi) sono soggetti ad <strong>un</strong>’elevata latenza a tal p<strong>un</strong><strong>to</strong> che le notifiche<br />

dei rispettivi movimenti vengano ricevute con <strong>un</strong> sincronizzazione temporale<br />

tale da bypassare la Collision Detection tra il Bullet ed il Character. O<br />

viceversa, che venga rilevata <strong>un</strong>a collisione con <strong>un</strong> Character che in realtà si<br />

trova già fuori portata <strong>di</strong> tiro.<br />

Facendo riferimen<strong>to</strong> alla Figura 2.28, si possono in<strong>di</strong>viduare alc<strong>un</strong>i problemi<br />

com<strong>un</strong>i: Il Player A ha <strong>un</strong> Lag relativamente basso (60ms), contrariamente<br />

a B e C che hanno <strong>un</strong> Lag relativamente al<strong>to</strong> (rispettivamente 120ms<br />

e 240ms).<br />

In T1 il Player A spara <strong>un</strong> Bullet. In ques<strong>to</strong> istante il proiettile è presente<br />

solamente nel Data Layer e Layer View del <strong>Peer</strong> A.<br />

In T2 il Player B riceve la notifica <strong>di</strong> creazione Bullet, e conseguentemente<br />

crea la propria copia del componente logico, e quin<strong>di</strong> il relativo ogget<strong>to</strong><br />

grafico nel proprio Layer View. Inoltre inizia a muovere il proprio Character<br />

nella <strong>di</strong>rezione del Bullet <strong>di</strong> A. Nel frattempo in A il proiettile si è mosso <strong>di</strong><br />

qualche step. Il Player C, invece, è ancora fermo allo sta<strong>to</strong> <strong>di</strong> gioco <strong>di</strong> T0.<br />

In T3 il Bullet <strong>di</strong> A ed il Character <strong>di</strong> B continuano la propria corsa, mentre<br />

in C è finalmente gi<strong>un</strong>ta la notifica <strong>di</strong> creazione Bullet.<br />

In T4, nel Layer View del Player B, si palesa <strong>un</strong>a collisione tra il Bullet <strong>di</strong> A<br />

ed il Character <strong>di</strong> B. Cosa che invece non avviene nel Layer View del Player<br />

A, poiché il movimen<strong>to</strong> <strong>di</strong> B è in ritardo <strong>di</strong> qualche step. Dal momen<strong>to</strong> che,<br />

per <strong>un</strong>a scelta implementativa, è il ComponentScript dell’Owner del Bullet<br />

ad effettuare la Collision Detection, cioè A, tale collisione viene ignorata e<br />

non ha ripercussioni quin<strong>di</strong> <strong>su</strong>llo sta<strong>to</strong> <strong>di</strong> gioco.<br />

Il Player C inizia a muovere il proprio Character, ma tale informazione per<br />

il momen<strong>to</strong> rimane confinata al <strong>su</strong>o <strong>Peer</strong>.<br />

In T5 è C a rilevare <strong>un</strong>a collisione tra il Bullet <strong>di</strong> A ed il Character <strong>di</strong> B, ma<br />

per gli stessi motivi elencati nel precedente p<strong>un</strong><strong>to</strong>, ciò non ha ripercussioni


60 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

<strong>su</strong>llo sta<strong>to</strong> <strong>di</strong> gioco. Intan<strong>to</strong> C continua ad allontanarsi dalla rotta <strong>di</strong> collisione<br />

del Bullet, ma tale movimen<strong>to</strong> continua ad essere notifica<strong>to</strong> in ritardo<br />

agli altri Player.<br />

In T6, A rileva finalmente <strong>un</strong>a collisione, tra il proprio Bullet ed il Character<br />

<strong>di</strong> C. In realtà il Character <strong>di</strong> C si è già allontana<strong>to</strong> da tempo dalla rotta del<br />

Bullet, ma A, basandosi <strong>su</strong>l proprio DataLayer, crede ancora che il Player C<br />

si trovi alla posizione <strong>di</strong> partenza. Il Player A quin<strong>di</strong> invia il messaggio <strong>di</strong><br />

collisione al componente relativo al Character <strong>di</strong> C.<br />

In T8, il Character <strong>di</strong> C riceve il messaggio <strong>di</strong> A e si decrementa i propri<br />

P<strong>un</strong>ti vita.<br />

In T9 ed in T10, la propagazione <strong>di</strong> tale mo<strong>di</strong>fica raggi<strong>un</strong>ge infine sia il Player<br />

A che il PlayerB<br />

L’esempio, volutamente amplifica<strong>to</strong>, mostra come, in caso <strong>di</strong> prestazioni<br />

<strong>di</strong> rete non ottimali, la desincronizzazione “percepita” possa deteriorare<br />

notevolmente l’esperienza <strong>di</strong> gioco (il Player C si vede sottrarre dei P<strong>un</strong>ti<br />

vita, nonostante, dal <strong>su</strong>o p<strong>un</strong><strong>to</strong> <strong>di</strong> vista, abbia schiva<strong>to</strong> abbontantemente il<br />

proiettile <strong>di</strong> A). In <strong>un</strong> contes<strong>to</strong> più realistico, il rappor<strong>to</strong> tra gli spazi <strong>di</strong> movimen<strong>to</strong>,<br />

la frequenza <strong>di</strong> aggiornamen<strong>to</strong> ed il Lag è minore, rendendo l’impat<strong>to</strong><br />

<strong>di</strong> ques<strong>to</strong> genere <strong>di</strong> desincronizzazioni piut<strong>to</strong>s<strong>to</strong> ri<strong>di</strong>mensiona<strong>to</strong>.<br />

È importante notare però come, nell’ultimo istante temporale presenta<strong>to</strong> nell’esempio,<br />

lo sta<strong>to</strong> <strong>di</strong> gioco sia perfettamente sincronizza<strong>to</strong> in tutti i tre <strong>Peer</strong>.<br />

In <strong>un</strong> First Person Shooter solitamente si possono <strong>di</strong>stinguere due tipi<br />

<strong>di</strong> Bullet: quello “fisico”, tipicamente più len<strong>to</strong> e quin<strong>di</strong> schivabile, e quello<br />

det<strong>to</strong> “HitScan”, che non implica la creazione <strong>di</strong> <strong>un</strong> apposi<strong>to</strong> ogget<strong>to</strong> 3D e<br />

relativa “Collision Detection”: viene infatti testata <strong>di</strong>rettamente l’intersezione<br />

tra il vet<strong>to</strong>re “Ray”, le cui coor<strong>di</strong>nate coincidono con le coor<strong>di</strong>nate del<br />

mouse (con la dovuta conversione da ScreenSpace (2D) a WorldSpace (3D)<br />

ed il cui verso coincide con la profon<strong>di</strong>tà in<strong>di</strong>viduata dalla rotazione della<br />

telecamera, e gli oggetti <strong>di</strong> tipo Character (od <strong>un</strong>a approssimazione del loro<br />

volume geometrico).


2.7. ESEMPI PRATICI 61<br />

Figura 2.28: Problematiche relative alla collisione tra oggetti in <strong>un</strong> contes<strong>to</strong><br />

caratterizza<strong>to</strong> da <strong>un</strong>a <strong>un</strong>’elevata latenza


62 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Quando si verifica <strong>un</strong>’intersezione tra <strong>un</strong> “Ray” ed <strong>un</strong> Character, e quest’ultimo<br />

si trova in testa alla lista degli oggetti intersecati (<strong>un</strong> “Ray”, può<br />

intersecare, infatti, più oggetti contemporaneamente, or<strong>di</strong>nati in <strong>un</strong>a lista<br />

dal più vicino al più lontano), il <strong>Peer</strong> che ha esegui<strong>to</strong> l’“HitScan”, invierà <strong>un</strong><br />

messaggio al componente relativo al Character colpi<strong>to</strong>, che <strong>di</strong> conseguenza<br />

decrementerà i propri “P<strong>un</strong>ti vita”.<br />

2.7.3 Creazione e <strong>di</strong>struzione <strong>di</strong> oggetti<br />

Come illustra<strong>to</strong> nelle sezioni 2.4 e 2.6, la creazione <strong>di</strong> <strong>un</strong> elemen<strong>to</strong> grafico<br />

che apporta informazione allo sta<strong>to</strong> <strong>di</strong> gioco, come può essere <strong>un</strong> ogget<strong>to</strong> 3D,<br />

viene concretizzata, istanziando il componente vi<strong>su</strong>ale au<strong>to</strong>maticamente dal<br />

View Context del Layer View, basandosi <strong>su</strong>i componenti presenti nel Data<br />

Layer.<br />

Per quegli oggetti grafici che devono essere “con<strong>di</strong>visi”, cioè presenti in tutti<br />

i <strong>Peer</strong> appartenenti alla Membership, è imperativo, quin<strong>di</strong>, passare per il Data<br />

Layer, istanziando il componente logico, piut<strong>to</strong>s<strong>to</strong> che creare <strong>di</strong>rettamente<br />

l’ogget<strong>to</strong> 3D.<br />

Per esempio, se si vuole creare <strong>un</strong> Bullet tri<strong>di</strong>mensionale, sarà <strong>su</strong>fficiente<br />

creare <strong>un</strong> componente <strong>di</strong> tipo Bullet opport<strong>un</strong>amente inizializza<strong>to</strong> (coor<strong>di</strong>nate<br />

e rotazione devono coincidere con quella del Character che “spara” il<br />

Bullet).<br />

Analogamente, per <strong>di</strong>struggere <strong>un</strong> ogget<strong>to</strong> 3D, invece <strong>di</strong> eliminare <strong>di</strong>rettamente<br />

l’istanza grafica, è necessario rimuovere il relativo componente dal<br />

DataLayer.<br />

Eliminando solamente l’istanza grafica, infatti, ne verrebbe istanziata <strong>un</strong>a<br />

nuova copia, au<strong>to</strong>maticamente all’iterazione <strong>su</strong>ccessiva, dal momen<strong>to</strong> che il<br />

componente logico ri<strong>su</strong>lta ancora presente nel Data Layer.<br />

Ogni creazione e <strong>di</strong>struzione <strong>di</strong> <strong>un</strong> componente, come illustra<strong>to</strong> nella sezione<br />

2.4, viene propagata all’intera Membership attraverso i coman<strong>di</strong> “Create-


2.7. ESEMPI PRATICI 63<br />

Component” e “DestroyComponent”. Se il tipo <strong>di</strong> componente è <strong>un</strong> aggrega<strong>to</strong><br />

<strong>di</strong> sot<strong>to</strong>-componenti, allora saranno inoltrati tanti coman<strong>di</strong> “CreateComponent”<br />

e “DestroyComponent” quanti sono i sot<strong>to</strong>-componenti.<br />

Gli elementi presenti nell’ambiente tri<strong>di</strong>mensionale con<strong>di</strong>viso, a seconda delle<br />

loro caratteristiche e della loro f<strong>un</strong>zione, si possono raggruppare nei seguenti<br />

insiemi:<br />

• Elementi <strong>di</strong> scena: sono quegli elementi “statici” che non apportano informazione<br />

a livello <strong>di</strong> sta<strong>to</strong> <strong>di</strong> gioco. Tipicamente Arene (o mappe) 14 ,<br />

stanze, corridoi, o altri oggetti prettamente decorativi rientrano in questa<br />

tipologia <strong>di</strong> elementi, che non vengono istanziati conseguentemente<br />

ad <strong>un</strong> even<strong>to</strong> contestualizza<strong>to</strong> a livello logico o <strong>di</strong> rete, ma son presenti<br />

<strong>di</strong>rettamente nel Layer View, in<strong>di</strong>pendentemente dallo sta<strong>to</strong> del <strong>Peer</strong><br />

sot<strong>to</strong>stante.<br />

• Elementi attivi: sono quegli elementi “<strong>di</strong>namici” che, con la loro presenza<br />

alterano lo sta<strong>to</strong> <strong>di</strong> gioco: characters, Bullets, HealthPacks, ad<br />

esempio, rientrano in questa tipologia.<br />

Tra gli elementi attivi si può operare <strong>un</strong>’ulteriore <strong>di</strong>stinzione. Alc<strong>un</strong>i <strong>di</strong> questi<br />

elementi, infatti, “appartengono” in modo naturale ad <strong>un</strong> <strong>Peer</strong>: il Character<br />

del Player A è chiaramente <strong>di</strong> proprietà del rispettivo <strong>Peer</strong>. Analogamente<br />

<strong>un</strong> Bullet spara<strong>to</strong> da <strong>un</strong> Character del Player B apparterrà al <strong>Peer</strong> B. Altri<br />

elementi però sfuggono a questa regola. Si pensi agli HealthPack: a quale<br />

<strong>Peer</strong> appartengono? O, in altre parole, a quale Fac<strong>to</strong>ry è delegata la loro<br />

creazione?<br />

Per ques<strong>to</strong> tipo <strong>di</strong> elementi si è pensa<strong>to</strong> <strong>di</strong> agire nel seguente modo: <strong>su</strong>lla<br />

mappa “statica” (appartenente quin<strong>di</strong> alla categoria degli elementi <strong>di</strong> scena)<br />

vengono inseriti N PlaceHolder, cioè p<strong>un</strong>ti astratti che al momen<strong>to</strong> della<br />

realizzazione della mappa non contengono ness<strong>un</strong> ogget<strong>to</strong> in particoare, ma<br />

identificano com<strong>un</strong>que <strong>un</strong>a posizione eventualmente occupabile in r<strong>un</strong>time.<br />

14 Gli ambienti nei quali si svolgono le partite <strong>di</strong> <strong>un</strong> FPS


64 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

Questi PlaceHolder sono anch’essi elementi <strong>di</strong> scena dal momen<strong>to</strong> che caratterizzano<br />

la mappa <strong>di</strong> gioco (come colonne, p<strong>un</strong>ti luce, ostacoli, etc), e sono<br />

quin<strong>di</strong> caricati contestualmente al loa<strong>di</strong>ng della mappa (che viene eseguita<br />

in modo del tut<strong>to</strong> in<strong>di</strong>pendente da <strong>un</strong> <strong>di</strong>scorso <strong>di</strong> rete).<br />

Quando inizia <strong>un</strong>a partita, ogni <strong>Peer</strong> “occupa”, preventivamente, N/(Numero<br />

<strong>di</strong> <strong>Peer</strong>) PlaceHolder con <strong>un</strong> componente <strong>di</strong> tipo HealthPackGenera<strong>to</strong>r (ere<strong>di</strong>ta<strong>to</strong><br />

da Object3D). Il criterio (necessariamente con<strong>di</strong>viso) utilizza<strong>to</strong> per la<br />

<strong>di</strong>stribuzione e l’assegnazione dei PlaceHolder ai <strong>di</strong>versi <strong>Peer</strong> può essere realizza<strong>to</strong><br />

me<strong>di</strong>ante politiche basate <strong>su</strong>l NetID, o qual<strong>un</strong>que altra informazione<br />

che contrad<strong>di</strong>stingue ogni singolo <strong>Peer</strong>, evitando quin<strong>di</strong> f<strong>un</strong>zioni alea<strong>to</strong>rie.<br />

Ogni HealthPackGenera<strong>to</strong>r si occuperà <strong>di</strong> istanziare perio<strong>di</strong>camente, laddove<br />

non già presente, <strong>un</strong> componente <strong>di</strong> tipo HealthPack alle stesse coor<strong>di</strong>nate<br />

del relativo PlaceHolder.<br />

Ques<strong>to</strong> significa che ogni Player “possiede” <strong>un</strong> determina<strong>to</strong> numero <strong>di</strong><br />

HealthPack e ne gestisce quin<strong>di</strong> anche le collisioni con i Character degli altri<br />

Player (Figura 2.29).<br />

2.7.4 Connessione e Disconnessione dei Player<br />

Nelle sezioni precedenti è sta<strong>to</strong> evidenzia<strong>to</strong> come ogni informazione a<strong>to</strong>mica<br />

appartenga ad <strong>un</strong> determina<strong>to</strong> <strong>Peer</strong>.<br />

Ques<strong>to</strong> risolve, da <strong>un</strong>a parte, il problema della consistenza dello sta<strong>to</strong> <strong>di</strong> gioco,<br />

ma dall’altra introduce alc<strong>un</strong>e problematiche dovute all’importanza <strong>di</strong><br />

ogni singolo <strong>Peer</strong>, al p<strong>un</strong><strong>to</strong> da poter essere considerati degli SPOF.<br />

Quando <strong>un</strong> <strong>Peer</strong> si <strong>di</strong>sconnette od esce dalla Membership, gli effetti della<br />

logica <strong>di</strong> aggiornamen<strong>to</strong> dei componenti <strong>di</strong> <strong>su</strong>a appartenenza non viene più<br />

propagata agli altri <strong>Peer</strong>. Per alc<strong>un</strong>i tipi <strong>di</strong> componenti, inoltre, può essere<br />

necessario <strong>di</strong>struggerne le istanze quando il <strong>Peer</strong> owner non è più raggi<strong>un</strong>gibile.<br />

Non esiste <strong>un</strong>a regola generale, ma è possibile definirne <strong>un</strong>a per ogni tipo


2.7. ESEMPI PRATICI 65<br />

Figura 2.29: Arena e PlaceHolder sono elementi <strong>di</strong> scena, mentre HealthPack-<br />

Genera<strong>to</strong>r, HealthPack e Character sono elementi attivi. Alc<strong>un</strong>i <strong>di</strong> questi<br />

appartengono al Player A ed altri al Player B.<br />

<strong>di</strong> componente: gli HealthPack e i Bullet, ad esempio, non possono essere<br />

<strong>di</strong>strutti, e devono continuare ad essere aggiornati. Il Character, invece, generalmente<br />

viene <strong>di</strong>strut<strong>to</strong>.<br />

Sorge quin<strong>di</strong> <strong>un</strong> problema lega<strong>to</strong> all’aggiornamen<strong>to</strong> <strong>di</strong> quei componenti<br />

il cui <strong>Peer</strong> non è più presente all’interno della Membership. Una soluzione<br />

potrebbe essere quella <strong>di</strong> forzare il cambio <strong>di</strong> proprietà dal <strong>Peer</strong> <strong>di</strong>sconnesso<br />

ad <strong>un</strong> <strong>Peer</strong> ancora connesso.<br />

Il Modulo SharedComponents, in casi eccezionali, permette <strong>di</strong> delegare la<br />

proprietà <strong>di</strong> <strong>un</strong> componente come se fosse sta<strong>to</strong> genera<strong>to</strong> da <strong>un</strong>’altro Fac<strong>to</strong>ry.<br />

Il <strong>Peer</strong> che ne acquisisce la proprietà <strong>di</strong>venta il <strong>su</strong>o nuovo “Owner” e<br />

deve notificare tale passaggio a tutti gli altri <strong>Peer</strong> ancora connessi.<br />

Per decidere a quale <strong>Peer</strong> cedere la proprietà, analagomente a quan<strong>to</strong> <strong>su</strong>ccede<br />

per la creazione degli HealthPack, l’utilizzo <strong>di</strong> <strong>un</strong>a f<strong>un</strong>zione alea<strong>to</strong>ria<br />

è sconsigliabile. Così come è sconsigliabile eseguire <strong>un</strong> Polling N-a-N: ogni<br />

<strong>Peer</strong> esegue <strong>un</strong> Polling <strong>di</strong> check <strong>su</strong>l <strong>Peer</strong> temporalmente connesso dopo <strong>di</strong>


66 CAPITOLO 2. ARCHITETTURA SOFTWARE<br />

lui, e nel caso quest’ultimo non sia più raggi<strong>un</strong>gibile si appropria dei <strong>su</strong>oi<br />

componenti. Se l’or<strong>di</strong>ne <strong>di</strong> connessione è: Player A, Player B, Player C e<br />

Player D, quin<strong>di</strong>, Player A esegue <strong>un</strong> Polling <strong>su</strong>l Player B, il Player B <strong>su</strong>l<br />

Player C, il Player C <strong>su</strong>l Player D ed infine il Player D <strong>su</strong>l Player A. Ogni<br />

<strong>Peer</strong> com<strong>un</strong>que, a livello <strong>di</strong> implementazione del modulo NET, riceve <strong>un</strong>a<br />

notifica alla <strong>di</strong>sconnessione <strong>di</strong> nodo: se sia il Player B che il Player C si <strong>di</strong>sconnet<strong>to</strong>no<br />

contemporaneamente, prima che Player B sia riusci<strong>to</strong> quin<strong>di</strong> a<br />

notificare agli altri <strong>Peer</strong> l’avvenuta acquisizione dei componenti <strong>di</strong> Player C,<br />

Player A, sapendo che sia B che C non sono più presenti nella Membership,<br />

acquisisce i componenti appartenenti al Player B e quin<strong>di</strong> quelli appartenenti<br />

al Player C.


Capi<strong>to</strong>lo 3<br />

Implementazione<br />

Di segui<strong>to</strong>, dopo <strong>un</strong>’introduzione generale, verranno illustrate le problematiche<br />

e le soluzioni implementative che sono state in<strong>di</strong>viduate e concretizzate<br />

all’interno <strong>di</strong> ogni singolo Layer.<br />

3.1 Introduzione Generale<br />

L’implementazione software rispecchia la <strong>su</strong>d<strong>di</strong>visione dell’architettura<br />

presentata nel capi<strong>to</strong>lo 2 (Figura 3.1): Tutti i Layer ed i Moduli, ad esclusione<br />

del Layer View, sono <strong>di</strong>sponibili come DLL 1 e realizzati in modo da<br />

minimizzare le <strong>di</strong>pendenze.<br />

Quest’ultime sono, infatti, riscontrabili esclusivamente nei legami tra <strong>un</strong><br />

Layer <strong>su</strong>periore e quello inferiore, e non viceversa.<br />

Per la realizzazione <strong>di</strong> tali legami, inoltre, si é scel<strong>to</strong> da <strong>un</strong>a parte <strong>di</strong> esporre<br />

Interfacce piut<strong>to</strong>s<strong>to</strong> che Classi specifiche, e dall’altra <strong>di</strong> seguire, laddove<br />

possibile ed effettivamente conveniente, l’Observer Pattern, poiché induce <strong>un</strong><br />

maggiore <strong>di</strong>saccoppiamen<strong>to</strong> tra i <strong>di</strong>versi Layer.<br />

Si é inoltre cerca<strong>to</strong> <strong>di</strong> evitare l’utilizzo <strong>di</strong> me<strong>to</strong><strong>di</strong> e membri statici, rendendo<br />

1 Dynamic-Link Library, libreria software che viene caricata <strong>di</strong>namicamente in fase <strong>di</strong><br />

esecuzione<br />

67


68 CAPITOLO 3. IMPLEMENTAZIONE<br />

possibile l’esecuzione <strong>di</strong> più <strong>Peer</strong> all’interno dello stesso programma. Ciò ha<br />

facilita<strong>to</strong> i processo <strong>di</strong> debugging dei Layer logici e <strong>di</strong> rete.<br />

I <strong>di</strong>versi Layer con<strong>di</strong>vidono alc<strong>un</strong>i elementi <strong>di</strong> natura strutturale: ad esempio<br />

il Layer Net, il Layer P2P ed modulo SharedComponents concretizzano<br />

il concet<strong>to</strong> <strong>di</strong> “comando” nel medesimo modo (utilizzando lo stesso tipo <strong>di</strong><br />

interfacce e presentando implementazioni simili).<br />

Per quan<strong>to</strong> concerne le tecnologie ed i linguaggi <strong>di</strong> programmazione utilizzati,<br />

<strong>un</strong>o dei fat<strong>to</strong>ri che ne hanno vincola<strong>to</strong> la scelta, risiede nel Layer View.<br />

Il Layer View infatti é compos<strong>to</strong> da moduli piut<strong>to</strong>s<strong>to</strong> complessi, le cui f<strong>un</strong>zioni<br />

e<strong>su</strong>lano da quelle che sono le tematiche del proget<strong>to</strong> <strong>di</strong> tesi.<br />

Era necessario in<strong>di</strong>viduare <strong>un</strong> Framework od <strong>un</strong> Engine che offrisse il<br />

maggior numero <strong>di</strong> f<strong>un</strong>zionalità richieste dalle specifiche del Layer View e,<br />

contemporaneamente, permettesse in breve tempo l’integrazione con i Layer<br />

sot<strong>to</strong>stanti.<br />

La scelta é ricaduta <strong>su</strong> Unity3D 2 .<br />

Unity3D si presenta come <strong>un</strong> ambiente integra<strong>to</strong> che mette a <strong>di</strong>sposizione <strong>un</strong><br />

Renderer 3D, <strong>un</strong>o SceneGraph particolarmente modulare, <strong>un</strong> Engine fisico<br />

per la gestione dei movimenti e delle collisioni nonché sistemi per la gestione<br />

degli input ed il <strong>su</strong>ppor<strong>to</strong> au<strong>di</strong>o.<br />

Tra le caratteristiche peculiari <strong>di</strong> Unity3D vi sono il cos<strong>to</strong> (gratui<strong>to</strong> per<br />

applicazioni non commerciali), l’E<strong>di</strong><strong>to</strong>r WYSIWYG, che consente <strong>un</strong>a rapida<br />

definizione della scena tri<strong>di</strong>mensionale, e la possibilità <strong>di</strong> convertire il proget<strong>to</strong><br />

<strong>su</strong> <strong>di</strong>verse piattaforme.<br />

Per quan<strong>to</strong> riguarda la programmazione, Unity3D <strong>su</strong>pporta l’utilizzo del<br />

linguaggio C#, e mette a <strong>di</strong>sposizione <strong>un</strong> sistema semplifica<strong>to</strong> <strong>di</strong> “scripting”<br />

2 www.<strong>un</strong>ity3d.com


3.2. LAYER NET 69<br />

basa<strong>to</strong> <strong>su</strong>l concet<strong>to</strong> <strong>di</strong> Behaviour (che definisce parte della logica <strong>di</strong> ogni<br />

singolo ogget<strong>to</strong> grafico), consentendo com<strong>un</strong>que l’utilizzo <strong>di</strong> para<strong>di</strong>gmi ed<br />

approcci più classici.<br />

Per ridurre al minimo problematiche d’integrazione si é scel<strong>to</strong>, quin<strong>di</strong>, <strong>di</strong><br />

procedere con l’utilizzo del linguaggiio C# anche per l’implementazione dei<br />

Layer sot<strong>to</strong>stanti.<br />

Figura 3.1: Il Layer NET (de<strong>di</strong>ca<strong>to</strong> alla com<strong>un</strong>icazione) è implementa<strong>to</strong> nel<br />

file NET.DLL;<br />

Il Layer P2P (de<strong>di</strong>ca<strong>to</strong> alla gestione della Membership) è implementa<strong>to</strong> nel<br />

file P2P.DLL;<br />

Il Modulo SharedComponents (utilizza<strong>to</strong> come Data Layer) è implementa<strong>to</strong><br />

nel file SharedComponents.DLL;<br />

Il Layer Logic è implementa<strong>to</strong> nel file Logic.DLL, mentre il Layer View fa da<br />

EntryPoint e coincide con l’eseguibile dell’applicazione.<br />

3.2 Layer NET<br />

Il Layer NET presenta, ad <strong>un</strong> primo livello, alc<strong>un</strong>e classi <strong>di</strong> servizio, che<br />

per lo più espongono proprietà e me<strong>to</strong><strong>di</strong> statici:


70 CAPITOLO 3. IMPLEMENTAZIONE<br />

Figura 3.2: Diagramma delle Classi - Layer NET


3.2. LAYER NET 71<br />

• Le classi Setup e Constants fanno da conteni<strong>to</strong>re a tutti i parametri<br />

<strong>di</strong> configurazione del Layer. Ad esempio sono qui definiti i nomi delle<br />

classi che implementeranno le interfacce INet e ILink, i millisecon<strong>di</strong> <strong>di</strong><br />

attesa dei Thread <strong>di</strong> lettura e scrittura <strong>di</strong> <strong>un</strong> Link, e la <strong>di</strong>mensione<br />

della finestra TCP (nel caso sia utilizza<strong>to</strong> ques<strong>to</strong> pro<strong>to</strong>collo). Come<br />

prima implementazione, tali valori sono inizializzati <strong>di</strong>rettamente all’interno<br />

del co<strong>di</strong>ce, ma come sviluppo futuro è previs<strong>to</strong> l’utilizzo <strong>di</strong> file<br />

<strong>di</strong> configurazione esterni.<br />

• La classe Delegates raccoglie la definizione <strong>di</strong> tutti i Delegates, ovvero<br />

tipi <strong>di</strong> da<strong>to</strong> necessari a formalizzare la natura dei me<strong>to</strong><strong>di</strong> anonimi<br />

utilizzati per l’implementazione degli Eventi e dell’Observer Pattern in<br />

generale, <strong>su</strong>i quali si basa la com<strong>un</strong>icazione da ques<strong>to</strong> Layer verso i<br />

Layer <strong>su</strong>periori.<br />

• La classe Utils raccoglie <strong>un</strong>a serie <strong>di</strong> me<strong>to</strong><strong>di</strong> ausiliari e <strong>di</strong> utilità generale.<br />

Ad esempio qui risiedono i me<strong>to</strong><strong>di</strong> <strong>di</strong> conversione tra IP Address,<br />

Port e NetID.<br />

• La classe Fac<strong>to</strong>ry permette, attraverso il principio IoC 3 <strong>di</strong> istanziare<br />

oggetti concreti <strong>di</strong> INode e ILink astraendo dalla loro implementazione.<br />

Sono poi definite le interfacce esposte ai Layer <strong>su</strong>periori:<br />

• INode: Identifica <strong>un</strong> nodo <strong>di</strong> rete. Al <strong>su</strong>o interno è presente <strong>un</strong> lista<br />

<strong>di</strong> ILink, che vengono istanziati <strong>su</strong>lla chiamata del me<strong>to</strong>do ConnectTo(<br />

string ipAddress, int port).<br />

Il me<strong>to</strong>do SetNewIdentifierOfLink(ILink link, String newIdentifier) consente<br />

<strong>di</strong> cambiare l’identificativo <strong>di</strong> <strong>un</strong> link.<br />

Sono inoltre esposti <strong>un</strong>a serie <strong>di</strong> me<strong>to</strong><strong>di</strong> che permet<strong>to</strong>no ai Layer <strong>su</strong>periori<br />

<strong>di</strong> registrarsi ad alc<strong>un</strong>i eventi <strong>di</strong>spacciati dal singolo nodo: ad<br />

esempio quando <strong>un</strong> ILink presente nella lista riceve <strong>un</strong> messaggio, viene<br />

lancia<strong>to</strong> il me<strong>to</strong>do delega<strong>to</strong> che si era registra<strong>to</strong> all’even<strong>to</strong> OnRead.<br />

3 Inversion of control, <strong>un</strong> pattern grazie al quale è possibile delegare ad <strong>un</strong>a terza entità<br />

la creazione <strong>di</strong> <strong>un</strong> preciso ogget<strong>to</strong> in<strong>di</strong>candone, ad esempio, solamente l’interfaccia


72 CAPITOLO 3. IMPLEMENTAZIONE<br />

• ILink: identifica <strong>un</strong> canale <strong>di</strong> rete. Attraverso i me<strong>to</strong><strong>di</strong> Read() e Write()<br />

è possibile ascoltare ed inviare messaggi all’endpoint associa<strong>to</strong> all’ILink<br />

in questione.<br />

Figura 3.3: Interfacce NET<br />

Tali interfacce sono state concretizzate attraverso due classi: TCPNode e<br />

TPCLink. Il pro<strong>to</strong>collo <strong>di</strong> rete utilizza<strong>to</strong> come prima implementazione è infatti<br />

il TCP/IP. Applicazioni interattive come i videogiochi, spesso richiedono<br />

<strong>un</strong> frequente e rapido scambio <strong>di</strong> informazioni. Il pro<strong>to</strong>collo UDP potrebbe<br />

essere consigliabile in ques<strong>to</strong> senso, poiché è Message-Oriented invece che<br />

Stream-Oriented, e per ogni pacchet<strong>to</strong> invia<strong>to</strong> non deve aspettare <strong>un</strong> messaggio<br />

<strong>di</strong> ri<strong>to</strong>rno; d’altro can<strong>to</strong>, però, per evitare problemi <strong>di</strong> consistenza,<br />

ri<strong>su</strong>ltano necessari sistemi che garantiscono maggiore sicurezza e affidabilità<br />

in termini controllo <strong>di</strong> congestione, Ack <strong>di</strong> ricezione ed il mantenimen<strong>to</strong><br />

dell’or<strong>di</strong>ne <strong>di</strong> invio dei pacchetti. Inoltre per l’in<strong>di</strong>viduazione <strong>di</strong> <strong>un</strong>a Membership<br />

può ri<strong>su</strong>ltare più comodo <strong>un</strong> pro<strong>to</strong>collo Connection-oriented poiché<br />

la connessione e la <strong>di</strong>sconnessione <strong>di</strong> no<strong>di</strong> all’interno della rete vengono gestiti<br />

<strong>di</strong>rettamente dal sistema, rendendo <strong>su</strong>perflua <strong>un</strong>’emulazione logica la<strong>to</strong><br />

applicazione: esis<strong>to</strong>no infatti implementazioni UDP “Reliable”, anche appositamente<br />

mirate ai videogiochi (si veda Raknet 4 ), che, la<strong>to</strong> applicazione,<br />

4 http://www.jenkinssoftware.com


3.2. LAYER NET 73<br />

fanno fronte a ques<strong>to</strong> tipo <strong>di</strong> problematiche. Dal momen<strong>to</strong> che il Layer NET<br />

com<strong>un</strong>ica con il Layer de<strong>di</strong>ca<strong>to</strong> alla gestione della Membership attraverso interfacce<br />

agnostiche rispet<strong>to</strong> al pro<strong>to</strong>collo utilizza<strong>to</strong>, si è scel<strong>to</strong>, in prima istanza,<br />

<strong>di</strong> appoggiarsi al pro<strong>to</strong>collo TCP/IP. Questa scelta non ri<strong>su</strong>lta com<strong>un</strong>que<br />

vincolante, e sarà possibile, in futuro, <strong>su</strong>pportare <strong>un</strong>’implementazione esclusivamente<br />

UDP, od eventualmente ibrida, senza dover mo<strong>di</strong>ficare le interfacce<br />

dei Layer sovrastanti. E’ importante sot<strong>to</strong>lineare però come l’introduzione<br />

del <strong>su</strong>ppor<strong>to</strong> al pro<strong>to</strong>collo UDP renda necessario <strong>un</strong> sistema <strong>di</strong> or<strong>di</strong>namen<strong>to</strong><br />

dei pacchetti ricevuti, non richies<strong>to</strong> invece nell’attuale implementazione.<br />

Figura 3.4: Classi principali - Layer TCP<br />

• TCPNode: Concretizza l’interfaccia INode basandosi <strong>su</strong>l pro<strong>to</strong>collo<br />

TCP. Per rimanere in ascol<strong>to</strong> <strong>di</strong> connessioni esterne, viene utilizza<strong>to</strong><br />

<strong>un</strong> ogget<strong>to</strong> della classe TcpListener del FrameWork .NET.<br />

Quando si vuole connettere <strong>un</strong> TCPNode A ad <strong>un</strong> TCPNode B, <strong>su</strong>l<br />

primo viene chiama<strong>to</strong> il me<strong>to</strong>do ConnectTo(’B’) che creerà au<strong>to</strong>maticamente<br />

<strong>un</strong> TCPLink verso B, mentre <strong>su</strong>l secondo, quando sarà ri-


74 CAPITOLO 3. IMPLEMENTAZIONE<br />

levata la connessione da parte <strong>di</strong> A, verrà crea<strong>to</strong> <strong>un</strong> TCPLink verso<br />

quest’ultimo.<br />

• TCPLink: Concretizza l’interfaccia ILink basandosi <strong>su</strong>l pro<strong>to</strong>collo TCP.<br />

Attraverso due Thread sarà possibile rispettivamente leggere e scrivere<br />

<strong>su</strong>llo stream dal proprio TCPNode all’EndPoint specifica<strong>to</strong>, e viceversa.<br />

Quando <strong>su</strong>llo stream viene in<strong>di</strong>vidua<strong>to</strong> <strong>un</strong> messaggio, cioè quando si<br />

presentano i caratteri termina<strong>to</strong>ri “\r\n”, ques<strong>to</strong> viene memorizza<strong>to</strong><br />

in <strong>un</strong>’apposita coda, e <strong>su</strong>ccessivamente, passa<strong>to</strong> al me<strong>to</strong>do ReadLine(string<br />

message). In ReadLine() viene chiama<strong>to</strong> a <strong>su</strong>a volta il me<strong>to</strong>do<br />

ProcessMessage(ILink link, string message) del proprio TCPNode, che<br />

si occuperà <strong>di</strong> processare il messaggio.<br />

3.2.1 Commands<br />

La maggior parte dei messaggi scambiati tra i no<strong>di</strong> appartenenti alla<br />

Membership è realizzata tramite i Commands.<br />

L’idea che sta alla base dei Commands ricalca quella en<strong>un</strong>ciata dal Command<br />

Pattern.<br />

Sostanzialmente ogni comando è implementa<strong>to</strong> in <strong>un</strong>’apposita classe che concretizza<br />

l’interfaccia ICommand, ed ha <strong>un</strong>a duplice f<strong>un</strong>zione:<br />

Da <strong>un</strong>a parte permette <strong>di</strong> generare in modo au<strong>to</strong>matico e <strong>un</strong>iforme la stringa<br />

da inviare come messaggio, mentre dall’altra, attraverso il me<strong>to</strong>do “Exec()”,<br />

esegue le operazioni che caratterizzano il comando stesso.<br />

A livello <strong>di</strong> Layer NET, questi sono implementati dalla classe base Net-<br />

Command, estesa poi per ogni singolo comando. Un NetCommand è in<strong>di</strong>vidua<strong>to</strong><br />

dai Parameters, dal INode destinatario e dal ILink mittente.<br />

Tra questi vi sono i 3 coman<strong>di</strong> de<strong>di</strong>cati all’HandShaking (si veda Figura 2.1):<br />

• HandShakeBegin: Nel <strong>su</strong>o me<strong>to</strong>do Exec() viene chiama<strong>to</strong> Node.Set-<br />

NewIdentifierOfLink(ILink Link, string Parameters), che confermerà o<br />

aggiornerà l’identità del Link conosciu<strong>to</strong> dal Node <strong>su</strong>l quale è sta<strong>to</strong> ese-


3.2. LAYER NET 75<br />

Figura 3.5: Per inviare <strong>un</strong> comando da gestire a livello NET, da <strong>un</strong> Nodo A<br />

ad <strong>un</strong> Nodo B, viene prima creata <strong>un</strong>’istanza dell’apposita classe ere<strong>di</strong>tata<br />

da NetCommand, ed inizializzata secondo i parametri desiderati; quin<strong>di</strong> serializzata<br />

attraverso l’ovveride del me<strong>to</strong>do ToString() e scritta <strong>su</strong>llo stream<br />

del Link A-B.<br />

Quando il messaggio gi<strong>un</strong>ge a B, viene prima invoca<strong>to</strong> il Processor appartenente<br />

al Layer NET. Se il messaggio deve essere esegui<strong>to</strong> <strong>su</strong>l Layer NET,<br />

allora tale Processor istanzierà au<strong>to</strong>maticamente, grazie alla Reflection, <strong>un</strong><br />

ogget<strong>to</strong> della classe che definisce il comando, e, a seconda dei casi, lo eseguirà<br />

<strong>di</strong>rettamente, chiamando il <strong>su</strong>o me<strong>to</strong>do Exec() o lo inserirà in <strong>un</strong>a coda <strong>di</strong> esecuzione.<br />

Se invece non si tratta <strong>di</strong> <strong>un</strong> messaggio da eseguire <strong>su</strong>l Layer NET,<br />

allora l’INode destinatario chiamerà gli eventuali me<strong>to</strong><strong>di</strong> delegati registrati<br />

al proprio even<strong>to</strong> OnRead, cosicché i Layer <strong>su</strong>periori possano processare il<br />

messaggio allo stesso modo.


76 CAPITOLO 3. IMPLEMENTAZIONE<br />

gui<strong>to</strong> il comando, e quin<strong>di</strong> Link.Write(new HandShakeResponse( Node.GetNetID()<br />

).ToString() ) , che <strong>di</strong> fat<strong>to</strong> corrisponderà alla risposta<br />

che il Node invierà al Link per notificare la propria identità.<br />

• HandShakeResponse: analogamente a HandShakeBegin, viene prima<br />

chiama<strong>to</strong> Node.SetNew- IdentifierOfLink( ILink Link, string Parameters<br />

) (questa volta <strong>su</strong>ll’altro Nodo), e quin<strong>di</strong> Link.Write( new Hand-<br />

ShakeEnd( Node.GetNetID() ) ) per notificare a Link l’avvenuta ricezione<br />

del comando HandShakeResponse. Inoltre viene flagga<strong>to</strong> a “true”<br />

l’attribu<strong>to</strong> “Active” relativo alla connessione tra il Node e l’EndPoint<br />

<strong>di</strong> Link.<br />

• HandShakeEnd: analogamente ad HandShakeResponse, <strong>su</strong>ll’Exec() viene<br />

attivata la connessione tra il Node e l’EndPoint <strong>di</strong> Link.<br />

Tra gli sviluppi futuri è stata considerata la possibilità <strong>di</strong> implementare<br />

<strong>un</strong> sot<strong>to</strong>-stra<strong>to</strong> ulteriore de<strong>di</strong>ca<strong>to</strong> alla compressione / decompressione dei dati,<br />

da inserire o a livello del ToString() del NetCommand base, o a livello dei<br />

threads Read / Write della classe NetChannel, oppure <strong>di</strong>rettamente sot<strong>to</strong> il<br />

Layer NET.<br />

In Figura 3.6 è illustrata la struttura della stringa che viene generata <strong>di</strong><br />

default dall’override del ToString().<br />

Figura 3.6: Struttura della stringa dei messaggi implementati dai Commands


3.3. LAYER P2P 77<br />

3.3 Layer P2P<br />

Figura 3.7: Diagramma delle Classi - Layer P2P<br />

Il Layer P2P organizza gli INode esposti dal Layer NET sot<strong>to</strong>stante in<br />

<strong>un</strong>a Membership <strong>di</strong> <strong>Peer</strong> completamente connessi tra loro.<br />

Qui risiedono alc<strong>un</strong>e classi che per nome e f<strong>un</strong>zionalità sono del tut<strong>to</strong> simili<br />

alle controparti presenti nel Layer NET, ma ri<strong>su</strong>ltano finalizzate al contes<strong>to</strong><br />

del Layer P2P: oltre alle classi Setup, Constants e Delegates, vi sono i coman<strong>di</strong><br />

Add<strong>Peer</strong> e TimeSync, entrambi ere<strong>di</strong>tati da P2PCommand.<br />

É presente inoltre <strong>un</strong> sot<strong>to</strong> modulo, che al momen<strong>to</strong> contiene <strong>un</strong>a singola<br />

classe, de<strong>di</strong>ca<strong>to</strong> alla gestione del tempo (si veda la sezione 2.3.1).


78 CAPITOLO 3. IMPLEMENTAZIONE<br />

Infine sono qui implementate le due classi principali che permet<strong>to</strong>no <strong>di</strong> gestire<br />

la Membership: <strong>Peer</strong> e <strong>Peer</strong>Group<br />

La classe <strong>Peer</strong> è composta da <strong>un</strong>’istanza <strong>di</strong> INode che viene invocata per<br />

inviare e ricevere messaggi <strong>di</strong> rete. Contiene inoltre <strong>un</strong>’istanza della classe<br />

<strong>Peer</strong>Group, che tiene traccia <strong>di</strong> tutti i <strong>Peer</strong> conosciuti appartenenti alla<br />

Membership, ed <strong>un</strong>’istanza della classe Time, che viene utilizzata per la gestione<br />

del tempo. A livello <strong>di</strong> f<strong>un</strong>zionalità astrae il Layer NET esponendo<br />

i me<strong>to</strong><strong>di</strong> ConnectTo (), che fa da Wrapper all’omonimo me<strong>to</strong>do <strong>di</strong> INode,<br />

SendTo (), che permette <strong>di</strong> inviare messaggi ad altri <strong>Peer</strong> specificandone il<br />

NetID, e BroadCast () che invia au<strong>to</strong>maticamente <strong>un</strong> messaggio a tutti i <strong>Peer</strong><br />

conosciuti.<br />

Alla creazione <strong>di</strong> <strong>un</strong> ogget<strong>to</strong> <strong>di</strong> tipo <strong>Peer</strong>, viene istanzia<strong>to</strong>, attraverso il<br />

Fac<strong>to</strong>ry del Layer NET, <strong>un</strong> ogget<strong>to</strong> <strong>di</strong> <strong>un</strong>a classe che concretizza l’interfaccia<br />

INode (attualmente quest’ultima è in<strong>di</strong>viduata dalla classe TCPNode).<br />

Viene poi creata <strong>un</strong>’istanza <strong>di</strong> <strong>Peer</strong>Group, alla quale viene aggi<strong>un</strong><strong>to</strong> au<strong>to</strong>maticamente<br />

il riferimen<strong>to</strong> all’INode appena istanzia<strong>to</strong>, ed <strong>un</strong> ogget<strong>to</strong> <strong>di</strong> classe<br />

Time.<br />

Infine vengono registrati i delegati in ascol<strong>to</strong> <strong>su</strong>l Layer NET relativi ai me<strong>to</strong><strong>di</strong><br />

OnConnect(), OnRead() e OnLinksChanged().<br />

Quando viene invoca<strong>to</strong> OnConnect, attraverso il me<strong>to</strong>do AddToKnown-<br />

<strong>Peer</strong>s() viene aggi<strong>un</strong><strong>to</strong> nel proprio <strong>Peer</strong>Group il <strong>Peer</strong> che vi si è appena<br />

connesso.<br />

Inoltre viene notificata l’esistenza <strong>di</strong> quest’ultimo a tutti i gli altri <strong>Peer</strong> conosciuti<br />

(quelli già inclusi nella Membership), tramite il comando Add<strong>Peer</strong>()<br />

parametrizza<strong>to</strong> con il <strong>su</strong>o NetID.<br />

Sull’Exec() <strong>di</strong> Add<strong>Peer</strong>() viene chiama<strong>to</strong> a <strong>su</strong>a volta <strong>un</strong> ConnectTo() verso<br />

il NetID passa<strong>to</strong> come parametro: in ques<strong>to</strong> modo, quando <strong>su</strong>bentra <strong>un</strong><br />

nuovo <strong>Peer</strong> all’interno della Membership, tutti i <strong>Peer</strong> presenti vi si connetteranno<br />

au<strong>to</strong>maticamente (si veda la sezione 2.2).


3.3. LAYER P2P 79<br />

La classe <strong>Peer</strong>Group è quella che, associata alla classe <strong>Peer</strong>, concretizza il<br />

concet<strong>to</strong> <strong>di</strong> Membership.<br />

Si presenta come <strong>un</strong> piccolo Manager che gestisce <strong>un</strong>a lista <strong>di</strong> identifica<strong>to</strong>ri<br />

(NetID) sot<strong>to</strong> forma <strong>di</strong> stringhe: non è quin<strong>di</strong> vincola<strong>to</strong> dall’implementazione<br />

della classe <strong>Peer</strong>. Fornisce inoltre due me<strong>to</strong><strong>di</strong> <strong>di</strong> serializzazione e deserializzazione<br />

che consen<strong>to</strong>no <strong>di</strong> trasformare in stringa (e viceversa) CSV 5 la lista<br />

<strong>di</strong> identifica<strong>to</strong>ri, per poter essere facilmente scambiata, attraverso il Layer<br />

NET, tra due <strong>Peer</strong>.<br />

Figura 3.8: Classi principali- Layer P2P<br />

5 Comma-Separated Values


80 CAPITOLO 3. IMPLEMENTAZIONE<br />

3.3.1 Modulo Time<br />

Il modulo Time è attualmente compos<strong>to</strong> da <strong>un</strong>’<strong>un</strong>ica classe: Time. Questa<br />

contiene <strong>un</strong>a lista <strong>di</strong> TimeSpan (.NET Framework) in<strong>di</strong>cizzati per NetID,<br />

ed espone alc<strong>un</strong>i me<strong>to</strong><strong>di</strong> accessori per la <strong>su</strong>a gestione: AddDelta (), GetDelta<br />

() e GetAllDeltas ().<br />

Implementa inoltre <strong>un</strong> me<strong>to</strong>do polimorfo Convert () che permette <strong>di</strong> convertire,<br />

laddove possibile, TimeStamp calcolati <strong>su</strong>lla base temporale <strong>di</strong> altri<br />

<strong>Peer</strong> rispet<strong>to</strong> al proprio (si veda 2.3.1).<br />

Infine, grazie al me<strong>to</strong>do Now() è possibile ricavare il proprio TimeStamp.<br />

Tale me<strong>to</strong>do utilizza la proprietà statica del .NET framework DateTime.Now.<br />

In fase <strong>di</strong> debug e <strong>di</strong> analisi delle prestazioni, è ri<strong>su</strong>lta<strong>to</strong> mol<strong>to</strong> utile aggi<strong>un</strong>gere<br />

2 fat<strong>to</strong>ri alea<strong>to</strong>ri: il primo emula <strong>un</strong>a <strong>di</strong>fferente timezone (od <strong>un</strong> <strong>di</strong>fferente<br />

settaggio dell’orario <strong>di</strong> sistema), mentre il secondo introduce <strong>un</strong> fat<strong>to</strong>re <strong>di</strong><br />

Lag tra 0 e 1000 millisecon<strong>di</strong>.<br />

La lista contenuta in Time viene popolata perio<strong>di</strong>camente grazie al comando<br />

TimeSync: ogni <strong>Peer</strong> invia agli altri <strong>Peer</strong> conosciuti <strong>un</strong> comando<br />

TimeSync contenente il proprio TimeStamp. Quando ques<strong>to</strong> viene ricevu<strong>to</strong>,<br />

verrà esegui<strong>to</strong> quan<strong>to</strong> implementa<strong>to</strong> nel <strong>su</strong>o me<strong>to</strong>do Exec(), ovvero verrà<br />

calcola<strong>to</strong> il delta tra il TimeStamp ricevu<strong>to</strong> e quello ri<strong>to</strong>rna<strong>to</strong> dal me<strong>to</strong>do<br />

Now() relativo all’istanza Time appartenente al <strong>Peer</strong> destinatario. Quin<strong>di</strong><br />

inseri<strong>to</strong> nella lista, in<strong>di</strong>cizza<strong>to</strong> utilizzando il NetID del mittente.<br />

3.4 Modulo SharedComponents<br />

Il modulo si basa <strong>su</strong>l concet<strong>to</strong> <strong>di</strong> SharedComponent, implementa<strong>to</strong> nell’omonima<br />

classe. Le istanze <strong>di</strong> tale classe sono gestite e memorizzate in<br />

<strong>un</strong>’apposi<strong>to</strong> Manager (ISharedComponentsManager), e create da <strong>un</strong>’apposi<strong>to</strong><br />

Fac<strong>to</strong>ry (ISharedComponentsFac<strong>to</strong>ry).


3.4. MODULO SHAREDCOMPONENTS 81<br />

Figura 3.9: Diagramma delle Classi - Modulo SharedComponents


82 CAPITOLO 3. IMPLEMENTAZIONE<br />

Come illustra<strong>to</strong> nel capi<strong>to</strong>lo 2.4, ogni SharedComponent è identifica<strong>to</strong> da<br />

<strong>un</strong> GlobalID, qui implementa<strong>to</strong> attraverso l’attribu<strong>to</strong> ID ed <strong>un</strong> Value, qui<br />

rappresenta<strong>to</strong> sot<strong>to</strong> forma <strong>di</strong> stringa nell’attribu<strong>to</strong> SerializedValue: tipicamente,<br />

com<strong>un</strong>que, ogni classe che ere<strong>di</strong>ta da SharedComponents contiene al<br />

<strong>su</strong>o interno <strong>un</strong>a variabile privata appositamente tipizzata, a<strong>di</strong>bita alla memorizzazione<br />

del valore vero e proprio.<br />

Facoltativamente possono essere valorizzati anche gli attributi ParentID e<br />

LocalID, se l’istanza <strong>di</strong> SharedComponent si tratta <strong>di</strong> <strong>un</strong> sot<strong>to</strong>-componente.<br />

Inoltre ogni istanza <strong>di</strong> SharedComponent può essere “taggata” per essere raggruppata,<br />

in<strong>di</strong>viduata o filtrata in maniera efficace.<br />

Dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista f<strong>un</strong>zionale, sono presenti quattro me<strong>to</strong><strong>di</strong> virtuali <strong>di</strong><br />

inizializzazione: il primo, Initialize(), chiama in sequenza gli altri tre: InitializeClass(),<br />

InitializeSubComponents() e InitializeUpdate(). Possono <strong>su</strong>bire<br />

quin<strong>di</strong> <strong>un</strong>’override nel caso le operazioni <strong>di</strong> default non implementino le f<strong>un</strong>zionalità<br />

richieste, o lo facciano solo in parte.<br />

Ad esempio il componente Object3D esegue sia <strong>un</strong> override <strong>di</strong> Initialize-<br />

Class(), nel quale viene aggi<strong>un</strong><strong>to</strong> <strong>un</strong> Tag “View” dal momen<strong>to</strong> che si tratta<br />

<strong>di</strong> <strong>un</strong> componente au<strong>to</strong>maticamente lega<strong>to</strong> ad <strong>un</strong> elemen<strong>to</strong> grafico, sia <strong>un</strong><br />

override <strong>di</strong> InitializeSubComponents() per istanziare i due sot<strong>to</strong>componenti<br />

Vec<strong>to</strong>r3 Position e Vec<strong>to</strong>r3 Rotation. Ogni componente, <strong>di</strong> default, è tagga<strong>to</strong><br />

con il tag Constants.ComponentTag NotifyChange, che ne attiva la notifica<br />

au<strong>to</strong>matica <strong>su</strong>lle mo<strong>di</strong>fiche apportate al valore del componente stesso.<br />

La f<strong>un</strong>zione <strong>di</strong> InitializeUpdate() è strettamente legata al me<strong>to</strong>do virtuale<br />

Update(): <strong>di</strong> default infatti, se il componente che ere<strong>di</strong>ta da SharedComponent<br />

esegue <strong>un</strong> override <strong>di</strong> Update, in InitializeUpdate ques<strong>to</strong> verrà registra<strong>to</strong><br />

nel proprio Manager <strong>di</strong> appartenenza come componente da aggiornare ad<br />

ogni iterazione.<br />

SharedComponent espone inoltre <strong>un</strong>a serie <strong>di</strong> me<strong>to</strong><strong>di</strong> accessori per la gestione<br />

au<strong>to</strong>matizzata dei sot<strong>to</strong>-componenti (Add(), Remove(), FindByLocalID(),


3.4. MODULO SHAREDCOMPONENTS 83<br />

FindByGlobalID() e FindByType()) e per la gestione dei Tags (Tag Add(),<br />

Tag Remove() e Tag Has()).<br />

Infine è presente <strong>un</strong> me<strong>to</strong>do virtuale OnChange(), au<strong>to</strong>maticamente invoca<strong>to</strong><br />

ogniqualvolta viene mo<strong>di</strong>fica<strong>to</strong> il Value del componente. In ques<strong>to</strong> me<strong>to</strong>do,<br />

se si tratta <strong>di</strong> <strong>un</strong> proprio componente (non appartenente ad <strong>un</strong> contes<strong>to</strong><br />

esterno, quin<strong>di</strong>) e se ques<strong>to</strong> è tagga<strong>to</strong> con Constants.ComponentTag NotifyChange,<br />

allora viene chiamata la f<strong>un</strong>zione NotifyChange() del SharedComponentsManager.<br />

La classe SharedComponentsManager ha la f<strong>un</strong>zione principale <strong>di</strong> mantenere<br />

e gestire la lista <strong>di</strong> tutte le istanze <strong>di</strong> SharedComponent, sia quelle create<br />

<strong>di</strong>rettamente dal proprio Fac<strong>to</strong>ry (<strong>un</strong> ogget<strong>to</strong> <strong>di</strong> <strong>un</strong>a classe che concretizza<br />

ISharedComponentsFac<strong>to</strong>ry), che quelle provenienti da <strong>un</strong> contes<strong>to</strong> esterno.<br />

É identificata da <strong>un</strong> Name. Quest’ultimo sarà estremamente importante per<br />

la gestione del contes<strong>to</strong> logico introdotta dal Layer Logic.<br />

Sono inoltre implementati i seguenti me<strong>to</strong><strong>di</strong> ausiliari:<br />

• FindByGlobalID(): per cercare <strong>un</strong> componente all’interno della lista<br />

conoscendo il solo GlobalID.<br />

• GetOnlyMine(): per ricavare solo i propri componenti, cioè quelli <strong>di</strong>rettamente<br />

generati dal proprio Fac<strong>to</strong>ry.<br />

• IsMine(): per sapere se il componente passa<strong>to</strong> come parametro, appartiene<br />

o meno a ques<strong>to</strong> Manager.<br />

• AddToUpdater(): aggi<strong>un</strong>ge il componente passa<strong>to</strong> come parametro alla<br />

lista dei componenti da aggiornare ad ogni iterazione.<br />

• RemoveFromUpdater(): rimuove il componente passa<strong>to</strong> come parametro<br />

dalla lista dei componenti da aggiornare ad ogni iterazione.


84 CAPITOLO 3. IMPLEMENTAZIONE<br />

• Update(): il me<strong>to</strong>do da chiamare ad ogni iterazione per aggiornare tutti<br />

i componenti registrati.<br />

Infine vi sono i quattro me<strong>to</strong><strong>di</strong> utilizzati per invocare gli eventi OnCreate,<br />

OnChange, OnActive e OnDestroy.<br />

OnCreate viene invoca<strong>to</strong>, attraverso il Fac<strong>to</strong>ry, <strong>su</strong>lla creazione <strong>di</strong> <strong>un</strong> proprio<br />

componente, mentre OnDestroy viene invoca<strong>to</strong>, sempre attraverso il Fac<strong>to</strong>ry,<br />

<strong>su</strong>lla <strong>su</strong>a <strong>di</strong>struzione. OnChange viene invoca<strong>to</strong> quando cambia il valore <strong>di</strong><br />

<strong>un</strong> proprio componente, e OnActive quando quest’ultimo cambia sta<strong>to</strong> e <strong>di</strong>venta<br />

attivo (cioè quando ogni <strong>su</strong>o eventuale sot<strong>to</strong>-componente è sta<strong>to</strong> crea<strong>to</strong><br />

ed inizializza<strong>to</strong>). Tali eventi verranno poi ascoltati dal Layer Logic, che si<br />

occuperà <strong>di</strong> propagarne la loro notifica attraverso la rete.<br />

La classe SharedComponentFac<strong>to</strong>ry viene utilizzata per creare e <strong>di</strong>struggere<br />

istanze <strong>di</strong> SharedComponents.<br />

Quando il componente da creare appartiene al Manager lega<strong>to</strong> all’istanza del<br />

Fac<strong>to</strong>ry in questione, allora verrà crea<strong>to</strong> attraverso il mo<strong>to</strong>do Create().<br />

Quando invece il componente da creare appartiene ad <strong>un</strong> altro contes<strong>to</strong> (tipicamente<br />

sono copie <strong>di</strong> componenti appartenenti ad altri <strong>Peer</strong>), allora viene<br />

invoca<strong>to</strong> il me<strong>to</strong>do CreateFromOtherContext().<br />

3.5 Layer Logic<br />

Il Layer Logic è sostanzialmente <strong>di</strong>viso in due regioni, <strong>di</strong>fferenziate dal<br />

livello <strong>di</strong> generalizzazione implici<strong>to</strong> nelle classi che ne fanno parte.<br />

La regione più Generic Oriented introduce il contes<strong>to</strong> logico, in<strong>di</strong>vidua<strong>to</strong> dalla<br />

classe <strong>Peer</strong>Context: questa <strong>un</strong>isce le f<strong>un</strong>zionalità esposte dal Layer P2P e<br />

quelle caratteristiche del Data Layer rappresenta<strong>to</strong> dal modulo SharedComponents.<br />

La classe <strong>Peer</strong>Context, infatti, é composta da <strong>un</strong>’istanza <strong>di</strong> <strong>Peer</strong> e <strong>un</strong>a <strong>di</strong><br />

SharedcomponentsManager; queste ri<strong>su</strong>ltano legate tra loro tramite il mede-


3.5. LAYER LOGIC 85<br />

Figura 3.10: Classi Principali - Modulo SharedComponents


86 CAPITOLO 3. IMPLEMENTAZIONE<br />

Figura 3.11: Diagramma delle Classi - Layer Logic


3.6. LAYER VIEW 87<br />

simo identificativo: l’attribu<strong>to</strong> NetID dell’istanza <strong>di</strong> <strong>Peer</strong> e l’attribu<strong>to</strong> Name<br />

dell’istanza <strong>di</strong> SharedComponentsManager hanno lo stesso valore.<br />

Tale vincolo ha l’effet<strong>to</strong> implici<strong>to</strong> <strong>di</strong> estendere la proprietà <strong>di</strong> <strong>un</strong>o SharedComponent,<br />

non più al solo Manager ma anche all’intero <strong>Peer</strong>.<br />

Sono inoltre implementati i Commands che permet<strong>to</strong>no la sincronizzazione<br />

au<strong>to</strong>matica del DataLayer tra i <strong>di</strong>versi <strong>Peer</strong> ( CreateComponent, Update-<br />

Component, ActivateComponent e SendToComponent) ed i componenti che<br />

consen<strong>to</strong>no <strong>di</strong> rappresentare le informazioni più com<strong>un</strong>i per l’identificazione<br />

si <strong>un</strong> elemen<strong>to</strong> grafico all’interno <strong>di</strong> <strong>un</strong> generico videogioco tri<strong>di</strong>mensionale<br />

(Object3D e MovingObject3D).<br />

La seconda regione è più <strong>Game</strong> Oriented, nel senso che da qui in poi iniziano<br />

a presentarsi classi che implementano logiche strettamente legate alle<br />

specifiche <strong>di</strong> gioco e alle relative <strong>di</strong>namiche <strong>di</strong> <strong>Game</strong>Play.<br />

Qui si trova la classe PlayerContext, ere<strong>di</strong>tata da <strong>Peer</strong>Context, che da <strong>un</strong>a<br />

parte astrae il contes<strong>to</strong> lega<strong>to</strong> al concet<strong>to</strong> <strong>di</strong> “<strong>Peer</strong>”, limitandolo a quello<br />

più specifico <strong>di</strong> Player, e dall’altra implementa <strong>un</strong>a serie <strong>di</strong> logiche che caratterizzano<br />

quest’ultimo: ad esempio viene esegui<strong>to</strong> <strong>un</strong> override <strong>su</strong>l me<strong>to</strong>do<br />

Join, nel quale viene istanzia<strong>to</strong> <strong>un</strong> componente <strong>di</strong> tipo Character; in ques<strong>to</strong><br />

modo, quando inizia la partita, ogni Player creerà au<strong>to</strong>maticamente nel proprio<br />

contes<strong>to</strong> logico <strong>un</strong>’istanza Character, la quale sarà quin<strong>di</strong> con<strong>di</strong>visa tra<br />

tutti i <strong>Peer</strong>.<br />

3.6 Layer View<br />

Come evidenzia<strong>to</strong> nel capi<strong>to</strong>lo 2.6, il Layer View è mol<strong>to</strong> vas<strong>to</strong>, e fa fronte<br />

ad <strong>un</strong> notevole numero <strong>di</strong> problematiche e f<strong>un</strong>zionalità, molte delle quali non<br />

sono strettamente connesse all’argomen<strong>to</strong> <strong>di</strong> tesi.<br />

Aspetti come il Rendering, la gestione degli Input, la gestione della riprodu-


88 CAPITOLO 3. IMPLEMENTAZIONE<br />

Figura 3.12: Classi Principali - Layer Logic


3.6. LAYER VIEW 89<br />

Figura 3.13: Diagramma delle Classi - Layer View


90 CAPITOLO 3. IMPLEMENTAZIONE<br />

zione Au<strong>di</strong>o e la simulazione della fisica, sono infatti delegati agli strumenti<br />

messi a <strong>di</strong>sposizione da Unity3D.<br />

Quest’ultimo permette <strong>di</strong> definire i comportamenti che caratterizzano gli elementi<br />

presenti nella scena, me<strong>di</strong>ante <strong>un</strong> sistema <strong>di</strong> “Scripting” basa<strong>to</strong> <strong>su</strong>lla<br />

classe “Behaviour”.<br />

La classe principale, ContexView, concretizza il contes<strong>to</strong> “View” e fa da<br />

“Bridge” tra ques<strong>to</strong> ed il contes<strong>to</strong> “Logic” via composition. Ri<strong>su</strong>lta essere<br />

quin<strong>di</strong> il p<strong>un</strong><strong>to</strong> d’accesso a tutti i Layer sot<strong>to</strong>stanti (Figura 3.14).<br />

Figura 3.14: Catena dei Layer, legati via composition<br />

Parallelamente la classe ViewContextSync, estesa dalla classe Behaviour,<br />

si occupa della sincronizzazione tra il contes<strong>to</strong> logico e quello vi<strong>su</strong>ale.<br />

Ad ogni iterazione, infatti, esegue <strong>un</strong> polling <strong>su</strong>l Data Layer, controllando<br />

che non vi siano componenti logici taggati con il tag “View” senza <strong>un</strong>a<br />

rispettiva controparte vi<strong>su</strong>ale all’interno della scena 3D. Quando ciò accade,<br />

viene istanzia<strong>to</strong> au<strong>to</strong>maticamente <strong>un</strong> elemen<strong>to</strong> grafico ed applicata ad esso<br />

<strong>un</strong>a classe (che segue la naming convention “[nome componente]Script”),<br />

estesa da ComponentScript (Behaviour), che ne definisce il comportamen<strong>to</strong><br />

(si veda 2.6).<br />

La classe ComponentScript è definita secondo il seguente schema:


3.6. LAYER VIEW 91<br />

• String LogicComponentID: attribu<strong>to</strong> al quale viene assegna<strong>to</strong> il valore<br />

del GlobalID appartenente allo SharedComponent che rappresenta lo<br />

sta<strong>to</strong> logico dell’elemen<strong>to</strong> grafico.<br />

• Update(): il me<strong>to</strong>do che viene invoca<strong>to</strong> ad ogni iterazione. Il <strong>su</strong>o comportamen<strong>to</strong><br />

<strong>di</strong> default, eventualmente mo<strong>di</strong>ficabile via override, prevede<br />

la chiamata <strong>di</strong> Update Writer() se lo SharedComponent assegna<strong>to</strong><br />

appartiene al contes<strong>to</strong> logico del Player. In caso contrario viene chiama<strong>to</strong><br />

Update Reader(). Infine, attraverso CheckDestroy(), viene verificata<br />

l’esistenza del componente logico all’interno del Data Layer:<br />

se ques<strong>to</strong> non è più presente, allora verrà <strong>di</strong>strut<strong>to</strong> l’elemen<strong>to</strong> grafico<br />

corrispondente (e <strong>di</strong> conseguenza anche il relativo ComponentScript)<br />

Ad esempio, il ComponentScript relativo al componente <strong>di</strong> tipo Character<br />

(cioè la classe CharacterScript), all’interno del me<strong>to</strong>do Update Writer()<br />

eseguirà l’aggiornamen<strong>to</strong> perio<strong>di</strong>co delle coor<strong>di</strong>nate e della rotazione del personaggio<br />

controlla<strong>to</strong> dal Player, mentre nel me<strong>to</strong>do Update Reader() vi sarà<br />

implementata <strong>un</strong>a logica <strong>di</strong> Dead Reckoning (Figura 3.15).<br />

Figura 3.15: CharacterScript


92 CAPITOLO 3. IMPLEMENTAZIONE


Capi<strong>to</strong>lo 4<br />

Analisi delle prestazioni<br />

Il contes<strong>to</strong> nel quale è sta<strong>to</strong> sviluppa<strong>to</strong> il proget<strong>to</strong> rende <strong>di</strong>fficol<strong>to</strong>sa l’in<strong>di</strong>viduazione<br />

<strong>di</strong> parametri e delle relative mi<strong>su</strong>razioni che si possono effettuare,<br />

invece, in scenari più ampi e strutturati. Mi<strong>su</strong>re derivanti da fat<strong>to</strong>ri come<br />

la latenza, la <strong>su</strong>a variazione ed il numero <strong>di</strong> gioca<strong>to</strong>ri non sono facilmente<br />

simulabili in modo realistico in <strong>un</strong> contes<strong>to</strong> locale.<br />

In ques<strong>to</strong> senso è sta<strong>to</strong> implementa<strong>to</strong> <strong>un</strong> sistema che consente <strong>di</strong> simulare la<br />

presenza <strong>di</strong> Lag tra i <strong>di</strong>versi <strong>Peer</strong> che compongono la Membership, ritardando<br />

l’esecuzione dei coman<strong>di</strong> inviati e ricevuti.<br />

Introducendo infatti <strong>un</strong> valore <strong>di</strong> latenza relativamente al<strong>to</strong> (200 / 500<br />

millisecon<strong>di</strong>) in <strong>un</strong>o dei <strong>Peer</strong> connessi alla Membership <strong>di</strong> prova è sta<strong>to</strong> possibile<br />

ricavare alc<strong>un</strong>e considerazioni qualitative:<br />

I processi <strong>di</strong> interazione che coinvolgono elementi (SharedComponent) gestiti<br />

dal <strong>Peer</strong> sogget<strong>to</strong> a Lag, ri<strong>su</strong>ltano rallentati <strong>su</strong> tutti i <strong>Peer</strong>.<br />

Mentre, dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista del <strong>Peer</strong> sogget<strong>to</strong> a Lag, tale ritardo si ripercuote<br />

<strong>su</strong> qualsiasi tipo <strong>di</strong> aggiornamen<strong>to</strong> proveniente dagli altri <strong>Peer</strong>.<br />

Come era preve<strong>di</strong>bile, l’esperienza <strong>di</strong> gioco ri<strong>su</strong>lta quin<strong>di</strong> essere abbastanza<br />

compromessa, specialmente per i <strong>Peer</strong> con la latenza più elevata.<br />

Un primo scenario analizzabile quantitativamente in <strong>un</strong> contes<strong>to</strong> locale<br />

può essere in<strong>di</strong>vidua<strong>to</strong> nella mi<strong>su</strong>razione del tempo trascorso tra l’invio <strong>di</strong> <strong>un</strong><br />

93


94 CAPITOLO 4. ANALISI DELLE PRESTAZIONI<br />

messaggio da parte <strong>di</strong> <strong>un</strong> <strong>Peer</strong> e la <strong>su</strong>a esecuzione da parte degli altri <strong>Peer</strong><br />

appartenenti alla Membership. Ques<strong>to</strong> prova è stata eseguita istanziando<br />

10 oggetti <strong>di</strong> classe <strong>Peer</strong>Context (si veda la sezione 3.5): Il “<strong>Peer</strong> 1 ” invia 7<br />

aggiornamenti consecutivi <strong>di</strong> <strong>un</strong> componente presente nel proprio Data Layer,<br />

incrementandone ogni volta il valore all’interno <strong>di</strong> <strong>un</strong> ciclo For.<br />

In Figura 4.1 sono riportati i ri<strong>su</strong>ltati sot<strong>to</strong>forma <strong>di</strong> grafico a <strong>di</strong>spersione: i<br />

<strong>di</strong>versi stati <strong>di</strong> gioco (in ques<strong>to</strong> caso limitati al valore del singolo componente<br />

mo<strong>di</strong>fica<strong>to</strong>) sono rappresentati da linee curve che interpolano i p<strong>un</strong>ti nei quali<br />

i <strong>di</strong>versi <strong>Peer</strong> (linee verticali) eseguono l’aggiornamen<strong>to</strong> del componente in<br />

questione.<br />

Figura 4.1: Tempo <strong>di</strong> ricezione ed esecuzione <strong>di</strong> <strong>un</strong> aggiornamen<strong>to</strong> <strong>di</strong> <strong>un</strong><br />

componente logico<br />

L’esecuzione degli aggiornamenti, nonostante si presenti nel medesimo<br />

or<strong>di</strong>ne <strong>su</strong>i <strong>di</strong>versi <strong>Peer</strong> (grazie all’utilizzo del TCP), non avviene in modo<br />

sincronizza<strong>to</strong>: lo “Sta<strong>to</strong> 5 ”, ad esempio, viene esegui<strong>to</strong> dal “<strong>Peer</strong> 2 ” in T2,


95<br />

e dal “<strong>Peer</strong> 10 ” in T6.<br />

Il TimeSpan preso in esame è com<strong>un</strong>que estremamente ridot<strong>to</strong> (minore <strong>di</strong><br />

<strong>un</strong> millisecondo), e le variazioni riscontrate sono da ricondurre alla politica<br />

con la quale vengono schedulati i Thread <strong>di</strong> lettura e scrittura utilizzati da<br />

ogni <strong>Peer</strong> per com<strong>un</strong>icare con gli altri <strong>Peer</strong> appartenenti alla Membership .<br />

Utilizzando <strong>un</strong> sistema <strong>di</strong> sincronizzazione “S<strong>to</strong>p-And-Wait” (si veda la<br />

sezione ), tali variazioni non si sarebbero riscontrate; o meglio, l’istante <strong>di</strong><br />

tempo <strong>di</strong> esecuzione sarebbe sta<strong>to</strong> com<strong>un</strong>que <strong>di</strong>fferente <strong>su</strong>i <strong>di</strong>versi <strong>Peer</strong>, ma<br />

all’interno <strong>di</strong> <strong>un</strong>o stesso periodo <strong>di</strong> tempo lo sta<strong>to</strong> <strong>di</strong> gioco sarebbe ri<strong>su</strong>lta<strong>to</strong><br />

il medesimo (Figura 4.2).<br />

Figura 4.2: Tempo simula<strong>to</strong> <strong>di</strong> ricezione ed esecuzione <strong>di</strong> <strong>un</strong> aggiornamen<strong>to</strong><br />

<strong>di</strong> <strong>un</strong> componente logico con sistema <strong>di</strong> sincronizzazione S<strong>to</strong>p-And-Wait<br />

Il passo <strong>su</strong>ccessivo è sta<strong>to</strong> quello <strong>di</strong> introdurre nello scenario precedente<br />

la simulazione <strong>di</strong> latenza <strong>di</strong> rete: ogni <strong>Peer</strong> è sta<strong>to</strong> imposta<strong>to</strong> per simulare<br />

<strong>un</strong>a latenza variabile da 5 a 30 millisecon<strong>di</strong>, ad esclusione del “<strong>Peer</strong> 3 ”,


96 CAPITOLO 4. ANALISI DELLE PRESTAZIONI<br />

la cui latenza è stata settata <strong>su</strong>i 100 millisecon<strong>di</strong>. La frequenza <strong>di</strong> invio<br />

degli aggiornamenti è stata abbassata appositamente a 10 millisecon<strong>di</strong> per<br />

consentire <strong>un</strong>a migliore leggibilità del grafico (Figura 4.3).<br />

Figura 4.3: Tempo <strong>di</strong> ricezione ed esecuzione introducendo latenza <strong>di</strong> rete<br />

Come era facile prevedere, il “<strong>Peer</strong> 3 ” riceverà ed eseguirà gli aggiornamenti<br />

in ritardo rispet<strong>to</strong> agli altri <strong>Peer</strong>. L’or<strong>di</strong>ne <strong>di</strong> esecuzione rimane<br />

com<strong>un</strong>que coerente: graficamente ques<strong>to</strong> è visibile dal fat<strong>to</strong> che non sono<br />

presenti linee che si intersecano.<br />

Queste mi<strong>su</strong>razioni sono state effettuate <strong>di</strong>sabilitando il Layer View poichè<br />

la richiesta <strong>di</strong> risorse da parte del Renderer non consentiva l’esecuzione contemporanea<br />

<strong>di</strong> più <strong>di</strong> 4 <strong>Peer</strong>.<br />

Utilizzando Unity3D si è vincolati all’utilizzo <strong>di</strong> <strong>un</strong> <strong>un</strong>ico Thread, <strong>su</strong>l quale<br />

processare alternativamente la logica prima ed il rendering poi; quest’ultimo


97<br />

è in assolu<strong>to</strong> il processo che richiede più risorse, sia a livello <strong>di</strong> utilizzo CPU<br />

che <strong>di</strong> memoria (Figura 4.4).<br />

Figura 4.4: Threads <strong>di</strong> esecuzione: il Thread principale è gesti<strong>to</strong> da Unity3D<br />

e processa alternativamente le <strong>di</strong>namiche logiche e la pipeline <strong>di</strong> rendering.<br />

Per ogni <strong>Peer</strong> appartenente alla Membership vengono inoltre istanziati due<br />

Thread, <strong>un</strong>o <strong>di</strong> lettura e <strong>un</strong>o <strong>di</strong> scrittura.<br />

Successivamente è sta<strong>to</strong> analizza<strong>to</strong> <strong>un</strong>o scenario comprensivo del Layer<br />

View: sono stati mi<strong>su</strong>rati il numero <strong>di</strong> messaggi scambiati tra 4 <strong>Peer</strong> durante<br />

<strong>un</strong>a sessione <strong>di</strong> gioco. Il Update Write() <strong>di</strong> ogni CharacterScript è sta<strong>to</strong><br />

mo<strong>di</strong>fica<strong>to</strong> in modo da produrre aggiornamenti <strong>su</strong>fficientemente realistici per<br />

lo scenario <strong>di</strong> analisi, in maniera au<strong>to</strong>matica, senza cioè che sia richiesta la<br />

presenza <strong>di</strong> <strong>un</strong> gioca<strong>to</strong>re reale, simulando il movimen<strong>to</strong> del Character e la<br />

generazione <strong>di</strong> Bullets.<br />

Da i ri<strong>su</strong>ltati ottenuti è emersa l’esistenza <strong>di</strong> alc<strong>un</strong>e fasi critiche: facendo<br />

riferimen<strong>to</strong> alla Figura 4.5, in T2, T4 e T6 sono in<strong>di</strong>viduabili perio<strong>di</strong> <strong>di</strong> picco,<br />

esponenzialmente crescenti, sia per quan<strong>to</strong> rigurada il numero <strong>di</strong> messaggi


98 CAPITOLO 4. ANALISI DELLE PRESTAZIONI<br />

inviati, che per la durata dei perio<strong>di</strong> stessi, in f<strong>un</strong>zione dell’incremen<strong>to</strong> del<br />

numero dei <strong>Peer</strong> connessi alla Membership. Tali perio<strong>di</strong> sono contestualizzati<br />

all’interno della fase <strong>di</strong> sincronizzazione del Data Layer che avviene conseguentemente<br />

al join <strong>di</strong> <strong>un</strong> nuovo <strong>Peer</strong> all’interno della Membership, nella<br />

quale ogni <strong>Peer</strong> è tenu<strong>to</strong> ad inviare la lista dei propri componenti presenti<br />

nel modulo SharedComponents (capi<strong>to</strong>lo 2). In T1, T3, T5 e T7, invece il<br />

numero <strong>to</strong>tale <strong>di</strong> messaggi scambiati ri<strong>to</strong>rna nel range <strong>di</strong> 0-5 messaggi ogni<br />

0.25 secon<strong>di</strong>. Chiaramente anche quest’ultimo sarà destina<strong>to</strong> a crescere al<br />

crescere del numero <strong>di</strong> <strong>Peer</strong> connessi.<br />

Figura 4.5: Messaggi scambiati in <strong>un</strong>a sessione <strong>di</strong> gioco:


Capi<strong>to</strong>lo 5<br />

Sviluppi futuri<br />

5.1 Anti-Cheating<br />

Per “Cheating” si intende quella attività messa in at<strong>to</strong> da alc<strong>un</strong>i gioca<strong>to</strong>ri<br />

(“Cheaters”) in grado <strong>di</strong> mo<strong>di</strong>ficare l’esperienza <strong>di</strong> gioco e trarne vantaggio.<br />

Per alterare la <strong>di</strong>namica <strong>di</strong> gioco è possibile operare in <strong>di</strong>versi contesti e non<br />

necessariamente a livello software: si pensi ad esempio ad <strong>un</strong> gioco le cui<br />

regole prevedono <strong>un</strong> equo scontro tra N gioca<strong>to</strong>ri. Se alc<strong>un</strong>i <strong>di</strong> questi si coalizzano<br />

tra loro, guadagnano <strong>un</strong> vantaggio <strong>su</strong>i gioca<strong>to</strong>ri che invece non si sono<br />

coalizzati. La <strong>di</strong>namica <strong>di</strong> gioco viene così alterata, e le soluzioni software per<br />

far fronte a ques<strong>to</strong> problema sono, in ques<strong>to</strong> caso (“Cheating by collusion”),<br />

inefficaci.<br />

Tendenzialmente per far fronte a queste tipologie <strong>di</strong> Cheating è necessario<br />

lavorare <strong>di</strong>rettamente <strong>su</strong>l <strong>Game</strong>play, cercando <strong>di</strong> evitare, cioè, <strong>di</strong> far<br />

emergere meccaniche “sociali” <strong>di</strong> ques<strong>to</strong> tipo, ed eventualmente <strong>di</strong>sincentivarle,<br />

rendendole notevolmente svantaggiose per il gioca<strong>to</strong>re che le sfrutta.<br />

Non sempre è possibile: il solo at<strong>to</strong> <strong>di</strong> <strong>di</strong>sconnessione (o logout) durante <strong>un</strong>a<br />

partita, non solo turba pesantemente il flusso e l’asset<strong>to</strong> <strong>di</strong> gioco, ma è anche<br />

impossibile evitare.<br />

99


100 CAPITOLO 5. SVILUPPI FUTURI<br />

Un altro scenario particolarmente interessante che non coinvolge problematiche<br />

e soluzioni software è quello del cosiddet<strong>to</strong> “Gold farming”, ovvero<br />

la compraven<strong>di</strong>ta, esterna al contes<strong>to</strong> <strong>di</strong> gioco, <strong>di</strong> items e abilità virtuali in<br />

cambio <strong>di</strong> denaro reale.<br />

I sistemi <strong>di</strong> Cheating basati <strong>su</strong> exploit software operano <strong>su</strong> <strong>di</strong>versi livelli.<br />

E’ possibile infatti mo<strong>di</strong>ficare il Client in modo da au<strong>to</strong>matizzare alc<strong>un</strong>i processi,<br />

rimpiazzando <strong>di</strong> fat<strong>to</strong> il gioca<strong>to</strong>re, che in ques<strong>to</strong> modo può de<strong>di</strong>carsi<br />

ad altri aspetti <strong>di</strong> gioco: in <strong>un</strong> RTS, <strong>un</strong> Cheat Software può occuparsi della<br />

gestione economica del regno virtuale, lasciando le sezioni <strong>di</strong> combattimen<strong>to</strong><br />

in mano al gioca<strong>to</strong>re, o viceversa. O ancora, si possono vi<strong>su</strong>alizzare dati e<br />

informazioni presenti nel Data Layer ma volutamente nascoste nel Presentation<br />

Layer, ad esempio eliminando la cosiddetta “Fog Of War” e quin<strong>di</strong>, <strong>di</strong><br />

conseguenza, conoscere l’intera area <strong>di</strong> gioco, anche quella inesplorata.<br />

In ambi<strong>to</strong> FPS, invece, i sistemi <strong>di</strong> Cheating più utilizzati sono da <strong>un</strong>a<br />

parte quelli che permet<strong>to</strong>no <strong>di</strong> migliorare le prestazioni del gioca<strong>to</strong>re, attraverso<br />

lo Speed Hacking, che aumenta la velocità del Character, e l’Au<strong>to</strong><br />

Aiming, che ruota la vi<strong>su</strong>ale au<strong>to</strong>maticamente <strong>su</strong>l target più vicino, e dall’altra<br />

quei sistemi che si basano <strong>su</strong>lla riduzione e <strong>su</strong>ll’alterazione della qualità<br />

grafica, in modo tale da evidenziare o vi<strong>su</strong>alizzare elementi grafici altrimenti<br />

poco visibili o ad<strong>di</strong>rittura nascosti.<br />

Tipicamente questa tipologia <strong>di</strong> Cheat opera la<strong>to</strong> Client e pertan<strong>to</strong>, attraverso<br />

sistemi quali P<strong>un</strong>k Buster 1 e AntiTCC, è possibile in qualche modo<br />

limitare la loro azione. Tali sistemi infatti eseguono <strong>un</strong>a scansione locale, sia<br />

a livello <strong>di</strong> FileSystem, verificando l’integrità dei file utilizzati dal videogioco,<br />

che a livello dei processi e relativa memoria. Se la scansione <strong>di</strong> Integrity<br />

Check, solitamente avviata ad inizio e fine partita, o in concomitanza <strong>di</strong> particolari<br />

situazioni <strong>di</strong> gioco, ad esempio <strong>su</strong>bi<strong>to</strong> dopo <strong>un</strong> Frag, fallisce, allora il<br />

1 http://www.evenbalance.com


5.1. ANTI-CHEATING 101<br />

gioca<strong>to</strong>re viene esplulso dalla partita.<br />

Sistemi <strong>di</strong> Cheating come lo Speed Hacking e Au<strong>to</strong> Aiming, però, possono<br />

essere implementati anche ad <strong>un</strong> livello inferiore rispet<strong>to</strong> a quello applicativo<br />

in<strong>di</strong>vidua<strong>to</strong> dal Client. Utilizzando appositi programmi esterni è infatti<br />

possibile moni<strong>to</strong>rare e mo<strong>di</strong>ficare ogni singolo pacchet<strong>to</strong> invia<strong>to</strong> al Server al<br />

fine <strong>di</strong> trarne <strong>un</strong> vantaggio nel contes<strong>to</strong> delle <strong>di</strong>namiche <strong>di</strong> gioco.<br />

In <strong>un</strong>’architettura Client-Server si tende a delegare la logica <strong>di</strong> gioco ed<br />

i relativi controlli <strong>su</strong>l Server poichè si pre<strong>su</strong>me sia <strong>un</strong>’entità “trusted”, limitando<br />

il più possibile i Clients a quelle che sono le operazioni meno sensibili<br />

dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista dell’avanzamen<strong>to</strong> dello sta<strong>to</strong> <strong>di</strong> gioco.<br />

In <strong>un</strong>a logica <strong>Peer</strong>-To-<strong>Peer</strong>, la mancanza <strong>di</strong> <strong>un</strong> asset<strong>to</strong> centralizza<strong>to</strong> porta ad<br />

avere come <strong>un</strong>ici elementi potenzialmente “trusted” gli stessi <strong>Peer</strong>.<br />

In <strong>un</strong>a rete au<strong>to</strong>gestita, ques<strong>to</strong> implica da <strong>un</strong>a parte <strong>un</strong> sistema <strong>di</strong> Cheatdetection<br />

<strong>su</strong> ogni singolo <strong>Peer</strong>, e dall’altra <strong>un</strong>’organizzazione interna alla Memebership<br />

in grado <strong>di</strong> in<strong>di</strong>viduare <strong>un</strong>’au<strong>to</strong>rità a<strong>di</strong>bita al Cheat-management.<br />

Inoltre sistemi <strong>di</strong> sincronizizzazione temporale, come la Bucket Synchronization,<br />

possono essere aggirati sfruttando il ritardo tra la ricezione <strong>di</strong> eventi<br />

provenienti dagli altri <strong>Peer</strong> e la loro effettiva esecuzione: <strong>un</strong> <strong>Peer</strong> può ad esempio<br />

inviare <strong>un</strong> even<strong>to</strong> opport<strong>un</strong>amente crea<strong>to</strong> bastandosi <strong>su</strong>lle “intenzioni”<br />

ricevute ma non ancora eseguite (Look Ahead Cheat). O più semplicemente<br />

mo<strong>di</strong>ficare il TimeStamp <strong>di</strong> <strong>un</strong> even<strong>to</strong> così da ri<strong>su</strong>ltare essere sta<strong>to</strong> invia<strong>to</strong><br />

in <strong>un</strong> istante <strong>di</strong> tempo precedente (TimeStamp Cheat).<br />

Di segui<strong>to</strong> viene proposta l’implementazione <strong>di</strong> <strong>un</strong> Modulo de<strong>di</strong>ca<strong>to</strong> al<br />

Cheat-detection: come anticipa<strong>to</strong> nel capi<strong>to</strong>lo 1, tipicamente i MOGs che si<br />

basano <strong>su</strong> <strong>un</strong> modello <strong>Peer</strong>-To-<strong>Peer</strong> vengono <strong>su</strong>pportati com<strong>un</strong>que da <strong>un</strong>’architettura<br />

centralizzata, utilizzata come p<strong>un</strong><strong>to</strong> d’accesso alle partite, ed eventualmente<br />

come au<strong>to</strong>rità per la gestione dell’Anti-Cheating. Il contes<strong>to</strong> in<strong>di</strong>vidua<strong>to</strong><br />

del proget<strong>to</strong> <strong>di</strong> tesi, invece, non contempla ques<strong>to</strong> tipo <strong>di</strong> <strong>su</strong>ppor<strong>to</strong>.


102 CAPITOLO 5. SVILUPPI FUTURI<br />

Tale mancanza sposta il problema del Cheat-detection da <strong>un</strong> livello <strong>su</strong>periore<br />

al livello della <strong>Game</strong> Logic.<br />

Infatti è possibile estendere la classe ComponentScript, aggi<strong>un</strong>gendo la<br />

chiamata <strong>di</strong> <strong>un</strong>a f<strong>un</strong>zione astratta CheatDetection() all’interno del me<strong>to</strong>do<br />

Update Reader(). Eseguendo <strong>un</strong> Override <strong>di</strong> ques<strong>to</strong> me<strong>to</strong>do, a seconda delle<br />

caratteristiche del componente associa<strong>to</strong> al ComponentScript, si possono<br />

eseguire determinati controlli specifici atti a controllare la coerenza delle<br />

informazioni gi<strong>un</strong>te da altri <strong>Peer</strong>.<br />

Per quan<strong>to</strong> riguarda il Cheat-management è necessario implementare <strong>un</strong><br />

sistema “democratico” in grado <strong>di</strong> prendere decisioni quali, ad esempio,<br />

l’espulsione <strong>di</strong> <strong>un</strong> determina<strong>to</strong> <strong>Peer</strong> dalla Membership.<br />

Un sistema potrebbe essere quello <strong>di</strong> attribuire ad ogni Player <strong>un</strong> p<strong>un</strong>teggio<br />

<strong>di</strong> “Fairness”. Quando, in <strong>un</strong>a specifica implementazione <strong>di</strong> Cheat-<br />

Detection(), viene rilevata <strong>un</strong>’incoerenza sospetta tale p<strong>un</strong>teggio viene decrementa<strong>to</strong>.<br />

Ogni Player attribuisce agli altri Player <strong>un</strong>a propria visione <strong>di</strong><br />

Fairness: non è det<strong>to</strong>, cioè, che il p<strong>un</strong>teggio <strong>di</strong> “Fairness” appartenente al<br />

Player B, secondo il Player A, sia lo stesso attribui<strong>to</strong>gli dal Player C.<br />

Il p<strong>un</strong>teggio <strong>di</strong> Fairness attribu<strong>to</strong> da ogni Player ad ogni Player, dal<br />

momen<strong>to</strong> che deve rappresentare <strong>un</strong>’informazione costantemente con<strong>di</strong>visa,<br />

può prendere forma nel Data Layer, sot<strong>to</strong> forma <strong>di</strong> SharedComponent, e<br />

gesti<strong>to</strong> da <strong>un</strong>’apposi<strong>to</strong> modulo de<strong>di</strong>ca<strong>to</strong> all’Anti-Cheating.<br />

In ques<strong>to</strong> modo ogni Player può conoscere il p<strong>un</strong>teggio <strong>di</strong> Fairness globale<br />

(cioè la somma <strong>di</strong> tutti i p<strong>un</strong>teggi <strong>di</strong> Fairness che ogni singolo <strong>Peer</strong> attribuisce<br />

ad <strong>un</strong> determina<strong>to</strong> Player sospetta<strong>to</strong> <strong>di</strong> Cheating), e se ques<strong>to</strong> è al <strong>di</strong> sot<strong>to</strong> <strong>di</strong><br />

<strong>un</strong>a certa soglia <strong>di</strong> <strong>to</strong>lleranza, il Player incrimina<strong>to</strong> sarà rimosso dalla visione<br />

della Membership <strong>di</strong> ogni <strong>Peer</strong> (Figura 5.1).<br />

Ques<strong>to</strong> tipo <strong>di</strong> meccaniche <strong>di</strong> Cheat-management decentralizzate e au<strong>to</strong>gestite,<br />

non può però f<strong>un</strong>zionare in <strong>un</strong> contes<strong>to</strong> <strong>Peer</strong>-To-<strong>Peer</strong> nel quale la<br />

maggioranza dei Player fa uso <strong>di</strong> Cheats.<br />

Se si considera, inoltre, che le valutazioni <strong>di</strong> Cheat-Detection vengono eseguite<br />

<strong>su</strong> specifiche informazioni provenienti da generici messaggi in entata,


5.1. ANTI-CHEATING 103<br />

Figura 5.1: Il valore <strong>di</strong> Fairness attribu<strong>to</strong> al Player B dai Player A, C, D ed<br />

E è rispettivamente <strong>di</strong> -12, -9, -10 e 1 p<strong>un</strong>ti. La somma <strong>di</strong> tali valori è minore<br />

<strong>di</strong> zero, e per tan<strong>to</strong> il Player B viene escluso dalla Membership


104 CAPITOLO 5. SVILUPPI FUTURI<br />

senza <strong>un</strong> <strong>su</strong>ppor<strong>to</strong> la<strong>to</strong> Client (come l’Integrity Check esegui<strong>to</strong> da AntiTCC )<br />

ed <strong>un</strong> <strong>su</strong>ppor<strong>to</strong> la<strong>to</strong> server (come gestione e tracciamen<strong>to</strong> degli utenti malevoli),<br />

e dal momen<strong>to</strong> che alc<strong>un</strong>i comportamenti sospetti potrebbero essere<br />

causati dalla latenza, dalla <strong>su</strong>a variazione, e dalla congestione <strong>di</strong> rete, tali<br />

sistemi non possono mirare all’eliminazione del problema <strong>di</strong> Cheating, ma<br />

rappresentano solo <strong>un</strong> tentativo at<strong>to</strong> ad arginarne gli effetti.<br />

5.1.1 Time Based Cheating<br />

Come illustra<strong>to</strong> nel capi<strong>to</strong>lo 2.3.1, perio<strong>di</strong>camente ogni <strong>Peer</strong>, tramite il<br />

comando TimeSync, richiede agli altri <strong>Peer</strong> appartenenti alla Membership<br />

<strong>di</strong> notificare il valore del proprio TimeStamp, cosicché vi si possa possa<br />

calcolare, e memorizzare, il delta relativo.<br />

Quando viene memorizza<strong>to</strong> il nuovo valore <strong>di</strong> tale delta, ques<strong>to</strong> teoricamente<br />

non dovrebbe <strong>di</strong>scostarsi troppo dal valore memorizza<strong>to</strong> precedentemente.<br />

Se questa <strong>di</strong>fferenza è maggiore <strong>di</strong> <strong>un</strong>a certa soglia (che tiene con<strong>to</strong><br />

<strong>di</strong> eventuali oscillazioni dovute al Lag e Jitter), allora viene <strong>di</strong>minu<strong>to</strong> il<br />

p<strong>un</strong>teggio <strong>di</strong> Fairness relativo al <strong>Peer</strong> “sospetta<strong>to</strong>” <strong>di</strong> cheating.<br />

La soglia <strong>di</strong> <strong>to</strong>lleranza, sot<strong>to</strong> ques<strong>to</strong> aspet<strong>to</strong>, può anche essere relativamente<br />

alta, poiché a ques<strong>to</strong> livello, il sistema <strong>di</strong> Timing deve semplicemente<br />

garantire <strong>un</strong>a velocità <strong>di</strong> esecuzione “simile” <strong>su</strong> ogni <strong>Peer</strong>. Non deve essere<br />

possibile, quin<strong>di</strong>, avere <strong>un</strong> <strong>Peer</strong> A il cui tempo avanza a velocità N ed <strong>un</strong>’altro<br />

<strong>Peer</strong> B il cui tempo invece avanza a velocità 2N. Dal momen<strong>to</strong> che ogni<br />

singolo comando in grado <strong>di</strong> apportare mo<strong>di</strong>fiche allo sta<strong>to</strong> <strong>di</strong> gioco in<strong>di</strong>vidua<strong>to</strong><br />

nel modulo SharedComponents è accompagna<strong>to</strong> dal Timestamp, sarà<br />

possibile valutare, dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista temporale, la <strong>su</strong>a coerenza.<br />

Se si prende come riferimen<strong>to</strong> il Player A in Figura 5.2 e si analizza il<br />

<strong>su</strong>o delta time rispet<strong>to</strong> agli altri Player ogni 5 secon<strong>di</strong>, emergono i seguenti<br />

comportamenti:<br />

Il delta rispet<strong>to</strong> a B è costante per i primi due istanti <strong>di</strong> tempo, mentre al<br />

terzo ques<strong>to</strong> <strong>su</strong>bisce <strong>un</strong> decremen<strong>to</strong> <strong>di</strong> 5 secon<strong>di</strong>, per poi ristabilizzarsi al<br />

delta originale all’istante T4.


5.1. ANTI-CHEATING 105<br />

Il Player C ha <strong>un</strong> timing due volte più veloce rispet<strong>to</strong> ad A: il delta infatti<br />

decrementa costantemente fino a invertire il segno.<br />

Il Player D Invece ha <strong>un</strong> delta più o meno costante, ma nell’istante T3 ques<strong>to</strong><br />

invia <strong>un</strong> comando riportante <strong>un</strong> TimeStamp valorizza<strong>to</strong> come se fosse sta<strong>to</strong><br />

invia<strong>to</strong> in T4.<br />

E’ <strong>di</strong>fficile valutare con sicurezza se l’alterazione del delta del Player B sia<br />

dovuta a problemi <strong>di</strong> latenza o sia stata causata dall’utilizzo <strong>di</strong> <strong>un</strong> Cheat.<br />

Anche nel caso del Player D la valutazione ri<strong>su</strong>lta delicata, poichè può<br />

capitare che in <strong>un</strong> momen<strong>to</strong> <strong>di</strong> congestione il TimeSync invia<strong>to</strong> dal Player<br />

D al Player Player A, venga ricevu<strong>to</strong> da quest’ultimo con <strong>un</strong> ritardo tale da<br />

giustificare il TimeStamp riporta<strong>to</strong> <strong>su</strong>l comando invia<strong>to</strong> <strong>su</strong>ccessivamente.<br />

Nel caso del Player C, invece, il timing è palesemente accelera<strong>to</strong> (2X), e<br />

per tan<strong>to</strong> deve essere escluso dalla Membership in ogni caso.<br />

5.1.2 Space Based Cheating<br />

Un primo sistema in grado <strong>di</strong> scremare quelle situazioni palesemente sospette,<br />

come la velocità del Character raddoppiata, è relativamente semplice<br />

da implementare: in CheatDetection() <strong>di</strong> <strong>un</strong> MovingObjectScript è infatti<br />

possibile controllare, da <strong>un</strong>a parte che i valori dei componenti NextPosition e<br />

NextTimeStamp siano coerenti rispet<strong>to</strong> alle velocità <strong>di</strong> movimen<strong>to</strong> specificata<br />

all’interno della classe stessa (ovvero il valore <strong>su</strong>l quale, in Update Writer()<br />

verrà calcola<strong>to</strong> il vet<strong>to</strong>re <strong>di</strong> spostamen<strong>to</strong>), e dall’altra verificare che, salvo<br />

casi particolari (ed opport<strong>un</strong>amente gestiti) come il Respawn 2 , la <strong>di</strong>stanza<br />

tra il valore del componente Position appena aggiorna<strong>to</strong> ed il valore ass<strong>un</strong><strong>to</strong><br />

precedentemente stia entro i limiti imposti dalla velocità <strong>di</strong> spostamen<strong>to</strong><br />

(Figura 5.3).<br />

Da ques<strong>to</strong> p<strong>un</strong><strong>to</strong> <strong>di</strong> vista Cheats come lo Speed-Hack sono facilmente in<strong>di</strong>viduabili.<br />

2 Azione <strong>di</strong> riposizionamen<strong>to</strong>, all’interno della mappa <strong>di</strong> gioco, del Character quando<br />

quest’ultimo muore o viene <strong>di</strong>strut<strong>to</strong>


106 CAPITOLO 5. SVILUPPI FUTURI<br />

Figura 5.2: Time Based Cheating


5.1. ANTI-CHEATING 107<br />

Figura 5.3: In A viene esegui<strong>to</strong> <strong>un</strong> movimen<strong>to</strong> spazialmente coerente, ma<br />

temporalmente incoerente. In B, invece, il movimen<strong>to</strong> esegui<strong>to</strong> ri<strong>su</strong>lta incoerente<br />

poichè la posizione attuale (o prevista) non ricade entro l’area <strong>di</strong><br />

spostamen<strong>to</strong> consenti<strong>to</strong> nel periodo <strong>di</strong> tempo specifica<strong>to</strong> (cerchio verde).<br />

Maggiori <strong>di</strong>fficoltà sorgono quando vi è la necessità <strong>di</strong> controllare il comportamen<strong>to</strong><br />

<strong>di</strong> ogni singolo movimen<strong>to</strong>, non solo dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista della<br />

rapi<strong>di</strong>tà <strong>di</strong> spostamen<strong>to</strong>, quin<strong>di</strong>, ma anche dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista della rotazione<br />

e dei relativi cambi <strong>di</strong> <strong>di</strong>rezione.<br />

Ri<strong>su</strong>lta impossibile valutare, infatti, se l’agilità <strong>di</strong> movimen<strong>to</strong> <strong>di</strong> <strong>un</strong> Character<br />

sia dovuta all’abilità del gioca<strong>to</strong>re che lo controlla, o all’utilizzo <strong>di</strong> <strong>un</strong><br />

apposi<strong>to</strong> Cheat in grado <strong>di</strong> spingere tali capacità appena al <strong>di</strong> sot<strong>to</strong> del limite<br />

impos<strong>to</strong> dalle regole <strong>di</strong> gioco.<br />

Quello che però è sicuramente possibile (e necessario) controllare, è la<br />

coerenza delle rotazioni in relazione al TimeSpan tra <strong>un</strong> aggiornamen<strong>to</strong> e<br />

l’altro: se ad esempio il gioco prevede <strong>un</strong> Character in grado <strong>di</strong> compiere<br />

<strong>un</strong>a rotazione <strong>di</strong> 20 ◦ ogni secondo, nel me<strong>to</strong>do Update Reader() del relativo<br />

ComponentScript sarà possibile valutare se gli eventuali cambi <strong>di</strong> <strong>di</strong>rezione<br />

segnalati rientrino effettivamente nei limiti imposti dalle specifiche <strong>di</strong> gioco


108 CAPITOLO 5. SVILUPPI FUTURI<br />

(Figura 5.4).<br />

Figura 5.4: Le rotazioni effettuate dal Character (p<strong>un</strong>ti blu) in A rientrano<br />

nei limiti imposti dalle regole <strong>di</strong> gioco, mentre quelle in B ri<strong>su</strong>ltano, in relazione<br />

al TimeSpan intrercorso tra <strong>un</strong>’aggiornamen<strong>to</strong> e l’altro, essere troppo<br />

ampie.<br />

Vi sono inoltre alc<strong>un</strong>e situazioni particolari nelle quali è richies<strong>to</strong> <strong>un</strong> controllo<br />

<strong>su</strong>lle coor<strong>di</strong>nate spaziali che <strong>un</strong> ogget<strong>to</strong> 3D as<strong>su</strong>me in fase <strong>di</strong> inizializzazione:<br />

la creazione <strong>di</strong> <strong>un</strong> Bullet, ad esempio deve avvenire in prossimità<br />

del Character che l’ha genera<strong>to</strong>. Non è <strong>to</strong>llerabile, viceversa, che <strong>un</strong> Bullet<br />

venga istanzia<strong>to</strong> lontano dal proprio Character, o ad<strong>di</strong>rittura posiziona<strong>to</strong><br />

appositamente in prossimità <strong>di</strong> <strong>un</strong> Character nemico (Figura 5.5).<br />

Un’altro problema fondamentale lega<strong>to</strong> al Cheating è rappresenta<strong>to</strong> da<br />

quelle collisioni che implicano mo<strong>di</strong>fiche allo sta<strong>to</strong> <strong>di</strong> gioco: grazie ai controlli<br />

effettuati <strong>su</strong>llo spazio e <strong>su</strong>l tempo, è possibile garantire <strong>un</strong>a cer<strong>to</strong> grado<br />

<strong>di</strong> coerenza in quelle che sono le <strong>di</strong>namiche <strong>di</strong> gioco che coinvolgono movimenti<br />

e interazioni tra gli elementi <strong>di</strong> gioco. Come anticipa<strong>to</strong> nella sezione<br />

2.7.2, quando <strong>un</strong>a collisione coinvolge <strong>un</strong> Bullet ed <strong>un</strong> Character, il Player<br />

proprietario del Bullet segnala l’avvenuta collisione al Player proprietario del<br />

Character che decrementerà i propri p<strong>un</strong>ti HP <strong>di</strong> conseguenza.


5.1. ANTI-CHEATING 109<br />

Figura 5.5: Player A crea <strong>un</strong> proprio Bullet all’interno dell’area consentita<br />

(Cerchio verde, calcola<strong>to</strong> tenendo con<strong>to</strong> degli effetti causati dal Lag); Player<br />

B invece crea il proprio Bullet esternamente, e ques<strong>to</strong> viene interpreta<strong>to</strong><br />

come possibile segno <strong>di</strong> Cheating.<br />

Evidentemente <strong>un</strong> asset<strong>to</strong> <strong>di</strong> ques<strong>to</strong> tipo, se non controlla<strong>to</strong>, si presta ad<br />

essere sogget<strong>to</strong> a problematiche <strong>di</strong> Cheating: infatti da <strong>un</strong>a parte il Player<br />

che ha genera<strong>to</strong> il Bullet può notificare collisioni in realtà non avvenute,<br />

mentre dall’altra il Player possessore <strong>di</strong> <strong>un</strong> Character realmente colpi<strong>to</strong> può<br />

non operare le dovute mo<strong>di</strong>fiche al proprio HP (Figura 5.5).<br />

Una soluzione al primo problema potrebbe essere quella <strong>di</strong> controllare,<br />

<strong>su</strong>lla ricezione del messaggio Collision, che il Bullet coinvol<strong>to</strong> nella pres<strong>un</strong>ta<br />

collisione, esista nel proprio Data Layer e che abbia <strong>un</strong>a posizione ed <strong>un</strong>a<br />

<strong>di</strong>rezione tale da giustificare <strong>un</strong>a collisione con il Character (Figura 5.5).<br />

Per quan<strong>to</strong> riguarda il secondo problema si può procedere nel seguente<br />

modo: quando <strong>un</strong> Bullet appartenente al Player A colpisce il Character appartenente<br />

al B, ci si aspetta che B decrementi il proprio HP e lo notifichi,<br />

au<strong>to</strong>maticamente, a tutti gli altri Player. Parallelamente però, il Player A<br />

può prevedere tale decremen<strong>to</strong> e mo<strong>di</strong>ficando <strong>di</strong> conseguenza il valore del<br />

componente HP relativo al Character colpi<strong>to</strong>, all’interno del proprio Data<br />

Layer. Se il valore <strong>di</strong> HP invia<strong>to</strong> da B ri<strong>su</strong>lterà maggiore, allora si può<br />

sospettare l’utilizzo <strong>di</strong> <strong>un</strong> Cheat. E lo si può eventualmente accertare, dal<br />

momen<strong>to</strong> che ad ogni incremen<strong>to</strong> del valore <strong>di</strong> HP deve corrispondere la<br />

<strong>di</strong>struzione <strong>di</strong> <strong>un</strong> HealthPack.


110 CAPITOLO 5. SVILUPPI FUTURI<br />

Figura 5.6: Nella figura B viene invia<strong>to</strong> <strong>un</strong> messaggio Collision quando il<br />

Bullet in realtà non è avvenuta ness<strong>un</strong>a collisione<br />

5.2 Ottimizzazione NET Layer<br />

Attualmente le <strong>un</strong>iche classi che concretizzano le interfacce esposte dal<br />

Layer NET sono basate <strong>su</strong>l pro<strong>to</strong>collo TCP. In quest’ottica si può vagliare<br />

la possibilità <strong>di</strong> <strong>un</strong>a seconda implementazione, basata invece <strong>su</strong>l pro<strong>to</strong>collo<br />

UDP. Un’alternativa da valutare è l’utilizzo <strong>di</strong> librerie esterne <strong>di</strong> <strong>Game</strong> Networking<br />

(si veda il capi<strong>to</strong>lo 1.4).<br />

Nel primo caso gli interventi da effettuare a livello strutturale sono minimi,<br />

ma è com<strong>un</strong>que richiesta l’implementazione <strong>di</strong> <strong>un</strong>a serie <strong>di</strong> sistemi <strong>di</strong> controllo,<br />

che nel TCP sono gestiti <strong>di</strong>rettamente dal sistema operativo, come il<br />

controllo <strong>di</strong> flusso ed il controllo <strong>di</strong> congestione, mirati a rendere tale pro<strong>to</strong>collo<br />

Reliable.<br />

Il secondo caso, invece, implica la sostituzione <strong>di</strong> <strong>un</strong>o o più Layer a seconda<br />

della libreria utilizzata, e richiede <strong>un</strong> interven<strong>to</strong> <strong>di</strong> Refac<strong>to</strong>ring relativamente<br />

esteso.<br />

Sot<strong>to</strong> quest’aspet<strong>to</strong> può ri<strong>su</strong>ltare imprescin<strong>di</strong>bile l’introduzione <strong>di</strong> <strong>un</strong> si-


5.2. OTTIMIZZAZIONE NET LAYER 111<br />

Figura 5.7: In T1 avviene la collsione tra il Bullet del Player A ed il Character<br />

del Player B; in T2, il Player A decrementa il valore <strong>di</strong> HP appartenente<br />

al Player B <strong>di</strong> 10 p<strong>un</strong>ti come da specfiche, mentre il Player B, cheatando,<br />

decrementa il valore del proprio HP <strong>di</strong> solo <strong>un</strong> p<strong>un</strong><strong>to</strong>. In T3 il Player A riceve<br />

la notifica <strong>di</strong> aggiornamen<strong>to</strong> e nota la <strong>di</strong>fferenza tra il valore previs<strong>to</strong> (90) e<br />

quello notifica<strong>to</strong> (99).


112 CAPITOLO 5. SVILUPPI FUTURI<br />

stema <strong>di</strong> sincronizzazione temporale, perché se è vero che il modulo Shared-<br />

Components limita l’impat<strong>to</strong> <strong>di</strong> problemi legati alla latenza <strong>su</strong>lla consistenza<br />

dello sta<strong>to</strong> <strong>di</strong> gioco, utilizzando il pro<strong>to</strong>collo UDP la sicurezza <strong>di</strong> ricevere i<br />

messaggi nello stesso or<strong>di</strong>ne con il quale sono stati inviati viene meno.<br />

Un’ulteriore possibilità <strong>di</strong> ottimizzazione da vagliare è rappresentata dall’utilizzo<br />

<strong>di</strong> <strong>un</strong> sistema <strong>di</strong> compressione dati: attualmente i Commands vengono<br />

scritti <strong>su</strong>llo Stream sot<strong>to</strong>forma <strong>di</strong> stringhe UTF-8 (ogni carattere occupa<br />

da 1 a 4 byte), e l’utilizzo <strong>di</strong> <strong>un</strong>a libreria <strong>di</strong> compressione come Zlib 3 o<br />

GZip 4 , entrambe <strong>su</strong>pportate nativamente da .NET, può ridurre la richiesta<br />

<strong>di</strong> banda. L’efficacia <strong>di</strong> ques<strong>to</strong> tipo <strong>di</strong> compressione può però ri<strong>su</strong>ltare relativamente<br />

bassa, dal momen<strong>to</strong> che le stringhe scambiate tra i <strong>di</strong>versi <strong>Peer</strong><br />

sono piut<strong>to</strong>s<strong>to</strong> corte.<br />

5.3 Gestione utenti e MatchMaking<br />

Nell’attuale implementazione non sono presenti macrostrutture a<strong>di</strong>bite<br />

alla gestione del concet<strong>to</strong> <strong>di</strong> “partita” ed ai sot<strong>to</strong>-concetti ad esso connessi,<br />

come l’inizio e la fine <strong>di</strong> <strong>un</strong> match, la vit<strong>to</strong>ria e la sconfitta.<br />

Attualmente infatti non c’è ness<strong>un</strong> tipo <strong>di</strong> limitazione alla formazione au<strong>to</strong>noma<br />

<strong>di</strong> <strong>un</strong>a Membership, né tan<strong>to</strong> meno <strong>un</strong> sistema <strong>di</strong> controllo <strong>su</strong>l numero<br />

<strong>di</strong> partecipanti: ogni <strong>Peer</strong> può decidere <strong>di</strong> entrare in <strong>un</strong>a Membership<br />

in qualsiasi momen<strong>to</strong>, semplicemente connettendosi ad <strong>un</strong>o dei <strong>su</strong>oi no<strong>di</strong><br />

(Figura 5.8).<br />

Il primo problema da affrontare è il <strong>Peer</strong> Discovery e, nella fattispecie l’in<strong>di</strong>viduazione<br />

<strong>di</strong> <strong>un</strong> sistema in grado <strong>di</strong> notificare ai <strong>Peer</strong> non ancora connessi<br />

l’esistenza <strong>di</strong> Membership attive, e le informazioni necessarie che consentano<br />

<strong>di</strong> effettuarne il join.<br />

Tipicamente ques<strong>to</strong> viene realizza<strong>to</strong> attraverso <strong>un</strong> approccio centralizza<strong>to</strong>,<br />

3 http://www.zlib.net/<br />

4 http://www.gzip.org/


5.3. GESTIONE UTENTI E MATCHMAKING 113<br />

Figura 5.8: Campi testuali per la configurazione dll’in<strong>di</strong>rizzo IP e della porta<br />

d’ascol<strong>to</strong>, e per il join in <strong>un</strong>a Membership


114 CAPITOLO 5. SVILUPPI FUTURI<br />

caratterizza<strong>to</strong> da <strong>un</strong> “Master server” (o “Lobby Server”) che si occupa della<br />

gestione delle partite attive.<br />

Supponendo che <strong>un</strong> Player A voglia creare <strong>un</strong>a partita, <strong>un</strong>a volta specificati<br />

in<strong>di</strong>rizzo IP e porta (operazione in futuro au<strong>to</strong>matizzabile), da <strong>un</strong>a parte<br />

rimane in ascol<strong>to</strong> <strong>di</strong> eventuali <strong>Peer</strong> che vogliono “joinare” nella Membership,<br />

e dall’altra riferisce al Lobby Server dell’avvenuta creazione.<br />

Un Player B intenziona<strong>to</strong> a partecipare ad <strong>un</strong>a partita già esistente, interrogherà<br />

il Lobby Server, che invierà <strong>di</strong> conseguenza lista delle partite attive<br />

e le informazioni relative ai singoli partecipanti (Figura 5.9).<br />

Un’ulteriore au<strong>to</strong>mazione contestualizzabile nel Lobby Server è rappresentata<br />

dal Matchmaking, ovvero <strong>un</strong>a selezione delle partite attive più adatte<br />

al gioca<strong>to</strong>re, basata <strong>su</strong>lla valutazione <strong>di</strong> dati statistici espressi da <strong>un</strong> sistema<br />

<strong>di</strong> Ranking. Quest’ultimo, partita dopo partita, memorizza dati utili ad<br />

identificare l’abilità (Skill) <strong>di</strong> ogni singolo gioca<strong>to</strong>re.<br />

Alla base <strong>di</strong> tale au<strong>to</strong>mazione è necessario però che sia presente <strong>un</strong> sistema<br />

<strong>di</strong> autenticazione in grado <strong>di</strong> identificare i singoli gioca<strong>to</strong>ri.


5.3. GESTIONE UTENTI E MATCHMAKING 115<br />

Figura 5.9: <strong>Peer</strong> Discovery tramite Lobby server


116 CAPITOLO 5. SVILUPPI FUTURI


Capi<strong>to</strong>lo 6<br />

Conclusioni<br />

Negli ultimi venti anni, ed in particolare in quest’ultimo decennio, nonostante<br />

la crisi economica, l’industria dei videogiochi ha <strong>su</strong>bi<strong>to</strong> <strong>un</strong>a forte<br />

crescita, tan<strong>to</strong> da <strong>su</strong>perare le entrate <strong>di</strong> altri set<strong>to</strong>ri del merca<strong>to</strong> dell’intrattenimen<strong>to</strong>,<br />

come il cinema e l’home video[EntMerch 2008]. Complici <strong>di</strong>versi<br />

fat<strong>to</strong>ri: dall’ampliamen<strong>to</strong> del target demografico, alla <strong>di</strong>ffusione <strong>di</strong> nuove<br />

tecnologie e nuovi <strong>su</strong>pporti (si pensi agli SmartPhone) in grado <strong>di</strong> offrire<br />

esperienze videolu<strong>di</strong>che, anche <strong>Multiplayer</strong>, in luoghi, tempi e mo<strong>di</strong> impensabili<br />

anche solo qualche anno fa.<br />

Parallelamente sono cresciuti i costi e gli investimenti stanziati per lo<br />

sviluppo, per il marketing e per le infrastrutture necessarie al <strong>su</strong>ppor<strong>to</strong> <strong>Multiplayer</strong>.<br />

La realizzazione <strong>di</strong> <strong>un</strong> videogioco, intesa come processo produttivo, è oggigiorno<br />

<strong>un</strong>’attività trasversale, caratterizzata da temi, problematiche, ed in<br />

ultima analisi, da figure professionali specializzate in ambiti anche notevolmente<br />

<strong>di</strong>fferenti tra loro.<br />

In questa tesi <strong>di</strong> proget<strong>to</strong> si é cerca<strong>to</strong> <strong>di</strong> affrontare i problemi che stanno<br />

<strong>di</strong>etro all’implementazione <strong>di</strong> <strong>un</strong> videogioco <strong>Multiplayer</strong> <strong>Peer</strong>-To-<strong>Peer</strong>, esaminando<br />

l’intero processo da <strong>un</strong> p<strong>un</strong><strong>to</strong> <strong>di</strong> vista generale, e mantenendo il<br />

117


118 CAPITOLO 6. CONCLUSIONI<br />

focus <strong>su</strong> quelli che sono gli aspetti relativi alla progettazione e allo sviluppo<br />

della parte prettamente Software.<br />

Il contes<strong>to</strong> analizza<strong>to</strong> è vas<strong>to</strong> e complesso e non è sta<strong>to</strong> possibile quin<strong>di</strong><br />

entrare nel dettaglio <strong>di</strong> ogni singolo aspet<strong>to</strong>: ad esempio le problematiche<br />

legate allo sviluppo <strong>di</strong> <strong>un</strong> Engine grafico o <strong>di</strong> <strong>un</strong> Engine fisico, grazie all’utilizzo<br />

<strong>di</strong> <strong>un</strong> Middleware come Unity3D, sono state affrontate solo in maniera<br />

marginale.<br />

Anche per quan<strong>to</strong> riguarda ciò che concerne maggiormente l’argomen<strong>to</strong><br />

<strong>di</strong> tesi alc<strong>un</strong>e caratteristiche che si possono in<strong>di</strong>viduare nella maggior parte<br />

dei giochi <strong>Multiplayer</strong> commerciali, come i sistemi <strong>di</strong> Anti-Cheating ed i Lobby<br />

Server, per questioni <strong>di</strong> tempo non sono state sviluppate concretamente<br />

all’interno del proget<strong>to</strong> (si veda il capi<strong>to</strong>lo 5 relativo agli sviluppi futuri).<br />

Ciò nonostante, la realizzazione <strong>di</strong> <strong>un</strong> videogioco <strong>Multiplayer</strong> basa<strong>to</strong> <strong>su</strong><br />

reti <strong>Peer</strong>-To-<strong>Peer</strong>, ha permesso <strong>di</strong> sperimentare con mano quelli che sono i<br />

problemi e le <strong>di</strong>fficoltà caratteristiche che emergono durante lo sviluppo <strong>di</strong><br />

<strong>un</strong> software videolu<strong>di</strong>co, ed in particolare nel caso in cui quest’ultimo ri<strong>su</strong>lti<br />

contestualizza<strong>to</strong> in <strong>un</strong>o scenario <strong>di</strong> rete decentralizza<strong>to</strong>:<br />

In <strong>un</strong>a prima fase sono state analizzate le tecnologie, gli strumenti e le<br />

architetture prevalentemente utilizzate nel panorama attuale, al fine <strong>di</strong> selezionare<br />

quelle più adatte all’obiettivo <strong>di</strong> tesi.<br />

Sono stati valutati quelli che sono i vantaggi e gli svantaggi del modello<br />

<strong>Peer</strong>-To-<strong>Peer</strong> in contrapposizione al modello Client-Server, e <strong>di</strong> conseguenza<br />

esaminati i sistemi <strong>di</strong> sincronizzazione utilizzati per mantenere <strong>un</strong>o sta<strong>to</strong> <strong>di</strong><br />

gioco con<strong>di</strong>viso da tutti i gioca<strong>to</strong>ri.<br />

Quest’ultimo aspet<strong>to</strong> rappresenta probabilmente il cuore del problema:


119<br />

Sostanzialmente, astraendo dalle caratteristiche specifiche <strong>di</strong> gioco (come le<br />

<strong>di</strong>namiche <strong>di</strong> gameplay, la grafica, l’au<strong>di</strong>o e l’interazione utente), il requisi<strong>to</strong><br />

più importante per <strong>un</strong> MOG è garantire -al medesimo istante <strong>di</strong> tempo- <strong>un</strong>a<br />

rappresentazione dell’ambiente <strong>di</strong> gioco il più possibile simile per ogni singolo<br />

gioca<strong>to</strong>re, nonostante la presenza <strong>di</strong> fat<strong>to</strong>ri quali il Lag ed il Jitter.<br />

Infine, dal p<strong>un</strong><strong>to</strong> <strong>di</strong> vista del design del software è ri<strong>su</strong>ltata estremamente<br />

utile, sia in fase <strong>di</strong> progettazione che <strong>di</strong> implementazione, la separazione<br />

concettuale tra il contes<strong>to</strong> logico e gli aspetti prettamente vi<strong>su</strong>ali, poiché ha<br />

permesso <strong>di</strong> organizzare, identificare e soprattut<strong>to</strong> vincolare, gli elementi in<br />

grado <strong>di</strong> apportare informazioni allo sta<strong>to</strong> <strong>di</strong> gioco, al fine <strong>di</strong> generalizzare e<br />

au<strong>to</strong>matizzare le modalità <strong>di</strong> aggiornamen<strong>to</strong> <strong>di</strong> quest’ultimo.<br />

In conclusione l’approccio <strong>Peer</strong>-To-<strong>Peer</strong>, rispet<strong>to</strong> al modello Client-Server,<br />

pone <strong>un</strong>a serie <strong>di</strong> problemi dovuti alla <strong>su</strong>a natura decentralizzata e “<strong>un</strong>trusted”.<br />

Ri<strong>su</strong>lta inoltre meno <strong>di</strong>ffuso e relativamente ancora poco sfrutta<strong>to</strong><br />

in ambi<strong>to</strong> videolu<strong>di</strong>co, specialmente nella <strong>su</strong>a versione “pura”. Ma può<br />

rappresenta <strong>un</strong>a potenziale alternativa per quelle tipologie <strong>di</strong> gioco che non<br />

richiedono necessariamente la presenza <strong>di</strong> <strong>su</strong>pporti centralizzati.


120 CAPITOLO 6. CONCLUSIONI


Bibliografia<br />

[Abrash 1996] ABRASH M. 1996. Ramblings in Realtime<br />

[Bettner 2001] BETTNER P., TERRANO M. 2001. 1500 Archers on a<br />

28.8: Network Programming in Age of Empires and Beyond,<br />

URL: http://zoo.cs.yale.edu/classes/cs538/rea<strong>di</strong>ngs/papers/terrano<br />

1500arch.pdf<br />

[Rhalibi 2005] EL RHALIBI A., MERABTI M., 2005. Agent-Based Modeling<br />

for a <strong>Peer</strong>-<strong>to</strong>-<strong>Peer</strong> MMOG Architecture<br />

[Due Billing 2006] DUE BILLING O., PETERSEN J., 2006. Aspects of<br />

<strong>Peer</strong> <strong>to</strong> <strong>Peer</strong> game networks,<br />

URL: http://www.p2pgamenetwork.com/downloads/p2pgamenetwork.pdf<br />

[Ferretti 2008] FERRETTI S. 2008. A Synchronization Pro<strong>to</strong>col For Supporting<br />

<strong>Peer</strong>-<strong>to</strong>-<strong>Peer</strong> <strong>Multiplayer</strong> <strong>Online</strong> <strong>Game</strong>s in Overlay<br />

Networks,<br />

URL: http://sferrett.web.cs.<strong>un</strong>ibo.it/papers/debs08 p083-<br />

ferretti.pdf<br />

[Griwodz 2006] GRIWODZ C., HALVORSEN P., 2006. The F<strong>un</strong> of using<br />

TCP for an MMORPG<br />

[Smith 2000] SMITH R.D. 2000, Synchronizing Distribuited Virtual Worlds<br />

[Luo 2010]<br />

LUO J., CHANG H., 2010, A scalable architecture for massive<br />

Multi-Player <strong>Online</strong> <strong>Game</strong>s using peer-<strong>to</strong>-peer overlay<br />

121


122 BIBLIOGRAFIA<br />

[Yong-Tae 2008] YONG-TAE H., HONG-SHIK P., 2008, UDP based P2P<br />

game traffic classification with transport layer behaviors<br />

[Hampel 2006] HAMPEL T., BOPP T., HINN R., 2006, A <strong>Peer</strong>-<strong>to</strong>-<strong>Peer</strong><br />

Architecture for Massive <strong>Multiplayer</strong> <strong>Online</strong> <strong>Game</strong>s<br />

[Knutsson 2004] KNUTSSON B., LU T., XU W., HOPKINS B., 2004, <strong>Peer</strong><strong>to</strong>-<strong>Peer</strong><br />

Support for Massively <strong>Multiplayer</strong> <strong>Game</strong>s<br />

[Gang of Four 2004] GAMME E., RALPH R.H., JOHNSON R., VLISSIDES<br />

J., 1995. Design Patterns Elements of reusable Object Oriented<br />

Software<br />

[Cronin 2002] CRONIN E., FILSTRUP B., KURC A.R., JAMIN S., 2002.<br />

An efficient synchronization mechanism for mirrored game<br />

architectures<br />

[Gautier 1999] GAUTIER L., DIOT C., KUROSE J., 1999. End-<strong>to</strong>-end<br />

transmission control mechanisms for multiparty interactive<br />

applications on the Internet<br />

[Gregory 2009] GREGORY J., 2009 <strong>Game</strong> Engine Architecture<br />

[Chen 2007]<br />

[Ko 2005]<br />

CHEN B. His<strong>to</strong>ry Of <strong>Multiplayer</strong> <strong>Game</strong>s<br />

URL: http://www.ssagsg.org/LearningSpace/<br />

EntertainmentGaming/His<strong>to</strong>ryMPG.htm<br />

KO B.J., RUBENSTEIN D., CALO S., 2005 Dynamic server<br />

selection for large scale interactive online games<br />

[Hong 2003] HONG E., LEE E.D, KANG K, 2003 An efficient synchronization<br />

mechanism adapting <strong>to</strong> dynamic network state for<br />

networked virtual environment<br />

[Baughman 2001] BAUGHMAN N., LEVINE B., 2001 Cheat-proof playout<br />

for centralized and <strong>di</strong>stributed online games


BIBLIOGRAFIA 123<br />

[Paik 2008]<br />

PAIK D., YUN C., HWANG J., 2008 Effective message<br />

synchronization methods for multiplayer online games with<br />

maps<br />

[Neumann 2007] NEUMANN C., PRIGENT N., VARVELLO M., 2007<br />

Challenges in <strong>Peer</strong>-<strong>to</strong>-<strong>Peer</strong> Gaming<br />

[Mogaki 2007] MOGAKI S., KAMADA M., YONEKURA T., 2007, Minimization<br />

of Latency in Cheat-Proof Real-Time Gaming by<br />

Trusting Time-Stamp Servers<br />

[EntMerch 2008] http://www.entmerch.org/


124 BIBLIOGRAFIA


Ringraziamenti<br />

Desidero innanzitut<strong>to</strong> ringraziare il Professore Stefano Ferretti per i <strong>su</strong>oi<br />

preziosi <strong>su</strong>ggerimenti e la grande <strong>di</strong>sponibilità <strong>di</strong>mostratemi.<br />

Inoltre ringrazio sentitamente tutti i professori del corso, in particolare Vania<br />

Sordoni e Carla Guerrini, docenti delle materie degli ultimi due esami,<br />

forse i più ostici ma allo stesso tempo i più appaganti. Ringrazio tutti i miei<br />

compagni <strong>di</strong> corso con cui ho con<strong>di</strong>viso lezioni, ore <strong>di</strong> stu<strong>di</strong>o e <strong>di</strong>vertimenti,<br />

in particolare Daniele (Viva), Gianmarco (Giammolo), Marco (Bot), Giacomo<br />

(Jack), Marco, Nicolò, Matteo, Alessandro (Zacagno), Matteo (Fixxxer),<br />

Valentina, Marco (Ket<strong>to</strong>), Alessio (Torre) e soprattut<strong>to</strong> mio fratello Riccardo<br />

che mi ha sempre aiuta<strong>to</strong> in questi anni <strong>di</strong> Università e con cui ho con<strong>di</strong>viso<br />

ore e ore <strong>di</strong> stu<strong>di</strong>o.<br />

Infine, ho il desiderio <strong>di</strong> ringraziare con affet<strong>to</strong> i miei geni<strong>to</strong>ri Carlo e Laura<br />

per il sostegno ed il grande aiu<strong>to</strong> che mi hanno da<strong>to</strong> sia dal la<strong>to</strong> economico<br />

che dal la<strong>to</strong> affettivo e per avermi sprona<strong>to</strong> più volte a stu<strong>di</strong>are con più<br />

continuità. Ringrazio anche i miei nonni Livio e Renata e tutti i miei parenti.<br />

125

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!