Doom UI improvements for dynamic screen (#2812)

* Doom dynamic screen and other improvements

Doom dynamic screen and other improvements

* Res divider fix for big screens

* Format code
This commit is contained in:
RocketGod 2025-10-09 13:54:54 -07:00 committed by GitHub
parent 477d035dce
commit 193ac73b34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 63 additions and 24 deletions

View file

@ -17,6 +17,7 @@ int SCREEN_HEIGHT = 0;
int RENDER_HEIGHT = 0;
int HALF_WIDTH = 0;
int HALF_HEIGHT = 0;
int HUD_HEIGHT = 40;
#define LEVEL_WIDTH_BASE 6
#define LEVEL_WIDTH (1 << LEVEL_WIDTH_BASE)
#define LEVEL_HEIGHT 57
@ -24,7 +25,7 @@ int HALF_HEIGHT = 0;
#define MAX_RENDER_DEPTH 12
#define MIN_ENTITIES 15
#define MAX_ENTITIES 25
#define RES_DIVIDER 2
int RES_DIVIDER = 2;
#define DISTANCE_MULTIPLIER 20
#define ROT_SPEED 0.25
#define MOV_SPEED 1.0
@ -32,10 +33,10 @@ int HALF_HEIGHT = 0;
#define MAX_ENTITY_DISTANCE 200
#define ITEM_COLLIDER_DIST 6
#include "mathdef.hpp"
#define GUN_WIDTH 30
#define GUN_HEIGHT 40
#define GUN_TARGET_POS 24
#define GUN_SHOT_POS (GUN_TARGET_POS + 6)
int GUN_WIDTH = 30;
int GUN_HEIGHT = 40;
int GUN_TARGET_POS = 24;
int GUN_SHOT_POS = 30;
#define ENEMY_SIZE 16
#define ENEMY_SPEED 0.03
#define ENEMY_MELEE_DIST 20
@ -145,7 +146,7 @@ static bool up, down, left, right, fired;
static double jogging, view_height;
static bool needs_redraw = false;
static bool needs_gun_redraw = false;
static uint8_t gun_pos = GUN_TARGET_POS;
static uint8_t gun_pos = 24;
static bool gun_fired = false;
static int prev_gun_x = 0;
static int prev_gun_y = 0;
@ -850,13 +851,23 @@ void render_entities(Painter& painter) {
}
}
void render_map(Painter& painter, bool full_clear, int16_t x_start = 0, int16_t x_end = SCREEN_WIDTH) {
void render_map(Painter& painter, bool full_clear, int16_t x_start = 0, int16_t x_end = -1) {
if (x_end == -1) x_end = SCREEN_WIDTH;
// Add safety bounds
x_start = fmax(0, x_start);
x_end = fmin(SCREEN_WIDTH, x_end);
// Dynamically adjust RES_DIVIDER based on screen size
int dynamic_res = (SCREEN_WIDTH > 400) ? 4 : (SCREEN_WIDTH > 300) ? 3
: RES_DIVIDER;
if (full_clear) {
painter.fill_rectangle({0, 0, SCREEN_WIDTH, RENDER_HEIGHT / 2}, Color(64, 64, 128));
painter.fill_rectangle({0, RENDER_HEIGHT / 2, SCREEN_WIDTH, RENDER_HEIGHT / 2}, Color(32, 32, 32));
}
for (uint8_t x = x_start; x < x_end; x += RES_DIVIDER) {
for (uint16_t x = x_start; x < x_end; x += dynamic_res) {
double camera_x = 2 * (double)x / SCREEN_WIDTH - 1;
double ray_x = player.dir.x + player.plane.x * camera_x;
double ray_y = player.dir.y + player.plane.y * camera_x;
@ -985,15 +996,15 @@ void render_map(Painter& painter, bool full_clear, int16_t x_start = 0, int16_t
wall_color = Color(brightness / 5, (brightness - noise) * 0.8, brightness / 5);
}
painter.fill_rectangle({x, start_y, RES_DIVIDER, end_y - start_y}, wall_color);
painter.fill_rectangle({x, start_y, dynamic_res, end_y - start_y}, wall_color);
}
if (!full_clear && hit) {
if (start_y > 0) {
painter.fill_rectangle({x, 0, RES_DIVIDER, start_y}, Color(64, 64, 128));
painter.fill_rectangle({x, 0, dynamic_res, start_y}, Color(64, 64, 128));
}
if (end_y < RENDER_HEIGHT) {
painter.fill_rectangle({x, end_y, RES_DIVIDER, RENDER_HEIGHT - end_y}, Color(32, 32, 32));
painter.fill_rectangle({x, end_y, dynamic_res, RENDER_HEIGHT - end_y}, Color(32, 32, 32));
}
}
}
@ -1001,11 +1012,28 @@ void render_map(Painter& painter, bool full_clear, int16_t x_start = 0, int16_t
DoomView::DoomView(NavigationView& nav)
: nav_{nav} {
SCREEN_WIDTH = screen_width;
SCREEN_HEIGHT = screen_height;
RENDER_HEIGHT = screen_height - 40;
HALF_WIDTH = screen_width / 2;
SCREEN_WIDTH = ui::screen_width;
SCREEN_HEIGHT = ui::screen_height;
HUD_HEIGHT = 40;
RENDER_HEIGHT = SCREEN_HEIGHT - HUD_HEIGHT;
HALF_WIDTH = SCREEN_WIDTH / 2;
HALF_HEIGHT = RENDER_HEIGHT / 2;
// More aggressive resolution reduction for larger screens
if (SCREEN_WIDTH > 400) {
RES_DIVIDER = 4;
} else if (SCREEN_WIDTH > 300) {
RES_DIVIDER = 3;
} else {
RES_DIVIDER = 2;
}
// Cap gun size to prevent overflow
GUN_WIDTH = fmin(60, SCREEN_WIDTH / 8);
GUN_HEIGHT = fmin(50, SCREEN_HEIGHT / 8);
GUN_TARGET_POS = fmin(40, RENDER_HEIGHT / 13);
GUN_SHOT_POS = GUN_TARGET_POS + 6;
add_children({&dummy});
game_timer.attach(&game_timer_check, 1.0 / 60.0);
}
@ -1034,26 +1062,32 @@ void DoomView::paint(Painter& painter) {
if (scene == 0) {
auto style_yellow = *ui::Theme::getInstance()->fg_yellow;
painter.draw_string({50, 40}, style_yellow, "* * * DOOM * * *");
painter.draw_string({UI_POS_X_CENTER(15), 40}, style_yellow, "* * * DOOM * * *");
auto style_green = *ui::Theme::getInstance()->fg_green;
painter.draw_string({15, 240}, style_green, "** PRESS SELECT TO START **");
painter.draw_string({UI_POS_X_CENTER(26), SCREEN_HEIGHT - 80}, style_green, "** PRESS SELECT TO START **");
} else if (scene == 1) {
if (needs_redraw || (needs_gun_redraw && jogging > 0)) {
bool full_clear = (player.velocity == 0 || !prev_velocity_moving);
render_map(painter, full_clear);
render_entities(painter);
render_gun(painter, gun_pos, jogging);
// Draw HUD
painter.fill_rectangle({0, RENDER_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - RENDER_HEIGHT}, pp_colors[COLOR_BACKGROUND]);
auto style_yellow = *ui::Theme::getInstance()->fg_yellow;
auto style_red = *ui::Theme::getInstance()->fg_red;
auto style_blue = *ui::Theme::getInstance()->fg_blue;
painter.draw_string({5, RENDER_HEIGHT + 5}, style_yellow, "Health: " + std::to_string(player.health));
painter.draw_string({100, RENDER_HEIGHT + 5}, style_red, "Kills: " + std::to_string(kills));
painter.draw_string({170, RENDER_HEIGHT + 5}, style_blue, "Ammo: " + std::to_string(player.ammo));
int hud_y = RENDER_HEIGHT + 5;
painter.draw_string({5, hud_y}, style_yellow, "Health: " + std::to_string(player.health));
painter.draw_string({UI_POS_X_CENTER(15), hud_y}, style_red, "Kills: " + std::to_string(kills));
painter.draw_string({UI_POS_X_RIGHT(80), hud_y}, style_blue, "Ammo: " + std::to_string(player.ammo));
prev_velocity_moving = (player.velocity != 0);
needs_redraw = false;
needs_gun_redraw = false;
} else if (needs_gun_redraw) {
// Partial redraw for gun only
int current_x = HALF_WIDTH - GUN_WIDTH / 2 + sin(LPC_RTC->CTIME0 * JOGGING_SPEED) * 10 * jogging;
int current_y = RENDER_HEIGHT - gun_pos - 29 + fabs(cos(LPC_RTC->CTIME0 * JOGGING_SPEED)) * 8 * jogging;
int flash_height = (gun_pos > GUN_TARGET_POS) ? (gun_pos - GUN_TARGET_POS) * 2 + 10 : 0;
@ -1069,13 +1103,18 @@ void DoomView::paint(Painter& painter) {
render_map(painter, false, min_x, max_x);
render_entities(painter);
render_gun(painter, gun_pos, jogging);
// Redraw HUD
painter.fill_rectangle({0, RENDER_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - RENDER_HEIGHT}, pp_colors[COLOR_BACKGROUND]);
auto style_yellow = *ui::Theme::getInstance()->fg_yellow;
auto style_red = *ui::Theme::getInstance()->fg_red;
auto style_blue = *ui::Theme::getInstance()->fg_blue;
painter.draw_string({5, RENDER_HEIGHT + 5}, style_yellow, "Health: " + std::to_string(player.health));
painter.draw_string({100, RENDER_HEIGHT + 5}, style_red, "Kills: " + std::to_string(kills));
painter.draw_string({170, RENDER_HEIGHT + 5}, style_blue, "Ammo: " + std::to_string(player.ammo));
int hud_y = RENDER_HEIGHT + 5;
painter.draw_string({5, hud_y}, style_yellow, "Health: " + std::to_string(player.health));
painter.draw_string({UI_POS_X_CENTER(15), hud_y}, style_red, "Kills: " + std::to_string(kills));
painter.draw_string({UI_POS_X_RIGHT(80), hud_y}, style_blue, "Ammo: " + std::to_string(player.ammo));
needs_gun_redraw = false;
}
}

View file

@ -70,7 +70,7 @@ class DoomView : public View {
private:
NavigationView& nav_;
Button dummy{{screen_width, 0, 0, 0}, ""};
Button dummy{{0, 0, 0, 0}, ""};
bool initialized{false};
bool prev_velocity_moving{false};
MessageHandlerRegistration message_handler_frame_sync{