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

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

Removed some print statements

  • Property mode set to 100644
File size: 15.1 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
[d352805]15#include <sys/types.h>
[88cdae2]16#include <cstdio>
17#include <cstdlib>
[a845faf]18#include <string>
[1912323]19#include <iostream>
[88cdae2]20#include <sstream>
[1912323]21
[eb8adb1]22#include <map>
[1912323]23
[3a79253]24#include <map>
25
[d352805]26#include <allegro5/allegro.h>
27#include <allegro5/allegro_font.h>
28#include <allegro5/allegro_ttf.h>
[88cdae2]29#include <allegro5/allegro_primitives.h>
[7d7df47]30
[b53c6b3]31#include "../../common/Message.h"
[e607c0f]32#include "../../common/Common.h"
[62ee2ce]33#include "../../common/WorldMap.h"
[4c202e0]34#include "../../common/Player.h"
[7d7df47]35
[87b3ee2]36#include "Window.h"
37#include "Textbox.h"
38#include "Button.h"
[6475138]39#include "chat.h"
40
[a845faf]41#ifdef WINDOWS
[6475138]42 #pragma comment(lib, "ws2_32.lib")
[a845faf]43#endif
[1912323]44
45using namespace std;
46
[0dde5da]47void initWinSock();
48void shutdownWinSock();
[88cdae2]49void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player>& mapPlayers, unsigned int& curPlayerId);
[62ee2ce]50void drawMap(WorldMap* gameMap);
[88cdae2]51void drawPlayers(map<unsigned int, Player>& mapPlayers, unsigned int curPlayerId);
[62ee2ce]52POSITION screenToMap(POSITION pos);
53POSITION mapToScreen(POSITION pos);
[87b3ee2]54
55// callbacks
56void registerAccount();
57void login();
58void logout();
59void quit();
60void sendChatMessage();
[4da5aa3]61
[1912323]62void error(const char *);
[7d7df47]63
[d352805]64const float FPS = 60;
65const int SCREEN_W = 640;
66const int SCREEN_H = 480;
67const int BOUNCER_SIZE = 32;
68enum MYKEYS {
[0cc431d]69 KEY_UP,
70 KEY_DOWN,
71 KEY_LEFT,
72 KEY_RIGHT
73};
74
75enum STATE {
76 STATE_START,
[87b3ee2]77 STATE_LOGIN // this means you're already logged in
[d352805]78};
[87b3ee2]79
80int state;
81
82bool doexit;
83
[3a79253]84map<unsigned int, Player> mapPlayers;
85
[87b3ee2]86Window* wndLogin;
87Window* wndMain;
88Window* wndCurrent;
89
90Textbox* txtUsername;
91Textbox* txtPassword;
92Textbox* txtChat;
93
94int sock;
95struct sockaddr_in server, from;
96struct hostent *hp;
97NETWORK_MSG msgTo, msgFrom;
98string username;
99chat chatConsole;
[d352805]100
101int main(int argc, char **argv)
102{
103 ALLEGRO_DISPLAY *display = NULL;
104 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
105 ALLEGRO_TIMER *timer = NULL;
106 ALLEGRO_BITMAP *bouncer = NULL;
107 bool key[4] = { false, false, false, false };
108 bool redraw = true;
[87b3ee2]109 doexit = false;
[eb8adb1]110 map<unsigned int, Player> mapPlayers;
[88cdae2]111 unsigned int curPlayerId = -1;
[9a3e6b1]112
[87b3ee2]113 float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
114 float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
[0cc431d]115
[87b3ee2]116 state = STATE_START;
[9a3e6b1]117
[d352805]118 if(!al_init()) {
119 fprintf(stderr, "failed to initialize allegro!\n");
120 return -1;
121 }
122
[88cdae2]123 if (al_init_primitives_addon())
124 cout << "Primitives initialized" << endl;
125 else
126 cout << "Primitives not initialized" << endl;
127
[d352805]128 al_init_font_addon();
129 al_init_ttf_addon();
130
[88cdae2]131 #if defined WINDOWS
132 ALLEGRO_FONT *font = al_load_ttf_font("../pirulen.ttf", 12, 0);
133 #elif defined LINUX
134 ALLEGRO_FONT *font = al_load_ttf_font("pirulen.ttf", 12, 0);
135 #endif
136
[d352805]137 if (!font) {
138 fprintf(stderr, "Could not load 'pirulen.ttf'.\n");
139 getchar();
140 return -1;
141 }
142
143 if(!al_install_keyboard()) {
144 fprintf(stderr, "failed to initialize the keyboard!\n");
145 return -1;
146 }
[87b3ee2]147
148 if(!al_install_mouse()) {
149 fprintf(stderr, "failed to initialize the mouse!\n");
150 return -1;
151 }
[d352805]152
153 timer = al_create_timer(1.0 / FPS);
154 if(!timer) {
155 fprintf(stderr, "failed to create timer!\n");
156 return -1;
157 }
158
159 display = al_create_display(SCREEN_W, SCREEN_H);
160 if(!display) {
161 fprintf(stderr, "failed to create display!\n");
162 al_destroy_timer(timer);
163 return -1;
164 }
[87b3ee2]165
[384b7e0]166 WorldMap* gameMap = WorldMap::loadMapFromFile("../../data/map.txt");
[62ee2ce]167
[87b3ee2]168 wndLogin = new Window(0, 0, SCREEN_W, SCREEN_H);
169 wndLogin->addComponent(new Textbox(104, 40, 100, 20, font));
170 wndLogin->addComponent(new Textbox(104, 70, 100, 20, font));
171 wndLogin->addComponent(new Button(22, 100, 90, 20, font, "Register", registerAccount));
172 wndLogin->addComponent(new Button(122, 100, 60, 20, font, "Login", login));
173 wndLogin->addComponent(new Button(540, 10, 80, 20, font, "Quit", quit));
174
175 txtUsername = (Textbox*)wndLogin->getComponent(0);
176 txtPassword = (Textbox*)wndLogin->getComponent(1);
177
178 wndMain = new Window(0, 0, SCREEN_W, SCREEN_H);
179 wndMain->addComponent(new Textbox(95, 40, 525, 20, font));
180 wndMain->addComponent(new Button(95, 70, 160, 20, font, "Send Message", sendChatMessage));
181 wndMain->addComponent(new Button(540, 10, 80, 20, font, "Logout", logout));
182
183 txtChat = (Textbox*)wndMain->getComponent(0);
184
185 wndCurrent = wndLogin;
186
[d352805]187 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
188 if(!bouncer) {
189 fprintf(stderr, "failed to create bouncer bitmap!\n");
190 al_destroy_display(display);
191 al_destroy_timer(timer);
192 return -1;
193 }
194
195 event_queue = al_create_event_queue();
196 if(!event_queue) {
197 fprintf(stderr, "failed to create event_queue!\n");
198 al_destroy_bitmap(bouncer);
199 al_destroy_display(display);
200 al_destroy_timer(timer);
201 return -1;
202 }
203
204 al_set_target_bitmap(bouncer);
205
206 al_clear_to_color(al_map_rgb(255, 0, 255));
207
208 al_set_target_bitmap(al_get_backbuffer(display));
209
210 al_register_event_source(event_queue, al_get_display_event_source(display));
211 al_register_event_source(event_queue, al_get_timer_event_source(timer));
212 al_register_event_source(event_queue, al_get_keyboard_event_source());
[87b3ee2]213 al_register_event_source(event_queue, al_get_mouse_event_source());
[d352805]214
215 al_clear_to_color(al_map_rgb(0,0,0));
216
217 al_flip_display();
[9a3e6b1]218
219 if (argc != 3) {
220 cout << "Usage: server port" << endl;
221 exit(1);
222 }
223
224 initWinSock();
225
226 sock = socket(AF_INET, SOCK_DGRAM, 0);
227 if (sock < 0)
228 error("socket");
229
[e607c0f]230 set_nonblock(sock);
231
[9a3e6b1]232 server.sin_family = AF_INET;
233 hp = gethostbyname(argv[1]);
234 if (hp==0)
235 error("Unknown host");
236
237 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
238 server.sin_port = htons(atoi(argv[2]));
239
[d352805]240 al_start_timer(timer);
[e607c0f]241
[d352805]242 while(!doexit)
243 {
244 ALLEGRO_EVENT ev;
[3d81c0d]245
[d352805]246 al_wait_for_event(event_queue, &ev);
[87b3ee2]247
248 if(wndCurrent->handleEvent(ev)) {
249 // do nothing
250 }
251 else if(ev.type == ALLEGRO_EVENT_TIMER) {
[d352805]252 if(key[KEY_UP] && bouncer_y >= 4.0) {
253 bouncer_y -= 4.0;
254 }
255
256 if(key[KEY_DOWN] && bouncer_y <= SCREEN_H - BOUNCER_SIZE - 4.0) {
257 bouncer_y += 4.0;
258 }
259
260 if(key[KEY_LEFT] && bouncer_x >= 4.0) {
261 bouncer_x -= 4.0;
262 }
263
264 if(key[KEY_RIGHT] && bouncer_x <= SCREEN_W - BOUNCER_SIZE - 4.0) {
265 bouncer_x += 4.0;
266 }
267
268 redraw = true;
269 }
270 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
[9a3e6b1]271 doexit = true;
[d352805]272 }
273 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
[87b3ee2]274 switch(ev.keyboard.keycode) {
275 case ALLEGRO_KEY_UP:
276 key[KEY_UP] = true;
277 break;
[d352805]278
[87b3ee2]279 case ALLEGRO_KEY_DOWN:
280 key[KEY_DOWN] = true;
281 break;
[d352805]282
[87b3ee2]283 case ALLEGRO_KEY_LEFT:
284 key[KEY_LEFT] = true;
285 break;
[d352805]286
[87b3ee2]287 case ALLEGRO_KEY_RIGHT:
288 key[KEY_RIGHT] = true;
289 break;
[d352805]290 }
291 }
292 else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
293 switch(ev.keyboard.keycode) {
294 case ALLEGRO_KEY_UP:
295 key[KEY_UP] = false;
296 break;
297
298 case ALLEGRO_KEY_DOWN:
299 key[KEY_DOWN] = false;
300 break;
301
302 case ALLEGRO_KEY_LEFT:
303 key[KEY_LEFT] = false;
304 break;
305
306 case ALLEGRO_KEY_RIGHT:
307 key[KEY_RIGHT] = false;
308 break;
309
310 case ALLEGRO_KEY_ESCAPE:
311 doexit = true;
312 break;
313 }
314 }
[88cdae2]315 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
[ad5d122]316 if(wndCurrent == wndMain) {
317 msgTo.type = MSG_TYPE_PLAYER_MOVE;
[88cdae2]318
[62ee2ce]319 POSITION pos;
320 pos.x = ev.mouse.x;
321 pos.y = ev.mouse.y;
322 pos = screenToMap(pos);
323
324 if (pos.x != -1)
325 {
326 memcpy(msgTo.buffer, &curPlayerId, 4);
327 memcpy(msgTo.buffer+4, &pos.x, 4);
328 memcpy(msgTo.buffer+8, &pos.y, 4);
[88cdae2]329
[62ee2ce]330 sendMessage(&msgTo, sock, &server);
331 }
332 else
333 cout << "Invalid point: User did not click on the map" << endl;
[ad5d122]334 }
[88cdae2]335 }
[e607c0f]336
337 if (receiveMessage(&msgFrom, sock, &from) >= 0)
[88cdae2]338 processMessage(msgFrom, state, chatConsole, mapPlayers, curPlayerId);
[d352805]339
[e607c0f]340 if (redraw && al_is_event_queue_empty(event_queue))
341 {
[d352805]342 redraw = false;
[88cdae2]343
[87b3ee2]344 wndCurrent->draw(display);
[9a3e6b1]345
[6475138]346 chatConsole.draw(font, al_map_rgb(255,255,255));
[9a3e6b1]347
[87b3ee2]348 if(wndCurrent == wndLogin) {
349 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Username:");
350 al_draw_text(font, al_map_rgb(0, 255, 0), 1, 73, ALLEGRO_ALIGN_LEFT, "Password:");
351 }
352 else if(wndCurrent == wndMain) {
353 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Message:");
[62ee2ce]354
355 drawMap(gameMap);
356 drawPlayers(mapPlayers, curPlayerId);
[87b3ee2]357 }
358
[d352805]359 al_flip_display();
360 }
361 }
[9a3e6b1]362
363 #if defined WINDOWS
364 closesocket(sock);
365 #elif defined LINUX
366 close(sock);
367 #endif
368
369 shutdownWinSock();
[d352805]370
[87b3ee2]371 delete wndLogin;
372 delete wndMain;
373
[62ee2ce]374 delete gameMap;
375
[d352805]376 al_destroy_event_queue(event_queue);
377 al_destroy_bitmap(bouncer);
378 al_destroy_display(display);
379 al_destroy_timer(timer);
380
381 return 0;
382}
383
[4da5aa3]384// need to make a function like this that works on windows
385void error(const char *msg)
386{
387 perror(msg);
388 shutdownWinSock();
389 exit(1);
390}
391
[0dde5da]392void initWinSock()
393{
394#if defined WINDOWS
395 WORD wVersionRequested;
396 WSADATA wsaData;
397 int wsaerr;
398
399 wVersionRequested = MAKEWORD(2, 2);
400 wsaerr = WSAStartup(wVersionRequested, &wsaData);
401
402 if (wsaerr != 0) {
403 cout << "The Winsock dll not found." << endl;
404 exit(1);
405 }else
406 cout << "The Winsock dll was found." << endl;
407#endif
408}
409
410void shutdownWinSock()
411{
412#if defined WINDOWS
413 WSACleanup();
414#endif
[1912323]415}
416
[62ee2ce]417POSITION screenToMap(POSITION pos)
418{
419 pos.x = pos.x-300;
420 pos.y = pos.y-100;
421
422 if (pos.x < 0 || pos.y < 0)
423 {
424 pos.x = -1;
425 pos.y = -1;
426 }
427
428 return pos;
429}
430
431POSITION mapToScreen(POSITION pos)
432{
433 pos.x = pos.x+300;
434 pos.y = pos.y+100;
435
436 return pos;
437}
438
[ca44f82]439POSITION mapToScreen(FLOAT_POSITION pos)
440{
441 POSITION p;
442 p.x = pos.x+300;
443 p.y = pos.y+100;
444
445 return p;
446}
447
[88cdae2]448void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player>& mapPlayers, unsigned int& curPlayerId)
[1912323]449{
[4da5aa3]450 string response = string(msg.buffer);
451
452 switch(state)
453 {
454 case STATE_START:
455 {
[e607c0f]456 cout << "In STATE_START" << endl;
457
[87b3ee2]458 switch(msg.type)
[4da5aa3]459 {
[87b3ee2]460 case MSG_TYPE_REGISTER:
461 {
462 break;
463 }
464 case MSG_TYPE_LOGIN:
465 {
466 if (response.compare("Player has already logged in.") == 0)
467 {
468 username.clear();
469 cout << "User login failed" << endl;
470 }
471 else if (response.compare("Incorrect username or password") == 0)
472 {
473 username.clear();
474 cout << "User login failed" << endl;
475 }
476 else
477 {
478 state = STATE_LOGIN;
479 wndCurrent = wndMain;
[88cdae2]480
481 Player p("", "");
482 p.deserialize(msg.buffer);
483 mapPlayers[p.id] = p;
484 curPlayerId = p.id;
485
486 cout << "Got a valid login response with the player" << endl;
487 cout << "Player id: " << curPlayerId << endl;
[87b3ee2]488 }
[88cdae2]489
[87b3ee2]490 break;
491 }
[4da5aa3]492 }
493
494 break;
495 }
496 case STATE_LOGIN:
497 {
[eb8adb1]498 switch(msg.type)
[4da5aa3]499 {
[87b3ee2]500 case MSG_TYPE_REGISTER:
501 {
502 break;
503 }
504 case MSG_TYPE_LOGIN:
505 {
[eb8adb1]506 chatConsole.addLine(response);
507
[87b3ee2]508 if (response.compare("You have successfully logged out.") == 0)
509 {
510 cout << "Logged out" << endl;
511 state = STATE_START;
512 wndCurrent = wndLogin;
513 }
514 else
515 {
516 cout << "Added new line" << endl;
517 }
518
[4c202e0]519 break;
520 }
521 case MSG_TYPE_PLAYER:
522 {
[60776f2]523 Player p("", "");
524 p.deserialize(msg.buffer);
[3a79253]525 mapPlayers[p.id] = p;
[4c202e0]526
[eb8adb1]527 break;
528 }
529 case MSG_TYPE_CHAT:
530 {
531 chatConsole.addLine(response);
[4c202e0]532
[87b3ee2]533 break;
534 }
[4da5aa3]535 }
[eb8adb1]536
[4da5aa3]537 break;
538 }
539 default:
540 {
541 cout << "The state has an invalid value: " << state << endl;
542
543 break;
544 }
545 }
[0dde5da]546}
[87b3ee2]547
[62ee2ce]548void drawMap(WorldMap* gameMap)
549{
550 POSITION mapPos;
551 mapPos.x = 0;
552 mapPos.y = 0;
553 mapPos = mapToScreen(mapPos);
554 for (int x=0; x<12; x++)
555 {
556 for (int y=0; y<12; y++)
557 {
558 WorldMap::TerrainType el = gameMap->getElement(x, y);
559
560 if (el == WorldMap::TERRAIN_GRASS)
561 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));
562 else if (el == WorldMap::TERRAIN_OCEAN)
563 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));
564 else if (el == WorldMap::TERRAIN_ROCK)
565 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));
566 }
567 }
568}
569
[88cdae2]570void drawPlayers(map<unsigned int, Player>& mapPlayers, unsigned int curPlayerId)
571{
572 map<unsigned int, Player>::iterator it;
573
[62ee2ce]574 Player* p;
575 POSITION pos;
576
[88cdae2]577 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
578 {
[62ee2ce]579 p = &it->second;
580 pos = mapToScreen(p->pos);
[88cdae2]581
582 if (p->id == curPlayerId)
[62ee2ce]583 al_draw_filled_circle(pos.x, pos.y, 12, al_map_rgb(255, 0, 0));
[88cdae2]584 else
[62ee2ce]585 al_draw_filled_circle(pos.x, pos.y, 12, al_map_rgb(191, 0, 0));
[88cdae2]586 }
587}
588
[87b3ee2]589void registerAccount()
590{
591 string username = txtUsername->getStr();
592 string password = txtPassword->getStr();
593
594 txtUsername->clear();
595 txtPassword->clear();
596
597 msgTo.type = MSG_TYPE_REGISTER;
598
599 strcpy(msgTo.buffer, username.c_str());
600 strcpy(msgTo.buffer+username.size()+1, password.c_str());
601
602 sendMessage(&msgTo, sock, &server);
603}
604
605void login()
606{
607 string strUsername = txtUsername->getStr();
608 string strPassword = txtPassword->getStr();
609 username = strUsername;
610
611 txtUsername->clear();
612 txtPassword->clear();
613
614 msgTo.type = MSG_TYPE_LOGIN;
615
616 strcpy(msgTo.buffer, strUsername.c_str());
617 strcpy(msgTo.buffer+username.size()+1, strPassword.c_str());
618
619 sendMessage(&msgTo, sock, &server);
620}
621
622void logout()
623{
624 txtChat->clear();
625
626 msgTo.type = MSG_TYPE_LOGOUT;
627
628 strcpy(msgTo.buffer, username.c_str());
629
630 sendMessage(&msgTo, sock, &server);
631}
632
633void quit()
634{
635 doexit = true;
636}
637
638void sendChatMessage()
639{
640 string msg = txtChat->getStr();
641
642 txtChat->clear();
643
644 msgTo.type = MSG_TYPE_CHAT;
645
646 strcpy(msgTo.buffer, msg.c_str());
647
648 sendMessage(&msgTo, sock, &server);
649}
Note: See TracBrowser for help on using the repository browser.