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

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

Created a simple gui for the client

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