Compare commits
42 Commits
v0.1
...
418579a627
Author | SHA1 | Date | |
---|---|---|---|
418579a627 | |||
6acbf90d80 | |||
2c7d1d0b43 | |||
00b83e6de2 | |||
9881567009 | |||
f23f307e17 | |||
dd658c9c1d | |||
52f8034f4e | |||
8758060bfb | |||
10f91fafd4 | |||
e9405b69e7 | |||
9a12edcdb1 | |||
83a0d5beb4 | |||
eeae444b1d | |||
f9d5e8cdeb | |||
9972e146d5 | |||
8848f0ff8c | |||
07ac3f9166 | |||
9e0990156e | |||
1423cc19a0 | |||
352d3f26f1 | |||
788b334e7c | |||
9de9353936 | |||
a3392308c4 | |||
0e9088beb6 | |||
7812611fe6 | |||
bc0d644399 | |||
d05ba0daa1 | |||
c8f29d1336 | |||
0d1dc049b5 | |||
f4bbb6ef6a | |||
1f470e23ee | |||
97e6da3b2b | |||
0286878c70 | |||
e9da48d9a0 | |||
832dae977a | |||
613b81c542 | |||
28c4b421d2 | |||
13ce75067b | |||
635d71f1c5 | |||
8c4a515046 | |||
f25e7fae38 |
21
README.md
21
README.md
@@ -4,16 +4,21 @@ __Netpong__ is a network-enabled Pong game, written in C++. It enables two playe
|
||||
|
||||
## How it works
|
||||
|
||||
The game has only one runtime dependency: The [raylib](https://www.raylib.com/) graphics system. In order to write idiomatic C++, I chose to use the [raylib-cpp](https://robloach.github.io/raylib-cpp/) wrapper, which provides an object-oriented interface to the Raylib library. However, this wrapper is bundled with the project, and is thus not required to be installed.
|
||||
The game has only one runtime dependency: The [raylib](https://www.raylib.com/) graphics library. In order to write idiomatic C++, I chose to use the [raylib-cpp](https://robloach.github.io/raylib-cpp/) wrapper, which provides an object-oriented interface to the Raylib library.
|
||||
|
||||
## Building
|
||||
|
||||
This application uses [Meson](https://mesonbuild.com/) as a build system. To build the application:
|
||||
1. Install __meson__ from the link above.
|
||||
2. Install __raylib__ from the link above (THIS IS OPTIONAL, SEE STEP 5)
|
||||
3. Set up the build directory with the `meson setup build` command.
|
||||
4. Compile the application, with the existing raylib installation, using `meson compile -C build`.
|
||||
5. If you don't have raylib installed, you can create a statically linked version of the library on Linux by running the following commands:
|
||||
1. Install meson from the link above.
|
||||
2. Set up the build directory.
|
||||
```
|
||||
meson setup build
|
||||
```
|
||||
3. Compile the application. Meson should use a system installation of raylib, if it exists. If not, it falls back to a bundled version.
|
||||
```
|
||||
meson compile -C build
|
||||
```
|
||||
4. You can also create a statically-linked version of the game (with no runtime dependencies) on Linux by running the following commands:
|
||||
|
||||
```
|
||||
meson configure -Ddefault_library=static build/
|
||||
@@ -30,3 +35,7 @@ This application uses [Meson](https://mesonbuild.com/) as a build system. To bui
|
||||
- One player runs the application in Server mode, specifying their IP address and a port: `build/pong -S <ip_address> <port>`
|
||||
- The other player connects to the first player by running in Client mode, specifying the first player's IP address and port: `build/pong -C <ip_address> <port>`.
|
||||
- The server controls the left paddle by default (WIP to allow the user to modify this), and the client controls the right paddle.
|
||||
|
||||
## TODO
|
||||
|
||||
See todo.txt.
|
||||
|
83
check_input.cpp
Normal file
83
check_input.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <iostream>
|
||||
#include "includes/easysock.h"
|
||||
#include "includes/connect_code.hpp"
|
||||
#include "includes/server.hpp"
|
||||
#include "includes/client.hpp"
|
||||
#include "includes/check_input.hpp"
|
||||
#include "includes/raygui/raygui.h"
|
||||
#include "includes/exception_consts.hpp"
|
||||
#include "includes/raygui_helpers.hpp"
|
||||
#include "includes/timer.h"
|
||||
|
||||
GameType check_server(char* ip_text, char* port_text) {
|
||||
GameType type;
|
||||
std::string addr;
|
||||
uint16_t port;
|
||||
|
||||
/* Check if IP address and port are in valid forms */
|
||||
if (check_ip_ver(ip_text) < 0) {
|
||||
throw std::invalid_argument("Invalid IP address");
|
||||
}
|
||||
if (port_to_num(port_text) < 0) {
|
||||
throw std::invalid_argument("Invalid port");
|
||||
}
|
||||
|
||||
/* From here on, we assume that the IP and port are valid */
|
||||
|
||||
addr = std::string(ip_text);
|
||||
port = std::stoi(std::string(port_text));
|
||||
|
||||
std::string code = connect_code::encode(addr, std::to_string(port));
|
||||
|
||||
/* Create server socket and wait for client to connect */
|
||||
Server* server = new Server(check_ip_ver(addr.data()), ES_UDP, addr.data(), port);
|
||||
server->create_socket();
|
||||
display_text_centered("Your code is " + code + "\nWaiting for connection...");
|
||||
std::string response = "";
|
||||
char* temp_response = NULL;
|
||||
/* Wait for the client to connect. Since recvAll returns a char*, we need to create a temporary variable to check for NULL.
|
||||
TODO - Check that the client actually sends 'GG'. */
|
||||
do {
|
||||
temp_response = server->recvAll();
|
||||
} while (temp_response == NULL);
|
||||
response = std::string(temp_response);
|
||||
|
||||
server->sendAll("U2");
|
||||
display_text_centered("Connection received from " + server->get_peer_addr());
|
||||
Timer timer = timer_init(3);
|
||||
while (!timer_done(timer)); // Wait for five seconds
|
||||
|
||||
type.mode = M_SERVER;
|
||||
type.netsock = server;
|
||||
return type;
|
||||
}
|
||||
|
||||
GameType check_client(char* code_text) {
|
||||
GameType type;
|
||||
std::vector<std::string> addr_port;
|
||||
std::string connect_code = std::string(code_text); /* The connect code is a special string, that contains the server address and port. It is given by the server. */
|
||||
try {
|
||||
addr_port = connect_code::decode(connect_code);
|
||||
Client* client = new Client(4, ES_UDP, addr_port[0].data(), std::stoi(addr_port[1]));
|
||||
client->create_socket();
|
||||
/* Send a specific message to the server, and wait for the appropriate response, to know that the server is ready */
|
||||
client->sendAll("GG");
|
||||
// display_text_centered("Connecting...");
|
||||
std::string msg_from_server = client->recvAll();
|
||||
if (msg_from_server == "U2") {
|
||||
display_text_centered("Connection made");
|
||||
Timer timer = timer_init(3);
|
||||
while (!timer_done(timer));
|
||||
} else {
|
||||
throw EXCEPT_WRONGRESPONSE;
|
||||
}
|
||||
type.mode = M_CLIENT;
|
||||
type.netsock = client;
|
||||
return type;
|
||||
} catch (int e) {
|
||||
throw;
|
||||
} catch (std::exception& e) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#include "includes/client.hpp"
|
||||
#include "includes/exception_consts.hpp"
|
||||
#include "includes/sock.hpp"
|
||||
#include "includes/easysock.hpp"
|
||||
#include "includes/easysock.h"
|
||||
|
||||
/* Destructor - closes any open sockets */
|
||||
Client::~Client() {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
@@ -5,6 +6,15 @@
|
||||
#include <cstdint>
|
||||
#include "includes/connect_code.hpp"
|
||||
#include "includes/numeric_base.hpp"
|
||||
#include "includes/easysock.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <In6addr.h>
|
||||
#include <Ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
namespace connect_code {
|
||||
|
||||
@@ -44,13 +54,70 @@ namespace connect_code {
|
||||
uint32_t addr_val = (std::stoul(octets[0]) << 24) + (std::stoul(octets[1]) << 16) + (std::stoul(octets[2]) << 8) + (std::stoul(octets[3]));
|
||||
return std::to_string(addr_val);
|
||||
}
|
||||
|
||||
/* Expand an IPv6 address (expand '::' into ':0000:', for example).
|
||||
This is done by first converting the address into a binary representation,
|
||||
and then printing every character of the binary representation into a string. */
|
||||
std::string expand_ip6_addr(std::string addr) {
|
||||
char ip6_string[40]; // 32 characters + 7 colons
|
||||
struct in6_addr* ip6_s_ptr = (struct in6_addr *)malloc(sizeof(in6_addr)); // Struct pointer, to store the binary representation of the address
|
||||
inet_pton(AF_INET6, addr.data(), ip6_s_ptr); // Convert the string representation into a binary form
|
||||
|
||||
/* This abomination, converts the binary representation into a string.
|
||||
It uses sprintf to print every byte in the binary representation into a string.
|
||||
The bytes are formatted as 2-character hexadecimal values. */
|
||||
sprintf(ip6_string,
|
||||
"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
ip6_s_ptr->s6_addr[0], ip6_s_ptr->s6_addr[1],
|
||||
ip6_s_ptr->s6_addr[2], ip6_s_ptr->s6_addr[3],
|
||||
ip6_s_ptr->s6_addr[4], ip6_s_ptr->s6_addr[5],
|
||||
ip6_s_ptr->s6_addr[6], ip6_s_ptr->s6_addr[7],
|
||||
ip6_s_ptr->s6_addr[8], ip6_s_ptr->s6_addr[9],
|
||||
ip6_s_ptr->s6_addr[10], ip6_s_ptr->s6_addr[11],
|
||||
ip6_s_ptr->s6_addr[12], ip6_s_ptr->s6_addr[13],
|
||||
ip6_s_ptr->s6_addr[14], ip6_s_ptr->s6_addr[15]);
|
||||
|
||||
return std::string(ip6_string);
|
||||
}
|
||||
|
||||
|
||||
std::string encode(std::string address, std::string port) {
|
||||
std::string addr_coded;
|
||||
/* Convert the address to decimal, and convert that to hex */
|
||||
std::string addr_coded = dotted_dec_to_dec(address);
|
||||
addr_coded = base_convert(addr_coded, 10, 32);
|
||||
|
||||
if (check_ip_ver(address.data()) == 4) {
|
||||
/* I don't really have a reason to use my own function (dotted_dec_to_dec()
|
||||
and dec_to_dotted_dec()), to convert the IP address from text to binary.
|
||||
The inet_pton() and inet_ntop() functions can do this just fine, and also
|
||||
take care of edge cases. Maybe someday, I might change this code. I could probably
|
||||
repurpose the functions for something else, though. */
|
||||
|
||||
/* First, convert the address into a 32-bit integer (the integer is stored as a string).
|
||||
Then, convert the address into base-32. */
|
||||
addr_coded = dotted_dec_to_dec(address);
|
||||
addr_coded = base_convert(addr_coded, 10, 32);
|
||||
}
|
||||
if (check_ip_ver(address.data()) == 6) {
|
||||
/* First, expand the address into the full 39-character format (32 hex values + 7 colons).
|
||||
Then, tokenize the string, using colons as the delimiters.
|
||||
Finally, take each token in the string, and convert it from base-16 to base-32, appending a '-' as a delimiter. */
|
||||
std::string addr_expanded = expand_ip6_addr(address);
|
||||
std::string addr_coded = "";
|
||||
std::vector<std::string> addr_tokenized = tokenize_str(addr_expanded, ":");
|
||||
|
||||
for (int i = 0; i < addr_tokenized.size()-1; i++ ) {
|
||||
addr_coded += base_convert(addr_tokenized[i], 16, 32);
|
||||
addr_coded += "-";
|
||||
}
|
||||
addr_coded += base_convert(addr_tokenized[addr_tokenized.size()-1], 16, 32); // I put this outside the loop, because I don't want a hyphen after it
|
||||
|
||||
/* TODO - Check if the IP address is actually converted properly, and test if the server socket is created correctly.
|
||||
Also do the same for client side, and check client-server connection. */
|
||||
|
||||
std::cout << addr_coded << std::endl;
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
/* Convert the port to hex */
|
||||
std::string port_coded = base_convert(port, 10, 32);
|
||||
std::string ret_val = addr_coded + "_" + port_coded;
|
||||
@@ -60,6 +127,15 @@ namespace connect_code {
|
||||
}
|
||||
|
||||
std::vector<std::string> decode(std::string connect_code) {
|
||||
//<AIRPLANE_CODE>
|
||||
int ip_ver = 0;
|
||||
if (connect_code.find("-") == connect_code.npos) {
|
||||
ip_ver = 6; // If the string contains hyphens, it must be an IPv6 address encoding.
|
||||
} else {
|
||||
ip_ver = 4;
|
||||
}
|
||||
|
||||
//</AIRPLANE_CODE>
|
||||
if (connect_code.find("_") == std::string::npos) {
|
||||
throw std::invalid_argument("Invalid code entered.");
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
# This script copies required DLLs, and the application itself into a folder called 'release'. It only runs on MinGW.
|
||||
|
||||
set -o errexit # Stop executing when a command fails
|
||||
BASE_DIR=$(dirname $0)
|
||||
REL_DIR="$BASE_DIR/release/dist"
|
||||
|
||||
@@ -19,3 +20,6 @@ cp "$BASE_DIR/build/pong" "$REL_DIR"
|
||||
# Remove the temporary file.
|
||||
rm "$BASE_DIR/tmp_file.txt"
|
||||
|
||||
#Zip the $REL_DIR folder
|
||||
zip -r "$BASE_DIR/release/netpong-win.zip" "$REL_DIR"
|
||||
|
26
create_static_linux.sh
Executable file
26
create_static_linux.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script creates and packages a statically-linked build of the game, for Linux.
|
||||
# It must be placed in the root of the source code.
|
||||
|
||||
set -o errexit # Stop executing when a command fails
|
||||
BASE_DIR=$(dirname 0)
|
||||
REL_DIR="$BASE_DIR/release/static/pong"
|
||||
|
||||
mkdir -p "$REL_DIR"
|
||||
|
||||
# Set the default build target to static
|
||||
meson configure -Ddefault_library=static "$BASE_DIR/build/"
|
||||
|
||||
# Build the application
|
||||
meson compile -C "$BASE_DIR/build/"
|
||||
|
||||
# Package the application:
|
||||
# 1. Copy the executable to REL_DIR
|
||||
# 2. Create a tarball
|
||||
|
||||
cp "$BASE_DIR/build/pong" "$REL_DIR"
|
||||
tar -czf "$BASE_DIR/release/pong.tar.gz" "$REL_DIR"
|
||||
|
||||
# Reset default build target to shared
|
||||
meson configure -Ddefault_library=shared "$BASE_DIR/build/"
|
@@ -1,8 +1,9 @@
|
||||
#include "includes/easysock.hpp"
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
#include "includes/easysock.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -187,6 +188,29 @@ int check_ip_ver(const char* address) {
|
||||
}
|
||||
}
|
||||
|
||||
int port_to_num(const char* port_str) {
|
||||
/* The largest possible port value is 65535: a 5 character string */
|
||||
if (strlen(port_str) > 5) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < strlen(port_str); i++) {
|
||||
if (isdigit(port_str[i]) == 0) { // Ensure that every character in port_str is a digit (isidigit() returns 0 if the parameter is not a digit)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Convert the string to a base-10 integer */
|
||||
int port_num = (int)strtol(port_str, NULL, 10);
|
||||
if (port_num > 65535) {
|
||||
return -1;
|
||||
}
|
||||
if (port_num < 1024) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return port_num;
|
||||
}
|
||||
|
||||
int int_to_inet(int network) {
|
||||
if (network == 4) {
|
||||
return AF_INET;
|
28
includes/check_input.hpp
Normal file
28
includes/check_input.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _CHECK_INPUT_H
|
||||
#define _CHECK_INPUT_H
|
||||
|
||||
#include "includes/sock.hpp"
|
||||
|
||||
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;
|
||||
|
||||
/* This function checks the IP address and port passed to it, and returns a struct,
|
||||
that contains information about the game mode, and contains the server socket.
|
||||
It assumes that both ip_text and port_text are non-null
|
||||
TODO - Add better error checking. */
|
||||
GameType check_server(char* ip_text, char* port_text);
|
||||
|
||||
/* NOT IMPLEMENTED YET - This function checks the code given to it, and returns a struct
|
||||
that contains information about the game mode, and contains the client socket. */
|
||||
GameType check_client(char* code);
|
||||
|
||||
#endif
|
@@ -1,12 +1,15 @@
|
||||
#ifndef EASYSOCK_HPP_
|
||||
#define EASYSOCK_HPP_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef EASYSOCK_H_
|
||||
#define EASYSOCK_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <winsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#ifdef __unix__
|
||||
#if defined(__unix) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
@@ -70,6 +73,12 @@ IPv6 address (returns 6) or neither (returns -1). */
|
||||
|
||||
int check_ip_ver(const char* address);
|
||||
|
||||
/* port_to_num - Converts a string representing a port, into a numeric value.
|
||||
Returns -1 if the string is not numeric, or exceeds the maximum port length.
|
||||
Returns -2 if the string is lower than 1024, This serves as a warning, as ports less
|
||||
than 1023 are reserved. */
|
||||
int port_to_num(const char* port_str);
|
||||
|
||||
/* int_to_inet - Takes an int value (4 for IPv4, 6 for IPv6) and returns AF_INET or
|
||||
AF_INET6 respectively. */
|
||||
|
||||
@@ -92,3 +101,6 @@ int sock_quit(void);
|
||||
int sock_close(SOCKET);
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
5535
includes/raygui/raygui.h
Normal file
5535
includes/raygui/raygui.h
Normal file
File diff suppressed because it is too large
Load Diff
589
includes/raygui/style_dark.h
Normal file
589
includes/raygui/style_dark.h
Normal file
@@ -0,0 +1,589 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// StyleAsCode exporter v2.0 - Style data exported as a values array //
|
||||
// //
|
||||
// USAGE: On init call: GuiLoadStyleDark(); //
|
||||
// //
|
||||
// more info and bugs-report: github.com/raysan5/raygui //
|
||||
// feedback and support: ray[at]raylibtech.com //
|
||||
// //
|
||||
// Copyright (c) 2020-2024 raylib technologies (@raylibtech) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DARK_STYLE_PROPS_COUNT 23
|
||||
|
||||
// Custom style name: Dark
|
||||
static const GuiStyleProp darkStyleProps[DARK_STYLE_PROPS_COUNT] = {
|
||||
{ 0, 0, 0x878787ff }, // DEFAULT_BORDER_COLOR_NORMAL
|
||||
{ 0, 1, 0x2c2c2cff }, // DEFAULT_BASE_COLOR_NORMAL
|
||||
{ 0, 2, 0xc3c3c3ff }, // DEFAULT_TEXT_COLOR_NORMAL
|
||||
{ 0, 3, 0xe1e1e1ff }, // DEFAULT_BORDER_COLOR_FOCUSED
|
||||
{ 0, 4, 0x848484ff }, // DEFAULT_BASE_COLOR_FOCUSED
|
||||
{ 0, 5, 0x181818ff }, // DEFAULT_TEXT_COLOR_FOCUSED
|
||||
{ 0, 6, 0x000000ff }, // DEFAULT_BORDER_COLOR_PRESSED
|
||||
{ 0, 7, 0xefefefff }, // DEFAULT_BASE_COLOR_PRESSED
|
||||
{ 0, 8, 0x202020ff }, // DEFAULT_TEXT_COLOR_PRESSED
|
||||
{ 0, 9, 0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED
|
||||
{ 0, 10, 0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED
|
||||
{ 0, 11, 0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED
|
||||
{ 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE
|
||||
{ 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING
|
||||
{ 0, 18, 0x9d9d9dff }, // DEFAULT_LINE_COLOR
|
||||
{ 0, 19, 0x3c3c3cff }, // DEFAULT_BACKGROUND_COLOR
|
||||
{ 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING
|
||||
{ 1, 5, 0xf7f7f7ff }, // LABEL_TEXT_COLOR_FOCUSED
|
||||
{ 1, 8, 0x898989ff }, // LABEL_TEXT_COLOR_PRESSED
|
||||
{ 4, 5, 0xb0b0b0ff }, // SLIDER_TEXT_COLOR_FOCUSED
|
||||
{ 5, 5, 0x848484ff }, // PROGRESSBAR_TEXT_COLOR_FOCUSED
|
||||
{ 9, 5, 0xf5f5f5ff }, // TEXTBOX_TEXT_COLOR_FOCUSED
|
||||
{ 10, 5, 0xf6f6f6ff }, // VALUEBOX_TEXT_COLOR_FOCUSED
|
||||
};
|
||||
|
||||
// WARNING: This style uses a custom font: "PixelOperator.ttf" (size: 16, spacing: 0)
|
||||
|
||||
#define DARK_STYLE_FONT_ATLAS_COMP_SIZE 2126
|
||||
|
||||
// Font atlas image pixels data: DEFLATE compressed
|
||||
static unsigned char darkFontData[DARK_STYLE_FONT_ATLAS_COMP_SIZE] = { 0xed,
|
||||
0xdd, 0xdb, 0x72, 0xa4, 0x3a, 0x12, 0x05, 0x50, 0xfd, 0xff, 0x4f, 0xe7, 0x3c, 0x4c, 0x4c, 0x4c, 0x74, 0x9c, 0xd3, 0x20,
|
||||
0xa5, 0x52, 0x17, 0xec, 0xd5, 0xeb, 0xcd, 0xe5, 0x76, 0x51, 0xa0, 0x94, 0x84, 0x28, 0x36, 0xd1, 0x00, 0x00, 0x00, 0x80,
|
||||
0x5f, 0x2f, 0xfe, 0xf5, 0x27, 0xf1, 0xd7, 0xdf, 0x8c, 0xee, 0xbf, 0xf3, 0xfc, 0xf3, 0xff, 0xbd, 0x1a, 0x0f, 0xef, 0xd5,
|
||||
0xb7, 0xad, 0xa3, 0xef, 0x1b, 0x03, 0x7b, 0xe2, 0xdf, 0xb7, 0x2f, 0xba, 0xff, 0xee, 0xdf, 0x3e, 0xdf, 0xf8, 0xef, 0x3f,
|
||||
0xfd, 0xa5, 0xe7, 0xad, 0x8f, 0xa1, 0xfd, 0x3e, 0xfe, 0x7f, 0xc6, 0x8e, 0x62, 0x2c, 0xd9, 0xf7, 0xef, 0x5b, 0x37, 0xbe,
|
||||
0xed, 0x95, 0xff, 0x27, 0x1e, 0x3e, 0x4f, 0xe6, 0x28, 0xf5, 0xd4, 0xd6, 0x0d, 0xf5, 0x1f, 0x5d, 0x95, 0x18, 0xa5, 0x2d,
|
||||
0xe7, 0xff, 0xef, 0x1a, 0x85, 0x3d, 0x55, 0x76, 0x4f, 0x3e, 0x55, 0xfa, 0xf8, 0xfe, 0x78, 0x6a, 0xfd, 0xe3, 0x3d, 0x60,
|
||||
0x94, 0x7c, 0x96, 0xf9, 0xd6, 0x18, 0xd3, 0xbf, 0xdd, 0xd7, 0x92, 0x6a, 0x3e, 0xd5, 0xcc, 0x2b, 0xad, 0xe4, 0x28, 0x9d,
|
||||
0xa8, 0xff, 0x48, 0xf7, 0x54, 0x31, 0x58, 0xd1, 0x15, 0x7b, 0x30, 0xd3, 0x0f, 0xb7, 0x8d, 0xf5, 0x1f, 0xa5, 0x73, 0x97,
|
||||
0x28, 0x6b, 0x73, 0x27, 0xea, 0xff, 0x79, 0xd4, 0x6e, 0x25, 0xed, 0x26, 0x5e, 0xf6, 0x51, 0x6d, 0x2d, 0xaf, 0x9d, 0xa7,
|
||||
0xae, 0xae, 0xff, 0xe7, 0xdf, 0x1c, 0x1d, 0x6f, 0x63, 0x70, 0xec, 0xae, 0xd8, 0x4f, 0xb9, 0xf1, 0xbf, 0x7e, 0x3f, 0xc6,
|
||||
0x5f, 0xc7, 0xe6, 0xec, 0x3c, 0x64, 0x64, 0x0f, 0xc7, 0xe0, 0xd9, 0xd5, 0xec, 0x08, 0x7b, 0x72, 0xfc, 0xef, 0x9b, 0x0b,
|
||||
0xaa, 0xff, 0xb5, 0xf5, 0x9f, 0xf9, 0x24, 0xd1, 0xb9, 0x05, 0x99, 0x31, 0xb1, 0x5d, 0x50, 0xff, 0xa3, 0xfd, 0xd0, 0xf3,
|
||||
0xbe, 0xaa, 0x9a, 0xcb, 0x8f, 0xae, 0x4b, 0xf4, 0x9d, 0x61, 0xef, 0x6b, 0x85, 0xe3, 0x73, 0xa3, 0xf1, 0xfa, 0x1f, 0xef,
|
||||
0x3d, 0xdf, 0xfe, 0xda, 0xe8, 0x5e, 0xfd, 0xfb, 0x99, 0xdd, 0xfc, 0x1e, 0xdf, 0x57, 0xff, 0x91, 0x18, 0x53, 0xce, 0xd7,
|
||||
0x73, 0x4d, 0xfd, 0x47, 0x62, 0xe5, 0xa2, 0x95, 0xad, 0xf2, 0xe5, 0xd6, 0x25, 0xea, 0xd6, 0x0c, 0xce, 0x1f, 0x81, 0xf7,
|
||||
0xfa, 0x7f, 0x3b, 0x1f, 0x3c, 0x3f, 0xfe, 0xc7, 0x15, 0xe3, 0x7f, 0xa4, 0xd7, 0x86, 0x5b, 0xa2, 0xf7, 0xfd, 0x5a, 0xfd,
|
||||
0x47, 0xa2, 0x66, 0xa2, 0xe4, 0xbc, 0xbc, 0x2d, 0x59, 0xcb, 0xab, 0x5d, 0x33, 0xdc, 0x73, 0xb4, 0xde, 0x46, 0xd1, 0xaa,
|
||||
0xb3, 0x9a, 0x9f, 0x55, 0xff, 0xad, 0x60, 0xfc, 0xef, 0x9b, 0x03, 0xcc, 0x7e, 0x8e, 0xf8, 0xd8, 0xe8, 0x5f, 0x59, 0xff,
|
||||
0xbb, 0x56, 0xec, 0xd7, 0xb7, 0xc6, 0xb8, 0xe2, 0xc8, 0x58, 0xff, 0xaf, 0x9c, 0xff, 0xe7, 0xd7, 0x00, 0xc6, 0xce, 0x63,
|
||||
0xe2, 0xd2, 0xea, 0xcf, 0x9c, 0x33, 0x57, 0x5d, 0xb1, 0xaf, 0xfd, 0x36, 0x41, 0x24, 0xbe, 0xab, 0x51, 0xb3, 0x8a, 0xb3,
|
||||
0xfa, 0x18, 0x8c, 0x8f, 0xff, 0xbb, 0xae, 0xff, 0xbf, 0xcf, 0xb9, 0xef, 0x18, 0xff, 0xdb, 0xeb, 0xe8, 0x7e, 0xcb, 0xf6,
|
||||
0x00, 0x7b, 0x7b, 0x80, 0x50, 0xfd, 0xe0, 0x7b, 0xc4, 0x80, 0xfa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0a, 0xbf, 0x9f, 0x5f, 0x9f, 0x63, 0x30, 0x9e, 0x84, 0xbd, 0x3e, 0x81, 0x7d, 0x26, 0x13, 0x38, 0xbb,
|
||||
0x87, 0xaa, 0xfe, 0xe2, 0x73, 0x76, 0xfc, 0x48, 0xd2, 0x42, 0x7f, 0xcb, 0x88, 0xe1, 0xa7, 0x1f, 0x54, 0x26, 0x0a, 0x64,
|
||||
0x32, 0x0d, 0xda, 0x60, 0x9b, 0xa8, 0xcd, 0x52, 0x1a, 0xdb, 0xfa, 0x3d, 0x2d, 0xfe, 0x0b, 0xf5, 0x7f, 0xfe, 0x95, 0x96,
|
||||
0xc8, 0xef, 0xd9, 0x59, 0xff, 0xa3, 0x6d, 0x2f, 0x97, 0x8f, 0x3b, 0x37, 0x96, 0xec, 0x4e, 0x14, 0x8b, 0xc2, 0x63, 0xb8,
|
||||
0x6f, 0x5c, 0xfd, 0x33, 0x43, 0x67, 0x47, 0xbb, 0x9e, 0xa9, 0xff, 0xd1, 0xec, 0xd3, 0x78, 0xe8, 0x85, 0xef, 0xa9, 0xff,
|
||||
0xb6, 0xa5, 0xfe, 0xe3, 0x23, 0xf5, 0x5f, 0x9d, 0x24, 0x53, 0x95, 0x42, 0x9e, 0x49, 0xbe, 0x19, 0x3f, 0x86, 0xf9, 0x84,
|
||||
0xdf, 0x6c, 0x8b, 0xfb, 0x4e, 0xfd, 0x67, 0xda, 0xd6, 0x73, 0xce, 0xaa, 0xfa, 0x7f, 0xdf, 0xb7, 0x99, 0xd1, 0x64, 0xfe,
|
||||
0xe7, 0x35, 0x95, 0xbf, 0x27, 0x47, 0xf7, 0xed, 0x39, 0x5a, 0x6b, 0xdb, 0xca, 0xec, 0x58, 0xf9, 0x95, 0xfa, 0x8f, 0xe4,
|
||||
0x5f, 0x89, 0x97, 0x1e, 0xa5, 0x36, 0x81, 0xbd, 0x26, 0xb5, 0x6d, 0x6f, 0xfd, 0x57, 0x3f, 0xf7, 0xe7, 0x8e, 0xfa, 0x3f,
|
||||
0x9f, 0xa3, 0xbb, 0xea, 0x1c, 0xae, 0x76, 0xac, 0xfc, 0xd9, 0xe3, 0xff, 0x7b, 0x2f, 0xb9, 0xa3, 0x7d, 0xcc, 0x8c, 0xf4,
|
||||
0x27, 0xc7, 0xff, 0x73, 0x3f, 0x3f, 0x5b, 0xff, 0x55, 0xad, 0x3d, 0x36, 0xce, 0x4c, 0xb2, 0x63, 0xe5, 0xce, 0x55, 0xb2,
|
||||
0xdd, 0xe7, 0xff, 0xab, 0x3e, 0x59, 0x1b, 0x9e, 0x4d, 0xc4, 0xb5, 0xf5, 0x3f, 0xb3, 0x0a, 0xb9, 0x6e, 0xbe, 0x70, 0x66,
|
||||
0xfe, 0x9f, 0x7b, 0xbe, 0x6d, 0xe6, 0xa9, 0x80, 0xb7, 0x8d, 0xff, 0xbb, 0xae, 0x92, 0xb5, 0xcd, 0x35, 0xb9, 0xf7, 0xbd,
|
||||
0x2a, 0x9f, 0x52, 0x37, 0x9e, 0xdf, 0x1f, 0xc5, 0x33, 0xbc, 0xaf, 0xd7, 0x7f, 0x7e, 0x95, 0xbf, 0x15, 0xad, 0x4a, 0x9e,
|
||||
0x9b, 0xff, 0xef, 0x7e, 0xd2, 0x49, 0xe6, 0x5d, 0x6a, 0xfa, 0xdf, 0xbe, 0xab, 0xc2, 0xb5, 0xa3, 0xc0, 0xdf, 0xaf, 0x36,
|
||||
0x44, 0xd1, 0xc8, 0x51, 0x95, 0xdf, 0xff, 0xe7, 0xb6, 0x8d, 0x3f, 0xf1, 0x6c, 0xfc, 0x4a, 0x7c, 0x0c, 0x3e, 0x4f, 0xff,
|
||||
0x44, 0xfd, 0x67, 0xde, 0x39, 0xf3, 0xbf, 0x46, 0x8f, 0x61, 0x65, 0xfd, 0x9f, 0xeb, 0x01, 0xe4, 0x6e, 0xc2, 0x8d, 0xb3,
|
||||
0x18, 0xe0, 0xe7, 0xf4, 0x00, 0x9e, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xec, 0xbe, 0x13, 0xfb, 0xef, 0xd9, 0x5c, 0x99, 0xd4, 0xf8, 0xf1, 0xfb, 0xa4, 0x77, 0x26, 0xe6, 0xb7, 0x97, 0x14, 0xb2,
|
||||
0xe7, 0xdf, 0xfa, 0xf3, 0x95, 0x8a, 0x3c, 0xde, 0x28, 0xbc, 0x6b, 0xfd, 0x29, 0x93, 0xe4, 0x39, 0x4b, 0x71, 0x34, 0x77,
|
||||
0xe0, 0x7d, 0x0f, 0x8f, 0x1f, 0x97, 0x99, 0xd7, 0x5a, 0x61, 0x9a, 0x42, 0x24, 0xd2, 0x5e, 0xde, 0xf6, 0x7a, 0x7f, 0x36,
|
||||
0x70, 0x94, 0x6d, 0xf1, 0x58, 0x1d, 0x55, 0x65, 0x27, 0xdf, 0x9e, 0x98, 0x3f, 0x9f, 0xbc, 0x13, 0x2f, 0xad, 0xae, 0xbf,
|
||||
0xfe, 0x7b, 0x92, 0x23, 0xd6, 0xe7, 0x18, 0xf5, 0xfc, 0x34, 0x93, 0x7a, 0x31, 0x96, 0xc1, 0x36, 0xd7, 0x06, 0x56, 0x8f,
|
||||
0x50, 0x6d, 0xb2, 0x42, 0x62, 0xaa, 0xa5, 0xcc, 0x67, 0xff, 0xbd, 0x6f, 0x69, 0x1b, 0x1c, 0xb9, 0x6e, 0x48, 0xcc, 0x8c,
|
||||
0xce, 0xfa, 0xaa, 0xfe, 0x69, 0x1b, 0xec, 0x6f, 0x32, 0x79, 0x75, 0x51, 0x9a, 0x44, 0x91, 0xff, 0x3f, 0x91, 0x48, 0x6d,
|
||||
0x6e, 0xc9, 0x2c, 0xbe, 0x7c, 0x46, 0x7c, 0x26, 0xa7, 0x2a, 0x16, 0xef, 0xd9, 0x4c, 0xfd, 0xb7, 0x43, 0xf5, 0x9f, 0x49,
|
||||
0x3d, 0x38, 0x9f, 0x98, 0x1d, 0xa9, 0xda, 0xdd, 0x5b, 0xff, 0xd1, 0xd1, 0x7f, 0x65, 0x66, 0xd7, 0x51, 0x78, 0xce, 0xf0,
|
||||
0x3e, 0xe3, 0xad, 0x1e, 0xff, 0xdb, 0xe3, 0x7e, 0x1a, 0x4f, 0x75, 0x5b, 0x3f, 0x42, 0x65, 0x7a, 0x93, 0xb1, 0xfa, 0x5f,
|
||||
0xdd, 0x63, 0xcd, 0x3c, 0x07, 0x29, 0x3e, 0x37, 0xfe, 0x9f, 0x49, 0xcc, 0x8e, 0xc4, 0xd9, 0x75, 0xe6, 0x7d, 0xeb, 0xd7,
|
||||
0x5e, 0xa2, 0xb0, 0xfe, 0x33, 0x3d, 0x40, 0xbe, 0xfe, 0x77, 0xce, 0xa6, 0xb3, 0x79, 0x93, 0x31, 0xdd, 0x86, 0xce, 0xd4,
|
||||
0x7f, 0xe5, 0xd3, 0x96, 0x56, 0x24, 0xe6, 0x8e, 0x3f, 0xd9, 0xf1, 0xd4, 0xf8, 0xdf, 0x52, 0xe3, 0x7f, 0x6e, 0x9c, 0xa8,
|
||||
0x3b, 0xf6, 0xb5, 0x73, 0xe5, 0xf7, 0xfa, 0x8f, 0x0d, 0xef, 0xb6, 0xaf, 0xfe, 0x33, 0x3d, 0x61, 0x2c, 0x9b, 0xff, 0x67,
|
||||
0xab, 0x25, 0x86, 0xe7, 0xd7, 0x3b, 0x13, 0x73, 0x33, 0xeb, 0xcc, 0xf7, 0xd7, 0x7f, 0xe5, 0x33, 0x4c, 0xda, 0x54, 0xfa,
|
||||
0x72, 0x94, 0x8e, 0xc8, 0xfb, 0xc6, 0xff, 0x15, 0xb3, 0xe9, 0x4c, 0xfa, 0xfe, 0x3d, 0xeb, 0x7f, 0xad, 0xf8, 0x88, 0xb5,
|
||||
0xe3, 0x79, 0x88, 0x2b, 0x66, 0x85, 0x27, 0xce, 0xff, 0xab, 0x12, 0xd8, 0x73, 0xe7, 0xff, 0xd5, 0x2b, 0xf2, 0x73, 0xc7,
|
||||
0xf2, 0xde, 0xf1, 0x3f, 0xd7, 0x42, 0x62, 0x68, 0x7c, 0x6e, 0x9f, 0xaa, 0xff, 0x5b, 0xbe, 0xd1, 0x50, 0xd1, 0x6f, 0x45,
|
||||
0x49, 0xef, 0x96, 0x79, 0x6e, 0x4b, 0xe5, 0x3c, 0xaa, 0x72, 0xfd, 0x6a, 0xe6, 0xfa, 0xff, 0xcc, 0xb7, 0x53, 0x56, 0xbf,
|
||||
0x5b, 0xfe, 0xfa, 0xff, 0xda, 0xfa, 0x8f, 0xe2, 0x2d, 0xe6, 0x9e, 0x5e, 0xea, 0xe6, 0xf7, 0xd3, 0x7e, 0xee, 0x38, 0x82,
|
||||
0x6a, 0x59, 0xeb, 0x39, 0x71, 0x3e, 0xc4, 0xef, 0x9a, 0x33, 0xf3, 0xd3, 0xbf, 0xe1, 0x6d, 0x3f, 0x18, 0x9b, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xef, 0xde, 0xc3, 0x14, 0xaf, 0x77, 0x38, 0xbc, 0x65, 0x4b,
|
||||
0x64, 0x72, 0x29, 0x5b, 0x69, 0xce, 0x5d, 0x4b, 0x24, 0xf3, 0x67, 0xb7, 0xae, 0x77, 0xaf, 0xac, 0xff, 0x64, 0xb3, 0x69,
|
||||
0xe6, 0x99, 0xc4, 0xf9, 0xcc, 0x3e, 0x3e, 0x7b, 0x34, 0xdf, 0x32, 0x3c, 0x22, 0x91, 0xc6, 0x5a, 0x79, 0xbc, 0x5a, 0x6a,
|
||||
0xdf, 0x65, 0x5b, 0x59, 0x6f, 0x0f, 0xd0, 0x9f, 0x0f, 0x53, 0x7f, 0x8f, 0x69, 0xa4, 0xf6, 0x79, 0x4d, 0x32, 0xff, 0x4c,
|
||||
0x5b, 0x6a, 0xe9, 0x04, 0xe2, 0x6c, 0xab, 0xe9, 0xfd, 0x5b, 0x31, 0xfd, 0x97, 0xdf, 0xb3, 0x5a, 0xe3, 0x73, 0x47, 0x33,
|
||||
0x9b, 0x17, 0x5f, 0x7d, 0xbc, 0x6a, 0xd3, 0xdb, 0x6a, 0x7a, 0x80, 0x8a, 0xfa, 0xaf, 0xdb, 0xca, 0xfd, 0xf7, 0xc6, 0x46,
|
||||
0xf2, 0x7e, 0xfa, 0xf8, 0xfc, 0xfd, 0xa7, 0xf1, 0xd1, 0x24, 0x81, 0x5c, 0xca, 0xe4, 0xae, 0x4f, 0x95, 0xcb, 0xe5, 0xca,
|
||||
0xa7, 0xb7, 0xed, 0x1c, 0xff, 0x33, 0x49, 0x52, 0x99, 0xb4, 0xd0, 0xea, 0x57, 0xb2, 0xbd, 0x65, 0xae, 0xfe, 0x33, 0x99,
|
||||
0x4d, 0x51, 0x94, 0x67, 0x5c, 0xf7, 0xdc, 0x93, 0x48, 0xce, 0xaf, 0x4f, 0x1e, 0xcd, 0x78, 0x4d, 0x25, 0xaf, 0xca, 0xd8,
|
||||
0xdd, 0xfb, 0x4a, 0x4c, 0x26, 0x3e, 0x44, 0xd7, 0xf1, 0x8e, 0xe9, 0xb1, 0x70, 0xd7, 0xd3, 0x02, 0x33, 0xcf, 0xa4, 0x68,
|
||||
0xc9, 0xd4, 0xcc, 0x28, 0x9b, 0xe1, 0x57, 0xbf, 0xb2, 0xa2, 0xfe, 0xe3, 0xe1, 0x3c, 0xb9, 0xfa, 0x99, 0x65, 0xd5, 0x47,
|
||||
0xb3, 0xa7, 0x67, 0xf8, 0x62, 0xfd, 0xaf, 0x9d, 0xa7, 0xd5, 0x9c, 0xff, 0x47, 0xfa, 0x59, 0x3c, 0x77, 0xb6, 0x98, 0xe8,
|
||||
0x4c, 0x77, 0xfe, 0x69, 0xf5, 0xbf, 0x77, 0x1f, 0x57, 0xf7, 0xe6, 0xcf, 0x33, 0xec, 0xf6, 0xd1, 0xfa, 0x9f, 0x49, 0x8b,
|
||||
0xaf, 0x39, 0x5f, 0x79, 0x5f, 0xff, 0xaf, 0x5c, 0xd9, 0xb8, 0xa3, 0xfe, 0x6f, 0xa9, 0xf2, 0xb1, 0x7d, 0xbe, 0xb6, 0xfe,
|
||||
0xcf, 0xd7, 0xd0, 0x6c, 0xf2, 0xfb, 0xf9, 0x6d, 0x8f, 0xb2, 0xf3, 0xff, 0x9a, 0x75, 0xa1, 0xea, 0x79, 0xc4, 0x6d, 0x3d,
|
||||
0xe8, 0xaa, 0xa7, 0xab, 0xbd, 0xcd, 0x1d, 0xaa, 0xcf, 0x77, 0xef, 0x18, 0xff, 0x43, 0xfd, 0x2f, 0x58, 0x0b, 0xaf, 0x1d,
|
||||
0x25, 0xf3, 0x2b, 0xcc, 0x33, 0xfd, 0xc9, 0xf8, 0xb3, 0xec, 0x6b, 0x57, 0xc9, 0x32, 0x7d, 0x68, 0xcf, 0x2b, 0xf9, 0x27,
|
||||
0x6e, 0x7c, 0x75, 0xfe, 0xdf, 0xf3, 0x54, 0xa0, 0x6f, 0xd5, 0x7f, 0x24, 0xd7, 0xb7, 0xee, 0xa8, 0xff, 0xb5, 0x57, 0x06,
|
||||
0xd6, 0x5f, 0xcb, 0xbf, 0x79, 0xfe, 0xbf, 0xa2, 0xcf, 0xfb, 0x76, 0xfd, 0x7f, 0x61, 0x0e, 0xbd, 0xe6, 0x5b, 0x28, 0xe7,
|
||||
0xea, 0x7f, 0x6e, 0xdc, 0x56, 0xff, 0x2b, 0x56, 0x8c, 0xf3, 0x9f, 0x7a, 0xc5, 0xf9, 0x7f, 0xef, 0x4c, 0xe3, 0xe7, 0xd7,
|
||||
0x7f, 0x7d, 0xd2, 0xf9, 0x9a, 0xf3, 0xcd, 0x76, 0xe9, 0x77, 0x61, 0xee, 0xfa, 0x4e, 0xf2, 0x9e, 0x16, 0xb3, 0x66, 0xed,
|
||||
0x23, 0xf3, 0x94, 0xde, 0xda, 0xa7, 0x39, 0xc5, 0xa2, 0x4a, 0xcf, 0x5d, 0xe5, 0xdd, 0x73, 0xfd, 0x7f, 0xef, 0x37, 0x8a,
|
||||
0xaa, 0xb7, 0x50, 0xfd, 0x7f, 0xa3, 0x0f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdb,
|
||||
0xee, 0xd0, 0xdb, 0x9b, 0xa8, 0x5f, 0x9f, 0x82, 0x71, 0x7b, 0xa2, 0xfe, 0xdb, 0x5d, 0x33, 0xed, 0xda, 0x44, 0xfd, 0xd6,
|
||||
0x95, 0x4c, 0xf4, 0xbd, 0x44, 0xfd, 0xdf, 0x78, 0xc7, 0xc7, 0x6d, 0x89, 0xfa, 0x75, 0x77, 0x4e, 0xdf, 0x9e, 0xa8, 0xdf,
|
||||
0x5e, 0xf2, 0x87, 0x6e, 0x4e, 0xd4, 0xcf, 0xdf, 0x3b, 0x75, 0x6b, 0xa2, 0x3e, 0x6b, 0xef, 0x98, 0xec, 0xed, 0xfb, 0xe3,
|
||||
0xe0, 0x31, 0x5b, 0x75, 0x77, 0x69, 0x7c, 0xf4, 0xce, 0xcf, 0xf1, 0x8c, 0xa6, 0x15, 0x3d, 0x4a, 0xe5, 0x5d, 0x9a, 0xeb,
|
||||
0x13, 0xf5, 0x7f, 0x4a, 0xbd, 0xee, 0x4a, 0xd4, 0x7f, 0xcf, 0x19, 0x8b, 0x4d, 0xdb, 0x1f, 0x43, 0xf3, 0xc6, 0xb5, 0x89,
|
||||
0x5a, 0xcf, 0xfd, 0xe8, 0xbd, 0xcf, 0x47, 0xf8, 0x76, 0xa2, 0xf6, 0x6f, 0xab, 0xff, 0x55, 0xfb, 0x29, 0x8a, 0xaa, 0xae,
|
||||
0xf7, 0x95, 0x7d, 0x59, 0x41, 0x75, 0xf5, 0x1f, 0xe5, 0xaf, 0xed, 0x4d, 0xd4, 0xca, 0xae, 0x27, 0xa8, 0xff, 0xef, 0xac,
|
||||
0x01, 0xe4, 0xd6, 0xad, 0xe6, 0x12, 0x75, 0x4f, 0xb6, 0x80, 0x9d, 0x89, 0x5a, 0x5f, 0xaf, 0xff, 0xcc, 0xac, 0x5c, 0xfd,
|
||||
0xdf, 0x39, 0xff, 0x8f, 0xb2, 0x57, 0x32, 0xbd, 0x46, 0x7e, 0xfd, 0xff, 0xcb, 0x4f, 0xd4, 0xfa, 0x99, 0xf5, 0x7f, 0x47,
|
||||
0xa2, 0xae, 0xfa, 0x3f, 0x33, 0xff, 0x5f, 0xf7, 0x54, 0x82, 0x9d, 0x89, 0xba, 0xc6, 0xff, 0x55, 0x15, 0x71, 0x77, 0x95,
|
||||
0xdf, 0x95, 0x9b, 0xfb, 0xcd, 0xf3, 0xff, 0xdc, 0x93, 0x40, 0xb3, 0x3d, 0xc0, 0xbe, 0x84, 0xd6, 0x13, 0x89, 0xfa, 0x12,
|
||||
0x75, 0x67, 0x8e, 0xd7, 0xf3, 0xec, 0xef, 0x9b, 0xd7, 0x63, 0x6e, 0x9f, 0xff, 0xd7, 0x5e, 0xab, 0xf9, 0xe7, 0x9a, 0xd2,
|
||||
0xea, 0x15, 0xef, 0x55, 0xf3, 0xff, 0xda, 0x2b, 0x5b, 0x12, 0x75, 0xab, 0x8f, 0xda, 0x6f, 0x5f, 0xff, 0x3b, 0xdb, 0xd3,
|
||||
0xc0, 0xee, 0x79, 0xed, 0xf9, 0x9e, 0x10, 0xf8, 0xda, 0x37, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xf9, 0xef, 0x3f, 0xfb, 0x01, 0xd4, 0x3f,
|
||||
0xf0, 0xeb, 0xea, 0xff, 0x3f };
|
||||
|
||||
// Font glyphs rectangles data (on atlas)
|
||||
static const Rectangle darkFontRecs[189] = {
|
||||
{ 4, 4, 4 , 16 },
|
||||
{ 16, 4, 1 , 9 },
|
||||
{ 25, 4, 3 , 3 },
|
||||
{ 36, 4, 6 , 9 },
|
||||
{ 50, 4, 5 , 13 },
|
||||
{ 63, 4, 7 , 9 },
|
||||
{ 78, 4, 5 , 9 },
|
||||
{ 91, 4, 1 , 3 },
|
||||
{ 100, 4, 3 , 9 },
|
||||
{ 111, 4, 3 , 9 },
|
||||
{ 122, 4, 5 , 5 },
|
||||
{ 135, 4, 5 , 5 },
|
||||
{ 148, 4, 2 , 3 },
|
||||
{ 158, 4, 4 , 1 },
|
||||
{ 170, 4, 1 , 1 },
|
||||
{ 179, 4, 3 , 9 },
|
||||
{ 190, 4, 5 , 9 },
|
||||
{ 203, 4, 3 , 9 },
|
||||
{ 214, 4, 5 , 9 },
|
||||
{ 227, 4, 5 , 9 },
|
||||
{ 240, 4, 5 , 9 },
|
||||
{ 253, 4, 5 , 9 },
|
||||
{ 266, 4, 5 , 9 },
|
||||
{ 279, 4, 5 , 9 },
|
||||
{ 292, 4, 5 , 9 },
|
||||
{ 305, 4, 5 , 9 },
|
||||
{ 318, 4, 1 , 7 },
|
||||
{ 327, 4, 2 , 9 },
|
||||
{ 337, 4, 3 , 5 },
|
||||
{ 348, 4, 4 , 3 },
|
||||
{ 360, 4, 3 , 5 },
|
||||
{ 371, 4, 5 , 9 },
|
||||
{ 384, 4, 7 , 9 },
|
||||
{ 399, 4, 5 , 9 },
|
||||
{ 412, 4, 5 , 9 },
|
||||
{ 425, 4, 5 , 9 },
|
||||
{ 438, 4, 5 , 9 },
|
||||
{ 451, 4, 5 , 9 },
|
||||
{ 464, 4, 5 , 9 },
|
||||
{ 477, 4, 5 , 9 },
|
||||
{ 490, 4, 5 , 9 },
|
||||
{ 4, 28, 1 , 9 },
|
||||
{ 13, 28, 5 , 9 },
|
||||
{ 26, 28, 5 , 9 },
|
||||
{ 39, 28, 5 , 9 },
|
||||
{ 52, 28, 7 , 9 },
|
||||
{ 67, 28, 5 , 9 },
|
||||
{ 80, 28, 5 , 9 },
|
||||
{ 93, 28, 5 , 9 },
|
||||
{ 106, 28, 5 , 9 },
|
||||
{ 119, 28, 5 , 9 },
|
||||
{ 132, 28, 5 , 9 },
|
||||
{ 145, 28, 5 , 9 },
|
||||
{ 158, 28, 5 , 9 },
|
||||
{ 171, 28, 5 , 9 },
|
||||
{ 184, 28, 7 , 9 },
|
||||
{ 199, 28, 5 , 9 },
|
||||
{ 212, 28, 5 , 9 },
|
||||
{ 225, 28, 5 , 9 },
|
||||
{ 238, 28, 3 , 9 },
|
||||
{ 249, 28, 3 , 9 },
|
||||
{ 260, 28, 3 , 9 },
|
||||
{ 271, 28, 5 , 3 },
|
||||
{ 284, 28, 5 , 1 },
|
||||
{ 297, 28, 2 , 2 },
|
||||
{ 307, 28, 5 , 7 },
|
||||
{ 320, 28, 5 , 9 },
|
||||
{ 333, 28, 5 , 7 },
|
||||
{ 346, 28, 5 , 9 },
|
||||
{ 359, 28, 5 , 7 },
|
||||
{ 372, 28, 4 , 9 },
|
||||
{ 384, 28, 5 , 9 },
|
||||
{ 397, 28, 5 , 9 },
|
||||
{ 410, 28, 1 , 9 },
|
||||
{ 419, 28, 5 , 11 },
|
||||
{ 432, 28, 5 , 9 },
|
||||
{ 445, 28, 2 , 9 },
|
||||
{ 455, 28, 7 , 7 },
|
||||
{ 470, 28, 5 , 7 },
|
||||
{ 483, 28, 5 , 7 },
|
||||
{ 496, 28, 5 , 9 },
|
||||
{ 4, 52, 5 , 9 },
|
||||
{ 17, 52, 5 , 7 },
|
||||
{ 30, 52, 5 , 7 },
|
||||
{ 43, 52, 4 , 8 },
|
||||
{ 55, 52, 5 , 7 },
|
||||
{ 68, 52, 5 , 7 },
|
||||
{ 81, 52, 7 , 7 },
|
||||
{ 96, 52, 5 , 7 },
|
||||
{ 109, 52, 5 , 9 },
|
||||
{ 122, 52, 5 , 7 },
|
||||
{ 135, 52, 4 , 9 },
|
||||
{ 147, 52, 1 , 9 },
|
||||
{ 156, 52, 4 , 9 },
|
||||
{ 168, 52, 6 , 2 },
|
||||
{ 182, 52, 1 , 9 },
|
||||
{ 191, 52, 5 , 11 },
|
||||
{ 204, 52, 6 , 9 },
|
||||
{ 218, 52, 6 , 9 },
|
||||
{ 232, 52, 5 , 9 },
|
||||
{ 245, 52, 5 , 12 },
|
||||
{ 258, 52, 5 , 9 },
|
||||
{ 271, 52, 5 , 10 },
|
||||
{ 284, 52, 7 , 9 },
|
||||
{ 299, 52, 5 , 9 },
|
||||
{ 312, 52, 6 , 5 },
|
||||
{ 326, 52, 5 , 3 },
|
||||
{ 339, 52, 7 , 9 },
|
||||
{ 354, 52, 5 , 9 },
|
||||
{ 367, 52, 4 , 4 },
|
||||
{ 379, 52, 5 , 7 },
|
||||
{ 392, 52, 5 , 9 },
|
||||
{ 405, 52, 5 , 9 },
|
||||
{ 418, 52, 5 , 12 },
|
||||
{ 431, 52, 5 , 9 },
|
||||
{ 444, 52, 7 , 9 },
|
||||
{ 459, 52, 1 , 1 },
|
||||
{ 468, 52, 5 , 10 },
|
||||
{ 481, 52, 5 , 9 },
|
||||
{ 494, 52, 5 , 9 },
|
||||
{ 4, 76, 6 , 5 },
|
||||
{ 18, 76, 9 , 9 },
|
||||
{ 35, 76, 9 , 7 },
|
||||
{ 52, 76, 5 , 11 },
|
||||
{ 65, 76, 5 , 9 },
|
||||
{ 78, 76, 5 , 12 },
|
||||
{ 91, 76, 5 , 12 },
|
||||
{ 104, 76, 5 , 12 },
|
||||
{ 117, 76, 6 , 12 },
|
||||
{ 131, 76, 5 , 11 },
|
||||
{ 144, 76, 5 , 13 },
|
||||
{ 157, 76, 9 , 9 },
|
||||
{ 174, 76, 5 , 12 },
|
||||
{ 187, 76, 5 , 12 },
|
||||
{ 200, 76, 5 , 12 },
|
||||
{ 213, 76, 5 , 12 },
|
||||
{ 226, 76, 5 , 11 },
|
||||
{ 239, 76, 2 , 12 },
|
||||
{ 249, 76, 2 , 12 },
|
||||
{ 259, 76, 3 , 12 },
|
||||
{ 270, 76, 3 , 11 },
|
||||
{ 281, 76, 6 , 9 },
|
||||
{ 295, 76, 6 , 12 },
|
||||
{ 309, 76, 5 , 12 },
|
||||
{ 322, 76, 5 , 12 },
|
||||
{ 335, 76, 5 , 12 },
|
||||
{ 348, 76, 6 , 12 },
|
||||
{ 362, 76, 5 , 11 },
|
||||
{ 375, 76, 5 , 5 },
|
||||
{ 388, 76, 7 , 9 },
|
||||
{ 403, 76, 5 , 12 },
|
||||
{ 416, 76, 5 , 12 },
|
||||
{ 429, 76, 5 , 12 },
|
||||
{ 442, 76, 5 , 11 },
|
||||
{ 455, 76, 5 , 12 },
|
||||
{ 468, 76, 5 , 9 },
|
||||
{ 481, 76, 5 , 9 },
|
||||
{ 494, 76, 5 , 10 },
|
||||
{ 4, 100, 5 , 10 },
|
||||
{ 17, 100, 5 , 10 },
|
||||
{ 30, 100, 6 , 10 },
|
||||
{ 44, 100, 5 , 9 },
|
||||
{ 57, 100, 5 , 11 },
|
||||
{ 70, 100, 9 , 7 },
|
||||
{ 87, 100, 5 , 10 },
|
||||
{ 100, 100, 5 , 10 },
|
||||
{ 113, 100, 5 , 10 },
|
||||
{ 126, 100, 5 , 10 },
|
||||
{ 139, 100, 5 , 9 },
|
||||
{ 152, 100, 2 , 10 },
|
||||
{ 162, 100, 2 , 10 },
|
||||
{ 172, 100, 3 , 10 },
|
||||
{ 183, 100, 3 , 9 },
|
||||
{ 194, 100, 6 , 9 },
|
||||
{ 208, 100, 6 , 10 },
|
||||
{ 222, 100, 5 , 10 },
|
||||
{ 235, 100, 5 , 10 },
|
||||
{ 248, 100, 5 , 10 },
|
||||
{ 261, 100, 6 , 10 },
|
||||
{ 275, 100, 5 , 9 },
|
||||
{ 288, 100, 5 , 5 },
|
||||
{ 301, 100, 7 , 7 },
|
||||
{ 316, 100, 5 , 10 },
|
||||
{ 329, 100, 5 , 10 },
|
||||
{ 342, 100, 5 , 10 },
|
||||
{ 355, 100, 5 , 9 },
|
||||
{ 368, 100, 5 , 12 },
|
||||
{ 381, 100, 5 , 11 },
|
||||
{ 394, 100, 5 , 11 },
|
||||
};
|
||||
|
||||
// Font glyphs info data
|
||||
// NOTE: No glyphs.image data provided
|
||||
static const GlyphInfo darkFontGlyphs[189] = {
|
||||
{ 32, 0, 13, 4, { 0 }},
|
||||
{ 33, 2, 4, 5, { 0 }},
|
||||
{ 34, 2, 4, 7, { 0 }},
|
||||
{ 35, 1, 4, 8, { 0 }},
|
||||
{ 36, 1, 2, 7, { 0 }},
|
||||
{ 37, 1, 4, 9, { 0 }},
|
||||
{ 38, 1, 4, 7, { 0 }},
|
||||
{ 39, 2, 4, 5, { 0 }},
|
||||
{ 40, 3, 4, 7, { 0 }},
|
||||
{ 41, 1, 4, 7, { 0 }},
|
||||
{ 42, 1, 4, 7, { 0 }},
|
||||
{ 43, 1, 6, 7, { 0 }},
|
||||
{ 44, 1, 12, 5, { 0 }},
|
||||
{ 45, 1, 8, 6, { 0 }},
|
||||
{ 46, 2, 12, 5, { 0 }},
|
||||
{ 47, 1, 4, 5, { 0 }},
|
||||
{ 48, 1, 4, 7, { 0 }},
|
||||
{ 49, 2, 4, 7, { 0 }},
|
||||
{ 50, 1, 4, 7, { 0 }},
|
||||
{ 51, 1, 4, 7, { 0 }},
|
||||
{ 52, 1, 4, 7, { 0 }},
|
||||
{ 53, 1, 4, 7, { 0 }},
|
||||
{ 54, 1, 4, 7, { 0 }},
|
||||
{ 55, 1, 4, 7, { 0 }},
|
||||
{ 56, 1, 4, 7, { 0 }},
|
||||
{ 57, 1, 4, 7, { 0 }},
|
||||
{ 58, 2, 6, 5, { 0 }},
|
||||
{ 59, 1, 6, 5, { 0 }},
|
||||
{ 60, 1, 6, 5, { 0 }},
|
||||
{ 61, 1, 7, 6, { 0 }},
|
||||
{ 62, 1, 6, 5, { 0 }},
|
||||
{ 63, 1, 4, 7, { 0 }},
|
||||
{ 64, 1, 4, 9, { 0 }},
|
||||
{ 65, 1, 4, 7, { 0 }},
|
||||
{ 66, 1, 4, 7, { 0 }},
|
||||
{ 67, 1, 4, 7, { 0 }},
|
||||
{ 68, 1, 4, 7, { 0 }},
|
||||
{ 69, 1, 4, 7, { 0 }},
|
||||
{ 70, 1, 4, 7, { 0 }},
|
||||
{ 71, 1, 4, 7, { 0 }},
|
||||
{ 72, 1, 4, 7, { 0 }},
|
||||
{ 73, 2, 4, 5, { 0 }},
|
||||
{ 74, 1, 4, 7, { 0 }},
|
||||
{ 75, 1, 4, 7, { 0 }},
|
||||
{ 76, 1, 4, 7, { 0 }},
|
||||
{ 77, 1, 4, 9, { 0 }},
|
||||
{ 78, 1, 4, 7, { 0 }},
|
||||
{ 79, 1, 4, 7, { 0 }},
|
||||
{ 80, 1, 4, 7, { 0 }},
|
||||
{ 81, 1, 4, 7, { 0 }},
|
||||
{ 82, 1, 4, 7, { 0 }},
|
||||
{ 83, 1, 4, 7, { 0 }},
|
||||
{ 84, 1, 4, 7, { 0 }},
|
||||
{ 85, 1, 4, 7, { 0 }},
|
||||
{ 86, 1, 4, 7, { 0 }},
|
||||
{ 87, 1, 4, 9, { 0 }},
|
||||
{ 88, 1, 4, 7, { 0 }},
|
||||
{ 89, 1, 4, 7, { 0 }},
|
||||
{ 90, 1, 4, 7, { 0 }},
|
||||
{ 91, 3, 4, 7, { 0 }},
|
||||
{ 92, 1, 4, 5, { 0 }},
|
||||
{ 93, 1, 4, 7, { 0 }},
|
||||
{ 94, 1, 4, 7, { 0 }},
|
||||
{ 95, 0, 14, 5, { 0 }},
|
||||
{ 96, 1, 4, 5, { 0 }},
|
||||
{ 97, 1, 6, 7, { 0 }},
|
||||
{ 98, 1, 4, 7, { 0 }},
|
||||
{ 99, 1, 6, 7, { 0 }},
|
||||
{ 100, 1, 4, 7, { 0 }},
|
||||
{ 101, 1, 6, 7, { 0 }},
|
||||
{ 102, 1, 4, 6, { 0 }},
|
||||
{ 103, 1, 6, 7, { 0 }},
|
||||
{ 104, 1, 4, 7, { 0 }},
|
||||
{ 105, 2, 4, 5, { 0 }},
|
||||
{ 106, 1, 4, 7, { 0 }},
|
||||
{ 107, 1, 4, 7, { 0 }},
|
||||
{ 108, 2, 4, 5, { 0 }},
|
||||
{ 109, 1, 6, 9, { 0 }},
|
||||
{ 110, 1, 6, 7, { 0 }},
|
||||
{ 111, 1, 6, 7, { 0 }},
|
||||
{ 112, 1, 6, 7, { 0 }},
|
||||
{ 113, 1, 6, 7, { 0 }},
|
||||
{ 114, 1, 6, 7, { 0 }},
|
||||
{ 115, 1, 6, 7, { 0 }},
|
||||
{ 116, 1, 5, 6, { 0 }},
|
||||
{ 117, 1, 6, 7, { 0 }},
|
||||
{ 118, 1, 6, 7, { 0 }},
|
||||
{ 119, 1, 6, 9, { 0 }},
|
||||
{ 120, 1, 6, 7, { 0 }},
|
||||
{ 121, 1, 6, 7, { 0 }},
|
||||
{ 122, 1, 6, 7, { 0 }},
|
||||
{ 123, 2, 4, 7, { 0 }},
|
||||
{ 124, 2, 4, 5, { 0 }},
|
||||
{ 125, 1, 4, 7, { 0 }},
|
||||
{ 126, 1, 4, 8, { 0 }},
|
||||
{ 161, 2, 6, 5, { 0 }},
|
||||
{ 162, 1, 4, 7, { 0 }},
|
||||
{ 163, 1, 4, 8, { 0 }},
|
||||
{ 8364, 1, 4, 8, { 0 }},
|
||||
{ 165, 1, 4, 7, { 0 }},
|
||||
{ 352, 1, 1, 7, { 0 }},
|
||||
{ 167, 2, 4, 9, { 0 }},
|
||||
{ 353, 1, 3, 7, { 0 }},
|
||||
{ 169, 1, 4, 9, { 0 }},
|
||||
{ 170, 2, 4, 9, { 0 }},
|
||||
{ 171, 1, 6, 8, { 0 }},
|
||||
{ 172, 1, 8, 7, { 0 }},
|
||||
{ 174, 1, 4, 9, { 0 }},
|
||||
{ 175, 2, 4, 9, { 0 }},
|
||||
{ 176, 1, 4, 6, { 0 }},
|
||||
{ 177, 1, 6, 7, { 0 }},
|
||||
{ 178, 2, 4, 9, { 0 }},
|
||||
{ 179, 2, 4, 9, { 0 }},
|
||||
{ 381, 1, 1, 7, { 0 }},
|
||||
{ 181, 1, 6, 7, { 0 }},
|
||||
{ 182, 1, 4, 9, { 0 }},
|
||||
{ 183, 2, 8, 5, { 0 }},
|
||||
{ 382, 1, 3, 7, { 0 }},
|
||||
{ 185, 2, 4, 9, { 0 }},
|
||||
{ 186, 2, 4, 9, { 0 }},
|
||||
{ 187, 1, 6, 8, { 0 }},
|
||||
{ 338, 1, 4, 11, { 0 }},
|
||||
{ 339, 1, 6, 11, { 0 }},
|
||||
{ 376, 1, 2, 7, { 0 }},
|
||||
{ 191, 1, 6, 7, { 0 }},
|
||||
{ 192, 1, 1, 7, { 0 }},
|
||||
{ 193, 1, 1, 7, { 0 }},
|
||||
{ 194, 1, 1, 7, { 0 }},
|
||||
{ 195, 1, 1, 7, { 0 }},
|
||||
{ 196, 1, 2, 7, { 0 }},
|
||||
{ 197, 1, 0, 7, { 0 }},
|
||||
{ 198, 1, 4, 11, { 0 }},
|
||||
{ 199, 1, 4, 7, { 0 }},
|
||||
{ 200, 1, 1, 7, { 0 }},
|
||||
{ 201, 1, 1, 7, { 0 }},
|
||||
{ 202, 1, 1, 7, { 0 }},
|
||||
{ 203, 1, 2, 7, { 0 }},
|
||||
{ 204, 1, 1, 5, { 0 }},
|
||||
{ 205, 2, 1, 5, { 0 }},
|
||||
{ 206, 1, 1, 5, { 0 }},
|
||||
{ 207, 1, 2, 5, { 0 }},
|
||||
{ 208, 0, 4, 7, { 0 }},
|
||||
{ 209, 1, 1, 7, { 0 }},
|
||||
{ 210, 1, 1, 7, { 0 }},
|
||||
{ 211, 1, 1, 7, { 0 }},
|
||||
{ 212, 1, 1, 7, { 0 }},
|
||||
{ 213, 1, 1, 7, { 0 }},
|
||||
{ 214, 1, 2, 7, { 0 }},
|
||||
{ 215, 1, 6, 7, { 0 }},
|
||||
{ 216, 0, 4, 7, { 0 }},
|
||||
{ 217, 1, 1, 7, { 0 }},
|
||||
{ 218, 1, 1, 7, { 0 }},
|
||||
{ 219, 1, 1, 7, { 0 }},
|
||||
{ 220, 1, 2, 7, { 0 }},
|
||||
{ 221, 1, 1, 7, { 0 }},
|
||||
{ 222, 1, 4, 7, { 0 }},
|
||||
{ 223, 1, 4, 7, { 0 }},
|
||||
{ 224, 1, 3, 7, { 0 }},
|
||||
{ 225, 1, 3, 7, { 0 }},
|
||||
{ 226, 1, 3, 7, { 0 }},
|
||||
{ 227, 1, 3, 7, { 0 }},
|
||||
{ 228, 1, 4, 7, { 0 }},
|
||||
{ 229, 1, 2, 7, { 0 }},
|
||||
{ 230, 1, 6, 11, { 0 }},
|
||||
{ 231, 1, 6, 7, { 0 }},
|
||||
{ 232, 1, 3, 7, { 0 }},
|
||||
{ 233, 1, 3, 7, { 0 }},
|
||||
{ 234, 1, 3, 7, { 0 }},
|
||||
{ 235, 1, 4, 7, { 0 }},
|
||||
{ 236, 1, 3, 5, { 0 }},
|
||||
{ 237, 2, 3, 5, { 0 }},
|
||||
{ 238, 1, 3, 5, { 0 }},
|
||||
{ 239, 1, 4, 5, { 0 }},
|
||||
{ 240, 1, 4, 7, { 0 }},
|
||||
{ 241, 1, 3, 7, { 0 }},
|
||||
{ 242, 1, 3, 7, { 0 }},
|
||||
{ 243, 1, 3, 7, { 0 }},
|
||||
{ 244, 1, 3, 7, { 0 }},
|
||||
{ 245, 1, 3, 7, { 0 }},
|
||||
{ 246, 1, 4, 7, { 0 }},
|
||||
{ 247, 1, 6, 7, { 0 }},
|
||||
{ 248, 0, 6, 7, { 0 }},
|
||||
{ 249, 1, 3, 7, { 0 }},
|
||||
{ 250, 1, 3, 7, { 0 }},
|
||||
{ 251, 1, 3, 7, { 0 }},
|
||||
{ 252, 1, 4, 7, { 0 }},
|
||||
{ 253, 1, 3, 7, { 0 }},
|
||||
{ 254, 1, 4, 7, { 0 }},
|
||||
{ 255, 1, 4, 7, { 0 }},
|
||||
};
|
||||
|
||||
// Style loading function: Dark
|
||||
static void GuiLoadStyleDark(void)
|
||||
{
|
||||
// Load style properties provided
|
||||
// NOTE: Default properties are propagated
|
||||
for (int i = 0; i < DARK_STYLE_PROPS_COUNT; i++)
|
||||
{
|
||||
GuiSetStyle(darkStyleProps[i].controlId, darkStyleProps[i].propertyId, darkStyleProps[i].propertyValue);
|
||||
}
|
||||
|
||||
// Custom font loading
|
||||
// NOTE: Compressed font image data (DEFLATE), it requires DecompressData() function
|
||||
int darkFontDataSize = 0;
|
||||
unsigned char *data = DecompressData(darkFontData, DARK_STYLE_FONT_ATLAS_COMP_SIZE, &darkFontDataSize);
|
||||
Image imFont = { data, 512, 256, 1, 2 };
|
||||
|
||||
Font font = { 0 };
|
||||
font.baseSize = 16;
|
||||
font.glyphCount = 189;
|
||||
|
||||
// Load texture from image
|
||||
font.texture = LoadTextureFromImage(imFont);
|
||||
UnloadImage(imFont); // Uncompressed image data can be unloaded from memory
|
||||
|
||||
// Copy char recs data from global fontRecs
|
||||
// NOTE: Required to avoid issues if trying to free font
|
||||
font.recs = (Rectangle *)RAYGUI_MALLOC(font.glyphCount*sizeof(Rectangle));
|
||||
memcpy(font.recs, darkFontRecs, font.glyphCount*sizeof(Rectangle));
|
||||
|
||||
// Copy font char info data from global fontChars
|
||||
// NOTE: Required to avoid issues if trying to free font
|
||||
font.glyphs = (GlyphInfo *)RAYGUI_MALLOC(font.glyphCount*sizeof(GlyphInfo));
|
||||
memcpy(font.glyphs, darkFontGlyphs, font.glyphCount*sizeof(GlyphInfo));
|
||||
|
||||
GuiSetFont(font);
|
||||
|
||||
// Setup a white rectangle on the font to be used on shapes drawing,
|
||||
// it makes possible to draw shapes and text (full UI) in a single draw call
|
||||
Rectangle fontWhiteRec = { 510, 254, 1, 1 };
|
||||
SetShapesTexture(font.texture, fontWhiteRec);
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
// TODO: Custom user style setup: Set specific properties here (if required)
|
||||
// i.e. Controls specific BORDER_WIDTH, TEXT_PADDING, TEXT_ALIGNMENT
|
||||
}
|
9
includes/raygui_helpers.hpp
Normal file
9
includes/raygui_helpers.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef _RAYGUI_HELPERS_HPP
|
||||
#define _RAYGUI_HELPERS_HPP
|
||||
#include <string>
|
||||
|
||||
/* Display the given text, centered on the screen, as a label.
|
||||
NEEDS RAYGUI LIBRARY. */
|
||||
void display_text_centered(std::string to_disp);
|
||||
|
||||
#endif
|
@@ -1,8 +0,0 @@
|
||||
#ifndef _MATH_HELP
|
||||
#define _MATH_HELP
|
||||
int signum(int num) {
|
||||
int retval = 0;
|
||||
(num > 0) ? retval = 1 : retval = -1;
|
||||
return retval;
|
||||
}
|
||||
#endif
|
@@ -2,7 +2,7 @@
|
||||
#define _SOCK_CLASS
|
||||
|
||||
#include <string>
|
||||
#ifdef __unix__
|
||||
#if defined(__unix__) || defined(__unix) ||(defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
|
30
includes/timer.h
Normal file
30
includes/timer.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef _TIMER_H
|
||||
#define _TIMER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* This file defines a simple timer Types, and declares functions to initialize it,
|
||||
and keep track of time elapsed. The actual definition of the Timer struct is in timer.c
|
||||
It was copied from https://github.com/raysan5/raylib/wiki/Frequently-Asked-Questions#how-do-i-make-a-timer */
|
||||
|
||||
typedef struct Timer_s {
|
||||
double start_time; // Start time (seconds)
|
||||
double lifetime; // Lifetime (seconds)
|
||||
} Timer;
|
||||
|
||||
/* Starts a timer for given number of seconds */
|
||||
Timer timer_init(double lifetime_secs);
|
||||
|
||||
/* Returns true when timer finishes, false if not */
|
||||
bool timer_done(Timer timer);
|
||||
|
||||
/* Returns amount of time elapsed since start of timer */
|
||||
double timer_get_elapsed(Timer timer);
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
158
main.cpp
158
main.cpp
@@ -19,15 +19,21 @@
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include "includes/raylib-cpp/raylib-cpp.hpp"
|
||||
|
||||
#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/client.hpp"
|
||||
#include "includes/server.hpp"
|
||||
#include "includes/exception_consts.hpp"
|
||||
#include "includes/check_input.hpp"
|
||||
#include "includes/raygui_helpers.hpp"
|
||||
#include "includes/easysock.h"
|
||||
#include "includes/serialization.h"
|
||||
#include "includes/timer.h"
|
||||
|
||||
/* Global variables used to instantiate structs */
|
||||
const int WIDTH = 1500;
|
||||
@@ -38,21 +44,15 @@ const int PADDLE_SPEED = 8;
|
||||
const int CIRC_RAD = 10;
|
||||
const float BASE_BOUNCE_DEG = 45;
|
||||
const float BASE_BOUNCE_RAD = (BASE_BOUNCE_DEG / 180.0) * M_PI;
|
||||
const float BASE_SPEED_COMPONENTS = 18;
|
||||
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 */
|
||||
@@ -153,7 +153,8 @@ GameType check_server_client(int argc, char** argv) {
|
||||
std::cout << "Waiting for connection..." << std::endl;
|
||||
std::string response = "";
|
||||
char* temp_response = NULL;
|
||||
/* Wait for the right client to connect. Since recvAll returns a char*, we need to create a temporary variable to check for NULL. */
|
||||
/* Wait for the right client to connect. Since recvAll returns a char*, we need to create a temporary variable to check for NULL.
|
||||
TODO - Check that the client actually sends 'GG'. */
|
||||
do {
|
||||
temp_response = server->recvAll();
|
||||
} while (temp_response == NULL);
|
||||
@@ -217,6 +218,129 @@ 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);
|
||||
|
||||
/* 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(150, 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 || ((strlen(ip_text) == 0) || (strlen(port_text) == 0))) {
|
||||
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();
|
||||
}
|
||||
|
||||
try {
|
||||
type = check_server(ip_text, port_text);
|
||||
} catch (std::invalid_argument& inv) {
|
||||
display_text_centered(std::string(inv.what()) + "\nClosing game...");
|
||||
Timer timer = timer_init(2); // Wait for two seconds
|
||||
while (!timer_done(timer));
|
||||
CloseWindow(); // Close and exit
|
||||
return -1;
|
||||
}
|
||||
free(ip_text);
|
||||
free(port_text);
|
||||
}
|
||||
|
||||
if (selected_item == M_CLIENT) {
|
||||
button_pressed = false; // Whether submit button is pressed
|
||||
char* code_text = (char *)calloc(150, sizeof(char)); // Holds the connect code
|
||||
const char* code_label = "Enter code:";
|
||||
bool editing_code = false; // Indicates whether the port text box is being edited
|
||||
while (button_pressed == false || ((strlen(code_text) == 0))) {
|
||||
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}, code_label);
|
||||
|
||||
if (GuiTextBox(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2) - (HEIGHT/6), box_size.x, box_size.y}, code_text, 100, editing_code)) {
|
||||
editing_code = !editing_code;
|
||||
}
|
||||
|
||||
button_pressed = GuiButton(Rectangle{(WIDTH/2) - (box_size.x/2), (HEIGHT/2) + (HEIGHT/6), box_size.x, box_size.y}, "Connect");
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
type = check_client(code_text);
|
||||
free(code_text);
|
||||
}
|
||||
}
|
||||
|
||||
/* Variable to store the response given by the other player */
|
||||
std::string response;
|
||||
Serial_Data response_data;
|
||||
@@ -233,6 +357,7 @@ int main(int argc, char** argv) {
|
||||
Ball ball = Ball(window.GetWidth()/2, window.GetHeight()/2, CIRC_RAD, BASE_SPEED, 0);
|
||||
|
||||
window.BeginDrawing();
|
||||
window.ClearBackground(BLACK);
|
||||
pad1.draw();
|
||||
pad2.draw();
|
||||
ball.draw();
|
||||
@@ -281,7 +406,6 @@ int main(int argc, char** argv) {
|
||||
uint8_t* response_array = (uint8_t *)(type.netsock->recvAll());
|
||||
if (response_array != NULL) {
|
||||
response_data = Serial_deserialize(response_array);
|
||||
std::cout << response_data.pad_x << "\t" << response_data.pad_y << "\t" << response_data.ball_x << "\t" << response_data.ball_y << std::endl;
|
||||
} else {
|
||||
/* If the response is NULL, that means it timed-out. In this case, there's no value to print */
|
||||
std::cout << "NOTHING RECEIVED" << std::endl;
|
||||
|
28
meson.build
28
meson.build
@@ -1,21 +1,25 @@
|
||||
project('Pong', ['cpp', 'c'], version: '0.1')
|
||||
add_global_arguments('-g', '-Wall', '-pedantic', '-Wno-unused-function', language : ['cpp', 'c'])
|
||||
add_global_arguments('-g', '-Wall', '-pedantic', '-Wno-unused-function', '-Wno-narrowing', language : ['cpp', 'c'])
|
||||
add_global_arguments('-std=c++11', language: ['cpp'])
|
||||
compiler = meson.get_compiler('cpp')
|
||||
cmake = import('cmake')
|
||||
|
||||
# if we are building a shared library
|
||||
if get_option('default_library') == 'shared'
|
||||
raylib = dependency('raylib', required: false) # Try to find dependency with pkg-config
|
||||
if not raylib.found()
|
||||
raylib = compiler.find_library('raylib', has_headers: ['raylib.h', 'raymath.h'], required: true) # Try to manually search for the dependency
|
||||
raylib = compiler.find_library('raylib', has_headers: ['raylib.h', 'raymath.h'], required: false) # Try to manually search for the dependency
|
||||
endif
|
||||
if not raylib.found()
|
||||
opt_var = cmake.subproject_options()
|
||||
opt_var.add_cmake_defines({'BUILD_SHARED_LIBS' : true})
|
||||
opt_var.add_cmake_defines({'CMAKE_SKIP_RPATH' : true})
|
||||
raylib_proj = cmake.subproject('raylib', options: opt_var)
|
||||
raylib = raylib_proj.dependency('raylib')
|
||||
endif
|
||||
# if not raylib.found()
|
||||
# opt_var = cmake.subproject_options()
|
||||
# opt_var.add_cmake_defines({'BUILD_SHARED_LIBS' : true})
|
||||
# opt_var.add_cmake_defines({'CMAKE_SKIP_RPATH' : true})
|
||||
# raylib_proj = cmake.subproject('raylib', options: opt_var)
|
||||
# raylib = raylib_proj.dependency('raylib')
|
||||
# endif
|
||||
endif
|
||||
|
||||
# I we are building a static library
|
||||
if get_option('default_library') == 'static'
|
||||
raylib_proj = cmake.subproject('raylib')
|
||||
raylib = raylib_proj.dependency('raylib')
|
||||
@@ -29,8 +33,8 @@ if build_machine.system() == 'windows'
|
||||
|
||||
endif
|
||||
|
||||
executable('pong',
|
||||
'main.cpp', 'easysock.cpp', 'sock.cpp','paddle.cpp', 'ball.cpp', 'numeric_base.cpp', 'connect_code.cpp', 'server.cpp', 'client.cpp',
|
||||
'serialization.c',
|
||||
executable('pong',
|
||||
'main.cpp', 'sock.cpp','paddle.cpp', 'ball.cpp', 'numeric_base.cpp', 'connect_code.cpp', 'server.cpp', 'client.cpp', 'check_input.cpp', 'raygui_helpers.cpp',
|
||||
'serialization.c', 'timer.c', 'easysock.c',
|
||||
dependencies: [raylib, ws2_dep, winmm]
|
||||
)
|
||||
|
@@ -26,12 +26,17 @@ unsigned int to_decimal(std::string num, int from_base) {
|
||||
std::string from_decimal(unsigned int num, int to_base) {
|
||||
std::string return_val;
|
||||
int val = 0;
|
||||
while (num > 0) {
|
||||
val = num % to_base;
|
||||
return_val.push_back(possible_chars[val]);
|
||||
num /= to_base;
|
||||
/* Handle the special case of num being zero: In this case, the result is also zero */
|
||||
if (num == 0) {
|
||||
return_val = "0";
|
||||
} else {
|
||||
while (num > 0) {
|
||||
val = num % to_base;
|
||||
return_val.push_back(possible_chars[val]);
|
||||
num /= to_base;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Reverse the string, since we started from the right */
|
||||
std::reverse(return_val.begin(), return_val.end());
|
||||
|
||||
|
13
raygui_helpers.cpp
Normal file
13
raygui_helpers.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "includes/raygui_helpers.hpp"
|
||||
#include "includes/raygui/raygui.h"
|
||||
|
||||
void display_text_centered(std::string to_disp) {
|
||||
const char* to_disp_cstr = to_disp.c_str();
|
||||
Vector2 label_size = MeasureTextEx(GetFontDefault(), to_disp_cstr, GuiGetStyle(DEFAULT, TEXT_SIZE)+1, GuiGetStyle(DEFAULT, TEXT_SPACING)+1); // The '+1' is there to account for any rounding errors
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(BLACK);
|
||||
GuiLabel(Rectangle{(GetScreenWidth()/2) - (label_size.x/2), (GetScreenHeight()/2) - (label_size.y/2), label_size.x, label_size.y}, to_disp_cstr);
|
||||
EndDrawing();
|
||||
return;
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#ifdef __unix__
|
||||
#if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#ifdef __unix__
|
||||
#if defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
@@ -8,8 +8,8 @@
|
||||
#include "includes/sock.hpp"
|
||||
#include "includes/server.hpp"
|
||||
#include "includes/exception_consts.hpp"
|
||||
#include "includes/easysock.hpp"
|
||||
#include "includes/connect_code.hpp"
|
||||
#include "includes/easysock.h"
|
||||
|
||||
/* Destructor - closes any open sockets */
|
||||
Server::~Server() {
|
||||
|
2
sock.cpp
2
sock.cpp
@@ -2,7 +2,7 @@
|
||||
#include <stdexcept>
|
||||
#include "includes/sock.hpp"
|
||||
#include "includes/exception_consts.hpp"
|
||||
#include "includes/easysock.hpp"
|
||||
#include "includes/easysock.h"
|
||||
|
||||
/* Function to create socket. This function doesn't actually create a socket
|
||||
(and isn't meant to be called directly). Instead, the client and server classes
|
||||
|
19
timer.c
Normal file
19
timer.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <stdbool.h>
|
||||
#include "includes/timer.h"
|
||||
#include "includes/raygui/raygui.h"
|
||||
|
||||
Timer timer_init(double lifetime_secs) {
|
||||
Timer timer;
|
||||
timer.start_time = GetTime();
|
||||
timer.lifetime = lifetime_secs;
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
bool timer_done(Timer timer) {
|
||||
return GetTime() - timer.start_time >= timer.lifetime;
|
||||
}
|
||||
|
||||
double timer_get_elapsed(Timer timer) {
|
||||
return GetTime() - timer.start_time;
|
||||
}
|
15
todo.txt
15
todo.txt
@@ -1,2 +1,13 @@
|
||||
3. Try to make the ball go between screens.
|
||||
8. Have both client and server send a message if the game is quit.
|
||||
1. Try to make the ball go between screens.
|
||||
2. ----SHOULD BE DONE---- Add code to zip the dist/ folder inside the release_build script.
|
||||
3. Sign Windows executable, to remove 'Unknown Publisher' warnings.
|
||||
4. Create and publish statically-linked Linux binary, and create a build script for packaging it.
|
||||
5. Figure out how to build statically-linked Mac binary, and create a build script for packaging it.
|
||||
6. ----IN PROGRESS---- Figure out how to input game mode and (if applicable) IP address and port through the GUI, instead of the command-line.
|
||||
7. Clean up / refactor the raygui code in main.cpp, that asks user for game mode. Instead of just having a giant blob of code in main.cpp, maybe split it into a function, or move it to another file. It should be easy to split it into a different function, since none of the functions take any specific parameters. The text box function, for example, only takes in the rectangle coordinates, and the text to display. I can move the code to a function, and then pass in any parameters that I need to pass in (I don't think I need to pass many parameters, though).
|
||||
8. Allow the user to quit before the game actually starts i.e. while they are inputting the game mode.
|
||||
9. Add better error checking in check_server and check_client functions in check_input.cpp.
|
||||
10. Add 'install' target to Meson, to allow the user to install the game. This should also copy the .so files to the right locations.
|
||||
11. Allow the user to specify which paddle they want to control, in multi-player mode.
|
||||
12. Add IPv6 support for the server and client sockets (and everything that goes along with it, such as error handling for IP addresses).
|
||||
13. Figure out how to make 'tar' not include the entire directory structure, when creating the archive in create_static_linux.sh.
|
||||
|
Reference in New Issue
Block a user