Mercurial > molko
diff src/adventure/mainmenu_state.c @ 80:05ffbcdee585
adventure: create main menu, closes #2482 @4h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 15 Feb 2020 12:38:25 +0100 |
parents | |
children | ed72843a7194 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/adventure/mainmenu_state.c Sat Feb 15 12:38:25 2020 +0100 @@ -0,0 +1,210 @@ +/* + * mainmenu_state.c -- game main menu + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include <error.h> +#include <event.h> +#include <font.h> +#include <game.h> +#include <image.h> +#include <map_state.h> +#include <painter.h> +#include <state.h> +#include <sys.h> +#include <texture.h> +#include <window.h> + +#include "mainmenu_state.h" +#include "splashscreen_state.h" + +#define SPEED 120 +#define SEC 1000 + +enum substate { + SUBSTATE_MOVING, + SUBSTATE_WAITING +}; + +static int x; +static int y; +static unsigned int selection; +static int destination; +static enum substate substate; + +/* Menu items. */ +static struct { + struct texture *texture; + int x; + int y; +} items[3]; + +static void +enter(void) +{ + struct font *font = font_openf(sys_datapath("fonts/pirata-one.ttf"), 30); + + if (!font) + error_fatal(); + + substate = SUBSTATE_MOVING; + x = splashscreen_state_data.x; + y = splashscreen_state_data.y; + destination = window_height() / 4; + + /* TODO: change continue color if no game exists. */ + items[0].texture = font_render(font, "New game", 0x000000ff); + items[0].x = (window_width() / 2) - (texture_width(items[0].texture) / 2); + items[0].y = window_height() * 0.75; + + items[1].texture = font_render(font, "Continue", 0x000000ff); + items[1].x = items[0].x; + items[1].y = items[0].y + texture_height(items[0].texture); + + items[2].texture = font_render(font, "Quit", 0x000000ff); + items[2].x = items[0].x; + items[2].y = items[1].y + texture_height(items[1].texture); +} + +static void +new(void) +{ + struct map map; + struct texture *image; + + /* Prepare map. */ + if (!map_open(&map, sys_datapath("maps/test.map"))) + error_fatal(); + + memcpy(&map_state_data.map.map, &map, sizeof (map)); + + /* Prepare image and sprite. */ + if (!(image = image_openf(sys_datapath("sprites/test-walk.png")))) + error_fatal(); + + sprite_init(&map_state_data.player.sprite, image, 48, 48); + game_switch(&map_state, false); +} + +static void +resume(void) +{ +} + +static void +quit(void) +{ + game_quit(); +} + +static void +perform(void) +{ + assert(selection < 3); + + static void (*handlers[])(void) = { + [0] = new, + [1] = resume, + [2] = quit + }; + + handlers[selection](); +} + +static void +handle(const union event *event) +{ + if (substate != SUBSTATE_WAITING) + return; + + switch (event->type) { + case EVENT_KEYDOWN: + switch (event->key.key) { + case KEY_UP: + selection = selection == 0 ? 2 : selection - 1; + break; + case KEY_DOWN: + selection = (selection + 1) % 3; + break; + case KEY_ENTER: + perform(); + default: + break; + } + break; + default: + break; + } +} + +static void +update(unsigned int ticks) +{ + switch (substate) { + case SUBSTATE_MOVING: + y -= SPEED * ticks / SEC; + + if (y <= destination) { + y = destination; + substate = SUBSTATE_WAITING; + } + + break; + default: + break; + } +} + +static void +draw(void) +{ + painter_set_color(0xffffffff); + painter_clear(); + texture_draw(splashscreen_state_data.text, x, y); + + if (substate == SUBSTATE_WAITING) { + texture_draw(items[0].texture, items[0].x, items[0].y); + texture_draw(items[1].texture, items[1].x, items[1].y); + texture_draw(items[2].texture, items[2].x, items[2].y); + + /* Selection cursor. */ + + /* TODO: a sword here. */ + painter_set_color(0x000000ff); + painter_draw_rectangle(true, items[selection].x - 30, + items[selection].y + 11, 15, 15); + } +} + +static void +leave(void) +{ + texture_close(items[0].texture); + texture_close(items[1].texture); + memset(items, 0, sizeof (items)); +} + +struct state mainmenu_state = { + .enter = enter, + .handle = handle, + .update = update, + .draw = draw, + .leave = leave +};