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

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

Added Player to the visual studio project, changed Common to use the #defines in Compiler.h, and added basic client support for processing MSG_TYPE_PLAYER messages

  • Property mode set to 100644
File size: 11.8 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 <stdio.h>
17#include <stdlib.h>
18#include <string>
19#include <iostream>
20
21#include <allegro5/allegro.h>
22#include <allegro5/allegro_font.h>
23#include <allegro5/allegro_ttf.h>
24
25#include "../../common/Message.h"
26#include "../../common/Common.h"
27#include "../../common/Player.h"
28
29#include "Window.h"
30#include "Textbox.h"
31#include "Button.h"
32#include "chat.h"
33
34#ifdef WINDOWS
35 #pragma comment(lib, "ws2_32.lib")
36#endif
37
38using namespace std;
39
40void initWinSock();
41void shutdownWinSock();
42void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole);
43
44// callbacks
45void registerAccount();
46void login();
47void logout();
48void quit();
49void sendChatMessage();
50
51void error(const char *);
52
53const float FPS = 60;
54const int SCREEN_W = 640;
55const int SCREEN_H = 480;
56const int BOUNCER_SIZE = 32;
57enum MYKEYS {
58 KEY_UP,
59 KEY_DOWN,
60 KEY_LEFT,
61 KEY_RIGHT
62};
63
64enum STATE {
65 STATE_START,
66 STATE_LOGIN // this means you're already logged in
67};
68
69int state;
70
71bool doexit;
72
73Window* wndLogin;
74Window* wndMain;
75Window* wndCurrent;
76
77Textbox* txtUsername;
78Textbox* txtPassword;
79Textbox* txtChat;
80
81int sock;
82struct sockaddr_in server, from;
83struct hostent *hp;
84NETWORK_MSG msgTo, msgFrom;
85string username;
86chat chatConsole;
87
88int main(int argc, char **argv)
89{
90 ALLEGRO_DISPLAY *display = NULL;
91 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
92 ALLEGRO_TIMER *timer = NULL;
93 ALLEGRO_BITMAP *bouncer = NULL;
94 bool key[4] = { false, false, false, false };
95 bool redraw = true;
96 doexit = false;
97
98 float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
99 float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
100
101 state = STATE_START;
102
103 if(!al_init()) {
104 fprintf(stderr, "failed to initialize allegro!\n");
105 return -1;
106 }
107
108 al_init_primitives_addon();
109 al_init_font_addon();
110 al_init_ttf_addon();
111
112 ALLEGRO_FONT *font = al_load_ttf_font("../pirulen.ttf", 12, 0);
113
114 if (!font) {
115 fprintf(stderr, "Could not load 'pirulen.ttf'.\n");
116 getchar();
117 return -1;
118 }
119
120 if(!al_install_keyboard()) {
121 fprintf(stderr, "failed to initialize the keyboard!\n");
122 return -1;
123 }
124
125 if(!al_install_mouse()) {
126 fprintf(stderr, "failed to initialize the mouse!\n");
127 return -1;
128 }
129
130 timer = al_create_timer(1.0 / FPS);
131 if(!timer) {
132 fprintf(stderr, "failed to create timer!\n");
133 return -1;
134 }
135
136 display = al_create_display(SCREEN_W, SCREEN_H);
137 if(!display) {
138 fprintf(stderr, "failed to create display!\n");
139 al_destroy_timer(timer);
140 return -1;
141 }
142
143 wndLogin = new Window(0, 0, SCREEN_W, SCREEN_H);
144 wndLogin->addComponent(new Textbox(104, 40, 100, 20, font));
145 wndLogin->addComponent(new Textbox(104, 70, 100, 20, font));
146 wndLogin->addComponent(new Button(22, 100, 90, 20, font, "Register", registerAccount));
147 wndLogin->addComponent(new Button(122, 100, 60, 20, font, "Login", login));
148 wndLogin->addComponent(new Button(540, 10, 80, 20, font, "Quit", quit));
149
150 txtUsername = (Textbox*)wndLogin->getComponent(0);
151 txtPassword = (Textbox*)wndLogin->getComponent(1);
152
153 wndMain = new Window(0, 0, SCREEN_W, SCREEN_H);
154 wndMain->addComponent(new Textbox(95, 40, 525, 20, font));
155 wndMain->addComponent(new Button(95, 70, 160, 20, font, "Send Message", sendChatMessage));
156 wndMain->addComponent(new Button(540, 10, 80, 20, font, "Logout", logout));
157
158 txtChat = (Textbox*)wndMain->getComponent(0);
159
160 wndCurrent = wndLogin;
161
162 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
163 if(!bouncer) {
164 fprintf(stderr, "failed to create bouncer bitmap!\n");
165 al_destroy_display(display);
166 al_destroy_timer(timer);
167 return -1;
168 }
169
170 event_queue = al_create_event_queue();
171 if(!event_queue) {
172 fprintf(stderr, "failed to create event_queue!\n");
173 al_destroy_bitmap(bouncer);
174 al_destroy_display(display);
175 al_destroy_timer(timer);
176 return -1;
177 }
178
179 al_set_target_bitmap(bouncer);
180
181 al_clear_to_color(al_map_rgb(255, 0, 255));
182
183 al_set_target_bitmap(al_get_backbuffer(display));
184
185 al_register_event_source(event_queue, al_get_display_event_source(display));
186 al_register_event_source(event_queue, al_get_timer_event_source(timer));
187 al_register_event_source(event_queue, al_get_keyboard_event_source());
188 al_register_event_source(event_queue, al_get_mouse_event_source());
189
190 al_clear_to_color(al_map_rgb(0,0,0));
191
192 al_flip_display();
193
194 if (argc != 3) {
195 cout << "Usage: server port" << endl;
196 exit(1);
197 }
198
199 initWinSock();
200
201 sock = socket(AF_INET, SOCK_DGRAM, 0);
202 if (sock < 0)
203 error("socket");
204
205 set_nonblock(sock);
206
207 server.sin_family = AF_INET;
208 hp = gethostbyname(argv[1]);
209 if (hp==0)
210 error("Unknown host");
211
212 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
213 server.sin_port = htons(atoi(argv[2]));
214
215 al_start_timer(timer);
216
217 while(!doexit)
218 {
219 ALLEGRO_EVENT ev;
220 al_wait_for_event(event_queue, &ev);
221
222 if(wndCurrent->handleEvent(ev)) {
223 // do nothing
224 }
225 else if(ev.type == ALLEGRO_EVENT_TIMER) {
226 if(key[KEY_UP] && bouncer_y >= 4.0) {
227 bouncer_y -= 4.0;
228 }
229
230 if(key[KEY_DOWN] && bouncer_y <= SCREEN_H - BOUNCER_SIZE - 4.0) {
231 bouncer_y += 4.0;
232 }
233
234 if(key[KEY_LEFT] && bouncer_x >= 4.0) {
235 bouncer_x -= 4.0;
236 }
237
238 if(key[KEY_RIGHT] && bouncer_x <= SCREEN_W - BOUNCER_SIZE - 4.0) {
239 bouncer_x += 4.0;
240 }
241
242 redraw = true;
243 }
244 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
245 doexit = true;
246 }
247 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
248 switch(ev.keyboard.keycode) {
249 case ALLEGRO_KEY_UP:
250 key[KEY_UP] = true;
251 break;
252
253 case ALLEGRO_KEY_DOWN:
254 key[KEY_DOWN] = true;
255 break;
256
257 case ALLEGRO_KEY_LEFT:
258 key[KEY_LEFT] = true;
259 break;
260
261 case ALLEGRO_KEY_RIGHT:
262 key[KEY_RIGHT] = true;
263 break;
264 }
265 }
266 else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
267 switch(ev.keyboard.keycode) {
268 case ALLEGRO_KEY_UP:
269 key[KEY_UP] = false;
270 break;
271
272 case ALLEGRO_KEY_DOWN:
273 key[KEY_DOWN] = false;
274 break;
275
276 case ALLEGRO_KEY_LEFT:
277 key[KEY_LEFT] = false;
278 break;
279
280 case ALLEGRO_KEY_RIGHT:
281 key[KEY_RIGHT] = false;
282 break;
283
284 case ALLEGRO_KEY_ESCAPE:
285 doexit = true;
286 break;
287 }
288 }
289
290 if (receiveMessage(&msgFrom, sock, &from) >= 0)
291 {
292 processMessage(msgFrom, state, chatConsole);
293 cout << "state: " << state << endl;
294 }
295
296 if (redraw && al_is_event_queue_empty(event_queue))
297 {
298 redraw = false;
299
300 wndCurrent->draw(display);
301
302 al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
303
304 chatConsole.draw(font, al_map_rgb(255,255,255));
305
306 if(wndCurrent == wndLogin) {
307 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Username:");
308 al_draw_text(font, al_map_rgb(0, 255, 0), 1, 73, ALLEGRO_ALIGN_LEFT, "Password:");
309 }
310 else if(wndCurrent == wndMain) {
311 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Message:");
312 }
313
314 al_flip_display();
315 }
316 }
317
318 #if defined WINDOWS
319 closesocket(sock);
320 #elif defined LINUX
321 close(sock);
322 #endif
323
324 shutdownWinSock();
325
326 delete wndLogin;
327 delete wndMain;
328
329 al_destroy_event_queue(event_queue);
330 al_destroy_bitmap(bouncer);
331 al_destroy_display(display);
332 al_destroy_timer(timer);
333
334 return 0;
335}
336
337// need to make a function like this that works on windows
338void error(const char *msg)
339{
340 perror(msg);
341 shutdownWinSock();
342 exit(1);
343}
344
345void initWinSock()
346{
347#if defined WINDOWS
348 WORD wVersionRequested;
349 WSADATA wsaData;
350 int wsaerr;
351
352 wVersionRequested = MAKEWORD(2, 2);
353 wsaerr = WSAStartup(wVersionRequested, &wsaData);
354
355 if (wsaerr != 0) {
356 cout << "The Winsock dll not found." << endl;
357 exit(1);
358 }else
359 cout << "The Winsock dll was found." << endl;
360#endif
361}
362
363void shutdownWinSock()
364{
365#if defined WINDOWS
366 WSACleanup();
367#endif
368}
369
370void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole)
371{
372 string response = string(msg.buffer);
373
374 switch(state)
375 {
376 case STATE_START:
377 {
378 cout << "In STATE_START" << endl;
379
380 chatConsole.addLine(response);
381
382 switch(msg.type)
383 {
384 case MSG_TYPE_REGISTER:
385 {
386 break;
387 }
388 case MSG_TYPE_LOGIN:
389 {
390 if (response.compare("Player has already logged in.") == 0)
391 {
392 username.clear();
393 cout << "User login failed" << endl;
394 }
395 else if (response.compare("Incorrect username or password") == 0)
396 {
397 username.clear();
398 cout << "User login failed" << endl;
399 }
400 else
401 {
402 state = STATE_LOGIN;
403 wndCurrent = wndMain;
404 cout << "User login successful" << endl;
405 }
406 break;
407 }
408 }
409
410 break;
411 }
412 case STATE_LOGIN:
413 {
414 chatConsole.addLine(response);
415
416 switch(msg.type)
417 {
418 case MSG_TYPE_REGISTER:
419 {
420 break;
421 }
422 case MSG_TYPE_LOGIN:
423 {
424 if (response.compare("You have successfully logged out.") == 0)
425 {
426 cout << "Logged out" << endl;
427 state = STATE_START;
428 wndCurrent = wndLogin;
429 }
430 else
431 {
432 cout << "Added new line" << endl;
433 }
434
435 break;
436 }
437 case MSG_TYPE_PLAYER:
438 {
439 Player p = *(Player*)(&(msg.buffer));
440
441 cout << "p.name: " << p.name;
442 cout << "p.pos.x: " << p.pos.x;
443 cout << "p.pos.y: " << p.pos.y;
444
445 break;
446 }
447 }
448
449 break;
450 }
451 default:
452 {
453 cout << "The state has an invalid value: " << state << endl;
454
455 break;
456 }
457 }
458}
459
460void registerAccount()
461{
462 string username = txtUsername->getStr();
463 string password = txtPassword->getStr();
464
465 txtUsername->clear();
466 txtPassword->clear();
467
468 msgTo.type = MSG_TYPE_REGISTER;
469
470 strcpy(msgTo.buffer, username.c_str());
471 strcpy(msgTo.buffer+username.size()+1, password.c_str());
472
473 sendMessage(&msgTo, sock, &server);
474}
475
476void login()
477{
478 string strUsername = txtUsername->getStr();
479 string strPassword = txtPassword->getStr();
480 username = strUsername;
481
482 txtUsername->clear();
483 txtPassword->clear();
484
485 msgTo.type = MSG_TYPE_LOGIN;
486
487 strcpy(msgTo.buffer, strUsername.c_str());
488 strcpy(msgTo.buffer+username.size()+1, strPassword.c_str());
489
490 sendMessage(&msgTo, sock, &server);
491}
492
493void logout()
494{
495 txtChat->clear();
496
497 msgTo.type = MSG_TYPE_LOGOUT;
498
499 strcpy(msgTo.buffer, username.c_str());
500
501 sendMessage(&msgTo, sock, &server);
502}
503
504void quit()
505{
506 doexit = true;
507}
508
509void sendChatMessage()
510{
511 string msg = txtChat->getStr();
512
513 txtChat->clear();
514
515 msgTo.type = MSG_TYPE_CHAT;
516
517 strcpy(msgTo.buffer, msg.c_str());
518
519 sendMessage(&msgTo, sock, &server);
520}
Note: See TracBrowser for help on using the repository browser.