Mineur_Tycoon/src/ui.c
2025-04-05 12:25:04 +02:00

357 lines
8.3 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include <raylib.h>
#include <raymath.h>
#include "types.h"
#include "game.h"
#include "draw.h"
#include "ui.h"
#include "config.h"
char _ver_str[256];
char *VERSION_STR = _ver_str;
GUIInfo gui_info;
#define color_main_brown (Color){247, 239, 206, 255}
#define color_main_brown1 (Color){161, 151, 112, 255}
void draw_text_centered(char *str, int y, int font_size, Color color){
int width = MeasureText(str, font_size);
DrawText(str, 640-width/2, y, font_size, color);
}
void draw_buttons(Widget *widget){
for(int i = 0; i < widget->button_n; i++){
Button *butt = &widget->buttons[i];
DrawRectangleRounded(butt->box, 0.1, 3, butt->color_0);
Color outline_color = butt->curr_select ? SKYBLUE : butt->color_1;
DrawRectangleRoundedLines(butt->box, 0.1, 3, 2, outline_color);
int font_size = 0.75*butt->box.height;
int width = MeasureText(butt->txt, font_size);
int text_x = butt->box.x + butt->box.width/2 - width/2;
int text_y = butt->box.y + butt->box.height/5;
DrawText(butt->txt, text_x, text_y, font_size, butt->color_txt);
}
}
void buttons_do_event(Widget *widget, Game *game, MTEvent event){
if(event.type != EV_Mouse || event.click != MOUSE_BUTTON_LEFT)
return;
for(int i = 0; i < widget->button_n; i++){
Button *butt = &widget->buttons[i];
if(CheckCollisionPointRec(event.pos, butt->box) && butt->handler)
butt->handler(game);
}
}
void main_menu_draw(Widget *widget, Game *game){
ClearBackground(color_main_brown);
draw_text_centered("Mineur Tycoon", 50, 100, BLACK);
draw_text_centered(VERSION_STR, 160, 30, BLACK);
DrawRectangleRounded((Rectangle){500, 200, 280, 260}, 0.1, 3,
color_main_brown1);
draw_buttons(widget);
}
void widget_draw_game(Widget *widget, Game *game){
draw_game(game);
}
void game_exit(Game *game){
game->exit = true;
}
void main_menu_new_game(Game *game){
gui_info.widget_active[0] = true;
gui_info.widget_active[1] = false;
game->paused = false;
}
Widget main_menu = {
.box = {.x = 0, .y = 0, .width = -1, .height = -1},
.draw = main_menu_draw,
.do_event = buttons_do_event,
.capt_flags = CF_Mouse | CF_Keyb,
.buttons = {
{.box = {520,220,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = BLACK,
.txt = "New game",
.handler = main_menu_new_game
},
{.box = {520,270,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = GRAY,
.txt = "Load game",
.handler = NULL
},
{.box = {520,320,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = GRAY,
.txt = "Settings",
.handler = NULL
},
{.box = {520,400,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = BLACK,
.txt = "Exit",
.handler = game_exit
},
},
.button_n = 4
};
void pause_menu_draw(Widget *widget, Game *game){
DrawRectangleRounded((Rectangle){500, 150, 280, 380}, 0.1, 3,
color_main_brown1);
draw_buttons(widget);
}
void pause_menu_resume(Game *game){
gui_info.widget_active[4] = false;
gui_info.widget_active[0] = true;
game->paused = false;
}
void pause_menu_new_game(Game *game){
clean_game(game);
init_game(game);
pause_menu_resume(game);
}
Widget pause_menu = {
.box = {.x = 0, .y = 0, .width = -1, .height = -1},
.draw = pause_menu_draw,
.do_event = buttons_do_event,
.capt_flags = CF_Mouse | CF_Keyb,
.buttons = {
{.box = {520,170,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = BLACK,
.txt = "Resume",
.handler = pause_menu_resume
},
{.box = {520,240,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = BLACK,
.txt = "New game",
.handler = pause_menu_new_game
},
{.box = {520,290,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = GRAY,
.txt = "Save game",
.handler = NULL
},
{.box = {520,340,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = GRAY,
.txt = "Load game",
.handler = NULL
},
{.box = {520,390,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = GRAY,
.txt = "Settings",
.handler = NULL
},
{.box = {520,470,240,40},
.color_0 = WHITE,
.color_1 = BLACK,
.color_txt = BLACK,
.txt = "Exit",
.handler = game_exit
}
},
.button_n = 6
};
void worker_widget_draw(Widget *widget, Game *game){
DrawRectangleRounded(widget->box, 0.1, 3, color_main_brown);
}
void worker_widget_do_event(Widget *widget, Game *game, MTEvent event){
if(event.click == MOUSE_BUTTON_LEFT)
gui_info.widget_active[2] = false;
}
Widget worker_widget = {
.box = {.x = 40, .y = 40, .width = 300, .height = 600},
.draw = worker_widget_draw,
.do_event = worker_widget_do_event,
.capt_flags = CF_Mouse,
.buttons = {
},
.button_n = 0
};
Widget machine_widget = {
};
Widget game_widget = {
.box = {0,0,0,0},
.draw = widget_draw_game,
.do_event = NULL,
.capt_flags = 0,
.buttons = {},
.button_n = 0
};
void init_ui(){
snprintf(_ver_str, 256, "v%d.%d-%d", VERSION_MAJ, VERSION_MIN,
VERSION_PATCH);
// Android exclusive key -> no exit key
SetExitKey(KEY_MENU);
gui_info = (GUIInfo){{&game_widget, &main_menu, &worker_widget, &machine_widget, &pause_menu},
{false, true, false, false, false},
NULL};
}
void draw_widgets(Game *game){
for(int i = 0; i < WIDGET_N; i++){
if(!gui_info.widget_active[i])
continue;
Widget *w = gui_info.widgets[i];
if(w->draw)
w->draw(w, game);
}
}
bool widget_coll(Rectangle widget, V2d point){
if(widget.width < 0)
widget.width = SCREEN_W;
if(widget.height < 0)
widget.height = SCREEN_H;
return CheckCollisionPointRec(point, widget);
}
bool widgets_treat_event(Game *game, MTEvent event){
bool treated = true;
for(int i = WIDGET_N-1; i >= 0 && treated; i--){
if(!gui_info.widget_active[i])
continue;
Widget *w = gui_info.widgets[i];
if(!w || !w->do_event)
continue;
if(!widget_coll(w->box, event.pos))
continue;
// Only actually call do_key if the event type matches event flags
switch(event.type){
default:
continue;
case EV_Mouse:
if(w->capt_flags & CF_Mouse)
break;
continue;
case EV_Keyb:
if(w->capt_flags & CF_Keyb)
break;
continue;
}
treated = false;
w->do_event(w, game, event);
}
return treated;
}
bool ui_do_key(Game *game, int key){
MTEvent event = {.type = EV_Keyb, {.key = key}};
return widgets_treat_event(game, event);
}
bool ui_do_mouse(Game *game, V2d pos, int click){
MTEvent event = {.type = EV_Mouse, {.click = click}, .pos = pos};
return widgets_treat_event(game, event);
}
void try_interface(Game *game, V2d pos){
DrawRectangleV(pos, (V2d){16,16},PINK);
Machine *mach = get_machine_from_pos(&game->machines, pos);
if(mach){
printf("found machine %d\n",mach->id);
return;
}
Worker *work = get_worker_from_pos(&game->workers, pos);
if(!work)
return;
printf("found worker\n");
gui_info.widget_active[2] = true;
return;
}
bool keydown(int key){
return IsKeyDown(key);
}
void goto_pause_menu(Game *game){
if(gui_info.widget_active[1])
return;
memset(gui_info.widget_active, false, sizeof(bool)*WIDGET_N);
gui_info.widget_active[4] = true;
game->paused = true;
}
int get_mouse(){
for(int i = 0; i < MOUSE_BUTTON_NULL; i++){
if(IsMouseButtonPressed(i))
return i;
}
return MOUSE_BUTTON_NULL;
}
void get_keys(Game *game){
V2d mouse_pos = GetMousePosition();
int mouse_click = get_mouse();
if(ui_do_mouse(game, mouse_pos, mouse_click)){
if(mouse_click == MOUSE_BUTTON_LEFT)
try_interface(game, GetScreenToWorld2D(mouse_pos,game->camera));
}
if(keydown(KEY_W))
game->camera.target.y -= 3;
if(keydown(KEY_S))
game->camera.target.y += 3;
if(keydown(KEY_A))
game->camera.target.x -= 3;
if(keydown(KEY_D))
game->camera.target.x += 3;
if(keydown(KEY_UP))
game->camera.zoom *= 1.025;
if(keydown(KEY_DOWN))
game->camera.zoom *= 1/1.025;
if(IsKeyPressed(KEY_P))
game->paused = !game->paused;
if(IsKeyPressed(KEY_ESCAPE))
goto_pause_menu(game);
}