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

Last change on this file since d3e8f60 was 8c74150, checked in by dportnoy <dmp1488@…>, 11 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
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
[a1a3bd5]353 // update player positions
354 map<unsigned int, Player>::iterator it;
355 for (it = mapPlayers.begin(); it != mapPlayers.end(); it++)
356 {
[227baaa]357 it->second.move(gameMap); // ignore return value
[a1a3bd5]358 }
359
[8c74150]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
[62ee2ce]368 drawMap(gameMap);
[d09fe76]369 drawPlayers(mapPlayers, font, curPlayerId);
[8c74150]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 }
[87b3ee2]392 }
393
[d352805]394 al_flip_display();
395 }
396 }
[9a3e6b1]397
398 #if defined WINDOWS
399 closesocket(sock);
400 #elif defined LINUX
401 close(sock);
402 #endif
403
404 shutdownWinSock();
[d352805]405
[87b3ee2]406 delete wndLogin;
407 delete wndMain;
408
[62ee2ce]409 delete gameMap;
410
[d352805]411 al_destroy_event_queue(event_queue);
412 al_destroy_display(display);
413 al_destroy_timer(timer);
414
415 return 0;
416}
417
[4da5aa3]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
[0dde5da]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
[1912323]449}
450
[62ee2ce]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
[ca44f82]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
[fbcfc35]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)
[1912323]483{
[4da5aa3]484 string response = string(msg.buffer);
485
[a1a3bd5]486 cout << "Processing message" << endl;
487
[4da5aa3]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 {
[7511a2b]531 cout << "Got MSG_TYPE_PLAYER message in STATE_START" << endl;
[a1a3bd5]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
[45b2750]541 break;
542 }
543 case MSG_TYPE_OBJECT:
544 {
[7511a2b]545 cout << "Received OBJECT message in STATE_START." << endl;
[45b2750]546
547 WorldMap::Object o(0, WorldMap::OBJECT_NONE, 0, 0);
548 o.deserialize(msg.buffer);
[7511a2b]549 cout << "object id: " << o.id << endl;
[45b2750]550 gameMap->updateObject(o.id, o.type, o.pos.x, o.pos.y);
551
[87b3ee2]552 break;
553 }
[4da5aa3]554 }
555
556 break;
557 }
558 case STATE_LOGIN:
559 {
[eb8adb1]560 switch(msg.type)
[4da5aa3]561 {
[87b3ee2]562 case MSG_TYPE_REGISTER:
563 {
564 break;
565 }
566 case MSG_TYPE_LOGIN:
567 {
[a1a3bd5]568 cout << "Got a login message" << endl;
569
[eb8adb1]570 chatConsole.addLine(response);
[a1a3bd5]571 cout << "Added new line" << endl;
[eb8adb1]572
[a1a3bd5]573 break;
574 }
575 case MSG_TYPE_LOGOUT:
576 {
[054b50b]577 cout << "Got a logout message" << endl;
[a1a3bd5]578
[87b3ee2]579 if (response.compare("You have successfully logged out.") == 0)
580 {
581 cout << "Logged out" << endl;
582 state = STATE_START;
583 wndCurrent = wndLogin;
584 }
[054b50b]585
586 break;
587 }
[4c202e0]588 case MSG_TYPE_PLAYER:
589 {
[7511a2b]590 cout << "Got MSG_TYPE_PLAYER message in STATE_LOGIN" << endl;
[a1a3bd5]591
[60776f2]592 Player p("", "");
593 p.deserialize(msg.buffer);
[054b50b]594 p.timeLastUpdated = getCurrentMillis();
[3a79253]595 mapPlayers[p.id] = p;
[4c202e0]596
[eb8adb1]597 break;
598 }
[a1a3bd5]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 }
[eb8adb1]615 case MSG_TYPE_CHAT:
616 {
617 chatConsole.addLine(response);
[4c202e0]618
[87b3ee2]619 break;
620 }
[45b2750]621 case MSG_TYPE_OBJECT:
622 {
[7511a2b]623 cout << "Received object message in STATE_LOGIN." << endl;
[45b2750]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 }
[2df63d6]631 case MSG_TYPE_REMOVE_OBJECT:
632 {
[7511a2b]633 cout << "Received REMOVE_OBJECT message!" << endl;
634
[2df63d6]635 int id;
636 memcpy(&id, msg.buffer, 4);
[7511a2b]637
638 cout << "Removing object with id " << id << endl;
639
[2df63d6]640 if (!gameMap->removeObject(id))
641 cout << "Did not remove the object" << endl;
[7511a2b]642
643 break;
[2df63d6]644 }
[15efb4e]645 case MSG_TYPE_SCORE:
646 {
647 memcpy(&scoreBlue, msg.buffer, 4);
648 memcpy(&scoreRed, msg.buffer+4, 4);
649
650 break;
651 }
[b978503]652 case MSG_TYPE_ATTACK:
653 {
654 break;
655 }
656 case MSG_TYPE_PROJECTILE:
657 {
[8c74150]658 cout << "Received a PROJECTILE message" << endl;
[fbcfc35]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
[8c74150]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;
[fbcfc35]676
[b978503]677 break;
678 }
679 case MSG_TYPE_REMOVE_PROJECTILE:
680 {
[8c74150]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
[b978503]689 break;
690 }
[45b2750]691 default:
692 {
693 cout << "Received an unexpected message type: " << msg.type << endl;
694 }
[4da5aa3]695 }
[eb8adb1]696
[4da5aa3]697 break;
698 }
699 default:
700 {
701 cout << "The state has an invalid value: " << state << endl;
702
703 break;
704 }
705 }
[0dde5da]706}
[87b3ee2]707
[d436ac4]708// this should probably be in the WorldMap class
[62ee2ce]709void drawMap(WorldMap* gameMap)
710{
711 POSITION mapPos;
712 mapPos.x = 0;
713 mapPos.y = 0;
714 mapPos = mapToScreen(mapPos);
[6e66ffd]715
[62ee2ce]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);
[cc1c6c1]721 WorldMap::StructureType structure = gameMap->getStructure(x, y);
[62ee2ce]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));
[a1a3bd5]729
[6e66ffd]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 }
[62ee2ce]757 }
758 }
759}
760
[d09fe76]761void drawPlayers(map<unsigned int, Player>& mapPlayers, ALLEGRO_FONT* font, unsigned int curPlayerId)
[88cdae2]762{
763 map<unsigned int, Player>::iterator it;
764
[62ee2ce]765 Player* p;
766 POSITION pos;
[d09fe76]767 ALLEGRO_COLOR color;
[62ee2ce]768
[88cdae2]769 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
770 {
[62ee2ce]771 p = &it->second;
772 pos = mapToScreen(p->pos);
[88cdae2]773
[7efed11]774 if (p->id == curPlayerId)
[a6066e8]775 al_draw_filled_circle(pos.x, pos.y, 14, al_map_rgb(0, 0, 0));
776
777 if (p->team == 0)
[d09fe76]778 color = al_map_rgb(0, 0, 255);
[a6066e8]779 else if (p->team == 1)
[d09fe76]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)
[e1f78f5]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));
[7efed11]808
[7d91bbe]809 if (p->hasBlueFlag)
[7efed11]810 al_draw_filled_rectangle(pos.x+4, pos.y-18, pos.x+18, pos.y-4, al_map_rgb(0, 0, 255));
[a6066e8]811 else if (p->hasRedFlag)
[7efed11]812 al_draw_filled_rectangle(pos.x+4, pos.y-18, pos.x+18, pos.y-4, al_map_rgb(255, 0, 0));
[88cdae2]813 }
814}
815
[87b3ee2]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.