forked from samuelemusiani/project_00819
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreport.tex
270 lines (242 loc) · 16.1 KB
/
report.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
\documentclass[a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[italian]{babel}
\def\CC{{C\nolinebreak[4]\hspace{-.05em}\raisebox{.4ex}{\tiny\bf ++}}}
\title{\textbf{Only jump}\\
\vspace{0.2cm}\normalsize Relazione del progetto per il corso di Programmazione\\
\normalsize Università di Bologna
}
\author{
E. Argonni,
O. Ayache,
L. Peronese,
S. Musiani
}
\date{2022 - 2023}
\begin{document}
\maketitle
\section{Introduzione}
\emph{Only jump} è un gioco platform a scorrimento verticale illimitato
in grafica ASCII completamente realizzato in \CC. L'esecuzione del gioco
avviene interamente all'interno di un terminale, dove è possibile eseguire tutte
le azioni necessarie attraverso la tastiera. Sono presenti diversi tipi di
nemici e armi, queste ultime acquistabili in un apposito market tramite le
monete raccolte durante la partita. Essendo centrale nel gameplay la meccanica
di salto, è stata implementata quest'ultima in modo che si possa scegliere, in
funzione del tempo di pressione dell'apposito tasto, la forza del salto. È stato
inoltre previsto un pannello per calibrare la tastiera in modo che l'esperienza
di gioco sia il più simile possibile su tutti i dispositivi in cui viene
giocato.
\section{Spartizione dei ruoli}
Essendo il progetto sviluppato su più classi, è stato possibile lavorare
parallelamente suddividendo il lavoro tra tutti i componenti del gruppo. Nello
specifico la suddivisione è stata la seguente:
\begin{itemize}
\item \emph{E. Argonni}: Implementazione della classe \texttt{Game}, ovvero la
classe più importante di tutto il gioco in quanto si interfaccia con tutte
le restanti classi. Grazie a essa infatti c'è una coesione tra tutte le
porzioni di codice sviluppate separatamente. Al suo interno è possibile
trovare la funzione che contiene il loop principale in cui si svolge una
partita. \texttt{Menu} è la classe adibita alla gestione del menu iniziale
di gioco ed è inoltre responsabile dell'animazione a inizio gioco.
\texttt{Save} è classe che si occupa di interagire con l'utente quando è
necessario salvare una partita. Si occupa però solo dell'aspetto grafico,
mentre la classe che esegue l'effettivo salvataggio su file è differente.
La \texttt{Settings} invece si occupa delle impostazioni: personalizzazione
dei tasti di gioco, calibrazione della tastiera e altre impostazioni
specifiche minori. Infine la classe \texttt{Statistics} che si occupa di
tenere traccia della vita, delle monete e in generale delle statiche del
giocatore.
\item \emph{O. Ayache}: Implementazione delle classi \texttt{Screen} e
\texttt{Draw} che hanno il compito di nascondere completamente tutte le
funzioni di \texttt{ncurses}\footnote{\texttt{Ncurses} è la libreria esterna
usata per gestire la grafica su terminale del gioco} in due semplici e
comode classi in modo che tutte le classi avente necessità di disegnare
sullo schermo potessero semplicemente interfacciarsi a loro, senza usare
direttamente la libreria \texttt{ncurses}. Questo ha permesso di aggiungere
un livello di astrazione maggiore che nascondesse l'implementazione a basso
livello della libreria. La classe \texttt{Entity} è una generica entità nel
gioco che grazie all'ereditarietà fornita dal paradigma OOP è la classe padre di
\texttt{Enemy}, \texttt{Coin} e \texttt{Bullet} che da sole sono già
autoesplicative. La classe \texttt{Market} si occupa di disegnare tutto il
menu relativo al negozio e di fornire all'utente un metodo facile per
l'acquisto di armi e abilità. Queste ultime sono rappresentate grazie a
delle classi apposite: \texttt{Gun} e \texttt{Ability}. Infine la classe
\texttt{Events} si occupa della gestione delle e della loro integrazione con
la partita.
\item \emph{L. Peronese}: Implementazione delle mappe tramite la classe
\texttt{Map} insieme alle classi \texttt{Chunk} e \texttt{Platform}. Queste
ultime sono frammenti più piccoli che composti formano una mappa infinita e
facilmente utilizzabile attraverso la classe apposita. Il salvataggio delle
partite, delle impostazioni, come i tasti personalizzati, e la calibrazione
è delegato alla classe \texttt{File}. Questa classe si occupa della
effettiva scrittura su disco ed è quindi invisibile all'utente in quanto
chiamata da altre classi. Inoltre si occupa di leggere i salvataggi quando
il gioco viene riaperto o è necessario caricare una partita precedentemente
salvata. La classe \texttt{Random} viene usata come interfaccia dalle altre
classi in qualsiasi momento sia necessario generare numeri casuali per avere
un luogo unico dove vengono gestiti i \emph{seed}. Per fare debug, in quanto
lo \texttt{stdout} è occupato dalla grafica del gioco, è stata scritta la
libreria di funzioni \texttt{logs} che permettono di scrivere su file
stringhe arbitrarie.
\item \emph{S. Musiani}: Implementazione della libraria di fisica per la
simulazione di oggetti, gravità, velocità e salti. Distinta del namespace
\texttt{phy} comprende le seguenti classi: \texttt{Point} per rappresentare
un punto su un piano bidimensionale; \texttt{PrecisesPoint} per
rappresentare un punto su un piano bidimensionale il più precisamente
possibile, cioè senza approssimazioni; \texttt{Vector} per la
rappresentazione di un vettore; \texttt{Body} per la simulazione di un
corpo che ha una posizione, una velocità e una accelerazione. Sono inoltre
presenti delle costanti nel file \texttt{constants.hpp}, come
l'accelerazione della gravità in gioco e delle funzioni per simulare le
collisioni tra oggetti nel file \texttt{collisions.cpp}. La scrittura della
classe \texttt{Manager} che tiene traccia e gestisce tutte le entità nel
gioco come monete, proiettili e nemici. Tiene traccia della loro morte, dei
loro movimenti e dei loro comportamenti, anche in relazione al giocatore.
Comunica inoltre con la classe per il salvataggio su file in modo da
memorizzare lo stato delle entità efficientemente.
Essendo da specifiche proibito l'utilizzo della standar library di \CC\ e in
particolare tutte le classi che facilitano l'allocazione di memoria e la
gestione di essa, sono state re-implementate le classi \texttt{string} e
\texttt{vector} in particolare entrambi sotto il namespace \texttt{nostd}.
Esse fanno quello che ci si aspetta e sono una implementazione personale
delle classi di libreria. La classe \texttt{string} è stata realizzata con
\emph{L. Peronese}.
\end{itemize}
\section{Scelte implementative}
\subsection{Screen e Draw}
Per semplificare il più possibile le operazioni di disegno su schermo e in
generale tutto quello che riguardasse la grafica sono state create queste due
classi per nascondere completamente la libreria \texttt{ncurses}. In particolare
la classe \texttt{Screen} implementa solo le operazioni base che si possono fare
su uno schermo come inizializzarlo, cancellarlo, impostarne la dimensione ecc.
La classe è creata in modo che tutte le volte che un oggetto \texttt{Screen}
viene creato automaticamente un nuova finestra di \texttt{ncurses} viene
allocata.
La classe \texttt{Draw} estende \texttt{Screen} ereditando tutti i metodi base
per gestire lo schermo, ma implementando a sua volta tutti i metodi necessari
per disegnare. In particolare quelli necessari per scrivere a schermo stringhe,
interi o semplici caratteri. Vengono inoltre forniti metodi per disegnare figure
quali linee e rettangoli. Sono presenti anche i metodi per disegnare la mappa,
il giocatore e tutti i tipi di entità quali nemici, proiettili e monete.
\subsection{Game}
La classe principale del videogioco è \texttt{Game}, la quale gestisce
l’interazione con le altre classi e il flusso complessivo del gioco. La funzione
\textsc{run} è la prima a essere chiamata e ha il compito di far partire tutto
il gioco. In particolare esegue il menu principale del gioco che permette
all’utente di scegliere tra diverse opzioni come giocare, riprendere una partita
salvata, accedere alle impostazioni o uscire dal gioco. La funzione
\textsc{play} racchiude il ciclo principale in cui una partita viene svolta. È
infatti responsabile del progresso di gioco e gestisce l’interazione tra il
giocatore, le entità, le piattaforme e le statistiche. Tramite i controlli da
tastiera, il giocatore può muoversi, saltare, sparare e accedere al market.
La classe gestisce l’aggiornamento della posizione del giocatore e delle entità,
la collisione con le piattaforme e consente di mettere in pausa il gioco per
accedere alle opzioni come le impostazioni, i salvataggi e il market.
\subsection{Menu}
La classe \texttt{Menu} gestisce il menu principale del videogioco e
contribuisce a creare un’esperienza coinvolgente sin dai primi istanti di avvio.
È infatti responsabile dell’animazione di intro del gioco e della gestione del
menu principale, consentendo all’utente di scegliere fra le opzioni disponibili.
La funzione \textsc{getselectedoption} in particolare gestisce la navigazione
dell’utente all’interno del menu e rende possibile la scelta delle opzioni con
facilità evidenziando visivamente l’opzione selezionata.
\subsection{Statistics}
La classe \texttt{Statisitcs} fornisce la struttura per la gestione delle
statistiche del gioco. Permette all’utente, durante l’esecuzione del gioco, di
avere un’interfaccia in cui poter controllare in tempo reale le statistiche di
gioco, il numero di monete disponibili, la quantità di vite possedute, il
livello a cui si trova e il numero totale di salti effettuati.
\subsection{Settings}
La classe \texttt{Settings} fornisce un'interfaccia intuitiva per la gestione
delle opzioni di configurazione del gioco. Consente all’utente di personalizzare
la propria esperienza regolando diversi parametri come la sensibilità del salto,
il volume della musica e i tasti di controllo del personaggio. Inoltre, è
possibile effettuare la calibrazione della velocità della propria tastiera con
cui viene ricaricata la forza di un salto. Grazie all’interfaccia grafica
l’utente può navigare tra le varie opzioni utilizzando input da tastiera. Una
volta che l’utente ha effettuato le modifiche desiderate ed è uscito dalle
impostazioni, modifiche vengono automaticamente salvate e memorizzate per le
sessioni di gioco successive.
\subsection{Market, Ability, Gun e Events}
Le armi, allo stesso modo delle abilità, sono rappresentate da una classe
specifica, rispettivamente \texttt{Gun} e \texttt{Ability}, dove vengono
differenziate per i parametri al loro intero. Per esempio il nome, il costo e il
tempo di ricarica di un'arma. Questo permette di implementare una sola volta
tutte le funzioni che necessitano di avere in input armi o abilità e fare i
controlli necessari per distinguerle al loro interno.
Events è la classe che gestisce le abilità e il loro tempo di ricarica. Queste
ultime, infatti, dopo essere acquistate rimangono al giocatore, che però le può
utilizzare solo successivamente a ogni periodo di ricarica. Una barra in alto a
destra nella schermata di gioco mostra se si può utilizzare l'abilità, se si sta
scaricando o se si sta caricando.
\subsection{Random}
Fulcro di questa classe è il \texttt{seed}, ovvero un intero generato
casualmente all'avvio di una nuova partita e che viene associato a essa; grazie
a questo dato, la classe \texttt{Random} genera l'ordine dei chunk, la posizione
delle monete e gli attributi dei nemici utilizzando la generazione di numeri
casuali inclusa in \CC. Questo metodo ci garantisce la assoluta unicità di ogni
partita e semplifica molto il salvataggio: non è infatti necessario salvare gli
infiniti valori associati all'ordine dei chunk e alla posizione delle entità, ma
sarà sufficiente memorizzare il seed associato alla mappa, in quanto le funzioni
pseudocasuali presenti nel linguaggio generano la stessa sequenza di numeri a
partire dallo stesso seed.
\subsection{Map, Chunk, Platform}
Queste tre classi si occupano della gestione della mappa di gioco. La classe
\texttt{Platform} definisce una singola piattaforma nel gioco, che possiede come
attributi la lunghezza e le coordinate in cui si trova. La classe \texttt{Chunk}
invece rappresenta una sezione del livello di gioco e come attributo possiede
un vettore di oggetti \texttt{Platform}; la gestione delle collisioni si
interfaccia con questa classe per conoscere se in un certo punto c'è una
piattaforma. La classe \texttt{Map} infine rappresenta il livello generale del
gioco; qui vengono inizializzati i 10 chunk che vengono selezionati in maniera
randomica per formare l'infinita mappa di gioco; ogni mappa è caratterizzata da
un \texttt{seed} univoco.
\subsection{File}
La classe \texttt{File} è preposta ad interfacciarsi con i salvataggi, sia dei
progressi che delle impostazioni. Nel file \texttt{save.txt} vengono scritti e
aggiornati tutti i valori della partita attuale, quindi nome, seed, posizione
nella mappa del giocatore, entità, oggetti acquistati nel market e valori delle
statistiche; invece, nel file \texttt{settings.txt} vengono memorizzati i tasti
scelti dal giocatore per i comandi di gioco e le sue preferenze riguardo a
volume e sensibilità. Oltre a svolgere la funzione di scrittura, la classe si
occupa anche di leggere i file e trasferire i dati alla classe Game per
ricaricare impostazioni e salvataggi memorizzati in precedenti partite.
\subsection{Fisica}
Tutta la libraria di fisica si ragruppa sotto lo stesso \texttt{namespace}
denominato \texttt{phy}. Lo scopo di questa libreria è finalizzato soltanto alla
simulazione dei salti del giocatore e al movimento dei proiettili, soprattutto
quelli più complessi come quelli prodotti dal \textit{lancia granate}. Sono
quindi presenti solo gli elementi necessari a simulare il movimento di un punto
nello spazio dotato di posizione, velocità e accelerazione. La posizione in
particolare è rappresentata dalla classe \texttt{Point} e sia la velocità che
l'accelerazione, in quanto vettori, vengono rappresentati mediante la classe
\texttt{Vector}\footnote{Attenzione a non confodersi con i nomi della classi.
Quella citata è più precisamente la classe \texttt{phy::Vector}, in quanto
esiste anche la re-implementazione del vettore della libreria standar di \CC\
che invece è identificata dal \texttt{namespace nostd}}. Durante i test si è
notato però che alcuni oggetti avevano necessità di memorizzare la loro
posizione tramite stadi intermedi, senza quindi seguire forzatamente la
rappresentazione intera della posizione fornita dalla classe \texttt{Point}. È
quindi stata creata una ulteriore classe apposita identificata come
\texttt{PrecisesPoint}. Non si è deciso di rimuovere completamente la precedente
\texttt{Point} per una questione di ottimizzazione: fornendo una
rappresentazione estremamente più precisa della posizione, la classe
\texttt{PrecisesPoint} è necessariamente più pesane in memoria e più complessa
da gestire. Dove quindi era possibile evitarla si è continuato a fare uso della
semplice rappresentazione intera della posizione fornita dalla classe originale.
La classe \texttt{Body} è una semplice rappresentazione di un corpo puntiforme
privo di massa con la capacità di muoversi nello spazio: incorpora quindi tutti
i campi necessari per la posizione, velocità e accelerazione.
Le collisioni tra il giocatore e le piattaforme presenti nella mappa sono
gestite sempre dalla libraria di fisica. In particolare sono calcolate partendo
dalla posizione attuale del giocatore, successivamente si aggiorna la sua
posizione in base alla sua velocità e accelerazione. Si esegue quindi un
confronto tra la vecchia posizione e la nuova, controllando che nello
spostamento il giocatore non abbia colliso con nessun oggetto. Nel caso però una
collisione si sia verificata, viene spostato il giocatore nel punto della
collisione e vengono aggiornate velocità e accelerazione per rendere
approssimativamente l'effetto del trasferimento di energia cinetica avvenuto
durante la collisione, nonostante il calcolo dell'energia non sia effettivamente
eseguito.
\end{document}