Mercurial > molko
changeset 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 | 8f95462ac5f8 |
children | e8fcc2a1d250 |
files | Makefile assets/fonts/pirata-one.ttf assets/fonts/teutonic1.ttf src/adventure/main.c src/adventure/mainmenu_state.c src/adventure/mainmenu_state.h src/adventure/splashscreen_state.c src/adventure/splashscreen_state.h src/core/game.c src/core/game.h src/core/map_state.h |
diffstat | 11 files changed, 298 insertions(+), 81 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Sun Feb 02 15:48:36 2020 +0100 +++ b/Makefile Sat Feb 15 12:38:25 2020 +0100 @@ -50,7 +50,8 @@ CORE_DEPS= ${CORE_SRCS:.c=.d} ADV_SRCS= src/adventure/main.c \ - src/adventure/splashscreen_state.c + src/adventure/splashscreen_state.c \ + src/adventure/mainmenu_state.c ADV_OBJS= ${ADV_SRCS:.c=.o} ADV_DEPS= ${ADV_SRCS:.c=.d}
--- a/src/adventure/main.c Sun Feb 02 15:48:36 2020 +0100 +++ b/src/adventure/main.c Sat Feb 15 12:38:25 2020 +0100 @@ -56,22 +56,12 @@ } static void -myresult(struct action *a) -{ - struct message *msg = a->data; - - printf("selected: %d\n", msg->index); -} - -static void run(void) { union event ev; struct clock clock; struct font *font; struct texture *frame; - struct script sc; - struct action ac; if (!(font = font_openf(sys_datapath("fonts/DejaVuSans.ttf"), 15))) error_fatal(); @@ -80,50 +70,11 @@ if (!(frame = image_openf(sys_datapath("images/message.png")))) error_fatal(); - struct message msg = { - .text = { - "Flip a coin.", - "Try your best my friend." - }, - .colors = { - 0xd9caddff, - 0x94d5ffff - }, - .font = font, - .frame = frame, - .flags = MESSAGE_QUESTION - }; - debug_options.enable = true; clock_start(&clock); - script_init(&sc); - /* Wait first. */ - struct wait w = { .delay = 5000 }; - - wait_action(&w, &ac); - script_append(&sc, &ac); - - /* Inhibit input. */ - inhibit_action(INHIBIT_STATE_INPUT, &ac); - script_append(&sc, &ac); - - message_start(&msg); - message_action(&msg, &ac); - ac.end = myresult; - script_append(&sc, &ac); - - /* Put it back. */ - inhibit_action(INHIBIT_NONE, &ac); - script_append(&sc, &ac); - - script_start(&sc); - script_action(&sc, &ac); - - game_add_action(&ac); - - for (;;) { + while (game.state) { unsigned int elapsed = clock_elapsed(&clock); clock_start(&clock);
--- /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 +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/adventure/mainmenu_state.h Sat Feb 15 12:38:25 2020 +0100 @@ -0,0 +1,32 @@ +/* + * mainmenu_state.h -- 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. + */ + +#ifndef MOLKO_MAINMENU_STATE_H +#define MOLKO_MAINMENU_STATE_H + +/** + * \file mainmenu_state.h + * \brief Game main menu. + */ + +/** + * \brief Main menu state. + */ +extern struct state mainmenu_state; + +#endif /* !MOLKO_MAINMENU_STATE_H */
--- a/src/adventure/splashscreen_state.c Sun Feb 02 15:48:36 2020 +0100 +++ b/src/adventure/splashscreen_state.c Sat Feb 15 12:38:25 2020 +0100 @@ -23,40 +23,42 @@ #include "map.h" #include "map_state.h" #include "painter.h" -#include "splashscreen_state.h" #include "state.h" #include "sys.h" #include "texture.h" #include "window.h" -#define DELAY 3000 +#include "splashscreen_state.h" +#include "mainmenu_state.h" -static unsigned int elapsed; -static struct font *font; -static struct texture *text; -static int x; -static int y; +#define DELAY 2000 + +struct splashscreen_state_data splashscreen_state_data; static void enter(void) { - if (!(font = font_openf(sys_datapath("fonts/knights-quest.ttf"), 160))) + struct font *font; + + if (!(font = font_openf(sys_datapath("fonts/teutonic1.ttf"), 130))) error_fatal(); - if (!(text = font_render(font, "Molko's Adventure", 0x000000ff))) + if (!(splashscreen_state_data.text = font_render(font, "Molko's Adventure", 0x000000ff))) error_fatal(); /* Compute position. */ - const unsigned int w = texture_width(text); - const unsigned int h = texture_height(text); + const unsigned int w = texture_width(splashscreen_state_data.text); + const unsigned int h = texture_height(splashscreen_state_data.text); - x = (window_width() / 2) - (w / 2); - y = (window_height() / 2) - (h / 2) - 100; + splashscreen_state_data.x = (window_width() / 2) - (w / 2); + splashscreen_state_data.y = (window_height() / 2) - (h / 2); + + font_close(font); } static void leave(void) { - font_close(font); + /* We don't delete the texture because it is used by mainmenu_state. */ } static void @@ -68,21 +70,10 @@ static void update(unsigned int ticks) { - elapsed += ticks; - - /* TODO: change this once map is done. */ - if (elapsed >= DELAY) { - /* TODO: this will be removed too. */ - static struct texture *image; + splashscreen_state_data.elapsed += ticks; - if (!map_open(&map_state_data.map.map, sys_datapath("maps/test.map"))) - error_fatal(); - 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); - } + if (splashscreen_state_data.elapsed >= DELAY) + game_switch(&mainmenu_state, false); } static void @@ -90,7 +81,9 @@ { painter_set_color(0xffffffff); painter_clear(); - texture_draw(text, x, y); + texture_draw(splashscreen_state_data.text, + splashscreen_state_data.x, + splashscreen_state_data.y); } struct state splashscreen_state = {
--- a/src/adventure/splashscreen_state.h Sun Feb 02 15:48:36 2020 +0100 +++ b/src/adventure/splashscreen_state.h Sat Feb 15 12:38:25 2020 +0100 @@ -24,6 +24,18 @@ * \brief Splash screen state. */ +struct texture; + +/** + * \brief Data for splashscreen. + */ +extern struct splashscreen_state_data { + struct texture *text; /*!< (RW) Texture for the text. */ + int x; /*!< (RW) Position in x. */ + int y; /*!< (RW) Position in y. */ + unsigned int elapsed; /*!< (RW) Time elapsed. */ +} splashscreen_state_data; /*!< (RW) Global state data. */ + /** * \brief Splash screen state. */
--- a/src/core/game.c Sun Feb 02 15:48:36 2020 +0100 +++ b/src/core/game.c Sat Feb 15 12:38:25 2020 +0100 @@ -157,3 +157,12 @@ if ((pos = find_empty_action())) memcpy(pos, action, sizeof (struct action)); } + +void +game_quit(void) +{ + if (game.state && game.state->leave) + game.state->leave(); + + game.state = NULL; +}
--- a/src/core/game.h Sun Feb 02 15:48:36 2020 +0100 +++ b/src/core/game.h Sat Feb 15 12:38:25 2020 +0100 @@ -106,4 +106,13 @@ void game_add_action(const struct action *action); +/** + * Stop the game. + * + * This will effectively stop the current state but the main loop may continue + * until it has completed. + */ +void +game_quit(void); + #endif /* !MOLKO_GAME_H */
--- a/src/core/map_state.h Sun Feb 02 15:48:36 2020 +0100 +++ b/src/core/map_state.h Sat Feb 15 12:38:25 2020 +0100 @@ -38,7 +38,7 @@ * Map properties. */ struct { - struct map map; /*!< (RO) The map definition */ + struct map map; /*!< (RW) The map definition */ unsigned int w; /*!< (RO) Map width */ unsigned int h; /*!< (RO) Map height */ } map;