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

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

The client processes PROJECTILE and REMOVE_PROJECTILE messages and draws moving projectiles on the screen

  • Property mode set to 100644
File size: 24.4 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#endif
14
15#include <cstdio>
16#include <cstdlib>
17#include <cmath>
18#include <sys/types.h>
19#include <string>
20#include <iostream>
21#include <sstream>
22#include <map>
23
24#include <allegro5/allegro.h>
25#include <allegro5/allegro_font.h>
26#include <allegro5/allegro_ttf.h>
27#include <allegro5/allegro_primitives.h>
28
29#include "../../common/Message.h"
30#include "../../common/Common.h"
31#include "../../common/WorldMap.h"
32#include "../../common/Player.h"
33#include "../../common/Projectile.h"
34
35#include "Window.h"
36#include "Textbox.h"
37#include "Button.h"
38#include "chat.h"
39
40#ifdef WINDOWS
41 #pragma comment(lib, "ws2_32.lib")
42#endif
43
44using namespace std;
45
46void initWinSock();
47void shutdownWinSock();
48void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, WorldMap *gameMap, map<unsigned int, Player>& mapPlayers, map<unsigned int, Projectile>& mapProjectiles, unsigned int& curPlayerId, int &scoreBlue, int &scoreRed);
49void drawMap(WorldMap* gameMap);
50void drawPlayers(map<unsigned int, Player>& mapPlayers, ALLEGRO_FONT* font, unsigned int curPlayerId);
51POSITION screenToMap(POSITION pos);
52POSITION mapToScreen(POSITION pos);
53
54// callbacks
55void registerAccount();
56void login();
57void logout();
58void quit();
59void sendChatMessage();
60
61void error(const char *);
62
63const float FPS = 60;
64const int SCREEN_W = 640;
65const int SCREEN_H = 480;
66
67enum STATE {
68 STATE_START,
69 STATE_LOGIN // this means you're already logged in
70};
71
72int state;
73
74bool doexit;
75
76Window* wndLogin;
77Window* wndMain;
78Window* wndCurrent;
79
80Textbox* txtUsername;
81Textbox* txtPassword;
82Textbox* txtChat;
83
84int sock;
85struct sockaddr_in server, from;
86struct hostent *hp;
87NETWORK_MSG msgTo, msgFrom;
88string username;
89chat chatConsole;
90
91int main(int argc, char **argv)
92{
93 ALLEGRO_DISPLAY *display = NULL;
94 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
95 ALLEGRO_TIMER *timer = NULL;
96 bool key[4] = { false, false, false, false };
97 bool redraw = true;
98 doexit = false;
99 map<unsigned int, Player> mapPlayers;
100 map<unsigned int, Projectile> mapProjectiles;
101 unsigned int curPlayerId = -1;
102 int scoreBlue, scoreRed;
103
104 scoreBlue = 0;
105 scoreRed = 0;
106
107 state = STATE_START;
108
109 if(!al_init()) {
110 fprintf(stderr, "failed to initialize allegro!\n");
111 return -1;
112 }
113
114 if (al_init_primitives_addon())
115 cout << "Primitives initialized" << endl;
116 else
117 cout << "Primitives not initialized" << endl;
118
119 al_init_font_addon();
120 al_init_ttf_addon();
121
122 #if defined WINDOWS
123 ALLEGRO_FONT *font = al_load_ttf_font("../pirulen.ttf", 12, 0);
124 #elif defined LINUX
125 ALLEGRO_FONT *font = al_load_ttf_font("pirulen.ttf", 12, 0);
126 #endif
127
128 if (!font) {
129 fprintf(stderr, "Could not load 'pirulen.ttf'.\n");
130 getchar();
131 return -1;
132 }
133
134 if(!al_install_keyboard()) {
135 fprintf(stderr, "failed to initialize the keyboard!\n");
136 return -1;
137 }
138
139 if(!al_install_mouse()) {
140 fprintf(stderr, "failed to initialize the mouse!\n");
141 return -1;
142 }
143
144 timer = al_create_timer(1.0 / FPS);
145 if(!timer) {
146 fprintf(stderr, "failed to create timer!\n");
147 return -1;
148 }
149
150 display = al_create_display(SCREEN_W, SCREEN_H);
151 if(!display) {
152 fprintf(stderr, "failed to create display!\n");
153 al_destroy_timer(timer);
154 return -1;
155 }
156
157 WorldMap* gameMap = WorldMap::loadMapFromFile("../../data/map.txt");
158
159 wndLogin = new Window(0, 0, SCREEN_W, SCREEN_H);
160 wndLogin->addComponent(new Textbox(104, 40, 100, 20, font));
161 wndLogin->addComponent(new Textbox(104, 70, 100, 20, font));
162 wndLogin->addComponent(new Button(22, 100, 90, 20, font, "Register", registerAccount));
163 wndLogin->addComponent(new Button(122, 100, 60, 20, font, "Login", login));
164 wndLogin->addComponent(new Button(540, 10, 80, 20, font, "Quit", quit));
165
166 txtUsername = (Textbox*)wndLogin->getComponent(0);
167 txtPassword = (Textbox*)wndLogin->getComponent(1);
168
169 wndMain = new Window(0, 0, SCREEN_W, SCREEN_H);
170 wndMain->addComponent(new Textbox(95, 40, 525, 20, font));
171 wndMain->addComponent(new Button(95, 70, 160, 20, font, "Send Message", sendChatMessage));
172 wndMain->addComponent(new Button(540, 10, 80, 20, font, "Logout", logout));
173
174 txtChat = (Textbox*)wndMain->getComponent(0);
175
176 wndCurrent = wndLogin;
177
178 event_queue = al_create_event_queue();
179 if(!event_queue) {
180 fprintf(stderr, "failed to create event_queue!\n");
181 al_destroy_display(display);
182 al_destroy_timer(timer);
183 return -1;
184 }
185
186 al_set_target_bitmap(al_get_backbuffer(display));
187
188 al_register_event_source(event_queue, al_get_display_event_source(display));
189 al_register_event_source(event_queue, al_get_timer_event_source(timer));
190 al_register_event_source(event_queue, al_get_keyboard_event_source());
191 al_register_event_source(event_queue, al_get_mouse_event_source());
192
193 al_clear_to_color(al_map_rgb(0,0,0));
194
195 al_flip_display();
196
197 if (argc != 3) {
198 cout << "Usage: server port" << endl;
199 exit(1);
200 }
201
202 initWinSock();
203
204 sock = socket(AF_INET, SOCK_DGRAM, 0);
205 if (sock < 0)
206 error("socket");
207
208 set_nonblock(sock);
209
210 server.sin_family = AF_INET;
211 hp = gethostbyname(argv[1]);
212 if (hp==0)
213 error("Unknown host");
214
215 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
216 server.sin_port = htons(atoi(argv[2]));
217
218 al_start_timer(timer);
219
220 while(!doexit)
221 {
222 ALLEGRO_EVENT ev;
223
224 al_wait_for_event(event_queue, &ev);
225
226 if(wndCurrent->handleEvent(ev)) {
227 // do nothing
228 }
229 else if(ev.type == ALLEGRO_EVENT_TIMER) {
230 redraw = true; // seems like we should just call a draw function here instead
231 }
232 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
233 doexit = true;
234 }
235 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
236 }
237 else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
238 switch(ev.keyboard.keycode) {
239 case ALLEGRO_KEY_ESCAPE:
240 doexit = true;
241 break;
242 case ALLEGRO_KEY_S: // pickup an item next to you
243 if (state == STATE_LOGIN) {
244 msgTo.type = MSG_TYPE_PICKUP_FLAG;
245 memcpy(msgTo.buffer, &curPlayerId, 4);
246 sendMessage(&msgTo, sock, &server);
247 }
248 break;
249 case ALLEGRO_KEY_D: // drop the current item
250 if (state == STATE_LOGIN) {
251 // find the current player in the player list
252 map<unsigned int, Player>::iterator it;
253 Player* p = NULL;
254 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
255 {
256 if (it->second.id == curPlayerId)
257 p = &it->second;
258 }
259
260 if (p != NULL) {
261 int flagType = WorldMap::OBJECT_NONE;
262
263 if (p->hasBlueFlag)
264 flagType = WorldMap::OBJECT_BLUE_FLAG;
265 else if (p->hasRedFlag)
266 flagType = WorldMap::OBJECT_RED_FLAG;
267
268 if (flagType != WorldMap::OBJECT_NONE) {
269 msgTo.type = MSG_TYPE_DROP_FLAG;
270 memcpy(msgTo.buffer, &curPlayerId, 4);
271 sendMessage(&msgTo, sock, &server);
272 }
273 }
274 }
275 break;
276 }
277 }
278 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
279 if(wndCurrent == wndMain) {
280 if (ev.mouse.button == 1) { // left click
281 msgTo.type = MSG_TYPE_PLAYER_MOVE;
282
283 POSITION pos;
284 pos.x = ev.mouse.x;
285 pos.y = ev.mouse.y;
286 pos = screenToMap(pos);
287
288 if (pos.x != -1)
289 {
290 memcpy(msgTo.buffer, &curPlayerId, 4);
291 memcpy(msgTo.buffer+4, &pos.x, 4);
292 memcpy(msgTo.buffer+8, &pos.y, 4);
293
294 sendMessage(&msgTo, sock, &server);
295 }
296 else
297 cout << "Invalid point: User did not click on the map" << endl;
298 }else if (ev.mouse.button == 2) { // right click
299 map<unsigned int, Player>::iterator it;
300
301 cout << "Detected a right-click" << endl;
302
303 Player* curPlayer;
304 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
305 {
306 if (it->second.id == curPlayerId)
307 curPlayer = &it->second;
308 }
309
310 Player* target;
311 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
312 {
313 // need to check if the right-click was actually on this player
314 target = &it->second;
315 if (target->id != curPlayerId && target->team != curPlayer->team) {
316 msgTo.type = MSG_TYPE_START_ATTACK;
317 memcpy(msgTo.buffer, &curPlayerId, 4);
318 memcpy(msgTo.buffer+4, &target->id, 4);
319
320 sendMessage(&msgTo, sock, &server);
321 }
322 }
323 }
324 }
325 }
326
327 if (receiveMessage(&msgFrom, sock, &from) >= 0)
328 processMessage(msgFrom, state, chatConsole, gameMap, mapPlayers, mapProjectiles, curPlayerId, scoreBlue, scoreRed);
329
330 if (redraw)
331 {
332 redraw = false;
333
334 wndCurrent->draw(display);
335
336 chatConsole.draw(font, al_map_rgb(255,255,255));
337
338 if(wndCurrent == wndLogin) {
339 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Username:");
340 al_draw_text(font, al_map_rgb(0, 255, 0), 1, 73, ALLEGRO_ALIGN_LEFT, "Password:");
341 }
342 else if(wndCurrent == wndMain) {
343 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Message:");
344
345 ostringstream ossScoreBlue, ossScoreRed;
346
347 ossScoreBlue << "Blue: " << scoreBlue << endl;
348 ossScoreRed << "Red: " << scoreRed << endl;
349
350 al_draw_text(font, al_map_rgb(0, 255, 0), 330, 80, ALLEGRO_ALIGN_LEFT, ossScoreBlue.str().c_str());
351 al_draw_text(font, al_map_rgb(0, 255, 0), 515, 80, ALLEGRO_ALIGN_LEFT, ossScoreRed.str().c_str());
352
353 // update player positions
354 map<unsigned int, Player>::iterator it;
355 for (it = mapPlayers.begin(); it != mapPlayers.end(); it++)
356 {
357 it->second.move(gameMap); // ignore return value
358 }
359
360 // update projectile positions
361 map<unsigned int, Projectile>::iterator it2;
362 for (it2 = mapProjectiles.begin(); it2 != mapProjectiles.end(); it2++)
363 {
364 cout << "Update projectile position" << endl;
365 it2->second.move(mapPlayers);
366 }
367
368 drawMap(gameMap);
369 drawPlayers(mapPlayers, font, curPlayerId);
370
371 // draw projectiles
372 for (it2 = mapProjectiles.begin(); it2 != mapProjectiles.end(); it2++)
373 {
374 cout << "Draw projectile" << endl;
375
376 Projectile proj = it2->second;
377
378 FLOAT_POSITION target = mapPlayers[proj.target].pos;
379 float angle = atan2(target.y-proj.pos.toFloat().y, target.x-proj.pos.toFloat().x);
380
381 POSITION start, end;
382 start.x = cos(angle)*15+proj.pos.x;
383 start.y = sin(angle)*15+proj.pos.y;
384 end.x = proj.pos.x;
385 end.y = proj.pos.y;
386
387 start = mapToScreen(start);
388 end = mapToScreen(end);
389
390 al_draw_line(start.x, start.y, end.x, end.y, al_map_rgb(0, 0, 0), 4);
391 }
392 }
393
394 al_flip_display();
395 }
396 }
397
398 #if defined WINDOWS
399 closesocket(sock);
400 #elif defined LINUX
401 close(sock);
402 #endif
403
404 shutdownWinSock();
405
406 delete wndLogin;
407 delete wndMain;
408
409 delete gameMap;
410
411 al_destroy_event_queue(event_queue);
412 al_destroy_display(display);
413 al_destroy_timer(timer);
414
415 return 0;
416}
417
418// need to make a function like this that works on windows
419void error(const char *msg)
420{
421 perror(msg);
422 shutdownWinSock();
423 exit(1);
424}
425
426void initWinSock()
427{
428#if defined WINDOWS
429 WORD wVersionRequested;
430 WSADATA wsaData;
431 int wsaerr;
432
433 wVersionRequested = MAKEWORD(2, 2);
434 wsaerr = WSAStartup(wVersionRequested, &wsaData);
435
436 if (wsaerr != 0) {
437 cout << "The Winsock dll not found." << endl;
438 exit(1);
439 }else
440 cout << "The Winsock dll was found." << endl;
441#endif
442}
443
444void shutdownWinSock()
445{
446#if defined WINDOWS
447 WSACleanup();
448#endif
449}
450
451POSITION screenToMap(POSITION pos)
452{
453 pos.x = pos.x-300;
454 pos.y = pos.y-100;
455
456 if (pos.x < 0 || pos.y < 0)
457 {
458 pos.x = -1;
459 pos.y = -1;
460 }
461
462 return pos;
463}
464
465POSITION mapToScreen(POSITION pos)
466{
467 pos.x = pos.x+300;
468 pos.y = pos.y+100;
469
470 return pos;
471}
472
473POSITION mapToScreen(FLOAT_POSITION pos)
474{
475 POSITION p;
476 p.x = pos.x+300;
477 p.y = pos.y+100;
478
479 return p;
480}
481
482void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, WorldMap *gameMap, map<unsigned int, Player>& mapPlayers, map<unsigned int, Projectile>& mapProjectiles, unsigned int& curPlayerId, int &scoreBlue, int &scoreRed)
483{
484 string response = string(msg.buffer);
485
486 cout << "Processing message" << endl;
487
488 switch(state)
489 {
490 case STATE_START:
491 {
492 cout << "In STATE_START" << endl;
493
494 switch(msg.type)
495 {
496 case MSG_TYPE_REGISTER:
497 {
498 break;
499 }
500 case MSG_TYPE_LOGIN:
501 {
502 if (response.compare("Player has already logged in.") == 0)
503 {
504 username.clear();
505 cout << "User login failed" << endl;
506 }
507 else if (response.compare("Incorrect username or password") == 0)
508 {
509 username.clear();
510 cout << "User login failed" << endl;
511 }
512 else
513 {
514 state = STATE_LOGIN;
515 wndCurrent = wndMain;
516
517 Player p("", "");
518 p.deserialize(msg.buffer);
519 mapPlayers[p.id] = p;
520 curPlayerId = p.id;
521
522 cout << "Got a valid login response with the player" << endl;
523 cout << "Player id: " << curPlayerId << endl;
524 cout << "map size: " << mapPlayers.size() << endl;
525 }
526
527 break;
528 }
529 case MSG_TYPE_PLAYER: // kind of hacky to put this here
530 {
531 cout << "Got MSG_TYPE_PLAYER message in STATE_START" << endl;
532
533 Player p("", "");
534 p.deserialize(msg.buffer);
535 p.timeLastUpdated = getCurrentMillis();
536 mapPlayers[p.id] = p;
537
538 cout << "new player id: " << p.id << endl;
539 cout << "map size: " << mapPlayers.size() << endl;
540
541 break;
542 }
543 case MSG_TYPE_OBJECT:
544 {
545 cout << "Received OBJECT message in STATE_START." << endl;
546
547 WorldMap::Object o(0, WorldMap::OBJECT_NONE, 0, 0);
548 o.deserialize(msg.buffer);
549 cout << "object id: " << o.id << endl;
550 gameMap->updateObject(o.id, o.type, o.pos.x, o.pos.y);
551
552 break;
553 }
554 }
555
556 break;
557 }
558 case STATE_LOGIN:
559 {
560 switch(msg.type)
561 {
562 case MSG_TYPE_REGISTER:
563 {
564 break;
565 }
566 case MSG_TYPE_LOGIN:
567 {
568 cout << "Got a login message" << endl;
569
570 chatConsole.addLine(response);
571 cout << "Added new line" << endl;
572
573 break;
574 }
575 case MSG_TYPE_LOGOUT:
576 {
577 cout << "Got a logout message" << endl;
578
579 if (response.compare("You have successfully logged out.") == 0)
580 {
581 cout << "Logged out" << endl;
582 state = STATE_START;
583 wndCurrent = wndLogin;
584 }
585
586 break;
587 }
588 case MSG_TYPE_PLAYER:
589 {
590 cout << "Got MSG_TYPE_PLAYER message in STATE_LOGIN" << endl;
591
592 Player p("", "");
593 p.deserialize(msg.buffer);
594 p.timeLastUpdated = getCurrentMillis();
595 mapPlayers[p.id] = p;
596
597 break;
598 }
599 case MSG_TYPE_PLAYER_MOVE:
600 {
601 cout << "Got a player move message" << endl;
602
603 unsigned int id;
604 int x, y;
605
606 memcpy(&id, msg.buffer, 4);
607 memcpy(&x, msg.buffer+4, 4);
608 memcpy(&y, msg.buffer+8, 4);
609
610 mapPlayers[id].target.x = x;
611 mapPlayers[id].target.y = y;
612
613 break;
614 }
615 case MSG_TYPE_CHAT:
616 {
617 chatConsole.addLine(response);
618
619 break;
620 }
621 case MSG_TYPE_OBJECT:
622 {
623 cout << "Received object message in STATE_LOGIN." << endl;
624
625 WorldMap::Object o(0, WorldMap::OBJECT_NONE, 0, 0);
626 o.deserialize(msg.buffer);
627 gameMap->updateObject(o.id, o.type, o.pos.x, o.pos.y);
628
629 break;
630 }
631 case MSG_TYPE_REMOVE_OBJECT:
632 {
633 cout << "Received REMOVE_OBJECT message!" << endl;
634
635 int id;
636 memcpy(&id, msg.buffer, 4);
637
638 cout << "Removing object with id " << id << endl;
639
640 if (!gameMap->removeObject(id))
641 cout << "Did not remove the object" << endl;
642
643 break;
644 }
645 case MSG_TYPE_SCORE:
646 {
647 memcpy(&scoreBlue, msg.buffer, 4);
648 memcpy(&scoreRed, msg.buffer+4, 4);
649
650 break;
651 }
652 case MSG_TYPE_ATTACK:
653 {
654 break;
655 }
656 case MSG_TYPE_PROJECTILE:
657 {
658 cout << "Received a PROJECTILE message" << endl;
659
660 int id, x, y, targetId;
661
662 memcpy(&id, msg.buffer, 4);
663 memcpy(&x, msg.buffer+4, 4);
664 memcpy(&y, msg.buffer+8, 4);
665 memcpy(&targetId, msg.buffer+12, 4);
666
667 cout << "id: " << id << endl;
668 cout << "x: " << x << endl;
669 cout << "y: " << y << endl;
670 cout << "Target: " << targetId << endl;
671
672 Projectile proj(x, y, targetId, 0);
673 proj.setId(id);
674
675 mapProjectiles[id] = proj;
676
677 break;
678 }
679 case MSG_TYPE_REMOVE_PROJECTILE:
680 {
681 cout << "Received a REMOVE_PROJECTILE message" << endl;
682
683 int id;
684
685 memcpy(&id, msg.buffer, 4);
686
687 mapProjectiles.erase(id);
688
689 break;
690 }
691 default:
692 {
693 cout << "Received an unexpected message type: " << msg.type << endl;
694 }
695 }
696
697 break;
698 }
699 default:
700 {
701 cout << "The state has an invalid value: " << state << endl;
702
703 break;
704 }
705 }
706}
707
708// this should probably be in the WorldMap class
709void drawMap(WorldMap* gameMap)
710{
711 POSITION mapPos;
712 mapPos.x = 0;
713 mapPos.y = 0;
714 mapPos = mapToScreen(mapPos);
715
716 for (int x=0; x<12; x++)
717 {
718 for (int y=0; y<12; y++)
719 {
720 WorldMap::TerrainType el = gameMap->getElement(x, y);
721 WorldMap::StructureType structure = gameMap->getStructure(x, y);
722
723 if (el == WorldMap::TERRAIN_GRASS)
724 al_draw_filled_rectangle(x*25+mapPos.x, y*25+mapPos.y, x*25+25+mapPos.x, y*25+25+mapPos.y, al_map_rgb(0, 255, 0));
725 else if (el == WorldMap::TERRAIN_OCEAN)
726 al_draw_filled_rectangle(x*25+mapPos.x, y*25+mapPos.y, x*25+25+mapPos.x, y*25+25+mapPos.y, al_map_rgb(0, 0, 255));
727 else if (el == WorldMap::TERRAIN_ROCK)
728 al_draw_filled_rectangle(x*25+mapPos.x, y*25+mapPos.y, x*25+25+mapPos.x, y*25+25+mapPos.y, al_map_rgb(100, 100, 0));
729
730 if (structure == WorldMap::STRUCTURE_BLUE_FLAG) {
731 al_draw_circle(x*25+12+mapPos.x, y*25+12+mapPos.y, 12, al_map_rgb(0, 0, 0), 3);
732 //al_draw_filled_rectangle(x*25+5+mapPos.x, y*25+5+mapPos.y, x*25+20+mapPos.x, y*25+20+mapPos.y, al_map_rgb(0, 0, 255));
733 }else if (structure == WorldMap::STRUCTURE_RED_FLAG) {
734 al_draw_circle(x*25+12+mapPos.x, y*25+12+mapPos.y, 12, al_map_rgb(0, 0, 0), 3);
735 //al_draw_filled_rectangle(x*25+5+mapPos.x, y*25+5+mapPos.y, x*25+20+mapPos.x, y*25+20+mapPos.y, al_map_rgb(255, 0, 0));
736 }
737 }
738 }
739
740 for (int x=0; x<12; x++)
741 {
742 for (int y=0; y<12; y++)
743 {
744 vector<WorldMap::Object> vctObjects = gameMap->getObjects(x, y);
745
746 vector<WorldMap::Object>::iterator it;
747 for(it = vctObjects.begin(); it != vctObjects.end(); it++) {
748 switch(it->type) {
749 case WorldMap::OBJECT_BLUE_FLAG:
750 al_draw_filled_rectangle(it->pos.x-8+mapPos.x, it->pos.y-8+mapPos.y, it->pos.x+8+mapPos.x, it->pos.y+8+mapPos.y, al_map_rgb(0, 0, 255));
751 break;
752 case WorldMap::OBJECT_RED_FLAG:
753 al_draw_filled_rectangle(it->pos.x-8+mapPos.x, it->pos.y-8+mapPos.y, it->pos.x+8+mapPos.x, it->pos.y+8+mapPos.y, al_map_rgb(255, 0, 0));
754 break;
755 }
756 }
757 }
758 }
759}
760
761void drawPlayers(map<unsigned int, Player>& mapPlayers, ALLEGRO_FONT* font, unsigned int curPlayerId)
762{
763 map<unsigned int, Player>::iterator it;
764
765 Player* p;
766 POSITION pos;
767 ALLEGRO_COLOR color;
768
769 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
770 {
771 p = &it->second;
772 pos = mapToScreen(p->pos);
773
774 if (p->id == curPlayerId)
775 al_draw_filled_circle(pos.x, pos.y, 14, al_map_rgb(0, 0, 0));
776
777 if (p->team == 0)
778 color = al_map_rgb(0, 0, 255);
779 else if (p->team == 1)
780 color = al_map_rgb(255, 0, 0);
781
782 al_draw_filled_circle(pos.x, pos.y, 12, color);
783
784 // draw player class
785 int fontHeight = al_get_font_line_height(font);
786
787 string strClass;
788 switch (p->playerClass) {
789 case Player::CLASS_WARRIOR:
790 strClass = "W";
791 break;
792 case Player::CLASS_RANGER:
793 strClass = "R";
794 break;
795 case Player::CLASS_NONE:
796 strClass = "";
797 break;
798 default:
799 strClass = "";
800 break;
801 }
802 al_draw_text(font, al_map_rgb(0, 0, 0), pos.x, pos.y-fontHeight/2, ALLEGRO_ALIGN_CENTRE, strClass.c_str());
803
804 // draw player health
805 al_draw_filled_rectangle(pos.x-12, pos.y-24, pos.x+12, pos.y-16, al_map_rgb(0, 0, 0));
806 if (it->second.maxHealth != 0)
807 al_draw_filled_rectangle(pos.x-11, pos.y-23, pos.x-11+(22*it->second.health)/it->second.maxHealth, pos.y-17, al_map_rgb(255, 0, 0));
808
809 if (p->hasBlueFlag)
810 al_draw_filled_rectangle(pos.x+4, pos.y-18, pos.x+18, pos.y-4, al_map_rgb(0, 0, 255));
811 else if (p->hasRedFlag)
812 al_draw_filled_rectangle(pos.x+4, pos.y-18, pos.x+18, pos.y-4, al_map_rgb(255, 0, 0));
813 }
814}
815
816void registerAccount()
817{
818 string username = txtUsername->getStr();
819 string password = txtPassword->getStr();
820
821 txtUsername->clear();
822 txtPassword->clear();
823
824 msgTo.type = MSG_TYPE_REGISTER;
825
826 strcpy(msgTo.buffer, username.c_str());
827 strcpy(msgTo.buffer+username.size()+1, password.c_str());
828
829 sendMessage(&msgTo, sock, &server);
830}
831
832void login()
833{
834 string strUsername = txtUsername->getStr();
835 string strPassword = txtPassword->getStr();
836 username = strUsername;
837
838 txtUsername->clear();
839 txtPassword->clear();
840
841 msgTo.type = MSG_TYPE_LOGIN;
842
843 strcpy(msgTo.buffer, strUsername.c_str());
844 strcpy(msgTo.buffer+username.size()+1, strPassword.c_str());
845
846 sendMessage(&msgTo, sock, &server);
847}
848
849void logout()
850{
851 txtChat->clear();
852
853 msgTo.type = MSG_TYPE_LOGOUT;
854
855 strcpy(msgTo.buffer, username.c_str());
856
857 sendMessage(&msgTo, sock, &server);
858}
859
860void quit()
861{
862 doexit = true;
863}
864
865void sendChatMessage()
866{
867 string msg = txtChat->getStr();
868
869 txtChat->clear();
870
871 msgTo.type = MSG_TYPE_CHAT;
872
873 strcpy(msgTo.buffer, msg.c_str());
874
875 sendMessage(&msgTo, sock, &server);
876}
Note: See TracBrowser for help on using the repository browser.