132 lines
3.5 KiB
C
132 lines
3.5 KiB
C
#include "map.h"
|
|
#include "level.h"
|
|
#include "render.h"
|
|
#include <gint/timer.h>
|
|
#include <gint/cpu.h>
|
|
#include <gint/keyboard.h>
|
|
#include <gint/defs/util.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef struct {
|
|
/* Same mechanism as in game_t */
|
|
map_t const *map;
|
|
uint16_t *map_anim;
|
|
camera_t camera;
|
|
|
|
} menu_game_t;
|
|
|
|
static menu_game_t *menu_load_game(level_t const *level)
|
|
{
|
|
menu_game_t *mg = malloc(sizeof *mg);
|
|
mg->map = level->map;
|
|
mg->map_anim = malloc(mg->map->width * mg->map->height *
|
|
sizeof *mg->map_anim);
|
|
|
|
for(int i = 0; i < mg->map->width * mg->map->height; i++)
|
|
mg->map_anim[i] = rand() & 4095;
|
|
|
|
camera_init(&mg->camera, mg->map);
|
|
|
|
return mg;
|
|
}
|
|
|
|
static void menu_destroy_game(menu_game_t *mg)
|
|
{
|
|
free(mg->map_anim);
|
|
free(mg);
|
|
}
|
|
|
|
static void menu_render_game(menu_game_t *mg)
|
|
{
|
|
render_map_layer(mg->map, &mg->camera, 0, 0, HORIZONTAL, mg->map_anim,
|
|
DIMAGE_NONE);
|
|
render_map_layer(mg->map, &mg->camera, 0, 0, VERTICAL, mg->map_anim,
|
|
DIMAGE_NONE);
|
|
render_map_layer(mg->map, &mg->camera, 0, 0, CEILING, mg->map_anim,
|
|
DIMAGE_NONE);
|
|
}
|
|
|
|
static void menu_update_animations(menu_game_t *mg, fixed_t dt)
|
|
{
|
|
for(int i = 0; i < mg->map->width * mg->map->height; i++)
|
|
mg->map_anim[i] += fround(dt * 1000);
|
|
}
|
|
|
|
int menu_level_select(int start)
|
|
{
|
|
extern bopti_image_t img_menu_title, img_menu_arrows;
|
|
|
|
menu_game_t *options[2];
|
|
#define OPTION_COUNT ((int)(sizeof options / sizeof options[0]))
|
|
|
|
options[0] = menu_load_game(&level_lv1);
|
|
options[1] = menu_load_game(&level_lv2);
|
|
|
|
int selection = (start >= 0 && start < OPTION_COUNT) ? start : 0;
|
|
int target_x=0, x=0;
|
|
|
|
int volatile frame_tick = 1;
|
|
int t = timer_configure(TIMER_ANY, 1000000 / FRAME_RATE,
|
|
GINT_CALL_SET(&frame_tick));
|
|
timer_start(t);
|
|
|
|
while(1) {
|
|
while(!frame_tick)
|
|
sleep();
|
|
fixed_t dt = fix(1) / FRAME_RATE;
|
|
|
|
if(x != target_x) {
|
|
int dx = (target_x - x) / 6;
|
|
if(x < target_x && dx < 6)
|
|
dx = min(target_x-x, 6);
|
|
if(x > target_x && dx > -6)
|
|
dx = max(target_x-x, -6);
|
|
x += dx;
|
|
}
|
|
|
|
dclear(C_BLACK);
|
|
|
|
for(int i = 0; i < OPTION_COUNT; i++) {
|
|
if(-x <= (i-1)*DWIDTH)
|
|
continue;
|
|
if(-x >= (i+1)*DWIDTH)
|
|
continue;
|
|
|
|
int local_offset = x + i*DWIDTH;
|
|
fixed_t map_center = fix(options[i]->map->width) / 2;
|
|
options[i]->camera.x = map_center - fix(local_offset) / TILE_WIDTH;
|
|
menu_render_game(options[i]);
|
|
}
|
|
|
|
dimage(148, 9, &img_menu_title);
|
|
if(selection > 0)
|
|
dsubimage(16, 93, &img_menu_arrows, 0, 0, 35, 42, DIMAGE_NOCLIP);
|
|
if(selection < OPTION_COUNT - 1)
|
|
dsubimage(345, 93, &img_menu_arrows, 35, 0, 35, 42, DIMAGE_NOCLIP);
|
|
|
|
dupdate();
|
|
|
|
for(int i = 0; i < OPTION_COUNT; i++)
|
|
menu_update_animations(options[i], dt);
|
|
|
|
int key = getkey_opt(GETKEY_MENU, &frame_tick).key;
|
|
if(key == KEY_LEFT && selection > 0) {
|
|
selection--;
|
|
target_x += DWIDTH;
|
|
}
|
|
if(key == KEY_RIGHT && selection < OPTION_COUNT - 1) {
|
|
selection++;
|
|
target_x -= DWIDTH;
|
|
}
|
|
if(key == KEY_EXE || key == KEY_SHIFT)
|
|
return selection;
|
|
}
|
|
|
|
timer_stop(t);
|
|
|
|
for(size_t i = 0; i < OPTION_COUNT; i++)
|
|
menu_destroy_game(options[i]);
|
|
|
|
return 0;
|
|
}
|