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
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 <sys/types.h>
16#include <cstdio>
17#include <cstdlib>
18#include <string>
19#include <iostream>
20#include <sstream>
21
22#include <map>
23
24#include <map>
25
26#include <allegro5/allegro.h>
27#include <allegro5/allegro_font.h>
28#include <allegro5/allegro_ttf.h>
29#include <allegro5/allegro_primitives.h>
30
31#include "../../common/Message.h"
32#include "../../common/Common.h"
33#include "../../common/WorldMap.h"
34#include "../../common/Player.h"
35
36#include "Window.h"
37#include "Textbox.h"
38#include "Button.h"
39#include "chat.h"
40
41#ifdef WINDOWS
42 #pragma comment(lib, "ws2_32.lib")
43#endif
44
45using namespace std;
46
47void initWinSock();
48void shutdownWinSock();
49void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player>& mapPlayers, unsigned int& curPlayerId);
50void drawMap(WorldMap* gameMap);
51void drawPlayers(map<unsigned int, Player>& mapPlayers, unsigned int curPlayerId);
52POSITION screenToMap(POSITION pos);
53POSITION mapToScreen(POSITION pos);
54
55// callbacks
56void registerAccount();
57void login();
58void logout();
59void quit();
60void sendChatMessage();
61
62void error(const char *);
63
64const float FPS = 60;
65const int SCREEN_W = 640;
66const int SCREEN_H = 480;
67const int BOUNCER_SIZE = 32;
68enum MYKEYS {
69 KEY_UP,
70 KEY_DOWN,
71 KEY_LEFT,
72 KEY_RIGHT
73};
74
75enum STATE {
76 STATE_START,
77 STATE_LOGIN // this means you're already logged in
78};
79
80int state;
81
82bool doexit;
83
84map<unsigned int, Player> mapPlayers;
85
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;
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;
109 doexit = false;
110 map<unsigned int, Player> mapPlayers;
111 unsigned int curPlayerId = -1;
112
113 float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
114 float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
115
116 state = STATE_START;
117
118 if(!al_init()) {
119 fprintf(stderr, "failed to initialize allegro!\n");
120 return -1;
121 }
122
123 if (al_init_primitives_addon())
124 cout << "Primitives initialized" << endl;
125 else
126 cout << "Primitives not initialized" << endl;
127
128 al_init_font_addon();
129 al_init_ttf_addon();
130
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
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 }
147
148 if(!al_install_mouse()) {
149 fprintf(stderr, "failed to initialize the mouse!\n");
150 return -1;
151 }
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 }
165
166 WorldMap* gameMap = WorldMap::loadMapFromFile("../../data/map.txt");
167
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
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());
213 al_register_event_source(event_queue, al_get_mouse_event_source());
214
215 al_clear_to_color(al_map_rgb(0,0,0));
216
217 al_flip_display();
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
230 set_nonblock(sock);
231
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
240 al_start_timer(timer);
241
242 while(!doexit)
243 {
244 ALLEGRO_EVENT ev;
245
246 al_wait_for_event(event_queue, &ev);
247
248 if(wndCurrent->handleEvent(ev)) {
249 // do nothing
250 }
251 else if(ev.type == ALLEGRO_EVENT_TIMER) {
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) {
271 doexit = true;
272 }
273 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
274 switch(ev.keyboard.keycode) {
275 case ALLEGRO_KEY_UP:
276 key[KEY_UP] = true;
277 break;
278
279 case ALLEGRO_KEY_DOWN:
280 key[KEY_DOWN] = true;
281 break;
282
283 case ALLEGRO_KEY_LEFT:
284 key[KEY_LEFT] = true;
285 break;
286
287 case ALLEGRO_KEY_RIGHT:
288 key[KEY_RIGHT] = true;
289 break;
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 }
315 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
316 if(wndCurrent == wndMain) {
317 msgTo.type = MSG_TYPE_PLAYER_MOVE;
318
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);
329
330 sendMessage(&msgTo, sock, &server);
331 }
332 else
333 cout << "Invalid point: User did not click on the map" << endl;
334 }
335 }
336
337 if (receiveMessage(&msgFrom, sock, &from) >= 0)
338 processMessage(msgFrom, state, chatConsole, mapPlayers, curPlayerId);
339
340 if (redraw && al_is_event_queue_empty(event_queue))
341 {
342 redraw = false;
343
344 wndCurrent->draw(display);
345
346 chatConsole.draw(font, al_map_rgb(255,255,255));
347
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:");
354
355 drawMap(gameMap);
356 drawPlayers(mapPlayers, curPlayerId);
357 }
358
359 al_flip_display();
360 }
361 }
362
363 #if defined WINDOWS
364 closesocket(sock);
365 #elif defined LINUX
366 close(sock);
367 #endif
368
369 shutdownWinSock();
370
371 delete wndLogin;
372 delete wndMain;
373
374 delete gameMap;
375
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
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
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
415}
416
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
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
448void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player>& mapPlayers, unsigned int& curPlayerId)
449{
450 string response = string(msg.buffer);
451
452 switch(state)
453 {
454 case STATE_START:
455 {
456 cout << "In STATE_START" << endl;
457
458 switch(msg.type)
459 {
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;
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;
488 }
489
490 break;
491 }
492 }
493
494 break;
495 }
496 case STATE_LOGIN:
497 {
498 switch(msg.type)
499 {
500 case MSG_TYPE_REGISTER:
501 {
502 break;
503 }
504 case MSG_TYPE_LOGIN:
505 {
506 chatConsole.addLine(response);
507
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
519 break;
520 }
521 case MSG_TYPE_PLAYER:
522 {
523 Player p("", "");
524 p.deserialize(msg.buffer);
525 mapPlayers[p.id] = p;
526
527 break;
528 }
529 case MSG_TYPE_CHAT:
530 {
531 chatConsole.addLine(response);
532
533 break;
534 }
535 }
536
537 break;
538 }
539 default:
540 {
541 cout << "The state has an invalid value: " << state << endl;
542
543 break;
544 }
545 }
546}
547
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
570void drawPlayers(map<unsigned int, Player>& mapPlayers, unsigned int curPlayerId)
571{
572 map<unsigned int, Player>::iterator it;
573
574 Player* p;
575 POSITION pos;
576
577 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
578 {
579 p = &it->second;
580 pos = mapToScreen(p->pos);
581
582 if (p->id == curPlayerId)
583 al_draw_filled_circle(pos.x, pos.y, 12, al_map_rgb(255, 0, 0));
584 else
585 al_draw_filled_circle(pos.x, pos.y, 12, al_map_rgb(191, 0, 0));
586 }
587}
588
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.