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

Last change on this file since 5a5f131 was 5a5f131, checked in by dportnoy <dmp1488@…>, 12 years ago

Dead players aren't drawn

  • Property mode set to 100644
File size: 24.8 KB
RevLine 
[4c202e0]1#include "../../common/Compiler.h"
2
[e08572c]3#if defined WINDOWS
[0dde5da]4 #include <winsock2.h>
5 #include <WS2tcpip.h>
[e08572c]6#elif defined LINUX
[0dde5da]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>
[a845faf]13#endif
[1912323]14
[88cdae2]15#include <cstdio>
16#include <cstdlib>
[8c74150]17#include <cmath>
18#include <sys/types.h>
[a845faf]19#include <string>
[1912323]20#include <iostream>
[88cdae2]21#include <sstream>
[3a79253]22#include <map>
23
[d352805]24#include <allegro5/allegro.h>
25#include <allegro5/allegro_font.h>
26#include <allegro5/allegro_ttf.h>
[88cdae2]27#include <allegro5/allegro_primitives.h>
[7d7df47]28
[b53c6b3]29#include "../../common/Message.h"
[e607c0f]30#include "../../common/Common.h"
[62ee2ce]31#include "../../common/WorldMap.h"
[4c202e0]32#include "../../common/Player.h"
[fbcfc35]33#include "../../common/Projectile.h"
[7d7df47]34
[87b3ee2]35#include "Window.h"
36#include "Textbox.h"
37#include "Button.h"
[6475138]38#include "chat.h"
39
[a845faf]40#ifdef WINDOWS
[6475138]41 #pragma comment(lib, "ws2_32.lib")
[a845faf]42#endif
[1912323]43
44using namespace std;
45
[0dde5da]46void initWinSock();
47void shutdownWinSock();
[fbcfc35]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);
[62ee2ce]49void drawMap(WorldMap* gameMap);
[d09fe76]50void drawPlayers(map<unsigned int, Player>& mapPlayers, ALLEGRO_FONT* font, unsigned int curPlayerId);
[62ee2ce]51POSITION screenToMap(POSITION pos);
52POSITION mapToScreen(POSITION pos);
[87b3ee2]53
54// callbacks
55void registerAccount();
56void login();
57void logout();
58void quit();
59void sendChatMessage();
[4da5aa3]60
[1912323]61void error(const char *);
[7d7df47]62
[d352805]63const float FPS = 60;
64const int SCREEN_W = 640;
65const int SCREEN_H = 480;
[0cc431d]66
67enum STATE {
68 STATE_START,
[87b3ee2]69 STATE_LOGIN // this means you're already logged in
[d352805]70};
[87b3ee2]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;
[d352805]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;
[87b3ee2]98 doexit = false;
[eb8adb1]99 map<unsigned int, Player> mapPlayers;
[fbcfc35]100 map<unsigned int, Projectile> mapProjectiles;
[88cdae2]101 unsigned int curPlayerId = -1;
[15efb4e]102 int scoreBlue, scoreRed;
103
104 scoreBlue = 0;
105 scoreRed = 0;
[9a3e6b1]106
[87b3ee2]107 state = STATE_START;
[9a3e6b1]108
[d352805]109 if(!al_init()) {
110 fprintf(stderr, "failed to initialize allegro!\n");
111 return -1;
112 }
113
[88cdae2]114 if (al_init_primitives_addon())
115 cout << "Primitives initialized" << endl;
116 else
117 cout << "Primitives not initialized" << endl;
118
[d352805]119 al_init_font_addon();
120 al_init_ttf_addon();
121
[88cdae2]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
[d352805]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 }
[87b3ee2]138
139 if(!al_install_mouse()) {
140 fprintf(stderr, "failed to initialize the mouse!\n");
141 return -1;
142 }
[d352805]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 }
[87b3ee2]156
[384b7e0]157 WorldMap* gameMap = WorldMap::loadMapFromFile("../../data/map.txt");
[62ee2ce]158
[87b3ee2]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;
[d352805]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());
[87b3ee2]191 al_register_event_source(event_queue, al_get_mouse_event_source());
[d352805]192
193 al_clear_to_color(al_map_rgb(0,0,0));
194
195 al_flip_display();
[9a3e6b1]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
[e607c0f]208 set_nonblock(sock);
209
[9a3e6b1]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
[d352805]218 al_start_timer(timer);
[e607c0f]219
[d352805]220 while(!doexit)
221 {
222 ALLEGRO_EVENT ev;
[3d81c0d]223
[d352805]224 al_wait_for_event(event_queue, &ev);
[87b3ee2]225
226 if(wndCurrent->handleEvent(ev)) {
227 // do nothing
228 }
229 else if(ev.type == ALLEGRO_EVENT_TIMER) {
[a1a3bd5]230 redraw = true; // seems like we should just call a draw function here instead
[d352805]231 }
232 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
[9a3e6b1]233 doexit = true;
[d352805]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;
[4926168]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;
[626e5b0]249 case ALLEGRO_KEY_D: // drop the current item
250 if (state == STATE_LOGIN) {
[4926168]251 // find the current player in the player list
[626e5b0]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;
[d352805]276 }
277 }
[88cdae2]278 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
[ad5d122]279 if(wndCurrent == wndMain) {
[e1f78f5]280 if (ev.mouse.button == 1) { // left click
281 msgTo.type = MSG_TYPE_PLAYER_MOVE;
[88cdae2]282
[e1f78f5]283 POSITION pos;
284 pos.x = ev.mouse.x;
285 pos.y = ev.mouse.y;
286 pos = screenToMap(pos);
[62ee2ce]287
[e1f78f5]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
[fbcfc35]301 cout << "Detected a right-click" << endl;
302
[e1f78f5]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 {
[fbcfc35]313 // need to check if the right-click was actually on this player
[e1f78f5]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);
[88cdae2]319
[e1f78f5]320 sendMessage(&msgTo, sock, &server);
321 }
322 }
[62ee2ce]323 }
[ad5d122]324 }
[88cdae2]325 }
[e607c0f]326
327 if (receiveMessage(&msgFrom, sock, &from) >= 0)
[fbcfc35]328 processMessage(msgFrom, state, chatConsole, gameMap, mapPlayers, mapProjectiles, curPlayerId, scoreBlue, scoreRed);
[054b50b]329
[a1a3bd5]330 if (redraw)
[e607c0f]331 {
[d352805]332 redraw = false;
[88cdae2]333
[87b3ee2]334 wndCurrent->draw(display);
[9a3e6b1]335
[6475138]336 chatConsole.draw(font, al_map_rgb(255,255,255));
[9a3e6b1]337
[87b3ee2]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:");
[62ee2ce]344
[15efb4e]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
[032e550]353 // update players
[a1a3bd5]354 map<unsigned int, Player>::iterator it;
[032e550]355 for (it = mapPlayers.begin(); it != mapPlayers.end(); it++)
356 {
357 it->second.updateTarget(mapPlayers);
358 }
359
[a1a3bd5]360 for (it = mapPlayers.begin(); it != mapPlayers.end(); it++)
361 {
[227baaa]362 it->second.move(gameMap); // ignore return value
[a1a3bd5]363 }
364
[8c74150]365 // update projectile positions
366 map<unsigned int, Projectile>::iterator it2;
367 for (it2 = mapProjectiles.begin(); it2 != mapProjectiles.end(); it2++)
368 {
369 it2->second.move(mapPlayers);
370 }
371
[62ee2ce]372 drawMap(gameMap);
[d09fe76]373 drawPlayers(mapPlayers, font, curPlayerId);
[8c74150]374
375 // draw projectiles
376 for (it2 = mapProjectiles.begin(); it2 != mapProjectiles.end(); it2++)
377 {
378 Projectile proj = it2->second;
379
380 FLOAT_POSITION target = mapPlayers[proj.target].pos;
381 float angle = atan2(target.y-proj.pos.toFloat().y, target.x-proj.pos.toFloat().x);
382
383 POSITION start, end;
384 start.x = cos(angle)*15+proj.pos.x;
385 start.y = sin(angle)*15+proj.pos.y;
386 end.x = proj.pos.x;
387 end.y = proj.pos.y;
388
389 start = mapToScreen(start);
390 end = mapToScreen(end);
391
392 al_draw_line(start.x, start.y, end.x, end.y, al_map_rgb(0, 0, 0), 4);
393 }
[87b3ee2]394 }
395
[d352805]396 al_flip_display();
397 }
398 }
[9a3e6b1]399
400 #if defined WINDOWS
401 closesocket(sock);
402 #elif defined LINUX
403 close(sock);
404 #endif
405
406 shutdownWinSock();
[d352805]407
[87b3ee2]408 delete wndLogin;
409 delete wndMain;
410
[62ee2ce]411 delete gameMap;
412
[d352805]413 al_destroy_event_queue(event_queue);
414 al_destroy_display(display);
415 al_destroy_timer(timer);
416
417 return 0;
418}
419
[4da5aa3]420// need to make a function like this that works on windows
421void error(const char *msg)
422{
423 perror(msg);
424 shutdownWinSock();
425 exit(1);
426}
427
[0dde5da]428void initWinSock()
429{
430#if defined WINDOWS
431 WORD wVersionRequested;
432 WSADATA wsaData;
433 int wsaerr;
434
435 wVersionRequested = MAKEWORD(2, 2);
436 wsaerr = WSAStartup(wVersionRequested, &wsaData);
437
438 if (wsaerr != 0) {
439 cout << "The Winsock dll not found." << endl;
440 exit(1);
441 }else
442 cout << "The Winsock dll was found." << endl;
443#endif
444}
445
446void shutdownWinSock()
447{
448#if defined WINDOWS
449 WSACleanup();
450#endif
[1912323]451}
452
[62ee2ce]453POSITION screenToMap(POSITION pos)
454{
455 pos.x = pos.x-300;
456 pos.y = pos.y-100;
457
458 if (pos.x < 0 || pos.y < 0)
459 {
460 pos.x = -1;
461 pos.y = -1;
462 }
463
464 return pos;
465}
466
467POSITION mapToScreen(POSITION pos)
468{
469 pos.x = pos.x+300;
470 pos.y = pos.y+100;
471
472 return pos;
473}
474
[ca44f82]475POSITION mapToScreen(FLOAT_POSITION pos)
476{
477 POSITION p;
478 p.x = pos.x+300;
479 p.y = pos.y+100;
480
481 return p;
482}
483
[fbcfc35]484void 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)
[1912323]485{
[4da5aa3]486 string response = string(msg.buffer);
487
488 switch(state)
489 {
490 case STATE_START:
491 {
[e607c0f]492 cout << "In STATE_START" << endl;
493
[87b3ee2]494 switch(msg.type)
[4da5aa3]495 {
[87b3ee2]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;
[88cdae2]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;
[a1a3bd5]524 cout << "map size: " << mapPlayers.size() << endl;
[87b3ee2]525 }
[88cdae2]526
[a1a3bd5]527 break;
528 }
529 case MSG_TYPE_PLAYER: // kind of hacky to put this here
530 {
531 Player p("", "");
532 p.deserialize(msg.buffer);
533 p.timeLastUpdated = getCurrentMillis();
534
[5a5f131]535 mapPlayers[p.id] = p;
[a1a3bd5]536
[45b2750]537 break;
538 }
539 case MSG_TYPE_OBJECT:
540 {
541 WorldMap::Object o(0, WorldMap::OBJECT_NONE, 0, 0);
542 o.deserialize(msg.buffer);
[7511a2b]543 cout << "object id: " << o.id << endl;
[45b2750]544 gameMap->updateObject(o.id, o.type, o.pos.x, o.pos.y);
545
[87b3ee2]546 break;
547 }
[4da5aa3]548 }
549
550 break;
551 }
552 case STATE_LOGIN:
553 {
[eb8adb1]554 switch(msg.type)
[4da5aa3]555 {
[87b3ee2]556 case MSG_TYPE_REGISTER:
557 {
558 break;
559 }
560 case MSG_TYPE_LOGIN:
561 {
[a1a3bd5]562 cout << "Got a login message" << endl;
563
[eb8adb1]564 chatConsole.addLine(response);
[a1a3bd5]565 cout << "Added new line" << endl;
[eb8adb1]566
[a1a3bd5]567 break;
568 }
569 case MSG_TYPE_LOGOUT:
570 {
[054b50b]571 cout << "Got a logout message" << endl;
[a1a3bd5]572
[87b3ee2]573 if (response.compare("You have successfully logged out.") == 0)
574 {
575 cout << "Logged out" << endl;
576 state = STATE_START;
577 wndCurrent = wndLogin;
578 }
[054b50b]579
580 break;
581 }
[4c202e0]582 case MSG_TYPE_PLAYER:
583 {
[60776f2]584 Player p("", "");
585 p.deserialize(msg.buffer);
[054b50b]586 p.timeLastUpdated = getCurrentMillis();
[032e550]587 p.isChasing = false;
[5a5f131]588 if (p.health <= 0)
589 p.isDead = true;
590 else
591 p.isDead = false;
592
[3a79253]593 mapPlayers[p.id] = p;
[4c202e0]594
[eb8adb1]595 break;
596 }
[a1a3bd5]597 case MSG_TYPE_PLAYER_MOVE:
598 {
599 unsigned int id;
600 int x, y;
601
602 memcpy(&id, msg.buffer, 4);
603 memcpy(&x, msg.buffer+4, 4);
604 memcpy(&y, msg.buffer+8, 4);
605
606 mapPlayers[id].target.x = x;
607 mapPlayers[id].target.y = y;
608
609 break;
610 }
[eb8adb1]611 case MSG_TYPE_CHAT:
612 {
613 chatConsole.addLine(response);
[4c202e0]614
[87b3ee2]615 break;
616 }
[45b2750]617 case MSG_TYPE_OBJECT:
618 {
[7511a2b]619 cout << "Received object message in STATE_LOGIN." << endl;
[45b2750]620
621 WorldMap::Object o(0, WorldMap::OBJECT_NONE, 0, 0);
622 o.deserialize(msg.buffer);
623 gameMap->updateObject(o.id, o.type, o.pos.x, o.pos.y);
624
625 break;
626 }
[2df63d6]627 case MSG_TYPE_REMOVE_OBJECT:
628 {
[7511a2b]629 cout << "Received REMOVE_OBJECT message!" << endl;
630
[2df63d6]631 int id;
632 memcpy(&id, msg.buffer, 4);
[7511a2b]633
634 cout << "Removing object with id " << id << endl;
635
[2df63d6]636 if (!gameMap->removeObject(id))
637 cout << "Did not remove the object" << endl;
[7511a2b]638
639 break;
[2df63d6]640 }
[15efb4e]641 case MSG_TYPE_SCORE:
642 {
643 memcpy(&scoreBlue, msg.buffer, 4);
644 memcpy(&scoreRed, msg.buffer+4, 4);
645
646 break;
647 }
[b978503]648 case MSG_TYPE_ATTACK:
649 {
[032e550]650 cout << "Received ATTACK message" << endl;
651
652 break;
653 }
654 case MSG_TYPE_START_ATTACK:
655 {
656 cout << "Received START_ATTACK message" << endl;
657
658 unsigned int id, targetID;
659 memcpy(&id, msg.buffer, 4);
660 memcpy(&targetID, msg.buffer+4, 4);
661
662 cout << "source id: " << id << endl;
663 cout << "target id: " << targetID << endl;
664
665 Player* source = &mapPlayers[id];
666 source->targetPlayer = targetID;
667 source->isChasing = true;
668
[b978503]669 break;
670 }
671 case MSG_TYPE_PROJECTILE:
672 {
[8c74150]673 cout << "Received a PROJECTILE message" << endl;
[fbcfc35]674
675 int id, x, y, targetId;
676
677 memcpy(&id, msg.buffer, 4);
678 memcpy(&x, msg.buffer+4, 4);
679 memcpy(&y, msg.buffer+8, 4);
680 memcpy(&targetId, msg.buffer+12, 4);
681
[8c74150]682 cout << "id: " << id << endl;
683 cout << "x: " << x << endl;
684 cout << "y: " << y << endl;
685 cout << "Target: " << targetId << endl;
686
687 Projectile proj(x, y, targetId, 0);
688 proj.setId(id);
689
690 mapProjectiles[id] = proj;
[fbcfc35]691
[b978503]692 break;
693 }
694 case MSG_TYPE_REMOVE_PROJECTILE:
695 {
[8c74150]696 cout << "Received a REMOVE_PROJECTILE message" << endl;
697
698 int id;
699
700 memcpy(&id, msg.buffer, 4);
701
702 mapProjectiles.erase(id);
703
[b978503]704 break;
705 }
[45b2750]706 default:
707 {
708 cout << "Received an unexpected message type: " << msg.type << endl;
709 }
[4da5aa3]710 }
[eb8adb1]711
[4da5aa3]712 break;
713 }
714 default:
715 {
716 cout << "The state has an invalid value: " << state << endl;
717
718 break;
719 }
720 }
[0dde5da]721}
[87b3ee2]722
[d436ac4]723// this should probably be in the WorldMap class
[62ee2ce]724void drawMap(WorldMap* gameMap)
725{
726 POSITION mapPos;
727 mapPos.x = 0;
728 mapPos.y = 0;
729 mapPos = mapToScreen(mapPos);
[6e66ffd]730
[62ee2ce]731 for (int x=0; x<12; x++)
732 {
733 for (int y=0; y<12; y++)
734 {
735 WorldMap::TerrainType el = gameMap->getElement(x, y);
[cc1c6c1]736 WorldMap::StructureType structure = gameMap->getStructure(x, y);
[62ee2ce]737
738 if (el == WorldMap::TERRAIN_GRASS)
739 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));
740 else if (el == WorldMap::TERRAIN_OCEAN)
741 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));
742 else if (el == WorldMap::TERRAIN_ROCK)
743 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));
[a1a3bd5]744
[6e66ffd]745 if (structure == WorldMap::STRUCTURE_BLUE_FLAG) {
746 al_draw_circle(x*25+12+mapPos.x, y*25+12+mapPos.y, 12, al_map_rgb(0, 0, 0), 3);
747 //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));
748 }else if (structure == WorldMap::STRUCTURE_RED_FLAG) {
749 al_draw_circle(x*25+12+mapPos.x, y*25+12+mapPos.y, 12, al_map_rgb(0, 0, 0), 3);
750 //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));
751 }
752 }
753 }
754
755 for (int x=0; x<12; x++)
756 {
757 for (int y=0; y<12; y++)
758 {
759 vector<WorldMap::Object> vctObjects = gameMap->getObjects(x, y);
760
761 vector<WorldMap::Object>::iterator it;
762 for(it = vctObjects.begin(); it != vctObjects.end(); it++) {
763 switch(it->type) {
764 case WorldMap::OBJECT_BLUE_FLAG:
765 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));
766 break;
767 case WorldMap::OBJECT_RED_FLAG:
768 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));
769 break;
770 }
771 }
[62ee2ce]772 }
773 }
774}
775
[d09fe76]776void drawPlayers(map<unsigned int, Player>& mapPlayers, ALLEGRO_FONT* font, unsigned int curPlayerId)
[88cdae2]777{
778 map<unsigned int, Player>::iterator it;
779
[62ee2ce]780 Player* p;
781 POSITION pos;
[d09fe76]782 ALLEGRO_COLOR color;
[62ee2ce]783
[88cdae2]784 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
785 {
[62ee2ce]786 p = &it->second;
[5a5f131]787
788 if (p->isDead)
789 continue;
790
[62ee2ce]791 pos = mapToScreen(p->pos);
[88cdae2]792
[7efed11]793 if (p->id == curPlayerId)
[a6066e8]794 al_draw_filled_circle(pos.x, pos.y, 14, al_map_rgb(0, 0, 0));
795
796 if (p->team == 0)
[d09fe76]797 color = al_map_rgb(0, 0, 255);
[a6066e8]798 else if (p->team == 1)
[d09fe76]799 color = al_map_rgb(255, 0, 0);
800
801 al_draw_filled_circle(pos.x, pos.y, 12, color);
802
803 // draw player class
804 int fontHeight = al_get_font_line_height(font);
805
806 string strClass;
807 switch (p->playerClass) {
808 case Player::CLASS_WARRIOR:
809 strClass = "W";
810 break;
811 case Player::CLASS_RANGER:
812 strClass = "R";
813 break;
814 case Player::CLASS_NONE:
815 strClass = "";
816 break;
817 default:
818 strClass = "";
819 break;
820 }
821 al_draw_text(font, al_map_rgb(0, 0, 0), pos.x, pos.y-fontHeight/2, ALLEGRO_ALIGN_CENTRE, strClass.c_str());
822
823 // draw player health
824 al_draw_filled_rectangle(pos.x-12, pos.y-24, pos.x+12, pos.y-16, al_map_rgb(0, 0, 0));
825 if (it->second.maxHealth != 0)
[e1f78f5]826 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));
[7efed11]827
[7d91bbe]828 if (p->hasBlueFlag)
[7efed11]829 al_draw_filled_rectangle(pos.x+4, pos.y-18, pos.x+18, pos.y-4, al_map_rgb(0, 0, 255));
[a6066e8]830 else if (p->hasRedFlag)
[7efed11]831 al_draw_filled_rectangle(pos.x+4, pos.y-18, pos.x+18, pos.y-4, al_map_rgb(255, 0, 0));
[88cdae2]832 }
833}
834
[87b3ee2]835void registerAccount()
836{
837 string username = txtUsername->getStr();
838 string password = txtPassword->getStr();
839
840 txtUsername->clear();
841 txtPassword->clear();
842
843 msgTo.type = MSG_TYPE_REGISTER;
844
845 strcpy(msgTo.buffer, username.c_str());
846 strcpy(msgTo.buffer+username.size()+1, password.c_str());
847
848 sendMessage(&msgTo, sock, &server);
849}
850
851void login()
852{
853 string strUsername = txtUsername->getStr();
854 string strPassword = txtPassword->getStr();
855 username = strUsername;
856
857 txtUsername->clear();
858 txtPassword->clear();
859
860 msgTo.type = MSG_TYPE_LOGIN;
861
862 strcpy(msgTo.buffer, strUsername.c_str());
863 strcpy(msgTo.buffer+username.size()+1, strPassword.c_str());
864
865 sendMessage(&msgTo, sock, &server);
866}
867
868void logout()
869{
870 txtChat->clear();
871
872 msgTo.type = MSG_TYPE_LOGOUT;
873
874 strcpy(msgTo.buffer, username.c_str());
875
876 sendMessage(&msgTo, sock, &server);
877}
878
879void quit()
880{
881 doexit = true;
882}
883
884void sendChatMessage()
885{
886 string msg = txtChat->getStr();
887
888 txtChat->clear();
889
890 msgTo.type = MSG_TYPE_CHAT;
891
892 strcpy(msgTo.buffer, msg.c_str());
893
894 sendMessage(&msgTo, sock, &server);
895}
Note: See TracBrowser for help on using the repository browser.