# HG changeset patch # User David Demelier # Date 1579120277 -3600 # Node ID c97fe725fdeb6a1507b127fdf24795f6d7fee714 # Parent 291be94202c73b3aa34076ee5d27d709c8851c79 core: implement basic states, closes #2457 @1h diff -r 291be94202c7 -r c97fe725fdeb Makefile --- a/Makefile Wed Jan 15 20:54:53 2020 +0100 +++ b/Makefile Wed Jan 15 21:31:17 2020 +0100 @@ -27,6 +27,7 @@ src/error.c \ src/event.c \ src/font.c \ + src/game.c \ src/image.c \ src/map.c \ src/message.c \ diff -r 291be94202c7 -r c97fe725fdeb src/game.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/game.c Wed Jan 15 21:31:17 2020 +0100 @@ -0,0 +1,58 @@ +/* + * game.c -- main game object + * + * Copyright (c) 2020 David Demelier + * + * 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 + +#include "game.h" +#include "state.h" + +struct game game = { + .state = NULL, + .state_next = NULL +}; + +void +game_handle(const union event *event) +{ + if (game.state) + game.state->handle(event); +} + +void +game_update(unsigned int ticks) +{ + /* Change state if any. */ + if (game.state_next) { + /* Inform the current state we're gonna leave it. */ + if (game.state) + game.state->leave(); + + game.state = game.state_next; + game.state->enter(); + } + + if (game.state) + game.state->update(ticks); +} + +void +game_draw(void) +{ + if (game.state) + game.state->draw(); +} diff -r 291be94202c7 -r c97fe725fdeb src/game.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/game.h Wed Jan 15 21:31:17 2020 +0100 @@ -0,0 +1,67 @@ +/* + * game.h -- main game object + * + * Copyright (c) 2020 David Demelier + * + * 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_GAME_H +#define MOLKO_GAME_H + +/** + * \file game.h + * \brief Main game object. + */ + +struct state; + +union event; + +/** + * \brief Main game object. + */ +struct game { + /* Game states */ + struct state *state; /*!< (RO) Current state */ + struct state *state_next; /*!< (RO) Next state */ +}; + +/** + * Global game object. + */ +extern struct game game; + +/** + * Handle input event. + * + * \param event the event + */ +void +game_handle(const union event *event); + +/** + * Update the game state. + * + * \param ticks the number of milliseconds between last frame + */ +void +game_update(unsigned int ticks); + +/** + * Draw the game using the current state. + */ +void +game_draw(void); + +#endif /* !MOLKO_GAME_H */ diff -r 291be94202c7 -r c97fe725fdeb src/main.c --- a/src/main.c Wed Jan 15 20:54:53 2020 +0100 +++ b/src/main.c Wed Jan 15 21:31:17 2020 +0100 @@ -16,20 +16,57 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include - #include "clock.h" +#include "game.h" #include "error.h" #include "event.h" -#include "painter.h" -#include "image.h" -#include "map.h" #include "sys.h" -#include "walksprite.h" #include "window.h" -#include "util.h" -#include "texture.h" + +#define WINDOW_WIDTH 1280 +#define WINDOW_HEIGHT 720 + +static void +init(void) +{ + if (!sys_init()) + error_fatal(); + if (!window_init("Molko's Adventure", WINDOW_WIDTH, WINDOW_HEIGHT)) + error_fatal(); +} + +static void +run(void) +{ + union event ev; + struct clock clock; + + clock_start(&clock); + + for (;;) { + uint64_t elapsed = clock_elapsed(&clock); + + clock_start(&clock); + + while (event_poll(&ev)) { + /* TODO: this must be handled by states. */ + if (ev.type == EVENT_QUIT) + return; + + game_handle(&ev); + } + + game_update(elapsed); + game_draw(); + } +} + +static void +close(void) +{ + window_close(); + sys_close(); +} int main(int argc, char **argv) @@ -37,121 +74,9 @@ (void)argc; (void)argv; - struct texture *tex; - - if (!sys_init()) - error_fatal(); - if (!window_init("Molko's Adventure", 1024, 576)) - error_fatal(); - if (!(tex = texture_new(100, 100))) - error_fatal(); - - painter_set_color(0xffffffff); - painter_clear(); - - PAINTER_BEGIN(tex); - painter_set_color(0xff0000ff); - painter_clear(); - PAINTER_END(); - - texture_draw(tex, 10, 10); - painter_present(); - delay(5000); - -#if 0 - - struct clock clock; - struct map map; - struct texture *guy; - struct sprite sprite; - struct walksprite ws; - - if (!sys_init()) - error_fatal(); - if (!window_init("Molko's Adventure", 1024, 576)) - error_fatal(); - if (!map_open(&map, "world.json")) - error_fatal(); - if (!(guy = image_openf(sys_datapath("sprites/test-walk.png")))) - error_fatal(); - - sprite_init(&sprite, guy, 48, 48); - walksprite_init(&ws, &sprite, 200); - clock_start(&clock); - map_repaint(&map); - - int guy_x = 10; - int guy_y = 10; - int guy_dx = 0; - int guy_dy = 0; - - int dx = 0; - int dy = 0; - int orientation = 0; - - for (;;) { - uint64_t elapsed = clock_elapsed(&clock); - union event ev; - - clock_start(&clock); - - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_QUIT: - return 0; - case EVENT_KEYDOWN: - switch (ev.key.key) { - case KEY_UP: - orientation = 0; - dy = -5; - break; - case KEY_RIGHT: - orientation = 2; - dx = 5; - break; - case KEY_DOWN: - orientation = 4; - dy = 5; - break; - case KEY_LEFT: - orientation = 6; - dx = -5; - break; - default: - break; - } - break; - case EVENT_KEYUP: - switch (ev.key.key) { - case KEY_DOWN: - dy = 0; - break; - case KEY_UP: - dy = 0; - break; - case KEY_LEFT: - dx = 0; - break; - case KEY_RIGHT: - dx = 0; - break; - default: - break; - } - break; - default: - break; - } - } - - walksprite_update(&ws, elapsed); - painter_clear(); - map_draw(&map); - walksprite_draw(&ws, orientation, 100, 100); - painter_present(); - delay(50); - } -#endif + init(); + run(); + close(); return 0; } diff -r 291be94202c7 -r c97fe725fdeb src/state.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/state.h Wed Jan 15 21:31:17 2020 +0100 @@ -0,0 +1,60 @@ +/* + * state.h -- abstract state + * + * Copyright (c) 2020 David Demelier + * + * 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_STATE_H +#define MOLKO_STATE_H + +/** + * \file state.h + * \brief Abstract state. + */ + +union event; + +/** + * \brief Abstract state. + */ +struct state { + /** + * This function is called when the state is entered. + */ + void (*enter)(void); + + /** + * This function is called when the state is about to be left. + */ + void (*leave)(void); + + /** + * This function is called for each event that happened. + */ + void (*handle)(const union event *); + + /** + * This function is called to update the game, with the number of + * milliseconds since the last frame. + */ + void (*update)(unsigned int ticks); + + /** + * This function is supposed to draw the game. + */ + void (*draw)(void); +}; + +#endif /* !MOLKO_STATE_H */