source: network-game/client/Client/main.cpp@ fd9cdb5

Last change on this file since fd9cdb5 was fd9cdb5, checked in by dportnoy <dmp1488@…>, 11 years ago

Add new player profile screen, accessible from the lobby, which shows the game history and other information.

  • Property mode set to 100644
File size: 46.2 KB
Line 
1#include "../../common/Compiler.h"
2
3#if defined WINDOWS
4 #include <winsock2.h>
5 #include <ws2tcpip.h>
6#elif defined LINUX
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <netdb.h>
12 #include <cstring>
13#elif defined MAC
14 #include <netdb.h>
15#endif
16
17#include <cstdio>
18#include <cstdlib>
19//#include <cmath>
20#include <sys/types.h>
21#include <string>
22#include <iostream>
23#include <sstream>
24#include <fstream>
25#include <map>
26#include <vector>
27#include <stdexcept>
28
29#include <allegro5/allegro.h>
30#include <allegro5/allegro_font.h>
31#include <allegro5/allegro_ttf.h>
32#include <allegro5/allegro_primitives.h>
33
34#include "../../common/Common.h"
35#include "../../common/MessageContainer.h"
36#include "../../common/MessageProcessor.h"
37#include "../../common/WorldMap.h"
38#include "../../common/Player.h"
39#include "../../common/Projectile.h"
40#include "../../common/Game.h"
41#include "../../common/GameSummary.h"
42
43#include "Window.h"
44#include "TextLabel.h"
45#include "Button.h"
46#include "Textbox.h"
47#include "RadioButtonList.h"
48
49#include "GameRender.h"
50
51#include "chat.h"
52
53#ifdef WINDOWS
54 #pragma comment(lib, "ws2_32.lib")
55#endif
56
57using namespace std;
58
59void initWinSock();
60void shutdownWinSock();
61void createGui(ALLEGRO_FONT* font);
62
63void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player*>& mapPlayers, map<string, int>& mapGames, unsigned int& curPlayerId);
64void handleMsgPlayer(NETWORK_MSG &msg, map<unsigned int, Player*>& mapPlayers, map<string, int>& mapGames);
65void handleMsgGameInfo(NETWORK_MSG &msg, map<unsigned int, Player*>& mapPlayers, map<string, int>& mapGames);
66
67int getRefreshRate(int width, int height);
68void drawMessageStatus(ALLEGRO_FONT* font);
69
70// Callback declarations
71void goToLoginScreen();
72void goToRegisterScreen();
73void registerAccount();
74void login();
75void logout();
76void quit();
77void sendChatMessage();
78void toggleDebugging();
79void goToProfileScreen();
80void goToLobbyScreen();
81void joinGame(); // for joining the game lobby
82void createGame(); // for joining the game lobby
83void joinWaitingArea();
84void joinRedTeam();
85void joinBlueTeam();
86void startGame(); // for leaving game lobby and starting the actual game
87void leaveGame();
88void closeGameSummary();
89
90const float FPS = 60;
91const int SCREEN_W = 1024;
92const int SCREEN_H = 768;
93
94enum STATE {
95 STATE_START,
96 STATE_LOBBY,
97 STATE_GAME_LOBBY,
98 STATE_GAME
99};
100
101int state;
102
103bool doexit;
104
105vector<GuiComponent*> vctComponents;
106
107Window* wndLogin;
108Window* wndRegister;
109Window* wndLobby;
110Window* wndLobbyDebug;
111Window* wndProfile;
112Window* wndGameLobby;
113Window* wndGame;
114Window* wndGameSummary;
115Window* wndCurrent;
116
117// wndLogin
118Textbox* txtUsername;
119Textbox* txtPassword;
120TextLabel* lblLoginStatus;
121
122// wndRegister
123Textbox* txtUsernameRegister;
124Textbox* txtPasswordRegister;
125RadioButtonList* rblClasses;
126TextLabel* lblRegisterStatus;
127
128// wndLobby
129Textbox* txtJoinGame;
130Textbox* txtCreateGame;
131Textbox* txtChat;
132
133int sock;
134struct sockaddr_in server, from;
135struct hostent *hp;
136NETWORK_MSG msgTo, msgFrom;
137string username;
138chat chatConsole, debugConsole;
139bool debugging;
140Game* game;
141GameSummary* gameSummary;
142Player* currentPlayer;
143
144MessageProcessor msgProcessor;
145
146int main(int argc, char **argv)
147{
148 ALLEGRO_DISPLAY *display = NULL;
149 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
150 ALLEGRO_TIMER *timer = NULL;
151 map<unsigned int, Player*> mapPlayers;
152 map<string, int> mapGames;
153 unsigned int curPlayerId = -1;
154 ofstream outputLog;
155
156 doexit = false;
157 debugging = false;
158 bool redraw = true;
159 bool fullscreen = false;
160 game = NULL;
161 gameSummary = NULL;
162
163 state = STATE_START;
164
165 if(!al_init()) {
166 fprintf(stderr, "failed to initialize allegro!\n");
167 return -1;
168 }
169
170 outputLog.open("client.log", ios::app);
171 outputLog << "Started client on " << getCurrentDateTimeString() << endl;
172
173 if (al_init_primitives_addon())
174 cout << "Primitives initialized" << endl;
175 else
176 cout << "Primitives not initialized" << endl;
177
178 al_init_font_addon();
179 al_init_ttf_addon();
180
181 ALLEGRO_FONT* font;
182 #if defined WINDOWS
183 font = al_load_ttf_font("../pirulen.ttf", 12, 0);
184 #elif defined LINUX
185 font = al_load_ttf_font("pirulen.ttf", 12, 0);
186 #elif defined MAC
187 font = al_load_ttf_font("pirulen.ttf", 12, 0);
188 #endif
189
190 if (!font) {
191 fprintf(stderr, "Could not load 'pirulen.ttf'.\n");
192 getchar();
193 return -1;
194 }
195
196 if(!al_install_keyboard()) {
197 fprintf(stderr, "failed to initialize the keyboard!\n");
198 return -1;
199 }
200
201 if(!al_install_mouse()) {
202 fprintf(stderr, "failed to initialize the mouse!\n");
203 return -1;
204 }
205
206 timer = al_create_timer(1.0 / FPS);
207 if(!timer) {
208 fprintf(stderr, "failed to create timer!\n");
209 return -1;
210 }
211
212 int refreshRate = getRefreshRate(SCREEN_W, SCREEN_H);
213 // if the computer doesn't support this resolution, just use windowed mode
214 if (refreshRate > 0 && fullscreen) {
215 al_set_new_display_flags(ALLEGRO_FULLSCREEN);
216 al_set_new_display_refresh_rate(refreshRate);
217 }
218 display = al_create_display(SCREEN_W, SCREEN_H);
219 if(!display) {
220 fprintf(stderr, "failed to create display!\n");
221 al_destroy_timer(timer);
222 return -1;
223 }
224
225 debugConsole.addLine("Debug console:");
226 debugConsole.addLine("");
227
228 createGui(font);
229
230 goToLoginScreen();
231
232 event_queue = al_create_event_queue();
233 if(!event_queue) {
234 fprintf(stderr, "failed to create event_queue!\n");
235 al_destroy_display(display);
236 al_destroy_timer(timer);
237 return -1;
238 }
239
240 al_set_target_bitmap(al_get_backbuffer(display));
241
242 al_register_event_source(event_queue, al_get_display_event_source(display));
243 al_register_event_source(event_queue, al_get_timer_event_source(timer));
244 al_register_event_source(event_queue, al_get_keyboard_event_source());
245 al_register_event_source(event_queue, al_get_mouse_event_source());
246
247 al_clear_to_color(al_map_rgb(0,0,0));
248
249 al_flip_display();
250
251 if (argc != 3) {
252 cout << "Usage: server port" << endl;
253 exit(1);
254 }
255
256 initWinSock();
257
258 sock = socket(AF_INET, SOCK_DGRAM, 0);
259 if (sock < 0)
260 error("socket");
261
262 set_nonblock(sock);
263
264 server.sin_family = AF_INET;
265 hp = gethostbyname(argv[1]);
266 if (hp == 0)
267 error("Unknown host");
268
269 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
270 server.sin_port = htons(atoi(argv[2]));
271
272 msgProcessor = MessageProcessor(sock, &outputLog);
273
274 al_start_timer(timer);
275
276 while (!doexit)
277 {
278 ALLEGRO_EVENT ev;
279
280 al_wait_for_event(event_queue, &ev);
281
282 if(wndCurrent->handleEvent(ev)) {
283 // do nothing
284 }
285 else if(ev.type == ALLEGRO_EVENT_TIMER) {
286 redraw = true;
287
288 // remove any other timer events in the queue
289 while (al_peek_next_event(event_queue, &ev) && ev.type == ALLEGRO_EVENT_TIMER) {
290 al_get_next_event(event_queue, &ev);
291 }
292 }
293 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
294 doexit = true;
295 }
296 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
297 }
298 else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
299 switch(ev.keyboard.keycode) {
300 case ALLEGRO_KEY_ESCAPE:
301 doexit = true;
302 break;
303 case ALLEGRO_KEY_S: // pickup an item next to you
304 if (state == STATE_GAME) {
305 msgTo.type = MSG_TYPE_PICKUP_FLAG;
306 memcpy(msgTo.buffer, &curPlayerId, 4);
307 msgProcessor.sendMessage(&msgTo, &server);
308 }
309 break;
310 case ALLEGRO_KEY_D: // drop the current item
311 if (state == STATE_GAME) {
312 try {
313 Player* p = mapPlayers.at(curPlayerId);
314 int flagType = OBJECT_NONE;
315
316 if (p->hasBlueFlag)
317 flagType = OBJECT_BLUE_FLAG;
318 else if (p->hasRedFlag)
319 flagType = OBJECT_RED_FLAG;
320
321 if (flagType != OBJECT_NONE) {
322 msgTo.type = MSG_TYPE_DROP_FLAG;
323 memcpy(msgTo.buffer, &curPlayerId, 4);
324 msgProcessor.sendMessage(&msgTo, &server);
325 }
326 } catch (const out_of_range& ex) {}
327 }
328 break;
329 }
330 }
331 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
332 if (wndCurrent == wndGame) {
333 if (ev.mouse.button == 1) { // left click
334 msgTo.type = MSG_TYPE_PLAYER_MOVE;
335
336 POSITION pos;
337 pos.x = ev.mouse.x;
338 pos.y = ev.mouse.y;
339 pos = screenToMap(pos);
340
341 if (pos.x != -1)
342 {
343 memcpy(msgTo.buffer, &curPlayerId, 4);
344 memcpy(msgTo.buffer+4, &pos.x, 4);
345 memcpy(msgTo.buffer+8, &pos.y, 4);
346
347 msgProcessor.sendMessage(&msgTo, &server);
348 }
349 else
350 cout << "Invalid point: User did not click on the map" << endl;
351 }else if (ev.mouse.button == 2) { // right click
352 cout << "Detected a right-click" << endl;
353 map<unsigned int, Player*>::iterator it;
354
355 Player* curPlayer = mapPlayers[curPlayerId];;
356
357 cout << "Got current player" << endl;
358 cout << "current game: " << game << endl;
359
360 map<unsigned int, Player*> playersInGame = game->getPlayers();
361 Player* target;
362
363 for (it = playersInGame.begin(); it != playersInGame.end(); it++)
364 {
365 target = it->second;
366 cout << "set target" << endl;
367 if (target->team != curPlayer->team)
368 {
369 cout << "Found valid target" << endl;
370
371 POSITION cursorPos;
372 cursorPos.x = ev.mouse.x;
373 cursorPos.y = ev.mouse.y;
374 cursorPos = screenToMap(cursorPos);
375
376 float distance =posDistance(cursorPos.toFloat(), target->pos);
377
378 if (distance < 25) {
379 unsigned int targetId = target->getId();
380
381 msgTo.type = MSG_TYPE_ATTACK;
382 memcpy(msgTo.buffer, &curPlayerId, 4);
383 memcpy(msgTo.buffer+4, &targetId, 4);
384
385 msgProcessor.sendMessage(&msgTo, &server);
386 }
387 }
388 }
389 }
390 }
391 }
392
393 if (msgProcessor.receiveMessage(&msgFrom, &from) >= 0)
394 processMessage(msgFrom, state, chatConsole, mapPlayers, mapGames, curPlayerId);
395
396 if (redraw)
397 {
398 redraw = false;
399
400 msgProcessor.resendUnackedMessages();
401
402 if (debugging && wndCurrent == wndLobby)
403 wndLobbyDebug->draw(display);
404 else
405 wndCurrent->draw(display);
406
407 if (wndCurrent == wndLobby) {
408 if (!debugging)
409 chatConsole.draw(font, al_map_rgb(255,255,255));
410
411 al_draw_text(font, al_map_rgb(0, 255, 0), SCREEN_W*1/2-100, 120, ALLEGRO_ALIGN_LEFT, "Current Games");
412
413 map<string, int>::iterator it;
414 int i=0;
415 ostringstream oss;
416 for (it = mapGames.begin(); it != mapGames.end(); it++) {
417 oss << it->first << " (" << it->second << " players)" << endl;
418 al_draw_text(font, al_map_rgb(0, 255, 0), SCREEN_W*1/2-100, 135+i*15, ALLEGRO_ALIGN_LEFT, oss.str().c_str());
419 oss.clear();
420 oss.str("");
421 i++;
422 }
423
424 al_draw_text(font, al_map_rgb(0, 255, 0), SCREEN_W*3/4-100, 120, ALLEGRO_ALIGN_LEFT, "Online Players");
425
426 map<unsigned int, Player*>::iterator itPlayers;
427 i=0;
428 for (itPlayers = mapPlayers.begin(); itPlayers != mapPlayers.end(); itPlayers++) {
429 oss << itPlayers->second->name << endl;
430 al_draw_text(font, al_map_rgb(0, 255, 0), SCREEN_W*3/4-100, 135+i*15, ALLEGRO_ALIGN_LEFT, oss.str().c_str());
431 oss.clear();
432 oss.str("");
433 i++;
434 }
435 }
436 else if (wndCurrent == wndProfile)
437 {
438 al_draw_text(font, al_map_rgb(0, 255, 0), 65, 90, ALLEGRO_ALIGN_LEFT, "Honor Points: 500");
439
440 // display records of the last 10 games
441 for (int i=0; i<10; i++) {
442 al_draw_text(font, al_map_rgb(0, 255, 0), 142, 160+30*(i+1), ALLEGRO_ALIGN_CENTRE, "VICTORY");
443 al_draw_text(font, al_map_rgb(0, 255, 0), 302, 160+30*(i+1), ALLEGRO_ALIGN_CENTRE, "3");
444 al_draw_text(font, al_map_rgb(0, 255, 0), 462, 160+30*(i+1), ALLEGRO_ALIGN_CENTRE, "2");
445 al_draw_text(font, al_map_rgb(0, 255, 0), 622, 160+30*(i+1), ALLEGRO_ALIGN_CENTRE, "6/11/2014, 5:12 PM");
446 }
447
448 }
449 else if (wndCurrent == wndGameLobby)
450 {
451 al_draw_text(font, al_map_rgb(0, 255, 0), 200, 100, ALLEGRO_ALIGN_LEFT, "Waiting Area");
452 al_draw_text(font, al_map_rgb(0, 255, 0), 400, 100, ALLEGRO_ALIGN_LEFT, "Blue Team");
453 al_draw_text(font, al_map_rgb(0, 255, 0), 600, 100, ALLEGRO_ALIGN_LEFT, "Red Team");
454
455 int drawPosition = 0;
456
457 map<unsigned int, Player*> gamePlayers = game->getPlayers();
458 map<unsigned int, Player*>::iterator itPlayers;
459 ostringstream oss;
460 int i=0;
461 for (itPlayers = gamePlayers.begin(); itPlayers != gamePlayers.end(); itPlayers++) {
462 switch (itPlayers->second->team) {
463 case -1:
464 drawPosition = 200;
465 break;
466 case 0:
467 drawPosition = 400;
468 break;
469 case 1:
470 drawPosition = 600;
471 break;
472 }
473
474 oss << itPlayers->second->name << endl;
475 al_draw_text(font, al_map_rgb(0, 255, 0), drawPosition, 135+i*15, ALLEGRO_ALIGN_LEFT, oss.str().c_str());
476 oss.clear();
477 oss.str("");
478 i++;
479 }
480 }
481 else if (wndCurrent == wndGame)
482 {
483 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 4, ALLEGRO_ALIGN_LEFT, "Players");
484
485 map<unsigned int, Player*>& gamePlayers = game->getPlayers();
486 map<unsigned int, Player*>::iterator it;
487
488 if (!debugging) {
489 int playerCount = 0;
490 for (it = gamePlayers.begin(); it != gamePlayers.end(); it++)
491 {
492 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 19+(playerCount+1)*15, ALLEGRO_ALIGN_LEFT, it->second->name.c_str());
493 playerCount++;
494 }
495 }
496
497 ostringstream ossScoreBlue, ossScoreRed;
498
499 ossScoreBlue << "Blue: " << game->getBlueScore() << endl;
500 ossScoreRed << "Red: " << game->getRedScore() << endl;
501
502 al_draw_text(font, al_map_rgb(0, 255, 0), 330, 80, ALLEGRO_ALIGN_LEFT, ossScoreBlue.str().c_str());
503 al_draw_text(font, al_map_rgb(0, 255, 0), 515, 80, ALLEGRO_ALIGN_LEFT, ossScoreRed.str().c_str());
504
505 // update players
506 for (it = game->getPlayers().begin(); it != game->getPlayers().end(); it++)
507 {
508 it->second->updateTarget(game->getPlayers());
509 }
510
511 for (it = game->getPlayers().begin(); it != game->getPlayers().end(); it++)
512 {
513 it->second->move(game->getMap()); // ignore return value
514 }
515
516 // update projectile positions
517 map<unsigned int, Projectile>::iterator it2;
518 for (it2 = game->getProjectiles().begin(); it2 != game->getProjectiles().end(); it2++)
519 {
520 it2->second.move(game->getPlayers());
521 }
522
523 GameRender::drawMap(game->getMap());
524 GameRender::drawPlayers(game->getPlayers(), font, curPlayerId);
525 GameRender::drawProjectiles(game->getProjectiles(), game->getPlayers());
526 }
527 else if (wndCurrent == wndGameSummary)
528 {
529 ostringstream ossBlueScore, ossRedScore;
530
531 ossBlueScore << "Blue Score: " << gameSummary->getBlueScore();
532 ossRedScore << "Red Score: " << gameSummary->getRedScore();
533
534 string strWinner;
535
536 if (gameSummary->getWinner() == 0)
537 strWinner = "Blue Team Wins";
538 else if (gameSummary->getWinner() == 1)
539 strWinner = "Red Team Wins";
540 else
541 strWinner = "winner set to wrong value";
542
543 al_draw_text(font, al_map_rgb(0, 255, 0), 512, 40, ALLEGRO_ALIGN_CENTRE, gameSummary->getName().c_str());
544 al_draw_text(font, al_map_rgb(0, 255, 0), 330, 80, ALLEGRO_ALIGN_LEFT, ossBlueScore.str().c_str());
545 al_draw_text(font, al_map_rgb(0, 255, 0), 515, 80, ALLEGRO_ALIGN_LEFT, ossRedScore.str().c_str());
546 al_draw_text(font, al_map_rgb(0, 255, 0), 512, 120, ALLEGRO_ALIGN_CENTRE, strWinner.c_str());
547 }
548
549 if (debugging) {
550 drawMessageStatus(font);
551 }
552
553 al_flip_display();
554 }
555 }
556
557 #if defined WINDOWS
558 closesocket(sock);
559 #elif defined LINUX
560 close(sock);
561 #endif
562
563 shutdownWinSock();
564
565 // delete all components
566 for (unsigned int x=0; x<vctComponents.size(); x++)
567 delete vctComponents[x];
568
569 delete wndLogin;
570 delete wndRegister;
571 delete wndLobby;
572 delete wndLobbyDebug;
573 delete wndGameLobby;
574 delete wndGame;
575 delete wndGameSummary;
576
577 // game should be deleted when the player leaves a gamw
578 if (game != NULL)
579 delete game;
580
581 if (gameSummary != NULL)
582 delete gameSummary;
583
584 map<unsigned int, Player*>::iterator it;
585
586 for (it = mapPlayers.begin(); it != mapPlayers.end(); it++) {
587 delete it->second;
588 }
589
590 al_destroy_event_queue(event_queue);
591 al_destroy_display(display);
592 al_destroy_timer(timer);
593
594 outputLog << "Stopped client on " << getCurrentDateTimeString() << endl;
595 outputLog.close();
596
597 return 0;
598}
599
600void initWinSock()
601{
602#if defined WINDOWS
603 WORD wVersionRequested;
604 WSADATA wsaData;
605 int wsaerr;
606
607 wVersionRequested = MAKEWORD(2, 2);
608 wsaerr = WSAStartup(wVersionRequested, &wsaData);
609
610 if (wsaerr != 0) {
611 cout << "The Winsock dll not found." << endl;
612 exit(1);
613 }else
614 cout << "The Winsock dll was found." << endl;
615#endif
616}
617
618void shutdownWinSock()
619{
620#if defined WINDOWS
621 WSACleanup();
622#endif
623}
624
625void createGui(ALLEGRO_FONT* font) {
626
627 // wndLogin
628
629 wndLogin = new Window(0, 0, SCREEN_W, SCREEN_H);
630 vctComponents.push_back(wndLogin->addComponent(new Textbox(516, 40, 100, 20, font)));
631 vctComponents.push_back(wndLogin->addComponent(new Textbox(516, 70, 100, 20, font)));
632 vctComponents.push_back(wndLogin->addComponent(new TextLabel(410, 40, 100, 20, font, "Username:", ALLEGRO_ALIGN_RIGHT)));
633 vctComponents.push_back(wndLogin->addComponent(new TextLabel(410, 70, 100, 20, font, "Password:", ALLEGRO_ALIGN_RIGHT)));
634 vctComponents.push_back(wndLogin->addComponent(new TextLabel((SCREEN_W-600)/2, 100, 600, 20, font, "", ALLEGRO_ALIGN_CENTRE)));
635 vctComponents.push_back(wndLogin->addComponent(new Button(SCREEN_W/2-100, 130, 90, 20, font, "Register", goToRegisterScreen)));
636 vctComponents.push_back(wndLogin->addComponent(new Button(SCREEN_W/2+10, 130, 90, 20, font, "Login", login)));
637 vctComponents.push_back(wndLogin->addComponent(new Button(920, 10, 80, 20, font, "Quit", quit)));
638 vctComponents.push_back(wndLogin->addComponent(new Button(20, 10, 160, 20, font, "Toggle Debugging", toggleDebugging)));
639
640 txtUsername = (Textbox*)wndLogin->getComponent(0);
641 txtPassword = (Textbox*)wndLogin->getComponent(1);
642 lblLoginStatus = (TextLabel*)wndLogin->getComponent(4);
643
644 cout << "Created login screen" << endl;
645
646
647 // wndRegister
648
649 wndRegister = new Window(0, 0, SCREEN_W, SCREEN_H);
650 vctComponents.push_back(wndRegister->addComponent(new Textbox(516, 40, 100, 20, font)));
651 vctComponents.push_back(wndRegister->addComponent(new Textbox(516, 70, 100, 20, font)));
652 vctComponents.push_back(wndRegister->addComponent(new TextLabel(410, 40, 100, 20, font, "Username:", ALLEGRO_ALIGN_RIGHT)));
653 vctComponents.push_back(wndRegister->addComponent(new TextLabel(410, 70, 100, 20, font, "Password:", ALLEGRO_ALIGN_RIGHT)));
654 vctComponents.push_back(wndRegister->addComponent(new RadioButtonList(432, 100, "Pick a class", font)));
655 vctComponents.push_back(wndRegister->addComponent(new TextLabel((SCREEN_W-600)/2, 190, 600, 20, font, "", ALLEGRO_ALIGN_CENTRE)));
656 vctComponents.push_back(wndRegister->addComponent(new Button(SCREEN_W/2-100, 220, 90, 20, font, "Back", goToLoginScreen)));
657 vctComponents.push_back(wndRegister->addComponent(new Button(SCREEN_W/2+10, 220, 90, 20, font, "Submit", registerAccount)));
658 vctComponents.push_back(wndRegister->addComponent(new Button(920, 10, 80, 20, font, "Quit", quit)));
659 vctComponents.push_back(wndRegister->addComponent(new Button(20, 10, 160, 20, font, "Toggle Debugging", toggleDebugging)));
660
661 txtUsernameRegister = (Textbox*)wndRegister->getComponent(0);
662 txtPasswordRegister = (Textbox*)wndRegister->getComponent(1);
663
664 rblClasses = (RadioButtonList*)wndRegister->getComponent(4);
665 rblClasses->addRadioButton("Warrior");
666 rblClasses->addRadioButton("Ranger");
667
668 lblRegisterStatus = (TextLabel*)wndRegister->getComponent(5);
669
670 cout << "Created register screen" << endl;
671
672
673 // wndLobby
674
675 txtJoinGame = new Textbox(SCREEN_W*1/2+15+4, 40, 100, 20, font);
676 vctComponents.push_back(txtJoinGame);
677
678 txtCreateGame = new Textbox(SCREEN_W*3/4+4, 40, 100, 20, font);
679 vctComponents.push_back(txtCreateGame);
680
681 wndLobby = new Window(0, 0, SCREEN_W, SCREEN_H);
682 vctComponents.push_back(wndLobby->addComponent(new Button(920, 10, 80, 20, font, "Profile", goToProfileScreen)));
683 vctComponents.push_back(wndLobby->addComponent(new Button(920, 738, 80, 20, font, "Logout", logout)));
684 vctComponents.push_back(wndLobby->addComponent(new TextLabel(SCREEN_W*1/2+15-112, 40, 110, 20, font, "Game Name:", ALLEGRO_ALIGN_RIGHT)));
685 wndLobby->addComponent(txtJoinGame);
686 vctComponents.push_back(wndLobby->addComponent(new Button(SCREEN_W*1/2+15-100, 80, 200, 20, font, "Join Existing Game", joinGame)));
687 vctComponents.push_back(wndLobby->addComponent(new TextLabel(SCREEN_W*3/4-112, 40, 110, 20, font, "Game Name:", ALLEGRO_ALIGN_RIGHT)));
688 wndLobby->addComponent(txtCreateGame);
689 vctComponents.push_back(wndLobby->addComponent(new Button(SCREEN_W*3/4-100, 80, 200, 20, font, "Create New Game", createGame)));
690 vctComponents.push_back(wndLobby->addComponent(new Textbox(95, 40, 300, 20, font)));
691 vctComponents.push_back(wndLobby->addComponent(new Button(95, 70, 60, 20, font, "Send", sendChatMessage)));
692 vctComponents.push_back(wndLobby->addComponent(new Button(20, 10, 160, 20, font, "Toggle Debugging", toggleDebugging)));
693
694 txtChat = (Textbox*)wndLobby->getComponent(7);
695
696 cout << "Created lobby screen" << endl;
697
698
699 // wndLobbyDebug
700
701 wndLobbyDebug = new Window(0, 0, SCREEN_W, SCREEN_H);
702 vctComponents.push_back(wndLobbyDebug->addComponent(new Button(920, 10, 80, 20, font, "Profile", goToProfileScreen)));
703 vctComponents.push_back(wndLobbyDebug->addComponent(new Button(920, 738, 80, 20, font, "Logout", logout)));
704 vctComponents.push_back(wndLobbyDebug->addComponent(new TextLabel(SCREEN_W*1/2+15-112, 40, 110, 20, font, "Game Name:", ALLEGRO_ALIGN_RIGHT)));
705 wndLobbyDebug->addComponent(txtJoinGame);
706 vctComponents.push_back(wndLobbyDebug->addComponent(new Button(SCREEN_W*1/2+15-100, 80, 200, 20, font, "Join Existing Game", joinGame)));
707 vctComponents.push_back(wndLobbyDebug->addComponent(new TextLabel(SCREEN_W*3/4-112, 40, 110, 20, font, "Game Name:", ALLEGRO_ALIGN_RIGHT)));
708 wndLobbyDebug->addComponent(txtCreateGame);
709 vctComponents.push_back(wndLobbyDebug->addComponent(new Button(SCREEN_W*3/4-100, 80, 200, 20, font, "Create New Game", createGame)));
710 vctComponents.push_back(wndLobbyDebug->addComponent(new Button(20, 10, 160, 20, font, "Toggle Debugging", toggleDebugging)));
711
712 cout << "Created debug lobby screen" << endl;
713
714
715 // wndProfile
716
717 wndProfile = new Window(0, 0, SCREEN_W, SCREEN_H);
718 vctComponents.push_back(wndProfile->addComponent(new TextLabel(450, 40, 124, 20, font, "Profile", ALLEGRO_ALIGN_CENTRE)));
719 vctComponents.push_back(wndProfile->addComponent(new TextLabel(160, 120, 124, 20, font, "Game History", ALLEGRO_ALIGN_CENTRE)));
720 vctComponents.push_back(wndProfile->addComponent(new TextLabel(600, 160, 124, 20, font, "Time", ALLEGRO_ALIGN_CENTRE)));
721 vctComponents.push_back(wndProfile->addComponent(new TextLabel(80, 160, 124, 20, font, "Result", ALLEGRO_ALIGN_CENTRE)));
722 vctComponents.push_back(wndProfile->addComponent(new TextLabel(240, 160, 124, 20, font, "Blue Score", ALLEGRO_ALIGN_CENTRE)));
723 vctComponents.push_back(wndProfile->addComponent(new TextLabel(400, 160, 124, 20, font, "Red Score", ALLEGRO_ALIGN_CENTRE)));
724 vctComponents.push_back(wndProfile->addComponent(new TextLabel(560, 160, 124, 20, font, "Time", ALLEGRO_ALIGN_CENTRE)));
725 vctComponents.push_back(wndProfile->addComponent(new Button(920, 738, 80, 20, font, "Back", goToLobbyScreen)));
726
727
728 // wndGameLobby
729
730 wndGameLobby = new Window(0, 0, SCREEN_W, SCREEN_H);
731 vctComponents.push_back(wndGameLobby->addComponent(new Button(180, 120, 160, 300, font, "", joinWaitingArea)));
732 vctComponents.push_back(wndGameLobby->addComponent(new Button(380, 120, 160, 300, font, "", joinBlueTeam)));
733 vctComponents.push_back(wndGameLobby->addComponent(new Button(580, 120, 160, 300, font, "", joinRedTeam)));
734 vctComponents.push_back(wndGameLobby->addComponent(new Button(40, 600, 120, 20, font, "Leave Game", leaveGame)));
735 vctComponents.push_back(wndGameLobby->addComponent(new Button(800, 600, 120, 20, font, "Start Game", startGame)));
736
737
738 // wndGame
739
740 wndGame = new Window(0, 0, SCREEN_W, SCREEN_H);
741 vctComponents.push_back(wndGame->addComponent(new Button(880, 10, 120, 20, font, "Leave Game", leaveGame)));
742
743 cout << "Created new game screen" << endl;
744
745 wndGameSummary = new Window(0, 0, SCREEN_W, SCREEN_H);
746 vctComponents.push_back(wndGameSummary->addComponent(new Button(840, 730, 160, 20, font, "Back to Lobby", closeGameSummary)));
747
748 cout << "Created game summary screen" << endl;
749}
750
751void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player*>& mapPlayers, map<string, int>& mapGames, unsigned int& curPlayerId)
752{
753 cout << "Total players in map: " << mapPlayers.size() << endl;
754
755 // this is outdated since most messages now don't contain just a text string
756 string response = string(msg.buffer);
757
758 switch(state)
759 {
760 case STATE_START:
761 {
762 cout << "In STATE_START" << endl;
763
764 switch(msg.type)
765 {
766 case MSG_TYPE_REGISTER:
767 {
768 lblRegisterStatus->setText(response);
769 break;
770 }
771 default:
772 {
773 cout << "(STATE_REGISTER) Received invalid message of type " << msg.type << endl;
774 break;
775 }
776 }
777
778 break;
779 }
780 case STATE_LOBBY:
781 {
782 cout << "In STATE_LOBBY" << endl;
783 switch(msg.type)
784 {
785 case MSG_TYPE_LOGIN:
786 {
787 if (response.compare("Player has already logged in.") == 0)
788 {
789 goToLoginScreen();
790 state = STATE_START;
791
792 lblLoginStatus->setText(response);
793 }
794 else if (response.compare("Incorrect username or password") == 0)
795 {
796 goToLoginScreen();
797 state = STATE_START;
798
799 lblLoginStatus->setText(response);
800 }
801 else
802 {
803 wndCurrent = wndLobby;
804
805 // this message should only be sent when a player first logs in so they know their id
806
807 Player* p = new Player("", "");
808 p->deserialize(msg.buffer);
809
810 if (mapPlayers.find(p->getId()) != mapPlayers.end())
811 delete mapPlayers[p->getId()];
812 mapPlayers[p->getId()] = p;
813 curPlayerId = p->getId();
814 currentPlayer = mapPlayers[curPlayerId];
815
816 cout << "Got a valid login response with the player" << endl;
817 cout << "Player id: " << curPlayerId << endl;
818 cout << "Player health: " << p->health << endl;
819 cout << "player map size: " << mapPlayers.size() << endl;
820 }
821
822 break;
823 }
824 case MSG_TYPE_LOGOUT:
825 {
826 cout << "Got a logout message" << endl;
827
828 unsigned int playerId;
829
830 // Check if it's about you or another player
831 memcpy(&playerId, msg.buffer, 4);
832 response = string(msg.buffer+4);
833
834 if (playerId == curPlayerId)
835 {
836 cout << "Got logout message for self" << endl;
837
838 if (response.compare("You have successfully logged out.") == 0)
839 {
840 cout << "Logged out" << endl;
841 state = STATE_START;
842 goToLoginScreen();
843 }
844
845 // if there was an error logging out, nothing happens
846 }
847 else
848 {
849 delete mapPlayers[playerId];
850 mapPlayers.erase(playerId);
851 }
852
853 break;
854 }
855 case MSG_TYPE_CHAT:
856 {
857 chatConsole.addLine(response);
858
859 break;
860 }
861 case MSG_TYPE_PROFILE:
862 {
863 wndCurrent = wndProfile;
864
865 break;
866 }
867 case MSG_TYPE_JOIN_GAME_SUCCESS:
868 {
869 cout << "Received a JOIN_GAME_SUCCESS message" << endl;
870
871 string gameName(msg.buffer);
872
873 #if defined WINDOWS
874 game = new Game(gameName, "../../data/map.txt", &msgProcessor);
875 #elif defined LINUX
876 game = new Game(gameName, "../data/map.txt", &msgProcessor);
877 #elif defined MAC
878 game = new Game(gameName, "../data/map.txt", &msgProcessor);
879 #endif
880
881 cout << "Game name: " << gameName << endl;
882
883 state = STATE_GAME_LOBBY;
884 wndCurrent = wndGameLobby;
885
886 msgTo.type = MSG_TYPE_JOIN_GAME_ACK;
887 strcpy(msgTo.buffer, gameName.c_str());
888
889 msgProcessor.sendMessage(&msgTo, &server);
890
891 break;
892 }
893 case MSG_TYPE_JOIN_GAME_FAILURE:
894 {
895 cout << "Received a JOIN_GAME_FAILURE message" << endl;
896
897 break;
898 }
899 case MSG_TYPE_PLAYER:
900 {
901 handleMsgPlayer(msg, mapPlayers, mapGames);
902
903 break;
904 }
905 case MSG_TYPE_GAME_INFO:
906 {
907 handleMsgGameInfo(msg, mapPlayers, mapGames);
908
909 break;
910 }
911 default:
912 {
913 cout << "(STATE_LOBBY) Received invlaid message of type " << msg.type << endl;
914
915 break;
916 }
917 }
918
919 break;
920 }
921 case STATE_GAME_LOBBY:
922 {
923 cout << "(STATE_GAME_LOBBY) ";
924 switch(msg.type)
925 {
926 case MSG_TYPE_START_GAME:
927 {
928 state = STATE_GAME;
929 wndCurrent = wndGame;
930
931 break;
932 }
933 default:
934 {
935 // keep these lines commented until until the correct messages are moved into the STATE_GAME_LOBBY section
936 //cout << "Received invalid message of type " << msg.type << endl;
937
938 //break;
939 }
940 }
941 }
942 case STATE_GAME:
943 {
944 cout << "(STATE_GAME) ";
945 switch(msg.type)
946 {
947 case MSG_TYPE_SCORE:
948 {
949 cout << "Received SCORE message!" << endl;
950
951 int blueScore;
952 memcpy(&blueScore, msg.buffer, 4);
953 cout << "blue score: " << blueScore << endl;
954 game->setBlueScore(blueScore);
955
956 int redScore;
957 memcpy(&redScore, msg.buffer+4, 4);
958 cout << "red score: " << redScore << endl;
959 game->setRedScore(redScore);
960
961 cout << "Processed SCORE message!" << endl;
962
963 break;
964 }
965 case MSG_TYPE_FINISH_GAME:
966 {
967 cout << "Got a finish game message" << endl;
968 cout << "Should switch to STATE_LOBBY and show the final score" << endl;
969
970 unsigned int winner, blueScore, redScore;
971 memcpy(&winner, msg.buffer, 4);
972 memcpy(&blueScore, msg.buffer+4, 4);
973 memcpy(&redScore, msg.buffer+8, 4);
974
975 string gameName(msg.buffer+12);
976
977 gameSummary = new GameSummary(gameName, winner, blueScore, redScore);
978
979 delete game;
980 game = NULL;
981 state = STATE_LOBBY;
982 wndCurrent = wndGameSummary;
983
984 break;
985 }
986 case MSG_TYPE_LOGOUT:
987 {
988 cout << "Got a logout message" << endl;
989
990 unsigned int playerId;
991
992 // Check if it's about you or another player
993 memcpy(&playerId, msg.buffer, 4);
994 response = string(msg.buffer+4);
995
996 if (playerId == curPlayerId)
997 cout << "Received MSG_TYPE_LOGOUT for self in STATE_GAME. This shouldn't happen." << endl;
998 else {
999 delete mapPlayers[playerId];
1000 mapPlayers.erase(playerId);
1001 }
1002
1003 break;
1004 }
1005 case MSG_TYPE_PLAYER_JOIN_GAME:
1006 {
1007 cout << "Received MSG_TYPE_PLAYER_JOIN_GAME" << endl;
1008
1009 Player p("", "");
1010 p.deserialize(msg.buffer);
1011 cout << "Deserialized player" << endl;
1012 cout << "player team: " << p.team << endl;
1013 cout << "current player team: " << currentPlayer->team << endl;
1014 p.timeLastUpdated = getCurrentMillis();
1015 p.isChasing = false;
1016 if (p.health <= 0)
1017 p.isDead = true;
1018 else
1019 p.isDead = false;
1020
1021 if (mapPlayers.find(p.getId()) != mapPlayers.end())
1022 *(mapPlayers[p.getId()]) = p;
1023 else
1024 mapPlayers[p.getId()] = new Player(p);
1025
1026 game->addPlayer(mapPlayers[p.getId()], false);
1027
1028 break;
1029 }
1030 case MSG_TYPE_LEAVE_GAME:
1031 {
1032 cout << "Received a LEAVE_GAME message" << endl;
1033
1034 string gameName(msg.buffer+4);
1035 unsigned int playerId;
1036
1037 memcpy(&playerId, msg.buffer, 4);
1038
1039 game->removePlayer(playerId);
1040
1041 break;
1042 }
1043 case MSG_TYPE_PLAYER_MOVE:
1044 {
1045 cout << "Received PLAYER_MOVE message" << endl;
1046
1047 unsigned int id;
1048 int x, y;
1049
1050 memcpy(&id, msg.buffer, 4);
1051 memcpy(&x, msg.buffer+4, 4);
1052 memcpy(&y, msg.buffer+8, 4);
1053
1054 cout << "id: " << id << endl;
1055
1056 mapPlayers[id]->target.x = x;
1057 mapPlayers[id]->target.y = y;
1058
1059 mapPlayers[id]->isChasing = false;
1060 mapPlayers[id]->setTargetPlayer(0);
1061
1062 break;
1063 }
1064 case MSG_TYPE_OBJECT:
1065 {
1066 cout << "Received object message in STATE_GAME" << endl;
1067
1068 WorldMap::Object o(0, OBJECT_NONE, 0, 0);
1069 o.deserialize(msg.buffer);
1070 cout << "object id: " << o.id << endl;
1071 game->getMap()->updateObject(o.id, o.type, o.pos.x, o.pos.y);
1072
1073 break;
1074 }
1075 case MSG_TYPE_REMOVE_OBJECT:
1076 {
1077 cout << "Received REMOVE_OBJECT message!" << endl;
1078
1079 int id;
1080 memcpy(&id, msg.buffer, 4);
1081
1082 cout << "Removing object with id " << id << endl;
1083
1084 if (!game->getMap()->removeObject(id))
1085 cout << "Did not remove the object" << endl;
1086
1087 break;
1088 }
1089 case MSG_TYPE_ATTACK:
1090 {
1091 cout << "Received START_ATTACK message" << endl;
1092
1093 unsigned int id, targetId;
1094 memcpy(&id, msg.buffer, 4);
1095 memcpy(&targetId, msg.buffer+4, 4);
1096
1097 cout << "source id: " << id << endl;
1098 cout << "target id: " << targetId << endl;
1099
1100 // need to check the target exists in the current game
1101 Player* source = game->getPlayers()[id];
1102 source->setTargetPlayer(targetId);
1103 source->isChasing = true;
1104
1105 break;
1106 }
1107 case MSG_TYPE_PROJECTILE:
1108 {
1109 cout << "Received a PROJECTILE message" << endl;
1110
1111 unsigned int projId, x, y, targetId;
1112
1113 memcpy(&projId, msg.buffer, 4);
1114 memcpy(&x, msg.buffer+4, 4);
1115 memcpy(&y, msg.buffer+8, 4);
1116 memcpy(&targetId, msg.buffer+12, 4);
1117
1118 cout << "projId: " << projId << endl;
1119 cout << "x: " << x << endl;
1120 cout << "y: " << y << endl;
1121 cout << "Target: " << targetId << endl;
1122
1123 Projectile proj(x, y, targetId, 0);
1124 proj.setId(projId);
1125
1126 game->addProjectile(proj);
1127
1128 break;
1129 }
1130 case MSG_TYPE_REMOVE_PROJECTILE:
1131 {
1132 cout << "Received a REMOVE_PROJECTILE message" << endl;
1133
1134 unsigned int id;
1135 memcpy(&id, msg.buffer, 4);
1136
1137 game->removeProjectile(id);
1138
1139 break;
1140 }
1141 case MSG_TYPE_PLAYER:
1142 {
1143 handleMsgPlayer(msg, mapPlayers, mapGames);
1144
1145 break;
1146 }
1147 case MSG_TYPE_GAME_INFO:
1148 {
1149 handleMsgGameInfo(msg, mapPlayers, mapGames);
1150
1151 break;
1152 }
1153 default:
1154 {
1155 cout << "Received invalid message of type " << msg.type << endl;
1156
1157 break;
1158 }
1159 }
1160
1161 break;
1162 }
1163 default:
1164 {
1165 cout << "The state has an invalid value: " << state << endl;
1166
1167 break;
1168 }
1169 }
1170}
1171
1172int getRefreshRate(int width, int height)
1173{
1174 int numRefreshRates = al_get_num_display_modes();
1175 ALLEGRO_DISPLAY_MODE displayMode;
1176
1177 for(int i=0; i<numRefreshRates; i++) {
1178 al_get_display_mode(i, &displayMode);
1179
1180 if (displayMode.width == width && displayMode.height == height)
1181 return displayMode.refresh_rate;
1182 }
1183
1184 return 0;
1185}
1186
1187void drawMessageStatus(ALLEGRO_FONT* font)
1188{
1189 int clientMsgOffset = 5;
1190 int serverMsgOffset = 950;
1191
1192 al_draw_text(font, al_map_rgb(0, 255, 255), 0+clientMsgOffset, 43, ALLEGRO_ALIGN_LEFT, "ID");
1193 al_draw_text(font, al_map_rgb(0, 255, 255), 20+clientMsgOffset, 43, ALLEGRO_ALIGN_LEFT, "Type");
1194 al_draw_text(font, al_map_rgb(0, 255, 255), 240+clientMsgOffset, 43, ALLEGRO_ALIGN_LEFT, "Acked?");
1195
1196 //al_draw_text(font, al_map_rgb(0, 255, 255), serverMsgOffset, 43, ALLEGRO_ALIGN_LEFT, "ID");
1197
1198 map<unsigned int, map<unsigned long, MessageContainer> >& sentMessages = msgProcessor.getSentMessages();
1199 int id, type;
1200 bool acked;
1201 ostringstream ossId, ossAcked;
1202
1203 map<unsigned int, map<unsigned long, MessageContainer> >::iterator it;
1204
1205 int msgCount = 0;
1206 for (it = sentMessages.begin(); it != sentMessages.end(); it++) {
1207 map<unsigned long, MessageContainer> playerMessage = it->second;
1208 map<unsigned long, MessageContainer>::iterator it2;
1209 for (it2 = playerMessage.begin(); it2 != playerMessage.end(); it2++) {
1210
1211 id = it->first;
1212 ossId.str("");;
1213 ossId << id;
1214
1215 type = it2->second.getMessage()->type;
1216 string typeStr = MessageContainer::getMsgTypeString(type);
1217
1218 acked = it2->second.getAcked();
1219 ossAcked.str("");;
1220 ossAcked << boolalpha << acked;
1221
1222 al_draw_text(font, al_map_rgb(0, 255, 0), clientMsgOffset, 60+15*msgCount, ALLEGRO_ALIGN_LEFT, ossId.str().c_str());
1223 al_draw_text(font, al_map_rgb(0, 255, 0), 20+clientMsgOffset, 60+15*msgCount, ALLEGRO_ALIGN_LEFT, typeStr.c_str());
1224 al_draw_text(font, al_map_rgb(0, 255, 0), 240+clientMsgOffset, 60+15*msgCount, ALLEGRO_ALIGN_LEFT, ossAcked.str().c_str());
1225
1226 msgCount++;
1227 }
1228 }
1229
1230 if (msgProcessor.getAckedMessages().size() > 0) {
1231 map<unsigned int, unsigned long long> ackedMessages = msgProcessor.getAckedMessages()[0];
1232 map<unsigned int, unsigned long long>::iterator it3;
1233
1234 msgCount = 0;
1235 for (it3 = ackedMessages.begin(); it3 != ackedMessages.end(); it3++) {
1236 ossId.str("");;
1237 ossId << it3->first;
1238
1239 al_draw_text(font, al_map_rgb(255, 0, 0), 25+serverMsgOffset, 60+15*msgCount, ALLEGRO_ALIGN_LEFT, ossId.str().c_str());
1240
1241 msgCount++;
1242 }
1243 }
1244}
1245
1246// message handling functions
1247
1248void handleMsgPlayer(NETWORK_MSG &msg, map<unsigned int, Player*>& mapPlayers, map<string, int>& mapGames) {
1249 cout << "Received MSG_TYPE_PLAYER" << endl;
1250
1251 Player p("", "");
1252 p.deserialize(msg.buffer);
1253 p.timeLastUpdated = getCurrentMillis();
1254 p.isChasing = false;
1255 if (p.health <= 0)
1256 p.isDead = true;
1257 else
1258 p.isDead = false;
1259
1260 if (mapPlayers.find(p.getId()) != mapPlayers.end())
1261 *(mapPlayers[p.getId()]) = p;
1262 else
1263 mapPlayers[p.getId()] = new Player(p);
1264}
1265
1266void handleMsgGameInfo(NETWORK_MSG &msg, map<unsigned int, Player*>& mapPlayers, map<string, int>& mapGames) {
1267 cout << "Received a GAME_INFO message" << endl;
1268
1269 string gameName(msg.buffer+4);
1270 int numPlayers;
1271
1272 memcpy(&numPlayers, msg.buffer, 4);
1273
1274 cout << "Received game info for " << gameName << " (num players: " << numPlayers << ")" << endl;
1275
1276 if (numPlayers > 0)
1277 mapGames[gameName] = numPlayers;
1278 else
1279 mapGames.erase(gameName);
1280}
1281
1282// Callback definitions
1283
1284void goToRegisterScreen()
1285{
1286 txtUsernameRegister->clear();
1287 txtPasswordRegister->clear();
1288 lblRegisterStatus->setText("");
1289 rblClasses->setSelectedButton(-1);
1290
1291 wndCurrent = wndRegister;
1292}
1293
1294void goToLoginScreen()
1295{
1296 txtUsername->clear();
1297 txtPassword->clear();
1298 lblLoginStatus->setText("");
1299
1300 wndCurrent = wndLogin;
1301}
1302
1303// maybe need a goToGameScreen function as well and add state changes to these functions as well
1304
1305void registerAccount()
1306{
1307 string username = txtUsernameRegister->getStr();
1308 string password = txtPasswordRegister->getStr();
1309
1310 txtUsernameRegister->clear();
1311 txtPasswordRegister->clear();
1312 // maybe clear rblClasses as well (add a method to RadioButtonList to enable this)
1313
1314 Player::PlayerClass playerClass;
1315
1316 switch (rblClasses->getSelectedButton()) {
1317 case 0:
1318 playerClass = Player::CLASS_WARRIOR;
1319 break;
1320 case 1:
1321 playerClass = Player::CLASS_RANGER;
1322 break;
1323 default:
1324 cout << "Invalid class selection" << endl;
1325 playerClass = Player::CLASS_NONE;
1326 break;
1327 }
1328
1329 msgTo.type = MSG_TYPE_REGISTER;
1330
1331 strcpy(msgTo.buffer, username.c_str());
1332 strcpy(msgTo.buffer+username.size()+1, password.c_str());
1333 memcpy(msgTo.buffer+username.size()+password.size()+2, &playerClass, 4);
1334
1335 msgProcessor.sendMessage(&msgTo, &server);
1336}
1337
1338void login()
1339{
1340 string strUsername = txtUsername->getStr();
1341 string strPassword = txtPassword->getStr();
1342 username = strUsername;
1343
1344 txtUsername->clear();
1345 txtPassword->clear();
1346
1347 msgTo.type = MSG_TYPE_LOGIN;
1348
1349 strcpy(msgTo.buffer, strUsername.c_str());
1350 strcpy(msgTo.buffer+username.size()+1, strPassword.c_str());
1351
1352 msgProcessor.sendMessage(&msgTo, &server);
1353
1354 state = STATE_LOBBY;
1355}
1356
1357void logout()
1358{
1359 switch(state) {
1360 case STATE_LOBBY:
1361 txtJoinGame->clear();
1362 txtCreateGame->clear();
1363 break;
1364 default:
1365 cout << "Logout called from invalid state: " << state << endl;
1366 break;
1367 }
1368
1369 msgTo.type = MSG_TYPE_LOGOUT;
1370
1371 strcpy(msgTo.buffer, username.c_str());
1372
1373 msgProcessor.sendMessage(&msgTo, &server);
1374}
1375
1376void quit()
1377{
1378 doexit = true;
1379}
1380
1381void sendChatMessage()
1382{
1383 string msg = txtChat->getStr();
1384 txtChat->clear();
1385
1386 msgTo.type = MSG_TYPE_CHAT;
1387 strcpy(msgTo.buffer, msg.c_str());
1388
1389 msgProcessor.sendMessage(&msgTo, &server);
1390}
1391
1392void toggleDebugging()
1393{
1394 debugging = !debugging;
1395}
1396
1397void goToProfileScreen()
1398{
1399 msgTo.type = MSG_TYPE_PROFILE;
1400
1401 msgProcessor.sendMessage(&msgTo, &server);
1402}
1403
1404void goToLobbyScreen()
1405{
1406 wndCurrent = wndLobby;
1407}
1408
1409void joinGame()
1410{
1411 cout << "Joining game" << endl;
1412
1413 string msg = txtJoinGame->getStr();
1414 txtJoinGame->clear();
1415
1416 msgTo.type = MSG_TYPE_JOIN_GAME;
1417 strcpy(msgTo.buffer, msg.c_str());
1418
1419 msgProcessor.sendMessage(&msgTo, &server);
1420}
1421
1422void createGame()
1423{
1424 cout << "Creating game" << endl;
1425
1426 string msg = txtCreateGame->getStr();
1427 txtCreateGame->clear();
1428
1429 cout << "Sending message: " << msg.c_str() << endl;
1430
1431 msgTo.type = MSG_TYPE_CREATE_GAME;
1432 strcpy(msgTo.buffer, msg.c_str());
1433
1434 msgProcessor.sendMessage(&msgTo, &server);
1435 cout << "Sent CREATE_GAME message" << endl;
1436}
1437
1438void joinWaitingArea() {
1439 cout << "joining waiting area" << endl;
1440 currentPlayer->team = -1;
1441
1442 msgTo.type = MSG_TYPE_JOIN_TEAM;
1443 memcpy(msgTo.buffer, &(currentPlayer->team), 4);
1444
1445 msgProcessor.sendMessage(&msgTo, &server);
1446}
1447
1448void joinBlueTeam() {
1449 cout << "joining blue team" << endl;
1450 currentPlayer->team = 0;
1451
1452 msgTo.type = MSG_TYPE_JOIN_TEAM;
1453 memcpy(msgTo.buffer, &(currentPlayer->team), 4);
1454
1455 msgProcessor.sendMessage(&msgTo, &server);
1456}
1457
1458void joinRedTeam() {
1459 cout << "joining red team" << endl;
1460 currentPlayer->team = 1;
1461
1462 msgTo.type = MSG_TYPE_JOIN_TEAM;
1463 memcpy(msgTo.buffer, &(currentPlayer->team), 4);
1464
1465 msgProcessor.sendMessage(&msgTo, &server);
1466}
1467
1468void startGame() {
1469 msgTo.type = MSG_TYPE_START_GAME;
1470
1471 msgProcessor.sendMessage(&msgTo, &server);
1472}
1473
1474void leaveGame()
1475{
1476 cout << "Leaving game" << endl;
1477
1478 delete game;
1479 game = NULL;
1480
1481 state = STATE_LOBBY;
1482 wndCurrent = wndLobby;
1483
1484 msgTo.type = MSG_TYPE_LEAVE_GAME;
1485
1486 msgProcessor.sendMessage(&msgTo, &server);
1487}
1488
1489void closeGameSummary()
1490{
1491 delete gameSummary;
1492 gameSummary = NULL;
1493 wndCurrent = wndLobby;
1494 cout << "Processed button actions" << endl;
1495}
Note: See TracBrowser for help on using the repository browser.