Mercurial > molko
changeset 207:133926e08d6e
examples: use game_loop for all
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 11 Nov 2020 16:09:43 +0100 |
parents | 4e2bf083759b |
children | c0e0d4accae8 |
files | examples/example-action.c examples/example-animation.c examples/example-audio.c examples/example-battle.c examples/example-cursor.c examples/example-debug.c examples/example-drawable.c examples/example-font.c examples/example-gridmenu.c examples/example-label.c examples/example-message.c examples/example-sprite.c examples/example-trace.c examples/example-ui.c libcore/core/game.c libcore/core/game.h |
diffstat | 16 files changed, 846 insertions(+), 627 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/example-action.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-action.c Wed Nov 11 16:09:43 2020 +0100 @@ -19,15 +19,16 @@ #include <assert.h> #include <core/action.h> -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/image.h> #include <core/maths.h> #include <core/painter.h> #include <core/panic.h> #include <core/script.h> #include <core/sprite.h> +#include <core/state.h> #include <core/sys.h> #include <core/texture.h> #include <core/util.h> @@ -324,41 +325,56 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_QUIT: + game_quit(); + break; + default: + action_stack_handle(&events, ev); + action_stack_handle(&modal, ev); + break; + } +} + +static void +update(struct state *st, unsigned int ticks) +{ + (void)st; + + action_stack_update(&events, ticks); + action_stack_update(&modal, ticks); +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0xffffffff); + painter_clear(); + action_stack_draw(&events); + action_stack_draw(&modal); + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; + struct state state = { + .handle = handle, + .update = update, + .draw = draw + }; - clock_start(&clock); action_stack_add(&events, &chest.event); action_stack_add(&events, &guide.event); - for (;;) { - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - for (union event ev; event_poll(&ev); ) { - switch (ev.type) { - case EVENT_QUIT: - return; - default: - action_stack_handle(&events, &ev); - action_stack_handle(&modal, &ev); - break; - } - } - - painter_set_color(0xffffffff); - painter_clear(); - action_stack_update(&events, elapsed); - action_stack_update(&modal, elapsed); - action_stack_draw(&events); - action_stack_draw(&modal); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void
--- a/examples/example-animation.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-animation.c Wed Nov 11 16:09:43 2020 +0100 @@ -17,15 +17,16 @@ */ #include <core/animation.h> -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/image.h> #include <core/sys.h> #include <core/window.h> #include <core/painter.h> #include <core/panic.h> #include <core/sprite.h> +#include <core/state.h> #include <core/texture.h> #include <core/util.h> @@ -37,8 +38,6 @@ #define W 1280 #define H 720 -static struct texture numbers; - static struct label label = { .text = "Keys: <Space> start or reset the animation.", .x = 10, @@ -46,6 +45,11 @@ .flags = LABEL_FLAGS_SHADOW }; +static struct texture numbers; +static struct animation animation; +static struct sprite sprite; +static bool completed = true; + static void init(void) { @@ -58,57 +62,67 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_KEYDOWN: + switch (ev->key.key) { + case KEY_SPACE: + animation_start(&animation); + completed = animation_completed(&animation); + break; + default: + break; + } + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +update(struct state *st, unsigned int ticks) +{ + (void)st; + + if (!completed) + completed = animation_update(&animation, ticks); +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0x4f8fbaff); + painter_clear(); + label_draw(&label); + + if (!completed) + animation_draw(&animation, (window.w - sprite.cellw) / 2, (window.h - sprite.cellh) / 2); + + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; - struct animation animation; - struct sprite sprite; - bool completed = true; + struct state state = { + .handle = handle, + .update = update, + .draw = draw + }; - clock_start(&clock); sprite_init(&sprite, &numbers, 48, 48); animation_init(&animation, &sprite, 1000); - for (;;) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_KEYDOWN: - switch (ev.key.key) { - case KEY_SPACE: - animation_start(&animation); - completed = animation_completed(&animation); - break; - default: - break; - } - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - if (!completed) - completed = animation_update(&animation, elapsed); - - painter_set_color(0x4f8fbaff); - painter_clear(); - label_draw(&label); - - if (!completed) - animation_draw(&animation, (window.w - sprite.cellw) / 2, (window.h - sprite.cellh) / 2); - - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void
--- a/examples/example-audio.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-audio.c Wed Nov 11 16:09:43 2020 +0100 @@ -1,5 +1,5 @@ /* - * example-sound.c -- show how to use sounds + * example-audio.c -- show how to use sounds and music * * Copyright (c) 2020 David Demelier <markand@malikania.fr> * @@ -16,13 +16,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/music.h> #include <core/painter.h> #include <core/panic.h> #include <core/sound.h> +#include <core/state.h> #include <core/sys.h> #include <core/util.h> #include <core/window.h> @@ -62,9 +63,8 @@ panic(); if (!window_open("Example - Audio", W, H)) panic(); - if (!music_openmem(&music, musics_vabsounds_romance, sizeof (musics_vabsounds_romance))) - panic(); - if (!sound_openmem(&sound, sounds_fire, sizeof (sounds_fire))) + if (!music_openmem(&music, musics_vabsounds_romance, sizeof (musics_vabsounds_romance)) || + !sound_openmem(&sound, sounds_fire, sizeof (sounds_fire))) panic(); } @@ -77,67 +77,72 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_CLICKDOWN: + if (!sound_play(&sound, -1, 0)) + panic(); + break; + case EVENT_KEYDOWN: + switch (ev->key.key) { + case KEY_f: + music_play(&music, 0, 500); + break; + case KEY_s: + music_stop(500); + break; + case KEY_p: + music_pause(); + break; + case KEY_r: + music_resume(); + break; + case KEY_q: + music_stop(0); + break; + case KEY_l: + music_play(&music, MUSIC_LOOP, 0); + break; + case KEY_SPACE: + music_play(&music, 0, 0); + break; + default: + break; + } + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0x006554ff); + painter_clear(); + label_draw(&label_music); + label_draw(&label_sound); + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; - - clock_start(&clock); - - for (;;) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); + struct state state = { + .handle = handle, + .draw = draw + }; - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_CLICKDOWN: - if (!sound_play(&sound, -1, 0)) - panic(); - break; - case EVENT_KEYDOWN: - switch (ev.key.key) { - case KEY_f: - music_play(&music, 0, 500); - break; - case KEY_s: - music_stop(500); - break; - case KEY_p: - music_pause(); - break; - case KEY_r: - music_resume(); - break; - case KEY_q: - music_stop(0); - break; - case KEY_l: - music_play(&music, MUSIC_LOOP, 0); - break; - case KEY_SPACE: - music_play(&music, 0, 0); - break; - default: - break; - } - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - painter_set_color(0x006554ff); - painter_clear(); - label_draw(&label_music); - label_draw(&label_sound); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); music_finish(&music); sound_finish(&sound);
--- a/examples/example-battle.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-battle.c Wed Nov 11 16:09:43 2020 +0100 @@ -18,15 +18,18 @@ #include <assert.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <core/clock.h> +#include <core/alloc.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/image.h> #include <core/painter.h> #include <core/panic.h> #include <core/sprite.h> +#include <core/state.h> #include <core/sys.h> #include <core/texture.h> #include <core/util.h> @@ -148,29 +151,23 @@ static void init(void) { - struct clock clock = {0}; - if (!core_init() || !ui_init() || !rpg_init()) panic(); if (!window_open("Example - Battle", W, H)) panic(); - /* Wait 1 second to let all events processed. */ - while (clock_elapsed(&clock) < 1000) - for (union event ev; event_poll(&ev); ) - if (ev.type == EVENT_QUIT) - return; - registry_init(); /* Set cursor in default theme. */ theme_default()->sprites[THEME_SPRITE_CURSOR] = ®istry_sprites[REGISTRY_TEXTURE_CURSOR]; } +static struct state fight_state; + static void -prepare_to_fight(struct battle *bt) +prepare_to_fight(void) { - assert(bt); + struct battle *bt = alloc_zero(1, sizeof (*bt)); // bt->enemies[0].ch = &haunted_wood; bt->team[0].ch = &team[0]; @@ -187,60 +184,96 @@ bt->enemies[1].y = 100; battle_start(bt); + + fight_state.data = bt; + game_switch(&fight_state, false); +} + + +static void +empty_handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_QUIT: + game_quit(); + break; + case EVENT_KEYDOWN: + if (ev->key.key == KEY_SPACE) + prepare_to_fight(); + break; + default: + break; + } } static void -run(void) +empty_draw(struct state *st) { - struct clock clock; - struct battle battle = {0}; - struct label info = { + (void)st; + + static const struct label info = { .text = "Press <Space> to start a battle.", .x = 10, .y = 10, .flags = LABEL_FLAGS_SHADOW }; - clock_start(&clock); + painter_set_color(0x4f8fbaff); + painter_clear(); + label_draw(&info); + painter_present(); +} + +static struct state empty_state = { + .handle = empty_handle, + .draw = empty_draw +}; - for (;;) { - unsigned int elapsed = clock_elapsed(&clock); +static void +fight_handle(struct state *st, const union event *ev) +{ + battle_handle(st->data, ev); +} - clock_start(&clock); +static void +fight_update(struct state *st, unsigned int ticks) +{ + struct battle *bt = st->data; + + if (battle_update(bt, ticks)) + game_switch(&empty_state, false); +} - for (union event ev; event_poll(&ev); ) { - switch (ev.type) { - case EVENT_QUIT: - return; - case EVENT_KEYDOWN: - if (ev.key.key == KEY_SPACE && !battle.state) - prepare_to_fight(&battle); - else if (battle.state) - battle_handle(&battle, &ev); - break; - default: - if (battle.state) - battle_handle(&battle, &ev); - break; - } - } +static void +fight_draw(struct state *st) +{ + painter_set_color(0x000000ff); + painter_clear(); + battle_draw(st->data); + painter_present(); +} - if (battle.state) { - if (battle_update(&battle, elapsed)) - battle_finish(&battle); - else - battle_draw(&battle); - } else { - painter_set_color(0x4f8fbaff); - painter_clear(); - label_draw(&info); - } +static void +fight_finish(struct state *st) +{ + battle_finish(st->data); + free(st->data); +} - painter_present(); +static struct state fight_state = { + .handle = fight_handle, + .update = fight_update, + .draw = fight_draw, + .finish = fight_finish, +}; - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(1); - } +static void +run(void) +{ + game_switch(&empty_state, true); + game_loop(); } static void
--- a/examples/example-cursor.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-cursor.c Wed Nov 11 16:09:43 2020 +0100 @@ -18,12 +18,13 @@ #include <stdio.h> -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/key.h> #include <core/painter.h> #include <core/panic.h> +#include <core/state.h> #include <core/sys.h> #include <core/util.h> #include <core/window.h> @@ -35,6 +36,7 @@ #define H 720 static char help_text[128]; +static enum window_cursor cursor = WINDOW_CURSOR_ARROW; static struct label help = { .x = 10, @@ -70,53 +72,58 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_KEYDOWN: + switch (ev->key.key) { + case KEY_LEFT: + if (cursor > 0) + change(--cursor); + break; + case KEY_RIGHT: + if (cursor + 1 < WINDOW_CURSOR_LAST) + change(++cursor); + break; + default: + break; + } + + + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0xebede9ff); + painter_clear(); + label_draw(&help); + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; - enum window_cursor cursor = WINDOW_CURSOR_ARROW; + struct state state = { + .handle = handle, + .draw = draw + }; - clock_start(&clock); change(cursor); - for (;;) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_KEYDOWN: - switch (ev.key.key) { - case KEY_LEFT: - if (cursor > 0) - change(--cursor); - break; - case KEY_RIGHT: - if (cursor + 1 < WINDOW_CURSOR_LAST) - change(++cursor); - break; - default: - break; - } - - - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - painter_set_color(0xebede9ff); - painter_clear(); - label_draw(&help); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void @@ -137,4 +144,3 @@ run(); quit(); } -
--- a/examples/example-debug.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-debug.c Wed Nov 11 16:09:43 2020 +0100 @@ -16,14 +16,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <core/clock.h> #include <core/core.h> #include <core/event.h> -#include <core/sys.h> +#include <core/game.h> #include <core/window.h> #include <core/painter.h> #include <core/panic.h> -#include <core/trace.h> +#include <core/state.h> #include <core/util.h> #include <ui/debug.h> @@ -33,6 +32,9 @@ #define W 1280 #define H 720 +static int mouse_x; +static int mouse_y; + static void init(void) { @@ -45,42 +47,47 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_MOUSE: + mouse_x = ev->mouse.x; + mouse_y = ev->mouse.y; + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +draw(struct state *st) +{ + (void)st; + + struct debug_report report = {0}; + + painter_set_color(0x4f8fbaff); + painter_clear(); + debugf(&report, "Game running."); + debugf(&report, "mouse: %d, %d", mouse_x, mouse_y); + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; - int x = 0, y = 0; - - clock_start(&clock); - - for (;;) { - struct debug_report report = {0}; - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); + struct state state = { + .handle = handle, + .draw = draw + }; - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_MOUSE: - x = ev.mouse.x; - y = ev.mouse.y; - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - painter_set_color(0x4f8fbaff); - painter_clear(); - debugf(&report, "Game running."); - debugf(&report, "mouse: %d, %d", x, y); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void
--- a/examples/example-drawable.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-drawable.c Wed Nov 11 16:09:43 2020 +0100 @@ -16,13 +16,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <stdio.h> #include <stdlib.h> #include <core/alloc.h> #include <core/animation.h> -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/drawable.h> #include <core/key.h> #include <core/painter.h> @@ -30,6 +31,7 @@ #include <core/sys.h> #include <core/image.h> #include <core/sprite.h> +#include <core/state.h> #include <core/texture.h> #include <core/util.h> #include <core/window.h> @@ -81,6 +83,22 @@ sprite_init(&explosion_sprite, &explosion_tex, 256, 256); } +static bool +explosion_update(struct drawable *dw, unsigned int ticks) +{ + struct explosion *ex = dw->data; + + return animation_update(&ex->anim, ticks); +} + +static void +explosion_draw(struct drawable *dw) +{ + struct explosion *ex = dw->data; + + animation_draw(&ex->anim, ex->dw.x, ex->dw.y); +} + static void explosion_finish(struct drawable *dw) { @@ -90,67 +108,78 @@ static void spawn(int x, int y) { - struct explosion *expl = alloc(1, sizeof (struct explosion)); + struct explosion *ex = alloc_zero(1, sizeof (*ex)); + + animation_init(&ex->anim, &explosion_sprite, 15); - animation_init(&expl->anim, &explosion_sprite, 10); - animation_drawable(&expl->anim, &expl->dw, x, y); + ex->dw.data = ex; + ex->dw.x = x - (int)(explosion_sprite.cellw / 2); + ex->dw.y = y - (int)(explosion_sprite.cellh / 2); + ex->dw.update = explosion_update; + ex->dw.draw = explosion_draw; + ex->dw.finish = explosion_finish; + + drawable_stack_add(&stack, &ex->dw); +} + +static void +handle(struct state *st, const union event *ev) +{ + (void)st; - /* - * This work because the drawable->data field expects a struct animation - * pointer which is the first member of struct explosion. - * - * Thus this "poor man inheritance" trick works perfectly in our case - * and we simply need to free the whole explosion struct afterwards. - */ - expl->dw.finish = explosion_finish; + switch (ev->type) { + case EVENT_KEYDOWN: + switch (ev->key.key) { + case KEY_ESCAPE: + drawable_stack_finish(&stack); + break; + default: + break; + } + break; + case EVENT_CLICKDOWN: + spawn(ev->click.x, ev->click.y); + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} - drawable_stack_add(&stack, &expl->dw); +static void +update(struct state *st, unsigned int ticks) +{ + (void)st; + + drawable_stack_update(&stack, ticks); + +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0xebede9ff); + painter_clear(); + label_draw(&help); + drawable_stack_draw(&stack); + painter_present(); } static void run(void) { - struct clock clock = {0}; - - clock_start(&clock); - - for (;;) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); + struct state state = { + .handle = handle, + .update = update, + .draw = draw + }; - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_KEYDOWN: - switch (ev.key.key) { - case KEY_ESCAPE: - drawable_stack_finish(&stack); - break; - default: - break; - } - break; - case EVENT_CLICKDOWN: - spawn(ev.click.x, ev.click.y); - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - drawable_stack_update(&stack, elapsed); - painter_set_color(0xebede9ff); - painter_clear(); - label_draw(&help); - drawable_stack_draw(&stack); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void
--- a/examples/example-font.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-font.c Wed Nov 11 16:09:43 2020 +0100 @@ -16,12 +16,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <core/clock.h> #include <core/core.h> #include <core/event.h> #include <core/font.h> +#include <core/game.h> #include <core/painter.h> #include <core/panic.h> +#include <core/state.h> #include <core/sys.h> #include <core/texture.h> #include <core/util.h> @@ -45,6 +46,9 @@ 0xc7cfccff, /* Christian Grey. */ }; +static int ci = 0; +static enum font_style style = FONT_STYLE_ANTIALIASED; + static void init(void) { @@ -55,65 +59,69 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_KEYDOWN: + switch (ev->key.key) { + case KEY_LEFT: + if (ci > 0) + ci--; + break; + case KEY_RIGHT: + if ((size_t)ci < NELEM(colors)) + ci++; + break; + case KEY_SPACE: + if (style == FONT_STYLE_ANTIALIASED) + style = FONT_STYLE_NONE; + else + style = FONT_STYLE_ANTIALIASED; + + theme_default()->fonts[THEME_FONT_INTERFACE]->style = style; + default: + break; + } + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +draw(struct state *st) +{ + (void)st; + + struct font *font = theme_default()->fonts[THEME_FONT_INTERFACE]; + struct texture tex; + + painter_set_color(0xffffffff); + painter_clear(); + + if (!font_render(font, &tex, "Example of text. Use <Left>/<Right> to change color and <Space> to toggle antialiasing.", colors[ci])) + panic(); + + texture_draw(&tex, 10, 10); + painter_present(); + texture_finish(&tex); +} + +static void run(void) { - struct clock clock = {0}; - struct font *font = theme_default()->fonts[THEME_FONT_INTERFACE]; - int ci = 0; - enum font_style style = font->style; - - clock_start(&clock); - - for (;;) { - struct texture tex; - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); + struct state state = { + .handle = handle, + .draw = draw + }; - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_KEYDOWN: - switch (ev.key.key) { - case KEY_LEFT: - if (ci > 0) - ci--; - break; - case KEY_RIGHT: - if ((size_t)ci < NELEM(colors)) - ci++; - break; - case KEY_SPACE: - if (style == FONT_STYLE_ANTIALIASED) - style = FONT_STYLE_NONE; - else - style = FONT_STYLE_ANTIALIASED; - default: - break; - } - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - painter_set_color(0xffffffff); - painter_clear(); - - font->style = style; - - if (!font_render(font, &tex, "Example of text. Use <Left>/<Right> to change color and <Space> to toggle antialiasing.", colors[ci])) - panic(); - - texture_draw(&tex, 10, 10); - painter_present(); - texture_finish(&tex); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void
--- a/examples/example-gridmenu.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-gridmenu.c Wed Nov 11 16:09:43 2020 +0100 @@ -16,11 +16,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/painter.h> #include <core/panic.h> +#include <core/state.h> #include <core/sys.h> #include <core/trace.h> #include <core/util.h> @@ -53,9 +54,43 @@ } static void +handle(struct state *st, const union event *ev) +{ + switch (ev->type) { + case EVENT_QUIT: + game_quit(); + break; + default: + gridmenu_handle(st->data, ev); + break; + } +} + +static void +update(struct state *st, unsigned int ticks) +{ + (void)ticks; + + struct gridmenu *menu = st->data; + + if (menu->state == GRIDMENU_STATE_ACTIVATED) { + tracef("selected index: %u", (unsigned int)menu->selected); + gridmenu_reset(menu); + } +} + +static void +draw(struct state *st) +{ + painter_set_color(0x4f8fbaff); + painter_clear(); + gridmenu_draw(st->data); + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; struct gridmenu menu = { .menu = { "Feu mineur", @@ -76,42 +111,20 @@ .nrows = 3, .ncols = 2 }; + struct state state = { + .data = &menu, + .handle = handle, + .update = update, + .draw = draw, + }; - clock_start(&clock); align(ALIGN_CENTER, &menu.x, &menu.y, menu.w, menu.h, 0, 0, W, H); /* Need to repaint at least once. */ gridmenu_repaint(&menu); - for (;;) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_QUIT: - return; - default: - gridmenu_handle(&menu, &ev); - break; - } - } - - if (menu.state == GRIDMENU_STATE_ACTIVATED) { - tracef("selected index: %u", (unsigned int)menu.selected); - gridmenu_reset(&menu); - } - - painter_set_color(0x4f8fbaff); - painter_clear(); - gridmenu_draw(&menu); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } int
--- a/examples/example-label.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-label.c Wed Nov 11 16:09:43 2020 +0100 @@ -16,11 +16,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/painter.h> #include <core/panic.h> +#include <core/state.h> #include <core/sys.h> #include <core/util.h> #include <core/window.h> @@ -94,6 +95,10 @@ } }; +static struct label mlabel = { + .text = "This one follows your mouse and is not aligned." +}; + static void init(void) { @@ -120,46 +125,48 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_MOUSE: + mlabel.x = ev->mouse.x; + mlabel.y = ev->mouse.y; + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0x4f8fbaff); + painter_clear(); + + for (size_t i = 0; i < NELEM(table); ++i) + label_draw(&table[i].label); + + label_draw(&mlabel); + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; - struct label mlabel = { - .text = "This one follows your mouse and is not aligned." + struct state state = { + .handle = handle, + .draw = draw }; - clock_start(&clock); - - for (;;) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_MOUSE: - mlabel.x = ev.mouse.x; - mlabel.y = ev.mouse.y; - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - painter_set_color(0x4f8fbaff); - painter_clear(); - - for (size_t i = 0; i < NELEM(table); ++i) - label_draw(&table[i].label); - - label_draw(&mlabel); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } int
--- a/examples/example-message.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-message.c Wed Nov 11 16:09:43 2020 +0100 @@ -16,13 +16,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <string.h> - -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/painter.h> #include <core/panic.h> +#include <core/state.h> #include <core/sys.h> #include <core/util.h> #include <core/window.h> @@ -61,39 +60,48 @@ } static void +handle(struct state *st, const union event *ev) +{ + switch (ev->type) { + case EVENT_QUIT: + game_quit(); + break; + default: + message_handle(st->data, ev); + break; + } +} + +static void +update(struct state *st, unsigned int ticks) +{ + if (message_update(st->data, ticks)) + game_quit(); +} + +static void +draw(struct state *st) +{ + painter_set_color(0xffffffff); + painter_clear(); + message_draw(st->data); + painter_present(); +} + +static void run(struct message *msg) { - struct clock clock = {0}; + struct state state = { + .data = msg, + .handle = handle, + .update = update, + .draw = draw + }; message_start(msg); - clock_start(&clock); - while (msg->state) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_QUIT: - msg->state = MESSAGE_STATE_NONE; - break; - default: - message_handle(msg, &ev); - break; - } - } - - message_update(msg, elapsed); - painter_set_color(0xffffffff); - painter_clear(); - message_draw(msg); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void @@ -289,7 +297,7 @@ }; /* Borrow default theme and change its frame drawing. */ - memcpy(&theme, theme_default(), sizeof (theme)); + theme_shallow(&theme, NULL); theme.draw_frame = my_draw_frame; theme.colors[THEME_COLOR_NORMAL] = 0x0000ffff;
--- a/examples/example-sprite.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-sprite.c Wed Nov 11 16:09:43 2020 +0100 @@ -18,15 +18,16 @@ #include <stdio.h> -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/image.h> #include <core/key.h> #include <core/painter.h> #include <core/panic.h> #include <core/image.h> #include <core/sprite.h> +#include <core/state.h> #include <core/texture.h> #include <core/util.h> #include <core/window.h> @@ -73,63 +74,68 @@ } static void -run(void) +handle(struct state *st, const union event *ev) { - struct clock clock = {0}; + (void)st; + + switch (ev->type) { + case EVENT_KEYDOWN: + switch (ev->key.key) { + case KEY_LEFT: + if (column > 0) + column--; + break; + case KEY_RIGHT: + if (column + 1 < sprite.ncols) + column++; + break; + case KEY_UP: + if (row > 0) + row--; + break; + case KEY_DOWN: + if (row + 1 < sprite.nrows) + row++; + break; + default: + break; + } + + changed(); + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +draw(struct state *st) +{ + (void)st; + int x, y; - clock_start(&clock); - changed(); - - for (;;) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); + painter_set_color(0xebede9ff); + painter_clear(); + align(ALIGN_CENTER, &x, &y, sprite.cellw, sprite.cellh, 0, 0, W, H); + sprite_draw(&sprite, row, column, x, y); + label_draw(&help); + painter_present(); +} - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_KEYDOWN: - switch (ev.key.key) { - case KEY_LEFT: - if (column > 0) - column--; - break; - case KEY_RIGHT: - if (column + 1 < sprite.ncols) - column++; - break; - case KEY_UP: - if (row > 0) - row--; - break; - case KEY_DOWN: - if (row + 1 < sprite.nrows) - row++; - break; - default: - break; - } +static void +run(void) +{ + struct state state = { + .handle = handle, + .draw = draw + }; - changed(); - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - painter_set_color(0xebede9ff); - painter_clear(); - align(ALIGN_CENTER, &x, &y, sprite.cellw, sprite.cellh, 0, 0, W, H); - sprite_draw(&sprite, row, column, x, y); - label_draw(&help); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void
--- a/examples/example-trace.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-trace.c Wed Nov 11 16:09:43 2020 +0100 @@ -16,13 +16,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/sys.h> #include <core/window.h> #include <core/painter.h> #include <core/panic.h> +#include <core/state.h> #include <core/trace.h> #include <core/util.h> @@ -46,49 +47,62 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_KEYDOWN: + switch (ev->key.key) { + case KEY_ESCAPE: + trace_hud_clear(); + break; + default: + tracef("keydown pressed: %d", ev->key.key); + break; + } + break; + case EVENT_CLICKDOWN: + tracef("click at %d,%d", ev->click.x, ev->click.y); + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +update(struct state *st, unsigned int ticks) +{ + (void)st; + + trace_hud_update(ticks); +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0x4f8fbaff); + painter_clear(); + trace_hud_draw(); + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; - - clock_start(&clock); - - for (;;) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); + struct state state = { + .handle = handle, + .update = update, + .draw = draw + }; - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_KEYDOWN: - switch (ev.key.key) { - case KEY_ESCAPE: - trace_hud_clear(); - break; - default: - tracef("keydown pressed: %d", ev.key.key); - break; - } - break; - case EVENT_CLICKDOWN: - tracef("click at %d,%d", ev.click.x, ev.click.y); - break; - case EVENT_QUIT: - return; - default: - break; - } - } - - painter_set_color(0x4f8fbaff); - painter_clear(); - trace_hud_update(elapsed); - trace_hud_draw(); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void
--- a/examples/example-ui.c Tue Nov 10 17:32:12 2020 +0100 +++ b/examples/example-ui.c Wed Nov 11 16:09:43 2020 +0100 @@ -17,12 +17,13 @@ */ #include <core/action.h> -#include <core/clock.h> #include <core/core.h> #include <core/event.h> +#include <core/game.h> #include <core/maths.h> #include <core/panic.h> #include <core/painter.h> +#include <core/state.h> #include <core/sys.h> #include <core/util.h> #include <core/window.h> @@ -226,62 +227,79 @@ } static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_QUIT: + game_quit(); + break; + case EVENT_MOUSE: + if (ui.motion.active) { + ui.panel.frame.x += ev->mouse.x - ui.motion.x; + ui.panel.frame.y += ev->mouse.y - ui.motion.y; + ui.motion.x = ev->mouse.x; + ui.motion.y = ev->mouse.y; + resize(); + } + break; + case EVENT_CLICKDOWN: + if (headerclick(ev->click.x, ev->click.y)) { + ui.motion.active = true; + ui.motion.x = ev->click.x; + ui.motion.y = ev->click.y; + window_set_cursor(WINDOW_CURSOR_SIZE); + } + else + action_stack_handle(&ui.st, ev); + break; + case EVENT_CLICKUP: + ui.motion.active = false; + window_set_cursor(WINDOW_CURSOR_ARROW); + /* Fallthrough. */ + default: + action_stack_handle(&ui.st, ev); + break; + } +} + +static void +update(struct state *st, unsigned int ticks) +{ + (void)st; + + if (ui.quit.button.state == BUTTON_STATE_ACTIVATED) + game_quit(); + else + action_stack_update(&ui.st, ticks); +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0xffffffff); + painter_clear(); + action_stack_draw(&ui.st); + painter_present(); +} + +static void run(void) { - struct clock clock = {0}; - - clock_start(&clock); + struct state state = { + .handle = handle, + .update = update, + .draw = draw + }; prepare(); resize(); - while (ui.quit.button.state != BUTTON_STATE_ACTIVATED) { - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - for (union event ev; event_poll(&ev); ) { - switch (ev.type) { - case EVENT_QUIT: - return; - case EVENT_MOUSE: - if (ui.motion.active) { - ui.panel.frame.x += ev.mouse.x - ui.motion.x; - ui.panel.frame.y += ev.mouse.y - ui.motion.y; - ui.motion.x = ev.mouse.x; - ui.motion.y = ev.mouse.y; - resize(); - } - break; - case EVENT_CLICKDOWN: - if (headerclick(ev.click.x, ev.click.y)) { - ui.motion.active = true; - ui.motion.x = ev.click.x; - ui.motion.y = ev.click.y; - window_set_cursor(WINDOW_CURSOR_SIZE); - } - else - action_stack_handle(&ui.st, &ev); - break; - case EVENT_CLICKUP: - ui.motion.active = false; - window_set_cursor(WINDOW_CURSOR_ARROW); - /* Fallthrough. */ - default: - action_stack_handle(&ui.st, &ev); - break; - } - } - - painter_set_color(0xffffffff); - painter_clear(); - action_stack_update(&ui.st, elapsed); - action_stack_draw(&ui.st); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } + game_switch(&state, true); + game_loop(); } static void
--- a/libcore/core/game.c Tue Nov 10 17:32:12 2020 +0100 +++ b/libcore/core/game.c Wed Nov 11 16:09:43 2020 +0100 @@ -20,9 +20,12 @@ #include <stddef.h> #include <string.h> +#include "clock.h" +#include "event.h" #include "game.h" #include "state.h" #include "painter.h" +#include "util.h" struct game game; @@ -94,8 +97,33 @@ { if (game.state && !(game.inhibit & INHIBIT_STATE_DRAW)) state_draw(game.state); +} - painter_present(); +void +game_loop(void) +{ + struct clock clock = {0}; + double frametimemax = 1000.0 / 60.0; + unsigned int frametime = 0; + + while (game.state) { + clock_start(&clock); + + for (union event ev; event_poll(&ev); ) + game_handle(&ev); + + game_update(frametime); + game_draw(); + + /* + * Sleep not the full left time to allow context switches and + * such. + */ + if (frametime < frametimemax) + delay((frametimemax - frametime) / 4); + + frametime = clock_elapsed(&clock); + } } void
--- a/libcore/core/game.h Tue Nov 10 17:32:12 2020 +0100 +++ b/libcore/core/game.h Wed Nov 11 16:09:43 2020 +0100 @@ -87,6 +87,13 @@ game_draw(void); /** + * Start a game loop that calls game_handle, game_update and game_draw until + * game_quit has been called. + */ +void +game_loop(void); + +/** * Stop the game. * * This will effectively stop the current state but the main loop may continue