diff --git a/CMakeLists.txt b/CMakeLists.txt index 2884e6b..ef204f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,8 @@ endif() find_path(CYAML_INCLUDE_DIR cyaml/cyaml.h) find_library(CYAML_LIBRARY cyaml) +add_subdirectory(states) + set(SOURCES kubo_file.c kubo_input.c @@ -42,6 +44,7 @@ set(SOURCES kubo_command.c kubo_camera.c main.c + ${STATES_SOURCES} ) add_executable(kubo ${SOURCES}) diff --git a/kubo_context.c b/kubo_context.c index d8f032a..3b5c7a6 100644 --- a/kubo_context.c +++ b/kubo_context.c @@ -24,11 +24,8 @@ static const struct kubo_context_state_data kubo_context_states[] = { {.id = KUBO_CONTEXT_WALL_NEW, .label = "Wall New", .color = GREEN}, {.id = KUBO_CONTEXT_WALL_SELECT, .label = "Wall Select", .color = BLUE}}; -static inline void wall_select_refresh(struct kubo_context *context); -static void select_next_wall(struct kubo_context *context); -static void select_prev_wall(struct kubo_context *context); - void kubo_context_init(struct kubo_context *context) { + if (!context) { return; } @@ -55,13 +52,16 @@ void kubo_context_set_state(struct kubo_context *context, case KUBO_CONTEXT_WALL_NEW: break; - case KUBO_CONTEXT_WALL_SELECT: - wall_select_refresh(context); - break; - default: break; } + + for (unsigned i = 0; i < kubo_state_data_length; i++) { + if (context->state.id == kubo_state_data[i].id && + kubo_state_data[i].data.state_entered != NULL) { + kubo_state_data[i].data.state_entered(context); + } + } } struct kubo_wall *kubo_context_get_pending_wall(struct kubo_context *context) { @@ -90,85 +90,11 @@ struct kubo_wall *kubo_context_get_pending_wall(struct kubo_context *context) { return wall; } -void kubo_context_delete_wall(struct kubo_context *context) { - if (context->state.id != KUBO_CONTEXT_WALL_SELECT || - !context->walls.count) { - return; - } - - kubo_wall_arr_del(&context->walls, context->wall_select_index); - select_next_wall(context); -} - -void kubo_context_input_up(struct kubo_context *context) { - switch (context->state.id) { - case KUBO_CONTEXT_WALL_SELECT: - select_next_wall(context); - break; - default: - break; - } -} - -void kubo_context_input_down(struct kubo_context *context) { - switch (context->state.id) { - case KUBO_CONTEXT_WALL_SELECT: - select_prev_wall(context); - break; - default: - break; - } -} - -void kubo_context_input_left(struct kubo_context *context) { - switch (context->state.id) { - case KUBO_CONTEXT_WALL_SELECT: - select_prev_wall(context); - break; - default: - break; - } -} - -void kubo_context_input_right(struct kubo_context *context) { - switch (context->state.id) { - case KUBO_CONTEXT_WALL_SELECT: - select_next_wall(context); - break; - default: - break; - } -} - -static void select_next_wall(struct kubo_context *context) { - if (!context->walls.count) { - return; - } - - context->wall_select_index = - (context->wall_select_index + 1) % context->walls.count; - - wall_select_refresh(context); -} - -static void select_prev_wall(struct kubo_context *context) { - if (context->state.id != KUBO_CONTEXT_WALL_SELECT || - !context->walls.count) { - return; - } - - size_t count = context->walls.count; - - context->wall_select_index = - (context->wall_select_index + count - 1) % count; - - wall_select_refresh(context); -} - -static inline void wall_select_refresh(struct kubo_context *context) { - for (size_t i = 0; i < context->walls.count; i++) { - struct kubo_wall *wall = kubo_wall_arr_get(&context->walls, i); - wall->state = i == context->wall_select_index ? KUBO_WALL_SELECTED - : KUBO_WALL_DONE; +void kubo_context_key(struct kubo_context *context, int key_code) { + for (unsigned i = 0; i < kubo_state_data_length; i++) { + if (context->state.id == kubo_state_data[i].id && + kubo_state_data[i].data.state_key != NULL) { + kubo_state_data[i].data.state_key(context, key_code); + } } } diff --git a/kubo_context.h b/kubo_context.h index 6f1ebc8..8c14ae5 100644 --- a/kubo_context.h +++ b/kubo_context.h @@ -27,17 +27,12 @@ #include "kubo_dynarray.h" #include "kubo_wall.h" +#include "states/kubo_states.h" + #define KUBO_CONTEXT_OFFSET_JMP 100 KUBO_DYNARRAY_REGISTER(kubo_wall_arr, struct kubo_wall *) -enum kubo_context_state { - KUBO_CONTEXT_NORMAL, - KUBO_CONTEXT_COMMAND, - KUBO_CONTEXT_WALL_NEW, - KUBO_CONTEXT_WALL_SELECT, -}; - struct kubo_context_state_data { enum kubo_context_state id; char *label; @@ -71,4 +66,6 @@ void kubo_context_input_down(struct kubo_context *context); void kubo_context_input_left(struct kubo_context *context); void kubo_context_input_right(struct kubo_context *context); +void kubo_context_key(struct kubo_context *context, int key_code); + #endif diff --git a/kubo_input.c b/kubo_input.c index ee95190..8821f5c 100644 --- a/kubo_input.c +++ b/kubo_input.c @@ -58,7 +58,6 @@ static void key_input(struct kubo_context *context, Camera2D *camera) { kubo_camera_shift(camera, (Vector2){.x = KUBO_INPUT_CAMERA_SHIFT, .y = 0}); } - kubo_context_input_right(context); break; case KEY_UP: @@ -67,7 +66,6 @@ static void key_input(struct kubo_context *context, Camera2D *camera) { kubo_camera_shift(camera, (Vector2){.x = 0, .y = KUBO_INPUT_CAMERA_SHIFT}); } - kubo_context_input_up(context); break; case KEY_LEFT: @@ -76,7 +74,6 @@ static void key_input(struct kubo_context *context, Camera2D *camera) { kubo_camera_shift(camera, (Vector2){.x = -KUBO_INPUT_CAMERA_SHIFT, .y = 0}); } - kubo_context_input_left(context); break; case KEY_DOWN: @@ -85,11 +82,6 @@ static void key_input(struct kubo_context *context, Camera2D *camera) { kubo_camera_shift(camera, (Vector2){.x = 0, .y = -KUBO_INPUT_CAMERA_SHIFT}); } - kubo_context_input_down(context); - break; - - case KEY_X: - kubo_context_delete_wall(context); break; case KEY_T: @@ -103,6 +95,8 @@ static void key_input(struct kubo_context *context, Camera2D *camera) { default: break; } + + kubo_context_key(context, key_code); } static void char_input(struct kubo_context *context) { diff --git a/states/CMakeLists.txt b/states/CMakeLists.txt new file mode 100644 index 0000000..bae1297 --- /dev/null +++ b/states/CMakeLists.txt @@ -0,0 +1,6 @@ +set(STATES_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/kubo_state_normal.c + ${CMAKE_CURRENT_SOURCE_DIR}/kubo_state_command.c + ${CMAKE_CURRENT_SOURCE_DIR}/kubo_state_wall_select.c + PARENT_SCOPE +) diff --git a/states/kubo_state_command.c b/states/kubo_state_command.c new file mode 100644 index 0000000..d30c114 --- /dev/null +++ b/states/kubo_state_command.c @@ -0,0 +1,26 @@ +/* + * Copyright Luka Jankovic 2025 + * + * This file is part of Kubo. + * + * Kubo is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Kubo. If not, see . + */ + +#include "kubo_state_command.h" +#include "../kubo_context.h" + +void kubo_state_command_entered(void *context_data) { + struct kubo_context *context = (struct kubo_context *)context_data; + (void)context; + printf("hello from state command\n"); +} diff --git a/states/kubo_state_command.h b/states/kubo_state_command.h new file mode 100644 index 0000000..fce2bd8 --- /dev/null +++ b/states/kubo_state_command.h @@ -0,0 +1,32 @@ +/* + * Copyright Luka Jankovic 2025 + * + * This file is part of Kubo. + * + * Kubo is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Kubo. If not, see . + */ + +#ifndef KUBO_STATE_COMMAND_H +#define KUBO_STATE_COMMAND_H + +#include + +#include "kubo_state_data.h" + +void kubo_state_command_entered(void *context_data); + +static const struct kubo_state_data kubo_state_command_data = { + .state_entered = kubo_state_command_entered +}; + +#endif diff --git a/states/kubo_state_data.h b/states/kubo_state_data.h new file mode 100644 index 0000000..2422384 --- /dev/null +++ b/states/kubo_state_data.h @@ -0,0 +1,35 @@ +/* + * Copyright Luka Jankovic 2025 + * + * This file is part of Kubo. + * + * Kubo is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Kubo. If not, see . + */ + +#ifndef KUBO_STATE_DATA_H +#define KUBO_STATE_DATA_H + +#include + +typedef void (*kubo_state_entered) (void *context_data); +typedef void (*kubo_state_key) (void *context_data, int key_code); + +struct kubo_state_data { + char *label; + Color color; + + kubo_state_entered state_entered; + kubo_state_key state_key; +}; + +#endif diff --git a/states/kubo_state_normal.c b/states/kubo_state_normal.c new file mode 100644 index 0000000..c2ae857 --- /dev/null +++ b/states/kubo_state_normal.c @@ -0,0 +1,26 @@ +/* + * Copyright Luka Jankovic 2025 + * + * This file is part of Kubo. + * + * Kubo is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Kubo. If not, see . + */ + +#include "kubo_state_normal.h" +#include "../kubo_context.h" + +void kubo_state_normal_entered(void *context_data) { + struct kubo_context *context = (struct kubo_context *)context_data; + (void)context; + printf("hello from state normal\n"); +} diff --git a/states/kubo_state_normal.h b/states/kubo_state_normal.h new file mode 100644 index 0000000..3c7b16b --- /dev/null +++ b/states/kubo_state_normal.h @@ -0,0 +1,32 @@ +/* + * Copyright Luka Jankovic 2025 + * + * This file is part of Kubo. + * + * Kubo is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Kubo. If not, see . + */ + +#ifndef KUBO_STATE_NORMAL_H +#define KUBO_STATE_NORMAL_H + +#include + +#include "kubo_state_data.h" + +void kubo_state_normal_entered(void *context_data); + +static const struct kubo_state_data kubo_state_normal_data = { + .state_entered = kubo_state_normal_entered, +}; + +#endif diff --git a/states/kubo_state_wall_select.c b/states/kubo_state_wall_select.c new file mode 100644 index 0000000..42f5a33 --- /dev/null +++ b/states/kubo_state_wall_select.c @@ -0,0 +1,91 @@ +/* + * Copyright Luka Jankovic 2025 + * + * This file is part of Kubo. + * + * Kubo is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Kubo. If not, see . + */ + +#include "kubo_state_wall_select.h" +#include "../kubo_context.h" + +static inline void wall_select_refresh(struct kubo_context *context); +static void select_next_wall(struct kubo_context *context); +static void select_prev_wall(struct kubo_context *context); +static void delete_wall(struct kubo_context *context); + +void kubo_state_wall_select_entered(void *context_data) { + struct kubo_context *context = (struct kubo_context *)context_data; + wall_select_refresh(context); +} + +void kubo_state_wall_select_key(void *context_data, int key_code) { + struct kubo_context *context = (struct kubo_context *)context_data; + + switch (key_code) { + case KEY_RIGHT: + case KEY_L: + case KEY_UP: + case KEY_K: + select_next_wall(context); + break; + case KEY_LEFT: + case KEY_H: + case KEY_DOWN: + case KEY_J: + select_prev_wall(context); + break; + case KEY_X: + delete_wall(context); + default: + break; + } +} + +static void select_next_wall(struct kubo_context *context) { + if (!context->walls.count) { + return; + } + + context->wall_select_index = + (context->wall_select_index + 1) % context->walls.count; + + wall_select_refresh(context); +} + +static void select_prev_wall(struct kubo_context *context) { + if (context->state.id != KUBO_CONTEXT_WALL_SELECT || + !context->walls.count) { + return; + } + + size_t count = context->walls.count; + + context->wall_select_index = + (context->wall_select_index + count - 1) % count; + + wall_select_refresh(context); +} + +static inline void wall_select_refresh(struct kubo_context *context) { + for (size_t i = 0; i < context->walls.count; i++) { + struct kubo_wall *wall = kubo_wall_arr_get(&context->walls, i); + wall->state = i == context->wall_select_index ? KUBO_WALL_SELECTED + : KUBO_WALL_DONE; + } +} + +static void delete_wall(struct kubo_context *context) { + kubo_wall_arr_del(&context->walls, context->wall_select_index); + select_next_wall(context); +} diff --git a/states/kubo_state_wall_select.h b/states/kubo_state_wall_select.h new file mode 100644 index 0000000..89c9c05 --- /dev/null +++ b/states/kubo_state_wall_select.h @@ -0,0 +1,32 @@ +/* + * Copyright Luka Jankovic 2025 + * + * This file is part of Kubo. + * + * Kubo is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Kubo. If not, see . + */ + +#ifndef KUBO_STATE_WALL_SELECT_H +#define KUBO_STATE_WALL_SELECT_H + +#include "kubo_state_data.h" + +void kubo_state_wall_select_entered(void *context_data); +void kubo_state_wall_select_key(void *context_data, int key_code); + +static const struct kubo_state_data kubo_state_wall_select_data = { + .state_entered = kubo_state_wall_select_entered, + .state_key = kubo_state_wall_select_key +}; + +#endif diff --git a/states/kubo_states.h b/states/kubo_states.h new file mode 100644 index 0000000..3525e43 --- /dev/null +++ b/states/kubo_states.h @@ -0,0 +1,46 @@ +/* + * Copyright Luka Jankovic 2025 + * + * This file is part of Kubo. + * + * Kubo is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * Kubo is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Kubo. If not, see . + */ + +#ifndef KUBO_STATES_H +#define KUBO_STATES_H + +#include "kubo_state_command.h" +#include "kubo_state_normal.h" +#include "kubo_state_wall_select.h" + +enum kubo_context_state { + KUBO_CONTEXT_NORMAL, + KUBO_CONTEXT_COMMAND, + KUBO_CONTEXT_WALL_NEW, + KUBO_CONTEXT_WALL_SELECT, +}; + +struct kubo_state_list_entry { + enum kubo_context_state id; + struct kubo_state_data data; +}; + +static const struct kubo_state_list_entry kubo_state_data[] = { + {KUBO_CONTEXT_NORMAL, kubo_state_normal_data}, + {KUBO_CONTEXT_COMMAND, kubo_state_command_data}, + {KUBO_CONTEXT_WALL_SELECT, kubo_state_wall_select_data}}; + +static const unsigned kubo_state_data_length = + sizeof(kubo_state_data) / sizeof(kubo_state_data[0]); + +#endif