forked from NotAShelf/rogged
various: add admin build; various layout improvements
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ieaa99fa0a32b42b1e97aada611d809b96a6a6964
This commit is contained in:
parent
d8b49054d5
commit
514a9560a2
9 changed files with 856 additions and 201 deletions
162
src/main.c
162
src/main.c
|
|
@ -118,7 +118,9 @@ static void init_floor(GameState *gs, int floor_num) {
|
|||
|
||||
// Find spawn position
|
||||
int start_x, start_y;
|
||||
get_random_floor_tile(&gs->map, &start_x, &start_y, 100);
|
||||
if (gs->map.room_count <= 0 || !get_room_floor_tile(&gs->map, &gs->map.rooms[0], &start_x, &start_y)) {
|
||||
get_random_floor_tile(&gs->map, &start_x, &start_y, 100);
|
||||
}
|
||||
|
||||
// Initialize player position if first floor
|
||||
if (floor_num == 1) {
|
||||
|
|
@ -148,6 +150,151 @@ static void init_floor(GameState *gs, int floor_num) {
|
|||
gs->turn_count = 0;
|
||||
}
|
||||
|
||||
#ifdef ROGGED_ADMIN_CONTROLS
|
||||
static void admin_recompute_lighting(GameState *gs) {
|
||||
LightSource player_light = {gs->player.position.x, gs->player.position.y, PLAYER_LIGHT_INTENSITY, PLAYER_LIGHT_RANGE};
|
||||
LightSource sources[1 + 32];
|
||||
sources[0] = player_light;
|
||||
memcpy(sources + 1, gs->static_lights, gs->static_light_count * sizeof(LightSource));
|
||||
compute_lighting(&gs->map, sources, 1 + gs->static_light_count);
|
||||
}
|
||||
|
||||
static void admin_reveal_map(GameState *gs) {
|
||||
for (int y = 0; y < MAP_HEIGHT; y++) {
|
||||
for (int x = 0; x < MAP_WIDTH; x++) {
|
||||
gs->map.remembered[y][x] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void admin_apply_fullbright(GameState *gs) {
|
||||
memset(gs->map.light_map, 255, sizeof(gs->map.light_map));
|
||||
admin_reveal_map(gs);
|
||||
}
|
||||
|
||||
static void admin_kill_enemies(GameState *gs) {
|
||||
for (int i = 0; i < gs->enemy_count; i++) {
|
||||
if (gs->enemies[i].alive) {
|
||||
gs->enemies[i].alive = 0;
|
||||
gs->enemies[i].hp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void admin_teleport_to_stairs(GameState *gs) {
|
||||
for (int y = 0; y < MAP_HEIGHT; y++) {
|
||||
for (int x = 0; x < MAP_WIDTH; x++) {
|
||||
if (gs->map.tiles[y][x] == TILE_STAIRS) {
|
||||
gs->player.position.x = x;
|
||||
gs->player.position.y = y;
|
||||
gs->awaiting_descend = 1;
|
||||
gs->last_message = "Admin: teleported to stairs";
|
||||
gs->message_timer = 90;
|
||||
admin_recompute_lighting(gs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int admin_button(Rectangle rect, const char *label) {
|
||||
Vector2 mouse = GetMousePosition();
|
||||
int hovered = CheckCollisionPointRec(mouse, rect);
|
||||
DrawRectangleRec(rect, hovered ? (Color){72, 62, 48, 235} : (Color){44, 42, 46, 235});
|
||||
DrawRectangleLines((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height,
|
||||
hovered ? (Color){210, 180, 110, 255} : (Color){112, 104, 92, 255});
|
||||
DrawText(label, (int)rect.x + 8, (int)rect.y + 5, SMALL_FONT, (Color){235, 228, 210, 255});
|
||||
return hovered && IsMouseButtonPressed(MOUSE_LEFT_BUTTON);
|
||||
}
|
||||
|
||||
static void admin_controls(GameState *gs, int *visible, int *fullbright) {
|
||||
if (IsKeyPressed(KEY_F1))
|
||||
*visible = !*visible;
|
||||
|
||||
DrawRectangle(8, 8, 142, 22, (Color){10, 10, 12, 190});
|
||||
DrawText("F1 Admin", 16, 13, SMALL_FONT, (Color){220, 190, 110, 255});
|
||||
|
||||
if (!*visible)
|
||||
return;
|
||||
|
||||
const int x = 20;
|
||||
const int start_y = 84;
|
||||
const int w = 166;
|
||||
const int h = 24;
|
||||
const int gap = 8;
|
||||
const int button_count = 10;
|
||||
const int panel_padding_bottom = 16;
|
||||
Rectangle panel = {8, 34, 190,
|
||||
(float)(start_y - 34 + button_count * h + (button_count - 1) * gap + panel_padding_bottom)};
|
||||
DrawRectangleRec(panel, (Color){12, 12, 15, 225});
|
||||
DrawRectangleLines((int)panel.x, (int)panel.y, (int)panel.width, (int)panel.height, (Color){170, 145, 90, 255});
|
||||
DrawText("Admin Controls", 20, 46, NORM_FONT, (Color){230, 205, 130, 255});
|
||||
DrawText("development build only", 20, 62, TINY_FONT, (Color){170, 164, 150, 255});
|
||||
|
||||
int y = start_y;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "Heal full")) {
|
||||
gs->player.hp = gs->player.max_hp;
|
||||
gs->game_over = 0;
|
||||
gs->last_message = "Admin: healed";
|
||||
gs->message_timer = 60;
|
||||
}
|
||||
y += h + gap;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "+10 max HP")) {
|
||||
gs->player.max_hp += 10;
|
||||
gs->player.hp = gs->player.max_hp;
|
||||
}
|
||||
y += h + gap;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "+2 attack"))
|
||||
gs->player.attack += 2;
|
||||
y += h + gap;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "+2 defense"))
|
||||
gs->player.defense += 2;
|
||||
y += h + gap;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "Reveal map"))
|
||||
admin_reveal_map(gs);
|
||||
y += h + gap;
|
||||
|
||||
char fullbright_label[32];
|
||||
snprintf(fullbright_label, sizeof(fullbright_label), "Fullbright: %s", *fullbright ? "on" : "off");
|
||||
if (admin_button((Rectangle){x, y, w, h}, fullbright_label)) {
|
||||
*fullbright = !*fullbright;
|
||||
if (*fullbright) {
|
||||
admin_apply_fullbright(gs);
|
||||
} else {
|
||||
admin_recompute_lighting(gs);
|
||||
}
|
||||
}
|
||||
y += h + gap;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "Kill enemies"))
|
||||
admin_kill_enemies(gs);
|
||||
y += h + gap;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "Teleport stairs"))
|
||||
admin_teleport_to_stairs(gs);
|
||||
y += h + gap;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "Reroll floor")) {
|
||||
init_floor(gs, gs->player.floor);
|
||||
gs->last_message = "Admin: rerolled floor";
|
||||
gs->message_timer = 60;
|
||||
}
|
||||
y += h + gap;
|
||||
|
||||
if (admin_button((Rectangle){x, y, w, h}, "Next floor")) {
|
||||
int next_floor = gs->player.floor < NUM_FLOORS ? gs->player.floor + 1 : gs->player.floor;
|
||||
init_floor(gs, next_floor);
|
||||
gs->last_message = "Admin: advanced floor";
|
||||
gs->message_timer = 60;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Tick all status effects at the start of a turn
|
||||
static void tick_all_effects(GameState *gs) {
|
||||
// Player effects
|
||||
|
|
@ -617,6 +764,10 @@ static void game_loop(unsigned int run_seed, FontManager *fm) {
|
|||
SetExitKey(0);
|
||||
|
||||
int frame_counter = 0;
|
||||
#ifdef ROGGED_ADMIN_CONTROLS
|
||||
int admin_visible = 1;
|
||||
int admin_fullbright = 0;
|
||||
#endif
|
||||
while (!WindowShouldClose()) {
|
||||
frame_counter++;
|
||||
|
||||
|
|
@ -692,6 +843,11 @@ static void game_loop(unsigned int run_seed, FontManager *fm) {
|
|||
if (gs.player.flash_timer > 0)
|
||||
gs.player.flash_timer--;
|
||||
|
||||
#ifdef ROGGED_ADMIN_CONTROLS
|
||||
if (admin_fullbright)
|
||||
admin_apply_fullbright(&gs);
|
||||
#endif
|
||||
|
||||
// Render
|
||||
BeginDrawing();
|
||||
ClearBackground(BLACK);
|
||||
|
|
@ -744,6 +900,10 @@ static void game_loop(unsigned int run_seed, FontManager *fm) {
|
|||
gs.final_score, gs.run_seed, fm);
|
||||
}
|
||||
|
||||
#ifdef ROGGED_ADMIN_CONTROLS
|
||||
admin_controls(&gs, &admin_visible, &admin_fullbright);
|
||||
#endif
|
||||
|
||||
EndDrawing();
|
||||
|
||||
// small delay for key repeat control
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue