Mercurial > molko
changeset 57:9f6267843815
core: implement basic actions, closes #2463 @1h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 21 Jan 2020 12:28:26 +0100 |
parents | 43d1102a367e |
children | d7d88ac30611 |
files | src/action.h src/game.c src/game.h src/main.c src/splashscreen.c |
diffstat | 5 files changed, 210 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/action.h Tue Jan 21 12:28:26 2020 +0100 @@ -0,0 +1,88 @@ +/* + * action.h -- action states + * + * 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 ACTION_H +#define ACTION_H + +/** + * \file action.h + * \brief Action states. + */ + +#include <stdbool.h> + +union event; + +/** + * \brief Action flags. + */ +enum action_flags { + ACTION_NONE, /*!< No flags */ + ACTION_AUTO_LEAVE = (1 << 0) /*!< Action is removed on state change */ +}; + +/** + * \brief Action structure. + */ +struct action { + /** + * (RW) + * + * Optional flags. + */ + enum action_flags flags; + + /** + * (RW) + * + * Arbitrary user data. + */ + void *data; + + /** + * (RW) + * + * Handle event. + */ + void (*handle)(struct action *, const union event *event); + + /** + * (RW) + * + * Update the action. + * + * If returns true, the action is removed. + */ + bool (*update)(struct action *, unsigned int); + + /** + * (RW) + * + * Draw the aciton. + */ + void (*draw)(struct action *); + + /** + * (RW) + * + * Close the action before removal. + */ + void (*finish)(struct action *); +}; + +#endif /* !ACTION_H*/
--- a/src/game.c Tue Jan 21 12:26:49 2020 +0100 +++ b/src/game.c Tue Jan 21 12:28:26 2020 +0100 @@ -18,6 +18,7 @@ #include <assert.h> #include <stddef.h> +#include <string.h> #include "game.h" #include "state.h" @@ -27,19 +28,81 @@ .state_next = NULL }; +static struct action * +find_empty_action(void) +{ + static struct action null; + + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) + if (memcmp(&game.actions[i], &null, sizeof (struct action)) == 0) + return &game.actions[i]; + + return NULL; +} + +static void +clear_actions(void) +{ + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) { + struct action *a = &game.actions[i]; + + /* These actions are removed on state change. */ + if (a->flags & ACTION_AUTO_LEAVE) { + if (a->finish) + a->finish(a); + + memset(a, 0, sizeof (struct action)); + } + } +} + +static void +handle_actions(const union event *event) +{ + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) + if (game.actions[i].handle) + game.actions[i].handle(&game.actions[i], event); +} + +static void +update_actions(unsigned int ticks) +{ + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) { + struct action *a = &game.actions[i]; + + if (!a->update) + continue; + + if (a->update(a, ticks)) { + if (a->finish) + a->finish(a); + + memset(&game.actions[i], 0, sizeof (struct action)); + } + } +} + void -game_switch(struct state *state) +game_switch(struct state *state, bool quick) { assert(state); - game.state_next = state; + if (quick) { + game.state = state; + game.state->enter(); + } else + game.state_next = state; } void game_handle(const union event *event) { + assert(event); + if (game.state) game.state->handle(event); + + handle_actions(event); } void @@ -54,10 +117,15 @@ game.state = game.state_next; game.state->enter(); game.state_next = NULL; + + /* Remove any actions that must be deleted. */ + clear_actions(); } if (game.state) game.state->update(ticks); + + update_actions(ticks); } void @@ -66,3 +134,14 @@ if (game.state) game.state->draw(); } + +void +game_add_action(const struct action *action) +{ + assert(action); + + struct action *pos; + + if ((pos = find_empty_action())) + memcpy(pos, action, sizeof (struct action)); +}
--- a/src/game.h Tue Jan 21 12:26:49 2020 +0100 +++ b/src/game.h Tue Jan 21 12:28:26 2020 +0100 @@ -24,6 +24,15 @@ * \brief Main game object. */ +#include <stdbool.h> + +#include "action.h" + +/** + * \brief Max number of actions allowed at the same time. + */ +#define GAME_ACTIONS_MAX 32 + struct state; union event; @@ -32,9 +41,12 @@ * \brief Main game object. */ struct game { - /* Game states */ + /* Game states. */ struct state *state; /*!< (RO) Current state */ struct state *state_next; /*!< (RO) Next state */ + + /** Array of actions. */ + struct action actions[GAME_ACTIONS_MAX]; }; /** @@ -47,11 +59,14 @@ * * This function will only update state after the next \a game_update call. * + * If quick is true, change state immediately. + * * \pre state != NULL * \param state the new state + * \param quick quickly change the state */ void -game_switch(struct state *state); +game_switch(struct state *state, bool quick); /** * Handle input event. @@ -75,4 +90,16 @@ void game_draw(void); +/** + * Add an action to the game. + * + * If there are no room for the action, action is discarded. Make sure to not + * exceed the limit GAME_ACTIONS_MAX. + * + * \pre action != NULL + * \param action the action to copy + */ +void +game_add_action(const struct action *action); + #endif /* !MOLKO_GAME_H */
--- a/src/main.c Tue Jan 21 12:26:49 2020 +0100 +++ b/src/main.c Tue Jan 21 12:28:26 2020 +0100 @@ -16,6 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <stdio.h> + #include "clock.h" #include "error.h" #include "event.h" @@ -35,25 +37,13 @@ static void init(void) { - struct texture *image; - if (!sys_init()) error_fatal(); if (!window_init("Molko's Adventure", WINDOW_WIDTH, WINDOW_HEIGHT)) error_fatal(); - image = image_openf(sys_datapath("sprites/test-walk.png")); - - if (!image) - error_fatal(); - if (!map_open(&map_state_data.map.map, sys_datapath("maps/test.map"))) - error_fatal(); - - sprite_init(&map_state_data.player.sprite, image, 48, 48); - game_switch(&map_state); - /* Default state is splash screen */ - //game_switch(&splashscreen_state); + game_switch(&splashscreen_state, true); } static void
--- a/src/splashscreen.c Tue Jan 21 12:26:49 2020 +0100 +++ b/src/splashscreen.c Tue Jan 21 12:28:26 2020 +0100 @@ -18,15 +18,16 @@ #include "error.h" #include "font.h" +#include "game.h" +#include "image.h" +#include "map.h" +#include "map_state.h" #include "painter.h" #include "splashscreen.h" -#include "map_state.h" -#include "image.h" #include "state.h" #include "sys.h" #include "texture.h" #include "window.h" -#include "map.h" #define DELAY 3000 @@ -72,17 +73,15 @@ /* TODO: change this once map is done. */ if (elapsed >= DELAY) { /* TODO: this will be removed too. */ - static struct map map; - static struct texture *player_texture; - static struct sprite player_sprite; + static struct texture *image; - if (!map_open(&map, sys_datapath("maps/test.map"))) + if (!map_open(&map_state_data.map.map, sys_datapath("maps/test.map"))) error_fatal(); - if (!(player_texture = image_openf(sys_datapath("sprites/test-walk.png")))) + if (!(image = image_openf(sys_datapath("sprites/test-walk.png")))) error_fatal(); - sprite_init(&player_sprite, player_texture, 48, 48); - //map_state_start(&map, &player_sprite); + sprite_init(&map_state_data.player.sprite, image, 48, 48); + game_switch(&map_state, false); } }