BosonX/src/menu.cpp

349 lines
7.5 KiB
C++

#include "util.h"
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/timer.h>
#include <gint/gint.h>
#include <gint/cpu.h>
#include <gint/defs/util.h>
//---
// Internal timers routines
//---
static int __menu_offset_update(int *menu_offset)
{
if(*menu_offset < 0)
*menu_offset = min(*menu_offset + 6, 0);
if(*menu_offset > 0)
*menu_offset = max(*menu_offset - 6, 0);
return TIMER_CONTINUE;
}
static int __title_blink_update(int *blink)
{
*blink ^= 1;
return TIMER_CONTINUE;
}
//---
// Internal menu content management
//---
#define annimX(x) ((x) + offset)
#define annimY(y) (y)
static void menu_display_start(int offset, int title_blink)
{
extern image_t img_bosonx_logo;
extern image_t img_bosonx_title;
dimage(
annimX((DWIDTH / 2) - (img_bosonx_logo.width / 2)),
annimY((DHEIGHT / 4) - (img_bosonx_logo.height / 2) - 6),
&img_bosonx_logo
);
dimage(
annimX((DWIDTH / 2) - (img_bosonx_title.width / 2)),
annimY((DHEIGHT / 2) - (img_bosonx_title.height / 2)),
&img_bosonx_title
);
dtext_opt(
annimX(DWIDTH / 2),
annimY((DHEIGHT / 2) + 18),
C_WHITE, C_NONE,
DTEXT_CENTER, DTEXT_TOP,
" status: undiscovered"
);
if (title_blink != 0 && offset == 0) {
dtext_opt(
DWIDTH / 2,
(DHEIGHT / 2) + 48,
C_WHITE, C_NONE,
DTEXT_CENTER, DTEXT_TOP,
"PRESS SHIFT TO START"
);
}
}
static void menu_display_about(int offset)
{
extern image_t img_bosonx_logo_empty;
extern image_t img_lepheyatis_logo;
dimage(
annimX((DWIDTH / 2) - (img_bosonx_logo_empty.width / 2)),
annimY((DHEIGHT / 4) - (img_bosonx_logo_empty.height / 2) - 6),
&img_bosonx_logo_empty
);
dimage(
annimX((DWIDTH / 2) - (img_lepheyatis_logo.width / 2)),
annimY((DHEIGHT / 2) + (DHEIGHT / 4) - (img_lepheyatis_logo.height / 2) - 15),
&img_lepheyatis_logo
);
dtext(annimX(8), annimY( 6), C_WHITE, "BIBLIOGRAPHY");
dtext(annimX(8), annimY(16), C_WHITE, "and acknowledgments");
dline(annimX(6), annimY(28), annimX(DWIDTH - 6), annimY(28), C_WHITE);
dtext_opt(
annimX(DWIDTH/ 2),
annimY(47),
C_WHITE, C_NONE,
DTEXT_CENTER, DTEXT_MIDDLE,
"ORIGINAL GAME BY IAN MACLARTY AND JON KERNEY"
);
dtext_opt(
annimX(DWIDTH/ 2),
annimY(60),
C_WHITE, C_NONE,
DTEXT_CENTER, DTEXT_MIDDLE,
"www.boson-x.com"
);
dtext_opt(
annimX(DWIDTH / 2),
annimY(DHEIGHT / 2) - 5,
C_WHITE, C_NONE,
DTEXT_CENTER, DTEXT_MIDDLE,
"ADAPTED BY LEPHENIXNOIR AND YATIS"
);
}
//---
// public
//---
int menu_title(void)
{
volatile int title_blink;
int selected = 0;
int timer0;
int timer1;
unsigned int exit;
uint16_t start_col;
uint16_t about_col;
volatile int menu_offset = 0;
timer0 = timer_configure(
TIMER_ANY,
3300,
GINT_CALL(&__menu_offset_update, &menu_offset)
);
title_blink = 1;
timer1 = timer_configure(
TIMER_ANY,
500000,
GINT_CALL(&__title_blink_update, &title_blink)
);
timer_start(timer0);
timer_start(timer1);
exit = 0xdeadbeef;
selected = 0;
while(exit == 0xdeadbeef)
{
dclear(RGB24(0x49759f));
/* Load atomically to avoid data races */
int off = menu_offset;
/* Display the current screen, and the one next to it if sliding */
int show_left = selected - (selected > 0 && off > 0);
int show_right = show_left + (off != 0);
for(int i = show_left; i <= show_right; i++)
{
int offset = off + DWIDTH * (i - selected);
if(i == 0)
menu_display_start(offset, title_blink);
if(i == 1)
menu_display_about(offset);
}
drect(0, DHEIGHT - 32, DWIDTH, DHEIGHT, C_WHITE);
drect_border(
(DWIDTH / 4) - 35 + ((DWIDTH / 2) * selected),
DHEIGHT - 27,
(DWIDTH / 4) + 35 + ((DWIDTH / 2) * selected),
DHEIGHT - 5,
C_NONE,
2, RGB24(0xca8a8a)
);
start_col = RGB24(0xca8a8a);
about_col = RGB24(0x49759f);
if (selected == 1) {
start_col = RGB24(0x49759f);
about_col = RGB24(0xca8a8a);
}
dtext_opt(
DWIDTH / 4,
DHEIGHT - 20,
start_col, C_NONE,
DTEXT_CENTER,
DTEXT_TOP,
"START"
);
dtext_opt(
(DWIDTH / 2) + (DWIDTH / 4),
DHEIGHT - 20,
about_col, C_NONE,
DTEXT_CENTER,
DTEXT_TOP,
"ABOUT"
);
dupdate();
key_event_t ev;
while((ev = pollevent()).type != KEYEV_NONE) {
if(ev.type == KEYEV_UP || ev.type == KEYEV_HOLD)
continue;
if (ev.key == KEY_SHIFT && selected == 0) exit = 0;
if (ev.key == KEY_LEFT && selected > 0) {
selected--;
menu_offset = -DWIDTH;
}
if (ev.key == KEY_RIGHT && selected < 1) {
selected++;
menu_offset = DWIDTH;
}
if (ev.key == KEY_MENU || ev.key == KEY_EXIT) exit = -1;
}
}
timer_stop(timer1);
timer_stop(timer0);
return exit;
}
int menu_select_level(int *select)
{
extern image_t img_bosonx_logo_empty;
extern image_t img_stage1;
extern image_t img_stage2;
extern image_t img_stage3;
extern image_t img_stage4;
extern image_t img_stage5;
extern image_t img_stage6;
struct {
image_t *img;
int peak;
char const * const name;
} stage[6] = {
{ .img = &img_stage1, .peak = 10, .name = "GEON" },
{ .img = &img_stage2, .peak = 56, .name = "ACCELERON"},
{ .img = &img_stage3, .peak = 34, .name = "RADION"},
{ .img = &img_stage4, .peak = 100, .name = "GRAVITON"},
{ .img = &img_stage5, .peak = 245, .name = "Y BOSON"},
{ .img = &img_stage6, .peak = -1, .name = "X BOSON"},
};
unsigned int exit;
int selected;
int color;
int colorb;
char const *text;
int x;
int y;
selected = 0;
exit = 0xdeadbeef;
while (exit == 0xdeadbeef) {
dclear(RGB24(0x49759f));
dimage(
(DWIDTH / 2) - (img_bosonx_logo_empty.width / 2),
(DHEIGHT / 4) - (img_bosonx_logo_empty.height / 2) - 6,
&img_bosonx_logo_empty
);
dtext(8, 6, C_WHITE, stage[selected].name);
dtext(8, 16, C_WHITE, "select experiment");
dline(6, 28, DWIDTH - 6, 28, C_WHITE);
for (int i = 0; i < 6; ++i)
{
x = 14 + ((i % 3) * 128);
y = 55 + ((i / 3) * 72);
if (i == selected) {
drect_border(
x - 4, y - 4, x + 121, y + 66, C_NONE,
2, RGB24(0xcc8181)
);
}
color = RGB24(0xb2ccd4);
colorb = RGB24(0x648da7);
if (stage[i].peak < 100) {
color = RGB24(0xd8d7ce);
colorb = RGB24(0x7492a4);
}
if (stage[i].peak < 0) {
color = RGB24(0x5686ad);
colorb = RGB24(0x3c79a9);
}
drect(x, y, x + 115, y + 60, color);
dline(x + 116, y + 1, x + 116, y + 61, colorb);
dline(x + 117, y + 2, x + 117, y + 62, colorb);
dline(x + 1, y + 61, x + 116, y + 61, colorb);
dline(x + 2, y + 62, x + 116, y + 62, colorb);
if (stage[i].peak < 0)
continue;
dimage(x + 4, y + 4, stage[i].img);
dline(x + 4, y + 32, x + 101, y + 32, RGB24(0x2d4e6a));
text = "DISCOVERED";
color = RGB24(0x47a2c9);
if (stage[i].peak < 100) {
color = RGB24(0xcc8181);
text = "UNDISCOVERED";
}
dtext(x + 4, y + 35, color, text);
drect(x + 4, y + 48, x + 9, y + 53, color);
dprint(
x + 14,
y + 46,
RGB24(0x2d4e6a),
"peak: %d%%",
stage[i].peak
);
}
dupdate();
key_event_t ev;
while((ev = pollevent()).type != KEYEV_NONE) {
if(ev.type == KEYEV_UP || ev.type == KEYEV_HOLD)
continue;
if (ev.key == KEY_LEFT) selected -= 1;
if (ev.key == KEY_RIGHT) selected += 1;
if (ev.key == KEY_EXIT) exit = -1;
if (ev.key == KEY_SHIFT) exit = 0;
if (ev.key == KEY_MENU) gint_osmenu();
if (ev.key == KEY_DOWN && selected < 3) selected += 3;
if (ev.key == KEY_UP && selected > 2) selected -= 3;
}
if (selected >= 6) selected = 5;
if (selected < 0) selected = 0;
while (selected > 0) {
if (stage[selected].peak >= 0)
break;
selected -= 1;
}
}
if (select != NULL)
*select = selected;
return exit;
}