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

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

Updated files to correctly compile on Windows

  • Property mode set to 100644
File size: 15.3 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");
167 //delete gameMap;
168 //gameMap = WorldMap::createDefaultMap();
[62ee2ce]169
[87b3ee2]170 wndLogin = new Window(0, 0, SCREEN_W, SCREEN_H);
171 wndLogin->addComponent(new Textbox(104, 40, 100, 20, font));
172 wndLogin->addComponent(new Textbox(104, 70, 100, 20, font));
173 wndLogin->addComponent(new Button(22, 100, 90, 20, font, "Register", registerAccount));
174 wndLogin->addComponent(new Button(122, 100, 60, 20, font, "Login", login));
175 wndLogin->addComponent(new Button(540, 10, 80, 20, font, "Quit", quit));
176
177 txtUsername = (Textbox*)wndLogin->getComponent(0);
178 txtPassword = (Textbox*)wndLogin->getComponent(1);
179
180 wndMain = new Window(0, 0, SCREEN_W, SCREEN_H);
181 wndMain->addComponent(new Textbox(95, 40, 525, 20, font));
182 wndMain->addComponent(new Button(95, 70, 160, 20, font, "Send Message", sendChatMessage));
183 wndMain->addComponent(new Button(540, 10, 80, 20, font, "Logout", logout));
184
185 txtChat = (Textbox*)wndMain->getComponent(0);
186
187 wndCurrent = wndLogin;
188
[d352805]189 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
190 if(!bouncer) {
191 fprintf(stderr, "failed to create bouncer bitmap!\n");
192 al_destroy_display(display);
193 al_destroy_timer(timer);
194 return -1;
195 }
196
197 event_queue = al_create_event_queue();
198 if(!event_queue) {
199 fprintf(stderr, "failed to create event_queue!\n");
200 al_destroy_bitmap(bouncer);
201 al_destroy_display(display);
202 al_destroy_timer(timer);
203 return -1;
204 }
205
206 al_set_target_bitmap(bouncer);
207
208 al_clear_to_color(al_map_rgb(255, 0, 255));
209
210 al_set_target_bitmap(al_get_backbuffer(display));
211
212 al_register_event_source(event_queue, al_get_display_event_source(display));
213 al_register_event_source(event_queue, al_get_timer_event_source(timer));
214 al_register_event_source(event_queue, al_get_keyboard_event_source());
[87b3ee2]215 al_register_event_source(event_queue, al_get_mouse_event_source());
[d352805]216
217 al_clear_to_color(al_map_rgb(0,0,0));
218
219 al_flip_display();
[9a3e6b1]220
221 if (argc != 3) {
222 cout << "Usage: server port" << endl;
223 exit(1);
224 }
225
226 initWinSock();
227
228 sock = socket(AF_INET, SOCK_DGRAM, 0);
229 if (sock < 0)
230 error("socket");
231
[e607c0f]232 set_nonblock(sock);
233
[9a3e6b1]234 server.sin_family = AF_INET;
235 hp = gethostbyname(argv[1]);
236 if (hp==0)
237 error("Unknown host");
238
239 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
240 server.sin_port = htons(atoi(argv[2]));
241
[d352805]242 al_start_timer(timer);
[e607c0f]243
[d352805]244 while(!doexit)
245 {
246 ALLEGRO_EVENT ev;
247 al_wait_for_event(event_queue, &ev);
[87b3ee2]248
249 if(wndCurrent->handleEvent(ev)) {
250 // do nothing
251 }
252 else if(ev.type == ALLEGRO_EVENT_TIMER) {
[d352805]253 if(key[KEY_UP] && bouncer_y >= 4.0) {
254 bouncer_y -= 4.0;
255 }
256
257 if(key[KEY_DOWN] && bouncer_y <= SCREEN_H - BOUNCER_SIZE - 4.0) {
258 bouncer_y += 4.0;
259 }
260
261 if(key[KEY_LEFT] && bouncer_x >= 4.0) {
262 bouncer_x -= 4.0;
263 }
264
265 if(key[KEY_RIGHT] && bouncer_x <= SCREEN_W - BOUNCER_SIZE - 4.0) {
266 bouncer_x += 4.0;
267 }
268
269 redraw = true;
270 }
271 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
[9a3e6b1]272 doexit = true;
[d352805]273 }
274 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
[87b3ee2]275 switch(ev.keyboard.keycode) {
276 case ALLEGRO_KEY_UP:
277 key[KEY_UP] = true;
278 break;
[d352805]279
[87b3ee2]280 case ALLEGRO_KEY_DOWN:
281 key[KEY_DOWN] = true;
282 break;
[d352805]283
[87b3ee2]284 case ALLEGRO_KEY_LEFT:
285 key[KEY_LEFT] = true;
286 break;
[d352805]287
[87b3ee2]288 case ALLEGRO_KEY_RIGHT:
289 key[KEY_RIGHT] = true;
290 break;
[d352805]291 }
292 }
293 else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
294 switch(ev.keyboard.keycode) {
295 case ALLEGRO_KEY_UP:
296 key[KEY_UP] = false;
297 break;
298
299 case ALLEGRO_KEY_DOWN:
300 key[KEY_DOWN] = false;
301 break;
302
303 case ALLEGRO_KEY_LEFT:
304 key[KEY_LEFT] = false;
305 break;
306
307 case ALLEGRO_KEY_RIGHT:
308 key[KEY_RIGHT] = false;
309 break;
310
311 case ALLEGRO_KEY_ESCAPE:
312 doexit = true;
313 break;
314 }
315 }
[88cdae2]316 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
[ad5d122]317 if(wndCurrent == wndMain) {
318 msgTo.type = MSG_TYPE_PLAYER_MOVE;
[88cdae2]319
[62ee2ce]320 POSITION pos;
321 pos.x = ev.mouse.x;
322 pos.y = ev.mouse.y;
323 pos = screenToMap(pos);
324
325 if (pos.x != -1)
326 {
327 memcpy(msgTo.buffer, &curPlayerId, 4);
328 memcpy(msgTo.buffer+4, &pos.x, 4);
329 memcpy(msgTo.buffer+8, &pos.y, 4);
[88cdae2]330
[62ee2ce]331 sendMessage(&msgTo, sock, &server);
332 }
333 else
334 cout << "Invalid point: User did not click on the map" << endl;
[ad5d122]335 }
[88cdae2]336 }
[e607c0f]337
338 if (receiveMessage(&msgFrom, sock, &from) >= 0)
339 {
[88cdae2]340 processMessage(msgFrom, state, chatConsole, mapPlayers, curPlayerId);
[e607c0f]341 cout << "state: " << state << endl;
342 }
[d352805]343
[e607c0f]344 if (redraw && al_is_event_queue_empty(event_queue))
345 {
[d352805]346 redraw = false;
[88cdae2]347
[87b3ee2]348 wndCurrent->draw(display);
[9a3e6b1]349
[6475138]350 chatConsole.draw(font, al_map_rgb(255,255,255));
[9a3e6b1]351
[87b3ee2]352 if(wndCurrent == wndLogin) {
353 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Username:");
354 al_draw_text(font, al_map_rgb(0, 255, 0), 1, 73, ALLEGRO_ALIGN_LEFT, "Password:");
355 }
356 else if(wndCurrent == wndMain) {
357 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Message:");
[62ee2ce]358
359 drawMap(gameMap);
360 drawPlayers(mapPlayers, curPlayerId);
[87b3ee2]361 }
362
[d352805]363 al_flip_display();
364 }
365 }
[9a3e6b1]366
367 #if defined WINDOWS
368 closesocket(sock);
369 #elif defined LINUX
370 close(sock);
371 #endif
372
373 shutdownWinSock();
[d352805]374
[87b3ee2]375 delete wndLogin;
376 delete wndMain;
377
[62ee2ce]378 delete gameMap;
379
[d352805]380 al_destroy_event_queue(event_queue);
381 al_destroy_bitmap(bouncer);
382 al_destroy_display(display);
383 al_destroy_timer(timer);
384
385 return 0;
386}
387
[4da5aa3]388// need to make a function like this that works on windows
389void error(const char *msg)
390{
391 perror(msg);
392 shutdownWinSock();
393 exit(1);
394}
395
[0dde5da]396void initWinSock()
397{
398#if defined WINDOWS
399 WORD wVersionRequested;
400 WSADATA wsaData;
401 int wsaerr;
402
403 wVersionRequested = MAKEWORD(2, 2);
404 wsaerr = WSAStartup(wVersionRequested, &wsaData);
405
406 if (wsaerr != 0) {
407 cout << "The Winsock dll not found." << endl;
408 exit(1);
409 }else
410 cout << "The Winsock dll was found." << endl;
411#endif
412}
413
414void shutdownWinSock()
415{
416#if defined WINDOWS
417 WSACleanup();
418#endif
[1912323]419}
420
[62ee2ce]421POSITION screenToMap(POSITION pos)
422{
423 pos.x = pos.x-300;
424 pos.y = pos.y-100;
425
426 if (pos.x < 0 || pos.y < 0)
427 {
428 pos.x = -1;
429 pos.y = -1;
430 }
431
432 return pos;
433}
434
435POSITION mapToScreen(POSITION pos)
436{
437 pos.x = pos.x+300;
438 pos.y = pos.y+100;
439
440 return pos;
441}
442
[ca44f82]443POSITION mapToScreen(FLOAT_POSITION pos)
444{
445 POSITION p;
446 p.x = pos.x+300;
447 p.y = pos.y+100;
448
449 return p;
450}
451
[88cdae2]452void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole, map<unsigned int, Player>& mapPlayers, unsigned int& curPlayerId)
[1912323]453{
[4da5aa3]454 string response = string(msg.buffer);
455
[60776f2]456 cout << "Got message: " << msg.type << endl;
457
[4da5aa3]458 switch(state)
459 {
460 case STATE_START:
461 {
[e607c0f]462 cout << "In STATE_START" << endl;
463
[87b3ee2]464 switch(msg.type)
[4da5aa3]465 {
[87b3ee2]466 case MSG_TYPE_REGISTER:
467 {
468 break;
469 }
470 case MSG_TYPE_LOGIN:
471 {
472 if (response.compare("Player has already logged in.") == 0)
473 {
474 username.clear();
475 cout << "User login failed" << endl;
476 }
477 else if (response.compare("Incorrect username or password") == 0)
478 {
479 username.clear();
480 cout << "User login failed" << endl;
481 }
482 else
483 {
484 state = STATE_LOGIN;
485 wndCurrent = wndMain;
[88cdae2]486
487 Player p("", "");
488 p.deserialize(msg.buffer);
489 mapPlayers[p.id] = p;
490 curPlayerId = p.id;
491
492 cout << "Got a valid login response with the player" << endl;
493 cout << "Player id: " << curPlayerId << endl;
[87b3ee2]494 }
[88cdae2]495
[87b3ee2]496 break;
497 }
[4da5aa3]498 }
499
500 break;
501 }
502 case STATE_LOGIN:
503 {
[eb8adb1]504 switch(msg.type)
[4da5aa3]505 {
[87b3ee2]506 case MSG_TYPE_REGISTER:
507 {
508 break;
509 }
510 case MSG_TYPE_LOGIN:
511 {
[eb8adb1]512 chatConsole.addLine(response);
513
[87b3ee2]514 if (response.compare("You have successfully logged out.") == 0)
515 {
516 cout << "Logged out" << endl;
517 state = STATE_START;
518 wndCurrent = wndLogin;
519 }
520 else
521 {
522 cout << "Added new line" << endl;
523 }
524
[4c202e0]525 break;
526 }
527 case MSG_TYPE_PLAYER:
528 {
[60776f2]529 Player p("", "");
530 p.deserialize(msg.buffer);
[3a79253]531 mapPlayers[p.id] = p;
[4c202e0]532
[3a79253]533 cout << "p.id: " << p.id << endl;
[88cdae2]534
[eb8adb1]535 break;
536 }
537 case MSG_TYPE_CHAT:
538 {
539 chatConsole.addLine(response);
[4c202e0]540
[87b3ee2]541 break;
542 }
[4da5aa3]543 }
[eb8adb1]544
[4da5aa3]545 break;
546 }
547 default:
548 {
549 cout << "The state has an invalid value: " << state << endl;
550
551 break;
552 }
553 }
[0dde5da]554}
[87b3ee2]555
[62ee2ce]556void drawMap(WorldMap* gameMap)
557{
558 POSITION mapPos;
559 mapPos.x = 0;
560 mapPos.y = 0;
561 mapPos = mapToScreen(mapPos);
562 for (int x=0; x<12; x++)
563 {
564 for (int y=0; y<12; y++)
565 {
566 WorldMap::TerrainType el = gameMap->getElement(x, y);
567
568 if (el == WorldMap::TERRAIN_GRASS)
569 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));
570 else if (el == WorldMap::TERRAIN_OCEAN)
571 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));
572 else if (el == WorldMap::TERRAIN_ROCK)
573 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));
574 }
575 }
576}
577
[88cdae2]578void drawPlayers(map<unsigned int, Player>& mapPlayers, unsigned int curPlayerId)
579{
580 map<unsigned int, Player>::iterator it;
581
[62ee2ce]582 Player* p;
583 POSITION pos;
584
[88cdae2]585 for(it = mapPlayers.begin(); it != mapPlayers.end(); it++)
586 {
[62ee2ce]587 p = &it->second;
588 pos = mapToScreen(p->pos);
[88cdae2]589
590 if (p->id == curPlayerId)
[62ee2ce]591 al_draw_filled_circle(pos.x, pos.y, 12, al_map_rgb(255, 0, 0));
[88cdae2]592 else
[62ee2ce]593 al_draw_filled_circle(pos.x, pos.y, 12, al_map_rgb(191, 0, 0));
[88cdae2]594 }
595}
596
[87b3ee2]597void registerAccount()
598{
599 string username = txtUsername->getStr();
600 string password = txtPassword->getStr();
601
602 txtUsername->clear();
603 txtPassword->clear();
604
605 msgTo.type = MSG_TYPE_REGISTER;
606
607 strcpy(msgTo.buffer, username.c_str());
608 strcpy(msgTo.buffer+username.size()+1, password.c_str());
609
610 sendMessage(&msgTo, sock, &server);
611}
612
613void login()
614{
615 string strUsername = txtUsername->getStr();
616 string strPassword = txtPassword->getStr();
617 username = strUsername;
618
619 txtUsername->clear();
620 txtPassword->clear();
621
622 msgTo.type = MSG_TYPE_LOGIN;
623
624 strcpy(msgTo.buffer, strUsername.c_str());
625 strcpy(msgTo.buffer+username.size()+1, strPassword.c_str());
626
627 sendMessage(&msgTo, sock, &server);
628}
629
630void logout()
631{
632 txtChat->clear();
633
634 msgTo.type = MSG_TYPE_LOGOUT;
635
636 strcpy(msgTo.buffer, username.c_str());
637
638 sendMessage(&msgTo, sock, &server);
639}
640
641void quit()
642{
643 doexit = true;
644}
645
646void sendChatMessage()
647{
648 string msg = txtChat->getStr();
649
650 txtChat->clear();
651
652 msgTo.type = MSG_TYPE_CHAT;
653
654 strcpy(msgTo.buffer, msg.c_str());
655
656 sendMessage(&msgTo, sock, &server);
657}
Note: See TracBrowser for help on using the repository browser.