Mercurial > molko
changeset 209:23a844fdc911
examples: move all into subdirectories, closes #2513
line wrap: on
line diff
--- a/cmake/MolkoDefineLibrary.cmake Wed Nov 11 16:31:55 2020 +0100 +++ b/cmake/MolkoDefineLibrary.cmake Wed Nov 11 17:10:40 2020 +0100 @@ -75,7 +75,7 @@ if (${LIB_TYPE} MATCHES "INTERFACE") add_library(${LIB_TARGET} INTERFACE) - target_sources(${LIB_TARGET} INTERFACE ${LIB_SOURCES}) + target_sources(${LIB_TARGET} INTERFACE ${LIB_SOURCES} ${OUTPUTS}) target_include_directories( ${LIB_TARGET} INTERFACE
--- a/examples/CMakeLists.txt Wed Nov 11 16:31:55 2020 +0100 +++ b/examples/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -18,123 +18,42 @@ project(examples) -molko_define_executable( - TARGET example-battle - SOURCES - ${examples_SOURCE_DIR}/example-battle.c - ${examples_SOURCE_DIR}/battle/spell-fire.c - ${examples_SOURCE_DIR}/battle/spell-fire.h - ${examples_SOURCE_DIR}/battle/registry.c - ${examples_SOURCE_DIR}/battle/registry.h - FOLDER examples - ASSETS - ${examples_SOURCE_DIR}/assets/images/haunted-wood.png - ${examples_SOURCE_DIR}/assets/images/black-cat.png - ${examples_SOURCE_DIR}/assets/sprites/cursor.png - ${examples_SOURCE_DIR}/assets/sprites/explosion.png - ${examples_SOURCE_DIR}/assets/sounds/fire.wav - LIBRARIES librpg libadventure -) - -molko_define_executable( - TARGET example-action - SOURCES example-action.c - FOLDER examples +set( ASSETS - ${examples_SOURCE_DIR}/assets/sprites/chest.png - ${examples_SOURCE_DIR}/assets/sprites/people.png - LIBRARIES librpg -) - -molko_define_executable( - TARGET example-animation - SOURCES example-animation.c - FOLDER examples - ASSETS - ${examples_SOURCE_DIR}/assets/sprites/numbers.png - LIBRARIES libui -) - -molko_define_executable( - TARGET example-audio - SOURCES example-audio.c - FOLDER examples - ASSETS - ${examples_SOURCE_DIR}/assets/musics/vabsounds-romance.ogg - ${examples_SOURCE_DIR}/assets/sounds/fire.wav - LIBRARIES libui -) - -molko_define_executable( - TARGET example-cursor - SOURCES example-cursor.c - FOLDER examples - LIBRARIES libui + ${examples_SOURCE_DIR}/assets/images/black-cat.png + ${examples_SOURCE_DIR}/assets/images/haunted-wood.png + ${examples_SOURCE_DIR}/assets/music/vabsounds-romance.ogg + ${examples_SOURCE_DIR}/assets/sounds/fire.wav + ${examples_SOURCE_DIR}/assets/sprites/chest.png + ${examples_SOURCE_DIR}/assets/sprites/cursor.png + ${examples_SOURCE_DIR}/assets/sprites/explosion.png + ${examples_SOURCE_DIR}/assets/sprites/numbers.png + ${examples_SOURCE_DIR}/assets/sprites/people.png ) -molko_define_executable( - TARGET example-debug - SOURCES example-debug.c - FOLDER examples - LIBRARIES libui -) +# Can't use an interface library as examples live in subdirectories. +file(WRITE ${examples_BINARY_DIR}/none.c "void molko() {}") -molko_define_executable( - TARGET example-font - SOURCES example-font.c - LIBRARIES libui +molko_define_library( + TARGET libexamples FOLDER examples -) - -molko_define_executable( - TARGET example-label - SOURCES example-label.c - LIBRARIES libui - FOLDER examples -) - -molko_define_executable( - TARGET example-message - SOURCES example-message.c - FOLDER examples - LIBRARIES librpg + SOURCES ${examples_BINARY_DIR}/none.c ${ASSETS} + ASSETS ${ASSETS} ) -molko_define_executable( - TARGET example-sprite - SOURCES example-sprite.c - FOLDER examples - ASSETS - ${examples_SOURCE_DIR}/assets/sprites/people.png - LIBRARIES libui -) - -molko_define_executable( - TARGET example-drawable - SOURCES example-drawable.c - FOLDER examples - LIBRARIES libui - ASSETS - ${examples_SOURCE_DIR}/assets/sprites/explosion.png -) +add_subdirectory(example-action) +add_subdirectory(example-animation) +add_subdirectory(example-audio) +add_subdirectory(example-battle) +add_subdirectory(example-cursor) +add_subdirectory(example-debug) +add_subdirectory(example-drawable) +add_subdirectory(example-font) +add_subdirectory(example-gridmenu) +add_subdirectory(example-label) +add_subdirectory(example-message) +add_subdirectory(example-sprite) +add_subdirectory(example-trace) +add_subdirectory(example-ui) -molko_define_executable( - TARGET example-gridmenu - SOURCES example-gridmenu.c - FOLDER examples - LIBRARIES libui -) - -molko_define_executable( - TARGET example-trace - SOURCES example-trace.c - FOLDER examples - LIBRARIES libui libadventure -) - -molko_define_executable( - TARGET example-ui - SOURCES example-ui.c - FOLDER examples - LIBRARIES libui -) +source_group("assets" FILES ${ASSETS})
--- a/examples/battle/character-john.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * character-john.c -- john character - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <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/examples/battle/character-john.h Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -/* - * character-john.h -- john character - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef EXAMPLES_BATTLE_CHARACTER_JOHN_H -#define EXAMPLES_BATTLE_CHARACTER_JOHN_H - -const struct character character_john; - -#endif /* !EXAMPLES_BATTLE_CHARACTER_JOHN_H */
--- a/examples/battle/registry.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* - * registry.h -- registry of resources - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <stddef.h> - -#include <core/image.h> -#include <core/panic.h> -#include <core/util.h> - -#include <adventure/assets/sprites/john.h> - -#include <assets/images/haunted-wood.h> -#include <assets/images/black-cat.h> - -#include <assets/sprites/cursor.h> -#include <assets/sprites/explosion.h> - -#include <assets/sounds/fire.h> - -#include "registry.h" - -struct texture registry_textures[REGISTRY_TEXTURE_NUM]; -struct sprite registry_sprites[REGISTRY_TEXTURE_NUM]; -struct sound registry_sounds[REGISTRY_SOUND_NUM]; - -#define REGISTRY_TEXTURE(s, ptr, cw, ch) \ - { (s), (ptr), sizeof ((ptr)), (cw), (ch) } - -static const struct { - enum registry_texture index; - const void *data; - size_t datasz; - unsigned int cellw; - unsigned int cellh; -} textures[] = { - REGISTRY_TEXTURE(REGISTRY_TEXTURE_CURSOR, sprites_cursor, 24, 24), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_EXPLOSION, sprites_explosion, 256, 256), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_JOHN, sprites_john, 48, 48), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_HAUNTED_WOOD, images_haunted_wood, 0, 0), - REGISTRY_TEXTURE(REGISTRY_TEXTURE_BLACK_CAT, images_black_cat, 0, 0) -}; - -#define REGISTRY_SOUND(s, ptr) \ - { (s), (ptr), sizeof ((ptr)) } - -static const struct { - enum registry_sound index; - const void *data; - size_t datasz; -} sounds[] = { - REGISTRY_SOUND(REGISTRY_SOUND_FIRE, sounds_fire) -}; - -static void -load_textures_and_sprites(void) -{ - for (size_t i = 0; i < NELEM(textures); ++i) { - struct texture *texture = ®istry_textures[textures[i].index]; - struct sprite *sprite = ®istry_sprites[textures[i].index]; - - if (!image_openmem(texture, textures[i].data, textures[i].datasz)) - 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 < NELEM(sounds); ++i) { - struct sound *sound = ®istry_sounds[sounds[i].index]; - - if (!sound_openmem(sound, sounds[i].data, sounds[i].datasz)) - panic(); - } -} - -void -registry_init(void) -{ - load_textures_and_sprites(); - load_sounds(); -} - -void -registry_finish(void) -{ - for (size_t i = 0; i < NELEM(registry_textures); ++i) - texture_finish(®istry_textures[i]); - for (size_t i = 0; i < NELEM(registry_sounds); ++i) - sound_finish(®istry_sounds[i]); -}
--- a/examples/battle/registry.h Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * registry.h -- registry of resources - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef 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, - - /* Enemies. */ - REGISTRY_TEXTURE_HAUNTED_WOOD, - REGISTRY_TEXTURE_BLACK_CAT, - - /* Unused.*/ - REGISTRY_TEXTURE_NUM -}; - -enum registry_sound { - REGISTRY_SOUND_FIRE, - REGISTRY_SOUND_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/examples/battle/spell-fire.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * spell-fire.c -- example of spell: fire - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <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 animation animation; - struct action action; - unsigned int selection; -}; - -static bool -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]; - int x, y; - - align(ALIGN_CENTER, - &x, &y, data->animation.sprite->cellw, data->animation.sprite->cellh, - et->x, et->y, et->ch->sprite->cellw, et->ch->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_action(struct battle *bt, struct character *owner, unsigned int selection) -{ - struct data *data; - - (void)owner; - - data = alloc_zero(1, sizeof (*data)); - data->battle = bt; - data->selection = selection; - 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, - .selection = SELECTION_ENEMY_ONE, - .action = fire_action -};
--- a/examples/battle/spell-fire.h Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -/* - * spell-fire.c -- example of spell: fire - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef EXAMPLES_BATTLE_SPELL_FIRE_H -#define EXAMPLES_BATTLE_SPELL_FIRE_H - -extern const struct spell spell_fire; - -#endif /* !EXAMPLES_BATTLE_SPELL_FIRE_H */
--- a/examples/example-action.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,400 +0,0 @@ -/* - * example-action.c -- example on how to use automatic actions - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <assert.h> - -#include <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> - -#include <assets/sprites/chest.h> -#include <assets/sprites/people.h> - -#define W (1280) -#define H (720) - -#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; - bool 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 bool -guide_response_update(struct action *act, unsigned int ticks) -{ - /* Immediately return to get access to end. */ - (void)act; - (void)ticks; - - return true; -} - -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_openmem(&guide.image, sprites_people, sizeof (sprites_people))) - 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 = true; - 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 ? 3 : 0; - - sprite_draw(&chest.sprite, row, 0, chest.x, chest.y); -} - -static void -chest_init(void) -{ - if (!image_openmem(&chest.image, sprites_chest, sizeof (sprites_chest))) - 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() || !ui_init() || !rpg_init()) - panic(); - if (!window_open("Example - Action", W, H)) - 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_switch(&state, true); - 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-action/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-action) + +molko_define_executable( + TARGET example-action + SOURCES ${example-action_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES librpg libexamples +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-action/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,400 @@ +/* + * example-action.c -- example on how to use automatic actions + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> + +#include <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> + +#include <assets/sprites/chest.h> +#include <assets/sprites/people.h> + +#define W (1280) +#define H (720) + +#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; + bool 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 bool +guide_response_update(struct action *act, unsigned int ticks) +{ + /* Immediately return to get access to end. */ + (void)act; + (void)ticks; + + return true; +} + +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_openmem(&guide.image, sprites_people, sizeof (sprites_people))) + 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 = true; + 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 ? 3 : 0; + + sprite_draw(&chest.sprite, row, 0, chest.x, chest.y); +} + +static void +chest_init(void) +{ + if (!image_openmem(&chest.image, sprites_chest, sizeof (sprites_chest))) + 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() || !ui_init() || !rpg_init()) + panic(); + if (!window_open("Example - Action", W, H)) + 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_switch(&state, true); + 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/examples/example-animation.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * example-animation.c -- example on how to use animations - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <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> - -#include <assets/sprites/numbers.h> - -#define W 1280 -#define H 720 - -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 bool completed = true; - -static void -init(void) -{ - if (!core_init() || !ui_init()) - panic(); - if (!window_open("Example - Animation", W, H)) - panic(); - if (!image_openmem(&numbers, sprites_numbers, sizeof (sprites_numbers))) - 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_switch(&state, true); - 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-animation/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-animation) + +molko_define_executable( + TARGET example-animation + SOURCES ${example-animation_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui libexamples +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-animation/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,146 @@ +/* + * example-animation.c -- example on how to use animations + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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> + +#include <assets/sprites/numbers.h> + +#define W 1280 +#define H 720 + +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 bool completed = true; + +static void +init(void) +{ + if (!core_init() || !ui_init()) + panic(); + if (!window_open("Example - Animation", W, H)) + panic(); + if (!image_openmem(&numbers, sprites_numbers, sizeof (sprites_numbers))) + 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_switch(&state, true); + 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/examples/example-audio.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * example-audio.c -- show how to use sounds and music - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <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> - -/* https://freesound.org/people/VABsounds/sounds/423658 */ -#include <assets/musics/vabsounds-romance.h> -#include <assets/sounds/fire.h> - -#define W 1280 -#define H 720 - -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() || !ui_init()) - panic(); - if (!window_open("Example - Audio", W, H)) - panic(); - if (!music_openmem(&music, musics_vabsounds_romance, sizeof (musics_vabsounds_romance)) || - !sound_openmem(&sound, sounds_fire, sizeof (sounds_fire))) - 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)) - 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_switch(&state, true); - 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-audio/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-audio) + +molko_define_executable( + TARGET example-audio + SOURCES ${example-audio_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui libexamples +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-audio/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,160 @@ +/* + * example-audio.c -- show how to use sounds and music + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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> + +/* https://freesound.org/people/VABsounds/sounds/423658 */ +#include <assets/music/vabsounds-romance.h> +#include <assets/sounds/fire.h> + +#define W 1280 +#define H 720 + +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() || !ui_init()) + panic(); + if (!window_open("Example - Audio", W, H)) + panic(); + if (!music_openmem(&music, music_vabsounds_romance, sizeof (music_vabsounds_romance)) || + !sound_openmem(&sound, sounds_fire, sizeof (sounds_fire))) + 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)) + 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_switch(&state, true); + game_loop(); + + music_finish(&music); + sound_finish(&sound); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +}
--- a/examples/example-battle.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,299 +0,0 @@ -/* - * example-battle.c -- show how to use battle - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <assert.h> -#include <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 "battle/registry.h" -#include "battle/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 = 21; - ch->luck = 14; -} - -static struct character team[] = { - { - .name = "Molko", - .type = "Adventurer", - .level = 1, - .hp = 120, - .mp = 50, - .reset = adventurer_reset, - .sprite = ®istry_sprites[REGISTRY_TEXTURE_JOHN], - .spells = { - &spell_fire - } - }, - { - .name = "Fake Molko", - .type = "Adventurer", - .level = 1, - .hp = 120, - .mp = 50, - .reset = adventurer_reset, - .sprite = ®istry_sprites[REGISTRY_TEXTURE_JOHN], - .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", - .type = "Wood", - .level = 30, - .reset = haunted_wood_reset, - .sprite = ®istry_sprites[REGISTRY_TEXTURE_HAUNTED_WOOD], - .exec = haunted_wood_strat -}; - -static struct character black_cat = { - .name = "Black Cat", - .type = "Cat", - .level = 6, - .reset = black_cat_reset, - .sprite = ®istry_sprites[REGISTRY_TEXTURE_BLACK_CAT], - .exec = black_cat_strat -}; - -static void -init(void) -{ - if (!core_init() || !ui_init() || !rpg_init()) - panic(); - if (!window_open("Example - Battle", W, H)) - 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_zero(1, 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.sprite->cellw, haunted_wood.sprite->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; - - battle_start(bt); - - fight_state.data = bt; - game_switch(&fight_state, false); -} - - -static void -empty_handle(struct state *st, const union event *ev) -{ - (void)st; - - switch (ev->type) { - case EVENT_QUIT: - game_quit(); - break; - case EVENT_KEYDOWN: - if (ev->key.key == KEY_SPACE) - prepare_to_fight(); - break; - default: - break; - } -} - -static void -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_switch(&empty_state, false); -} - -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_switch(&empty_state, true); - 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/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,31 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-battle) + +molko_define_executable( + TARGET example-battle + SOURCES + ${example-battle_SOURCE_DIR}/main.c + ${example-battle_SOURCE_DIR}/spell-fire.c + ${example-battle_SOURCE_DIR}/spell-fire.h + ${example-battle_SOURCE_DIR}/registry.c + ${example-battle_SOURCE_DIR}/registry.h + FOLDER examples + LIBRARIES librpg libadventure libexamples +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/character-john.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,48 @@ +/* + * character-john.c -- john character + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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 Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,24 @@ +/* + * character-john.h -- john character + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef 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 Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,299 @@ +/* + * example-battle.c -- show how to use battle + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> +#include <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 = 21; + ch->luck = 14; +} + +static struct character team[] = { + { + .name = "Molko", + .type = "Adventurer", + .level = 1, + .hp = 120, + .mp = 50, + .reset = adventurer_reset, + .sprite = ®istry_sprites[REGISTRY_TEXTURE_JOHN], + .spells = { + &spell_fire + } + }, + { + .name = "Fake Molko", + .type = "Adventurer", + .level = 1, + .hp = 120, + .mp = 50, + .reset = adventurer_reset, + .sprite = ®istry_sprites[REGISTRY_TEXTURE_JOHN], + .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", + .type = "Wood", + .level = 30, + .reset = haunted_wood_reset, + .sprite = ®istry_sprites[REGISTRY_TEXTURE_HAUNTED_WOOD], + .exec = haunted_wood_strat +}; + +static struct character black_cat = { + .name = "Black Cat", + .type = "Cat", + .level = 6, + .reset = black_cat_reset, + .sprite = ®istry_sprites[REGISTRY_TEXTURE_BLACK_CAT], + .exec = black_cat_strat +}; + +static void +init(void) +{ + if (!core_init() || !ui_init() || !rpg_init()) + panic(); + if (!window_open("Example - Battle", W, H)) + 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_zero(1, 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.sprite->cellw, haunted_wood.sprite->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; + + battle_start(bt); + + fight_state.data = bt; + game_switch(&fight_state, false); +} + + +static void +empty_handle(struct state *st, const union event *ev) +{ + (void)st; + + switch (ev->type) { + case EVENT_QUIT: + game_quit(); + break; + case EVENT_KEYDOWN: + if (ev->key.key == KEY_SPACE) + prepare_to_fight(); + break; + default: + break; + } +} + +static void +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_switch(&empty_state, false); +} + +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_switch(&empty_state, true); + 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 Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,111 @@ +/* + * registry.h -- registry of resources + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stddef.h> + +#include <core/image.h> +#include <core/panic.h> +#include <core/util.h> + +#include <adventure/assets/sprites/john.h> + +#include <assets/images/haunted-wood.h> +#include <assets/images/black-cat.h> + +#include <assets/sprites/cursor.h> +#include <assets/sprites/explosion.h> + +#include <assets/sounds/fire.h> + +#include "registry.h" + +struct texture registry_textures[REGISTRY_TEXTURE_NUM]; +struct sprite registry_sprites[REGISTRY_TEXTURE_NUM]; +struct sound registry_sounds[REGISTRY_SOUND_NUM]; + +#define REGISTRY_TEXTURE(s, ptr, cw, ch) \ + { (s), (ptr), sizeof ((ptr)), (cw), (ch) } + +static const struct { + enum registry_texture index; + const void *data; + size_t datasz; + unsigned int cellw; + unsigned int cellh; +} textures[] = { + REGISTRY_TEXTURE(REGISTRY_TEXTURE_CURSOR, sprites_cursor, 24, 24), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_EXPLOSION, sprites_explosion, 256, 256), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_JOHN, sprites_john, 48, 48), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_HAUNTED_WOOD, images_haunted_wood, 0, 0), + REGISTRY_TEXTURE(REGISTRY_TEXTURE_BLACK_CAT, images_black_cat, 0, 0) +}; + +#define REGISTRY_SOUND(s, ptr) \ + { (s), (ptr), sizeof ((ptr)) } + +static const struct { + enum registry_sound index; + const void *data; + size_t datasz; +} sounds[] = { + REGISTRY_SOUND(REGISTRY_SOUND_FIRE, sounds_fire) +}; + +static void +load_textures_and_sprites(void) +{ + for (size_t i = 0; i < NELEM(textures); ++i) { + struct texture *texture = ®istry_textures[textures[i].index]; + struct sprite *sprite = ®istry_sprites[textures[i].index]; + + if (!image_openmem(texture, textures[i].data, textures[i].datasz)) + 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 < NELEM(sounds); ++i) { + struct sound *sound = ®istry_sounds[sounds[i].index]; + + if (!sound_openmem(sound, sounds[i].data, sounds[i].datasz)) + panic(); + } +} + +void +registry_init(void) +{ + load_textures_and_sprites(); + load_sounds(); +} + +void +registry_finish(void) +{ + for (size_t i = 0; i < NELEM(registry_textures); ++i) + texture_finish(®istry_textures[i]); + for (size_t i = 0; i < NELEM(registry_sounds); ++i) + sound_finish(®istry_sounds[i]); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/registry.h Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,59 @@ +/* + * registry.h -- registry of resources + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef 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, + + /* Enemies. */ + REGISTRY_TEXTURE_HAUNTED_WOOD, + REGISTRY_TEXTURE_BLACK_CAT, + + /* Unused.*/ + REGISTRY_TEXTURE_NUM +}; + +enum registry_sound { + REGISTRY_SOUND_FIRE, + REGISTRY_SOUND_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 Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,116 @@ +/* + * spell-fire.c -- example of spell: fire + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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 animation animation; + struct action action; + unsigned int selection; +}; + +static bool +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]; + int x, y; + + align(ALIGN_CENTER, + &x, &y, data->animation.sprite->cellw, data->animation.sprite->cellh, + et->x, et->y, et->ch->sprite->cellw, et->ch->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_action(struct battle *bt, struct character *owner, unsigned int selection) +{ + struct data *data; + + (void)owner; + + data = alloc_zero(1, sizeof (*data)); + data->battle = bt; + data->selection = selection; + 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, + .selection = SELECTION_ENEMY_ONE, + .action = fire_action +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-battle/spell-fire.h Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,24 @@ +/* + * spell-fire.c -- example of spell: fire + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef EXAMPLES_BATTLE_SPELL_FIRE_H +#define EXAMPLES_BATTLE_SPELL_FIRE_H + +extern const struct spell spell_fire; + +#endif /* !EXAMPLES_BATTLE_SPELL_FIRE_H */
--- a/examples/example-cursor.c Wed Nov 11 16:31:55 2020 +0100 +++ /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 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() || !ui_init()) - panic(); - if (!window_open("Example - Cursor", W, H)) - 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_switch(&state, true); - 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-cursor/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-cursor) + +molko_define_executable( + TARGET example-cursor + SOURCES ${example-cursor_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-cursor/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,146 @@ +/* + * example-cursor.c -- example on how to change cursor + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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() || !ui_init()) + panic(); + if (!window_open("Example - Cursor", W, H)) + 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_switch(&state, true); + 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/examples/example-debug.c Wed Nov 11 16:31:55 2020 +0100 +++ /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 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() || !ui_init()) - panic(); - if (!window_open("Example - Debug", W, H)) - panic(); - - debug_options.enable = true; -} - -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_switch(&state, true); - 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/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-debug) + +molko_define_executable( + TARGET example-debug + SOURCES ${example-debug_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-debug/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,111 @@ +/* + * example-debug.c -- example on how to use debug interface + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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() || !ui_init()) + panic(); + if (!window_open("Example - Debug", W, H)) + panic(); + + debug_options.enable = true; +} + +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_switch(&state, true); + 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/examples/example-drawable.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -/* - * example-drawable.c -- example on how to use automatic drawables - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <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> - -#include <assets/sprites/explosion.h> - -#define W 1280 -#define H 720 - -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() || !ui_init()) - panic(); - if (!window_open("Example - Drawable", W, H)) - panic(); - - /* 0: Explosion animation. */ - if (!image_openmem(&explosion_tex, sprites_explosion, sizeof (sprites_explosion))) - panic(); - - sprite_init(&explosion_sprite, &explosion_tex, 256, 256); -} - -static bool -explosion_update(struct drawable *dw, unsigned int ticks) -{ - struct explosion *ex = dw->data; - - return animation_update(&ex->anim, ticks); -} - -static void -explosion_draw(struct drawable *dw) -{ - struct explosion *ex = dw->data; - - animation_draw(&ex->anim, ex->dw.x, ex->dw.y); -} - -static void -explosion_finish(struct drawable *dw) -{ - free(dw->data); -} - -static void -spawn(int x, int y) -{ - struct explosion *ex = alloc_zero(1, 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_switch(&state, true); - 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/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-drawable) + +molko_define_executable( + TARGET example-drawable + SOURCES ${example-drawable_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui libexamples +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-drawable/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,202 @@ +/* + * example-drawable.c -- example on how to use automatic drawables + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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> + +#include <assets/sprites/explosion.h> + +#define W 1280 +#define H 720 + +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() || !ui_init()) + panic(); + if (!window_open("Example - Drawable", W, H)) + panic(); + + /* 0: Explosion animation. */ + if (!image_openmem(&explosion_tex, sprites_explosion, sizeof (sprites_explosion))) + panic(); + + sprite_init(&explosion_sprite, &explosion_tex, 256, 256); +} + +static bool +explosion_update(struct drawable *dw, unsigned int ticks) +{ + struct explosion *ex = dw->data; + + return animation_update(&ex->anim, ticks); +} + +static void +explosion_draw(struct drawable *dw) +{ + struct explosion *ex = dw->data; + + animation_draw(&ex->anim, ex->dw.x, ex->dw.y); +} + +static void +explosion_finish(struct drawable *dw) +{ + free(dw->data); +} + +static void +spawn(int x, int y) +{ + struct explosion *ex = alloc_zero(1, 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_switch(&state, true); + 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/examples/example-font.c Wed Nov 11 16:31:55 2020 +0100 +++ /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 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() || !ui_init()) - panic(); - if (!window_open("Example - Font", W, H)) - 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 < NELEM(colors)) - ci++; - break; - case KEY_SPACE: - if (style == FONT_STYLE_ANTIALIASED) - style = FONT_STYLE_NONE; - else - style = FONT_STYLE_ANTIALIASED; - - theme_default()->fonts[THEME_FONT_INTERFACE]->style = style; - default: - break; - } - break; - case EVENT_QUIT: - game_quit(); - break; - default: - break; - } -} - -static void -draw(struct state *st) -{ - (void)st; - - struct font *font = theme_default()->fonts[THEME_FONT_INTERFACE]; - struct texture tex; - - painter_set_color(0xffffffff); - painter_clear(); - - if (!font_render(font, &tex, "Example of text. Use <Left>/<Right> to change color and <Space> to toggle antialiasing.", colors[ci])) - panic(); - - texture_draw(&tex, 10, 10); - painter_present(); - texture_finish(&tex); -} - -static void -run(void) -{ - struct state state = { - .handle = handle, - .draw = draw - }; - - game_switch(&state, true); - 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-font/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-font) + +molko_define_executable( + TARGET example-font + SOURCES ${example-font_SOURCE_DIR}/main.c + LIBRARIES libui + FOLDER examples +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-font/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,146 @@ +/* + * example-font.c -- show how to use fonts + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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() || !ui_init()) + panic(); + if (!window_open("Example - Font", W, H)) + 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 < NELEM(colors)) + ci++; + break; + case KEY_SPACE: + if (style == FONT_STYLE_ANTIALIASED) + style = FONT_STYLE_NONE; + else + style = FONT_STYLE_ANTIALIASED; + + theme_default()->fonts[THEME_FONT_INTERFACE]->style = style; + default: + break; + } + break; + case EVENT_QUIT: + game_quit(); + break; + default: + break; + } +} + +static void +draw(struct state *st) +{ + (void)st; + + struct font *font = theme_default()->fonts[THEME_FONT_INTERFACE]; + struct texture tex; + + painter_set_color(0xffffffff); + painter_clear(); + + if (!font_render(font, &tex, "Example of text. Use <Left>/<Right> to change color and <Space> to toggle antialiasing.", colors[ci])) + panic(); + + texture_draw(&tex, 10, 10); + painter_present(); + texture_finish(&tex); +} + +static void +run(void) +{ + struct state state = { + .handle = handle, + .draw = draw + }; + + game_switch(&state, true); + 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/examples/example-gridmenu.c Wed Nov 11 16:31:55 2020 +0100 +++ /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 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() || !ui_init()) - panic(); - if (!window_open("Example - Grid menu", W, H)) - 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_switch(&state, true); - 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-gridmenu/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-gridmenu) + +molko_define_executable( + TARGET example-gridmenu + SOURCES ${example-gridmenu_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-gridmenu/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,139 @@ +/* + * example-gridmenu.c -- show how to use grid menu + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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() || !ui_init()) + panic(); + if (!window_open("Example - Grid menu", W, H)) + 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_switch(&state, true); + game_loop(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +}
--- a/examples/example-inventory.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -/* - * example-inventory.c -- show how to use inventory dialog - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <core/clock.h> -#include <core/core.h> -#include <core/event.h> -#include <core/image.h> -#include <core/painter.h> -#include <core/panic.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/item.h> -#include <rpg/inventory.h> -#include <rpg/inventory_dialog.h> -#include <rpg/rpg.h> - -/* https://shikashiassets.itch.io/shikashis-fantasy-icons-pack */ -#include <assets/images/fish.h> -#include <assets/images/potion.h> -#include <assets/images/sword.h> - -#define W 1280 -#define H 720 - -static struct { - const unsigned char *data; - const size_t datasz; - struct texture icon; - struct item item; -} items[] = { - { - .data = images_potion, - .datasz = sizeof (images_potion), - .item = { - .name = "Potion", - .summary = "Recover 100 HP.", - .stackable = ITEM_STACK_MAX - } - }, - { - .data = images_fish, - .datasz = sizeof (images_fish), - .item = { - .name = "Fish", - .summary = "Recover 1000 HP.", - .stackable = ITEM_STACK_MAX - } - }, - { - .data = images_sword, - .datasz = sizeof (images_sword), - .item = { - .name = "Sword", - .summary = "A very basic sword.", - .stackable = 1 - } - }, -}; - -static void -init(void) -{ - if (!core_init() || !ui_init() || !rpg_init()) - panic(); - if (!window_open("Example - Inventory", W, H)) - panic(); - - for (size_t i = 0; i < NELEM(items); ++i) { - if (!image_openmem(&items[i].icon, items[i].data, items[i].datasz)) - panic(); - - items[i].item.icon = &items[i].icon; - } -} - -static void -quit(void) -{ - window_finish(); - rpg_finish(); - ui_finish(); - core_finish(); -} - -static void -run(struct inventory_dialog *dlg) -{ - struct clock clock = {0}; - - clock_start(&clock); - inventory_dialog_open(dlg); - - while (dlg->state) { - union event ev; - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - while (event_poll(&ev)) { - switch (ev.type) { - case EVENT_QUIT: - inventory_dialog_finish(dlg); - break; - default: - inventory_dialog_handle(dlg, &ev); - break; - } - } - - inventory_dialog_update(dlg, elapsed); - painter_set_color(0xffffffff); - painter_clear(); - inventory_dialog_draw(dlg); - painter_present(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } -} - -static void -basic(void) -{ - struct inventory inv = { 0 }; - struct inventory_dialog dlg = { - .inv = &inv, - .x = 60, - .y = 60 - }; - - /* Add items manually to be able to sort. */ - inv.items[1][5].item = &items[0].item; - inv.items[1][5].amount = 12; - - inv.items[1][2].item = &items[0].item; - inv.items[1][2].amount = 9; - - inv.items[2][7].item = &items[1].item; - inv.items[2][7].amount = 9; - - inv.items[2][8].item = &items[1].item; - inv.items[2][8].amount = 3; - - inv.items[2][4].item = &items[2].item; - inv.items[2][4].amount = 1; - - run(&dlg); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - basic(); - quit(); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-inventory/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,180 @@ +/* + * example-inventory.c -- show how to use inventory dialog + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <core/clock.h> +#include <core/core.h> +#include <core/event.h> +#include <core/image.h> +#include <core/painter.h> +#include <core/panic.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/item.h> +#include <rpg/inventory.h> +#include <rpg/inventory_dialog.h> +#include <rpg/rpg.h> + +/* https://shikashiassets.itch.io/shikashis-fantasy-icons-pack */ +#include <assets/images/fish.h> +#include <assets/images/potion.h> +#include <assets/images/sword.h> + +#define W 1280 +#define H 720 + +static struct { + const unsigned char *data; + const size_t datasz; + struct texture icon; + struct item item; +} items[] = { + { + .data = images_potion, + .datasz = sizeof (images_potion), + .item = { + .name = "Potion", + .summary = "Recover 100 HP.", + .stackable = ITEM_STACK_MAX + } + }, + { + .data = images_fish, + .datasz = sizeof (images_fish), + .item = { + .name = "Fish", + .summary = "Recover 1000 HP.", + .stackable = ITEM_STACK_MAX + } + }, + { + .data = images_sword, + .datasz = sizeof (images_sword), + .item = { + .name = "Sword", + .summary = "A very basic sword.", + .stackable = 1 + } + }, +}; + +static void +init(void) +{ + if (!core_init() || !ui_init() || !rpg_init()) + panic(); + if (!window_open("Example - Inventory", W, H)) + panic(); + + for (size_t i = 0; i < NELEM(items); ++i) { + if (!image_openmem(&items[i].icon, items[i].data, items[i].datasz)) + panic(); + + items[i].item.icon = &items[i].icon; + } +} + +static void +quit(void) +{ + window_finish(); + rpg_finish(); + ui_finish(); + core_finish(); +} + +static void +run(struct inventory_dialog *dlg) +{ + struct clock clock = {0}; + + clock_start(&clock); + inventory_dialog_open(dlg); + + while (dlg->state) { + union event ev; + unsigned int elapsed = clock_elapsed(&clock); + + clock_start(&clock); + + while (event_poll(&ev)) { + switch (ev.type) { + case EVENT_QUIT: + inventory_dialog_finish(dlg); + break; + default: + inventory_dialog_handle(dlg, &ev); + break; + } + } + + inventory_dialog_update(dlg, elapsed); + painter_set_color(0xffffffff); + painter_clear(); + inventory_dialog_draw(dlg); + painter_present(); + + if ((elapsed = clock_elapsed(&clock)) < 20) + delay(20 - elapsed); + } +} + +static void +basic(void) +{ + struct inventory inv = { 0 }; + struct inventory_dialog dlg = { + .inv = &inv, + .x = 60, + .y = 60 + }; + + /* Add items manually to be able to sort. */ + inv.items[1][5].item = &items[0].item; + inv.items[1][5].amount = 12; + + inv.items[1][2].item = &items[0].item; + inv.items[1][2].amount = 9; + + inv.items[2][7].item = &items[1].item; + inv.items[2][7].amount = 9; + + inv.items[2][8].item = &items[1].item; + inv.items[2][8].amount = 3; + + inv.items[2][4].item = &items[2].item; + inv.items[2][4].amount = 1; + + run(&dlg); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + basic(); + quit(); +}
--- a/examples/example-label.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -/* - * example-label.c -- show how to use label and alignments - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <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() || !ui_init()) - panic(); - if (!window_open("Example - Label", W, H)) - panic(); - - for (size_t i = 0; i < NELEM(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 < NELEM(table); ++i) - label_draw(&table[i].label); - - label_draw(&mlabel); - painter_present(); -} - -static void -run(void) -{ - struct state state = { - .handle = handle, - .draw = draw - }; - - game_switch(&state, true); - 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/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-label) + +molko_define_executable( + TARGET example-label + SOURCES ${example-label_SOURCE_DIR}/main.c + LIBRARIES libui + FOLDER examples +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-label/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,182 @@ +/* + * example-label.c -- show how to use label and alignments + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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() || !ui_init()) + panic(); + if (!window_open("Example - Label", W, H)) + panic(); + + for (size_t i = 0; i < NELEM(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 < NELEM(table); ++i) + label_draw(&table[i].label); + + label_draw(&mlabel); + painter_present(); +} + +static void +run(void) +{ + struct state state = { + .handle = handle, + .draw = draw + }; + + game_switch(&state, true); + game_loop(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + quit(); +} +
--- a/examples/example-message.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,325 +0,0 @@ -/* - * example-message.c -- show how to use messages - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <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() || !ui_init() || !rpg_init()) - panic(); - if (!window_open("Example - Message", W, H)) - 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_switch(&state, true); - 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-message/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-message) + +molko_define_executable( + TARGET example-message + SOURCES ${example-message_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES librpg +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-message/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,325 @@ +/* + * example-message.c -- show how to use messages + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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() || !ui_init() || !rpg_init()) + panic(); + if (!window_open("Example - Message", W, H)) + 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_switch(&state, true); + 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/examples/example-sprite.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -/* - * example-sprite.c -- example on how to use sprites - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <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/texture.h> -#include <core/util.h> -#include <core/window.h> - -#include <ui/align.h> -#include <ui/label.h> -#include <ui/ui.h> - -#include <assets/sprites/people.h> - -#define W 1280 -#define H 720 -#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() || !ui_init()) - panic(); - if (!window_open("Example - Sprite", W, H)) - panic(); - if (!image_openmem(&texture, sprites_people, sizeof (sprites_people))) - 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 - }; - - game_switch(&state, true); - 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-sprite/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-sprite) + +molko_define_executable( + TARGET example-sprite + SOURCES ${example-sprite_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui libexamples +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-sprite/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,161 @@ +/* + * example-sprite.c -- example on how to use sprites + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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/texture.h> +#include <core/util.h> +#include <core/window.h> + +#include <ui/align.h> +#include <ui/label.h> +#include <ui/ui.h> + +#include <assets/sprites/people.h> + +#define W 1280 +#define H 720 +#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() || !ui_init()) + panic(); + if (!window_open("Example - Sprite", W, H)) + panic(); + if (!image_openmem(&texture, sprites_people, sizeof (sprites_people))) + 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_switch(&state, true); + 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/examples/example-trace.c Wed Nov 11 16:31:55 2020 +0100 +++ /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 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() || !ui_init()) - panic(); - if (!window_open("Example - Trace", W, H)) - 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_switch(&state, true); - 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-trace/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-trace) + +molko_define_executable( + TARGET example-trace + SOURCES ${example-trace_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui libadventure +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-trace/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,126 @@ +/* + * example-trace.c -- example on how to use custom trace handlers + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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() || !ui_init()) + panic(); + if (!window_open("Example - Trace", W, H)) + 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_switch(&state, true); + 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/examples/example-ui.c Wed Nov 11 16:31:55 2020 +0100 +++ /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 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 { - bool 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() || !ui_init()) - panic(); - if (!window_open("Example - UI", W, H)) - 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 bool -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 = true; - ui.motion.x = ev->click.x; - ui.motion.y = ev->click.y; - window_set_cursor(WINDOW_CURSOR_SIZE); - } - else - action_stack_handle(&ui.st, ev); - break; - case EVENT_CLICKUP: - ui.motion.active = false; - window_set_cursor(WINDOW_CURSOR_ARROW); - /* Fallthrough. */ - default: - action_stack_handle(&ui.st, ev); - break; - } -} - -static void -update(struct state *st, unsigned int ticks) -{ - (void)st; - - if (ui.quit.button.state == BUTTON_STATE_ACTIVATED) - game_quit(); - else - action_stack_update(&ui.st, ticks); -} - -static void -draw(struct state *st) -{ - (void)st; - - painter_set_color(0xffffffff); - painter_clear(); - action_stack_draw(&ui.st); - painter_present(); -} - -static void -run(void) -{ - struct state state = { - .handle = handle, - .update = update, - .draw = draw - }; - - prepare(); - resize(); - - game_switch(&state, true); - 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-ui/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,26 @@ +# +# CMakeLists.txt -- CMake build system for molko +# +# Copyright (c) 2020 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +project(example-ui) + +molko_define_executable( + TARGET example-ui + SOURCES ${example-ui_SOURCE_DIR}/main.c + FOLDER examples + LIBRARIES libui +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/example-ui/main.c Wed Nov 11 17:10:40 2020 +0100 @@ -0,0 +1,324 @@ +/* + * example-action.c -- example on how to use automatic actions + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <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 { + bool 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() || !ui_init()) + panic(); + if (!window_open("Example - UI", W, H)) + 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 bool +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 = true; + ui.motion.x = ev->click.x; + ui.motion.y = ev->click.y; + window_set_cursor(WINDOW_CURSOR_SIZE); + } + else + action_stack_handle(&ui.st, ev); + break; + case EVENT_CLICKUP: + ui.motion.active = false; + window_set_cursor(WINDOW_CURSOR_ARROW); + /* Fallthrough. */ + default: + action_stack_handle(&ui.st, ev); + break; + } +} + +static void +update(struct state *st, unsigned int ticks) +{ + (void)st; + + if (ui.quit.button.state == BUTTON_STATE_ACTIVATED) + game_quit(); + else + action_stack_update(&ui.st, ticks); +} + +static void +draw(struct state *st) +{ + (void)st; + + painter_set_color(0xffffffff); + painter_clear(); + action_stack_draw(&ui.st); + painter_present(); +} + +static void +run(void) +{ + struct state state = { + .handle = handle, + .update = update, + .draw = draw + }; + + prepare(); + resize(); + + game_switch(&state, true); + 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/librpg/CMakeLists.txt Wed Nov 11 16:31:55 2020 +0100 +++ b/librpg/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -48,8 +48,6 @@ ${librpg_SOURCE_DIR}/rpg/battle-state-victory.h ${librpg_SOURCE_DIR}/rpg/character.c ${librpg_SOURCE_DIR}/rpg/character.h - ${librpg_SOURCE_DIR}/rpg/inventory.c - ${librpg_SOURCE_DIR}/rpg/inventory.h ${librpg_SOURCE_DIR}/rpg/item.c ${librpg_SOURCE_DIR}/rpg/item.h ${librpg_SOURCE_DIR}/rpg/map.c
--- a/librpg/rpg/inventory.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -/* - * inventory.c -- inventory of items - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#if 0 - -#include <assert.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> - -#include "inventory.h" -#include "item.h" - -#define INVENTORY_TOTAL (INVENTORY_ROWS_MAX * INVENTORY_COLS_MAX) - -static bool -can_be_used(struct inventory_slot *slot, const struct item *item) -{ - assert(item); - - /* Empty slot. */ - if (!slot->item) - return false; - - /* Not same object. */ - if (strcmp(slot->item->name, item->name) != 0) - return false; - - /* No space in this slot. */ - if (slot->amount >= slot->item->stackable) - return false; - - return true; -} - -static struct inventory_slot * -find(struct inventory *iv, const struct item *item) -{ - assert(iv); - assert(item); - - /* First pass: find an entry with the same item. */ - for (unsigned int r = 0; r < INVENTORY_ROWS_MAX; ++r) - for (unsigned int c = 0; c < INVENTORY_COLS_MAX; ++c) - if (can_be_used(&iv->items[r][c], item)) - return &iv->items[r][c]; - - /* Second pass: try to find an empty slot. */ - for (unsigned int r = 0; r < INVENTORY_ROWS_MAX; ++r) - for (unsigned int c = 0; c < INVENTORY_COLS_MAX; ++c) - if (!iv->items[r][c].item) - return &iv->items[r][c]; - - return NULL; -} - -static unsigned -provide(struct inventory_slot *slot, struct item *item, unsigned int amount) -{ - assert(slot); - - unsigned int avail; - - /* The slot may be empty, make sure it contains this item. */ - slot->item = item; - - /* - * Example: - * - * The slot has already 10 items. - * The slot item is stackble up to 64 items. - * - * When pushing: - * - * 80: 54 pushed, 26 left - * 30: 30 pushed, 0 left. - */ - avail = slot->item->stackable - slot->amount; - - if (amount > avail) { - slot->amount += avail; - amount -= avail; - } else { - slot->amount += amount; - amount = 0; - } - - return amount; -} - -static bool -merge(struct inventory_slot *slot, struct inventory_slot *other) -{ - assert(slot); - assert(slot->item); - assert(other); - - /* Not compatible, return false to let the sorting continue. */ - if (slot->item != other->item) - return false; - - while (slot->amount < slot->item->stackable && other->amount) { - slot->amount++; - other->amount--; - } - - /* No more amount in the other slot, empty it. */ - if (other->amount == 0U) - memset(other, 0, sizeof (*other)); - - return slot->amount >= slot->item->stackable; -} - -static void -sort(struct inventory *iv, struct inventory_slot *slot, int r, int c) -{ - assert(slot); - assert(slot->item); - - /* Merge until the end of thiw row. */ - for (c = c + 1; c < INVENTORY_COLS_MAX; ++c) - if (merge(slot, &iv->items[r][c])) - return; - - /* Merge the next rows. */ - for (r = r + 1; r < INVENTORY_ROWS_MAX; ++r) - for (c = 0; c < INVENTORY_COLS_MAX; ++c) - if (merge(slot, &iv->items[r][c])) - return; -} - -unsigned int -inventory_push(struct inventory *iv, struct item *item, unsigned int amount) -{ - assert(iv); - assert(item); - - while (amount) { - struct inventory_slot *slot; - - if (!(slot = find(iv, item))) - break; - - /* Add as much as we can in this slot. */ - amount = provide(slot, item, amount); - } - - return amount; -} - -static int -compare_slot(const void *v1, const void *v2) -{ - const struct inventory_slot *slot1 = v1; - const struct inventory_slot *slot2 = v2; - int cmp; - - /* Two null slots compare equal. */ - if (!slot1->item && !slot2->item) - return 0; - - /* Null left should be moved after. */ - if (!slot1->item) - return 1; - - /* Null right slots should be moved after. */ - if (!slot2->item) - return -1; - - /* If they are identical, use amount to sort. */ - if ((cmp = strcmp(slot1->item->name, slot2->item->name)) == 0) - return (long long int)slot2->amount - (long long int)slot1->amount; - - return cmp; -} - -void -inventory_sort(struct inventory *iv) -{ - assert(iv); - - for (int r = 0; r < INVENTORY_ROWS_MAX; ++r) - for (int c = 0; c < INVENTORY_COLS_MAX; ++c) - if (iv->items[r][c].item) - sort(iv, &iv->items[r][c], r, c); - - /* Sort by names AND by amount. */ - qsort(iv->items, INVENTORY_TOTAL, sizeof (struct inventory_slot), compare_slot); -} - -void -inventory_clear(struct inventory *iv) -{ - assert(iv); - - memset(iv, 0, sizeof (*iv)); -} - -#endif
--- a/librpg/rpg/inventory.h Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * inventory.h -- inventory of items - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef MOLKO_INVENTORY_H -#define MOLKO_INVENTORY_H - -#if 0 - -/** - * \file inventory.h - * \brief Inventory of items. - */ - -/** - * \brief Maximum number of rows. - */ -#define INVENTORY_ROWS_MAX 3 - -/** - * \brief Maximum number of columns. - */ -#define INVENTORY_COLS_MAX 10 - -struct item; - -/** - * \brief Inventory slot. - * - * This structure describe a 'cell' into the inventory. It references a item - * and has a given amount of it. - */ -struct inventory_slot { - struct item *item; /*!< (+&?) Pointer to the item. */ - unsigned int amount; /*!< (-) Number of items in this slot. */ -}; - -/** - * \brief Inventory structure. - */ -struct inventory { - /** - * (-) Grid of objects. - */ - struct inventory_slot items[INVENTORY_ROWS_MAX][INVENTORY_COLS_MAX]; -}; - -/** - * Try to push as much as possible the given item. - * - * \pre iv != NULL - * \pre item != NULL - * \param iv the inventory - * \param item the item to reference - * \param amount the desired amount - * \return 0 if all items were pushed or the number left otherwise - */ -unsigned int -inventory_push(struct inventory *iv, struct item *item, unsigned int amount); - -/** - * Sort the inventory. - * - * \pre iv != NULL - * \pre item != NULL - * \param iv the inventory - */ -void -inventory_sort(struct inventory *iv); - -/** - * Clears the inventory. - * - * \pre iv != NULL - * \param iv the inventory - */ -void -inventory_clear(struct inventory *iv); - -#endif - -#endif /* !MOLKO_INVENTORY_H */
--- a/tests/CMakeLists.txt Wed Nov 11 16:31:55 2020 +0100 +++ b/tests/CMakeLists.txt Wed Nov 11 17:10:40 2020 +0100 @@ -22,7 +22,6 @@ molko_define_test(TARGET action-script SOURCES test-action-script.c) molko_define_test(TARGET color SOURCES test-color.c) molko_define_test(TARGET error SOURCES test-error.c) -molko_define_test(TARGET inventory SOURCES test-inventory.c) molko_define_test( TARGET map SOURCES test-map.c
--- a/tests/test-inventory.c Wed Nov 11 16:31:55 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -/* - * test-inventory.c -- test inventory functions - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define GREATEST_USE_ABBREVS 0 -#include <greatest.h> - -#if 0 - -#include <rpg/item.h> -#include <rpg/inventory.h> - -static struct item potion = { - .name = "Potion", - .stackable = 64 -}; - -static struct item elixir = { - .name = "Elixir", - .stackable = 64 -}; - -static struct item sword = { - .name = "Sword", - .stackable = 1 -}; - -#define SET(iv, r, c, i, a) \ -do { \ - (iv)->items[(r)][(c)].item = (i); \ - (iv)->items[(r)][(c)].amount = (a); \ -} while (0) \ - -GREATEST_TEST -push_simple(void) -{ - struct inventory inv = { 0 }; - unsigned int left; - - /* - * [0][0] should contain 50 potions. - */ - left = inventory_push(&inv, &potion, 50U); - GREATEST_ASSERT_EQ(left, 0U); - GREATEST_ASSERT_EQ(inv.items[0][0].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][0].amount, 50U); - inventory_clear(&inv); - - /* - * [0][1] should contain 64 potions. - * [0][2] should contain 10 potions. - */ - left = inventory_push(&inv, &potion, 74U); - GREATEST_ASSERT_EQ(left, 0U); - GREATEST_ASSERT_EQ(inv.items[0][0].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][0].amount, 64U); - GREATEST_ASSERT_EQ(inv.items[0][1].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][1].amount, 10U); - inventory_clear(&inv); - - /* - * 1. We push 10 potions - * 2. We push 10 more potions. - * - * [0][0] should contain 20 potions. - */ - left = inventory_push(&inv, &potion, 10U); - GREATEST_ASSERT_EQ(left, 0U); - GREATEST_ASSERT_EQ(inv.items[0][0].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][0].amount, 10U); - left = inventory_push(&inv, &potion, 10U); - GREATEST_ASSERT_EQ(left, 0U); - GREATEST_ASSERT_EQ(inv.items[0][0].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][0].amount, 20U); - inventory_clear(&inv); - - GREATEST_PASS(); -} - -GREATEST_TEST -push_full(void) -{ - struct inventory inv = { 0 }; - unsigned int left; - - /* - * Fill the inventory with - * - * - 29 x 64 potions - * - Last slot will have already 50 potions. - * - * This means the maximum potions to push is only 14. - */ - for (int i = 0; i < 29; ++i) { - left = inventory_push(&inv, &potion, 64U); - GREATEST_ASSERT_EQ(left, 0U); - } - - left = inventory_push(&inv, &potion, 50U); - GREATEST_ASSERT_EQ(left, 0U); - - /* - * Try to add 20 potions, only 14 should be pushed. - */ - left = inventory_push(&inv, &potion, 20U); - GREATEST_ASSERT_EQ(left, 6U); - GREATEST_ASSERT_EQ(inv.items[2][9].amount, 64U); - - GREATEST_PASS(); -} - -GREATEST_TEST -push_other(void) -{ - struct inventory inv = { 0 }; - unsigned int left; - - /* - * [0][0] should contain 30 potions. - */ - left = inventory_push(&inv, &potion, 30U); - GREATEST_ASSERT_EQ(left, 0U); - GREATEST_ASSERT_EQ(inv.items[0][0].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][0].amount, 30U); - - /* - * Since elixir is not a potion, it should be pushed into an other - * cell. - * - * [0][0] should be untouched - * [0][1] should contain 30 elixir. - */ - left = inventory_push(&inv, &elixir, 30U); - GREATEST_ASSERT_EQ(left, 0U); - GREATEST_ASSERT_EQ(inv.items[0][0].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][0].amount, 30U); - GREATEST_ASSERT_EQ(inv.items[0][1].item, &elixir); - GREATEST_ASSERT_EQ(inv.items[0][1].amount, 30U); - - GREATEST_PASS(); -} - -GREATEST_SUITE(push) -{ - GREATEST_RUN_TEST(push_simple); - GREATEST_RUN_TEST(push_full); - GREATEST_RUN_TEST(push_other); -} - -GREATEST_TEST -sort_simple(void) -{ - struct inventory inv = { 0 }; - - /* - * Create this inventory: - * - * 0 1 2 3 4 5 6 7 8 9 - * 0 [ ] [P:10] [ ] [ ] [S: 1] [ ] [ ] [E:24] [ ] [ ] - * 1 [ ] [ ] [P:12] [ ] [ ] [ ] [ ] [ ] [ ] [ ] - * 2 [ ] [ ] [ ] [ ] [E: 8] [ ] [ ] [ ] [P: 5] [ ] - */ - SET(&inv, 0, 1, &potion, 10); - SET(&inv, 0, 4, &sword, 1); - SET(&inv, 0, 7, &elixir, 24); - SET(&inv, 1, 2, &potion, 12); - SET(&inv, 2, 4, &elixir, 8); - SET(&inv, 2, 8, &potion, 5); - - /* - * Should look like this: - * - * 0 1 2 3 4 5 6 7 8 9 - * 0 [E:32] [P:27] [S: 1] [ ] [ ] [ ] [ ] [ ] [ ] [ ] - * 1 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] - * 2 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] - */ - inventory_sort(&inv); - GREATEST_ASSERT_EQ(inv.items[0][0].item, &elixir); - GREATEST_ASSERT_EQ(inv.items[0][0].amount, 32U); - GREATEST_ASSERT_EQ(inv.items[0][1].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][1].amount, 27U); - GREATEST_ASSERT_EQ(inv.items[0][2].item, &sword); - GREATEST_ASSERT_EQ(inv.items[0][2].amount, 1U); - - GREATEST_PASS(); -} - -GREATEST_TEST -sort_with_full(void) -{ - struct inventory inv = { 0 }; - - /* - * Create this inventory: - * - * 0 1 2 3 4 5 6 7 8 9 - * 0 [ ] [P:62] [ ] [ ] [S: 1] [ ] [ ] [E:64] [ ] [ ] - * 1 [ ] [ ] [P:12] [ ] [ ] [ ] [ ] [ ] [ ] [ ] - * 2 [ ] [ ] [ ] [ ] [E: 8] [ ] [ ] [ ] [P: 5] [ ] - */ - SET(&inv, 0, 1, &potion, 62); - SET(&inv, 0, 4, &sword, 1); - SET(&inv, 0, 7, &elixir, 64); - SET(&inv, 1, 2, &potion, 12); - SET(&inv, 2, 4, &elixir, 8); - SET(&inv, 2, 8, &potion, 5); - - /* - * Should look like this: - * - * 0 1 2 3 4 5 6 7 8 9 - * 0 [E:64] [E: 8] [P:64] [P:10] [S: 1] [ ] [ ] [ ] [ ] [ ] - * 1 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] - * 2 [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] - */ - inventory_sort(&inv); - GREATEST_ASSERT_EQ(inv.items[0][0].item, &elixir); - GREATEST_ASSERT_EQ(inv.items[0][0].amount, 64U); - GREATEST_ASSERT_EQ(inv.items[0][1].item, &elixir); - GREATEST_ASSERT_EQ(inv.items[0][1].amount, 8U); - GREATEST_ASSERT_EQ(inv.items[0][2].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][2].amount, 64U); - GREATEST_ASSERT_EQ(inv.items[0][3].item, &potion); - GREATEST_ASSERT_EQ(inv.items[0][3].amount, 15U); - GREATEST_ASSERT_EQ(inv.items[0][4].item, &sword); - GREATEST_ASSERT_EQ(inv.items[0][4].amount, 1U); - - GREATEST_PASS(); -} - -GREATEST_SUITE(sort) -{ - GREATEST_RUN_TEST(sort_simple); - GREATEST_RUN_TEST(sort_with_full); -} - -GREATEST_MAIN_DEFS(); - -#endif - -int -main(int argc, char **argv) -{ -#if 0 - GREATEST_MAIN_BEGIN(); - GREATEST_RUN_SUITE(push); - GREATEST_RUN_SUITE(sort); - GREATEST_MAIN_END(); -#endif - return 0; -}