summary refs log tree commit diff stats
path: root/hslist.cpp
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2023-11-02 18:38:53 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2023-11-02 18:38:53 -0400
commita59fcafb2e81f3cb40ff320b106030e8fed4bd66 (patch)
tree7e7396a9422814365a5f903a53d7391d3e7b22fd /hslist.cpp
parent45d6e635c880a7fae8711fba366519dd314d9faf (diff)
downloadmazeoflife-a59fcafb2e81f3cb40ff320b106030e8fed4bd66.tar.gz
mazeoflife-a59fcafb2e81f3cb40ff320b106030e8fed4bd66.tar.bz2
mazeoflife-a59fcafb2e81f3cb40ff320b106030e8fed4bd66.zip
Modernized C++ a bit (and removed global highscores) HEAD master
Diffstat (limited to 'hslist.cpp')
-rw-r--r--hslist.cpp969
1 files changed, 73 insertions, 896 deletions
diff --git a/hslist.cpp b/hslist.cpp index 5eb9b6c..9ae2aa4 100644 --- a/hslist.cpp +++ b/hslist.cpp
@@ -5,946 +5,123 @@
5 5
6#include <algorithm> 6#include <algorithm>
7#include <fstream> 7#include <fstream>
8#include <memory>
8#include <sstream> 9#include <sstream>
9 10
10#include "gamestate.h" 11#include "gamestate.h"
11#include "titlestate.h" 12#include "titlestate.h"
12#include "util.h" 13#include "util.h"
13 14
14// We want to be able to sort Highscore objects in descending score order 15HighscoreList::HighscoreList(std::vector<Highscore> hslist) : hslist_(hslist) {
15struct hslist_comp { 16 resetRanks();
16 bool operator()(Highscore* lhs, Highscore* rhs) const { 17}
17 return (lhs->getLevel() > rhs->getLevel());
18 }
19} hslist_comp_i;
20 18
21// resetRanks : sets the rank of all Highscore objects in a hslist_t to their 19void HighscoreList::resetRanks() {
22// (one-based) index in the list
23void resetRanks(hslist_t in) {
24 int i = 1; 20 int i = 1;
25 for (hslist_t::iterator it = in.begin(); it != in.end(); ++it, ++i) { 21 for (Highscore& hs : hslist_) {
26 ((Highscore*)*it)->setRank(i); 22 hs.setRank(i++);
27 } 23 }
28} 24}
29 25
30SDL_Surface* HighscoreList::render() { 26surface_ptr HighscoreList::render() {
31 SDL_Surface* tmp = SDL_CreateRGBSurface(0, 480, 480, 32, 0, 0, 0, 0); 27 surface_ptr tmp =
28 surface_ptr(SDL_CreateRGBSurface(0, 480, 480, 32, 0, 0, 0, 0));
32 Uint32 bgColor = SDL_MapRGB(tmp->format, 255, 255, 255); 29 Uint32 bgColor = SDL_MapRGB(tmp->format, 255, 255, 255);
33 SDL_FillRect(tmp, NULL, bgColor); 30 SDL_FillRect(tmp.get(), NULL, bgColor);
34 SDL_SetColorKey(tmp, SDL_TRUE, bgColor); 31 SDL_SetColorKey(tmp.get(), SDL_TRUE, bgColor);
35 TTF_Font* posFont = loadFont(40); 32 font_ptr posFont = loadFont(40);
36 TTF_Font* dataFont = loadFont(25); 33 font_ptr dataFont = loadFont(25);
37 SDL_Color fontColor = {0, 0, 0, 0}; 34 SDL_Color fontColor = {0, 0, 0, 0};
38 35
39 int i = 0; 36 for (const Highscore& h : hslist_) {
40 for (hslist_t::iterator it = hslist.begin(); it != hslist.end(); ++it, ++i) {
41 Highscore* h = *it;
42
43 int posw, posh; 37 int posw, posh;
44 char pos[4]; // 2 max characters in rank plus the colon at the end, plus 38
45 // terminator 39 std::ostringstream posstr;
46 sprintf(pos, "%d:", h->getRank()); 40 posstr << h.getRank() << ":";
47 TTF_SizeText(posFont, pos, &posw, &posh); 41
48 SDL_Rect posSpace = {0, (i + 1) * 40, posw, posh}; 42 std::string pos = posstr.str();
49 SDL_BlitSurface(TTF_RenderText_Blended(posFont, pos, fontColor), NULL, tmp, 43 TTF_SizeText(posFont.get(), pos.c_str(), &posw, &posh);
50 &posSpace); 44 SDL_Rect posSpace = {0, h.getRank() * 40, posw, posh};
45 SDL_BlitSurface(
46 TTF_RenderText_Blended(posFont.get(), pos.c_str(), fontColor), NULL,
47 tmp.get(), &posSpace);
48
49 std::ostringstream namestr;
50 namestr << " " << h.getName();
51 51
52 int namew, nameh; 52 int namew, nameh;
53 char name[27]; // 25 max characters in username plus the space at the 53 std::string name = namestr.str();
54 // beginning, plus terminator 54 TTF_SizeText(dataFont.get(), name.c_str(), &namew, &nameh);
55 sprintf(name, " %s", h->getName()); 55 SDL_Rect nameSpace = {posw, h.getRank() * 40 + ((posh / 2) - (nameh / 2)),
56 TTF_SizeText(dataFont, name, &namew, &nameh);
57 SDL_Rect nameSpace = {posw, (i + 1) * 40 + ((posh / 2) - (nameh / 2)),
58 namew, nameh}; 56 namew, nameh};
59 SDL_BlitSurface(TTF_RenderText_Blended(dataFont, name, fontColor), NULL, 57 SDL_BlitSurface(
60 tmp, &nameSpace); 58 TTF_RenderText_Blended(dataFont.get(), name.c_str(), fontColor), NULL,
59 tmp.get(), &nameSpace);
61 60
62 int lvlw, lvlh; 61 int lvlw, lvlh;
63 char lvl[11]; // 10 max characters in level (based off the fact that 2^32-1 62 std::string lvl = std::to_string(h.getLevel());
64 // is 10 characters long, and is the highest int), plus 63 TTF_SizeText(dataFont.get(), lvl.c_str(), &lvlw, &lvlh);
65 // terminator 64 SDL_Rect lvlSpace = {
66 sprintf(lvl, "%d", h->getLevel()); 65 480 - lvlw, h.getRank() * 40 + ((posh / 2) - (nameh / 2)), lvlw, lvlh};
67 TTF_SizeText(dataFont, lvl, &lvlw, &lvlh); 66 SDL_BlitSurface(
68 SDL_Rect lvlSpace = {480 - lvlw, (i + 1) * 40 + ((posh / 2) - (nameh / 2)), 67 TTF_RenderText_Blended(dataFont.get(), lvl.c_str(), fontColor), NULL,
69 lvlw, lvlh}; 68 tmp.get(), &lvlSpace);
70 SDL_BlitSurface(TTF_RenderText_Blended(dataFont, lvl, fontColor), NULL, tmp,
71 &lvlSpace);
72 } 69 }
73 70
74 return tmp; 71 return tmp;
75} 72}
76 73
77hslist_t HighscoreList::getLocalHighscores() { 74std::unique_ptr<HighscoreList> HighscoreList::GetLocalHighscores() {
78 hslist_t temp; 75 std::vector<Highscore> hslist;
79 76
80 std::ifstream exists(getDataFile()); 77 std::ifstream hsstream(getDataFile());
81 if (exists) { 78 if (hsstream) {
82 FILE* hslist = fopen(getDataFile(), "r"); 79 int num_scores = 0;
83 int scores; 80 hsstream >> num_scores;
84 fscanf(hslist, "%d%*c", &scores);
85 81
86 for (int i = 0; i < scores; i++) { 82 for (int i = 0; i < num_scores; i++) {
87 int namelen; 83 std::string name;
88 char namelens[4];
89 char* name = (char*)calloc(25, sizeof(char));
90 int score; 84 int score;
91 85
92 fscanf(hslist, "%d", &namelen); 86 hsstream >> name;
93 sprintf(namelens, "%%%dc", namelen); 87 hsstream >> score;
94 fscanf(hslist, namelens, name);
95 fscanf(hslist, "%d%*c", &score);
96
97 Highscore* h = new Highscore(name, score);
98 h->setRank(i + 1);
99 88
100 temp.push_back(h); 89 hslist.emplace_back(name, score);
101 } 90 }
102
103 fclose(hslist);
104 } 91 }
105 92
106 return temp; 93 return std::unique_ptr<HighscoreList>(new HighscoreList(hslist));
107} 94}
108 95
109hslist_t HighscoreList::getGlobalHighscores() { 96int HighscoreList::addHighscore(Highscore h) {
110 IPaddress ipaddress; 97 int i = 1;
111
112 if (SDLNet_ResolveHost(&ipaddress, "other.fourisland.com", 80) == -1) {
113 printf("Could not resolve host \"other.fourisland.com\": %s\n",
114 SDLNet_GetError());
115 throw 1;
116 }
117
118 TCPsocket tcpsock = SDLNet_TCP_Open(&ipaddress);
119 if (!tcpsock) {
120 printf("Could not connect to host \"other.fourisland.com\": %s\n",
121 SDLNet_GetError());
122 throw 2;
123 }
124
125 const char* headers =
126 "GET /mol/hslist.php HTTP/1.1\nHost: other.fourisland.com\nUser-Agent: "
127 "Maze Of Life v3.0\nAccept: text/plain\nKeep-Alive: 300\nConnection: "
128 "keep-alive\n\n";
129 if (SDLNet_TCP_Send(tcpsock, headers, strlen(headers) + 1) <
130 strlen(headers)) {
131 printf("Connection closed by peer: %s\n", SDLNet_GetError());
132 throw 3;
133 }
134
135 std::stringstream download(std::stringstream::in | std::stringstream::out);
136 char hslist[1024];
137 SDLNet_TCP_Recv(tcpsock, hslist, 1024);
138 download << hslist;
139 SDLNet_TCP_Close(tcpsock);
140
141 char temps[256];
142 download.getline(temps, 256);
143 while (strlen(temps) != 1) {
144 download.getline(temps, 256);
145 }
146
147 hslist_t temp;
148 int scores;
149 download.getline(temps, 256);
150 if (sscanf(temps, "%d%*c", &scores) != 1) {
151 printf("Recieved data is of an invalid format: %s\n", temps);
152 throw 4;
153 }
154
155 for (int i = 0; i < scores; i++) {
156 int namelen;
157 char namelens[13];
158 char* name = (char*)calloc(25, sizeof(char));
159 int score;
160 download.getline(temps, 256);
161
162 if (sscanf(temps, "%d", &namelen) != 1) {
163 printf("Recieved data is of an invalid format (1-%d): %s\n", i, temps);
164 throw 4;
165 }
166
167 sprintf(namelens, "%%*d%%%dc", namelen);
168
169 if (sscanf(temps, namelens, name) != 1) {
170 printf("Recieved data is of an invalid format (2-%d): %s\n", i, temps);
171 throw 4;
172 }
173
174 sprintf(namelens, "%%*d%%*%dc%%d", namelen);
175
176 if (sscanf(temps, namelens, &score) != 1) {
177 printf("Recieved data is of an invalid format (3-%d): %s\n", i, temps);
178 throw 4;
179 }
180
181 Highscore* h = new Highscore(name, score);
182 h->setRank(i + 1);
183
184 temp.push_back(h);
185 }
186
187 return temp;
188}
189
190LocalHighscoreList::LocalHighscoreList() {
191 this->hslist = getLocalHighscores();
192}
193
194int LocalHighscoreList::addHighscore(Highscore* h) {
195 hslist.push_back(h);
196 std::sort(hslist.begin(), hslist.end(), hslist_comp_i);
197 resetRanks(hslist);
198
199 if (hslist.size() > 10) {
200 hslist.resize(10);
201 }
202
203 return h->getRank();
204}
205
206void LocalHighscoreList::writeHighscores() {
207 FILE* hsfile = fopen(getDataFile(), "w");
208 fprintf(hsfile, "%d ", (int)this->hslist.size());
209
210 for (hslist_t::iterator it = hslist.begin(); it != this->hslist.end(); it++) {
211 Highscore* h = *it;
212
213 fprintf(hsfile, "%d%s%d ", (int)strlen(h->getName()), h->getName(),
214 h->getLevel());
215 }
216
217 fclose(hsfile);
218}
219
220GlobalHighscoreList::GlobalHighscoreList() {
221 fail = false;
222
223 try {
224 this->hslist = getGlobalHighscores();
225 } catch (int e) {
226 fail = true;
227 }
228}
229
230GlobalHighscoreList::GlobalHighscoreList(Highscore* h) {
231 fail = false;
232
233 try {
234 IPaddress ipaddress;
235
236 if (SDLNet_ResolveHost(&ipaddress, "other.fourisland.com", 80) == -1) {
237 printf("Could not resolve host \"other.fourisland.com\": %s\n",
238 SDLNet_GetError());
239 throw 1;
240 }
241
242 TCPsocket tcpsock = SDLNet_TCP_Open(&ipaddress);
243 if (!tcpsock) {
244 printf("Could not connect to host \"other.fourisland.com\": %s\n",
245 SDLNet_GetError());
246 throw 2;
247 }
248
249 char body[256];
250 sprintf(body, "name=%s&level=%d", h->getName(), h->getLevel());
251 char headers[256];
252 sprintf(
253 headers,
254 "POST /mol/hslist.php?add HTTP/1.1\nHost: "
255 "other.fourisland.com\nUser-Agent: Maze Of Life v2.0\nAccept: "
256 "text/plain\nKeep-Alive: 300\nConnection: keep-alive\nContent-Type: "
257 "application/x-www-form-urlencoded\nContent-Length: %d\n\n%s\n",
258 (int)strlen(body), body);
259 if (SDLNet_TCP_Send(tcpsock, headers, strlen(headers) + 1) <
260 strlen(headers)) {
261 printf("Connection closed by peer: %s\n", SDLNet_GetError());
262 throw 3;
263 }
264
265 std::stringstream download(std::stringstream::in | std::stringstream::out);
266 char hslist[1024];
267 SDLNet_TCP_Recv(tcpsock, hslist, 1024);
268 download << hslist;
269 SDLNet_TCP_Close(tcpsock);
270
271 char temps[256];
272 download.getline(temps, 256);
273 while (strlen(temps) != 1) {
274 download.getline(temps, 256);
275 }
276
277 int rank;
278 download.getline(temps, 256);
279 if (sscanf(temps, "%d%*c", &rank) != 1) {
280 printf("Recieved data is of an invalid format: %s\n", temps);
281 throw 4;
282 }
283
284 this->hslist = getGlobalHighscores();
285
286 if (this->hslist.empty()) {
287 printf(
288 "Global Highscore List cannot be empty after adding a score to "
289 "it.\n");
290 throw 5;
291 }
292
293 if (rank > 10) {
294 h->setRank(rank);
295
296 this->hslist[9] = h;
297 } else {
298 this->hslist.push_back(h);
299 std::sort(this->hslist.begin(), this->hslist.end(), hslist_comp_i);
300 resetRanks(this->hslist);
301
302 if (this->hslist.size() > 10) {
303 this->hslist.resize(10);
304 }
305 }
306 } catch (int e) {
307 fail = true;
308 }
309}
310
311SDL_Surface* GlobalHighscoreList::render() {
312 if (fail) {
313 SDL_Surface* tmp = SDL_CreateRGBSurface(0, 480, 480, 32, 0, 0, 0, 0);
314 Uint32 bgColor = SDL_MapRGB(tmp->format, 255, 255, 255);
315 SDL_FillRect(tmp, NULL, bgColor);
316 SDL_SetColorKey(tmp, SDL_TRUE, bgColor);
317 TTF_Font* dataFont = loadFont(25);
318 SDL_Color fontColor = {0, 0, 0, 0};
319 SDL_Surface* text = TTF_RenderText_Blended(
320 dataFont, "Error retrieving highscores", fontColor);
321 SDL_Rect tSpace = {240 - (text->w / 2), 240 - (text->h / 2), text->w,
322 text->h};
323 SDL_BlitSurface(text, NULL, tmp, &tSpace);
324
325 return tmp;
326 } else {
327 return super::render();
328 }
329}
330
331bool GlobalHighscoreList::didFail() { return fail; }
332
333State* ChooseHighscoreListState::operator()(SDL_Window* window,
334 SDL_Renderer* renderer) {
335 SDL_Texture* background = loadImage(renderer, "resources/chl.bmp");
336 SDL_Texture* pointer = loadImage(renderer, "resources/pointer.bmp");
337 int selection = 0;
338 SDL_Event e;
339
340 for (;;) {
341 SDL_RenderClear(renderer);
342 SDL_RenderCopy(renderer, background, NULL, NULL);
343 applyTexture(renderer, pointer, 127,
344 selection == 0 ? 306 : (selection == 1 ? 336 : 396));
345 SDL_RenderPresent(renderer);
346
347 while (SDL_PollEvent(&e)) {
348 if (e.type == SDL_QUIT) {
349 return NULL;
350 } else if (e.type == SDL_KEYDOWN) {
351 if ((e.key.keysym.sym == SDLK_UP) && (selection != 0)) {
352 selection--;
353 } else if ((e.key.keysym.sym == SDLK_DOWN) && (selection != 2)) {
354 selection++;
355 } else if (e.key.keysym.sym == SDLK_RETURN) {
356 switch (selection) {
357 case 0:
358 return new DisplayLocalHighscoreListState();
359 case 1:
360 return new DisplayGlobalHighscoreListState();
361 case 2:
362 return new TitleState();
363 }
364 }
365 }
366 }
367 }
368}
369
370State* DisplayLocalHighscoreListState::operator()(SDL_Window* window,
371 SDL_Renderer* renderer) {
372 SDL_Texture* pointer = loadImage(renderer, "resources/pointer.bmp");
373
374 LocalHighscoreList* lhl = new LocalHighscoreList();
375 SDL_Surface* list_s = lhl->render();
376 SDL_Color fontColor = {0, 0, 0, 0};
377 SDL_Surface* title =
378 TTF_RenderText_Blended(loadFont(40), "Highscore List", fontColor);
379 SDL_Rect tSpace = {240 - (title->w / 2), 0, title->w, title->h};
380 SDL_BlitSurface(title, NULL, list_s, &tSpace);
381 SDL_FreeSurface(title);
382
383 SDL_Surface* options_s = SDL_LoadBMP("resources/hlo_rtm.bmp");
384 SDL_Rect oSpace = {0, 440, options_s->w, options_s->h};
385 SDL_BlitSurface(options_s, NULL, list_s, &oSpace);
386 SDL_FreeSurface(options_s);
387
388 SDL_Texture* list = SDL_CreateTextureFromSurface(renderer, list_s);
389 SDL_FreeSurface(list_s);
390
391 SDL_Event e;
392
393 for (;;) {
394 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
395 SDL_RenderClear(renderer);
396 SDL_RenderCopy(renderer, list, NULL, NULL);
397 applyTexture(renderer, pointer, 137, 449);
398 SDL_RenderPresent(renderer);
399
400 while (SDL_PollEvent(&e)) {
401 if (e.type == SDL_QUIT) {
402 return NULL;
403 } else if (e.type == SDL_KEYDOWN) {
404 if (e.key.keysym.sym == SDLK_RETURN) {
405 return new ChooseHighscoreListState();
406 }
407 }
408 }
409 }
410}
411
412State* DisplayAndReturnLocalHighscoreListState::operator()(
413 SDL_Window* window, SDL_Renderer* renderer) {
414 SDL_Texture* pointer = loadImage(renderer, "resources/pointer.bmp");
415
416 LocalHighscoreList* lhl = new LocalHighscoreList();
417 SDL_Surface* list_s = lhl->render();
418 SDL_Color fontColor = {0, 0, 0, 0};
419 SDL_Surface* title =
420 TTF_RenderText_Blended(loadFont(40), "Highscore List", fontColor);
421 SDL_Rect tSpace = {240 - (title->w / 2), 0, title->w, title->h};
422 SDL_BlitSurface(title, NULL, list_s, &tSpace);
423 SDL_FreeSurface(title);
424
425 SDL_Surface* options_s = SDL_LoadBMP("resources/hlo_paartm.bmp");
426 SDL_Rect oSpace = {0, 440, options_s->w, options_s->h};
427 SDL_BlitSurface(options_s, NULL, list_s, &oSpace);
428 SDL_FreeSurface(options_s);
429
430 SDL_Texture* list = SDL_CreateTextureFromSurface(renderer, list_s);
431 SDL_FreeSurface(list_s);
432
433 int selection = 0;
434 SDL_Event e;
435
436 for (;;) {
437 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
438 SDL_RenderClear(renderer);
439 SDL_RenderCopy(renderer, list, NULL, NULL);
440 applyTexture(renderer, pointer, selection == 0 ? 52 : 225, 447);
441 SDL_RenderPresent(renderer);
442
443 while (SDL_PollEvent(&e)) {
444 if (e.type == SDL_QUIT) {
445 return NULL;
446 } else if (e.type == SDL_KEYDOWN) {
447 if ((e.key.keysym.sym == SDLK_LEFT) && (selection != 0)) {
448 selection--;
449 } else if ((e.key.keysym.sym == SDLK_RIGHT) && (selection != 1)) {
450 selection++;
451 } else if (e.key.keysym.sym == SDLK_RETURN) {
452 switch (selection) {
453 case 0:
454 return new GameState();
455 case 1:
456 return new TitleState();
457 }
458 }
459 }
460 }
461 }
462}
463
464State* DisplayGlobalHighscoreListState::operator()(SDL_Window* window,
465 SDL_Renderer* renderer) {
466 SDL_Texture* pointer = loadImage(renderer, "resources/pointer.bmp");
467
468 // Display loading message
469 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
470 SDL_RenderClear(renderer);
471
472 SDL_Surface* list_s = SDL_CreateRGBSurface(0, 480, 480, 32, 0, 0, 0, 0);
473 Uint32 bgColor = SDL_MapRGB(list_s->format, 255, 255, 255);
474 SDL_FillRect(list_s, NULL, bgColor);
475 SDL_SetColorKey(list_s, SDL_TRUE, bgColor);
476 TTF_Font* dataFont = loadFont(25);
477 SDL_Color fontColor = {0, 0, 0, 0};
478 SDL_Surface* text =
479 TTF_RenderText_Blended(dataFont, "Fetching highscores....", fontColor);
480 SDL_Rect aSpace = {240 - (text->w / 2), 240 - (text->h / 2), text->w,
481 text->h};
482 SDL_BlitSurface(text, NULL, list_s, &aSpace);
483 SDL_FreeSurface(text);
484
485 SDL_Surface* title =
486 TTF_RenderText_Blended(loadFont(40), "Highscore List", fontColor);
487 SDL_Rect tSpace = {240 - (title->w / 2), 0, title->w, title->h};
488 SDL_BlitSurface(title, NULL, list_s, &tSpace);
489 SDL_FreeSurface(title);
490
491 SDL_Surface* options_s = SDL_LoadBMP("resources/hlo_rtm.bmp");
492 SDL_Rect oSpace = {0, 440, options_s->w, options_s->h};
493 SDL_BlitSurface(options_s, NULL, list_s, &oSpace);
494 SDL_FreeSurface(options_s);
495
496 list = SDL_CreateTextureFromSurface(renderer, list_s);
497 SDL_FreeSurface(list_s);
498
499 m = SDL_CreateMutex();
500
501 // Start downloading scores
502 SDL_CreateThread(&LoadHighscoreList, "LoadHighscoreList", this);
503
504 // Parse keyboard events
505 SDL_Event e;
506
507 for (;;) {
508 if (SDL_LockMutex(m) == 0) {
509 if (lhl != NULL) {
510 SDL_Surface* list_s = lhl->render();
511
512 SDL_Color fontColor = {0, 0, 0, 0};
513 SDL_Surface* title =
514 TTF_RenderText_Blended(loadFont(40), "Highscore List", fontColor);
515 SDL_Rect tSpace = {240 - (title->w / 2), 0, title->w, title->h};
516 SDL_BlitSurface(title, NULL, list_s, &tSpace);
517 SDL_FreeSurface(title);
518
519 SDL_Surface* options_s = SDL_LoadBMP("resources/hlo_rtm.bmp");
520 SDL_Rect oSpace = {0, 440, options_s->w, options_s->h};
521 SDL_BlitSurface(options_s, NULL, list_s, &oSpace);
522 SDL_FreeSurface(options_s);
523
524 list = SDL_CreateTextureFromSurface(renderer, list_s);
525 SDL_FreeSurface(list_s);
526
527 lhl = NULL;
528 }
529
530 SDL_UnlockMutex(m);
531 }
532
533 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
534 SDL_RenderClear(renderer);
535 SDL_RenderCopy(renderer, list, NULL, NULL);
536 applyTexture(renderer, pointer, 137, 449);
537 SDL_RenderPresent(renderer);
538
539 while (SDL_PollEvent(&e)) {
540 if (e.type == SDL_QUIT) {
541 SDL_DestroyMutex(m);
542
543 return NULL;
544 } else if (e.type == SDL_KEYDOWN) {
545 if (e.key.keysym.sym == SDLK_RETURN) {
546 SDL_DestroyMutex(m);
547
548 return new ChooseHighscoreListState();
549 }
550 }
551 }
552 }
553}
554
555int DisplayGlobalHighscoreListState::LoadHighscoreList(void* pParam) {
556 DisplayGlobalHighscoreListState* parent =
557 ((DisplayGlobalHighscoreListState*)pParam);
558 if (SDL_LockMutex(parent->m) == 0) {
559 parent->lhl = new GlobalHighscoreList();
560
561 SDL_UnlockMutex(parent->m);
562 } else {
563 printf("Couldn't lock mutex: %s\n", SDL_GetError());
564 }
565}
566
567EnterHighscoreState::EnterHighscoreState(int level) { this->level = level; }
568
569State* EnterHighscoreState::operator()(SDL_Window* window,
570 SDL_Renderer* renderer) {
571 SDL_Texture* pointer = loadImage(renderer, "resources/pointer.bmp");
572
573 // Render highscore list
574 LocalHighscoreList* lhl = new LocalHighscoreList();
575 char* emp = new char[1];
576 emp[0] = 0;
577 Highscore* h = new Highscore(emp, level);
578 int newpos = lhl->addHighscore(h);
579
580 SDL_Surface* list_s = lhl->render();
581
582 SDL_Color fontColor = {0, 0, 0, 0};
583 SDL_Surface* title =
584 TTF_RenderText_Blended(loadFont(40), "New Highscore!", fontColor);
585 SDL_Rect tSpace = {240 - (title->w / 2), 0, title->w, title->h};
586 SDL_BlitSurface(title, NULL, list_s, &tSpace);
587 SDL_FreeSurface(title);
588
589 this->lp = 0;
590 this->hsname = (char*)calloc(25, sizeof(char));
591
592 SDL_Surface* text =
593 TTF_RenderText_Blended(loadFont(25), "Enter Your Name", fontColor);
594 SDL_Rect oSpace = {240 - (text->w / 2), 440, text->w, text->h};
595 SDL_BlitSurface(text, NULL, list_s, &oSpace);
596 SDL_FreeSurface(text);
597
598 SDL_Texture* list = SDL_CreateTextureFromSurface(renderer, list_s);
599 SDL_FreeSurface(list_s);
600
601 int selection = 0;
602 SDL_Event e;
603
604 int posw, posh;
605 char pos[3]; // 2 max characters in rank plus the colon at the end
606 sprintf(pos, "%d:", newpos);
607 char name[26]; // 25 max characters in username plus the space at the
608 // beginning
609 sprintf(name, " %s", hsname);
610 SDL_Surface* newName_s =
611 TTF_RenderText_Blended(loadFont(25), name, fontColor);
612 TTF_SizeText(loadFont(40), pos, &posw, &posh);
613 SDL_Rect rntSpace;
614 rntSpace.x = posw;
615 rntSpace.y = newpos * 40 + ((posh / 2) - (newName_s->h / 2));
616 rntSpace.w = newName_s->w;
617 rntSpace.h = newName_s->h;
618 newName = SDL_CreateTextureFromSurface(renderer, newName_s);
619 SDL_FreeSurface(newName_s);
620
621 for (;;) {
622 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
623 SDL_RenderClear(renderer);
624
625 SDL_Rect eSpace = {0, newpos * 40, 480, 40};
626 SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
627 SDL_RenderFillRect(renderer, &eSpace);
628
629 SDL_RenderCopy(renderer, list, NULL, NULL);
630 SDL_RenderCopy(renderer, newName, NULL, &rntSpace);
631
632 SDL_RenderPresent(renderer);
633
634 while (SDL_PollEvent(&e)) {
635 if (e.type == SDL_QUIT) {
636 return NULL;
637 } else if (e.type == SDL_KEYDOWN) {
638 if ((e.key.keysym.sym == SDLK_BACKSPACE) && (lp > 0)) {
639 hsname[--lp] = 0;
640
641 SDL_Color fontColor = {0, 0, 0, 0};
642 char name[26]; // 25 max characters in username plus the space at the
643 // beginning
644 sprintf(name, " %s", hsname);
645 newName_s = TTF_RenderText_Blended(loadFont(25), name, fontColor);
646 rntSpace.w = newName_s->w;
647 rntSpace.h = newName_s->h;
648 newName = SDL_CreateTextureFromSurface(renderer, newName_s);
649 SDL_FreeSurface(newName_s);
650 } else if ((e.key.keysym.sym == SDLK_RETURN) && (hsname[0] != 0)) {
651 lhl = new LocalHighscoreList();
652 Highscore* h2 = new Highscore(hsname, level);
653 lhl->addHighscore(h2);
654 lhl->writeHighscores();
655
656 return new NewHighscoreState(h2);
657 }
658 } else if (e.type == SDL_TEXTINPUT) {
659 if (((*e.text.text & 0xFF80) == 0) &&
660 (*e.text.text >= 32 && *e.text.text < 127) && (lp < 25)) {
661 hsname[lp++] = *e.text.text & 0x7f;
662 hsname[lp] = 0;
663
664 SDL_Color fontColor = {0, 0, 0, 0};
665 char name[26]; // 25 max characters in username plus the space at the
666 // beginning
667 sprintf(name, " %s", hsname);
668 newName_s = TTF_RenderText_Blended(loadFont(25), name, fontColor);
669 rntSpace.w = newName_s->w;
670 rntSpace.h = newName_s->h;
671 newName = SDL_CreateTextureFromSurface(renderer, newName_s);
672 SDL_FreeSurface(newName_s);
673 }
674 }
675 }
676 }
677}
678
679NewHighscoreState::NewHighscoreState(Highscore* h) { this->h = h; }
680
681State* NewHighscoreState::operator()(SDL_Window* window,
682 SDL_Renderer* renderer) {
683 SDL_Texture* pointer = loadImage(renderer, "resources/pointer.bmp");
684
685 // Render highscore list
686 LocalHighscoreList* lhl = new LocalHighscoreList();
687 SDL_Surface* list_s = lhl->render();
688
689 SDL_Color fontColor = {0, 0, 0, 0};
690 SDL_Surface* title =
691 TTF_RenderText_Blended(loadFont(40), "New Highscore!", fontColor);
692 SDL_Rect tSpace = {240 - (title->w / 2), 0, title->w, title->h};
693 SDL_BlitSurface(title, NULL, list_s, &tSpace);
694 SDL_FreeSurface(title);
695
696 SDL_Surface* options_s = SDL_LoadBMP("resources/hlo_passartm.bmp");
697 SDL_Rect oSpace = {0, 440, options_s->w, options_s->h};
698 SDL_BlitSurface(options_s, NULL, list_s, &oSpace);
699 SDL_FreeSurface(options_s);
700
701 SDL_Texture* list = SDL_CreateTextureFromSurface(renderer, list_s);
702 SDL_FreeSurface(list_s);
703
704 int selection = 0;
705 SDL_Event e;
706
707 for (;;) {
708 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
709 SDL_RenderClear(renderer);
710
711 SDL_Rect eSpace = {0, h->getRank() * 40, 480, 40};
712 SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
713 SDL_RenderFillRect(renderer, &eSpace);
714
715 SDL_RenderCopy(renderer, list, NULL, NULL);
716 applyTexture(renderer, pointer,
717 selection == 0 ? 13 : (selection == 1 ? 138 : 284), 448);
718 SDL_RenderPresent(renderer);
719
720 while (SDL_PollEvent(&e)) {
721 if (e.type == SDL_QUIT) {
722 return NULL;
723 } else if (e.type == SDL_KEYDOWN) {
724 if ((e.key.keysym.sym == SDLK_LEFT) && (selection != 0)) {
725 selection--;
726 } else if ((e.key.keysym.sym == SDLK_RIGHT) && (selection != 2)) {
727 selection++;
728 } else if (e.key.keysym.sym == SDLK_RETURN) {
729 switch (selection) {
730 case 0:
731 return new GameState();
732 case 1:
733 return new SubmitHighscoreState(h);
734 case 2:
735 return new TitleState();
736 }
737 }
738 }
739 }
740 }
741}
742
743SubmitHighscoreState::SubmitHighscoreState(Highscore* h) { this->h = h; }
744
745State* SubmitHighscoreState::operator()(SDL_Window* window,
746 SDL_Renderer* renderer) {
747 SDL_Surface* list_s = SDL_CreateRGBSurface(0, 480, 480, 32, 0, 0, 0, 0);
748 Uint32 bgColor = SDL_MapRGB(list_s->format, 255, 255, 255);
749 SDL_FillRect(list_s, NULL, bgColor);
750 SDL_SetColorKey(list_s, SDL_TRUE, bgColor);
751 TTF_Font* dataFont = loadFont(25);
752 SDL_Color fontColor = {0, 0, 0, 0};
753 SDL_Surface* text =
754 TTF_RenderText_Blended(dataFont, "Sending highscore....", fontColor);
755 SDL_Rect aSpace = {240 - (text->w / 2), 240 - (text->h / 2), text->w,
756 text->h};
757 SDL_BlitSurface(text, NULL, list_s, &aSpace);
758 SDL_FreeSurface(text);
759
760 SDL_Surface* title =
761 TTF_RenderText_Blended(loadFont(40), "Highscore List", fontColor);
762 SDL_Rect tSpace = {240 - (title->w / 2), 0, title->w, title->h};
763 SDL_BlitSurface(title, NULL, list_s, &tSpace);
764 SDL_FreeSurface(title);
765
766 SDL_Texture* list = SDL_CreateTextureFromSurface(renderer, list_s);
767 SDL_FreeSurface(list_s);
768
769 // Start submitting score
770 m = SDL_CreateMutex();
771 SDL_CreateThread(&SubmitHighscore, "SubmitHighscore", this);
772
773 SDL_Event e;
774
775 for (;;) {
776 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
777 SDL_RenderClear(renderer);
778 SDL_RenderCopy(renderer, list, NULL, NULL);
779 SDL_RenderPresent(renderer);
780
781 if (SDL_LockMutex(m) == 0) {
782 if (lhl != NULL) {
783 SDL_UnlockMutex(m);
784 SDL_DestroyMutex(m);
785
786 if (lhl->didFail()) {
787 return new FailedSubmittingHighscoreState(h);
788 } else {
789 return new SubmittedHighscoreState(lhl, h);
790 }
791 } else {
792 SDL_UnlockMutex(m);
793 }
794 }
795
796 while (SDL_PollEvent(&e)) {
797 if (e.type == SDL_QUIT) {
798 SDL_DestroyMutex(m);
799 98
800 return NULL; 99 for (const Highscore& cur_h : hslist_) {
801 } 100 if (h.getLevel() > cur_h.getLevel()) {
101 break;
802 } 102 }
103 i++;
803 } 104 }
804}
805
806int SubmitHighscoreState::SubmitHighscore(void* pParam) {
807 SubmitHighscoreState* parent = (SubmitHighscoreState*)pParam;
808 if (SDL_LockMutex(parent->m) == 0) {
809 parent->lhl = new GlobalHighscoreList(parent->h);
810
811 SDL_UnlockMutex(parent->m);
812 } else {
813 printf("Could not lock mutex: %s\n", SDL_GetError());
814 }
815}
816
817FailedSubmittingHighscoreState::FailedSubmittingHighscoreState(Highscore* h) {
818 this->h = h;
819}
820
821State* FailedSubmittingHighscoreState::operator()(SDL_Window* window,
822 SDL_Renderer* renderer) {
823 SDL_Surface* list_s = SDL_CreateRGBSurface(0, 480, 480, 32, 0, 0, 0, 0);
824 Uint32 bgColor = SDL_MapRGB(list_s->format, 255, 255, 255);
825 SDL_FillRect(list_s, NULL, bgColor);
826 SDL_SetColorKey(list_s, SDL_TRUE, bgColor);
827 TTF_Font* dataFont = loadFont(25);
828 SDL_Color fontColor = {0, 0, 0, 0};
829 SDL_Surface* text = TTF_RenderText_Blended(
830 dataFont, "Error submitting highscores", fontColor);
831 SDL_Rect tSpace = {240 - (text->w / 2), 240 - (text->h / 2), text->w,
832 text->h};
833 SDL_BlitSurface(text, NULL, list_s, &tSpace);
834 SDL_FreeSurface(text);
835
836 SDL_Surface* title =
837 TTF_RenderText_Blended(loadFont(40), "Highscore List", fontColor);
838 SDL_Rect aSpace = {240 - (title->w / 2), 0, title->w, title->h};
839 SDL_BlitSurface(title, NULL, list_s, &aSpace);
840 SDL_FreeSurface(title);
841
842 SDL_Surface* options_s = SDL_LoadBMP("resources/hlo_passartm.bmp");
843 SDL_Rect oSpace = {0, 440, options_s->w, options_s->h};
844 SDL_BlitSurface(options_s, NULL, list_s, &oSpace);
845 SDL_FreeSurface(options_s);
846
847 SDL_Texture* list = SDL_CreateTextureFromSurface(renderer, list_s);
848 SDL_FreeSurface(list_s);
849
850 SDL_Texture* pointer = loadImage(renderer, "resources/pointer.bmp");
851 int selection = 0;
852 SDL_Event e;
853 105
854 for (;;) { 106 hslist_.push_back(h);
855 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); 107 std::sort(hslist_.begin(), hslist_.end(),
856 SDL_RenderClear(renderer); 108 [](const Highscore& lhs, const Highscore& rhs) {
857 SDL_RenderCopy(renderer, list, NULL, NULL); 109 return lhs.getLevel() > rhs.getLevel();
858 applyTexture(renderer, pointer, 110 });
859 selection == 0 ? 13 : (selection == 1 ? 138 : 284), 448); 111 resetRanks();
860 SDL_RenderPresent(renderer);
861 112
862 while (SDL_PollEvent(&e)) { 113 if (hslist_.size() > 10) {
863 if (e.type == SDL_QUIT) { 114 hslist_.resize(10);
864 return NULL;
865 } else if (e.type == SDL_KEYDOWN) {
866 if ((e.key.keysym.sym == SDLK_LEFT) && (selection != 0)) {
867 selection--;
868 } else if ((e.key.keysym.sym == SDLK_RIGHT) && (selection != 2)) {
869 selection++;
870 } else if (e.key.keysym.sym == SDLK_RETURN) {
871 switch (selection) {
872 case 0:
873 return new GameState();
874 case 1:
875 return new SubmitHighscoreState(h);
876 case 2:
877 return new TitleState();
878 }
879 }
880 }
881 }
882 } 115 }
883}
884 116
885SubmittedHighscoreState::SubmittedHighscoreState(GlobalHighscoreList* lhl, 117 return i;
886 Highscore* h) {
887 this->lhl = lhl;
888 this->h = h;
889} 118}
890 119
891State* SubmittedHighscoreState::operator()(SDL_Window* window, 120void HighscoreList::writeToFile() {
892 SDL_Renderer* renderer) { 121 std::ofstream hsfile(getDataFile());
893 SDL_Surface* list_s = lhl->render(); 122 hsfile << hslist_.size() << std::endl;
894
895 SDL_Color fontColor = {0, 0, 0, 0};
896 SDL_Surface* title =
897 TTF_RenderText_Blended(loadFont(40), "Highscore List", fontColor);
898 SDL_Rect tSpace = {240 - (title->w / 2), 0, title->w, title->h};
899 SDL_BlitSurface(title, NULL, list_s, &tSpace);
900 SDL_FreeSurface(title);
901
902 SDL_Surface* options_s = SDL_LoadBMP("resources/hlo_paartm.bmp");
903 SDL_Rect oSpace = {0, 440, options_s->w, options_s->h};
904 SDL_BlitSurface(options_s, NULL, list_s, &oSpace);
905 SDL_FreeSurface(options_s);
906
907 SDL_Texture* list = SDL_CreateTextureFromSurface(renderer, list_s);
908 SDL_FreeSurface(list_s);
909
910 SDL_Texture* pointer = loadImage(renderer, "resources/pointer.bmp");
911 int selection = 0;
912 SDL_Event e;
913 123
914 int newpos = h->getRank(); 124 for (const Highscore& h : hslist_) {
915 if (newpos > 10) { 125 hsfile << h.getName() << std::endl << h.getLevel() << std::endl;
916 newpos = 10;
917 }
918
919 for (;;) {
920 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
921 SDL_RenderClear(renderer);
922
923 SDL_Rect eSpace = {0, newpos * 40, 480, 40};
924 SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
925 SDL_RenderFillRect(renderer, &eSpace);
926
927 SDL_RenderCopy(renderer, list, NULL, NULL);
928 applyTexture(renderer, pointer, selection == 0 ? 52 : 225, 447);
929 SDL_RenderPresent(renderer);
930
931 while (SDL_PollEvent(&e)) {
932 if (e.type == SDL_QUIT) {
933 return NULL;
934 } else if (e.type == SDL_KEYDOWN) {
935 if ((e.key.keysym.sym == SDLK_LEFT) && (selection != 0)) {
936 selection--;
937 } else if ((e.key.keysym.sym == SDLK_RIGHT) && (selection != 1)) {
938 selection++;
939 } else if (e.key.keysym.sym == SDLK_RETURN) {
940 switch (selection) {
941 case 0:
942 return new GameState();
943 case 1:
944 return new TitleState();
945 }
946 }
947 }
948 }
949 } 126 }
950} 127}