--- /dev/null
+#ifndef __LOCAL_ENUMS__
+#define __LOCAL_ENUMS__
+
+typedef enum
+{
+ Square = 0,
+ Circle,
+ Barrow
+} Shape;
+
+typedef enum
+{
+ STATUS_TEXT_FADE_TIME = 0,
+ STATUS_TIMERS
+} eTimers;
+
+typedef enum
+{
+ UNKNOWN = 0,
+ GOOD,
+ BAD,
+ WAITING,
+ FINISHED,
+ STATES
+} eState;
+
+typedef enum
+{
+ SAVE_FILE_LOAD = 0,
+ SAVE_FILE_SAVE,
+
+ /* Resource load and generation here eventually too */
+
+ PROCESSES
+} eProcess;
+
+typedef enum
+{
+ STATUS_TEXT_PLACE = 0,
+ TEXT_PLACES,
+} eTextPlaces;
+
+typedef enum
+{
+ RENDER_MAIN_MENU = 0,
+ RENDER_RESOURCE_WAIT,
+ RENDER_RESOURCE_READY,
+ RENDER_GAME,
+ RENDER_MODES
+} eRenderMode;
+
+typedef enum
+{
+ CONTROL_MAIN_MENU = 0,
+ CONTROL_RESOURCE_WAIT,
+ CONTROL_RESOURCE_READY,
+ CONTROL_GAME,
+ CONTROL_MODES
+} eControlMode;
+
+#define MENU_ITEMS \
+ X(MI_NONE) \
+ X(MI_NEW_GAME) \
+ X(MI_LOAD_GAME) \
+ X(MI_SAVE_GAME) \
+ X(MI_QUIT) \
+ X(MI_ITEMS)
+
+#define X(item) item,
+typedef enum
+{
+ MENU_ITEMS
+} eMenuItem;
+#undef X
+
+
+#endif /* __LOCAL_ENUMS__ */
+
start_render_loop();
pthread_join(generator_thread, NULL);
#else
- resource_state = 1;
+ resource_state = 0;
start_render_loop();
#endif /* ENABLE_BARROWGEN */
--- /dev/null
+#include <assert.h>
+#include <raylib.h>
+#include <stdio.h>
+
+#include "structs.h"
+
+bool menu_action_MI_NONE()
+{ return true; }
+
+bool menu_action_MI_NEW_GAME()
+{
+ bool response = false;
+
+
+
+ return response;
+}
+
+bool menu_action_MI_LOAD_GAME()
+{
+ bool response = false;
+
+
+
+ return response;
+}
+
+bool menu_action_MI_SAVE_GAME()
+{
+ bool response = false;
+
+
+
+ return response;
+}
+
+bool menu_action_MI_QUIT()
+{
+ bool response = false;
+
+ printf("shutting down!\n");
+ playtime.should_quit = 1;
+
+ return response;
+}
+
+bool menu_action_MI_ITEMS()
+{
+ /* Unreachable! */
+ assert(0);
+}
+
--- /dev/null
+#ifndef __MENUFUNCS__
+#define __MENUFUNCS__
+
+#include <stdbool.h>
+#include "enums.h"
+
+typedef bool(*menufunc)();
+
+bool menu_action_MI_NONE();
+bool menu_action_MI_NEW_GAME();
+bool menu_action_MI_LOAD_GAME();
+bool menu_action_MI_SAVE_GAME();
+bool menu_action_MI_QUIT();
+bool menu_action_MI_ITEMS();
+
+extern menufunc menufuncs[MI_ITEMS + 1];
+
+#endif /* __MENU_FUNCS__ */
+
#include <raymath.h>
#include "structs.h"
+#include "ui.h"
#define str(x) #x
#define xstr(x) str(x)
typedef void(*renderfunc)();
typedef void(*controlfunc)();
-#define MAX_RENDERFUNCS 3U
-renderfunc renderfuncs[MAX_RENDERFUNCS];
-controlfunc controlfuncs[MAX_RENDERFUNCS];
+renderfunc renderfuncs[RENDER_MODES];
+controlfunc controlfuncs[CONTROL_MODES];
Color ColorLerp(Color c1, Color c2, float amount)
{
return new_color;
}
+void drawing_main_menu_mode()
+{
+ ClearBackground(LIGHTGRAY);
+
+ const size_t title_font_size = 64;
+ const size_t sub_font_size = 48;
+ const char title_text[] = "Randy's Barrow Adventure";
+
+ DrawText(title_text,
+ (fscreen_dims.x/2.0f) - (MeasureText(title_text, title_font_size)/2.0f), (fscreen_dims.y/4.0f) * 1.0f, title_font_size, BLACK);
+
+ for (size_t n = 0; n < 3; n++)
+ {
+ const MenuButton button = main_menu_items[n];
+ const char* text = menu_items[button.item_index].text;
+ const Vector2 text_v2 = button.text_v2;
+ const Rectangle button_bound = button.button_bound;
+
+ const bool mouse_in_container = menu_info.hover_item == button.item_index;
+ const Color fg = (mouse_in_container) ? button.fg : button.bg;
+ const Color bg = (mouse_in_container) ? button.bg : button.fg;
+
+ DrawRectangle(button_bound.x, button_bound.y, button_bound.width, button_bound.height, bg);
+ DrawText(text,
+ text_v2.x, text_v2.y, sub_font_size, fg);
+ }
+}
+
/* Render the regular game mode.
NOTE: Only call inside a Raylib BeginDrawing() block!
*/
Rectangle minimap_dest = {.width = 64.0f*img_export_scale.x, .height = 64.0f*img_export_scale.y, .x = 0.0f, .y = 0.0f};
Rectangle minimap_src = {.width = barrow_texture.width, .height = barrow_texture.height, .x = 0.0f, .y = 0.0f};
- if (timers[E_STATUS_TEXT_FADE_TIME].time > 0.0)
+ if (timers[STATUS_TEXT_FADE_TIME].time > 0.0)
{
- const char* text = text_places[E_STATUS_TEXT_PLACE];
+ const char* text = text_places[STATUS_TEXT_PLACE];
DrawText(TextFormat("%s", text), 0, screen_dims.y - 32, 32, GREEN);
}
playtime.cam.position = cam_reset_position;
}
- if (IsKeyReleased(KEY_F4) && timers[E_STATUS_TEXT_FADE_TIME].time == 0)
+ if (IsKeyReleased(KEY_F4) && timers[STATUS_TEXT_FADE_TIME].time == 0)
{
- ProcessInfo* process = &processes[E_SAVE_FILE_SAVE];
- processes[E_SAVE_FILE_SAVE].state = E_WAITING;
+ ProcessInfo* process = &processes[SAVE_FILE_SAVE];
+ processes[SAVE_FILE_SAVE].state = WAITING;
const int success = save_game(playtime);
- if ((success == 0) && timers[E_STATUS_TEXT_FADE_TIME].time == 0)
+ if ((success == 0) && timers[STATUS_TEXT_FADE_TIME].time == 0)
{
- processes[E_SAVE_FILE_SAVE].state = E_FINISHED;
+ processes[SAVE_FILE_SAVE].state = FINISHED;
}
else if (success != 0)
{
- processes[E_SAVE_FILE_SAVE].state = E_BAD;
+ processes[SAVE_FILE_SAVE].state = BAD;
}
- memcpy(text_places[E_STATUS_TEXT_PLACE], process->info_text[process->state], 64);
- timers[E_STATUS_TEXT_FADE_TIME].time = timers[E_STATUS_TEXT_FADE_TIME].max;
+ memcpy(text_places[STATUS_TEXT_PLACE], process->info_text[process->state], 64);
+ timers[STATUS_TEXT_FADE_TIME].time = timers[STATUS_TEXT_FADE_TIME].max;
}
- if (IsKeyReleased(KEY_F5) && timers[E_STATUS_TEXT_FADE_TIME].time == 0)
+ if (IsKeyReleased(KEY_F5) && timers[STATUS_TEXT_FADE_TIME].time == 0)
{
- ProcessInfo* process = &processes[E_SAVE_FILE_LOAD];
- process->state = E_WAITING;
+ ProcessInfo* process = &processes[SAVE_FILE_LOAD];
+ process->state = WAITING;
const int success = load_game();
- if ((success == 0 ) && timers[E_STATUS_TEXT_FADE_TIME].time == 0.0)
+ if ((success == 0 ) && timers[STATUS_TEXT_FADE_TIME].time == 0.0)
{
- process->state = E_FINISHED;
+ process->state = FINISHED;
}
else if (success != 0)
{
- process->state = E_BAD;
+ process->state = BAD;
}
- memcpy(text_places[E_STATUS_TEXT_PLACE], process->info_text[process->state], 64);
- timers[E_STATUS_TEXT_FADE_TIME].time = timers[E_STATUS_TEXT_FADE_TIME].max;
+ memcpy(text_places[STATUS_TEXT_PLACE], process->info_text[process->state], 64);
+ timers[STATUS_TEXT_FADE_TIME].time = timers[STATUS_TEXT_FADE_TIME].max;
}
if (IsKeyReleased(KEY_ONE))
{
}
+
void wait_initialize_shaders()
{
shader = LoadShader("./src/shaders/lighting.vs", "./src/shaders/lighting.fs");
/* Mode handler setup */
{
- renderfuncs[0U] = drawing_resource_wait_mode;
- renderfuncs[1U] = drawing_resource_ready_mode;
- renderfuncs[2U] = drawing_game_mode;
- controlfuncs[0U] = control_resource_wait_mode;
- controlfuncs[1U] = control_resource_ready_mode;
- controlfuncs[2U] = control_game_mode;
+ renderfuncs[RENDER_MAIN_MENU] = drawing_main_menu_mode;
+ renderfuncs[RENDER_RESOURCE_WAIT] = drawing_resource_wait_mode;
+ renderfuncs[RENDER_RESOURCE_READY] = drawing_resource_ready_mode;
+ renderfuncs[RENDER_GAME] = drawing_game_mode;
+ controlfuncs[CONTROL_MAIN_MENU] = control_main_menu_mode;
+ controlfuncs[CONTROL_RESOURCE_WAIT] = control_resource_wait_mode;
+ controlfuncs[CONTROL_RESOURCE_READY] = control_resource_ready_mode;
+ controlfuncs[CONTROL_GAME] = control_game_mode;
}
}
void update_timers()
{
- for (int t = 0; t < E_STATUS_TIMERS; t++)
+ for (int t = 0; t < STATUS_TIMERS; t++)
{
if (timers[t].time > 0)
{
void start_render_loop()
{
+ /* Things that need to happen before Raylib init */
initialize_prerenderer();
+
SetTraceLogLevel(LOG_ALL);
InitWindow(fscreen_dims.x, fscreen_dims.y, screen_title);
+
+ /* Things that need to happen after Raylib init */
+ init_menus(fscreen_dims);
wait_initialize_shaders();
SetTargetFPS(target_fps);
int func_idx = resource_state;
player_collide_point = playtime.cam.position;
- //player_collide_point.y -= 1.0f;
controlfuncs[func_idx]();
SetShaderValue(shader, cam_position_shader_loc, &playtime.cam.position, SHADER_UNIFORM_VEC3);
/* Decay forward velocity and rotation */
playtime.player_velocity.x = Lerp(playtime.player_velocity.x, 0.0f, forward_speed_decay * frame_time);
playtime.player_rotation.x = Lerp(playtime.player_rotation.x, 0.0f, rotate_speed_decay * frame_time);
- }
- playtime.should_quit = 1;
+ if (playtime.should_quit) break;
+ }
UnloadImage(barrow_image);
UnloadTexture(barrow_texture);
.delta_t = 0.6f,
.name = "puffer",
- .shape = eCircle
+ .shape = Circle
};
// diff values influence tightness, delta between them shouldn't get wider than ~0.5 or narrower than ~0.4
.delta_t = 0.6f,
.name = "barrow",
- .shape = eBarrow
+ .shape = Barrow
};
RD_Opts worms =
.delta_t = 0.6f,
.name = "worms",
- .shape = eSquare
+ .shape = Square
};
RD_Opts meiosis =
.delta_t = 1.0f,
.name = "meiosis",
- .shape = eSquare
+ .shape = Square
};
const Mat3 laplacian_kernel =
PlaytimeData playtime;
-Timer timers[E_STATUS_TIMERS] =
+Timer timers[STATUS_TIMERS] =
{
/* timer time max */
/* E_STATUS_TEXT_FADE_TIME */ { 0, 4000 }
};
-ProcessInfo processes[E_PROCESSES] =
+ProcessInfo processes[PROCESSES] =
{
/* Process { STATE Progress, { E_UNKNOWN, E_GOOD, E_BAD, E_WAITING, E_FINISHED } } */
- /* E_SAVE_FILE_LOAD */ { E_UNKNOWN, 0.0f, { "", "", "Failed to load save.", "Loading...", "Loaded" } },
- /* E_SAVE_FILE_SAVE */ { E_UNKNOWN, 0.0f, { "", "", "Failed to create save.", "Saving...", "Saved" } }
+ /* E_SAVE_FILE_LOAD */ { UNKNOWN, 0.0f, { "", "", "Failed to load save.", "Loading...", "Loaded" } },
+ /* E_SAVE_FILE_SAVE */ { UNKNOWN, 0.0f, { "", "", "Failed to create save.", "Saving...", "Saved" } }
};
-char text_places[E_TEXT_PLACES][64];
+
+char text_places[TEXT_PLACES][64];
const char chars[6] = {' ', ' ', ' ', '+', '#', '@'};
const int max_chars = sizeof(chars) / sizeof(chars[0]) - 1;
const IVec2 img_export_scale = {.x = 2, .y = 2};
float resource_generation_progress = 0.0f;
+
+// Move this into menuinfo
+// Actually merge all of them into a display manager
int resource_state = 0;
#include <stdint.h>
#include <raylib.h>
-typedef enum
-{
- eSquare = 0,
- eCircle,
- eBarrow
-} Shape;
+#include "enums.h"
+#include "ui.h"
typedef struct
{
float max;
} Timer;
-typedef enum
-{
- E_STATUS_TEXT_FADE_TIME = 0,
- E_STATUS_TIMERS
-} eTimers;
-
-typedef enum
-{
- E_UNKNOWN = 0,
- E_GOOD,
- E_BAD,
- E_WAITING,
- E_FINISHED,
- E_STATES
-} eState;
-
-typedef enum
-{
- E_SAVE_FILE_LOAD = 0,
- E_SAVE_FILE_SAVE,
-
- /* Resource load and generation here eventually too */
-
- E_PROCESSES
-} eProcess;
-
typedef struct
{
eState state;
float progress;
- char info_text[E_STATES][64];
+ char info_text[STATES][64];
} ProcessInfo;
-typedef enum
-{
- E_STATUS_TEXT_PLACE = 0,
- E_TEXT_PLACES,
-} eTextPlaces;
-
extern PlaytimeData playtime;
+extern MenuInfo menu_info;
-extern ProcessInfo processes[E_PROCESSES];
-extern Timer timers[E_STATUS_TIMERS];
-extern char text_places[E_TEXT_PLACES][64];
+extern ProcessInfo processes[PROCESSES];
+extern Timer timers[STATUS_TIMERS];
+extern char text_places[TEXT_PLACES][64];
extern RD_Opts barrow;
extern RD_Opts puffer;
--- /dev/null
+#include <stddef.h>
+#include <stdio.h>
+
+#include "menufuncs.h"
+#include "ui.h"
+
+const MenuItem menu_items[MI_ITEMS] =
+{
+ { MI_NONE, "" , false},
+ { MI_NEW_GAME, "New Game" , false},
+ { MI_LOAD_GAME, "Load Game" , false},
+ { MI_SAVE_GAME, "Save Game" , false},
+ { MI_QUIT, "Quit" , false},
+};
+
+MenuButton main_menu_items[3] =
+{
+ { MI_NEW_GAME , (Rectangle){}, (Vector2){}, DARKGRAY, LIGHTGRAY, 48 },
+ { MI_LOAD_GAME, (Rectangle){}, (Vector2){}, DARKGRAY, LIGHTGRAY, 48 },
+ { MI_QUIT , (Rectangle){}, (Vector2){}, DARKGRAY, LIGHTGRAY, 48 }
+};
+
+MenuInfo menu_info =
+{
+ RENDER_MAIN_MENU,
+ CONTROL_MAIN_MENU,
+ MI_NONE
+};
+
+menufunc menufuncs[MI_ITEMS+1];
+
+void init_menus(Vector2 screen_dims)
+{
+ for (size_t n = 0; n < sizeof(main_menu_items)/sizeof(main_menu_items[0]); n++)
+ {
+ MenuButton* button = &main_menu_items[n];
+ const MenuItem* menu_item = &menu_items[button->item_index];
+ const int text_width = MeasureText(menu_item->text, button->font_size);
+ const Vector2 text_size = {.x = text_width, .y = button->font_size};
+
+ Vector2 text_v2 =
+ {
+ (screen_dims.x/2.0f) - (text_size.x / 2.0f),
+ (screen_dims.y/13.0f) * (n+5),
+ };
+
+ const uint32_t margin = 8U;
+ Rectangle button_bound =
+ (Rectangle){
+ .x = text_v2.x - margin,
+ .y = text_v2.y - margin,
+ .width = text_size.x + margin * 2U,
+ .height = text_size.y + margin,
+ };
+
+ button->button_bound = button_bound;
+ button->text_v2 = text_v2;
+
+ }
+
+#define X(emenu_item) menufuncs[emenu_item] = menu_action_ ## emenu_item;
+ MENU_ITEMS
+#undef X
+
+}
+
+void control_main_menu_mode()
+{
+ const Vector2 mouse = GetMousePosition();
+ const bool left_click = IsMouseButtonReleased(MOUSE_LEFT_BUTTON);
+
+ /* Figure out a click in menu item bounds
+ Set globals
+ Let renderfunc act on it
+ */
+
+ menu_info.hover_item = MI_NONE;
+ for (size_t n = 0; n < sizeof(main_menu_items)/sizeof(main_menu_items[0]); n++)
+ {
+ const MenuButton button = main_menu_items[n];
+ const Rectangle button_bound = button.button_bound;
+ const bool mouse_in_container = CheckCollisionPointRec(mouse, button_bound);
+
+ if (mouse_in_container)
+ {
+ menu_info.hover_item = button.item_index;
+ menu_info.hover_item_picked = menu_info.hover_item && left_click;
+ }
+
+ if ((menu_info.hover_item == button.item_index) && (menu_info.hover_item_picked))
+ {
+ menufuncs[menu_info.hover_item]();
+ }
+ }
+
+}
+
--- /dev/null
+#ifndef __UI__
+#define __UI__
+
+#include <raylib.h>
+#include <stdint.h>
+
+#include "enums.h"
+
+typedef struct
+{
+ eRenderMode render_mode;
+ eControlMode control_mode;
+ eMenuItem hover_item;
+ bool hover_item_picked;
+} MenuInfo;
+
+typedef struct
+{
+ eMenuItem type;
+ char text[64];
+ bool selected;
+} MenuItem;
+
+typedef struct
+{
+ eMenuItem item_index;
+ Rectangle button_bound;
+ Vector2 text_v2;
+ Color bg;
+ Color fg;
+ int font_size;
+} MenuButton;
+
+extern MenuInfo menu_info;
+extern const MenuItem menu_items[MI_ITEMS];
+extern MenuButton main_menu_items[3];
+
+void init_menus(Vector2 screen_dims);
+void control_main_menu_mode();
+
+#define stringify2(x) #x
+#define stringify(x) stringify2(x)
+
+#endif /* __UI__ */
+