add first two menus

This commit is contained in:
Yann MAGNIN 2022-08-14 16:31:09 +02:00
commit be50e9fc66
15 changed files with 488 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.vxsdk
*.map
test/

BIN
GravityDuck Executable file

Binary file not shown.

93
Makefile Normal file
View File

@ -0,0 +1,93 @@
#! /usr/bin/make -f
#
# variable definition
#
# color definition, for swagg :D
red := \033[1;31m
green := \033[1;32m
blue := \033[1;34m
white := \033[1;37m
nocolor := \033[1;0m
src := $(foreach path,\
$(shell find src -not -path "*/\.*" -type d), \
$(wildcard $(path)/*.c) \
$(wildcard $(path)/*.S) \
$(wildcard $(path)/*.s))
obj := $(patsubst src_%,$(VXSDK_PREFIX_BUILD)/%.o,$(subst /,_,$(src)))
obj += $(patsubst \
$(VXSDK_ASSETS_SRC)/%,\
$(VXSDK_ASSETS_BUILD)/%.o,\
$(wildcard $(VXSDK_ASSETS_SRC)/*.c) \
)
cflags := -ffreestanding -nostdlib -m4-nofpu -fPIE -O1
cflags += -mb -fstrict-volatile-bitfields -Wa,--dsp
cflags += $(VXSDK_CFLAGS_INCLUDE) -Iinclude
# debug vars
VERBOSE ?= true
#
# build rules
#
GravityDuck: $(obj)
@ printf "$(blue)Create $(red)$@$(nocolor)\n"
sh-elf-vhex-gcc \
-T $(VXSDK_PREFIX_LIB)/fxcg50.ld \
-Wl,-q -Wl,-Map=$(VXSDK_PREFIX_BUILD)/map \
$(VXSDK_CFLAGS_LINK) \
-o $@ $^ \
-Wl,--whole-archive -lvhex-fxcg50 \
-Wl,--no-whole-archive -lc -lgcc
#vxsdk conv addin -b $@ -n vxaddin -o /tmp/vxaddin
version:
@echo "$(VXSDK_PKG_VERSION)"
help:
@ echo 'Rules listing:'
@ echo '... all the default, if no target is provided'
@ echo '... clean remove build object'
@ echo '... fclean remove all generated object'
@ echo '... re same as `make fclean all`'
@ echo '... version display version'
@ echo '... install install the library'
@ echo '... uninstall uninstall the library'
.PHONY: help version
#
# Object rules
#
$(VXSDK_PREFIX_BUILD)%.o:
ifneq ($(VERBOSE),false)
@ mkdir -p $(dir $@)
sh-elf-vhex-gcc \
$(cflags) -D FXCG50 \
-o $@ \
-c $(addprefix src/,$(subst _,/,$(notdir $(basename $@))))
else
@ mkdir -p $(dir $@)
@ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n"
@ sh-elf-vhex-gcc \
$(cflags) -D FXCG50 \
-o $@ \
-c $(addprefix src/,$(subst _,/,$(notdir $(basename $@))))
endif
$(VXSDK_ASSETS_BUILD)%.o: $(VXSDK_ASSETS_SRC)/%
ifneq ($(VERBOSE),false)
@ mkdir -p $(dir $@)
sh-elf-vhex-gcc $(cflags) -D FXCG50 -o $@ -c $<
else
@ mkdir -p $(dir $@)
@ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n"
@ sh-elf-vhex-gcc $(cflags) -D FXCG50 -o $@ -c $<
endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
assets/gduck_menu_title.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/troll.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

34
assets/vxconv.toml Normal file
View File

@ -0,0 +1,34 @@
[gduck_menu_title]
type = 'image'
profile = 'p4a'
path = 'gduck_menu_title.png'
[gduck_menu_select_title]
type = 'image'
profile = 'p4a'
path = 'gduck_menu_select_title.png'
[gduck_menu_select_button_bg]
type = 'image'
profile = 'p4a'
path = 'gduck_menu_select_button_bg.png'
[gduck_menu_select_button_0]
type = 'image'
profile = 'p4a'
path = 'gduck_menu_select_button_0.png'
[gduck_menu_select_button_1]
type = 'image'
profile = 'p4a'
path = 'gduck_menu_select_button_1.png'
[gduck_menu_select_button_2]
type = 'image'
profile = 'p4a'
path = 'gduck_menu_select_button_2.png'
[troll]
type = 'image'
profile = 'p4'
path = 'troll.png'

10
include/gduck/menu.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _MENU
#define _MENU
/* menu_title() : display logo/animation and wait user interaction */
extern void menu_title(void);
/* menu_main() : display menu selection */
extern int menu_main(void);
#endif //_MENU

47
src/main.c Normal file
View File

@ -0,0 +1,47 @@
#include <vhex/display.h>
#include <string.h>
#include <stdint.h>
extern void menu_title(void);
extern int menu_select(int max_level);
int main(void)
{
extern const image_t troll;
int level;
menu_title();
level = menu_select(12);
dclear(C_WHITE);
dimage(
&troll,
dwidth() / 2,
dheight() / 2,
DIMAGE_CENTER | DIMAGE_MIDDLE
);
dprint(0, 0, C_BLACK, "selected level = %d", level);
dupdate();
while (1) { __asm__("sleep"); }
#if 0
unlock = 0;
id_level = 0;
while(1) {
id_level = menu_main(id_level, unlock);
if (id_level < 0) break;
if(id_level == 1) intro();
id_level = engine_main(id_level);
if(id_level > unlock) {
unlock = id_level;
save_write(unlock);
}
if(id_level > NB_LEVEL) {
ending();
menu_title();
}
}
#endif
return (0);
}

290
src/menu.c Normal file
View File

@ -0,0 +1,290 @@
#include <vhex/display.h>
#include <vhex/display/draw/circle.h>
#include <vhex/display/draw/pixel.h>
#include <vhex/display/image.h>
#include <vhex/timer.h>
#include <vhex/timer/fps.h>
#include <vhex/timer/profiling.h>
#include <vhex/keyboard.h>
#define BG_COLOR 0x869c
#define CIRCLE_COLOR 0xcf1c
#define NB_CIRCLE 9
#define NB_BUTTON_ROW 8
#define NB_BUTTON_COL 5
#define NB_BUTTON_TOTAL (NB_BUTTON_ROW * NB_BUTTON_COL)
/* define internal circle information structure */
struct circle {
int x;
int y;
int size;
} circle[NB_CIRCLE] = {
{ .x = 42, .y = 163, .size = 35 },
{ .x = 72, .y = 31, .size = 55 },
{ .x = 223, .y = 239, .size = 60 },
{ .x = 265, .y = 109, .size = 51 },
{ .x = 358, .y = 0, .size = 34 },
{ .x = 396, .y = 185, .size = 50 },
{ .x = 506, .y = 83, .size = 65 },
{ .x = 587, .y = 230, .size = 53 },
{ .x = 606, .y = 38, .size = 27 },
};
//---
// Internal functions
//---
/* menu_background() : update and draw circle */
static void menu_background(void)
{
for (int i = 0; i < NB_CIRCLE; ++i) {
circle[i].x += 1;
if ((circle[i].x - circle[i].size) >= (int)dwidth())
circle[i].x -= (dwidth() + (circle[i].size << 1));
dcircle_filled(
circle[i].x,
circle[i].y,
circle[i].size,
DCIRCLE_CENTER | DCIRCLE_MIDDLE,
CIRCLE_COLOR
);
}
}
/* title menu */
/* menu_title_background() : display circle */
static void menu_title_background(void)
{
menu_background();
}
/* menu_icon() : display the game icon */
static void menu_title_icon(void)
{
extern const image_t gduck_menu_title;
did_t did;
did = dimage(
&gduck_menu_title,
dwidth() / 2,
(dheight() / 2) - (dheight() / 8),
DIMAGE_CENTER | DIMAGE_MIDDLE
);
dimage_shader_shadow(did, -4, 4);
}
/* menu_hub() : display HUD information */
static void menu_title_hud(fps_t *fps, int trigger)
{
dprint(0, 0, C_WHITE, "FPS: %d", fps->fps);
if (trigger != 0) {
dtext_opt(
dwidth() / 2,
(dheight() / 2) + (dheight() / 4),
C_WHITE,
C_NONE,
DTEXT_CENTER | DTEXT_MIDDLE,
"Press [SHIFT] to start !",
-1
);
}
}
/* menu_text_blink() : change trigger status each 500ms */
static int menu_title_text_blink(volatile int *trigger)
{
*trigger ^= 1;
return TIMER_CONTINUE;
}
/* selection menu */
/* menu_select_background() : display circle */
static void menu_select_background(void)
{
menu_background();
}
/* menu_select_ui() : display button selection */
static void menu_select_ui(int max_level, int cursor)
{
extern const image_t gduck_menu_select_title;
extern const image_t gduck_menu_select_button_bg;
extern const image_t gduck_menu_select_button_0;
extern const image_t gduck_menu_select_button_1;
extern const image_t gduck_menu_select_button_2;
const image_t *image;
int counter;
int imgx;
int imgy;
int imgs;
dimage(
&gduck_menu_select_title,
dwidth() / 2,
dheight() / 6,
DIMAGE_CENTER | DIMAGE_MIDDLE
);
dimage(
&gduck_menu_select_button_bg,
dwidth() / 2,
(dheight() / 2) + (dheight() / 8),
DIMAGE_CENTER | DIMAGE_MIDDLE
);
imgx = (NB_BUTTON_ROW * gduck_menu_select_button_0.width);
imgx += (NB_BUTTON_ROW - 1);
imgx = (dwidth() / 2) - (imgx / 2);
imgx += (gduck_menu_select_button_0.width / 2);
imgy = (NB_BUTTON_COL * gduck_menu_select_button_0.height);
imgy += (NB_BUTTON_COL - 1);
imgy = ((dheight() / 2) + (dheight() / 8)) - (imgy / 2);
imgy += (gduck_menu_select_button_0.height / 2);
imgs = imgx;
counter = 0;
for (int y = 0; y < NB_BUTTON_COL; ++y)
{
imgx = imgs;
for (int x = 0; x < NB_BUTTON_ROW; ++x)
{
image = &gduck_menu_select_button_0;
if (counter == cursor)
image = &gduck_menu_select_button_1;
if (counter >= max_level)
image = &gduck_menu_select_button_2;
dimage(
image,
imgx,
imgy,
DIMAGE_CENTER | DIMAGE_MIDDLE
);
if (image != &gduck_menu_select_button_2) {
dprint_opt(
imgx - 1,
imgy + 1,
C_WHITE,
C_NONE,
DTEXT_CENTER | DTEXT_MIDDLE,
"%d",
counter + 1
);
}
imgx += image->width + 1;
counter += 1;
}
imgy += image->height + 1;
}
}
/* menu_select_hud() : display HUB information */
static void menu_select_hud(fps_t *fps)
{
dprint(0, 0, C_WHITE, "FPS: %d (%d us)", fps->fps, fps->render);
}
//---
// Public function
//----
/* menu_title() : display logo/animation and wait user interaction */
void menu_title(void)
{
volatile int trigger;
key_event_t e;
fps_t fps;
int exit;
int timer;
trigger = 1;
timer = timer_configure(
TIMER_DELAY_MS(500),
VHEX_CALL(&menu_title_text_blink, &trigger)
);
timer_start(timer);
uint32_t cache_us = 0;
uint32_t render_us = 0;
uint32_t key_us = 0;
exit = 1;
timer_fps_init(&fps);
while (exit)
{
cache_us = timer_prof_exec({
dclear(BG_COLOR);
menu_title_background();
menu_title_icon();
menu_title_hud(&fps, trigger);
dprint(0, 20, C_WHITE,
"cache = %d us\nrender = %d us\nkey = %d us",
cache_us, render_us, key_us
);
});
render_us = timer_prof_exec({ dupdate(); });
//timer_fps_sync(&fps, 30);
key_us = timer_prof_exec({
while (1) {
e = keyvent_poll();
if (e.type == KEYEV_NONE)
break;
if (e.type != KEYEV_UP)
continue;
if (e.key == KEY_SHIFT)
exit = 0;
}
});
}
timer_fps_quit(&fps);
timer_stop(timer);
}
/* menu_select() : level selection */
int menu_select(int max_level)
{
key_event_t e;
fps_t fps;
int cursor;
int exit;
exit = -1;
cursor = 0;
timer_fps_init(&fps);
while (exit < 0)
{
dclear(BG_COLOR);
menu_select_background();
menu_select_ui(max_level, cursor);
menu_select_hud(&fps);
dupdate();
timer_fps_sync(&fps, 3);
while (1) {
e = keyvent_poll();
if (e.type == KEYEV_NONE)
break;
if (e.type != KEYEV_UP)
continue;
if (e.key == KEY_LEFT) cursor -= 1;
if (e.key == KEY_RIGHT) cursor += 1;
if (e.key == KEY_DOWN) cursor += NB_BUTTON_ROW;
if (e.key == KEY_UP) cursor -= NB_BUTTON_ROW;
if (cursor < 0) cursor = 0;
if (cursor >= max_level) cursor = max_level - 1;
if (e.key == KEY_SHIFT) exit = cursor;
}
}
timer_fps_quit(&fps);
return (cursor);
}

11
vxsdk.toml Normal file
View File

@ -0,0 +1,11 @@
[project]
name = 'GravityDuck'
[dependencies]
vxKernel = 'dev'
[build]
build = 'make'
[extra.vxKernel]
configure = '--static --verbose'