Moved struct definition to separate file, and added check for displaying GUI
I moved the GameType struct (and the Mode enum) to a separate file, as I will need to use it in the check_server and check_client functions as well. I also added the signum function (which was previously in sign.hpp) to this file, since it was the only function in sign.hpp. Finally, I added a check, that will only display the GUI, if the user didn't provide any command-line arguments.
This commit is contained in:
		
							
								
								
									
										182
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										182
									
								
								main.cpp
									
									
									
									
									
								
							| @@ -23,15 +23,14 @@ | ||||
| #define RAYGUI_IMPLEMENTATION | ||||
| #include "includes/raygui/raygui.h" | ||||
| #include "includes/raygui/style_dark.h" | ||||
|  | ||||
| #include "includes/paddle.hpp" | ||||
| #include "includes/ball.hpp" | ||||
| #include "includes/easysock.hpp" | ||||
| #include "includes/sign.hpp" | ||||
| #include "includes/connect_code.hpp" | ||||
| #include "includes/easysock.hpp" | ||||
| #include "includes/client.hpp" | ||||
| #include "includes/server.hpp" | ||||
| #include "includes/exception_consts.hpp" | ||||
| #include "includes/check_input.hpp" | ||||
| #include "includes/serialization.h" | ||||
| #include "includes/timer.h" | ||||
|  | ||||
| @@ -47,18 +46,12 @@ const float BASE_BOUNCE_RAD = (BASE_BOUNCE_DEG / 180.0) * M_PI; | ||||
| const float BASE_SPEED_COMPONENTS = 15; | ||||
| const float BASE_SPEED = sqrt(powf(BASE_SPEED_COMPONENTS, 2) * 2); | ||||
|  | ||||
| typedef enum {M_SINGLE, M_CLIENT, M_SERVER} Mode; | ||||
|  | ||||
| /* This struct contains a Mode enum, which indicates the type of game we are | ||||
|    playing (Single player, client mode or server mode). The netsock parameter is | ||||
|    a 'Sock' object - Client and Server classes inherit from this object, so this | ||||
|    parameter can be instantiated to either a client or server, depending on the | ||||
|    game type. */ | ||||
|  | ||||
| typedef struct { | ||||
| 	Mode mode; | ||||
| 	Sock* netsock; | ||||
| } GameType; | ||||
| /* Simple function to return 1 if a value is positive, and -1 if it is negative */ | ||||
| int signum(int num) { | ||||
| 	int retval = 0; | ||||
| 	(num > 0) ? retval = 1 : retval = -1; | ||||
| 	return retval; | ||||
| } | ||||
|  | ||||
| raylib::Vector2 changeVelocityAfterCollision(Paddle paddle, Ball ball) { | ||||
| 	float paddle_mid_y = (paddle.getRect().y + paddle.getRect().GetHeight()) / 2.0; /* Middle y value of rectangle */ | ||||
| @@ -223,93 +216,96 @@ int main(int argc, char** argv) { | ||||
| 	bool game_started = false; | ||||
| 	srand(std::time(NULL)); | ||||
|  | ||||
| 	/* If there were no command-line arguments, the user is prompted in the GUI */ | ||||
| 	if (argc == 1) { | ||||
| 		/* Display a drop-down menu, to allow user to pick between Single player, server and client. This section of the code uses the raygui library, and is written in C. */ | ||||
| 		 | ||||
| 		GuiLoadStyleDark(); // Load the dark theme style | ||||
| 		/* Modify the default style, by changing font size and spacing */ | ||||
| 		int font_size = 25; | ||||
| 		int font_spacing = 2; | ||||
| 		GuiSetStyle(DEFAULT, TEXT_SIZE, font_size); | ||||
| 		GuiSetStyle(DEFAULT, TEXT_SPACING, font_spacing); | ||||
|  | ||||
|  | ||||
| 	/* Display a drop-down menu, to allow user to pick between Single player, server and client. This section of the code uses the raygui library, and is written in C. */ | ||||
|  | ||||
| 	GuiLoadStyleDark(); // Load the dark theme style | ||||
| 	/* Modify the default style, by changing font size and spacing */ | ||||
| 	int font_size = 25; | ||||
| 	int font_spacing = 2; | ||||
| 	GuiSetStyle(DEFAULT, TEXT_SIZE, font_size); | ||||
| 	GuiSetStyle(DEFAULT, TEXT_SPACING, font_spacing); | ||||
|  | ||||
| 	/* Set variables to position objects on screen */ | ||||
| 	int selected_item = 0; 	// variable to hold the index of the selected item | ||||
| 	const char* text_to_display = "Select Game Mode"; // Text to display | ||||
| 	/* Size of the label, drop down box and button */ | ||||
| 	Vector2 label_size = MeasureTextEx(GetFontDefault(), text_to_display, font_size, font_spacing); // Set the size based on the width of the string to print, the font size and the text spacing. I added 1 to font_size and font_spacing, to account for any possible rounding errors, since the function expects floats. | ||||
| 	Vector2 box_size = Vector2{label_size.x, HEIGHT / 20}; | ||||
| 	bool is_being_edited = false; // Indicates whether the drop-down menu is being 'edited' i.e. whether an option is being selected | ||||
| 	bool button_pressed = false; // Indicates whether the submit button has been pressed | ||||
| 	 | ||||
| 	while (button_pressed == false) { | ||||
| 		BeginDrawing(); | ||||
| 			ClearBackground(BLACK); | ||||
| 			GuiLabel(Rectangle{(WIDTH/2)-(label_size.x/2), (HEIGHT/8), label_size.x, label_size.y}, text_to_display); // Label to display text on top | ||||
|  | ||||
| 			if (is_being_edited) { | ||||
| 				GuiLock(); // If the drop-down menu is being 'edited', we need to prevent the user from modifying any other aspect of the UI | ||||
| 			} | ||||
|  | ||||
| 			/* Button that allows user to proceed */ | ||||
| 			button_pressed = GuiButton(Rectangle{(WIDTH/2)-(box_size.x/2), (HEIGHT/2) + (HEIGHT/8), box_size.x, box_size.y}, "Continue"); | ||||
|  | ||||
| 			/* Drop-down menu, that allows user to select game mode */ | ||||
| 			if (GuiDropdownBox(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2) - (HEIGHT/8), box_size.x, box_size.y}, "SINGLE;CLIENT;SERVER", &selected_item, is_being_edited)) { // This function returns != 0 if there was a mouse click inside the dropdown area | ||||
| 				is_being_edited = !is_being_edited; // If the dropdown menu was selected, then it is being edited (or not being edited, if it previously was). | ||||
| 			} | ||||
| 			 | ||||
| 			GuiUnlock(); | ||||
| 		EndDrawing(); | ||||
| 	} | ||||
| 	 | ||||
| 	/* Single player mode */ | ||||
| 	if (selected_item == M_SINGLE) {	 | ||||
| 		GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // Enable text wrapping so that the long text, displayed below, will be wrapped | ||||
| 		BeginDrawing(); | ||||
| 			ClearBackground(BLACK); | ||||
| 			GuiLabel(Rectangle{(WIDTH/2)-(WIDTH/8), (HEIGHT/2)-(HEIGHT/8), WIDTH/4, HEIGHT/4}, "W and S control left paddle, Up and Down arrow keys control right paddle. Good luck!"); | ||||
| 		EndDrawing(); | ||||
| 		Timer timer = timer_init(5); | ||||
| 		while (!timer_done(timer)); | ||||
| 	} | ||||
| 	 | ||||
| 	/* Server mode, ask user to input IP address and port */ | ||||
| 	if (selected_item == M_SERVER) { | ||||
| 		button_pressed = false; // Whether submit button is pressed | ||||
| 		char* ip_text = (char *)calloc(100, sizeof(char)); // Holds input of IP text box | ||||
| 		char* port_text = (char *)calloc(20, sizeof(char)); // Holds input of port text box | ||||
| 		const char* ip_label = "Local IP address"; | ||||
| 		const char* port_label = "Port number (1024 - 65535)"; | ||||
| 		int port_label_x_size = MeasureTextEx(GetFontDefault(), port_label, font_size, font_spacing).x; // Custom size for port label, because it's long | ||||
| 		bool editing_ip = false; // Indicates whether the IP address text box is being edited | ||||
| 		bool editing_port = false; // Indicates whether the port text box is being edited | ||||
| 		/* Set variables to position objects on screen */ | ||||
| 		int selected_item = 0; 	// variable to hold the index of the selected item | ||||
| 		const char* text_to_display = "Select Game Mode"; // Text to display | ||||
| 		/* Size of the label, drop down box and button */ | ||||
| 		Vector2 label_size = MeasureTextEx(GetFontDefault(), text_to_display, font_size, font_spacing); // Set the size based on the width of the string to print, the font size and the text spacing. I added 1 to font_size and font_spacing, to account for any possible rounding errors, since the function expects floats. | ||||
| 		Vector2 box_size = Vector2{label_size.x, HEIGHT / 20}; | ||||
| 		bool is_being_edited = false; // Indicates whether the drop-down menu is being 'edited' i.e. whether an option is being selected | ||||
| 		bool button_pressed = false; // Indicates whether the submit button has been pressed | ||||
| 		 | ||||
| 		while (button_pressed == false) { | ||||
| 			BeginDrawing(); | ||||
| 				ClearBackground(BLACK); | ||||
| 				/* Label and text box for IP address */ | ||||
| 				GuiLabel(Rectangle{(WIDTH/2)-(label_size.x/2), (HEIGHT/2) - (HEIGHT/6) - label_size.y - 10, label_size.x, label_size.y}, ip_label); // Label to display text on top | ||||
| 				/* The reason this if statement exists, is largely the same as the reasoning for the drop-down menu. We want to make the text box editable  | ||||
| 				if it has been clicked. If it is already editable, we want to make it read-only if the user clicks outside the box. This functionality | ||||
| 				is mostly handled in the GuiTextBox function. If the text box is in edit mode, this function returns nonzero if the user clicks INSIDE | ||||
| 				the box. If the text box is in editable mode, this function returns nonzero if the user clicks OUTSIDE the box. */ | ||||
| 				if (GuiTextBox(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2) - (HEIGHT/6), box_size.x, box_size.y}, ip_text, 100, editing_ip)) { | ||||
| 					editing_ip = !editing_ip; | ||||
| 				GuiLabel(Rectangle{(WIDTH/2)-(label_size.x/2), (HEIGHT/8), label_size.x, label_size.y}, text_to_display); // Label to display text on top | ||||
|  | ||||
| 				if (is_being_edited) { | ||||
| 					GuiLock(); // If the drop-down menu is being 'edited', we need to prevent the user from modifying any other aspect of the UI | ||||
| 				} | ||||
|  | ||||
| 				/* Button that allows user to proceed */ | ||||
| 				button_pressed = GuiButton(Rectangle{(WIDTH/2)-(box_size.x/2), (HEIGHT/2) + (HEIGHT/8), box_size.x, box_size.y}, "Continue"); | ||||
|  | ||||
| 				/* Drop-down menu, that allows user to select game mode */ | ||||
| 				if (GuiDropdownBox(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2) - (HEIGHT/8), box_size.x, box_size.y}, "SINGLE;CLIENT;SERVER", &selected_item, is_being_edited)) { // This function returns != 0 if there was a mouse click inside the dropdown area | ||||
| 					is_being_edited = !is_being_edited; // If the dropdown menu was selected, then it is being edited (or not being edited, if it previously was). | ||||
| 				} | ||||
| 				 | ||||
| 				/* Label and text box for port. See above for explanation of if statement. */ | ||||
| 				GuiLabel(Rectangle{(WIDTH/2)-(label_size.x/2), (HEIGHT/2) - label_size.y, port_label_x_size }, port_label); // Label to display text on top | ||||
| 				if (GuiTextBox(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2), box_size.x, box_size.y}, port_text, 100, editing_port)) { | ||||
| 					editing_port = !editing_port; | ||||
| 				} | ||||
| 			 | ||||
| 				button_pressed = GuiButton(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2) + (HEIGHT/6), box_size.x, box_size.y}, "Start Server"); | ||||
| 				 | ||||
| 				GuiUnlock(); | ||||
| 			EndDrawing(); | ||||
| 		} | ||||
| 		 | ||||
| 		GameType type = check_server(ip_text, port_text); | ||||
| 		/* Single player mode */ | ||||
| 		if (selected_item == M_SINGLE) {	 | ||||
| 			GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // Enable text wrapping so that the long text, displayed below, will be wrapped | ||||
| 			BeginDrawing(); | ||||
| 				ClearBackground(BLACK); | ||||
| 				GuiLabel(Rectangle{(WIDTH/2)-(WIDTH/8), (HEIGHT/2)-(HEIGHT/8), WIDTH/4, HEIGHT/4}, "W and S control left paddle, Up and Down arrow keys control right paddle. Good luck!"); | ||||
| 			EndDrawing(); | ||||
| 			Timer timer = timer_init(5); | ||||
| 			while (!timer_done(timer)); | ||||
| 		} | ||||
| 		 | ||||
| 		/* Server mode, ask user to input IP address and port */ | ||||
| 		if (selected_item == M_SERVER) { | ||||
| 			button_pressed = false; // Whether submit button is pressed | ||||
| 			char* ip_text = (char *)calloc(100, sizeof(char)); // Holds input of IP text box | ||||
| 			char* port_text = (char *)calloc(20, sizeof(char)); // Holds input of port text box | ||||
| 			const char* ip_label = "Local IP address"; | ||||
| 			const char* port_label = "Port number (1024 - 65535)"; | ||||
| 			int port_label_x_size = MeasureTextEx(GetFontDefault(), port_label, font_size, font_spacing).x; // Custom size for port label, because it's long | ||||
| 			bool editing_ip = false; // Indicates whether the IP address text box is being edited | ||||
| 			bool editing_port = false; // Indicates whether the port text box is being edited | ||||
| 			while (button_pressed == false) { | ||||
| 				BeginDrawing(); | ||||
| 					ClearBackground(BLACK); | ||||
| 					/* Label and text box for IP address */ | ||||
| 					GuiLabel(Rectangle{(WIDTH/2)-(label_size.x/2), (HEIGHT/2) - (HEIGHT/6) - label_size.y - 10, label_size.x, label_size.y}, ip_label); // Label to display text on top | ||||
| 					/* The reason this if statement exists, is largely the same as the reasoning for the drop-down menu. We want to make the text box editable  | ||||
| 					if it has been clicked. If it is already editable, we want to make it read-only if the user clicks outside the box. This functionality | ||||
| 					is mostly handled in the GuiTextBox function. If the text box is in edit mode, this function returns nonzero if the user clicks INSIDE | ||||
| 					the box. If the text box is in editable mode, this function returns nonzero if the user clicks OUTSIDE the box. */ | ||||
| 					if (GuiTextBox(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2) - (HEIGHT/6), box_size.x, box_size.y}, ip_text, 100, editing_ip)) { | ||||
| 						editing_ip = !editing_ip; | ||||
| 					} | ||||
| 					 | ||||
| 					/* Label and text box for port. See above for explanation of if statement. */ | ||||
| 					GuiLabel(Rectangle{(WIDTH/2)-(label_size.x/2), (HEIGHT/2) - label_size.y, port_label_x_size }, port_label); // Label to display text on top | ||||
| 					if (GuiTextBox(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2), box_size.x, box_size.y}, port_text, 100, editing_port)) { | ||||
| 						editing_port = !editing_port; | ||||
| 					} | ||||
| 				 | ||||
| 					button_pressed = GuiButton(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2) + (HEIGHT/6), box_size.x, box_size.y}, "Start Server"); | ||||
| 					 | ||||
| 				EndDrawing(); | ||||
| 			} | ||||
| 			 | ||||
| 			type = check_server(ip_text, port_text); | ||||
| 			free(ip_text); | ||||
| 			free(port_text); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Variable to store the response given by the other player */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user