mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-14 16:07:43 +00:00
Prepare for display orientation part 1 (#2661)
This commit is contained in:
@@ -87,7 +87,7 @@ class ACARSAppView : public View {
|
||||
true};
|
||||
|
||||
Console console{
|
||||
{0, 3 * 16, 240, 256}};
|
||||
{0, 3 * 16, screen_width, 256}};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{28 * 8, 1 * 16}};
|
||||
|
@@ -218,7 +218,7 @@ class ADSBTxView : public View {
|
||||
void start_tx();
|
||||
void generate_frames();
|
||||
|
||||
Rect view_rect = {0, 7 * 8, 240, 192};
|
||||
Rect view_rect = {0, 7 * 8, screen_width, 192};
|
||||
|
||||
ADSBPositionView view_position{nav_, view_rect};
|
||||
ADSBCallsignView view_callsign{nav_, view_rect};
|
||||
|
@@ -105,7 +105,7 @@ class AFSKRxView : public View {
|
||||
LanguageHelper::currentMessages[LANG_MODEM_SETUP]};
|
||||
|
||||
Console console{
|
||||
{0, 4 * 16, 240, screen_width}};
|
||||
{0, 4 * 16, screen_width, screen_width}};
|
||||
|
||||
void on_data_afsk(const AFSKDataMessage& message);
|
||||
|
||||
|
@@ -86,7 +86,7 @@ class WhipCalcView : public View {
|
||||
{13 * 8, 4 * 16, 10 * 16, 16},
|
||||
"-"};
|
||||
Console console{
|
||||
{0, 6 * 16, 240, 160}};
|
||||
{0, 6 * 16, screen_width, 160}};
|
||||
|
||||
Button button_exit{
|
||||
{72, 17 * 16, 96, 32},
|
||||
|
@@ -119,7 +119,7 @@ class BLESpamView : public View {
|
||||
|
||||
#ifdef BLESPMUSECONSOLE
|
||||
Console console{
|
||||
{0, 70, 240, 220}};
|
||||
{0, 70, screen_width, 220}};
|
||||
#endif
|
||||
OptionsField options_atkmode{
|
||||
{0 * 8, 2 * 8},
|
||||
|
@@ -12,8 +12,8 @@ namespace ui::external_app::breakout {
|
||||
|
||||
Ticker game_timer;
|
||||
|
||||
int paddle_x = (SCREEN_WIDTH - PADDLE_WIDTH) / 2;
|
||||
float ball_x = SCREEN_WIDTH / 2;
|
||||
int paddle_x = 0;
|
||||
float ball_x = 0;
|
||||
float ball_y = GAME_AREA_BOTTOM - PADDLE_HEIGHT - BALL_SIZE - 1;
|
||||
float ball_dx = 1.5f;
|
||||
float ball_dy = -2.0f;
|
||||
@@ -105,7 +105,7 @@ void game_timer_check() {
|
||||
}
|
||||
|
||||
void init_game() {
|
||||
paddle_x = (SCREEN_WIDTH - PADDLE_WIDTH) / 2;
|
||||
paddle_x = (screen_width - PADDLE_WIDTH) / 2;
|
||||
score = 0;
|
||||
lives = 3;
|
||||
level = 1;
|
||||
@@ -157,7 +157,7 @@ void draw_screen() {
|
||||
}
|
||||
|
||||
void draw_borders() {
|
||||
rect(0, GAME_AREA_TOP - 1, SCREEN_WIDTH, GAME_AREA_TOP, COLOR_BORDER);
|
||||
rect(0, GAME_AREA_TOP - 1, screen_width, GAME_AREA_TOP, COLOR_BORDER);
|
||||
}
|
||||
|
||||
void draw_bricks() {
|
||||
@@ -218,14 +218,14 @@ void move_paddle_left() {
|
||||
}
|
||||
|
||||
void move_paddle_right() {
|
||||
if (paddle_x < SCREEN_WIDTH - PADDLE_WIDTH) {
|
||||
if (paddle_x < screen_width - PADDLE_WIDTH) {
|
||||
fillrect(paddle_x, PADDLE_Y, paddle_x + PADDLE_WIDTH, PADDLE_Y + PADDLE_HEIGHT, COLOR_BACKGROUND);
|
||||
if (ball_attached) {
|
||||
fillrect(ball_x, ball_y, ball_x + BALL_SIZE, ball_y + BALL_SIZE, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
paddle_x += 10;
|
||||
if (paddle_x > SCREEN_WIDTH - PADDLE_WIDTH) paddle_x = SCREEN_WIDTH - PADDLE_WIDTH;
|
||||
if (paddle_x > screen_width - PADDLE_WIDTH) paddle_x = screen_width - PADDLE_WIDTH;
|
||||
|
||||
if (ball_attached) {
|
||||
ball_x = paddle_x + (PADDLE_WIDTH / 2) - (BALL_SIZE / 2);
|
||||
@@ -277,8 +277,8 @@ void update_game() {
|
||||
if (ball_x < 0) {
|
||||
ball_x = 0;
|
||||
ball_dx = -ball_dx;
|
||||
} else if (ball_x > SCREEN_WIDTH - BALL_SIZE) {
|
||||
ball_x = SCREEN_WIDTH - BALL_SIZE;
|
||||
} else if (ball_x > screen_width - BALL_SIZE) {
|
||||
ball_x = screen_width - BALL_SIZE;
|
||||
ball_dx = -ball_dx;
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ void init_menu() {
|
||||
auto style_blue = *ui::Theme::getInstance()->fg_blue;
|
||||
auto style_cyan = *ui::Theme::getInstance()->fg_cyan;
|
||||
|
||||
int16_t screen_width = 240;
|
||||
int16_t screen_width = ui::screen_width;
|
||||
int16_t title_x = (screen_width - 17 * 8) / 2;
|
||||
int16_t divider_width = 24 * 8;
|
||||
int16_t divider_x = (screen_width - divider_width) / 2;
|
||||
@@ -428,7 +428,7 @@ void init_game_over() {
|
||||
auto style_red = *ui::Theme::getInstance()->fg_red;
|
||||
auto style_yellow = *ui::Theme::getInstance()->fg_yellow;
|
||||
|
||||
int16_t screen_width = 240;
|
||||
// int16_t screen_width = screen_width;
|
||||
int16_t title_width = 9 * 8;
|
||||
int16_t title_x = (screen_width - title_width) / 2;
|
||||
int16_t score_text_width = (16 + std::to_string(score).length()) * 8;
|
||||
@@ -484,6 +484,8 @@ void reset_game() {
|
||||
|
||||
BreakoutView::BreakoutView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
paddle_x = (screen_width - PADDLE_WIDTH) / 2;
|
||||
ball_x = screen_width / 2;
|
||||
add_children({&dummy});
|
||||
game_timer.attach(&game_timer_check, 1.0 / 60.0);
|
||||
}
|
||||
|
@@ -56,8 +56,6 @@ class Ticker {
|
||||
void detach();
|
||||
};
|
||||
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 320
|
||||
#define PADDLE_WIDTH 40
|
||||
#define PADDLE_HEIGHT 10
|
||||
#define BALL_SIZE 8
|
||||
@@ -141,7 +139,7 @@ class BreakoutView : public View {
|
||||
NavigationView& nav_;
|
||||
|
||||
Button dummy{
|
||||
{240, 0, 0, 0},
|
||||
{screen_width, 0, 0, 0},
|
||||
""};
|
||||
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
|
@@ -53,7 +53,7 @@ class CVSSpamView : public View {
|
||||
std::vector<std::filesystem::path> file_list{};
|
||||
|
||||
MenuView menu_view{
|
||||
{0, 0, 240, 180},
|
||||
{0, 0, screen_width, 180},
|
||||
true};
|
||||
|
||||
Text text_empty{
|
||||
@@ -84,7 +84,7 @@ class CVSSpamView : public View {
|
||||
LanguageHelper::currentMessages[LANG_STOP]};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{0, 256, 240, 44}};
|
||||
{0, 256, screen_width, 44}};
|
||||
|
||||
MessageHandlerRegistration message_handler_fifo_signal{
|
||||
Message::ID::RequestSignal,
|
||||
|
15
firmware/application/external/doom/ui_doom.cpp
vendored
15
firmware/application/external/doom/ui_doom.cpp
vendored
@@ -12,11 +12,11 @@
|
||||
namespace ui::external_app::doom {
|
||||
|
||||
//clang-format off
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 320
|
||||
#define RENDER_HEIGHT 280
|
||||
#define HALF_WIDTH (SCREEN_WIDTH / 2)
|
||||
#define HALF_HEIGHT (RENDER_HEIGHT / 2)
|
||||
int SCREEN_WIDTH = 0;
|
||||
int SCREEN_HEIGHT = 0;
|
||||
int RENDER_HEIGHT = 0;
|
||||
int HALF_WIDTH = 0;
|
||||
int HALF_HEIGHT = 0;
|
||||
#define LEVEL_WIDTH_BASE 6
|
||||
#define LEVEL_WIDTH (1 << LEVEL_WIDTH_BASE)
|
||||
#define LEVEL_HEIGHT 57
|
||||
@@ -1001,6 +1001,11 @@ 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;
|
||||
HALF_HEIGHT = RENDER_HEIGHT / 2;
|
||||
add_children({&dummy});
|
||||
game_timer.attach(&game_timer_check, 1.0 / 60.0);
|
||||
}
|
||||
|
@@ -70,7 +70,7 @@ class DoomView : public View {
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
Button dummy{{240, 0, 0, 0}, ""};
|
||||
Button dummy{{screen_width, 0, 0, 0}, ""};
|
||||
bool initialized{false};
|
||||
bool prev_velocity_moving{false};
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
|
@@ -73,7 +73,7 @@ class FoxhuntRxView : public View {
|
||||
{0 * 8, 2 * 16 + 4, 14 * 8, 14},
|
||||
};
|
||||
RSSIGraph rssi_graph{
|
||||
{0, 50, 240, 30},
|
||||
{0, 50, screen_width, 30},
|
||||
};
|
||||
|
||||
Button clear_markers{
|
||||
@@ -84,7 +84,7 @@ class FoxhuntRxView : public View {
|
||||
{2, 18, 7 * 8, 16},
|
||||
"Mark"};
|
||||
|
||||
GeoMap geomap{{0, 80, 240, 240}};
|
||||
GeoMap geomap{{0, 80, screen_width, screen_height - 80}};
|
||||
|
||||
MessageHandlerRegistration message_handler_gps{
|
||||
Message::ID::GPSPosData,
|
||||
|
@@ -165,12 +165,12 @@ void gfxEQView::render_equalizer(Painter& painter) {
|
||||
|
||||
if (prev_bar_heights[bar] > active_segments) {
|
||||
int clear_height = (prev_bar_heights[bar] - active_segments) * SEGMENT_HEIGHT;
|
||||
int clear_y = SCREEN_HEIGHT - prev_bar_heights[bar] * SEGMENT_HEIGHT;
|
||||
int clear_y = screen_height - prev_bar_heights[bar] * SEGMENT_HEIGHT;
|
||||
painter.fill_rectangle({x, clear_y, BAR_WIDTH, clear_height}, Color(0, 0, 0));
|
||||
}
|
||||
|
||||
for (int seg = 0; seg < active_segments; seg++) {
|
||||
int y = SCREEN_HEIGHT - (seg + 1) * SEGMENT_HEIGHT;
|
||||
int y = screen_height - (seg + 1) * SEGMENT_HEIGHT;
|
||||
if (y < header_height) break;
|
||||
|
||||
Color segment_color = (seg >= active_segments - 2 && seg < active_segments) ? theme.peak_color : theme.base_color;
|
||||
@@ -183,7 +183,7 @@ void gfxEQView::render_equalizer(Painter& painter) {
|
||||
|
||||
void gfxEQView::paint(Painter& painter) {
|
||||
if (needs_background_redraw) {
|
||||
painter.fill_rectangle({0, header_height, SCREEN_WIDTH, RENDER_HEIGHT}, Color(0, 0, 0));
|
||||
painter.fill_rectangle({0, header_height, screen_width, RENDER_HEIGHT}, Color(0, 0, 0));
|
||||
needs_background_redraw = false;
|
||||
}
|
||||
render_equalizer(painter);
|
||||
|
@@ -40,12 +40,10 @@ class gfxEQView : public View {
|
||||
|
||||
private:
|
||||
static constexpr ui::Dim header_height = 2 * 16;
|
||||
static constexpr int SCREEN_WIDTH = 240;
|
||||
static constexpr int SCREEN_HEIGHT = 320;
|
||||
static constexpr int RENDER_HEIGHT = 288;
|
||||
static constexpr int NUM_BARS = 11;
|
||||
static constexpr int BAR_SPACING = 2;
|
||||
static constexpr int BAR_WIDTH = (SCREEN_WIDTH - (BAR_SPACING * (NUM_BARS - 1))) / NUM_BARS;
|
||||
int BAR_WIDTH = (screen_width - (BAR_SPACING * (NUM_BARS - 1))) / NUM_BARS;
|
||||
static constexpr int HORIZONTAL_OFFSET = 2;
|
||||
static constexpr int SEGMENT_HEIGHT = 10;
|
||||
|
||||
|
@@ -330,7 +330,7 @@ void JammerView::on_timer() {
|
||||
JammerView::JammerView(
|
||||
NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
Rect view_rect = {0, 3 * 8, 240, 80};
|
||||
Rect view_rect = {0, 3 * 8, screen_width, 80};
|
||||
// baseband::run_image(portapack::spi_flash::image_tag_jammer);
|
||||
baseband::run_prepared_image(portapack::memory::map::m4_code.base());
|
||||
|
||||
|
@@ -178,12 +178,12 @@ class LevelView : public View {
|
||||
|
||||
RSSIGraph rssi_graph{
|
||||
// 240x320 =>
|
||||
{0, 6 * 16 + 8, 240 - 5 * 8, 320 - (6 * 16)},
|
||||
{0, 6 * 16 + 8, screen_width - 5 * 8, screen_height - (6 * 16)},
|
||||
};
|
||||
|
||||
RSSI rssi{
|
||||
// 240x320 =>
|
||||
{240 - 5 * 8, 6 * 16 + 8, 5 * 8, 320 - (6 * 16)},
|
||||
{screen_width - 5 * 8, 6 * 16 + 8, 5 * 8, screen_height - (6 * 16)},
|
||||
};
|
||||
|
||||
void handle_coded_squelch(const uint32_t value);
|
||||
|
@@ -72,16 +72,16 @@ class McuTemperatureView : public View {
|
||||
|
||||
private:
|
||||
Text text_title{
|
||||
{76, 16, 240, 16},
|
||||
{76, 16, screen_width, 16},
|
||||
"Temperature",
|
||||
};
|
||||
|
||||
McuTemperatureWidget temperature_widget{
|
||||
{0, 40, 240, 180},
|
||||
{0, 40, screen_width, 180},
|
||||
};
|
||||
|
||||
Button button_done{
|
||||
{72, 264, 96, 24},
|
||||
{72, screen_height - 56, 96, 24},
|
||||
"Done"};
|
||||
};
|
||||
|
||||
|
@@ -131,7 +131,7 @@ void NoaaAptRxView::on_status(NoaaAptRxStatusDataMessage msg) {
|
||||
|
||||
// this stores and displays the image. keep it as simple as you can. a bit more complexity will kill the sync
|
||||
void NoaaAptRxView::on_image(NoaaAptRxImageDataMessage msg) {
|
||||
if ((line_num) >= 320 - NOAA_IMG_START_ROW * 16) line_num = 0; // for draw reset
|
||||
if ((line_num) >= screen_height - NOAA_IMG_START_ROW * 16) line_num = 0; // for draw reset
|
||||
|
||||
for (uint16_t i = 0; i < msg.cnt; i += 1) {
|
||||
Color pxl = {msg.image[i], msg.image[i], msg.image[i]};
|
||||
|
@@ -77,11 +77,11 @@ class NRFRxView : public View {
|
||||
nav_};
|
||||
|
||||
Button button_modem_setup{
|
||||
{240 - 12 * 8, 1 * 16, 96, 24},
|
||||
{screen_width - 12 * 8, 1 * 16, 96, 24},
|
||||
LanguageHelper::currentMessages[LANG_MODEM_SETUP]};
|
||||
|
||||
Console console{
|
||||
{0, 4 * 16, 240, 240}};
|
||||
{0, 4 * 16, screen_width, screen_height - 80}};
|
||||
|
||||
MessageHandlerRegistration message_handler_packet{
|
||||
Message::ID::AFSKData,
|
||||
|
@@ -134,7 +134,7 @@ class OOKEditorAppView : public View {
|
||||
ProgressBar progressbar{{2 * 8, 250, 208, 16}};
|
||||
|
||||
// Waveform display using waveform buffer and yellow theme color.
|
||||
Waveform waveform{{0, 208, 240, 32}, waveform_buffer, 0, 0, true, Theme::getInstance()->fg_yellow->foreground};
|
||||
Waveform waveform{{0, 208, screen_width, 32}, waveform_buffer, 0, 0, true, Theme::getInstance()->fg_yellow->foreground};
|
||||
};
|
||||
|
||||
/******** bug key input view **********/
|
||||
|
@@ -56,7 +56,7 @@ class PlaylistEditorView : public View {
|
||||
"New"};
|
||||
|
||||
Text text_current_ppl_file{
|
||||
{sizeof("PPL file:") * 8, 0 * 16, screen_width - sizeof("PPL file:") * 8, 16},
|
||||
{sizeof("PPL file:") * 8, 0 * 16, screen_width - (int)sizeof("PPL file:") * 8, 16},
|
||||
""};
|
||||
|
||||
MenuView menu_view{};
|
||||
|
@@ -111,7 +111,7 @@ class ProtoView : public View {
|
||||
LanguageHelper::currentMessages[LANG_PAUSE]};
|
||||
|
||||
Waveform waveform{
|
||||
{0, 8 * 8, 240, 50},
|
||||
{0, 8 * 8, screen_width, 50},
|
||||
waveform_buffer,
|
||||
0,
|
||||
0,
|
||||
@@ -119,7 +119,7 @@ class ProtoView : public View {
|
||||
Theme::getInstance()->fg_yellow->foreground};
|
||||
|
||||
Waveform waveform2{
|
||||
{0, 8 * 8 + 55, 240, 50},
|
||||
{0, 8 * 8 + 55, screen_width, 50},
|
||||
&waveform_buffer[MAXDRAWCNTPERWF],
|
||||
0,
|
||||
0,
|
||||
@@ -127,7 +127,7 @@ class ProtoView : public View {
|
||||
Theme::getInstance()->fg_yellow->foreground};
|
||||
|
||||
Waveform waveform3{
|
||||
{0, 8 * 8 + 110, 240, 50},
|
||||
{0, 8 * 8 + 110, screen_width, 50},
|
||||
&waveform_buffer[MAXDRAWCNTPERWF * 2],
|
||||
0,
|
||||
0,
|
||||
@@ -135,7 +135,7 @@ class ProtoView : public View {
|
||||
Theme::getInstance()->fg_yellow->foreground};
|
||||
|
||||
Waveform waveform4{
|
||||
{0, 8 * 8 + 165, 240, 50},
|
||||
{0, 8 * 8 + 165, screen_width, 50},
|
||||
&waveform_buffer[MAXDRAWCNTPERWF * 3],
|
||||
0,
|
||||
0,
|
||||
|
@@ -203,7 +203,7 @@ class RandomPasswordView : public View {
|
||||
' '};
|
||||
|
||||
OptionsField field_method{
|
||||
{(screen_width / 2) + (sizeof("method:") - 1) * 8, 7 * 16 - 2},
|
||||
{(screen_width / 2) + (int)(sizeof("method:") - 1) * 8, 7 * 16 - 2},
|
||||
sizeof("R+L+R+H"),
|
||||
{{"R+L+R", Method::RADIO_LCG_ROLL},
|
||||
{"R+L+R+H", Method::RADIO_LCG_ROLL_HASH}}};
|
||||
|
@@ -292,12 +292,12 @@ class RemoteAppView : public View {
|
||||
bool is_sending() const { return replay_thread_ != nullptr; }
|
||||
void show_error(const std::string& msg) const;
|
||||
|
||||
static constexpr Dim button_rows = 4;
|
||||
static constexpr Dim button_cols = 3;
|
||||
static constexpr uint8_t max_buttons = button_rows * button_cols;
|
||||
static constexpr Dim button_area_height = 200;
|
||||
static constexpr Dim button_width = screen_width / button_cols;
|
||||
static constexpr Dim button_height = button_area_height / button_rows;
|
||||
Dim button_rows = 4;
|
||||
Dim button_cols = 3;
|
||||
uint8_t max_buttons = button_rows * button_cols;
|
||||
Dim button_area_height = 200;
|
||||
Dim button_width = screen_width / button_cols;
|
||||
Dim button_height = button_area_height / button_rows;
|
||||
|
||||
// This value is mysterious... why?
|
||||
static constexpr uint32_t baseband_bandwidth = 2'500'000;
|
||||
|
@@ -238,7 +238,7 @@ class ScannerView : public View {
|
||||
};
|
||||
|
||||
Text text_current_desc{
|
||||
{0, 4 * 16, 240 - 6 * 8, 16},
|
||||
{0, 4 * 16, screen_width - 6 * 8, 16},
|
||||
};
|
||||
|
||||
BigFrequency big_display{
|
||||
|
@@ -85,7 +85,7 @@ class WipeSDView : public View {
|
||||
{2 * 8, 19 * 8, 26 * 8, 24}};
|
||||
|
||||
Button dummy{
|
||||
{240, 0, 0, 0},
|
||||
{screen_width, 0, 0, 0},
|
||||
""};
|
||||
};
|
||||
|
||||
|
@@ -58,7 +58,7 @@ class ShoppingCartLock : public View {
|
||||
void restart_playback();
|
||||
|
||||
MenuView menu_view{
|
||||
{0, 0, 240, 150},
|
||||
{0, 0, screen_width, 150},
|
||||
true};
|
||||
|
||||
Text text_empty{
|
||||
|
93
firmware/application/external/snake/ui_snake.cpp
vendored
93
firmware/application/external/snake/ui_snake.cpp
vendored
@@ -10,81 +10,54 @@
|
||||
|
||||
namespace ui::external_app::snake {
|
||||
|
||||
Ticker game_timer;
|
||||
|
||||
int snake_x[GRID_WIDTH * GRID_HEIGHT];
|
||||
int snake_y[GRID_WIDTH * GRID_HEIGHT];
|
||||
int snake_length = 1;
|
||||
int snake_dx = 1;
|
||||
int snake_dy = 0;
|
||||
int food_x, food_y;
|
||||
int score = 0;
|
||||
int game_state = STATE_MENU;
|
||||
bool initialized = false;
|
||||
|
||||
const Color pp_colors[] = {
|
||||
Color::white(),
|
||||
Color::blue(),
|
||||
Color::yellow(),
|
||||
Color::purple(),
|
||||
Color::green(),
|
||||
Color::red(),
|
||||
Color::magenta(),
|
||||
Color::orange(),
|
||||
Color::black(),
|
||||
};
|
||||
|
||||
Painter painter;
|
||||
|
||||
bool but_RIGHT = false;
|
||||
bool but_LEFT = false;
|
||||
bool but_SELECT = false;
|
||||
|
||||
static Callback game_update_callback = nullptr;
|
||||
static uint32_t game_update_timeout = 0;
|
||||
static uint32_t game_update_counter = 0;
|
||||
|
||||
void cls() {
|
||||
void SnakeView::cls() {
|
||||
painter.fill_rectangle({0, 0, portapack::display.width(), portapack::display.height()}, Color::black());
|
||||
}
|
||||
|
||||
void background(int color) {
|
||||
void SnakeView::background(int color) {
|
||||
(void)color;
|
||||
}
|
||||
|
||||
void fillrect(int x1, int y1, int x2, int y2, int color) {
|
||||
void SnakeView::fillrect(int x1, int y1, int x2, int y2, int color) {
|
||||
painter.fill_rectangle({x1, y1, x2 - x1, y2 - y1}, pp_colors[color]);
|
||||
}
|
||||
|
||||
void rect(int x1, int y1, int x2, int y2, int color) {
|
||||
void SnakeView::rect(int x1, int y1, int x2, int y2, int color) {
|
||||
painter.draw_rectangle({x1, y1, x2 - x1, y2 - y1}, pp_colors[color]);
|
||||
}
|
||||
|
||||
void check_game_timer() {
|
||||
void SnakeView::check_game_timer() {
|
||||
if (game_update_callback) {
|
||||
if (++game_update_counter >= game_update_timeout) {
|
||||
game_update_counter = 0;
|
||||
game_update_callback();
|
||||
game_timer_check();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Ticker::attach(Callback func, double delay_sec) {
|
||||
game_update_callback = func;
|
||||
void SnakeView::attach(double delay_sec) {
|
||||
game_update_callback = true;
|
||||
game_update_timeout = delay_sec * 60;
|
||||
}
|
||||
|
||||
void Ticker::detach() {
|
||||
game_update_callback = nullptr;
|
||||
void SnakeView::detach() {
|
||||
game_update_callback = false;
|
||||
}
|
||||
|
||||
void game_timer_check() {
|
||||
void SnakeView::game_timer_check() {
|
||||
if (game_state == STATE_PLAYING) {
|
||||
update_game();
|
||||
}
|
||||
}
|
||||
|
||||
void init_game() {
|
||||
void SnakeView::init_game() {
|
||||
SCREEN_WIDTH = screen_width;
|
||||
SCREEN_HEIGHT = screen_height;
|
||||
GAME_AREA_HEIGHT = (SCREEN_HEIGHT - INFO_BAR_HEIGHT - 2);
|
||||
GRID_WIDTH = ((SCREEN_WIDTH - 2) / SNAKE_SIZE);
|
||||
GRID_HEIGHT = (GAME_AREA_HEIGHT / SNAKE_SIZE);
|
||||
snake_x.resize(GRID_WIDTH * GRID_HEIGHT);
|
||||
snake_y.resize(GRID_WIDTH * GRID_HEIGHT);
|
||||
snake_x[0] = GRID_WIDTH / 2;
|
||||
snake_y[0] = GRID_HEIGHT / 2;
|
||||
snake_length = 1;
|
||||
@@ -99,7 +72,7 @@ void init_game() {
|
||||
}
|
||||
}
|
||||
|
||||
void spawn_food() {
|
||||
void SnakeView::spawn_food() {
|
||||
bool valid;
|
||||
do {
|
||||
food_x = rand() % GRID_WIDTH;
|
||||
@@ -114,7 +87,7 @@ void spawn_food() {
|
||||
} while (!valid);
|
||||
}
|
||||
|
||||
void update_game() {
|
||||
void SnakeView::update_game() {
|
||||
int new_x = snake_x[0] + snake_dx;
|
||||
int new_y = snake_y[0] + snake_dy;
|
||||
bool ate_food = (new_x == food_x && new_y == food_y);
|
||||
@@ -152,7 +125,7 @@ void update_game() {
|
||||
}
|
||||
}
|
||||
|
||||
bool check_collision() {
|
||||
bool SnakeView::check_collision() {
|
||||
if (snake_x[0] < 0 || snake_x[0] >= GRID_WIDTH || snake_y[0] < 0 || snake_y[0] >= GRID_HEIGHT) {
|
||||
return true;
|
||||
}
|
||||
@@ -164,7 +137,7 @@ bool check_collision() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void draw_screen() {
|
||||
void SnakeView::draw_screen() {
|
||||
cls();
|
||||
background(COLOR_BACKGROUND);
|
||||
draw_borders();
|
||||
@@ -173,44 +146,44 @@ void draw_screen() {
|
||||
draw_score();
|
||||
}
|
||||
|
||||
void draw_snake() {
|
||||
void SnakeView::draw_snake() {
|
||||
fillrect(1 + snake_x[0] * SNAKE_SIZE, GAME_AREA_TOP + snake_y[0] * SNAKE_SIZE,
|
||||
1 + snake_x[0] * SNAKE_SIZE + SNAKE_SIZE, GAME_AREA_TOP + snake_y[0] * SNAKE_SIZE + SNAKE_SIZE, COLOR_SNAKE);
|
||||
}
|
||||
|
||||
void draw_full_snake() {
|
||||
void SnakeView::draw_full_snake() {
|
||||
for (int i = 0; i < snake_length; i++) {
|
||||
fillrect(1 + snake_x[i] * SNAKE_SIZE, GAME_AREA_TOP + snake_y[i] * SNAKE_SIZE,
|
||||
1 + snake_x[i] * SNAKE_SIZE + SNAKE_SIZE, GAME_AREA_TOP + snake_y[i] * SNAKE_SIZE + SNAKE_SIZE, COLOR_SNAKE);
|
||||
}
|
||||
}
|
||||
|
||||
void erase_tail(int x, int y) {
|
||||
void SnakeView::erase_tail(int x, int y) {
|
||||
fillrect(1 + x * SNAKE_SIZE, GAME_AREA_TOP + y * SNAKE_SIZE,
|
||||
1 + x * SNAKE_SIZE + SNAKE_SIZE, GAME_AREA_TOP + y * SNAKE_SIZE + SNAKE_SIZE, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
void draw_food() {
|
||||
void SnakeView::draw_food() {
|
||||
fillrect(1 + food_x * SNAKE_SIZE, GAME_AREA_TOP + food_y * SNAKE_SIZE,
|
||||
1 + food_x * SNAKE_SIZE + SNAKE_SIZE, GAME_AREA_TOP + food_y * SNAKE_SIZE + SNAKE_SIZE, COLOR_FOOD);
|
||||
}
|
||||
|
||||
void erase_food() {
|
||||
void SnakeView::erase_food() {
|
||||
fillrect(1 + food_x * SNAKE_SIZE, GAME_AREA_TOP + food_y * SNAKE_SIZE,
|
||||
1 + food_x * SNAKE_SIZE + SNAKE_SIZE, GAME_AREA_TOP + food_y * SNAKE_SIZE + SNAKE_SIZE, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
void draw_score() {
|
||||
void SnakeView::draw_score() {
|
||||
auto style = *ui::Theme::getInstance()->fg_blue;
|
||||
painter.draw_string({5, 5}, style, "Score: " + std::to_string(score));
|
||||
}
|
||||
|
||||
void draw_borders() {
|
||||
void SnakeView::draw_borders() {
|
||||
rect(0, GAME_AREA_TOP - 1, SCREEN_WIDTH, GAME_AREA_TOP, COLOR_BORDER);
|
||||
rect(0, GAME_AREA_TOP, SCREEN_WIDTH, SCREEN_HEIGHT, COLOR_BORDER);
|
||||
}
|
||||
|
||||
void show_menu() {
|
||||
void SnakeView::show_menu() {
|
||||
cls();
|
||||
background(COLOR_BACKGROUND);
|
||||
auto style_yellow = *ui::Theme::getInstance()->fg_yellow;
|
||||
@@ -223,7 +196,7 @@ void show_menu() {
|
||||
painter.draw_string({15, 240}, style_green, "** PRESS SELECT TO START **");
|
||||
}
|
||||
|
||||
void show_game_over() {
|
||||
void SnakeView::show_game_over() {
|
||||
cls();
|
||||
background(COLOR_BACKGROUND);
|
||||
auto style_red = *ui::Theme::getInstance()->fg_red;
|
||||
@@ -238,7 +211,7 @@ void show_game_over() {
|
||||
SnakeView::SnakeView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
add_children({&dummy});
|
||||
game_timer.attach(&game_timer_check, 1.0 / 5.0);
|
||||
attach(1.0 / 5.0);
|
||||
}
|
||||
|
||||
void SnakeView::on_show() {
|
||||
|
113
firmware/application/external/snake/ui_snake.hpp
vendored
113
firmware/application/external/snake/ui_snake.hpp
vendored
@@ -32,36 +32,11 @@ enum {
|
||||
Black,
|
||||
};
|
||||
|
||||
extern const Color pp_colors[];
|
||||
extern Painter painter;
|
||||
extern bool but_RIGHT;
|
||||
extern bool but_LEFT;
|
||||
extern bool but_SELECT;
|
||||
|
||||
void cls();
|
||||
void background(int color);
|
||||
void fillrect(int x1, int y1, int x2, int y2, int color);
|
||||
void rect(int x1, int y1, int x2, int y2, int color);
|
||||
|
||||
#define wait(x) chThdSleepMilliseconds(x * 1000)
|
||||
|
||||
using Callback = void (*)(void);
|
||||
|
||||
class Ticker {
|
||||
public:
|
||||
Ticker() = default;
|
||||
void attach(Callback func, double delay_sec);
|
||||
void detach();
|
||||
};
|
||||
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 320
|
||||
#define SNAKE_SIZE 10
|
||||
#define INFO_BAR_HEIGHT 25
|
||||
#define GAME_AREA_TOP (INFO_BAR_HEIGHT + 1)
|
||||
#define GAME_AREA_HEIGHT (SCREEN_HEIGHT - INFO_BAR_HEIGHT - 2)
|
||||
#define GRID_WIDTH ((SCREEN_WIDTH - 2) / SNAKE_SIZE)
|
||||
#define GRID_HEIGHT (GAME_AREA_HEIGHT / SNAKE_SIZE)
|
||||
#define STATE_MENU 0
|
||||
#define STATE_PLAYING 1
|
||||
#define STATE_GAME_OVER 2
|
||||
@@ -71,35 +46,6 @@ class Ticker {
|
||||
#define COLOR_FOOD Red
|
||||
#define COLOR_BORDER White
|
||||
|
||||
extern Ticker game_timer;
|
||||
|
||||
extern int snake_x[GRID_WIDTH * GRID_HEIGHT];
|
||||
extern int snake_y[GRID_WIDTH * GRID_HEIGHT];
|
||||
extern int snake_length;
|
||||
extern int snake_dx;
|
||||
extern int snake_dy;
|
||||
extern int food_x;
|
||||
extern int food_y;
|
||||
extern int score;
|
||||
extern int game_state;
|
||||
extern bool initialized;
|
||||
|
||||
void game_timer_check();
|
||||
void init_game();
|
||||
void update_game();
|
||||
void draw_screen();
|
||||
void draw_snake();
|
||||
void draw_full_snake();
|
||||
void erase_tail(int x, int y);
|
||||
void draw_food();
|
||||
void erase_food();
|
||||
void draw_score();
|
||||
void draw_borders();
|
||||
void spawn_food();
|
||||
bool check_collision();
|
||||
void show_menu();
|
||||
void show_game_over();
|
||||
|
||||
class SnakeView : public View {
|
||||
public:
|
||||
SnakeView(NavigationView& nav);
|
||||
@@ -112,12 +58,67 @@ class SnakeView : public View {
|
||||
void frame_sync();
|
||||
bool on_key(KeyEvent key) override;
|
||||
|
||||
void cls();
|
||||
void background(int color);
|
||||
void fillrect(int x1, int y1, int x2, int y2, int color);
|
||||
void rect(int x1, int y1, int x2, int y2, int color);
|
||||
void game_timer_check();
|
||||
void init_game();
|
||||
void update_game();
|
||||
void draw_screen();
|
||||
void draw_snake();
|
||||
void draw_full_snake();
|
||||
void erase_tail(int x, int y);
|
||||
void draw_food();
|
||||
void erase_food();
|
||||
void draw_score();
|
||||
void draw_borders();
|
||||
void spawn_food();
|
||||
bool check_collision();
|
||||
void show_menu();
|
||||
void show_game_over();
|
||||
void check_game_timer();
|
||||
|
||||
void attach(double delay_sec);
|
||||
void detach();
|
||||
|
||||
private:
|
||||
bool initialized = false;
|
||||
const Color pp_colors[9] = {
|
||||
Color::white(),
|
||||
Color::blue(),
|
||||
Color::yellow(),
|
||||
Color::purple(),
|
||||
Color::green(),
|
||||
Color::red(),
|
||||
Color::magenta(),
|
||||
Color::orange(),
|
||||
Color::black(),
|
||||
};
|
||||
NavigationView& nav_;
|
||||
Painter painter{};
|
||||
|
||||
std::vector<int> snake_x{}; //[GRID_WIDTH * GRID_HEIGHT];
|
||||
std::vector<int> snake_y{}; //[GRID_WIDTH * GRID_HEIGHT];
|
||||
int snake_length = 1;
|
||||
int snake_dx = 1;
|
||||
int snake_dy = 0;
|
||||
int food_x = 0, food_y = 0;
|
||||
int score = 0;
|
||||
int game_state = STATE_MENU;
|
||||
bool initialized = false;
|
||||
|
||||
int SCREEN_WIDTH = 0;
|
||||
int SCREEN_HEIGHT = 0;
|
||||
int GAME_AREA_HEIGHT = 0; //(SCREEN_HEIGHT - INFO_BAR_HEIGHT - 2);
|
||||
int GRID_WIDTH = 0; // ((SCREEN_WIDTH - 2) / SNAKE_SIZE);
|
||||
int GRID_HEIGHT = 0; //(GAME_AREA_HEIGHT / SNAKE_SIZE);
|
||||
|
||||
bool game_update_callback = false;
|
||||
double game_update_timeout = 0;
|
||||
uint32_t game_update_counter = 0;
|
||||
|
||||
Button dummy{
|
||||
{240, 0, 0, 0},
|
||||
{screen_width, 0, 0, 0},
|
||||
""};
|
||||
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
|
@@ -55,7 +55,7 @@ SpectrumPainterView::SpectrumPainterView(
|
||||
&field_pause,
|
||||
});
|
||||
|
||||
Rect view_rect = {0, 3 * 8, 240, 80};
|
||||
Rect view_rect = {0, 3 * 8, screen_width, 80};
|
||||
input_image.set_parent_rect(view_rect);
|
||||
input_text.set_parent_rect(view_rect);
|
||||
|
||||
|
@@ -89,7 +89,7 @@ class SpectrumPainterView : public View {
|
||||
|
||||
static constexpr int32_t footer_location = 15 * 16 + 8;
|
||||
ProgressBar progressbar{
|
||||
{4, footer_location - 16, 240 - 8, 16}};
|
||||
{4, footer_location - 16, screen_width - 8, 16}};
|
||||
|
||||
Labels labels{
|
||||
{{10 * 8, footer_location + 1 * 16}, "GAIN A:", Theme::getInstance()->fg_light->foreground},
|
||||
|
@@ -244,12 +244,12 @@ std::vector<uint8_t> SpectrumInputImageView::get_line(uint16_t y) {
|
||||
|
||||
void SpectrumInputImageView::paint(Painter& painter) {
|
||||
painter.fill_rectangle(
|
||||
{{0, 40}, {240, 204}},
|
||||
{{0, 40}, {screen_width, 204}},
|
||||
style().background);
|
||||
|
||||
if (!painted) {
|
||||
// This is very slow for big pictures. Do only once.
|
||||
this->drawBMP_scaled({{0, 40}, {240, 160}}, this->file);
|
||||
this->drawBMP_scaled({{0, 40}, {screen_width, 160}}, this->file);
|
||||
painted = true;
|
||||
}
|
||||
}
|
||||
|
@@ -73,7 +73,7 @@ void SpectrumInputTextView::paint(Painter& painter) {
|
||||
}
|
||||
|
||||
painter.fill_rectangle(
|
||||
{{0, 40}, {240, 204}},
|
||||
{{0, 40}, {screen_width, 204}},
|
||||
style().background);
|
||||
}
|
||||
|
||||
|
@@ -75,11 +75,11 @@ class StopwatchView : public View {
|
||||
"START"};
|
||||
|
||||
Button button_reset_lap{
|
||||
{72, 240, 96, 24},
|
||||
{72, screen_height - 80, 96, 24},
|
||||
"RESET"};
|
||||
|
||||
Button button_done{
|
||||
{72, 270, 96, 24},
|
||||
{72, screen_height - 50, 96, 24},
|
||||
"EXIT"};
|
||||
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
|
@@ -209,9 +209,9 @@ void StartGame() {
|
||||
cls();
|
||||
background(Black);
|
||||
foreground(White);
|
||||
fillrect(0, 0, 162, 320, Black);
|
||||
rect(162, 0, 164, 320, White);
|
||||
fillrect(164, 0, 240, 320, Black);
|
||||
fillrect(0, 0, 162, screen_height, Black);
|
||||
rect(162, 0, 164, screen_height, White);
|
||||
fillrect(164, 0, screen_width, screen_height, Black);
|
||||
ShowScore();
|
||||
ShowNextFigure();
|
||||
}
|
||||
@@ -483,7 +483,7 @@ void UpdateBoard() {
|
||||
board[i - numberOfLines][j] = 0;
|
||||
}
|
||||
}
|
||||
fillrect(0, 0, 162, 320, Black);
|
||||
fillrect(0, 0, 162, screen_height, Black);
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (int j = 0; j < 10; j++) {
|
||||
if (board[i][j] != 0) {
|
||||
|
@@ -148,7 +148,7 @@ class TetrisView : public View {
|
||||
NavigationView& nav_;
|
||||
|
||||
Button dummy{
|
||||
{240, 0, 0, 0},
|
||||
{screen_width, 0, 0, 0},
|
||||
""};
|
||||
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
|
@@ -76,12 +76,12 @@ class TunerView : public View {
|
||||
{{0 * 8, 5 * 16}, "Volume:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_note_frequency{
|
||||
{(sizeof("Note Frequency:") + 1) * 8, 3 * 16, screen_width - (sizeof("Note Frequency:") + 1) * 8, 16},
|
||||
{(sizeof("Note Frequency:") + 1) * 8, 3 * 16, (int)screen_width - (int)(sizeof("Note Frequency:") + 1) * 8, 16},
|
||||
"",
|
||||
};
|
||||
|
||||
Text text_note_octave_shift{
|
||||
{(sizeof("Note Octave Shift:") + 1) * 8, 4 * 16, screen_width - (sizeof("Note Octave Shift:") + 1) * 8, 16},
|
||||
{(sizeof("Note Octave Shift:") + 1) * 8, 4 * 16, (int)screen_width - (int)(sizeof("Note Octave Shift:") + 1) * 8, 16},
|
||||
"",
|
||||
};
|
||||
|
||||
|
@@ -54,7 +54,7 @@ class WardriveMapView : public View {
|
||||
{0, 20},
|
||||
GeoPos::alt_unit::METERS,
|
||||
GeoPos::spd_unit::HIDDEN};
|
||||
GeoMap geomap{{0, 75, 240, 320 - 75}};
|
||||
GeoMap geomap{{0, 75, screen_width, screen_height - 75}};
|
||||
|
||||
Button btn_back{{22 * 8, 0 * 8, 3 * 8, 16}, "<-"};
|
||||
Button btn_next{{26 * 8, 0 * 8, 3 * 8, 16}, "->"};
|
||||
|
@@ -121,7 +121,7 @@ class ViewWavView : public View {
|
||||
{28 * 8, 18 * 16}};
|
||||
|
||||
Waveform waveform{
|
||||
{0, 5 * 16, 240, 64},
|
||||
{0, 5 * 16, screen_width, 64},
|
||||
waveform_buffer,
|
||||
240,
|
||||
0,
|
||||
|
@@ -130,7 +130,7 @@ void WeFaxRxView::on_status(WeFaxRxStatusDataMessage msg) {
|
||||
|
||||
// this stores and displays the image. keep it as simple as you can. a bit more complexity will kill the sync
|
||||
void WeFaxRxView::on_image(WeFaxRxImageDataMessage msg) {
|
||||
if ((line_num) >= 320 - 4 * 16) line_num = 0; // for draw reset
|
||||
if ((line_num) >= screen_height - 4 * 16) line_num = 0; // for draw reset
|
||||
|
||||
for (uint16_t i = 0; i < msg.cnt; i += 1) {
|
||||
Color pxl = {msg.image[i], msg.image[i], msg.image[i]};
|
||||
|
Reference in New Issue
Block a user