Mercurial > molko
changeset 322:eaab6bd635ab
misc: move examples from src/
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 02 Oct 2021 08:25:30 +0200 |
parents | 687ac7516bbf |
children | fbc748292c01 |
files | examples/example-action/main.c examples/example-animation/main.c examples/example-audio/main.c examples/example-battle/character-john.c examples/example-battle/character-john.h examples/example-battle/main.c examples/example-battle/registry.c examples/example-battle/registry.h examples/example-battle/spell-fire.c examples/example-battle/spell-fire.h examples/example-cursor/main.c examples/example-debug/main.c examples/example-drawable/main.c examples/example-font/main.c examples/example-gridmenu/main.c examples/example-label/main.c examples/example-message/main.c examples/example-sprite/main.c examples/example-trace/main.c examples/example-ui/main.c src/examples/example-action/main.c src/examples/example-animation/main.c src/examples/example-audio/main.c src/examples/example-battle/character-john.c src/examples/example-battle/character-john.h src/examples/example-battle/main.c src/examples/example-battle/registry.c src/examples/example-battle/registry.h src/examples/example-battle/spell-fire.c src/examples/example-battle/spell-fire.h src/examples/example-cursor/main.c src/examples/example-debug/main.c src/examples/example-drawable/main.c src/examples/example-font/main.c src/examples/example-gridmenu/main.c src/examples/example-label/main.c src/examples/example-message/main.c src/examples/example-sprite/main.c src/examples/example-trace/main.c src/examples/example-ui/main.c |
diffstat | 40 files changed, 3279 insertions(+), 3279 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-action/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,399 @@ +/* + * example-action.c -- example on how to use automatic actions + * + * Copyright (c) 2020-2021 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 <core/action.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> +#include <core/window.h> + +#include <ui/theme.h> +#include <ui/ui.h> + +#include <rpg/message.h> +#include <rpg/rpg.h> + +#define W 1280 +#define H 720 +#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) + +#define MW (W * 0.75) +#define MX ((W / 2) - (MW / 2)) +#define MY (100) + +/* This is a stack of "parallel" events. */ +static struct action_stack events; + +/* This is a stack of modal events. */ +static struct action_stack modal; + +/* + * Event object for the chest to click on. + */ +static struct { + struct message msg; + struct action msg_act; + int x; + int y; + int opened; + struct texture image; + struct sprite sprite; + struct action event; +} chest = { + .msg = { + .x = MX, + .y = MY, + .w = MW, + .text = { + "100000 pièces.", + "Te voilà riche sale file de crevette." + } + } +}; + +/* + * Event object for the guide who ask dialog with you. + * + * It is a script spawned upon click like this. + * + * [guide.event] + * | spawn + * (on click)------------------->[message 1] + * v + * [message 2] + * v + * [question 3] + * spawn v + * [response]<---------------------[check result] + * v + * [message 4/5] + */ +static struct { + struct { + struct message msg; + struct action act; + } msgs[5]; + + /* This is the sprite and action to click on. */ + int x; + int y; + struct texture image; + struct sprite sprite; + struct action event; + + /* This is the event for the response. */ + struct action response; + + struct script script; + struct action script_act; +} guide = { + .msgs = { + { + .msg = { + .x = MX, + .y = MY, + .w = MW, + .delay = MESSAGE_DELAY_DEFAULT, + .flags = MESSAGE_FLAGS_FADEIN, + .text = { + "Bienvenue dans ce monde Molko." + } + }, + }, + { + .msg = { + .x = MX, + .y = MY, + .w = MW, + .text = { + "Penses tu vraiment pouvoir me battre ?" + } + } + }, + { + .msg = { + .x = MX, + .y = MY, + .w = MW, + .flags = MESSAGE_FLAGS_QUESTION, + .text = { + "Non j'ai la trouille.", + "Bien sûr, je suis la légende." + } + } + }, + + /* In case of NO. */ + { + .msg = { + .x = MX, + .y = MY, + .w = MW, + .text = { + "Poule mouillée." + } + } + }, + + /* In case of YES. */ + { + .msg = { + .x = MX, + .y = MY, + .w = MW, + .text = { + "Prépare toi à souffrir." + } + } + } + } +}; + +static int +guide_response_update(struct action *act, unsigned int ticks) +{ + /* Immediately return to get access to end. */ + (void)act; + (void)ticks; + + return 1; +} + +static void +guide_response_end(struct action *act) +{ + (void)act; + + /* We add a final response depending on the result. */ + const int index = guide.msgs[2].msg.index + 3; + + message_action(&guide.msgs[index].msg, &guide.msgs[index].act); + message_query(&guide.msgs[index].msg, NULL, &guide.msgs[index].msg.h); + action_stack_add(&modal, &guide.msgs[index].act); +} + +static void +guide_popup(void) +{ + /* Prepare the script with first 3 messages. */ + for (size_t i = 0; i < 3; ++i) { + message_action(&guide.msgs[i].msg, &guide.msgs[i].act); + message_query(&guide.msgs[i].msg, NULL, &guide.msgs[i].msg.h); + script_append(&guide.script, &guide.msgs[i].act); + } + + /* Reset the message index. */ + guide.msgs[2].msg.index = 0; + + /* This is final action that analyze user input. */ + guide.response.update = guide_response_update; + guide.response.end = guide_response_end; + script_append(&guide.script, &guide.response); + + script_action(&guide.script, &guide.script_act); + action_stack_add(&modal, &guide.script_act); +} + +static void +guide_handle(struct action *act, const union event *ev) +{ + (void)act; + + if (!action_stack_completed(&modal)) + return; + + switch (ev->type) { + case EVENT_CLICKDOWN: + if (maths_is_boxed(guide.x, guide.y, + guide.sprite.cellw, guide.sprite.cellh, + ev->click.x, ev->click.y)) + guide_popup(); + break; + default: + break; + } +} + +static void +guide_draw(struct action *act) +{ + (void)act; + + sprite_draw(&guide.sprite, 0, 0, guide.x, guide.y); +} + +static void +guide_init(void) +{ + if (image_open(&guide.image, PATH("sprites/people.png")) < 0) + panic(); + + sprite_init(&guide.sprite, &guide.image, 48, 48); + + /* This is the global guide action. */ + guide.event.handle = guide_handle; + guide.event.draw = guide_draw; + guide.x = 200; + guide.y = 200; +} + +static void +chest_handle(struct action *act, const union event *ev) +{ + (void)act; + + if (chest.opened || !action_stack_completed(&modal)) + return; + + switch (ev->type) { + case EVENT_CLICKDOWN: + if (maths_is_boxed(chest.x, chest.y, chest.sprite.cellw, chest.sprite.cellh, + ev->click.x, ev->click.y)) { + chest.opened = 1; + message_action(&chest.msg, &chest.msg_act); + message_query(&chest.msg, NULL, &chest.msg.h); + action_stack_add(&modal, &chest.msg_act); + } + default: + break; + } +} + +static void +chest_draw(struct action *act) +{ + (void)act; + + const int row = chest.opened ? chest.sprite.nrows - 1 : 0; + const int col = chest.opened ? chest.sprite.ncols - 1 : 0; + + sprite_draw(&chest.sprite, row, col, chest.x, chest.y); +} + +static void +chest_init(void) +{ + if (image_open(&chest.image, PATH("sprites/chest.png")) < 0) + panic(); + + sprite_init(&chest.sprite, &chest.image, 32, 32); + + chest.x = 100; + chest.y = 100; + chest.event.handle = chest_handle; + chest.event.draw = chest_draw; +} + +static void +init(void) +{ + if (core_init("fr.malikania", "actions") < 0 || ui_init() < 0 || rpg_init() < 0) + panic(); + if (window_open("Example - Action", W, H) < 0) + panic(); + + guide_init(); + chest_init(); +} + +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 state state = { + .handle = handle, + .update = update, + .draw = draw + }; + + action_stack_add(&events, &chest.event); + action_stack_add(&events, &guide.event); + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + window_finish(); + rpg_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-animation/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,145 @@ +/* + * example-animation.c -- example on how to use animations + * + * Copyright (c) 2020-2021 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 <core/animation.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> + +#include <ui/label.h> +#include <ui/ui.h> + +#define W 1280 +#define H 720 +#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) + +static struct label label = { + .text = "Keys: <Space> start or reset the animation.", + .x = 10, + .y = 10, + .flags = LABEL_FLAGS_SHADOW +}; + +static struct texture numbers; +static struct animation animation; +static struct sprite sprite; +static int completed = 1; + +static void +init(void) +{ + if (core_init("fr.malikania", "animation") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Animation", W, H) < 0) + panic(); + if (image_open(&numbers, PATH("sprites/numbers.png")) < 0) + panic(); +} + +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 state state = { + .handle = handle, + .update = update, + .draw = draw + }; + + sprite_init(&sprite, &numbers, 48, 48); + animation_init(&animation, &sprite, 1000); + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-audio/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,157 @@ +/* + * example-audio.c -- show how to use sounds and music + * + * Copyright (c) 2020-2021 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 <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> + +#include <ui/label.h> +#include <ui/theme.h> +#include <ui/ui.h> + +#define W 1280 +#define H 720 +#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) + +static struct music music; +static struct sound sound; + +static struct label label_music = { + .text = "Music: <Space> play, <f> fade in, <s> fade out, <p> pause, <r> resume, <q> stop, <l> loop.", + .x = 10, + .y = 10, + .flags = LABEL_FLAGS_SHADOW +}; + +static struct label label_sound = { + .text = "Sound: click anywhere to pop a sound.", + .x = 10, + .y = 30, + .flags = LABEL_FLAGS_SHADOW +}; + +static void +init(void) +{ + if (core_init("fr.malikania", "audio") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Audio", W, H) < 0) + panic(); + if (music_open(&music, PATH("music/vabsounds-romance.ogg")) < 0 || + sound_open(&sound, PATH("sounds/fire.wav")) < 0) + panic(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +static void +handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_CLICKDOWN: + if (sound_play(&sound, -1, 0) < 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 state state = { + .handle = handle, + .draw = draw + }; + + game_push(&state); + game_loop(); + + music_finish(&music); + sound_finish(&sound); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/character-john.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,48 @@ +/* + * character-john.c -- john character + * + * Copyright (c) 2020-2021 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 <rpg/character.h> + +#include "character-john.h" +#include "spell-fire.h" +#include "registry.h" + +static void +adventurer_reset(struct character *ch) +{ + /* TODO: this function should compute the attack thanks to the level. */ + ch->hpmax = 120; + ch->mpmax = 50; + ch->atk = 50; + ch->def = 50; + ch->agt = 50; + ch->luck = 50; +} + +const struct character character_john = { + .name = "John ", + .type = "Adventurer", + .level = 1, + .hp = 120, + .mp = 50, + .reset = adventurer_reset, + .sprite = ®istry_sprites[REGISTRY_TEXTURE_JOHN], + .spells = { + &spell_fire + } +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/character-john.h Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,24 @@ +/* + * character-john.h -- john character + * + * Copyright (c) 2020-2021 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 EXAMPLES_BATTLE_CHARACTER_JOHN_H +#define EXAMPLES_BATTLE_CHARACTER_JOHN_H + +const struct character character_john; + +#endif /* !EXAMPLES_BATTLE_CHARACTER_JOHN_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,295 @@ +/* + * example-battle.c -- show how to use battle + * + * Copyright (c) 2020-2021 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 <stdio.h> +#include <stdlib.h> +#include <string.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> +#include <core/window.h> + +#include <ui/align.h> +#include <ui/label.h> +#include <ui/theme.h> +#include <ui/ui.h> + +#include <rpg/character.h> +#include <rpg/battle.h> +#include <rpg/rpg.h> +#include <rpg/spell.h> + +#include "registry.h" +#include "spell-fire.h" + +#define W 1280 +#define H 720 + +static void +adventurer_reset(struct character *ch) +{ + /* TODO: this function should compute the attack thanks to the level. */ + ch->hpmax = 120; + ch->mpmax = 50; + ch->atk = 50; + ch->def = 50; + ch->agt = 50; + ch->luck = 50; +} + +static void +haunted_wood_reset(struct character *ch) +{ + ch->hpmax = ch->hp = 2000; + ch->mpmax = ch->mp = 250; + ch->atk = 178; + ch->def = 80; + ch->agt = 80; + ch->luck = 100; +} + +static void +black_cat_reset(struct character *ch) +{ + ch->hpmax = ch->hp = 126; + ch->mpmax = ch->mp = 38; + ch->atk = 22; + ch->def = 19; + ch->agt = 11; + ch->luck = 14; +} + +static struct character team[] = { + { + .name = "Molko", + .level = 1, + .hp = 120, + .mp = 50, + .reset = adventurer_reset, + .sprites = { + [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_JOHN_WALK], + [CHARACTER_SPRITE_SWORD] = ®istry_sprites[REGISTRY_TEXTURE_JOHN_SWORD], + }, + .spells = { + &spell_fire + } + }, +}; + +static void +haunted_wood_strat(struct character *ch, struct battle *bt) +{ + (void)ch; + + /* TODO: Select randomly. */ + battle_attack(bt, bt->order_cur->ch, bt->team[0].ch); +} + +static void +black_cat_strat(struct character *ch, struct battle *bt) +{ + (void)ch; + + /* TODO: Select randomly. */ + battle_attack(bt, bt->order_cur->ch, bt->team[0].ch); +} + +static struct character haunted_wood = { + .name = "Haunted Wood", + .level = 30, + .reset = haunted_wood_reset, + .sprites = { + [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_HAUNTED_WOOD], + }, + .exec = haunted_wood_strat +}; + +static struct character black_cat = { + .name = "Black Cat", + .level = 6, + .reset = black_cat_reset, + .sprites = { + [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_BLACK_CAT], + }, + .exec = black_cat_strat +}; + +static void +init(void) +{ + if (core_init("fr.malikania", "battle") < 0 || ui_init() < 0 || rpg_init() < 0) + panic(); + if (window_open("Example - Battle", W, H) < 0) + panic(); + + 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(void) +{ + struct battle *bt = alloc_new0(sizeof (*bt)); + +// bt->enemies[0].ch = &haunted_wood; + bt->team[0].ch = &team[0]; + //bt->team[1].ch = &team[1]; + + /* Positionate the single ennemy to the left. */ + align(ALIGN_LEFT, + &bt->enemies[0].x, &bt->enemies[0].y, + haunted_wood.sprites[CHARACTER_SPRITE_NORMAL]->cellw, + haunted_wood.sprites[CHARACTER_SPRITE_NORMAL]->cellh, + 0, 0, window.w, window.h); + + /* Black cat is near the previous monster. */ + bt->enemies[1].ch = &black_cat; + bt->enemies[1].x = 500; + bt->enemies[1].y = 100; + + bt->background = ®istry_images[REGISTRY_IMAGE_BATTLE_BACKGROUND]; + + battle_start(bt); + + fight_state.data = bt; + game_push(&fight_state); +} + + +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 +empty_draw(struct state *st) +{ + (void)st; + + static const struct label info = { + .text = "Press <Space> to start a battle.", + .x = 10, + .y = 10, + .flags = LABEL_FLAGS_SHADOW + }; + + painter_set_color(0x4f8fbaff); + painter_clear(); + label_draw(&info); + painter_present(); +} + +static struct state empty_state = { + .handle = empty_handle, + .draw = empty_draw +}; + +static void +fight_handle(struct state *st, const union event *ev) +{ + battle_handle(st->data, ev); +} + +static void +fight_update(struct state *st, unsigned int ticks) +{ + struct battle *bt = st->data; + + if (battle_update(bt, ticks)) + game_push(&empty_state); +} + +static void +fight_draw(struct state *st) +{ + painter_set_color(0x000000ff); + painter_clear(); + battle_draw(st->data); + painter_present(); +} + +static void +fight_finish(struct state *st) +{ + battle_finish(st->data); + free(st->data); +} + +static struct state fight_state = { + .handle = fight_handle, + .update = fight_update, + .draw = fight_draw, + .finish = fight_finish, +}; + +static void +run(void) +{ + game_push(&empty_state); + game_loop(); +} + +static void +quit(void) +{ + registry_finish(); + theme_finish(); + window_finish(); + sys_finish(); +} + +int +main(int argc, char **argv) +{ + --argc; + ++argv; + + init(); + run(); + quit(); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/registry.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,128 @@ +/* + * registry.h -- registry of resources + * + * Copyright (c) 2020-2021 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 <stddef.h> + +#include <core/image.h> +#include <core/panic.h> +#include <core/util.h> +#include <core/sys.h> + +#include "registry.h" + +#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) + +struct texture registry_images[REGISTRY_IMAGE_NUM]; +struct texture registry_textures[REGISTRY_TEXTURE_NUM]; +struct sprite registry_sprites[REGISTRY_TEXTURE_NUM]; +struct sound registry_sounds[REGISTRY_SOUND_NUM]; + +#define REGISTRY_IMAGE(i, path) \ + { (i), (path) } + +static const struct { + enum registry_image index; + const char *path; +} images[] = { + REGISTRY_IMAGE(REGISTRY_IMAGE_BATTLE_BACKGROUND, "images/battle-background.png") +}; + +#define REGISTRY_TEXTURE(s, path, cw, ch) \ + { (s), (path), (cw), (ch) } + +static const struct { + enum registry_texture index; + const char *path; + unsigned int cellw; + unsigned int cellh; +} textures[] = { + REGISTRY_TEXTURE(REGISTRY_TEXTURE_CURSOR, "sprites/ui-cursor.png", 24, 24), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_EXPLOSION, "sprites/explosion.png", 256, 256), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_JOHN_SWORD, "sprites/john-sword.png", 256, 256), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_JOHN_WALK, "sprites/john-walk.png", 256, 256), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_HAUNTED_WOOD, "images/haunted-wood.png", 0, 0), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_BLACK_CAT, "images/black-cat.png", 0, 0) +}; + +#define REGISTRY_SOUND(s, path) \ + { (s), (path) } + +static const struct { + enum registry_sound index; + const char *path; +} sounds[] = { + REGISTRY_SOUND(REGISTRY_SOUND_FIRE, "sounds/fire.wav") +}; + +static void +load_images(void) +{ + for (size_t i = 0; i < UTIL_SIZE(images); ++i) { + struct texture *texture = ®istry_images[images[i].index]; + + if (image_open(texture, PATH(images[i].path)) < 0) + panic(); + } +} + +static void +load_textures_and_sprites(void) +{ + for (size_t i = 0; i < UTIL_SIZE(textures); ++i) { + struct texture *texture = ®istry_textures[textures[i].index]; + struct sprite *sprite = ®istry_sprites[textures[i].index]; + + if (image_open(texture, PATH(textures[i].path)) < 0) + panic(); + + if (textures[i].cellw == 0 || textures[i].cellh == 0) + sprite_init(sprite, texture, texture->w, texture->h); + else + sprite_init(sprite, texture, textures[i].cellw, textures[i].cellh); + } +} + +static void +load_sounds(void) +{ + for (size_t i = 0; i < UTIL_SIZE(sounds); ++i) { + struct sound *sound = ®istry_sounds[sounds[i].index]; + + if (sound_open(sound, PATH(sounds[i].path)) < 0) + panic(); + } +} + +void +registry_init(void) +{ + load_images(); + load_textures_and_sprites(); + load_sounds(); +} + +void +registry_finish(void) +{ + for (size_t i = 0; i < UTIL_SIZE(registry_images); ++i) + texture_finish(®istry_images[i]); + for (size_t i = 0; i < UTIL_SIZE(registry_textures); ++i) + texture_finish(®istry_textures[i]); + for (size_t i = 0; i < UTIL_SIZE(registry_sounds); ++i) + sound_finish(®istry_sounds[i]); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/registry.h Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,66 @@ +/* + * registry.h -- registry of resources + * + * Copyright (c) 2020-2021 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 EXAMPLES_BATTLE_REGISTRY_H +#define EXAMPLES_BATTLE_REGISTRY_H + +#include <core/sound.h> +#include <core/sprite.h> +#include <core/texture.h> + +enum registry_texture { + /* UI. */ + REGISTRY_TEXTURE_CURSOR, + + /* Animations. */ + REGISTRY_TEXTURE_EXPLOSION, + + /* Characters. */ + REGISTRY_TEXTURE_JOHN_WALK, + REGISTRY_TEXTURE_JOHN_SWORD, + + /* Enemies. */ + REGISTRY_TEXTURE_HAUNTED_WOOD, + REGISTRY_TEXTURE_BLACK_CAT, + + /* Unused.*/ + REGISTRY_TEXTURE_NUM +}; + +enum registry_image { + REGISTRY_IMAGE_BATTLE_BACKGROUND, + REGISTRY_IMAGE_NUM +}; + +enum registry_sound { + REGISTRY_SOUND_FIRE, + REGISTRY_SOUND_NUM +}; + +extern struct texture registry_images[REGISTRY_IMAGE_NUM]; +extern struct texture registry_textures[REGISTRY_TEXTURE_NUM]; +extern struct sprite registry_sprites[REGISTRY_TEXTURE_NUM]; +extern struct sound registry_sounds[REGISTRY_SOUND_NUM]; + +void +registry_init(void); + +void +registry_finish(void); + +#endif /* !EXAMPLES_BATTLE_REGISTRY_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/spell-fire.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,129 @@ +/* + * spell-fire.c -- example of spell: fire + * + * Copyright (c) 2020-2021 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 <stdlib.h> + +#include <core/action.h> +#include <core/animation.h> +#include <core/alloc.h> + +#include <ui/align.h> + +#include <rpg/battle.h> +#include <rpg/character.h> +#include <rpg/spell.h> + +#include "registry.h" +#include "spell-fire.h" + +struct data { + struct battle *battle; + struct character *target; + struct animation animation; + struct action action; + unsigned int selection; +}; + +static int +update(struct action *act, unsigned int ticks) +{ + struct data *data = act->data; + + return animation_update(&data->animation, ticks); +} + +static void +draw(struct action *act) +{ + const struct data *data = act->data; + const struct battle_entity *et = &data->battle->enemies[data->selection]; + const struct sprite *sprite = et->ch->sprites[CHARACTER_SPRITE_NORMAL]; + int x, y; + + align(ALIGN_CENTER, + &x, &y, data->animation.sprite->cellw, data->animation.sprite->cellh, + et->x, et->y, sprite->cellw, sprite->cellh); + + animation_draw(&data->animation, x, y); +} + +static void +end(struct action *act) +{ + struct data *data = act->data; + struct character *ch = data->battle->enemies[data->selection].ch; + + /* TODO: compute damage. */ + const unsigned int damage = 100; + + if ((unsigned int)ch->hp < damage) + ch->hp = 0; + else + ch->hp -= damage; + + battle_indicator_hp(data->battle, data->battle->enemies[data->selection].ch, 100); +} + +static void +finish(struct action *act) +{ + free(act->data); +} + +static void +fire_select(const struct battle *bt, struct selection *slt) +{ + slt->index_side = 0; + + selection_first(slt, bt); +} + +static void +fire_action(struct battle *bt, struct character *owner, const struct selection *slt) +{ + struct data *data; + + (void)owner; + + data = alloc_new0(sizeof (*data)); + data->selection = slt->index_character; + data->battle = bt; + data->action.data = data; + data->action.update = update; + data->action.draw = draw; + data->action.finish = finish; + data->action.end = end; + + animation_init(&data->animation, ®istry_sprites[REGISTRY_TEXTURE_EXPLOSION], 12); + animation_start(&data->animation); + + sound_play(®istry_sounds[REGISTRY_SOUND_FIRE], -1, 0); + + action_stack_add(&bt->actions[0], &data->action); +} + +const struct spell spell_fire = { + .name = "Fire", + .description = "A delicate fire.", + .mp = 5, + .type = SPELL_TYPE_FIRE, + .select = fire_select, + .select_kind = SELECTION_KIND_ONE, + .select_side = SELECTION_SIDE_ENEMY, + .action = fire_action +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/spell-fire.h Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,24 @@ +/* + * spell-fire.c -- example of spell: fire + * + * Copyright (c) 2020-2021 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 EXAMPLES_BATTLE_SPELL_FIRE_H +#define EXAMPLES_BATTLE_SPELL_FIRE_H + +extern const struct spell spell_fire; + +#endif /* !EXAMPLES_BATTLE_SPELL_FIRE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-cursor/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,146 @@ +/* + * example-cursor.c -- example on how to change cursor + * + * Copyright (c) 2020-2021 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 <stdio.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> + +#include <ui/label.h> +#include <ui/ui.h> + +#define W 1280 +#define H 720 + +static char help_text[128]; +static enum window_cursor cursor = WINDOW_CURSOR_ARROW; + +static struct label help = { + .x = 10, + .y = 10, + .text = help_text, + .flags = LABEL_FLAGS_SHADOW +}; + +static void +init(void) +{ + if (core_init("fr.malikania", "cursor") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Cursor", W, H) < 0) + panic(); +} + +static void +change(enum window_cursor cursor) +{ + static const char *names[] = { + [WINDOW_CURSOR_ARROW] = "WINDOW_CURSOR_ARROW", + [WINDOW_CURSOR_EDIT] = "WINDOW_CURSOR_EDIT", + [WINDOW_CURSOR_WAIT] = "WINDOW_CURSOR_WAIT", + [WINDOW_CURSOR_CROSSHAIR] = "WINDOW_CURSOR_CROSSHAIR", + [WINDOW_CURSOR_SIZE] = "WINDOW_CURSOR_SIZE", + [WINDOW_CURSOR_NO] = "WINDOW_CURSOR_NO", + [WINDOW_CURSOR_HAND] = "WINDOW_CURSOR_HAND" + }; + + snprintf(help_text, sizeof (help_text), "Keys: <Left>/<Right> to change cursor. Current: %s", names[cursor]); + window_set_cursor(cursor); +} + +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 state state = { + .handle = handle, + .draw = draw + }; + + change(cursor); + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-debug/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,111 @@ +/* + * example-debug.c -- example on how to use debug interface + * + * Copyright (c) 2020-2021 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 <core/core.h> +#include <core/event.h> +#include <core/game.h> +#include <core/window.h> +#include <core/painter.h> +#include <core/panic.h> +#include <core/state.h> +#include <core/util.h> + +#include <ui/debug.h> +#include <ui/theme.h> +#include <ui/ui.h> + +#define W 1280 +#define H 720 + +static int mouse_x; +static int mouse_y; + +static void +init(void) +{ + if (core_init("fr.malikania", "debug") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Debug", W, H) < 0) + panic(); + + debug_options.enable = 1; +} + +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 state state = { + .handle = handle, + .draw = draw + }; + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-drawable/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,201 @@ +/* + * example-drawable.c -- example on how to use automatic drawables + * + * Copyright (c) 2020-2021 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 <stdio.h> +#include <stdlib.h> + +#include <core/alloc.h> +#include <core/animation.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> +#include <core/panic.h> +#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> + +#include <ui/label.h> +#include <ui/theme.h> +#include <ui/ui.h> + +#define W 1280 +#define H 720 +#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) + +static struct label help = { + .x = 10, + .y = 10, + .text = "Keys: <Esc> to reset. Click anywhere to spawn a drawable.", + .flags = LABEL_FLAGS_SHADOW +}; + +static struct drawable_stack stack; + +/* + * List of drawables for this example. + * ----------------------------------------------------------------------------- + */ + +/* 0: Explosion animation. */ +static struct texture explosion_tex; +static struct sprite explosion_sprite; + +struct explosion { + struct animation anim; + struct drawable dw; +}; + +static void +init(void) +{ + if (core_init("fr.malikania", "drawable") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Drawable", W, H) < 0) + panic(); + + /* 0: Explosion animation. */ + if (image_open(&explosion_tex, PATH("sprites/explosion.png")) < 0) + panic(); + + sprite_init(&explosion_sprite, &explosion_tex, 256, 256); +} + +static int +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) +{ + free(dw->data); +} + +static void +spawn(int x, int y) +{ + struct explosion *ex = alloc_new0(sizeof (*ex)); + + animation_init(&ex->anim, &explosion_sprite, 15); + + 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; + + 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; + } +} + +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 state state = { + .handle = handle, + .update = update, + .draw = draw + }; + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-font/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,146 @@ +/* + * example-font.c -- show how to use fonts + * + * Copyright (c) 2020-2021 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 <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> +#include <core/window.h> + +#include <ui/theme.h> +#include <ui/ui.h> + +#define W (1280) +#define H (720) + +/* Friendly taken from: https://lospec.com/palette-list/apollo */ +static const unsigned long colors[] = { + 0x3c5e8bff, /* Blue. */ + 0x468232ff, /* Green. */ + 0xad7757ff, /* Light brown. */ + 0x884b2bff, /* Brown. */ + 0x752438ff, /* Red. */ + 0x7a367bff, /* Magenta. */ + 0x151d28ff, /* Dark */ + 0xc7cfccff, /* Christian Grey. */ +}; + +static int ci = 0; +static enum font_style style = FONT_STYLE_ANTIALIASED; + +static void +init(void) +{ + if (core_init("fr.malikania", "font") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Font", W, H) < 0) + panic(); +} + +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 < UTIL_SIZE(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]) < 0) + panic(); + + texture_draw(&tex, 10, 10); + painter_present(); + texture_finish(&tex); +} + +static void +run(void) +{ + struct state state = { + .handle = handle, + .draw = draw + }; + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-gridmenu/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,139 @@ +/* + * example-gridmenu.c -- show how to use grid menu + * + * Copyright (c) 2020-2021 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 <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> +#include <core/window.h> + +#include <ui/align.h> +#include <ui/gridmenu.h> +#include <ui/label.h> +#include <ui/theme.h> +#include <ui/ui.h> + +#define W (1280) +#define H (720) + +static void +init(void) +{ + if (core_init("fr.malikania", "grid-menu") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Grid menu", W, H) < 0) + panic(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +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 gridmenu menu = { + .menu = { + "Feu mineur", + "Feu majeur", + "Feu septième", + "Glace mineure", + "Glace majeure", + "Glace septième", + "Foudre mineure", + "Foudre majeure", + "Foudre septième", + "Choc mineur", + "Choc majeur", + "Choc septième", + }, + .w = 300, + .h = 100, + .nrows = 3, + .ncols = 2 + }; + struct state state = { + .data = &menu, + .handle = handle, + .update = update, + .draw = draw, + }; + + align(ALIGN_CENTER, &menu.x, &menu.y, menu.w, menu.h, 0, 0, W, H); + + /* Need to repaint at least once. */ + gridmenu_repaint(&menu); + + game_push(&state); + game_loop(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-label/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,183 @@ +/* + * example-label.c -- show how to use label and alignments + * + * Copyright (c) 2020-2021 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 <stddef.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> + +#include <ui/align.h> +#include <ui/label.h> +#include <ui/theme.h> +#include <ui/ui.h> + +#define W (1280) +#define H (720) + +struct { + enum align align; + struct label label; +} table[] = { + { + .align = ALIGN_TOP_LEFT, + .label = { + .text = "Top left" + } + }, + { + .align = ALIGN_TOP, + .label = { + .text = "Top", + } + }, + { + .align = ALIGN_TOP_RIGHT, + .label = { + .text = "Top right", + } + }, + { + .align = ALIGN_RIGHT, + .label = { + .text = "Right", + } + }, + { + .align = ALIGN_BOTTOM_RIGHT, + .label = { + .text = "Bottom right", + } + }, + { + .align = ALIGN_BOTTOM, + .label = { + .text = "Bottom", + } + }, + { + .align = ALIGN_BOTTOM_LEFT, + .label = { + .text = "Bottom left", + } + }, + { + .align = ALIGN_LEFT, + .label = { + .text = "Left", + } + }, + { + .align = ALIGN_CENTER, + .label = { + .text = "The world is Malikania.", + .flags = LABEL_FLAGS_SHADOW + } + } +}; + +static struct label mlabel = { + .text = "This one follows your mouse and is not aligned." +}; + +static void +init(void) +{ + if (core_init("fr.malikania", "label") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Label", W, H) < 0) + panic(); + + for (size_t i = 0; i < UTIL_SIZE(table); ++i) { + struct label *l = &table[i].label; + unsigned int w, h; + + label_query(l, &w, &h); + align(table[i].align, &l->x, &l->y, w, h, 0, 0, W, H); + } +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +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 < UTIL_SIZE(table); ++i) + label_draw(&table[i].label); + + label_draw(&mlabel); + painter_present(); +} + +static void +run(void) +{ + struct state state = { + .handle = handle, + .draw = draw + }; + + game_push(&state); + game_loop(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-message/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,327 @@ +/* + * example-message.c -- show how to use messages + * + * Copyright (c) 2020-2021 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 <stddef.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> + +#include <ui/frame.h> +#include <ui/theme.h> +#include <ui/ui.h> + +#include <rpg/message.h> +#include <rpg/rpg.h> + +#define W (1280) +#define H (720) + +#define MW (W * 0.75) +#define MH (H * 0.120) +#define MX ((W / 2) - (MW / 2)) +#define MY (100) + +static void +init(void) +{ + if (core_init("fr.malikania", "message") < 0 || ui_init() < 0 || rpg_init() < 0) + panic(); + if (window_open("Example - Message", W, H) < 0) + panic(); +} + +static void +quit(void) +{ + window_finish(); + rpg_finish(); + ui_finish(); + core_finish(); +} + +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 state state = { + .data = msg, + .handle = handle, + .update = update, + .draw = draw + }; + + message_start(msg); + + game_push(&state); + game_loop(); +} + +static void +my_draw_frame(const struct theme *th, const struct frame *f) +{ + (void)th; + + painter_set_color(0xff0000ff); + painter_draw_rectangle(f->x, f->y, f->w, f->h); +} + +static void +basic(void) +{ + struct message msg = { + .x = MX, + .y = MY, + .w = MW, + .spacing = 12, + .text = { + "This is a basic message.", + "Vertical spacing is automatically computed.", + "You need to press <Enter> to close it.", + }, + }; + + message_query(&msg, NULL, &msg.h); + run(&msg); +} + +static void +automatic(void) +{ + struct message msg = { + .x = MX, + .y = MY, + .w = MW, + .timeout = MESSAGE_TIMEOUT_DEFAULT, + .text = { + "This is a an automatic message.", + "It will disappear in a few seconds.", + "You can still press <Enter> to close it quicker." + }, + .flags = MESSAGE_FLAGS_AUTOMATIC + }; + + message_query(&msg, NULL, &msg.h); + run(&msg); +} + +static void +fadein(void) +{ + struct message msg = { + .x = MX, + .y = MY, + .w = MW, + .delay = MESSAGE_DELAY_DEFAULT, + .text = { + "This message will fade in." + }, + .flags = MESSAGE_FLAGS_FADEIN + }; + + message_query(&msg, NULL, &msg.h); + run(&msg); +} + +static void +fadeout(void) +{ + struct message msg = { + .x = MX, + .y = MY, + .w = MW, + .delay = MESSAGE_DELAY_DEFAULT, + .text = { + "This message will fade out." + }, + .flags = MESSAGE_FLAGS_FADEOUT + }; + + message_query(&msg, NULL, &msg.h); + run(&msg); +} + +static void +fade(void) +{ + struct message msg = { + .x = MX, + .y = MY, + .w = MW, + .delay = MESSAGE_DELAY_DEFAULT, + .text = { + "This message will fade in and out." + }, + .flags = MESSAGE_FLAGS_FADEIN | MESSAGE_FLAGS_FADEOUT + }; + + message_query(&msg, NULL, &msg.h); + run(&msg); +} + +static void +question(void) +{ + struct message msg = { + .x = MX, + .y = MY, + .w = MW, + .text = { + "Okay, I've understood.", + "Nevermind, I'll do it again." + }, + .flags = MESSAGE_FLAGS_QUESTION + }; + + message_query(&msg, NULL, &msg.h); + run(&msg); +} + +static void +smallbottom(void) +{ + const unsigned int w = window.w / 4; + const unsigned int h = MH; + const int x = (window.w / 2) - (w / 2); + const int y = (window.h - h - 10); + + struct message msg = { + .x = x, + .y = y, + .w = w, + .h = h, + .delay = MESSAGE_DELAY_DEFAULT, + .flags = MESSAGE_FLAGS_FADEIN | MESSAGE_FLAGS_FADEOUT, + .text = { + "This one is small here." + } + }; + + run(&msg); +} + +static void +toosmallh(void) +{ + struct message msg = { + .x = MX, + .y = MY, + .w = MW, + .h = 40, + .text = { + "This one is too small in height and will emit a warning.", + "Because this line will be incomplete." + }, + }; + + run(&msg); +} + +static void +toosmallw(void) +{ + struct message msg = { + .x = MX, + .y = MY, + .w = 160, + .h = MH, + .text = { + "This one is too small in width." + }, + }; + + run(&msg); +} + +static void +custom(void) +{ + struct theme theme; + struct message msg = { + .x = MX, + .y = MY, + .w = MW, + .h = MH, + .text = { + "This one will destroy your eyes.", + "Because it use a terrible custom theme." + }, + .theme = &theme + }; + + /* Borrow default theme and change its frame drawing. */ + theme_shallow(&theme, NULL); + theme.draw_frame = my_draw_frame; + theme.colors[THEME_COLOR_NORMAL] = 0x0000ffff; + + run(&msg); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + basic(); + fadein(); + fadeout(); + fade(); + automatic(); + question(); + smallbottom(); + toosmallh(); + toosmallw(); + custom(); + quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-sprite/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,161 @@ +/* + * example-sprite.c -- example on how to use sprites + * + * Copyright (c) 2020-2021 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 <stdio.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/sys.h> +#include <core/texture.h> +#include <core/util.h> +#include <core/window.h> + +#include <ui/align.h> +#include <ui/label.h> +#include <ui/ui.h> + +#define W 1280 +#define H 720 +#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) +#define HEADER "Keys: <Left>/<Right> and <Up/Down> to select a column/row. Current: %u, %u (total %u/%u)" + +static char msg[512]; +static struct texture texture; +static struct sprite sprite; +static unsigned int row, column; + +static struct label help = { + .x = 10, + .y = 10, + .text = msg, + .flags = LABEL_FLAGS_SHADOW +}; + +static void +changed(void) +{ + snprintf(msg, sizeof (msg), HEADER, column, row, sprite.ncols, sprite.nrows); +} + +static void +init(void) +{ + if (core_init("fr.malikania", "sprite") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Sprite", W, H) < 0) + panic(); + if (image_open(&texture, PATH("sprites/people.png")) < 0) + panic(); + + sprite_init(&sprite, &texture, 48, 48); +} + +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 (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; + + 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(); +} + +static void +run(void) +{ + struct state state = { + .handle = handle, + .draw = draw + }; + + changed(); + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + texture_finish(&texture); + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-trace/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,126 @@ +/* + * example-trace.c -- example on how to use custom trace handlers + * + * Copyright (c) 2020-2021 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 <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> + +#include <ui/theme.h> +#include <ui/ui.h> + +#include <adventure/trace_hud.h> + +#define W 1280 +#define H 720 + +static void +init(void) +{ + if (core_init("fr.malikania", "trace") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - Trace", W, H) < 0) + panic(); + + trace_handler = trace_hud_handler; +} + +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 state state = { + .handle = handle, + .update = update, + .draw = draw + }; + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-ui/main.c Sat Oct 02 08:25:30 2021 +0200 @@ -0,0 +1,324 @@ +/* + * example-action.c -- example on how to use automatic actions + * + * Copyright (c) 2020-2021 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 <core/action.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> + +#include <ui/align.h> +#include <ui/button.h> +#include <ui/checkbox.h> +#include <ui/frame.h> +#include <ui/label.h> +#include <ui/theme.h> +#include <ui/ui.h> + +#define W (1280) +#define H (720) + +#define FRAME_ORIGIN_X (10) +#define FRAME_ORIGIN_Y (10) +#define FRAME_WIDTH (400) +#define FRAME_HEIGHT (200) + +#define HEADER_HEIGHT (32) + +#define ELEMENT_HEIGHT (20) + +/* + * We design a basic UI like this. + * + * FRAME_WIDTH + * +---------------------------------------------+-- + * | Title | | HEADER_HEIGHT + * +---------------------------------------------+-- + * | [x] Auto save | + * | | + * | | + * | [ Quit ] | + * +---------------------------------------------+ + */ +static struct { + struct action_stack st; + + struct { + int active; + int x; + int y; + } motion; + + struct { + struct frame frame; + struct action act; + } panel; + + struct { + struct label label; + struct action act; + } header; + + struct { + struct checkbox cb; + struct action cb_act; + struct label label; + struct action label_act; + } autosave; + + struct { + struct button button; + struct action act; + } quit; +} ui = { + .panel = { + .frame = { + .x = FRAME_ORIGIN_X, + .y = FRAME_ORIGIN_Y, + .w = FRAME_WIDTH, + .h = FRAME_HEIGHT + } + }, + .header = { + .label = { + .text = "Preferences", + .x = FRAME_ORIGIN_X, + .y = FRAME_ORIGIN_Y, + .flags = LABEL_FLAGS_SHADOW, + } + }, + .autosave = { + .cb = { + .w = ELEMENT_HEIGHT, + .h = ELEMENT_HEIGHT + }, + .label = { + .text = "Auto save game", + .flags = LABEL_FLAGS_SHADOW, + } + }, + .quit = { + .button = { + .text = "Quit", + .h = ELEMENT_HEIGHT + } + } +}; + +static void +init(void) +{ + if (core_init("fr.malikania", "ui") < 0 || ui_init() < 0) + panic(); + if (window_open("Example - UI", W, H) < 0) + panic(); +} + +static void +resize_header(void) +{ + struct frame *f = &ui.panel.frame; + struct label *l = &ui.header.label; + unsigned int w, h; + + /* Header. */ + label_query(l, &w, &h); + align(ALIGN_LEFT, &l->x, &l->y, w, h, f->x, f->y, f->w, HEADER_HEIGHT); + + l->x += theme_default()->padding; +} + +static void +resize_autosave(void) +{ + unsigned int padding = theme_default()->padding; + struct frame *f = &ui.panel.frame; + struct checkbox *c = &ui.autosave.cb; + struct label *l = &ui.autosave.label; + + c->x = f->x + padding; + c->y = f->y + HEADER_HEIGHT + padding; + + l->x = c->x + c->w + padding; + l->y = c->y; +} + +static void +resize_button(void) +{ + unsigned int padding = theme_default()->padding; + struct frame *f = &ui.panel.frame; + struct button *b = &ui.quit.button; + + /* Button. */ + b->w = f->w / 4; + + align(ALIGN_BOTTOM_RIGHT, &b->x, &b->y, b->w, b->h, + f->x, f->y, f->w, f->h); + + b->x -= padding; + b->y -= padding; +} + +static void +resize(void) +{ + resize_header(); + resize_autosave(); + resize_button(); +} + +static void +prepare(void) +{ + /* Frame. */ + frame_action(&ui.panel.frame, &ui.panel.act); + + /* Header title. */ + label_action(&ui.header.label, &ui.header.act); + + /* Button quit. */ + button_action(&ui.quit.button, &ui.quit.act); + + /* Autosave. */ + checkbox_action(&ui.autosave.cb, &ui.autosave.cb_act); + label_action(&ui.autosave.label, &ui.autosave.label_act); + + /* Add all UI elements. */ + action_stack_add(&ui.st, &ui.panel.act); + action_stack_add(&ui.st, &ui.header.act); + action_stack_add(&ui.st, &ui.autosave.cb_act); + action_stack_add(&ui.st, &ui.autosave.label_act); + action_stack_add(&ui.st, &ui.quit.act); +} + +static int +headerclick(int x, int y) +{ + return maths_is_boxed( + ui.panel.frame.x, + ui.panel.frame.y, + ui.panel.frame.w, + HEADER_HEIGHT, + x, + y + ); +} + +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 = 1; + 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 = 0; + 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 state state = { + .handle = handle, + .update = update, + .draw = draw + }; + + prepare(); + resize(); + + game_push(&state); + game_loop(); +} + +static void +quit(void) +{ + window_finish(); + ui_finish(); + core_finish(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); + + return 0; +}
--- a/src/examples/example-action/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,399 +0,0 @@ -/* - * example-action.c -- example on how to use automatic actions - * - * Copyright (c) 2020-2021 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 <core/action.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> -#include <core/window.h> - -#include <ui/theme.h> -#include <ui/ui.h> - -#include <rpg/message.h> -#include <rpg/rpg.h> - -#define W 1280 -#define H 720 -#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) - -#define MW (W * 0.75) -#define MX ((W / 2) - (MW / 2)) -#define MY (100) - -/* This is a stack of "parallel" events. */ -static struct action_stack events; - -/* This is a stack of modal events. */ -static struct action_stack modal; - -/* - * Event object for the chest to click on. - */ -static struct { - struct message msg; - struct action msg_act; - int x; - int y; - int opened; - struct texture image; - struct sprite sprite; - struct action event; -} chest = { - .msg = { - .x = MX, - .y = MY, - .w = MW, - .text = { - "100000 pièces.", - "Te voilà riche sale file de crevette." - } - } -}; - -/* - * Event object for the guide who ask dialog with you. - * - * It is a script spawned upon click like this. - * - * [guide.event] - * | spawn - * (on click)------------------->[message 1] - * v - * [message 2] - * v - * [question 3] - * spawn v - * [response]<---------------------[check result] - * v - * [message 4/5] - */ -static struct { - struct { - struct message msg; - struct action act; - } msgs[5]; - - /* This is the sprite and action to click on. */ - int x; - int y; - struct texture image; - struct sprite sprite; - struct action event; - - /* This is the event for the response. */ - struct action response; - - struct script script; - struct action script_act; -} guide = { - .msgs = { - { - .msg = { - .x = MX, - .y = MY, - .w = MW, - .delay = MESSAGE_DELAY_DEFAULT, - .flags = MESSAGE_FLAGS_FADEIN, - .text = { - "Bienvenue dans ce monde Molko." - } - }, - }, - { - .msg = { - .x = MX, - .y = MY, - .w = MW, - .text = { - "Penses tu vraiment pouvoir me battre ?" - } - } - }, - { - .msg = { - .x = MX, - .y = MY, - .w = MW, - .flags = MESSAGE_FLAGS_QUESTION, - .text = { - "Non j'ai la trouille.", - "Bien sûr, je suis la légende." - } - } - }, - - /* In case of NO. */ - { - .msg = { - .x = MX, - .y = MY, - .w = MW, - .text = { - "Poule mouillée." - } - } - }, - - /* In case of YES. */ - { - .msg = { - .x = MX, - .y = MY, - .w = MW, - .text = { - "Prépare toi à souffrir." - } - } - } - } -}; - -static int -guide_response_update(struct action *act, unsigned int ticks) -{ - /* Immediately return to get access to end. */ - (void)act; - (void)ticks; - - return 1; -} - -static void -guide_response_end(struct action *act) -{ - (void)act; - - /* We add a final response depending on the result. */ - const int index = guide.msgs[2].msg.index + 3; - - message_action(&guide.msgs[index].msg, &guide.msgs[index].act); - message_query(&guide.msgs[index].msg, NULL, &guide.msgs[index].msg.h); - action_stack_add(&modal, &guide.msgs[index].act); -} - -static void -guide_popup(void) -{ - /* Prepare the script with first 3 messages. */ - for (size_t i = 0; i < 3; ++i) { - message_action(&guide.msgs[i].msg, &guide.msgs[i].act); - message_query(&guide.msgs[i].msg, NULL, &guide.msgs[i].msg.h); - script_append(&guide.script, &guide.msgs[i].act); - } - - /* Reset the message index. */ - guide.msgs[2].msg.index = 0; - - /* This is final action that analyze user input. */ - guide.response.update = guide_response_update; - guide.response.end = guide_response_end; - script_append(&guide.script, &guide.response); - - script_action(&guide.script, &guide.script_act); - action_stack_add(&modal, &guide.script_act); -} - -static void -guide_handle(struct action *act, const union event *ev) -{ - (void)act; - - if (!action_stack_completed(&modal)) - return; - - switch (ev->type) { - case EVENT_CLICKDOWN: - if (maths_is_boxed(guide.x, guide.y, - guide.sprite.cellw, guide.sprite.cellh, - ev->click.x, ev->click.y)) - guide_popup(); - break; - default: - break; - } -} - -static void -guide_draw(struct action *act) -{ - (void)act; - - sprite_draw(&guide.sprite, 0, 0, guide.x, guide.y); -} - -static void -guide_init(void) -{ - if (image_open(&guide.image, PATH("sprites/people.png")) < 0) - panic(); - - sprite_init(&guide.sprite, &guide.image, 48, 48); - - /* This is the global guide action. */ - guide.event.handle = guide_handle; - guide.event.draw = guide_draw; - guide.x = 200; - guide.y = 200; -} - -static void -chest_handle(struct action *act, const union event *ev) -{ - (void)act; - - if (chest.opened || !action_stack_completed(&modal)) - return; - - switch (ev->type) { - case EVENT_CLICKDOWN: - if (maths_is_boxed(chest.x, chest.y, chest.sprite.cellw, chest.sprite.cellh, - ev->click.x, ev->click.y)) { - chest.opened = 1; - message_action(&chest.msg, &chest.msg_act); - message_query(&chest.msg, NULL, &chest.msg.h); - action_stack_add(&modal, &chest.msg_act); - } - default: - break; - } -} - -static void -chest_draw(struct action *act) -{ - (void)act; - - const int row = chest.opened ? chest.sprite.nrows - 1 : 0; - const int col = chest.opened ? chest.sprite.ncols - 1 : 0; - - sprite_draw(&chest.sprite, row, col, chest.x, chest.y); -} - -static void -chest_init(void) -{ - if (image_open(&chest.image, PATH("sprites/chest.png")) < 0) - panic(); - - sprite_init(&chest.sprite, &chest.image, 32, 32); - - chest.x = 100; - chest.y = 100; - chest.event.handle = chest_handle; - chest.event.draw = chest_draw; -} - -static void -init(void) -{ - if (core_init("fr.malikania", "actions") < 0 || ui_init() < 0 || rpg_init() < 0) - panic(); - if (window_open("Example - Action", W, H) < 0) - panic(); - - guide_init(); - chest_init(); -} - -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 state state = { - .handle = handle, - .update = update, - .draw = draw - }; - - action_stack_add(&events, &chest.event); - action_stack_add(&events, &guide.event); - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - window_finish(); - rpg_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); - - return 0; -}
--- a/src/examples/example-animation/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -/* - * example-animation.c -- example on how to use animations - * - * Copyright (c) 2020-2021 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 <core/animation.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> - -#include <ui/label.h> -#include <ui/ui.h> - -#define W 1280 -#define H 720 -#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) - -static struct label label = { - .text = "Keys: <Space> start or reset the animation.", - .x = 10, - .y = 10, - .flags = LABEL_FLAGS_SHADOW -}; - -static struct texture numbers; -static struct animation animation; -static struct sprite sprite; -static int completed = 1; - -static void -init(void) -{ - if (core_init("fr.malikania", "animation") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Animation", W, H) < 0) - panic(); - if (image_open(&numbers, PATH("sprites/numbers.png")) < 0) - panic(); -} - -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 state state = { - .handle = handle, - .update = update, - .draw = draw - }; - - sprite_init(&sprite, &numbers, 48, 48); - animation_init(&animation, &sprite, 1000); - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -} -
--- a/src/examples/example-audio/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -/* - * example-audio.c -- show how to use sounds and music - * - * Copyright (c) 2020-2021 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 <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> - -#include <ui/label.h> -#include <ui/theme.h> -#include <ui/ui.h> - -#define W 1280 -#define H 720 -#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) - -static struct music music; -static struct sound sound; - -static struct label label_music = { - .text = "Music: <Space> play, <f> fade in, <s> fade out, <p> pause, <r> resume, <q> stop, <l> loop.", - .x = 10, - .y = 10, - .flags = LABEL_FLAGS_SHADOW -}; - -static struct label label_sound = { - .text = "Sound: click anywhere to pop a sound.", - .x = 10, - .y = 30, - .flags = LABEL_FLAGS_SHADOW -}; - -static void -init(void) -{ - if (core_init("fr.malikania", "audio") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Audio", W, H) < 0) - panic(); - if (music_open(&music, PATH("music/vabsounds-romance.ogg")) < 0 || - sound_open(&sound, PATH("sounds/fire.wav")) < 0) - panic(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -static void -handle(struct state *st, const union event *ev) -{ - (void)st; - - switch (ev->type) { - case EVENT_CLICKDOWN: - if (sound_play(&sound, -1, 0) < 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 state state = { - .handle = handle, - .draw = draw - }; - - game_push(&state); - game_loop(); - - music_finish(&music); - sound_finish(&sound); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -}
--- a/src/examples/example-battle/character-john.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * character-john.c -- john character - * - * Copyright (c) 2020-2021 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 <rpg/character.h> - -#include "character-john.h" -#include "spell-fire.h" -#include "registry.h" - -static void -adventurer_reset(struct character *ch) -{ - /* TODO: this function should compute the attack thanks to the level. */ - ch->hpmax = 120; - ch->mpmax = 50; - ch->atk = 50; - ch->def = 50; - ch->agt = 50; - ch->luck = 50; -} - -const struct character character_john = { - .name = "John ", - .type = "Adventurer", - .level = 1, - .hp = 120, - .mp = 50, - .reset = adventurer_reset, - .sprite = ®istry_sprites[REGISTRY_TEXTURE_JOHN], - .spells = { - &spell_fire - } -};
--- a/src/examples/example-battle/character-john.h Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -/* - * character-john.h -- john character - * - * Copyright (c) 2020-2021 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 EXAMPLES_BATTLE_CHARACTER_JOHN_H -#define EXAMPLES_BATTLE_CHARACTER_JOHN_H - -const struct character character_john; - -#endif /* !EXAMPLES_BATTLE_CHARACTER_JOHN_H */
--- a/src/examples/example-battle/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,295 +0,0 @@ -/* - * example-battle.c -- show how to use battle - * - * Copyright (c) 2020-2021 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 <stdio.h> -#include <stdlib.h> -#include <string.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> -#include <core/window.h> - -#include <ui/align.h> -#include <ui/label.h> -#include <ui/theme.h> -#include <ui/ui.h> - -#include <rpg/character.h> -#include <rpg/battle.h> -#include <rpg/rpg.h> -#include <rpg/spell.h> - -#include "registry.h" -#include "spell-fire.h" - -#define W 1280 -#define H 720 - -static void -adventurer_reset(struct character *ch) -{ - /* TODO: this function should compute the attack thanks to the level. */ - ch->hpmax = 120; - ch->mpmax = 50; - ch->atk = 50; - ch->def = 50; - ch->agt = 50; - ch->luck = 50; -} - -static void -haunted_wood_reset(struct character *ch) -{ - ch->hpmax = ch->hp = 2000; - ch->mpmax = ch->mp = 250; - ch->atk = 178; - ch->def = 80; - ch->agt = 80; - ch->luck = 100; -} - -static void -black_cat_reset(struct character *ch) -{ - ch->hpmax = ch->hp = 126; - ch->mpmax = ch->mp = 38; - ch->atk = 22; - ch->def = 19; - ch->agt = 11; - ch->luck = 14; -} - -static struct character team[] = { - { - .name = "Molko", - .level = 1, - .hp = 120, - .mp = 50, - .reset = adventurer_reset, - .sprites = { - [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_JOHN_WALK], - [CHARACTER_SPRITE_SWORD] = ®istry_sprites[REGISTRY_TEXTURE_JOHN_SWORD], - }, - .spells = { - &spell_fire - } - }, -}; - -static void -haunted_wood_strat(struct character *ch, struct battle *bt) -{ - (void)ch; - - /* TODO: Select randomly. */ - battle_attack(bt, bt->order_cur->ch, bt->team[0].ch); -} - -static void -black_cat_strat(struct character *ch, struct battle *bt) -{ - (void)ch; - - /* TODO: Select randomly. */ - battle_attack(bt, bt->order_cur->ch, bt->team[0].ch); -} - -static struct character haunted_wood = { - .name = "Haunted Wood", - .level = 30, - .reset = haunted_wood_reset, - .sprites = { - [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_HAUNTED_WOOD], - }, - .exec = haunted_wood_strat -}; - -static struct character black_cat = { - .name = "Black Cat", - .level = 6, - .reset = black_cat_reset, - .sprites = { - [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_BLACK_CAT], - }, - .exec = black_cat_strat -}; - -static void -init(void) -{ - if (core_init("fr.malikania", "battle") < 0 || ui_init() < 0 || rpg_init() < 0) - panic(); - if (window_open("Example - Battle", W, H) < 0) - panic(); - - 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(void) -{ - struct battle *bt = alloc_new0(sizeof (*bt)); - -// bt->enemies[0].ch = &haunted_wood; - bt->team[0].ch = &team[0]; - //bt->team[1].ch = &team[1]; - - /* Positionate the single ennemy to the left. */ - align(ALIGN_LEFT, - &bt->enemies[0].x, &bt->enemies[0].y, - haunted_wood.sprites[CHARACTER_SPRITE_NORMAL]->cellw, - haunted_wood.sprites[CHARACTER_SPRITE_NORMAL]->cellh, - 0, 0, window.w, window.h); - - /* Black cat is near the previous monster. */ - bt->enemies[1].ch = &black_cat; - bt->enemies[1].x = 500; - bt->enemies[1].y = 100; - - bt->background = ®istry_images[REGISTRY_IMAGE_BATTLE_BACKGROUND]; - - battle_start(bt); - - fight_state.data = bt; - game_push(&fight_state); -} - - -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 -empty_draw(struct state *st) -{ - (void)st; - - static const struct label info = { - .text = "Press <Space> to start a battle.", - .x = 10, - .y = 10, - .flags = LABEL_FLAGS_SHADOW - }; - - painter_set_color(0x4f8fbaff); - painter_clear(); - label_draw(&info); - painter_present(); -} - -static struct state empty_state = { - .handle = empty_handle, - .draw = empty_draw -}; - -static void -fight_handle(struct state *st, const union event *ev) -{ - battle_handle(st->data, ev); -} - -static void -fight_update(struct state *st, unsigned int ticks) -{ - struct battle *bt = st->data; - - if (battle_update(bt, ticks)) - game_push(&empty_state); -} - -static void -fight_draw(struct state *st) -{ - painter_set_color(0x000000ff); - painter_clear(); - battle_draw(st->data); - painter_present(); -} - -static void -fight_finish(struct state *st) -{ - battle_finish(st->data); - free(st->data); -} - -static struct state fight_state = { - .handle = fight_handle, - .update = fight_update, - .draw = fight_draw, - .finish = fight_finish, -}; - -static void -run(void) -{ - game_push(&empty_state); - game_loop(); -} - -static void -quit(void) -{ - registry_finish(); - theme_finish(); - window_finish(); - sys_finish(); -} - -int -main(int argc, char **argv) -{ - --argc; - ++argv; - - init(); - run(); - quit(); - - return 0; -}
--- a/src/examples/example-battle/registry.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * registry.h -- registry of resources - * - * Copyright (c) 2020-2021 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 <stddef.h> - -#include <core/image.h> -#include <core/panic.h> -#include <core/util.h> -#include <core/sys.h> - -#include "registry.h" - -#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) - -struct texture registry_images[REGISTRY_IMAGE_NUM]; -struct texture registry_textures[REGISTRY_TEXTURE_NUM]; -struct sprite registry_sprites[REGISTRY_TEXTURE_NUM]; -struct sound registry_sounds[REGISTRY_SOUND_NUM]; - -#define REGISTRY_IMAGE(i, path) \ - { (i), (path) } - -static const struct { - enum registry_image index; - const char *path; -} images[] = { - REGISTRY_IMAGE(REGISTRY_IMAGE_BATTLE_BACKGROUND, "images/battle-background.png") -}; - -#define REGISTRY_TEXTURE(s, path, cw, ch) \ - { (s), (path), (cw), (ch) } - -static const struct { - enum registry_texture index; - const char *path; - unsigned int cellw; - unsigned int cellh; -} textures[] = { - REGISTRY_TEXTURE(REGISTRY_TEXTURE_CURSOR, "sprites/ui-cursor.png", 24, 24), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_EXPLOSION, "sprites/explosion.png", 256, 256), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_JOHN_SWORD, "sprites/john-sword.png", 256, 256), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_JOHN_WALK, "sprites/john-walk.png", 256, 256), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_HAUNTED_WOOD, "images/haunted-wood.png", 0, 0), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_BLACK_CAT, "images/black-cat.png", 0, 0) -}; - -#define REGISTRY_SOUND(s, path) \ - { (s), (path) } - -static const struct { - enum registry_sound index; - const char *path; -} sounds[] = { - REGISTRY_SOUND(REGISTRY_SOUND_FIRE, "sounds/fire.wav") -}; - -static void -load_images(void) -{ - for (size_t i = 0; i < UTIL_SIZE(images); ++i) { - struct texture *texture = ®istry_images[images[i].index]; - - if (image_open(texture, PATH(images[i].path)) < 0) - panic(); - } -} - -static void -load_textures_and_sprites(void) -{ - for (size_t i = 0; i < UTIL_SIZE(textures); ++i) { - struct texture *texture = ®istry_textures[textures[i].index]; - struct sprite *sprite = ®istry_sprites[textures[i].index]; - - if (image_open(texture, PATH(textures[i].path)) < 0) - panic(); - - if (textures[i].cellw == 0 || textures[i].cellh == 0) - sprite_init(sprite, texture, texture->w, texture->h); - else - sprite_init(sprite, texture, textures[i].cellw, textures[i].cellh); - } -} - -static void -load_sounds(void) -{ - for (size_t i = 0; i < UTIL_SIZE(sounds); ++i) { - struct sound *sound = ®istry_sounds[sounds[i].index]; - - if (sound_open(sound, PATH(sounds[i].path)) < 0) - panic(); - } -} - -void -registry_init(void) -{ - load_images(); - load_textures_and_sprites(); - load_sounds(); -} - -void -registry_finish(void) -{ - for (size_t i = 0; i < UTIL_SIZE(registry_images); ++i) - texture_finish(®istry_images[i]); - for (size_t i = 0; i < UTIL_SIZE(registry_textures); ++i) - texture_finish(®istry_textures[i]); - for (size_t i = 0; i < UTIL_SIZE(registry_sounds); ++i) - sound_finish(®istry_sounds[i]); -}
--- a/src/examples/example-battle/registry.h Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * registry.h -- registry of resources - * - * Copyright (c) 2020-2021 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 EXAMPLES_BATTLE_REGISTRY_H -#define EXAMPLES_BATTLE_REGISTRY_H - -#include <core/sound.h> -#include <core/sprite.h> -#include <core/texture.h> - -enum registry_texture { - /* UI. */ - REGISTRY_TEXTURE_CURSOR, - - /* Animations. */ - REGISTRY_TEXTURE_EXPLOSION, - - /* Characters. */ - REGISTRY_TEXTURE_JOHN_WALK, - REGISTRY_TEXTURE_JOHN_SWORD, - - /* Enemies. */ - REGISTRY_TEXTURE_HAUNTED_WOOD, - REGISTRY_TEXTURE_BLACK_CAT, - - /* Unused.*/ - REGISTRY_TEXTURE_NUM -}; - -enum registry_image { - REGISTRY_IMAGE_BATTLE_BACKGROUND, - REGISTRY_IMAGE_NUM -}; - -enum registry_sound { - REGISTRY_SOUND_FIRE, - REGISTRY_SOUND_NUM -}; - -extern struct texture registry_images[REGISTRY_IMAGE_NUM]; -extern struct texture registry_textures[REGISTRY_TEXTURE_NUM]; -extern struct sprite registry_sprites[REGISTRY_TEXTURE_NUM]; -extern struct sound registry_sounds[REGISTRY_SOUND_NUM]; - -void -registry_init(void); - -void -registry_finish(void); - -#endif /* !EXAMPLES_BATTLE_REGISTRY_H */
--- a/src/examples/example-battle/spell-fire.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/* - * spell-fire.c -- example of spell: fire - * - * Copyright (c) 2020-2021 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 <stdlib.h> - -#include <core/action.h> -#include <core/animation.h> -#include <core/alloc.h> - -#include <ui/align.h> - -#include <rpg/battle.h> -#include <rpg/character.h> -#include <rpg/spell.h> - -#include "registry.h" -#include "spell-fire.h" - -struct data { - struct battle *battle; - struct character *target; - struct animation animation; - struct action action; - unsigned int selection; -}; - -static int -update(struct action *act, unsigned int ticks) -{ - struct data *data = act->data; - - return animation_update(&data->animation, ticks); -} - -static void -draw(struct action *act) -{ - const struct data *data = act->data; - const struct battle_entity *et = &data->battle->enemies[data->selection]; - const struct sprite *sprite = et->ch->sprites[CHARACTER_SPRITE_NORMAL]; - int x, y; - - align(ALIGN_CENTER, - &x, &y, data->animation.sprite->cellw, data->animation.sprite->cellh, - et->x, et->y, sprite->cellw, sprite->cellh); - - animation_draw(&data->animation, x, y); -} - -static void -end(struct action *act) -{ - struct data *data = act->data; - struct character *ch = data->battle->enemies[data->selection].ch; - - /* TODO: compute damage. */ - const unsigned int damage = 100; - - if ((unsigned int)ch->hp < damage) - ch->hp = 0; - else - ch->hp -= damage; - - battle_indicator_hp(data->battle, data->battle->enemies[data->selection].ch, 100); -} - -static void -finish(struct action *act) -{ - free(act->data); -} - -static void -fire_select(const struct battle *bt, struct selection *slt) -{ - slt->index_side = 0; - - selection_first(slt, bt); -} - -static void -fire_action(struct battle *bt, struct character *owner, const struct selection *slt) -{ - struct data *data; - - (void)owner; - - data = alloc_new0(sizeof (*data)); - data->selection = slt->index_character; - data->battle = bt; - data->action.data = data; - data->action.update = update; - data->action.draw = draw; - data->action.finish = finish; - data->action.end = end; - - animation_init(&data->animation, ®istry_sprites[REGISTRY_TEXTURE_EXPLOSION], 12); - animation_start(&data->animation); - - sound_play(®istry_sounds[REGISTRY_SOUND_FIRE], -1, 0); - - action_stack_add(&bt->actions[0], &data->action); -} - -const struct spell spell_fire = { - .name = "Fire", - .description = "A delicate fire.", - .mp = 5, - .type = SPELL_TYPE_FIRE, - .select = fire_select, - .select_kind = SELECTION_KIND_ONE, - .select_side = SELECTION_SIDE_ENEMY, - .action = fire_action -};
--- a/src/examples/example-battle/spell-fire.h Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -/* - * spell-fire.c -- example of spell: fire - * - * Copyright (c) 2020-2021 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 EXAMPLES_BATTLE_SPELL_FIRE_H -#define EXAMPLES_BATTLE_SPELL_FIRE_H - -extern const struct spell spell_fire; - -#endif /* !EXAMPLES_BATTLE_SPELL_FIRE_H */
--- a/src/examples/example-cursor/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * example-cursor.c -- example on how to change cursor - * - * Copyright (c) 2020-2021 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 <stdio.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> - -#include <ui/label.h> -#include <ui/ui.h> - -#define W 1280 -#define H 720 - -static char help_text[128]; -static enum window_cursor cursor = WINDOW_CURSOR_ARROW; - -static struct label help = { - .x = 10, - .y = 10, - .text = help_text, - .flags = LABEL_FLAGS_SHADOW -}; - -static void -init(void) -{ - if (core_init("fr.malikania", "cursor") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Cursor", W, H) < 0) - panic(); -} - -static void -change(enum window_cursor cursor) -{ - static const char *names[] = { - [WINDOW_CURSOR_ARROW] = "WINDOW_CURSOR_ARROW", - [WINDOW_CURSOR_EDIT] = "WINDOW_CURSOR_EDIT", - [WINDOW_CURSOR_WAIT] = "WINDOW_CURSOR_WAIT", - [WINDOW_CURSOR_CROSSHAIR] = "WINDOW_CURSOR_CROSSHAIR", - [WINDOW_CURSOR_SIZE] = "WINDOW_CURSOR_SIZE", - [WINDOW_CURSOR_NO] = "WINDOW_CURSOR_NO", - [WINDOW_CURSOR_HAND] = "WINDOW_CURSOR_HAND" - }; - - snprintf(help_text, sizeof (help_text), "Keys: <Left>/<Right> to change cursor. Current: %s", names[cursor]); - window_set_cursor(cursor); -} - -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 state state = { - .handle = handle, - .draw = draw - }; - - change(cursor); - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -}
--- a/src/examples/example-debug/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * example-debug.c -- example on how to use debug interface - * - * Copyright (c) 2020-2021 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 <core/core.h> -#include <core/event.h> -#include <core/game.h> -#include <core/window.h> -#include <core/painter.h> -#include <core/panic.h> -#include <core/state.h> -#include <core/util.h> - -#include <ui/debug.h> -#include <ui/theme.h> -#include <ui/ui.h> - -#define W 1280 -#define H 720 - -static int mouse_x; -static int mouse_y; - -static void -init(void) -{ - if (core_init("fr.malikania", "debug") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Debug", W, H) < 0) - panic(); - - debug_options.enable = 1; -} - -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 state state = { - .handle = handle, - .draw = draw - }; - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -} -
--- a/src/examples/example-drawable/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,201 +0,0 @@ -/* - * example-drawable.c -- example on how to use automatic drawables - * - * Copyright (c) 2020-2021 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 <stdio.h> -#include <stdlib.h> - -#include <core/alloc.h> -#include <core/animation.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> -#include <core/panic.h> -#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> - -#include <ui/label.h> -#include <ui/theme.h> -#include <ui/ui.h> - -#define W 1280 -#define H 720 -#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) - -static struct label help = { - .x = 10, - .y = 10, - .text = "Keys: <Esc> to reset. Click anywhere to spawn a drawable.", - .flags = LABEL_FLAGS_SHADOW -}; - -static struct drawable_stack stack; - -/* - * List of drawables for this example. - * ----------------------------------------------------------------------------- - */ - -/* 0: Explosion animation. */ -static struct texture explosion_tex; -static struct sprite explosion_sprite; - -struct explosion { - struct animation anim; - struct drawable dw; -}; - -static void -init(void) -{ - if (core_init("fr.malikania", "drawable") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Drawable", W, H) < 0) - panic(); - - /* 0: Explosion animation. */ - if (image_open(&explosion_tex, PATH("sprites/explosion.png")) < 0) - panic(); - - sprite_init(&explosion_sprite, &explosion_tex, 256, 256); -} - -static int -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) -{ - free(dw->data); -} - -static void -spawn(int x, int y) -{ - struct explosion *ex = alloc_new0(sizeof (*ex)); - - animation_init(&ex->anim, &explosion_sprite, 15); - - 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; - - 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; - } -} - -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 state state = { - .handle = handle, - .update = update, - .draw = draw - }; - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -}
--- a/src/examples/example-font/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * example-font.c -- show how to use fonts - * - * Copyright (c) 2020-2021 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 <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> -#include <core/window.h> - -#include <ui/theme.h> -#include <ui/ui.h> - -#define W (1280) -#define H (720) - -/* Friendly taken from: https://lospec.com/palette-list/apollo */ -static const unsigned long colors[] = { - 0x3c5e8bff, /* Blue. */ - 0x468232ff, /* Green. */ - 0xad7757ff, /* Light brown. */ - 0x884b2bff, /* Brown. */ - 0x752438ff, /* Red. */ - 0x7a367bff, /* Magenta. */ - 0x151d28ff, /* Dark */ - 0xc7cfccff, /* Christian Grey. */ -}; - -static int ci = 0; -static enum font_style style = FONT_STYLE_ANTIALIASED; - -static void -init(void) -{ - if (core_init("fr.malikania", "font") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Font", W, H) < 0) - panic(); -} - -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 < UTIL_SIZE(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]) < 0) - panic(); - - texture_draw(&tex, 10, 10); - painter_present(); - texture_finish(&tex); -} - -static void -run(void) -{ - struct state state = { - .handle = handle, - .draw = draw - }; - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); - - return 0; -}
--- a/src/examples/example-gridmenu/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* - * example-gridmenu.c -- show how to use grid menu - * - * Copyright (c) 2020-2021 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 <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> -#include <core/window.h> - -#include <ui/align.h> -#include <ui/gridmenu.h> -#include <ui/label.h> -#include <ui/theme.h> -#include <ui/ui.h> - -#define W (1280) -#define H (720) - -static void -init(void) -{ - if (core_init("fr.malikania", "grid-menu") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Grid menu", W, H) < 0) - panic(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -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 gridmenu menu = { - .menu = { - "Feu mineur", - "Feu majeur", - "Feu septième", - "Glace mineure", - "Glace majeure", - "Glace septième", - "Foudre mineure", - "Foudre majeure", - "Foudre septième", - "Choc mineur", - "Choc majeur", - "Choc septième", - }, - .w = 300, - .h = 100, - .nrows = 3, - .ncols = 2 - }; - struct state state = { - .data = &menu, - .handle = handle, - .update = update, - .draw = draw, - }; - - align(ALIGN_CENTER, &menu.x, &menu.y, menu.w, menu.h, 0, 0, W, H); - - /* Need to repaint at least once. */ - gridmenu_repaint(&menu); - - game_push(&state); - game_loop(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -}
--- a/src/examples/example-label/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -/* - * example-label.c -- show how to use label and alignments - * - * Copyright (c) 2020-2021 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 <stddef.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> - -#include <ui/align.h> -#include <ui/label.h> -#include <ui/theme.h> -#include <ui/ui.h> - -#define W (1280) -#define H (720) - -struct { - enum align align; - struct label label; -} table[] = { - { - .align = ALIGN_TOP_LEFT, - .label = { - .text = "Top left" - } - }, - { - .align = ALIGN_TOP, - .label = { - .text = "Top", - } - }, - { - .align = ALIGN_TOP_RIGHT, - .label = { - .text = "Top right", - } - }, - { - .align = ALIGN_RIGHT, - .label = { - .text = "Right", - } - }, - { - .align = ALIGN_BOTTOM_RIGHT, - .label = { - .text = "Bottom right", - } - }, - { - .align = ALIGN_BOTTOM, - .label = { - .text = "Bottom", - } - }, - { - .align = ALIGN_BOTTOM_LEFT, - .label = { - .text = "Bottom left", - } - }, - { - .align = ALIGN_LEFT, - .label = { - .text = "Left", - } - }, - { - .align = ALIGN_CENTER, - .label = { - .text = "The world is Malikania.", - .flags = LABEL_FLAGS_SHADOW - } - } -}; - -static struct label mlabel = { - .text = "This one follows your mouse and is not aligned." -}; - -static void -init(void) -{ - if (core_init("fr.malikania", "label") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Label", W, H) < 0) - panic(); - - for (size_t i = 0; i < UTIL_SIZE(table); ++i) { - struct label *l = &table[i].label; - unsigned int w, h; - - label_query(l, &w, &h); - align(table[i].align, &l->x, &l->y, w, h, 0, 0, W, H); - } -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -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 < UTIL_SIZE(table); ++i) - label_draw(&table[i].label); - - label_draw(&mlabel); - painter_present(); -} - -static void -run(void) -{ - struct state state = { - .handle = handle, - .draw = draw - }; - - game_push(&state); - game_loop(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -}
--- a/src/examples/example-message/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,327 +0,0 @@ -/* - * example-message.c -- show how to use messages - * - * Copyright (c) 2020-2021 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 <stddef.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> - -#include <ui/frame.h> -#include <ui/theme.h> -#include <ui/ui.h> - -#include <rpg/message.h> -#include <rpg/rpg.h> - -#define W (1280) -#define H (720) - -#define MW (W * 0.75) -#define MH (H * 0.120) -#define MX ((W / 2) - (MW / 2)) -#define MY (100) - -static void -init(void) -{ - if (core_init("fr.malikania", "message") < 0 || ui_init() < 0 || rpg_init() < 0) - panic(); - if (window_open("Example - Message", W, H) < 0) - panic(); -} - -static void -quit(void) -{ - window_finish(); - rpg_finish(); - ui_finish(); - core_finish(); -} - -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 state state = { - .data = msg, - .handle = handle, - .update = update, - .draw = draw - }; - - message_start(msg); - - game_push(&state); - game_loop(); -} - -static void -my_draw_frame(const struct theme *th, const struct frame *f) -{ - (void)th; - - painter_set_color(0xff0000ff); - painter_draw_rectangle(f->x, f->y, f->w, f->h); -} - -static void -basic(void) -{ - struct message msg = { - .x = MX, - .y = MY, - .w = MW, - .spacing = 12, - .text = { - "This is a basic message.", - "Vertical spacing is automatically computed.", - "You need to press <Enter> to close it.", - }, - }; - - message_query(&msg, NULL, &msg.h); - run(&msg); -} - -static void -automatic(void) -{ - struct message msg = { - .x = MX, - .y = MY, - .w = MW, - .timeout = MESSAGE_TIMEOUT_DEFAULT, - .text = { - "This is a an automatic message.", - "It will disappear in a few seconds.", - "You can still press <Enter> to close it quicker." - }, - .flags = MESSAGE_FLAGS_AUTOMATIC - }; - - message_query(&msg, NULL, &msg.h); - run(&msg); -} - -static void -fadein(void) -{ - struct message msg = { - .x = MX, - .y = MY, - .w = MW, - .delay = MESSAGE_DELAY_DEFAULT, - .text = { - "This message will fade in." - }, - .flags = MESSAGE_FLAGS_FADEIN - }; - - message_query(&msg, NULL, &msg.h); - run(&msg); -} - -static void -fadeout(void) -{ - struct message msg = { - .x = MX, - .y = MY, - .w = MW, - .delay = MESSAGE_DELAY_DEFAULT, - .text = { - "This message will fade out." - }, - .flags = MESSAGE_FLAGS_FADEOUT - }; - - message_query(&msg, NULL, &msg.h); - run(&msg); -} - -static void -fade(void) -{ - struct message msg = { - .x = MX, - .y = MY, - .w = MW, - .delay = MESSAGE_DELAY_DEFAULT, - .text = { - "This message will fade in and out." - }, - .flags = MESSAGE_FLAGS_FADEIN | MESSAGE_FLAGS_FADEOUT - }; - - message_query(&msg, NULL, &msg.h); - run(&msg); -} - -static void -question(void) -{ - struct message msg = { - .x = MX, - .y = MY, - .w = MW, - .text = { - "Okay, I've understood.", - "Nevermind, I'll do it again." - }, - .flags = MESSAGE_FLAGS_QUESTION - }; - - message_query(&msg, NULL, &msg.h); - run(&msg); -} - -static void -smallbottom(void) -{ - const unsigned int w = window.w / 4; - const unsigned int h = MH; - const int x = (window.w / 2) - (w / 2); - const int y = (window.h - h - 10); - - struct message msg = { - .x = x, - .y = y, - .w = w, - .h = h, - .delay = MESSAGE_DELAY_DEFAULT, - .flags = MESSAGE_FLAGS_FADEIN | MESSAGE_FLAGS_FADEOUT, - .text = { - "This one is small here." - } - }; - - run(&msg); -} - -static void -toosmallh(void) -{ - struct message msg = { - .x = MX, - .y = MY, - .w = MW, - .h = 40, - .text = { - "This one is too small in height and will emit a warning.", - "Because this line will be incomplete." - }, - }; - - run(&msg); -} - -static void -toosmallw(void) -{ - struct message msg = { - .x = MX, - .y = MY, - .w = 160, - .h = MH, - .text = { - "This one is too small in width." - }, - }; - - run(&msg); -} - -static void -custom(void) -{ - struct theme theme; - struct message msg = { - .x = MX, - .y = MY, - .w = MW, - .h = MH, - .text = { - "This one will destroy your eyes.", - "Because it use a terrible custom theme." - }, - .theme = &theme - }; - - /* Borrow default theme and change its frame drawing. */ - theme_shallow(&theme, NULL); - theme.draw_frame = my_draw_frame; - theme.colors[THEME_COLOR_NORMAL] = 0x0000ffff; - - run(&msg); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - basic(); - fadein(); - fadeout(); - fade(); - automatic(); - question(); - smallbottom(); - toosmallh(); - toosmallw(); - custom(); - quit(); -}
--- a/src/examples/example-sprite/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* - * example-sprite.c -- example on how to use sprites - * - * Copyright (c) 2020-2021 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 <stdio.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/sys.h> -#include <core/texture.h> -#include <core/util.h> -#include <core/window.h> - -#include <ui/align.h> -#include <ui/label.h> -#include <ui/ui.h> - -#define W 1280 -#define H 720 -#define PATH(r) util_pathf("%s/mlk-adventure/%s", sys_dir(SYS_DIR_DATA), r) -#define HEADER "Keys: <Left>/<Right> and <Up/Down> to select a column/row. Current: %u, %u (total %u/%u)" - -static char msg[512]; -static struct texture texture; -static struct sprite sprite; -static unsigned int row, column; - -static struct label help = { - .x = 10, - .y = 10, - .text = msg, - .flags = LABEL_FLAGS_SHADOW -}; - -static void -changed(void) -{ - snprintf(msg, sizeof (msg), HEADER, column, row, sprite.ncols, sprite.nrows); -} - -static void -init(void) -{ - if (core_init("fr.malikania", "sprite") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Sprite", W, H) < 0) - panic(); - if (image_open(&texture, PATH("sprites/people.png")) < 0) - panic(); - - sprite_init(&sprite, &texture, 48, 48); -} - -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 (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; - - 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(); -} - -static void -run(void) -{ - struct state state = { - .handle = handle, - .draw = draw - }; - - changed(); - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - texture_finish(&texture); - window_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -}
--- a/src/examples/example-trace/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * example-trace.c -- example on how to use custom trace handlers - * - * Copyright (c) 2020-2021 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 <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> - -#include <ui/theme.h> -#include <ui/ui.h> - -#include <adventure/trace_hud.h> - -#define W 1280 -#define H 720 - -static void -init(void) -{ - if (core_init("fr.malikania", "trace") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - Trace", W, H) < 0) - panic(); - - trace_handler = trace_hud_handler; -} - -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 state state = { - .handle = handle, - .update = update, - .draw = draw - }; - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); -} -
--- a/src/examples/example-ui/main.c Fri Oct 01 15:04:00 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,324 +0,0 @@ -/* - * example-action.c -- example on how to use automatic actions - * - * Copyright (c) 2020-2021 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 <core/action.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> - -#include <ui/align.h> -#include <ui/button.h> -#include <ui/checkbox.h> -#include <ui/frame.h> -#include <ui/label.h> -#include <ui/theme.h> -#include <ui/ui.h> - -#define W (1280) -#define H (720) - -#define FRAME_ORIGIN_X (10) -#define FRAME_ORIGIN_Y (10) -#define FRAME_WIDTH (400) -#define FRAME_HEIGHT (200) - -#define HEADER_HEIGHT (32) - -#define ELEMENT_HEIGHT (20) - -/* - * We design a basic UI like this. - * - * FRAME_WIDTH - * +---------------------------------------------+-- - * | Title | | HEADER_HEIGHT - * +---------------------------------------------+-- - * | [x] Auto save | - * | | - * | | - * | [ Quit ] | - * +---------------------------------------------+ - */ -static struct { - struct action_stack st; - - struct { - int active; - int x; - int y; - } motion; - - struct { - struct frame frame; - struct action act; - } panel; - - struct { - struct label label; - struct action act; - } header; - - struct { - struct checkbox cb; - struct action cb_act; - struct label label; - struct action label_act; - } autosave; - - struct { - struct button button; - struct action act; - } quit; -} ui = { - .panel = { - .frame = { - .x = FRAME_ORIGIN_X, - .y = FRAME_ORIGIN_Y, - .w = FRAME_WIDTH, - .h = FRAME_HEIGHT - } - }, - .header = { - .label = { - .text = "Preferences", - .x = FRAME_ORIGIN_X, - .y = FRAME_ORIGIN_Y, - .flags = LABEL_FLAGS_SHADOW, - } - }, - .autosave = { - .cb = { - .w = ELEMENT_HEIGHT, - .h = ELEMENT_HEIGHT - }, - .label = { - .text = "Auto save game", - .flags = LABEL_FLAGS_SHADOW, - } - }, - .quit = { - .button = { - .text = "Quit", - .h = ELEMENT_HEIGHT - } - } -}; - -static void -init(void) -{ - if (core_init("fr.malikania", "ui") < 0 || ui_init() < 0) - panic(); - if (window_open("Example - UI", W, H) < 0) - panic(); -} - -static void -resize_header(void) -{ - struct frame *f = &ui.panel.frame; - struct label *l = &ui.header.label; - unsigned int w, h; - - /* Header. */ - label_query(l, &w, &h); - align(ALIGN_LEFT, &l->x, &l->y, w, h, f->x, f->y, f->w, HEADER_HEIGHT); - - l->x += theme_default()->padding; -} - -static void -resize_autosave(void) -{ - unsigned int padding = theme_default()->padding; - struct frame *f = &ui.panel.frame; - struct checkbox *c = &ui.autosave.cb; - struct label *l = &ui.autosave.label; - - c->x = f->x + padding; - c->y = f->y + HEADER_HEIGHT + padding; - - l->x = c->x + c->w + padding; - l->y = c->y; -} - -static void -resize_button(void) -{ - unsigned int padding = theme_default()->padding; - struct frame *f = &ui.panel.frame; - struct button *b = &ui.quit.button; - - /* Button. */ - b->w = f->w / 4; - - align(ALIGN_BOTTOM_RIGHT, &b->x, &b->y, b->w, b->h, - f->x, f->y, f->w, f->h); - - b->x -= padding; - b->y -= padding; -} - -static void -resize(void) -{ - resize_header(); - resize_autosave(); - resize_button(); -} - -static void -prepare(void) -{ - /* Frame. */ - frame_action(&ui.panel.frame, &ui.panel.act); - - /* Header title. */ - label_action(&ui.header.label, &ui.header.act); - - /* Button quit. */ - button_action(&ui.quit.button, &ui.quit.act); - - /* Autosave. */ - checkbox_action(&ui.autosave.cb, &ui.autosave.cb_act); - label_action(&ui.autosave.label, &ui.autosave.label_act); - - /* Add all UI elements. */ - action_stack_add(&ui.st, &ui.panel.act); - action_stack_add(&ui.st, &ui.header.act); - action_stack_add(&ui.st, &ui.autosave.cb_act); - action_stack_add(&ui.st, &ui.autosave.label_act); - action_stack_add(&ui.st, &ui.quit.act); -} - -static int -headerclick(int x, int y) -{ - return maths_is_boxed( - ui.panel.frame.x, - ui.panel.frame.y, - ui.panel.frame.w, - HEADER_HEIGHT, - x, - y - ); -} - -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 = 1; - 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 = 0; - 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 state state = { - .handle = handle, - .update = update, - .draw = draw - }; - - prepare(); - resize(); - - game_push(&state); - game_loop(); -} - -static void -quit(void) -{ - window_finish(); - ui_finish(); - core_finish(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - quit(); - - return 0; -}