mirror of
https://github.com/Tha14/toxic.git
synced 2024-12-22 17:43:25 +01:00
Refactor game window sizing
- Add large square and rectangle window types - Remove forced small windows - Fit game of life to largest possible window type - Hide cursor in game of life when game is running
This commit is contained in:
parent
5e67571908
commit
4514ecd839
@ -179,12 +179,6 @@ void cmd_game_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
bool force_small = false;
|
||||
|
||||
if (argc >= 2) {
|
||||
force_small = strcasecmp(argv[2], "small") == 0;
|
||||
}
|
||||
|
||||
if (!Friends.list[self->num].game_invite.pending) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending game invite.");
|
||||
return;
|
||||
@ -200,7 +194,7 @@ void cmd_game_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
uint8_t *data = Friends.list[self->num].game_invite.data;
|
||||
size_t length = Friends.list[self->num].game_invite.data_length;
|
||||
|
||||
int ret = game_initialize(self, m, type, id, data, length, force_small);
|
||||
int ret = game_initialize(self, m, type, id, data, length);
|
||||
|
||||
switch (ret) {
|
||||
case 0: {
|
||||
|
@ -55,17 +55,17 @@ extern struct user_settings *user_settings;
|
||||
|
||||
|
||||
/* Determines if window is large enough for a respective window type */
|
||||
#define WINDOW_SIZE_LARGE_SQUARE_VALID(max_x, max_y)((((max_y) - 4) >= (GAME_MAX_SQUARE_Y))\
|
||||
&& ((max_x) >= (GAME_MAX_SQUARE_X)))
|
||||
#define WINDOW_SIZE_SQUARE_VALID(max_x, max_y)((((max_y) - 4) >= (GAME_MAX_SQUARE_Y_DEFAULT))\
|
||||
&& ((max_x) >= (GAME_MAX_SQUARE_X_DEFAULT)))
|
||||
|
||||
#define WINDOW_SIZE_SMALL_SQUARE_VALID(max_x, max_y)((((max_y) - 4) >= (GAME_MAX_SQUARE_Y_SMALL))\
|
||||
&& ((max_x) >= (GAME_MAX_SQUARE_X_SMALL)))
|
||||
#define WINDOW_SIZE_LARGE_SQUARE_VALID(max_x, max_y)((((max_y) - 4) >= (GAME_MAX_SQUARE_Y_LARGE))\
|
||||
&& ((max_x) >= (GAME_MAX_SQUARE_X_LARGE)))
|
||||
|
||||
#define WINDOW_SIZE_LARGE_RECT_VALID(max_x, max_y)((((max_y) - 4) >= (GAME_MAX_RECT_Y))\
|
||||
&& ((max_x) >= (GAME_MAX_RECT_X)))
|
||||
#define WINDOW_SIZE_RECT_VALID(max_x, max_y)((((max_y) - 4) >= (GAME_MAX_RECT_Y_DEFAULT))\
|
||||
&& ((max_x) >= (GAME_MAX_RECT_X_DEFAULT)))
|
||||
|
||||
#define WINDOW_SIZE_SMALL_RECT_VALID(max_x, max_y)((((max_y) - 4) >= (GAME_MAX_RECT_Y_SMALL))\
|
||||
&& ((max_x) >= (GAME_MAX_RECT_X_SMALL)))
|
||||
#define WINDOW_SIZE_LARGE_RECT_VALID(max_x, max_y)((((max_y) - 4) >= (GAME_MAX_RECT_Y_LARGE))\
|
||||
&& ((max_x) >= (GAME_MAX_RECT_X_LARGE)))
|
||||
|
||||
|
||||
static ToxWindow *game_new_window(Tox *m, GameType type, uint32_t friendnumber);
|
||||
@ -229,7 +229,7 @@ static int game_initialize_type(GameData *game, const uint8_t *data, size_t leng
|
||||
}
|
||||
|
||||
int game_initialize(const ToxWindow *parent, Tox *m, GameType type, uint32_t id, const uint8_t *multiplayer_data,
|
||||
size_t length, bool force_small_window)
|
||||
size_t length)
|
||||
{
|
||||
int max_x;
|
||||
int max_y;
|
||||
@ -237,22 +237,6 @@ int game_initialize(const ToxWindow *parent, Tox *m, GameType type, uint32_t id,
|
||||
|
||||
max_y -= (CHATBOX_HEIGHT + WINDOW_BAR_HEIGHT);
|
||||
|
||||
int max_game_window_x = GAME_MAX_SQUARE_X;
|
||||
int max_game_window_y = GAME_MAX_SQUARE_Y;
|
||||
|
||||
if (!force_small_window && !WINDOW_SIZE_LARGE_SQUARE_VALID(max_x, max_y)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (force_small_window) {
|
||||
max_game_window_x = GAME_MAX_SQUARE_X_SMALL;
|
||||
max_game_window_y = GAME_MAX_SQUARE_Y_SMALL;
|
||||
|
||||
if (!WINDOW_SIZE_SMALL_SQUARE_VALID(max_x, max_y)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ToxWindow *self = game_new_window(m, type, parent->num);
|
||||
|
||||
if (self == NULL) {
|
||||
@ -287,8 +271,6 @@ int game_initialize(const ToxWindow *parent, Tox *m, GameType type, uint32_t id,
|
||||
|
||||
game->tox = m;
|
||||
game->window_shape = GW_ShapeSquare;
|
||||
game->game_max_x = max_game_window_x;
|
||||
game->game_max_y = max_game_window_y;
|
||||
game->parent_max_x = max_x;
|
||||
game->parent_max_y = max_y;
|
||||
game->update_interval = GAME_DEFAULT_UPDATE_INTERVAL;
|
||||
@ -327,28 +309,53 @@ int game_set_window_shape(GameData *game, GameWindowShape shape)
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (shape == game->window_shape) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shape == GW_ShapeSquare) {
|
||||
game->game_max_x = GAME_MAX_SQUARE_X;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int max_x = game->parent_max_x;
|
||||
const int max_y = game->parent_max_y;
|
||||
|
||||
if (WINDOW_SIZE_LARGE_RECT_VALID(max_x, max_y)) {
|
||||
game->game_max_x = GAME_MAX_RECT_X;
|
||||
game->game_max_y = GAME_MAX_RECT_Y;
|
||||
return 0;
|
||||
}
|
||||
switch (shape) {
|
||||
case GW_ShapeSquare: {
|
||||
if (WINDOW_SIZE_SQUARE_VALID(max_x, max_y)) {
|
||||
game->game_max_x = GAME_MAX_SQUARE_X_DEFAULT;
|
||||
game->game_max_y = GAME_MAX_SQUARE_Y_DEFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (WINDOW_SIZE_SMALL_RECT_VALID(max_x, max_y)) {
|
||||
game->game_max_x = GAME_MAX_RECT_X_SMALL;
|
||||
game->game_max_y = GAME_MAX_RECT_Y_SMALL;
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case GW_ShapeSquareLarge: {
|
||||
if (WINDOW_SIZE_LARGE_SQUARE_VALID(max_x, max_y)) {
|
||||
game->game_max_x = GAME_MAX_SQUARE_X_LARGE;
|
||||
game->game_max_y = GAME_MAX_SQUARE_Y_LARGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GW_ShapeRectangle: {
|
||||
if (WINDOW_SIZE_RECT_VALID(max_x, max_y)) {
|
||||
game->game_max_x = GAME_MAX_RECT_X_DEFAULT;
|
||||
game->game_max_y = GAME_MAX_RECT_Y_DEFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GW_ShapeRectangleLarge: {
|
||||
if (WINDOW_SIZE_LARGE_RECT_VALID(max_x, max_y)) {
|
||||
game->game_max_x = GAME_MAX_RECT_X_LARGE;
|
||||
game->game_max_y = GAME_MAX_RECT_Y_LARGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
@ -33,21 +33,22 @@
|
||||
|
||||
#define GAME_BORDER_COLOUR BAR_TEXT
|
||||
|
||||
/* Max size of a default size square game window */
|
||||
#define GAME_MAX_SQUARE_Y 26
|
||||
#define GAME_MAX_SQUARE_X (GAME_MAX_SQUARE_Y * 2)
|
||||
|
||||
/* Max size of a small square game window */
|
||||
#define GAME_MAX_SQUARE_Y_SMALL 18
|
||||
#define GAME_MAX_SQUARE_X_SMALL (GAME_MAX_SQUARE_Y_SMALL * 2)
|
||||
/* Max size of a default square game window */
|
||||
#define GAME_MAX_SQUARE_Y_DEFAULT 26
|
||||
#define GAME_MAX_SQUARE_X_DEFAULT (GAME_MAX_SQUARE_Y_DEFAULT * 2)
|
||||
|
||||
/* Max size of a large square game window */
|
||||
#define GAME_MAX_SQUARE_Y_LARGE 52
|
||||
#define GAME_MAX_SQUARE_X_LARGE (GAME_MAX_SQUARE_Y_LARGE * 2)
|
||||
|
||||
/* Max size of a default size rectangle game window */
|
||||
#define GAME_MAX_RECT_Y 24
|
||||
#define GAME_MAX_RECT_X (GAME_MAX_RECT_Y * 4)
|
||||
#define GAME_MAX_RECT_Y_DEFAULT 24
|
||||
#define GAME_MAX_RECT_X_DEFAULT (GAME_MAX_RECT_Y_DEFAULT * 4)
|
||||
|
||||
/* Max size of a small rectangle game window */
|
||||
#define GAME_MAX_RECT_Y_SMALL 14
|
||||
#define GAME_MAX_RECT_X_SMALL (GAME_MAX_RECT_Y_SMALL * 4)
|
||||
/* Max size of a large rectangle game window */
|
||||
#define GAME_MAX_RECT_Y_LARGE 52
|
||||
#define GAME_MAX_RECT_X_LARGE (GAME_MAX_RECT_Y_LARGE * 4)
|
||||
|
||||
/* Maximum length of a game message set with game_set_message() */
|
||||
#define GAME_MAX_MESSAGE_SIZE 64
|
||||
@ -56,7 +57,7 @@
|
||||
#define GAME_MESSAGE_DEFAULT_TIMEOUT 3
|
||||
|
||||
|
||||
/***** NETWORKING CONSTANTS *****/
|
||||
/***** START NETWORKING CONSTANTS *****/
|
||||
|
||||
/* Header starts after custom packet type byte. Comprised of: NetworkVersion (1b) + GameType (1b) + id (4b) */
|
||||
#define GAME_PACKET_HEADER_SIZE (1 + 1 + sizeof(uint32_t))
|
||||
@ -70,6 +71,9 @@
|
||||
/* Current version of networking protocol */
|
||||
#define GAME_NETWORKING_VERSION 0x01
|
||||
|
||||
/***** END NETWORKING CONSTANTS *****/
|
||||
|
||||
|
||||
typedef void cb_game_update_state(GameData *game, void *cb_data);
|
||||
typedef void cb_game_render_window(GameData *game, WINDOW *window, void *cb_data);
|
||||
typedef void cb_game_kill(GameData *game, void *cb_data);
|
||||
@ -84,7 +88,9 @@ typedef enum GamePacketType {
|
||||
|
||||
typedef enum GameWindowShape {
|
||||
GW_ShapeSquare = 0u,
|
||||
GW_ShapeSquareLarge,
|
||||
GW_ShapeRectangle,
|
||||
GW_ShapeRectangleLarge,
|
||||
GW_ShapeInvalid,
|
||||
} GameWindowShape;
|
||||
|
||||
@ -210,8 +216,6 @@ void game_set_cb_on_packet(GameData *game, cb_game_on_packet *func, void *cb_dat
|
||||
* `id` should be a unique integer to indentify the game instance. If we're being invited to a game
|
||||
* this identifier should be sent via the invite packet.
|
||||
*
|
||||
* `force_small_window` will make the game window small.
|
||||
*
|
||||
* if `multiplayer_data` is non-null this indicates that we accepted a game invite from a contact.
|
||||
* The data contains any information we need to initialize the game state.
|
||||
*
|
||||
@ -222,12 +226,12 @@ void game_set_cb_on_packet(GameData *game, cb_game_on_packet *func, void *cb_dat
|
||||
* Return -4 on other failure.
|
||||
*/
|
||||
int game_initialize(const ToxWindow *self, Tox *m, GameType type, uint32_t id, const uint8_t *multiplayer_data,
|
||||
size_t length, bool force_small_window);
|
||||
size_t length);
|
||||
|
||||
/*
|
||||
* Sets game window to `shape` and attempts to adjust size for best fit.
|
||||
* Sets game window to `shape`.
|
||||
*
|
||||
* This should be called in the game's initialize function.
|
||||
* This must be called on game initialization.
|
||||
*
|
||||
* Return 0 on success.
|
||||
* Return -1 if window is too small or shape is invalid.
|
||||
|
@ -33,7 +33,7 @@
|
||||
#define CENT_MUSHROOMS_POP_CONSTANT 35000
|
||||
|
||||
/* Max number of mushrooms */
|
||||
#define CENT_MUSHROOMS_LENGTH (GAME_MAX_SQUARE_X * GAME_MAX_SQUARE_Y)
|
||||
#define CENT_MUSHROOMS_LENGTH (GAME_MAX_SQUARE_X_DEFAULT * GAME_MAX_SQUARE_X_DEFAULT)
|
||||
|
||||
/* Max number of individual centipedes at any given time */
|
||||
#define CENT_MAX_NUM_HEADS 20
|
||||
@ -1714,6 +1714,7 @@ static int cent_init_state(GameData *game, CentState *state)
|
||||
|
||||
int centipede_initialize(GameData *game)
|
||||
{
|
||||
// note: If this changes we must update CENT_MUSHROOMS_LENGTH
|
||||
if (game_set_window_shape(game, GW_ShapeSquare) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1864,7 +1864,7 @@ static void chess_notify(const GameData *game, ChessPacketType type)
|
||||
}
|
||||
|
||||
case CHESS_PACKET_RESIGN: {
|
||||
msg = "Opponnet has resigned";
|
||||
msg = "Opponent has resigned";
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ typedef struct LifeState {
|
||||
TIME_MS time_last_cycle;
|
||||
size_t speed;
|
||||
size_t generation;
|
||||
bool paused;
|
||||
|
||||
Cell **cells;
|
||||
int num_columns;
|
||||
@ -321,7 +322,9 @@ void life_cb_render_window(GameData *game, WINDOW *win, void *cb_data)
|
||||
|
||||
move(state->curs_y, state->curs_x);
|
||||
|
||||
curs_set(1);
|
||||
if (state->generation == 0 || state->paused) {
|
||||
curs_set(1);
|
||||
}
|
||||
|
||||
life_draw_cells(game, win, state);
|
||||
}
|
||||
@ -478,6 +481,7 @@ void life_cb_on_keypress(GameData *game, int key, void *cb_data)
|
||||
|
||||
case '\t': {
|
||||
life_toggle_display_candy(state);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
@ -501,6 +505,17 @@ static void life_free_cells(LifeState *state)
|
||||
free(state->cells);
|
||||
}
|
||||
|
||||
void life_cb_pause(GameData *game, bool is_paused, void *cb_data)
|
||||
{
|
||||
if (!cb_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
LifeState *state = (LifeState *)cb_data;
|
||||
|
||||
state->paused = is_paused;
|
||||
}
|
||||
|
||||
void life_cb_kill(GameData *game, void *cb_data)
|
||||
{
|
||||
if (!cb_data) {
|
||||
@ -574,8 +589,15 @@ static int life_init_state(GameData *game, LifeState *state)
|
||||
|
||||
int life_initialize(GameData *game)
|
||||
{
|
||||
if (game_set_window_shape(game, GW_ShapeRectangle) == -1) {
|
||||
return -1;
|
||||
// Try best fit from largest to smallest before giving up
|
||||
if (game_set_window_shape(game, GW_ShapeRectangleLarge) == -1) {
|
||||
if (game_set_window_shape(game, GW_ShapeSquareLarge) == -1) {
|
||||
if (game_set_window_shape(game, GW_ShapeRectangle) == -1) {
|
||||
if (game_set_window_shape(game, GW_ShapeSquare) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LifeState *state = calloc(1, sizeof(LifeState));
|
||||
@ -596,6 +618,7 @@ int life_initialize(GameData *game)
|
||||
game_set_cb_update_state(game, life_cb_update_game_state, state);
|
||||
game_set_cb_render_window(game, life_cb_render_window, state);
|
||||
game_set_cb_on_keypress(game, life_cb_on_keypress, state);
|
||||
game_set_cb_on_pause(game, life_cb_pause, state);
|
||||
game_set_cb_kill(game, life_cb_kill, state);
|
||||
|
||||
return 0;
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include "game_snake.h"
|
||||
#include "misc_tools.h"
|
||||
|
||||
#define SNAKE_MAX_SNAKE_LENGTH (GAME_MAX_SQUARE_X * GAME_MAX_SQUARE_Y)
|
||||
#define SNAKE_AGENT_MAX_LIST_SIZE (GAME_MAX_SQUARE_X * GAME_MAX_SQUARE_Y)
|
||||
#define SNAKE_MAX_SNAKE_LENGTH (GAME_MAX_SQUARE_X_DEFAULT * GAME_MAX_SQUARE_Y_DEFAULT)
|
||||
#define SNAKE_AGENT_MAX_LIST_SIZE (GAME_MAX_SQUARE_X_DEFAULT * GAME_MAX_SQUARE_Y_DEFAULT)
|
||||
|
||||
#define SNAKE_DEFAULT_SNAKE_SPEED 6
|
||||
#define SNAKE_DEFAULT_AGENT_SPEED 1
|
||||
@ -850,6 +850,7 @@ static void snake_initialize_snake_head(const GameData *game, Snake *snake)
|
||||
|
||||
int snake_initialize(GameData *game)
|
||||
{
|
||||
// note: if this changes we must update SNAKE_MAX_SNAKE_LENGTH and SNAKE_AGENT_MAX_LIST_SIZE
|
||||
if (game_set_window_shape(game, GW_ShapeSquare) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -100,4 +100,3 @@ size_t game_util_pack_u32(uint8_t *bytes, uint32_t v);
|
||||
size_t game_util_unpack_u32(const uint8_t *bytes, uint32_t *v);
|
||||
|
||||
#endif // GAME_UTIL
|
||||
|
||||
|
@ -367,19 +367,8 @@ void cmd_game(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
return;
|
||||
}
|
||||
|
||||
bool force_small = false;
|
||||
|
||||
if (argc >= 2) {
|
||||
force_small = strcasecmp(argv[2], "small") == 0;
|
||||
|
||||
if (!force_small) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Unknown argument.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t id = rand();
|
||||
int ret = game_initialize(self, m, type, id, NULL, 0, force_small);
|
||||
int ret = game_initialize(self, m, type, id, NULL, 0);
|
||||
|
||||
switch (ret) {
|
||||
case 0: {
|
||||
@ -387,8 +376,7 @@ void cmd_game(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
}
|
||||
|
||||
case -1: {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0,
|
||||
"Window is too small. Try enlarging your window or re-running the command with the 'small' argument.");
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Window is too small.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user