Mercurial > molko
changeset 59:52792b863ff7
misc: separate core from game
line wrap: on
line diff
--- a/.hgignore Tue Jan 21 12:31:56 2020 +0100 +++ b/.hgignore Tue Jan 21 12:42:33 2020 +0100 @@ -16,7 +16,7 @@ ^tests/test-color(\.exe)?$ ^tests/test-error(\.exe)?$ ^tests/test-map(\.exe)?$ -^tools/molko-map$ +^tools/molko-map(\.exe)?$ # doxygen stuff. ^doxygen/html$
--- a/Makefile Tue Jan 21 12:31:56 2020 +0100 +++ b/Makefile Tue Jan 21 12:42:33 2020 +0100 @@ -24,26 +24,31 @@ # CFLAGS= -MMD -O3 -DNDEBUG -std=c18 -Wall -Wextra PROG= molko LIB= libmolko.a -SRCS= src/animation.c \ - src/clock.c \ - src/error.c \ - src/event.c \ - src/font.c \ - src/game.c \ - src/image.c \ - src/map.c \ - src/map_state.c \ - src/message.c \ - src/painter.c \ - src/sprite.c \ - src/sys.c \ - src/texture.c \ - src/util.c \ - src/splashscreen.c \ - src/walksprite.c \ - src/window.c -OBJS= ${SRCS:.c=.o} -DEPS= ${SRCS:.c=.d} + +CORE_SRCS= src/core/animation.c \ + src/core/clock.c \ + src/core/error.c \ + src/core/event.c \ + src/core/font.c \ + src/core/game.c \ + src/core/image.c \ + src/core/map.c \ + src/core/map_state.c \ + src/core/message.c \ + src/core/painter.c \ + src/core/sprite.c \ + src/core/sys.c \ + src/core/texture.c \ + src/core/util.c \ + src/core/walksprite.c \ + src/core/window.c +CORE_OBJS= ${CORE_SRCS:.c=.o} +CORE_DEPS= ${CORE_SRCS:.c=.d} + +ADV_SRCS= src/adventure/main.c \ + src/adventure/splashscreen_state.c +ADV_OBJS= ${ADV_SRCS:.c=.o} +ADV_DEPS= ${ADV_SRCS:.c=.d} PREFIX= /usr/local BINDIR= ${PREFIX}/bin @@ -58,7 +63,7 @@ TESTS= tests/test-color.c \ tests/test-error.c \ tests/test-map.c -TESTS_INCS= -I extern/libgreatest -I src ${SDL_CFLAGS} +TESTS_INCS= -I extern/libgreatest -I src/core ${SDL_CFLAGS} TESTS_LIBS= ${LIB} ${SDL_LDFLAGS} ${LDFLAGS} TESTS_OBJS= ${TESTS:.c=} TESTS_DEPS= ${TESTS:.c=.d} @@ -70,25 +75,26 @@ DEFINES= -DPREFIX=\""${PREFIX}"\" \ -DBINDIR=\""${BINDIR}"\" \ -DSHAREDIR=\""${SHAREDIR}"\" +INCLUDES= -I src/core -I src/adventure .SUFFIXES: .SUFFIXES: .c .o all: ${PROG} --include ${DEPS} ${TESTS_DEPS} ${TOOLS_DEPS} +-include ${CORE_DEPS} ${ADV_DEPS} ${TESTS_DEPS} ${TOOLS_DEPS} .c.o: - ${CC} ${DEFINES} ${SDL_CFLAGS} ${CFLAGS} -c $< -o $@ + ${CC} ${DEFINES} ${INCLUDES} ${SDL_CFLAGS} ${CFLAGS} -c $< -o $@ .c: ${CC} ${TESTS_INCS} -o $@ ${CFLAGS} $< ${TESTS_LIBS} -${LIB}: ${OBJS} - ${AR} -rcs $@ ${OBJS} +${LIB}: ${CORE_OBJS} + ${AR} -rcs $@ ${CORE_OBJS} -${PROG}: ${LIB} src/main.o - ${CC} -o $@ src/main.o ${LIB} ${SDL_LDFLAGS} ${LDFLAGS} +${PROG}: ${LIB} ${ADV_OBJS} + ${CC} -o $@ ${ADV_OBJS} ${LIB} ${SDL_LDFLAGS} ${LDFLAGS} ${TESTS_OBJS}: ${LIB} @@ -111,9 +117,10 @@ cp -R assets/* ${DESTDIR}${SHAREDIR}/molko clean: - rm -f ${PROG} src/main.o src/main.d rm -rf doxygen/html doxygen/man - rm -f ${LIB} ${OBJS} ${DEPS} + rm -f ${LIB} ${PROG} + rm -f ${CORE_OBJS} ${CORE_DEPS} + rm -f ${ADV_OBJS} ${ADV_DEPS} rm -f ${TESTS_OBJS} ${TESTS_DEPS} rm -f ${TOOLS_OBJS} ${TOOLS_DEPS}
--- a/src/action.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * action.h -- action states - * - * Copyright (c) 2020 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef ACTION_H -#define ACTION_H - -/** - * \file action.h - * \brief Action states. - */ - -#include <stdbool.h> - -union event; - -/** - * \brief Action flags. - */ -enum action_flags { - ACTION_NONE, /*!< No flags */ - ACTION_AUTO_LEAVE = (1 << 0) /*!< Action is removed on state change */ -}; - -/** - * \brief Action structure. - */ -struct action { - /** - * (RW) - * - * Optional flags. - */ - enum action_flags flags; - - /** - * (RW) - * - * Arbitrary user data. - */ - void *data; - - /** - * (RW) - * - * Handle event. - */ - void (*handle)(struct action *, const union event *event); - - /** - * (RW) - * - * Update the action. - * - * If returns true, the action is removed. - */ - bool (*update)(struct action *, unsigned int); - - /** - * (RW) - * - * Draw the aciton. - */ - void (*draw)(struct action *); - - /** - * (RW) - * - * Close the action before removal. - */ - void (*finish)(struct action *); -}; - -#endif /* !ACTION_H*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/adventure/main.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,96 @@ +/* + * main.c -- Molko's Adventure + * + * 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 "clock.h" +#include "error.h" +#include "event.h" +#include "game.h" +#include "image.h" +#include "map.h" +#include "map_state.h" +#include "splashscreen_state.h" +#include "sprite.h" +#include "sys.h" +#include "util.h" +#include "window.h" + +#define WINDOW_WIDTH 1280 +#define WINDOW_HEIGHT 720 + +static void +init(void) +{ + if (!sys_init()) + error_fatal(); + if (!window_init("Molko's Adventure", WINDOW_WIDTH, WINDOW_HEIGHT)) + error_fatal(); + + /* Default state is splash screen */ + game_switch(&splashscreen_state, true); +} + +static void +run(void) +{ + union event ev; + struct clock clock; + + clock_start(&clock); + + for (;;) { + unsigned int elapsed = clock_elapsed(&clock); + + clock_start(&clock); + + while (event_poll(&ev)) { + /* TODO: this must be handled by states. */ + if (ev.type == EVENT_QUIT) + return; + + game_handle(&ev); + } + + game_update(elapsed); + game_draw(); + + if ((elapsed = clock_elapsed(&clock)) < 20) + delay(20 - elapsed); + } +} + +static void +close(void) +{ + window_close(); + sys_close(); +} + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + run(); + close(); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/adventure/splashscreen_state.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,103 @@ +/* + * splashscreen_state.c -- splash screen state + * + * 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 "error.h" +#include "font.h" +#include "game.h" +#include "image.h" +#include "map.h" +#include "map_state.h" +#include "painter.h" +#include "splashscreen_state.h" +#include "state.h" +#include "sys.h" +#include "texture.h" +#include "window.h" + +#define DELAY 3000 + +static unsigned int elapsed; +static struct font *font; +static struct texture *text; +static int x; +static int y; + +static void +enter(void) +{ + if (!(font = font_openf(sys_datapath("fonts/knights-quest.ttf"), 160))) + error_fatal(); + if (!(text = font_render(font, "Molko's Adventure", 0x000000ff))) + error_fatal(); + + /* Compute position. */ + const unsigned int w = texture_width(text); + const unsigned int h = texture_height(text); + + x = (window_width() / 2) - (w / 2); + y = (window_height() / 2) - (h / 2) - 100; +} + +static void +leave(void) +{ + font_close(font); +} + +static void +handle(const union event *event) +{ + (void)event; +} + +static void +update(unsigned int ticks) +{ + elapsed += ticks; + + /* TODO: change this once map is done. */ + if (elapsed >= DELAY) { + /* TODO: this will be removed too. */ + static struct texture *image; + + if (!map_open(&map_state_data.map.map, sys_datapath("maps/test.map"))) + error_fatal(); + if (!(image = image_openf(sys_datapath("sprites/test-walk.png")))) + error_fatal(); + + sprite_init(&map_state_data.player.sprite, image, 48, 48); + game_switch(&map_state, false); + } +} + +static void +draw(void) +{ + painter_set_color(0xffffffff); + painter_clear(); + texture_draw(text, x, y); + painter_present(); +} + +struct state splashscreen_state = { + .enter = enter, + .leave = leave, + .handle = handle, + .update = update, + .draw = draw +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/adventure/splashscreen_state.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,32 @@ +/* + * splashscreen_state.h -- splash screen state + * + * 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_SPLASHSCREEN_ADVENTURE_H +#define MOLKO_SPLASHSCREEN_ADVENTURE_H + +/** + * \file splashscreen.h + * \brief Splash screen state. + */ + +/** + * \brief Splash screen state. + */ +extern struct state splashscreen_state; + +#endif /* !MOLKO_SPLASHSCREEN_ADVENTURE_H */
--- a/src/animation.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* - * animation.c -- basic 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 <assert.h> - -#include "animation.h" -#include "sprite.h" - -void -animation_init(struct animation *an, struct sprite *sprite, unsigned int delay) -{ - assert(an); - assert(sprite); - - an->sprite = sprite; - an->row = 0; - an->column = 0; - an->delay = delay; - an->elapsed = 0; -} - -bool -animation_is_complete(const struct animation *an) -{ - assert(an); - - return an->row == an->sprite->nrows && - an->column == an->sprite->ncols && - an->elapsed >= an->delay; -} - -void -animation_start(struct animation *an) -{ - assert(an); - - an->row = 0; - an->column = 0; - an->elapsed = 0; -} - -void -animation_update(struct animation *an, unsigned int ticks) -{ - assert(an); - - an->elapsed += ticks; - - if (an->elapsed < an->delay) - return; - - /* Increment column first */ - if (++an->column >= an->sprite->ncols) { - /* - * Increment row, if we reach the last row it means we are - * at the last frame. - */ - if (++an->row >= an->sprite->nrows) - an->row = an->sprite->nrows; - else - an->column = 0; - } -} - -void -animation_draw(struct animation *an, int x, int y) -{ - sprite_draw(an->sprite, an->row, an->column, x, y); -}
--- a/src/animation.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* - * animation.h -- basic 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. - */ - -#ifndef MOLKO_ANIMATION_H -#define MOLKO_ANIMATION_H - -/** - * \file animation.h - * \brief Basic animations. - */ - -#include <stdbool.h> - -struct sprite; - -/** - * \brief Animation object - */ -struct animation { - struct sprite *sprite; /*!< Sprite to use (RW) */ - unsigned int row; /*!< current row (RO) */ - unsigned int column; /*!< current column (RO) */ - unsigned int delay; /*!< delay between frames (RW) */ - unsigned int elapsed; /*!< elapsed time since last frame (RO) */ -}; - -/** - * Initialize the animation. - * - * The animation does not take sprite ownership, it must be valid until - * animation is no longer used. - * - * \pre an != NULL - * \pre sprite != NULL - * \param an the animation - * \param sprite the sprite to use - * \param delay the delay between frames in milliseconds - */ -void -animation_init(struct animation *an, struct sprite *sprite, unsigned int delay); - -/** - * Tells if the animation is complete. - * - * \pre an != NULL - * \param an the animation - * \return true if the animation has completed - */ -bool -animation_is_complete(const struct animation *an); - -/** - * Start an animation. - * - * \pre an != NULL - * \param an the animation - */ -void -animation_start(struct animation *an); - -/** - * Update the animation. - * - * You must call this function at each loop iteration to update the animation - * frame depending on its delay. - * - * \pre an != NULL - * \param an the animation - * \param ticks the elapsed ticks since the last call - */ -void -animation_update(struct animation *an, unsigned int ticks); - -/** - * Draw the animation. - * - * \pre an != NULL - * \param an the animation - * \param x the X coordinate - * \param y the Y coordinate - */ -void -animation_draw(struct animation *an, int x, int y); - -#endif /* !MOLKO_ANIMATION_H */
--- a/src/clock.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * clock.c -- track elapsed time - * - * 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 <SDL.h> - -#include "clock.h" - -void -clock_start(struct clock *clock) -{ - clock->ticks = SDL_GetTicks(); -} - -unsigned int -clock_elapsed(const struct clock *clock) -{ - return SDL_GetTicks() - clock->ticks; -}
--- a/src/clock.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * clock.h -- track elapsed time - * - * 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_CLOCK_H -#define MOLKO_CLOCK_H - -/** - * \file clock.h - * \brief Track elapsed time. - */ - -/** - * \brief Clock structure. - */ -struct clock { - unsigned int ticks; /*!< time point on initialization */ -}; - -/** - * Start the clock and track elapsed time. - * - * \pre clock != NULL - * \param clock the clock - */ -void -clock_start(struct clock *clock); - -/** - * Tell the measured time. - * - * \pre clock != NULL - * \param clock the clock - * \return the elapsed time in milliseconds - */ -unsigned int -clock_elapsed(const struct clock *clock); - -#endif /* !MOLKO_CLOCK_H */
--- a/src/color.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * color.h -- basic color routines - * - * 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_COLOR_H -#define MOLKO_COLOR_H - -/** - * \file color.h - * \brief Basic color routines. - */ - -/** - * Get red component of hexadecimal color. - * - * \param c the hexadecimal color - * \return the red component - */ -#define COLOR_R(c) (c >> 24 & 0xff) - -/** - * Get green component of hexadecimal color. - * - * \param c the hexadecimal color - * \return the green component - */ -#define COLOR_G(c) (c >> 16 & 0xff) - -/** - * Get blue component of hexadecimal color. - * - * \param c the hexadecimal color - * \return the blue component - */ -#define COLOR_B(c) (c >> 8 & 0xff) - -/** - * Get alpha component of hexadecimal color. - * - * \param c the hexadecimal color - * \return the alpha component - */ -#define COLOR_A(c) (c & 0xff) - -/** - * Convert individual RGBA components into a hexadecimal color. - * - * \param r the red component - * \param g the green component - * \param b the blue component - * \param a the alpha component - * \return the hexadecimal color - */ -#define COLOR_HEX(r, g, b, a) \ - ((r << 24 & 0xff000000) | \ - (g << 16 & 0x00ff0000) | \ - (b << 8 & 0x0000ff00) | \ - (a & 0x000000ff)) - -#endif /* !MOLKO_COLOR_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/action.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,88 @@ +/* + * action.h -- action states + * + * Copyright (c) 2020 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ACTION_H +#define ACTION_H + +/** + * \file action.h + * \brief Action states. + */ + +#include <stdbool.h> + +union event; + +/** + * \brief Action flags. + */ +enum action_flags { + ACTION_NONE, /*!< No flags */ + ACTION_AUTO_LEAVE = (1 << 0) /*!< Action is removed on state change */ +}; + +/** + * \brief Action structure. + */ +struct action { + /** + * (RW) + * + * Optional flags. + */ + enum action_flags flags; + + /** + * (RW) + * + * Arbitrary user data. + */ + void *data; + + /** + * (RW) + * + * Handle event. + */ + void (*handle)(struct action *, const union event *event); + + /** + * (RW) + * + * Update the action. + * + * If returns true, the action is removed. + */ + bool (*update)(struct action *, unsigned int); + + /** + * (RW) + * + * Draw the aciton. + */ + void (*draw)(struct action *); + + /** + * (RW) + * + * Close the action before removal. + */ + void (*finish)(struct action *); +}; + +#endif /* !ACTION_H*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/animation.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,84 @@ +/* + * animation.c -- basic 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 <assert.h> + +#include "animation.h" +#include "sprite.h" + +void +animation_init(struct animation *an, struct sprite *sprite, unsigned int delay) +{ + assert(an); + assert(sprite); + + an->sprite = sprite; + an->row = 0; + an->column = 0; + an->delay = delay; + an->elapsed = 0; +} + +bool +animation_is_complete(const struct animation *an) +{ + assert(an); + + return an->row == an->sprite->nrows && + an->column == an->sprite->ncols && + an->elapsed >= an->delay; +} + +void +animation_start(struct animation *an) +{ + assert(an); + + an->row = 0; + an->column = 0; + an->elapsed = 0; +} + +void +animation_update(struct animation *an, unsigned int ticks) +{ + assert(an); + + an->elapsed += ticks; + + if (an->elapsed < an->delay) + return; + + /* Increment column first */ + if (++an->column >= an->sprite->ncols) { + /* + * Increment row, if we reach the last row it means we are + * at the last frame. + */ + if (++an->row >= an->sprite->nrows) + an->row = an->sprite->nrows; + else + an->column = 0; + } +} + +void +animation_draw(struct animation *an, int x, int y) +{ + sprite_draw(an->sprite, an->row, an->column, x, y); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/animation.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,100 @@ +/* + * animation.h -- basic 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. + */ + +#ifndef MOLKO_ANIMATION_H +#define MOLKO_ANIMATION_H + +/** + * \file animation.h + * \brief Basic animations. + */ + +#include <stdbool.h> + +struct sprite; + +/** + * \brief Animation object + */ +struct animation { + struct sprite *sprite; /*!< Sprite to use (RW) */ + unsigned int row; /*!< current row (RO) */ + unsigned int column; /*!< current column (RO) */ + unsigned int delay; /*!< delay between frames (RW) */ + unsigned int elapsed; /*!< elapsed time since last frame (RO) */ +}; + +/** + * Initialize the animation. + * + * The animation does not take sprite ownership, it must be valid until + * animation is no longer used. + * + * \pre an != NULL + * \pre sprite != NULL + * \param an the animation + * \param sprite the sprite to use + * \param delay the delay between frames in milliseconds + */ +void +animation_init(struct animation *an, struct sprite *sprite, unsigned int delay); + +/** + * Tells if the animation is complete. + * + * \pre an != NULL + * \param an the animation + * \return true if the animation has completed + */ +bool +animation_is_complete(const struct animation *an); + +/** + * Start an animation. + * + * \pre an != NULL + * \param an the animation + */ +void +animation_start(struct animation *an); + +/** + * Update the animation. + * + * You must call this function at each loop iteration to update the animation + * frame depending on its delay. + * + * \pre an != NULL + * \param an the animation + * \param ticks the elapsed ticks since the last call + */ +void +animation_update(struct animation *an, unsigned int ticks); + +/** + * Draw the animation. + * + * \pre an != NULL + * \param an the animation + * \param x the X coordinate + * \param y the Y coordinate + */ +void +animation_draw(struct animation *an, int x, int y); + +#endif /* !MOLKO_ANIMATION_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/clock.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,33 @@ +/* + * clock.c -- track elapsed time + * + * 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 <SDL.h> + +#include "clock.h" + +void +clock_start(struct clock *clock) +{ + clock->ticks = SDL_GetTicks(); +} + +unsigned int +clock_elapsed(const struct clock *clock) +{ + return SDL_GetTicks() - clock->ticks; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/clock.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,53 @@ +/* + * clock.h -- track elapsed time + * + * 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_CLOCK_H +#define MOLKO_CLOCK_H + +/** + * \file clock.h + * \brief Track elapsed time. + */ + +/** + * \brief Clock structure. + */ +struct clock { + unsigned int ticks; /*!< time point on initialization */ +}; + +/** + * Start the clock and track elapsed time. + * + * \pre clock != NULL + * \param clock the clock + */ +void +clock_start(struct clock *clock); + +/** + * Tell the measured time. + * + * \pre clock != NULL + * \param clock the clock + * \return the elapsed time in milliseconds + */ +unsigned int +clock_elapsed(const struct clock *clock); + +#endif /* !MOLKO_CLOCK_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/color.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,74 @@ +/* + * color.h -- basic color routines + * + * 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_COLOR_H +#define MOLKO_COLOR_H + +/** + * \file color.h + * \brief Basic color routines. + */ + +/** + * Get red component of hexadecimal color. + * + * \param c the hexadecimal color + * \return the red component + */ +#define COLOR_R(c) (c >> 24 & 0xff) + +/** + * Get green component of hexadecimal color. + * + * \param c the hexadecimal color + * \return the green component + */ +#define COLOR_G(c) (c >> 16 & 0xff) + +/** + * Get blue component of hexadecimal color. + * + * \param c the hexadecimal color + * \return the blue component + */ +#define COLOR_B(c) (c >> 8 & 0xff) + +/** + * Get alpha component of hexadecimal color. + * + * \param c the hexadecimal color + * \return the alpha component + */ +#define COLOR_A(c) (c & 0xff) + +/** + * Convert individual RGBA components into a hexadecimal color. + * + * \param r the red component + * \param g the green component + * \param b the blue component + * \param a the alpha component + * \return the hexadecimal color + */ +#define COLOR_HEX(r, g, b, a) \ + ((r << 24 & 0xff000000) | \ + (g << 16 & 0x00ff0000) | \ + (b << 8 & 0x0000ff00) | \ + (a & 0x000000ff)) + +#endif /* !MOLKO_COLOR_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/error.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,97 @@ +/* + * error.c -- error routines + * + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "error.h" +#include "error_p.h" + +#include <SDL.h> + +static char buffer[2048]; + +const char * +error(void) +{ + return buffer; +} + +bool +error_errno(void) +{ + error_printf("%s", strerror(errno)); + + return false; +} + +bool +error_printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_vprintf(fmt, ap); + va_end(ap); + + return false; +} + +bool +error_vprintf(const char *fmt, va_list ap) +{ + vsnprintf(buffer, sizeof (buffer), fmt, ap); + + return false; +} + +noreturn void +error_fatal(void) +{ + fprintf(stderr, "%s\n", buffer); + exit(1); +} + +noreturn void +error_fatalf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + error_vfatalf(fmt, ap); + va_end(ap); +} + +noreturn void +error_vfatalf(const char *fmt, va_list ap) +{ + fprintf(stderr, fmt, ap); + exit(1); +} + +/* private: error_p.h */ + +bool +error_sdl(void) +{ + error_printf("%s", SDL_GetError()); + + return false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/error.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,90 @@ +/* + * error.h -- error routines + * + * 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_ERROR_H +#define MOLKO_ERROR_H + +/** + * \file error.h + * \brief Error routines. + */ + +#include <stdarg.h> +#include <stdbool.h> +#include <stdnoreturn.h> + +/** + * Get the last error returned. + * + * \return the error string + */ +const char * +error(void); + +/** + * Convenient handler that sets last error from global C errno and then return + * false. + * + * \return false + */ +bool +error_errno(void); + +/** + * Set the game error with a printf-like format. + * + * \param fmt the format string + * \return false + */ +bool +error_printf(const char *fmt, ...); + +/** + * Similar to \a error_printf. + * + * \param fmt the format stinrg + * \param ap the variadic arguments pointer + * \return false + */ +bool +error_vprintf(const char *fmt, va_list ap); + +/** + * Print last registered error and exit with code 1. + */ +noreturn void +error_fatal(void); + +/** + * Prints an error to stderr and exit. + * + * \param fmt the format string + */ +noreturn void +error_fatalf(const char *fmt, ...); + +/** + * Similar to \a error_fatalf + * + * \param fmt the format string + * \param ap the variadic arguments pointer + */ +noreturn void +error_vfatalf(const char *fmt, va_list ap); + +#endif /* !MOLKO_ERROR_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/error_p.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,33 @@ +/* + * error.h -- (PRIVATE) error routines + * + * 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_ERROR_P_H +#define MOLKO_ERROR_P_H + +#include <stdbool.h> + +/** + * Convenient handler that sets the game error to the last SDL error and then + * return false. + * + * \return false + */ +bool +error_sdl(void); + +#endif /* !MOLKO_ERROR_P_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/event.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,255 @@ +/* + * event.c -- event management + * + * 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 <SDL.h> + +#include "event.h" + +/* Maintain with enum key constants in key.h */ +static const struct { + SDL_Keycode key; + enum key value; +} keymap[] = { + { SDLK_RETURN, KEY_ENTER }, + { SDLK_ESCAPE, KEY_ESCAPE }, + { SDLK_BACKSPACE, KEY_BACKSPACE }, + { SDLK_TAB, KEY_TAB }, + { SDLK_SPACE, KEY_SPACE }, + { SDLK_EXCLAIM, KEY_EXCLAIM }, + { SDLK_QUOTEDBL, KEY_DOUBLE_QUOTE }, + { SDLK_HASH, KEY_HASH }, + { SDLK_PERCENT, KEY_PERCENT }, + { SDLK_DOLLAR, KEY_DOLLAR }, + { SDLK_AMPERSAND, KEY_AMPERSAND }, + { SDLK_QUOTE, KEY_QUOTE }, + { SDLK_LEFTPAREN, KEY_LEFT_PAREN }, + { SDLK_RIGHTPAREN, KEY_RIGHT_PAREN }, + { SDLK_ASTERISK, KEY_ASTERISK }, + { SDLK_PLUS, KEY_PLUS }, + { SDLK_COMMA, KEY_COMMA }, + { SDLK_MINUS, KEY_MINUS }, + { SDLK_PERIOD, KEY_PERIOD }, + { SDLK_SLASH, KEY_SLASH }, + { SDLK_0, KEY_0 }, + { SDLK_1, KEY_1 }, + { SDLK_2, KEY_2 }, + { SDLK_3, KEY_3 }, + { SDLK_4, KEY_4 }, + { SDLK_5, KEY_5 }, + { SDLK_6, KEY_6 }, + { SDLK_7, KEY_7 }, + { SDLK_8, KEY_8 }, + { SDLK_9, KEY_9 }, + { SDLK_COLON, KEY_COLON }, + { SDLK_SEMICOLON, KEY_SEMICOLON }, + { SDLK_LESS, KEY_LESS }, + { SDLK_EQUALS, KEY_EQUALS }, + { SDLK_GREATER, KEY_GREATER }, + { SDLK_QUESTION, KEY_QUESTION }, + { SDLK_AT, KEY_AT }, + { SDLK_LEFTBRACKET, KEY_LEFT_BRACKET }, + { SDLK_BACKSLASH, KEY_BACKSLASH }, + { SDLK_RIGHTBRACKET, KEY_RIGHT_BRACKET }, + { SDLK_CARET, KEY_CARET }, + { SDLK_UNDERSCORE, KEY_UNDERSCORE }, + { SDLK_BACKQUOTE, KEY_BACKQUOTE }, + { SDLK_a, KEY_a }, + { SDLK_b, KEY_b }, + { SDLK_c, KEY_c }, + { SDLK_d, KEY_d }, + { SDLK_e, KEY_e }, + { SDLK_f, KEY_f }, + { SDLK_g, KEY_g }, + { SDLK_h, KEY_h }, + { SDLK_i, KEY_i }, + { SDLK_j, KEY_j }, + { SDLK_k, KEY_k }, + { SDLK_l, KEY_l }, + { SDLK_m, KEY_m }, + { SDLK_n, KEY_n }, + { SDLK_o, KEY_o }, + { SDLK_p, KEY_p }, + { SDLK_q, KEY_q }, + { SDLK_r, KEY_r }, + { SDLK_s, KEY_s }, + { SDLK_t, KEY_t }, + { SDLK_u, KEY_u }, + { SDLK_v, KEY_v }, + { SDLK_w, KEY_w }, + { SDLK_x, KEY_x }, + { SDLK_y, KEY_y }, + { SDLK_z, KEY_z }, + { SDLK_CAPSLOCK, KEY_CAPSLOCK }, + { SDLK_F1, KEY_F1 }, + { SDLK_F2, KEY_F2 }, + { SDLK_F3, KEY_F3 }, + { SDLK_F4, KEY_F4 }, + { SDLK_F5, KEY_F5 }, + { SDLK_F6, KEY_F6 }, + { SDLK_F7, KEY_F7 }, + { SDLK_F8, KEY_F8 }, + { SDLK_F9, KEY_F9 }, + { SDLK_F10, KEY_F10 }, + { SDLK_F11, KEY_F11 }, + { SDLK_F12, KEY_F12 }, + { SDLK_F13, KEY_F13 }, + { SDLK_F14, KEY_F14 }, + { SDLK_F15, KEY_F15 }, + { SDLK_F16, KEY_F16 }, + { SDLK_F17, KEY_F17 }, + { SDLK_F18, KEY_F18 }, + { SDLK_F19, KEY_F19 }, + { SDLK_F20, KEY_F20 }, + { SDLK_F21, KEY_F21 }, + { SDLK_F22, KEY_F22 }, + { SDLK_F23, KEY_F23 }, + { SDLK_F24, KEY_F24 }, + { SDLK_PRINTSCREEN, KEY_PRINTSCREEN }, + { SDLK_SCROLLLOCK, KEY_SCROLLLOCK }, + { SDLK_PAUSE, KEY_PAUSE }, + { SDLK_INSERT, KEY_INSERT }, + { SDLK_HOME, KEY_HOME }, + { SDLK_PAGEUP, KEY_PAGEUP }, + { SDLK_DELETE, KEY_DELETE }, + { SDLK_END, KEY_END }, + { SDLK_PAGEDOWN, KEY_PAGEDOWN }, + { SDLK_RIGHT, KEY_RIGHT }, + { SDLK_LEFT, KEY_LEFT }, + { SDLK_DOWN, KEY_DOWN }, + { SDLK_UP, KEY_UP }, + { SDLK_KP_DIVIDE, KEY_KP_DIVIDE }, + { SDLK_KP_MULTIPLY, KEY_KP_MULTIPLY }, + { SDLK_KP_MINUS, KEY_KP_MINUS }, + { SDLK_KP_PLUS, KEY_KP_PLUS }, + { SDLK_KP_ENTER, KEY_KP_ENTER }, + { SDLK_KP_1, KEY_KP_1 }, + { SDLK_KP_2, KEY_KP_2 }, + { SDLK_KP_3, KEY_KP_3 }, + { SDLK_KP_4, KEY_KP_4 }, + { SDLK_KP_5, KEY_KP_5 }, + { SDLK_KP_6, KEY_KP_6 }, + { SDLK_KP_7, KEY_KP_7 }, + { SDLK_KP_8, KEY_KP_8 }, + { SDLK_KP_9, KEY_KP_9 }, + { SDLK_KP_0, KEY_KP_0 }, + { SDLK_KP_PERIOD, KEY_KP_PERIOD }, + { SDLK_KP_COMMA, KEY_KP_COMMA }, + { SDLK_MENU, KEY_MENU }, + { SDLK_MUTE, KEY_MUTE }, + { SDLK_VOLUMEUP, KEY_VOLUME_UP }, + { SDLK_VOLUMEDOWN, KEY_VOLUME_DOWN }, + { SDLK_LCTRL, KEY_LCTRL }, + { SDLK_LSHIFT, KEY_LSHIFT }, + { SDLK_LALT, KEY_LALT }, + { SDLK_LGUI, KEY_LSUPER }, + { SDLK_RCTRL, KEY_RCTRL }, + { SDLK_RSHIFT, KEY_RSHIFT }, + { SDLK_RALT, KEY_RALT }, + { SDLK_RGUI, KEY_RSUPER }, + { 0, -1 } +}; + +/* Maintain with enum mouse_button constants in mouse.h */ +static const struct { + int key; + enum mouse_button value; +} buttons[] = { + { SDL_BUTTON_LEFT, MOUSE_BUTTON_LEFT }, + { SDL_BUTTON_MIDDLE, MOUSE_BUTTON_MIDDLE }, + { SDL_BUTTON_RIGHT, MOUSE_BUTTON_RIGHT }, + { -1, MOUSE_BUTTON_UNKNOWN } +}; + +static void +convert_key(const SDL_Event *event, union event *ev) +{ + ev->type = event->type == SDL_KEYDOWN ? EVENT_KEYDOWN : EVENT_KEYUP; + ev->key.key = KEY_UNKNOWN; + + for (size_t i = 0; keymap[i].key != 0; ++i) { + if (keymap[i].key == event->key.keysym.sym) { + ev->key.key = keymap[i].value; + break; + } + } +} + +static void +convert_mouse(const SDL_Event *event, union event *ev) +{ + ev->type = EVENT_MOUSE; + ev->mouse.buttons = 0; + ev->mouse.x = event->motion.x; + ev->mouse.y = event->motion.y; + + if (event->motion.state & SDL_BUTTON_LMASK) + ev->mouse.buttons |= MOUSE_BUTTON_LEFT; + if (event->motion.state & SDL_BUTTON_MMASK) + ev->mouse.buttons |= MOUSE_BUTTON_MIDDLE; + if (event->motion.state & SDL_BUTTON_RMASK) + ev->mouse.buttons |= MOUSE_BUTTON_RIGHT; +} + +static void +convert_click(const SDL_Event *event, union event *ev) +{ + ev->type = event->type == SDL_MOUSEBUTTONDOWN ? EVENT_CLICKDOWN : EVENT_CLICKUP; + ev->click.button = MOUSE_BUTTON_UNKNOWN; + ev->click.x = event->button.x; + ev->click.y = event->button.y; + + for (size_t i = 0; buttons[i].value != MOUSE_BUTTON_UNKNOWN; ++i) { + if (buttons[i].key == event->button.button) { + ev->click.button = buttons[i].value; + break; + } + } +} + +bool +event_poll(union event *ev) +{ + SDL_Event event; + + /* + * Loop until we find an event we want to report, we skip unneeded + * ones. + */ + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + ev->type = EVENT_QUIT; + return true; + case SDL_KEYDOWN: + case SDL_KEYUP: + convert_key(&event, ev); + return true; + case SDL_MOUSEMOTION: + convert_mouse(&event, ev); + return true; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + convert_click(&event, ev); + return true; + default: + continue; + } + } + + return false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/event.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,88 @@ +/* + * event.h -- event management + * + * 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_EVENT_H +#define MOLKO_EVENT_H + +/** + * \file event.h + * \brief Event management. + */ + +#include <stdbool.h> + +#include "key.h" +#include "mouse.h" + +/** + * \brief Kind of event. + */ +enum event_type { + EVENT_CLICKDOWN, /*!< Mouse click down */ + EVENT_CLICKUP, /*!< Mouse click released */ + EVENT_KEYDOWN, /*!< Single key down */ + EVENT_KEYUP, /*!< Single key released */ + EVENT_MOUSE, /*!< Mouse moved */ + EVENT_QUIT, /*!< Quit request */ +}; + +/** + * \brief Store events. + */ +union event { + enum event_type type; /*!< Which kind of event */ + + /** + * Store key down/up event. + */ + struct { + enum event_type type; /*!< EVENT_KEYDOWN or EVENT_KEYUP */ + enum key key; /*!< Which key */ + } key; + + /** + * Store mouse motion event. + */ + struct { + enum event_type type; /*!< EVENT_MOUSE */ + enum mouse_button buttons; /*!< OR'ed buttons that are pressed */ + int x; /*!< Mouse position in x */ + int y; /*!< Mouse position in y */ + } mouse; + + /** + * Store mouse click event. + */ + struct { + enum event_type type; /*!< EVENT_CLICKDOWN or EVENT_CLICKUP */ + enum mouse_button button; /*!< Unique button that was pressed */ + int x; /*!< Mouse position in x */ + int y; /*!< Mouse position in y */ + } click; +}; + +/** + * Fetch the next event or return false if there are not. + * + * \param ev the event + * \return true if the event was filled or false otherwise + */ +bool +event_poll(union event *ev); + +#endif /* !MOLKO_EVENT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/font.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,104 @@ +/* + * font.c -- basic font management + * + * 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 <stdbool.h> +#include <stdio.h> + +#include <SDL_ttf.h> + +#include "color.h" +#include "error.h" +#include "error_p.h" +#include "font.h" +#include "texture_p.h" +#include "util.h" + +struct font { + TTF_Font *handle; +}; + +struct font * +font_openf(const char *path, unsigned int size) +{ + assert(path); + + struct font *f; + + f = ecalloc(1, sizeof (struct font)); + + if (!(f->handle = TTF_OpenFont(path, size))) { + error_sdl(); + free(f); + return NULL; + } + + return f; +} + +struct font * +font_openb(const void *buffer, size_t buflen, unsigned int size) +{ + assert(buffer); + + struct font *f; + SDL_RWops *ops; + + f = ecalloc(1, sizeof (struct font)); + + if (!(ops = SDL_RWFromConstMem(buffer, buflen)) || + (!(f->handle = TTF_OpenFontRW(ops, true, size)))) { + error_sdl(); + free(f); + return NULL; + } + + return f; +} + +struct texture * +font_render(struct font *font, const char *text, unsigned long color) +{ + assert(font); + assert(text); + + SDL_Color fg = { + .r = COLOR_R(color), + .g = COLOR_G(color), + .b = COLOR_B(color), + .a = COLOR_A(color) + }; + + SDL_Surface *surface; + + if (!(surface = TTF_RenderUTF8_Blended(font->handle, text, fg))) { + error_sdl(); + return NULL; + } + + return texture_from_surface(surface); +} + +void +font_close(struct font *font) +{ + assert(font); + + TTF_CloseFont(font->handle); + free(font); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/font.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,83 @@ +/* + * font.h -- basic font management + * + * 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_FONT_H +#define MOLKO_FONT_H + +/** + * \file font.h + * \brief Basic font management. + */ + +#include <stddef.h> + +/** + * \brief Font object. + * + * This object is not publicly defined because it contains + * implementation-defined data. + */ +struct font; +struct texture; + +/** + * Open font from path file. + * + * \pre path != NULL + * \param path the path to the font + * \param size the desired size + * \return the font or NULL on error + */ +struct font * +font_openf(const char *path, unsigned int size); + +/** + * Open font from memory buffer. + * + * \pre buffer != NULL + * \param buffer the memory buffer + * \param buflen the memory buffer length + * \param size the desired size + * \warning The buffer must remain valid until font is closed + * \return the font or NULL on error + */ +struct font * +font_openb(const void *buffer, size_t buflen, unsigned int size); + +/** + * Render a text. + * + * \pre font != NULL + * \pre text != NULL + * \param font the font handle + * \param text the text in UTF-8 + * \param color the color + */ +struct texture * +font_render(struct font *font, const char *text, unsigned long color); + +/** + * Close the font. + * + * \pre font != NULL + * \param font the font handle + */ +void +font_close(struct font *font); + +#endif /* !MOLKO_FONT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/game.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,158 @@ +/* + * game.c -- main game object + * + * 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 <stddef.h> +#include <string.h> + +#include "game.h" +#include "state.h" + +struct game game = { + .state = NULL, + .state_next = NULL +}; + +static struct action * +find_empty_action(void) +{ + static struct action null; + + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) + if (memcmp(&game.actions[i], &null, sizeof (struct action)) == 0) + return &game.actions[i]; + + return NULL; +} + +static void +clear_actions(void) +{ + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) { + struct action *a = &game.actions[i]; + + /* These actions are removed on state change. */ + if (a->flags & ACTION_AUTO_LEAVE) { + if (a->finish) + a->finish(a); + + memset(a, 0, sizeof (struct action)); + } + } +} + +static void +handle_actions(const union event *event) +{ + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) + if (game.actions[i].handle) + game.actions[i].handle(&game.actions[i], event); +} + +static void +update_actions(unsigned int ticks) +{ + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) { + struct action *a = &game.actions[i]; + + if (!a->update) + continue; + + if (a->update(a, ticks)) { + if (a->finish) + a->finish(a); + + memset(&game.actions[i], 0, sizeof (struct action)); + } + } +} + +static void +draw_actions(void) +{ + for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) + if (game.actions[i].draw) + game.actions[i].draw(&game.actions[i]); +} + + +void +game_switch(struct state *state, bool quick) +{ + assert(state); + + if (quick) { + game.state = state; + game.state->enter(); + } else + game.state_next = state; +} + +void +game_handle(const union event *event) +{ + assert(event); + + if (game.state) + game.state->handle(event); + + handle_actions(event); +} + +void +game_update(unsigned int ticks) +{ + /* Change state if any. */ + if (game.state_next) { + /* Inform the current state we're gonna leave it. */ + if (game.state) + game.state->leave(); + + game.state = game.state_next; + game.state->enter(); + game.state_next = NULL; + + /* Remove any actions that must be deleted. */ + clear_actions(); + } + + if (game.state) + game.state->update(ticks); + + update_actions(ticks); +} + +void +game_draw(void) +{ + if (game.state) + game.state->draw(); + + draw_actions(); +} + +void +game_add_action(const struct action *action) +{ + assert(action); + + struct action *pos; + + if ((pos = find_empty_action())) + memcpy(pos, action, sizeof (struct action)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/game.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,105 @@ +/* + * game.h -- main game object + * + * 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_GAME_H +#define MOLKO_GAME_H + +/** + * \file game.h + * \brief Main game object. + */ + +#include <stdbool.h> + +#include "action.h" + +/** + * \brief Max number of actions allowed at the same time. + */ +#define GAME_ACTIONS_MAX 32 + +struct state; + +union event; + +/** + * \brief Main game object. + */ +struct game { + /* Game states. */ + struct state *state; /*!< (RO) Current state */ + struct state *state_next; /*!< (RO) Next state */ + + /** Array of actions. */ + struct action actions[GAME_ACTIONS_MAX]; +}; + +/** + * Global game object. + */ +extern struct game game; + +/** + * Request to change state. + * + * This function will only update state after the next \a game_update call. + * + * If quick is true, change state immediately. + * + * \pre state != NULL + * \param state the new state + * \param quick quickly change the state + */ +void +game_switch(struct state *state, bool quick); + +/** + * Handle input event. + * + * \param event the event + */ +void +game_handle(const union event *event); + +/** + * Update the game state. + * + * \param ticks the number of milliseconds between last frame + */ +void +game_update(unsigned int ticks); + +/** + * Draw the game using the current state. + */ +void +game_draw(void); + +/** + * Add an action to the game. + * + * If there are no room for the action, action is discarded. Make sure to not + * exceed the limit GAME_ACTIONS_MAX. + * + * \pre action != NULL + * \param action the action to copy + */ +void +game_add_action(const struct action *action); + +#endif /* !MOLKO_GAME_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/image.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,56 @@ +/* + * image.c -- basic image management + * + * 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 <stdbool.h> + +#include <SDL_image.h> + +#include "error_p.h" +#include "texture_p.h" + +struct texture * +image_openf(const char *path) +{ + assert(path); + + SDL_Surface *surface = IMG_Load(path); + + if (!surface) { + error_sdl(); + return NULL; + } + + return texture_from_surface(surface); +} + +struct texture * +image_openb(const void *buffer, size_t size) +{ + assert(buffer); + + SDL_RWops *ops = SDL_RWFromConstMem(buffer, size); + SDL_Surface *surface; + + if (!ops || !(surface = IMG_Load_RW(ops, true))) { + error_sdl(); + return NULL; + } + + return texture_from_surface(surface); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/image.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,52 @@ +/* + * image.h -- basic image management + * + * 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_IMAGE_H +#define MOLKO_IMAGE_H + +/** + * \file image.h + * \brief Basic image management. + */ + +#include <stddef.h> + +struct texture; + +/** + * Open a file from a path. + * + * \pre path != NULL + * \param path the path to the file + * \return the texture or NULL on error + */ +struct texture * +image_openf(const char *path); + +/** + * Open a file from a memory buffer. + * + * \pre buffer != NULL + * \param buffer the memory buffer + * \param size the memory size + * \return the texture or NULL on error + */ +struct texture * +image_openb(const void *buffer, size_t size); + +#endif /* !MOLKO_IMAGE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/key.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,190 @@ +/* + * key.h -- keyboard definitions + * + * 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_KEY_H +#define MOLKO_KEY_H + +/** + * \file key.h + * \brief Keyboard definitions. + */ + +/** + * \brief Key codes. + */ +enum key { + KEY_UNKNOWN, + KEY_ENTER, + KEY_ESCAPE, + KEY_BACKSPACE, + KEY_TAB, + KEY_SPACE, + KEY_EXCLAIM, + KEY_DOUBLE_QUOTE, + KEY_HASH, + KEY_PERCENT, + KEY_DOLLAR, + KEY_AMPERSAND, + KEY_QUOTE, + KEY_LEFT_PAREN, + KEY_RIGHT_PAREN, + KEY_ASTERISK, + KEY_PLUS, + KEY_COMMA, + KEY_MINUS, + KEY_PERIOD, + KEY_SLASH, + KEY_0, + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_COLON, + KEY_SEMICOLON, + KEY_LESS, + KEY_EQUALS, + KEY_GREATER, + KEY_QUESTION, + KEY_AT, + KEY_LEFT_BRACKET, + KEY_BACKSLASH, + KEY_RIGHT_BRACKET, + KEY_CARET, + KEY_UNDERSCORE, + KEY_BACKQUOTE, + KEY_a, + KEY_b, + KEY_c, + KEY_d, + KEY_e, + KEY_f, + KEY_g, + KEY_h, + KEY_i, + KEY_j, + KEY_k, + KEY_l, + KEY_m, + KEY_n, + KEY_o, + KEY_p, + KEY_q, + KEY_r, + KEY_s, + KEY_t, + KEY_u, + KEY_v, + KEY_w, + KEY_x, + KEY_y, + KEY_z, + KEY_CAPSLOCK, + KEY_F1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + KEY_F6, + KEY_F7, + KEY_F8, + KEY_F9, + KEY_F10, + KEY_F11, + KEY_F12, + KEY_F13, + KEY_F14, + KEY_F15, + KEY_F16, + KEY_F17, + KEY_F18, + KEY_F19, + KEY_F20, + KEY_F21, + KEY_F22, + KEY_F23, + KEY_F24, + KEY_PRINTSCREEN, + KEY_SCROLLLOCK, + KEY_PAUSE, + KEY_INSERT, + KEY_HOME, + KEY_PAGEUP, + KEY_DELETE, + KEY_END, + KEY_PAGEDOWN, + KEY_RIGHT, + KEY_LEFT, + KEY_DOWN, + KEY_UP, + KEY_NUMLOCKCLEAR, + KEY_KP_DIVIDE, + KEY_KP_MULTIPLY, + KEY_KP_MINUS, + KEY_KP_PLUS, + KEY_KP_ENTER, + KEY_KP_00, + KEY_KP_000, + KEY_KP_1, + KEY_KP_2, + KEY_KP_3, + KEY_KP_4, + KEY_KP_5, + KEY_KP_6, + KEY_KP_7, + KEY_KP_8, + KEY_KP_9, + KEY_KP_0, + KEY_KP_PERIOD, + KEY_KP_COMMA, + KEY_MENU, + KEY_MUTE, + KEY_VOLUME_UP, + KEY_VOLUME_DOWN, + KEY_LCTRL, + KEY_LSHIFT, + KEY_LALT, + KEY_LSUPER, + KEY_RCTRL, + KEY_RSHIFT, + KEY_RALT, + KEY_RSUPER, +}; + +/** + * \brief Keybord modifiers. + * + * This enumeration is usually stored as OR'ed flags as several modifiers can + * be pressed at a time. + */ +enum keymod { + KEYMOD_LSHIFT = 1 << 0, /*!< Left shift */ + KEYMOD_LCTRL = 1 << 1, /*!< Left control */ + KEYMOD_LALT = 1 << 2, /*!< Left alt */ + KEYMOD_LSUPER = 1 << 3, /*!< Left super (logo) */ + KEYMOD_RSHIFT = 1 << 4, /*!< Right shift */ + KEYMOD_RCTRL = 1 << 5, /*!< Right control */ + KEYMOD_RALT = 1 << 6, /*!< Right alt */ + KEYMOD_RSUPER = 1 << 7 /*!< Right super (logo) */ +}; + +#endif /* !MOLKO_KEY_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/map.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,225 @@ +/* + * map.c -- game map + * + * 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 "error.h" +#include "error_p.h" +#include "image.h" +#include "map.h" +#include "painter.h" +#include "sprite.h" +#include "sys.h" +#include "texture.h" +#include "window.h" + +#include <SDL.h> + +/* Create %<v>c string literal for scanf */ +#define MAX_F(v) MAX_F_(v) +#define MAX_F_(v) "%" #v "c" + +static void +parse_layer(struct map *map, const char *line, FILE *fp) +{ + char layer_name[32 + 1] = { 0 }; + struct map_layer *layer; + size_t amount, current; + + /* Determine layer. */ + if (sscanf(line, "layer|%32s", layer_name) <= 0) + return; + if (strcmp(layer_name, "background") == 0) + layer = &map->layers[0]; + else if (strcmp(layer_name, "foreground") == 0) + layer = &map->layers[1]; + else + return; + + /* Check if weight/height has been specified. */ + if (map->width == 0 || map->height == 0) + return; + + amount = map->width * map->height; + current = 0; + + if (!(layer->tiles = calloc(amount, sizeof (unsigned short)))) + return; + + for (int tile; fscanf(fp, "%d", &tile) && current < amount; ++current) + layer->tiles[current] = tile; +} + +static void +parse_tileset(struct map *map, const char *line) +{ + char filename[128 + 1] = { 0 }; + + sscanf(line, "tileset|%128s", filename); + + if (map->tilewidth == 0 || map->tileheight == 0) + return; + if (!(map->tileset = image_openf(sys_datapath("tilesets/%s", filename)))) + return; + + sprite_init(&map->sprite, map->tileset, map->tilewidth, map->tileheight); +} + +static void +parse(struct map *map, const char *line, FILE *fp) +{ + if (strncmp(line, "title", 5) == 0) + sscanf(line, "title|" MAX_F(MAP_TITLE_MAX), map->title); + else if (strncmp(line, "width", 5) == 0) + sscanf(line, "width|%u", &map->width); + else if (strncmp(line, "height", 6) == 0) + sscanf(line, "height|%u", &map->height); + else if (strncmp(line, "tilewidth", 9) == 0) + sscanf(line, "tilewidth|%hu", &map->tilewidth); + else if (strncmp(line, "tileheight", 10) == 0) + sscanf(line, "tileheight|%hu", &map->tileheight); + else if (strncmp(line, "origin", 6) == 0) + sscanf(line, "origin|%d|%d", &map->origin_x, &map->origin_y); + else if (strncmp(line, "tileset", 7) == 0) + parse_tileset(map, line); + else if (strncmp(line, "layer", 5) == 0) + parse_layer(map, line, fp); +} + +static bool +check(struct map *map) +{ + if (strlen(map->title) == 0) + return error_printf("map has no title"); + if (!map->tileset) + return error_printf("unable to open tileset"); + if (map->width == 0 || map->height == 0) + return error_printf("map has null sizes"); + if (map->tilewidth == 0 || map->tileheight == 0) + return error_printf("map has null tile sizes"); + if (!map->layers[0].tiles || !map->layers[1].tiles) + return error_printf("could not allocate data"); + + return true; +} + +static void +draw_layer(struct map *map, const struct map_layer *layer) +{ + assert(map); + assert(layer); + + int x = 0, y = 0; + + for (unsigned int r = 0; r < map->width; ++r) { + for (unsigned int c = 0; c < map->height; ++c) { + unsigned int si = r * map->width + c; + unsigned int sr = (layer->tiles[si] - 1) / map->sprite.ncols; + unsigned int sc = (layer->tiles[si] - 1) % map->sprite.nrows; + + if (layer->tiles[si] != 0) + sprite_draw(&map->sprite, sr, sc, x, y); + + x += map->tilewidth; + } + + x = 0; + y += map->tileheight; + } +} + +bool +map_open(struct map *map, const char *path) +{ + assert(map); + assert(path); + + memset(map, 0, sizeof (struct map)); + + FILE *fp = fopen(path, "r"); + char line[BUFSIZ]; + + if (!fp) + return false; + + while (fgets(line, sizeof (line), fp)) { + /* Remove \n if any */ + line[strcspn(line, "\n")] = '\0'; + parse(map, line, fp); + } + + fclose(fp); + + if (!check(map)) { + map_close(map); + return false; + } + + size_t pw = map->width * map->tilewidth; + size_t ph = map->height * map->tileheight; + + if (!(map->picture = texture_new(pw, ph))) + return error_sdl(); + + return true; +} + +void +map_draw(struct map *map, int srcx, int srcy) +{ + texture_draw_ex( + map->picture, + srcx, + srcy, + window_width(), + window_height(), + 0, + 0, + window_width(), + window_height(), + 0 + ); +} + +void +map_repaint(struct map *map) +{ + PAINTER_BEGIN(map->picture); + draw_layer(map, &map->layers[0]); + draw_layer(map, &map->layers[1]); + PAINTER_END(); +} + +void +map_close(struct map *map) +{ + assert(map); + + if (map->tileset) + texture_close(map->tileset); + if (map->picture) + texture_close(map->picture); + + free(map->layers[0].tiles); + free(map->layers[1].tiles); + + memset(map, 0, sizeof (struct map)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/map.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,107 @@ +/* + * map.h -- game map + * + * 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_MAP_H +#define MOLKO_MAP_H + +/** + * \file map.h + * \brief Game map. + */ + +#include <stdbool.h> + +#include "sprite.h" + +/** + * \brief Max title length for a map. + */ +#define MAP_TITLE_MAX 32 + +struct texture; + +/** + * \brief Map layer. + */ +struct map_layer { + unsigned short *tiles; /*!< (RO) Array of tiles, depending on the map size. */ +}; + +/** + * \brief Map object. + * + * This structure only defines the map characteristics. It does not have any + * logic and is left for game state. + */ +struct map { + char title[MAP_TITLE_MAX]; /*!< (RW) The map title */ + struct texture *tileset; /*!< (RW) Tileset to use */ + struct texture *picture; /*!< (RO) Map drawn into a picture */ + struct sprite sprite; /*!< (RO) Sprite to render */ + int origin_x; /*!< (RO) Where the player starts in X */ + int origin_y; /*!< (RO) Where the player starts in Y */ + unsigned int width; /*!< (RO) Map width in cells */ + unsigned int height; /*!< (RO) Map height in cells */ + unsigned short tilewidth; /*!< (RO) Pixels per cell (width) */ + unsigned short tileheight; /*!< (RO) Pixels per cell (height) */ + struct map_layer layers[2]; /*!< (RO) Layers (background, foreground) */ +}; + +/** + * Open a map. + * + * \pre map != NULL + * \pre path != NULL + * \param map the map to fill + * \param path the path to the map + * \return true if successfully loaded + */ +bool +map_open(struct map *map, const char *path); + +/** + * Render a map. + * + * \pre map != NULL + * \param map the map to render + * \param srcx the x coordinate region + * \param srcy the y coordinate region + */ +void +map_draw(struct map *map, int srcx, int srcy); + +/** + * Force map repaint on its texture. + * + * \pre map != NULL + * \param map the map to repaint + * \warning This function does not render anything on the screen + */ +void +map_repaint(struct map *map); + +/** + * Close the map and its resources. + * + * \pre map != NULL + * \param map the map to render + */ +void +map_close(struct map *map); + +#endif /* !MOLKO_MAP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/map_state.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,341 @@ +/* + * map_state.c -- state when player is on a map + * + * 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 "event.h" +#include "game.h" +#include "map.h" +#include "map_state.h" +#include "painter.h" +#include "state.h" +#include "texture.h" +#include "walksprite.h" +#include "window.h" + +/* + * This is the speed the player moves on the map. + * + * SPEED represents the number of pixels it must move per SEC. + * SEC simply represends the number of milliseconds in one second. + */ +#define SPEED 100 +#define SEC 1000 + +/* + * Those are margins within the edge of the screen. The camera always try to + * keep those padding between the player and the screen. + */ +#define MARGIN_WIDTH 80 +#define MARGIN_HEIGHT 80 + +/* + * This structure defines the possible movement of the player as flags since + * it's possible to make diagonal movements. + */ +enum movement { + MOVING_UP = 1 << 0, + MOVING_RIGHT = 1 << 1, + MOVING_DOWN = 1 << 2, + MOVING_LEFT = 1 << 3 +}; + +/* + * A bit of explanation within this array. The structure walksprite requires + * an orientation between 0-7 depending on the user direction. + * + * Since keys for moving the character may be pressed at the same time, we need + * a conversion table from "key pressed" to "orientation". + * + * When an orientation is impossible, it is set to -1. Example, when both left + * and right are pressed. + * + * MOVING_UP = 0001 = 0x1 + * MOVING_RIGHT = 0010 = 0x2 + * MOVING_DOWN = 0100 = 0x3 + * MOVING_LEFT = 1000 = 0x4 + */ +static unsigned int orientations[16] = { + [0x1] = 0, + [0x2] = 2, + [0x3] = 1, + [0x4] = 4, + [0x6] = 3, + [0x8] = 6, + [0x9] = 7, + [0xC] = 5 +}; + +/* + * Additional data that is not necessary to expose in map_state_data. + */ +static struct { + struct { + enum movement moving; + struct walksprite ws; + } player; + + struct { + int x; + int y; + unsigned int w; + unsigned int h; + } margin; +} cache; + +static void +center(void) +{ + map_state_data.view.x = map_state_data.player.x - (map_state_data.view.w / 2); + map_state_data.view.y = map_state_data.player.y - (map_state_data.view.h / 2); + + if (map_state_data.view.x < 0) + map_state_data.view.x = 0; + else if ((unsigned int)map_state_data.view.x > map_state_data.map.w - map_state_data.view.w) + map_state_data.view.x = map_state_data.map.w - map_state_data.view.w; + + if (map_state_data.view.y < 0) + map_state_data.view.y = 0; + else if ((unsigned int)map_state_data.view.y > map_state_data.map.h - map_state_data.view.h) + map_state_data.view.y = map_state_data.map.h - map_state_data.view.h; +} + +static void +enter(void) +{ + /* Adjust map properties. */ + struct map *m = &map_state_data.map.map; + + if (!m->picture) + map_repaint(m); + + map_repaint(m); + map_state_data.map.w = texture_width(m->picture); + map_state_data.map.h = texture_height(m->picture); + + /* Adjust view. */ + map_state_data.view.w = window_width(); + map_state_data.view.h = window_height(); + + /* Adjust margin. */ + cache.margin.w = map_state_data.view.w - (MARGIN_WIDTH * 2); + cache.margin.h = map_state_data.view.h - (MARGIN_HEIGHT * 2); + + /* Center the view by default. */ + center(); + + /* Final bits. */ + walksprite_init(&cache.player.ws, &map_state_data.player.sprite, 300); +} + +static void +leave(void) +{ +} + +static void +handle_keydown(const union event *event) +{ + switch (event->key.key) { + case KEY_UP: + cache.player.moving |= MOVING_UP; + break; + case KEY_RIGHT: + cache.player.moving |= MOVING_RIGHT; + break; + case KEY_DOWN: + cache.player.moving |= MOVING_DOWN; + break; + case KEY_LEFT: + cache.player.moving |= MOVING_LEFT; + break; + default: + break; + } + + map_state_data.player.angle = orientations[cache.player.moving]; +} + +static void +handle_keyup(const union event *event) +{ + switch (event->key.key) { + case KEY_UP: + cache.player.moving &= ~(MOVING_UP); + break; + case KEY_RIGHT: + cache.player.moving &= ~(MOVING_RIGHT); + break; + case KEY_DOWN: + cache.player.moving &= ~(MOVING_DOWN); + break; + case KEY_LEFT: + cache.player.moving &= ~(MOVING_LEFT); + break; + default: + break; + } +} + +static void +move_right(unsigned int delta) +{ + map_state_data.player.x += delta; + + if (map_state_data.player.x > (int)(cache.margin.x + cache.margin.w)) { + map_state_data.view.x = (map_state_data.player.x - map_state_data.view.w) + MARGIN_WIDTH; + + if (map_state_data.view.x >= (int)(map_state_data.map.w - map_state_data.view.w)) + map_state_data.view.x = map_state_data.map.w - map_state_data.view.w; + } + + if (map_state_data.player.x > (int)map_state_data.map.w - 48) + map_state_data.player.x = map_state_data.map.w - 48; +} + +static void +move_left(unsigned int delta) +{ + map_state_data.player.x -= delta; + + if (map_state_data.player.x < cache.margin.x) { + map_state_data.view.x = map_state_data.player.x - MARGIN_WIDTH; + + if (map_state_data.view.x < 0) + map_state_data.view.x = 0; + } + + if (map_state_data.player.x < 0) + map_state_data.player.x = 0; +} + +static void +move_down(unsigned int delta) +{ + map_state_data.player.y += delta; + + if (map_state_data.player.y > (int)(cache.margin.y + cache.margin.h)) { + map_state_data.view.y = (map_state_data.player.y - map_state_data.view.h) + MARGIN_HEIGHT; + + if (map_state_data.view.y >= (int)(map_state_data.map.h - map_state_data.view.h)) + map_state_data.view.y = map_state_data.map.h - map_state_data.view.h; + } + + if (map_state_data.player.y > (int)map_state_data.map.h - 48) + map_state_data.player.y = map_state_data.map.h - 48; +} + +static void +move_up(unsigned int delta) +{ + map_state_data.player.y -= delta; + + if (map_state_data.player.y < cache.margin.y) { + map_state_data.view.y = map_state_data.player.y - MARGIN_HEIGHT; + + if (map_state_data.view.y < 0) + map_state_data.view.y = 0; + } + + if (map_state_data.player.y < 0) + map_state_data.player.y = 0; +} + +static void +move(unsigned int ticks) +{ + /* This is the amount of pixels the player must move. */ + const int delta = SPEED * ticks / SEC; + + /* This is the rectangle within the view where users must be. */ + cache.margin.x = map_state_data.view.x + MARGIN_WIDTH; + cache.margin.y = map_state_data.view.y + MARGIN_HEIGHT; + + int dx = 0; + int dy = 0; + + if (cache.player.moving == 0) + return; + + if (cache.player.moving & MOVING_UP) + dy = -1; + if (cache.player.moving & MOVING_DOWN) + dy = 1; + if (cache.player.moving & MOVING_LEFT) + dx = -1; + if (cache.player.moving & MOVING_RIGHT) + dx = 1; + + /* Move the player and adjust view if needed. */ + if (dx > 0) + move_right(delta); + else if (dx < 0) + move_left(delta); + + if (dy > 0) + move_down(delta); + else if (dy < 0) + move_up(delta); + + walksprite_update(&cache.player.ws, ticks); +} + +static void +handle(const union event *event) +{ + switch (event->type) { + case EVENT_KEYDOWN: + handle_keydown(event); + break; + case EVENT_KEYUP: + handle_keyup(event); + break; + default: + break; + } +} + +static void +update(unsigned int ticks) +{ + move(ticks); +} + +static void +draw(void) +{ + painter_set_color(0x000000ff); + painter_clear(); + map_draw(&map_state_data.map.map, map_state_data.view.x, map_state_data.view.y); + walksprite_draw( + &cache.player.ws, + map_state_data.player.angle, + map_state_data.player.x - map_state_data.view.x, + map_state_data.player.y - map_state_data.view.y); + painter_present(); +} + +struct map_state_data map_state_data; + +struct state map_state = { + .enter = enter, + .leave = leave, + .update = update, + .handle = handle, + .draw = draw +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/map_state.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,74 @@ +/* + * map_state.h -- state when player is on a map + * + * 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_MAP_STATE_H +#define MOLKO_MAP_STATE_H + +/** + * \file map_state.h + * \brief State when player is on a map. + */ + +#include "map.h" +#include "sprite.h" + +/** + * \brief Data for the state. + * + * Update this structure before switching to this state. + */ +extern struct map_state_data { + /** + * Map properties. + */ + struct { + struct map map; /*!< (RO) The map definition */ + unsigned int w; /*!< (RO) Map width */ + unsigned int h; /*!< (RO) Map height */ + } map; + + /** + * Player position. + * + * If you adjust this structure, it is strictly encouraged to update + * the view as well. + */ + struct { + struct sprite sprite; /*!< (RW) The sprite to use */ + int x; /*!< (RO) Player position in x */ + int y; /*!< (RO) Player position in y */ + int angle; /*!< (RO) Player angle (see walksprite) */ + } player; + + /** + * Position and size of the view. + */ + struct { + int x; /*!< (RW) Position in x */ + int y; /*!< (RW) Position in y */ + unsigned int w; /*!< (RO) View width */ + unsigned int h; /*!< (RO) View height */ + } view; +} map_state_data; /*!< Access to data. */ + +/** + * \brief State when player is on a map. + */ +extern struct state map_state; + +#endif /* !MOLKO_MAP_STATE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/message.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,101 @@ +/* + * message.c -- message 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 <assert.h> + +#include "font.h" +#include "message.h" +#include "painter.h" +#include "sprite.h" +#include "texture.h" + +#define MESSAGE_SPEED 1000 /* Time delay for animations */ +#define MESSAGE_TIMEOUT 5000 /* Time for auto-closing */ + +void +message_start(struct message *msg) +{ + assert(msg); + + msg->elapsed = 0; + msg->state = MESSAGE_OPENING; +} + +void +message_update(struct message *msg, unsigned int ticks) +{ + assert(msg); + + msg->elapsed += ticks; + + switch (msg->state) { + case MESSAGE_OPENING: + if (msg->elapsed >= MESSAGE_SPEED) + msg->state = MESSAGE_SHOWING; + break; + case MESSAGE_SHOWING: + /* Do automatically switch state if requested by the user. */ + if (msg->flags & MESSAGE_AUTOMATIC && msg->elapsed >= MESSAGE_TIMEOUT) + msg->state = MESSAGE_HIDING; + + break; + default: + break; + } +} + +void +message_draw(struct message *msg) +{ + assert(msg); + + /* TODO: more constant variables. */ + struct texture *lines[3]; + int x = 160; + int y = 80; + + painter_set_color(0xff0000ff); + painter_draw_rectangle(true, x, y, 960, 160); + + for (int i = 0; msg->text[i]; ++i) { + lines[i] = font_render(msg->font, msg->text[i], 0xffffffff); + + if (!lines[i]) + continue; + + texture_draw(lines[i], x, y); + texture_close(lines[i]); + y += 53; + } +} + +void +message_hide(struct message *msg) +{ + assert(msg); + + msg->elapsed = 0; +} + +bool +message_is_complete(struct message *msg) +{ + assert(msg); + + return msg->state == MESSAGE_HIDING && msg->elapsed >= MESSAGE_SPEED; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/message.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,110 @@ +/* + * message.h -- message 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. + */ + +#ifndef MOLKO_MESSAGE_H +#define MOLKO_MESSAGE_H + +/** + * \file message.h + * \brief Message dialog. + */ + +#include <stdbool.h> + +struct sprite; +struct font; + +/** + * \brief Message flags. + */ +enum message_flags { + MESSAGE_AUTOMATIC = (1 << 0) /*!< Message will automatically close */ +}; + +/** + * \brief Message state. + */ +enum message_state { + MESSAGE_OPENING, /*!< Message animation is opening */ + MESSAGE_SHOWING, /*!< Message is displaying */ + MESSAGE_HIDING /*!< Message animation for hiding */ +}; + +/** + * \brief Message object. + */ +struct message { + const char *text[3]; /*!< (RW) lines of text to show */ + struct sprite *theme; /*!< (RW) sprite to use for the frame */ + struct texture *avatar; /*!< (RW) optional avatar */ + struct font *font; /*!< (RW) font to use */ + enum message_flags flags; /*!< (RW) message flags */ + enum message_state state; /*!< (RO) current state */ + unsigned int elapsed; /*!< (RW) elapsed time while displaying */ +}; + +/** + * Start opening the message. This function will reset the message state and + * elapsed time. + * + * \pre msg != NULL + * \param msg the message + */ +void +message_start(struct message *msg); + +/** + * Update the message state and elapsed time.. + * + * \pre msg != NULL + * \param msg the message + * \param ticks the elapsed delay since last frame + */ +void +message_update(struct message *msg, unsigned int ticks); + +/** + * Draw the message into the screen. + * + * \pre msg != NULL + * \param msg the message + */ +void +message_draw(struct message *msg); + +/** + * Start hiding the message. + * + * \pre msg != NULL + * \param msg the message + * \note You should still continue to draw the message as the animation is not + * finished! + */ +void +message_hide(struct message *msg); + +/** + * Tells if the message is complete. + * + * \pre msg != NULL + * \param msg the message + */ +bool +message_is_complete(struct message *msg); + +#endif /* !MOLKO_MESSAGE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/mouse.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,42 @@ +/* + * mouse.h -- mouse definitions + * + * 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_MOUSE_H +#define MOLKO_MOUSE_H + +/** + * \file mouse.h + * \brief Mouse definitions. + */ + +/** + * \brief Buttons from mouse. + * + * This enumeration is used as both flags or constants. For example when the + * user press one button on the mouse it generates one constant event. On the + * other hand, while moving the mouse the user may have one or more buttons + * pressed, thus the OR'ed combination. + */ +enum mouse_button { + MOUSE_BUTTON_UNKNOWN = 0, /*!< No buttons pressed */ + MOUSE_BUTTON_LEFT = (1 << 0), /*!< Left button pressed */ + MOUSE_BUTTON_MIDDLE = (1 << 1), /*!< Middle button pressed */ + MOUSE_BUTTON_RIGHT = (1 << 2) /*!< Right button pressed */ +}; + +#endif /* !MOLKO_MOUSE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/painter.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,99 @@ +/* + * painter.c -- basic drawing routines + * + * 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 "color.h" +#include "painter.h" +#include "texture_p.h" +#include "window_p.h" + +static struct texture *renderer; + +struct texture * +painter_get_target(void) +{ + return renderer; +} + +void +painter_set_target(struct texture *tex) +{ + renderer = tex; + SDL_SetRenderTarget(win.renderer, tex ? tex->handle : NULL); +} + +unsigned long +painter_get_color(void) +{ + Uint8 r = 0, g = 0, b = 0, a = 0; + + SDL_GetRenderDrawColor(win.renderer, &r, &g, &b, &a); + + return COLOR_HEX(r, g, b, a); +} + +void +painter_set_color(unsigned long color) +{ + SDL_SetRenderDrawColor( + win.renderer, + COLOR_R(color), + COLOR_G(color), + COLOR_B(color), + COLOR_A(color) + ); +} + +void +painter_draw_line(int x1, int y1, int x2, int y2) +{ + SDL_RenderDrawLine(win.renderer, x1, y1, x2, y2); +} + +void +painter_draw_point(int x1, int y1) +{ + SDL_RenderDrawPoint(win.renderer, x1, y1); +} + +void +painter_draw_rectangle(bool fill, int x, int y, unsigned int width, unsigned int height) +{ + const SDL_Rect rect = { + .w = width, + .h = height, + .x = x, + .y = y + }; + + if (fill) + SDL_RenderFillRect(win.renderer, &rect); + else + SDL_RenderDrawRect(win.renderer, &rect); +} + +void +painter_clear(void) +{ + SDL_RenderClear(win.renderer); +} + +void +painter_present(void) +{ + SDL_RenderPresent(win.renderer); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/painter.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,140 @@ +/* + * painter.h -- basic drawing routines + * + * 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_PAINTER_H +#define MOLKO_PAINTER_H + +/** + * \file painter.h + * \brief Basic drawing routines. + */ + +#include <stdbool.h> + +struct texture; + +/** + * Give the current texture being used for rendering, maybe NULL if the + * rendering is on root. + * + * \return texture or NULL + */ +struct texture * +painter_get_target(void); + +/** + * Set the rendering context to the given texture. + * + * Since this function change an internal global variable it is strongly + * encouraged to store a local backup of the current texture using \a + * painter_get_target and call this function with it afterwards. + * + * If texture is NULL, use default context aka the window. + * + * \param tex the texture + * \see PAINTER_BEGIN + * \see PAINTER_END + */ +void +painter_set_target(struct texture *tex); + +/** + * Get the current drawing color. + * + * \return the color in RRGGBBAA format + */ +unsigned long +painter_get_color(void); + +/** + * Set the rendering drawing color. + * + * \param color in RRGGBBAA format + */ +void +painter_set_color(unsigned long color); + +/** + * Draw a line. + * + * \param x1 first X coordinate + * \param y1 first Y coordinate + * \param x2 second X coordinate + * \param y2 second Y coordinate + */ +void +painter_draw_line(int x1, int y1, int x2, int y2); + +/** + * Draw a pixel point. + * + * \param x the X coordinate + * \param y the Y coordinate + */ +void +painter_draw_point(int x, int y); + +/** + * Draw a rectangle + * + * \param fill set to true to fill the rectangle + * \param x the X coordinate + * \param y the Y coordinate + * \param w the rectangle width + * \param h the rectangle height + */ +void +painter_draw_rectangle(bool fill, int x, int y, unsigned int w, unsigned int h); + +/** + * Clear the window. + */ +void +painter_clear(void); + +/** + * Present the window, only call this function one time in the main loop. + */ +void +painter_present(void); + +/** + * Use this macro to start painting on the texture to store the current + * rendering context and put it back afterwards. + * + * \pre tex != NULL + * \param tex the texture to use + * \see PAINTER_END + */ +#define PAINTER_BEGIN(tex ) \ +do { \ + struct texture *__current_texture__; \ + \ + __current_texture__ = painter_get_target(); \ + painter_set_target((tex)) + +/** + * Use this macro at the end of rendering into a given texture. + * + * \see PAINTER_BEGIN + */ +#define PAINTER_END() \ + painter_set_target(__current_texture__); \ +} while (0) + +#endif /* !MOLKO_PAINTER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/sprite.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,64 @@ +/* + * sprite.c -- image 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 <assert.h> + +#include "sprite.h" +#include "texture_p.h" +#include "texture.h" + +void +sprite_init(struct sprite *sprite, + struct texture *tex, + unsigned int cellw, + unsigned int cellh) +{ + int w = 0; + int h = 0; + + assert(sprite); + assert(tex); + + /* TODO: use texture_get_size */ + SDL_QueryTexture(tex->handle, NULL, NULL, &w, &h); + + sprite->texture = tex; + sprite->cellw = cellw; + sprite->cellh = cellh; + sprite->nrows = h / cellh; + sprite->ncols = w / cellw; +} + +void +sprite_draw(struct sprite *sprite, unsigned int r, unsigned int c, int x, int y) +{ + assert(sprite); + + texture_draw_ex( + sprite->texture, + c * sprite->cellw, /* src y */ + r * sprite->cellh, /* src x */ + sprite->cellw, /* src width */ + sprite->cellh, /* src height */ + x, /* dst x */ + y, /* dst y */ + sprite->cellw, /* dst width */ + sprite->cellh, /* dst height */ + 0.0 /* angle */ + ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/sprite.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,79 @@ +/* + * sprite.h -- image 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. + */ + +#ifndef MOLKO_SPRITE_H +#define MOLKO_SPRITE_H + +/** + * \file sprite.h + * \brief Image sprites. + */ + +struct texture; + +/** + * \brief Sprite structure. + */ +struct sprite { + struct texture *texture; /*!< Texture to access (RO) */ + unsigned int cellw; /*!< Width per cell (RW) */ + unsigned int cellh; /*!< Height per cell (RW) */ + unsigned int nrows; /*!< Number of rows (RW) */ + unsigned int ncols; /*!< Number of columns (RW) */ +}; + +/** + * Initialize a sprite. + * + * The sprite does not take ownership of texture and must be valid until the + * sprite is no longer used. + * + * This function is only provided as convenience, user may initialize the + * sprite by itself if wanted. + * + * The fields `nrows' and `ncols' will be determined automatically from the + * texture size. + * + * \pre sprite != NULL + * \pre tex != NULL + * \param sprite the sprite to initialize + * \param tex the texture + * \param cellw the width per cell in pixels + * \param cellh the height per cell in pixels + */ +void +sprite_init(struct sprite *sprite, + struct texture *tex, + unsigned int cellw, + unsigned int cellh); + +/** + * Draw the sprite component from row `r' and column `c'. + * + * \pre sprite != NULL + * \param sprite the sprite to draw + * \param r the row number + * \param c the column number + * \param x the X destination + * \param y the Y destination + * \warning No bounds checking + */ +void +sprite_draw(struct sprite *sprite, unsigned int r, unsigned int c, int x, int y); + +#endif /* !MOLKO_SPRITE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/state.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,60 @@ +/* + * state.h -- abstract state + * + * 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_STATE_H +#define MOLKO_STATE_H + +/** + * \file state.h + * \brief Abstract state. + */ + +union event; + +/** + * \brief Abstract state. + */ +struct state { + /** + * This function is called when the state is entered. + */ + void (*enter)(void); + + /** + * This function is called when the state is about to be left. + */ + void (*leave)(void); + + /** + * This function is called for each event that happened. + */ + void (*handle)(const union event *); + + /** + * This function is called to update the game, with the number of + * milliseconds since the last frame. + */ + void (*update)(unsigned int ticks); + + /** + * This function is supposed to draw the game. + */ + void (*draw)(void); +}; + +#endif /* !MOLKO_STATE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/sys.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,162 @@ +/* + * sys.c -- system routines + * + * 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 <SDL.h> +#include <SDL_image.h> +#include <SDL_mixer.h> +#include <SDL_ttf.h> + +#if !defined(_WIN32) /* Assuming POSIX */ +# include <sys/types.h> +# include <dirent.h> +#endif + +#include "error.h" +#include "error_p.h" +#include "sys.h" + +#if defined(_WIN32) + +static void +determine(char path[], size_t pathlen) +{ + char *base = SDL_GetBasePath(); + + /* On Windows, the data hierarchy is the same as the project. */ + snprintf(path, pathlen, "%sassets", base); + SDL_free(base); +} + +#else /* Assuming POSIX */ + +static bool +is_absolute(const char *path) +{ + assert(path); + + return path[0] == '/'; +} + +static void +determine(char path[], size_t pathlen) +{ + char localassets[FILENAME_MAX]; + char *base = SDL_GetBasePath(); + DIR *dp; + + /* Try assets directory where executable lives. */ + snprintf(localassets, sizeof (localassets), "%sassets", base); + + if ((dp = opendir(localassets))) { + snprintf(path, pathlen, "%sassets", base); + closedir(dp); + } else { + /* We are not in the project source directory. */ + if (is_absolute(SHAREDIR)) { + /* SHAREDIR is absolute */ + snprintf(path, pathlen, "%s/molko", SHAREDIR); + } else if (is_absolute(BINDIR)) { + /* SHAREDIR is relative but BINDIR is absolute */ + snprintf(path, pathlen, "%s/%s/molko", PREFIX, SHAREDIR); + } else { + /* SHAREDIR, BINDIR are both relative */ + char *ptr = strstr(base, BINDIR); + + if (ptr) { + *ptr = '\0'; + snprintf(path, pathlen, "%s%s/molko", base, SHAREDIR); + } else { + /* Unable to determine. */ + snprintf(path, pathlen, "."); + } + } + } + + SDL_free(base); +} + +#endif + +bool +sys_init(void) +{ +#if defined(__MINGW64__) + /* On MinGW buffering leads to painful debugging. */ + setvbuf(stdout, NULL, _IONBF, 0); +#endif + + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) + return error_sdl(); + if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) + return error_sdl(); + if (TTF_Init() < 0) + return error_sdl(); + if (Mix_Init(MIX_INIT_OGG) != MIX_INIT_OGG) + return error_sdl(); + + return true; +} + +const char * +sys_datadir(void) +{ + static char path[1024]; + + if (path[0] == '\0') + determine(path, sizeof (path)); + + return path; +} + +const char * +sys_datapath(const char *fmt, ...) +{ + const char *ret; + va_list ap; + + va_start(ap, fmt); + ret = sys_datapathv(fmt, ap); + va_end(ap); + + return ret; +} + +const char * +sys_datapathv(const char *fmt, va_list ap) +{ + static char path[2048 + FILENAME_MAX]; + char filename[FILENAME_MAX]; + + vsnprintf(filename, sizeof (filename), fmt, ap); + snprintf(path, sizeof (path), "%s/%s", sys_datadir(), filename); + + return path; +} + +void +sys_close(void) +{ + Mix_Quit(); + TTF_Quit(); + IMG_Quit(); + SDL_Quit(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/sys.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,71 @@ +/* + * sys.h -- system routines + * + * 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_SYS_H +#define MOLKO_SYS_H + +/** + * \file sys.h + * \brief System routines. + */ + +#include <stdarg.h> +#include <stdbool.h> + +/** + * Initialize the system, should be called in the beginning of the main. + */ +bool +sys_init(void); + +/** + * Get the base system directory path. + * + * \return the path where the executable lives + */ +const char * +sys_datadir(void); + +/** + * Construct path to assets directory using printf-like format. + * + * \param fmt the format string + * \return the path to the file + * \note This function returns pointer to static string. + */ +const char * +sys_datapath(const char *fmt, ...); + +/** + * Similar to \a sys_datapath. + * + * \param fmt the format string + * \param ap the variadic arguments pointer + * \return the path to the file + * \note This function returns pointer to static string. + */ +const char * +sys_datapathv(const char *fmt, va_list ap); + +/** + * Close the system. + */ +void +sys_close(void); + +#endif /* !MOLKO_SYS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/texture.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,139 @@ +/* + * texture.c -- basic texture management + * + * 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 "error.h" +#include "error_p.h" +#include "texture.h" +#include "texture_p.h" +#include "util.h" +#include "window_p.h" + +struct texture * +texture_new(unsigned int w, unsigned int h) +{ + struct texture *tex = emalloc(sizeof (struct texture)); + + if (!(tex->handle = SDL_CreateTexture(win.renderer, + SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h))) { + error_sdl(); + free(tex); + return NULL; + } + + return tex; +} + +unsigned int +texture_width(struct texture *tex) +{ + assert(tex); + + int width; + + if (SDL_QueryTexture(tex->handle, NULL, NULL, &width, NULL) < 0) + return 0; + + return width; +} + +unsigned int +texture_height(struct texture *tex) +{ + assert(tex); + + int height; + + if (SDL_QueryTexture(tex->handle, NULL, NULL, NULL, &height) < 0) + return 0; + + return height; +} + +void +texture_draw(struct texture *tex, int x, int y) +{ + SDL_Rect dst = { + .x = x, + .y = y, + .w = 0, + .h = 0 + }; + + assert(tex); + + /* We need to determine size */ + SDL_QueryTexture(tex->handle, NULL, NULL, &dst.w, &dst.h); + SDL_RenderCopy(win.renderer, tex->handle, NULL, &dst); +} + +void +texture_draw_ex(struct texture *tex, + int src_x, + int src_y, + unsigned src_w, + unsigned src_h, + int dst_x, + int dst_y, + unsigned dst_w, + unsigned dst_h, + double angle) +{ + const SDL_Rect src = { + .x = src_x, + .y = src_y, + .w = src_w, + .h = src_h + }; + const SDL_Rect dst = { + .x = dst_x, + .y = dst_y, + .w = dst_w, + .h = dst_h + }; + + SDL_RenderCopyEx(win.renderer, tex->handle, &src, &dst, angle, NULL, SDL_FLIP_NONE); +} + +void +texture_close(struct texture *tex) +{ + assert(tex); + + SDL_DestroyTexture(tex->handle); + free(tex); +} + +/* private */ + +struct texture * +texture_from_surface(SDL_Surface *surface) +{ + assert(surface); + + struct texture *texture = ecalloc(1, sizeof (struct texture)); + + if (!(texture->handle = SDL_CreateTextureFromSurface(win.renderer, surface))) { + error_sdl(); + free(texture); + return NULL; + } + + return texture; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/texture.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,116 @@ +/* + * texture.h -- basic texture management + * + * 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_TEXTURE_H +#define MOLKO_TEXTURE_H + +/** + * \file texture.h + * \brief Basic texture management. + * + * See also \a image.h for usage of textures. + */ + +#include <stdbool.h> + +/** + * \brief Texture object. + * + * This object is not publicly defined because it contains + * implementation-defined data. + */ +struct texture; + +/** + * Create a new texture. + * + * \param w the width + * \param h the height + * \return the texture or NULL on error + */ +struct texture * +texture_new(unsigned int w, unsigned int h); + +/** + * Get texture width. + * + * \pre tex != NULL + * \param tex the texture + * \return the width + */ +unsigned int +texture_width(struct texture *tex); + +/** + * Get texture height. + * + * \pre tex != NULL + * \param tex the texture + * \return the height + */ +unsigned int +texture_height(struct texture *tex); + +/** + * Simple texture drawing. + * + * \pre tex != NULL + * \param tex the texture + * \param x the X coordinate + * \param y the Y coordinate + */ +void +texture_draw(struct texture *tex, int x, int y); + +/** + * Advanced texture drawing. + * + * \pre tex != NULL + * \param tex the texture + * \param src_x the source rectangle X coordinate + * \param src_y the source rectangle Y coordinate + * \param src_w the source rectangle width + * \param src_h the source rectangle height + * \param dst_x the destination rectangle X coordinate + * \param dst_y the destination rectangle Y coordinate + * \param dst_w the destination rectangle width + * \param dst_h the destination rectangle height + * \param angle the angle + */ +void +texture_draw_ex(struct texture *tex, + int src_x, + int src_y, + unsigned src_w, + unsigned src_h, + int dst_x, + int dst_y, + unsigned dst_w, + unsigned dst_h, + double angle); + +/** + * Close the texture, do not use afterwards. + * + * \pre tex != NULL + * \param tex the texture + */ +void +texture_close(struct texture *tex); + +#endif /* !MOLKO_TEXTURE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/texture_p.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,31 @@ +/* + * texture_p.h -- (PRIVATE) basic texture management + * + * 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_TEXTURE_P_H +#define MOLKO_TEXTURE_P_H + +#include <SDL.h> + +struct texture { + SDL_Texture *handle; +}; + +struct texture * +texture_from_surface(SDL_Surface *surface); + +#endif /* !MOLKO_TEXTURE_P_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/util.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,54 @@ +/* + * util.c -- utilities + * + * 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 <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <SDL.h> + +#include "util.h" +#include "error.h" + +void * +emalloc(size_t size) +{ + void *mem; + + if (!(mem = malloc(size))) + error_fatalf("%s\n", strerror(errno)); + + return mem; +} + +void * +ecalloc(size_t n, size_t size) +{ + void *mem; + + if (!(mem = calloc(n, size))) + error_fatalf("%s\n", strerror(errno)); + + return mem; +} + +void +delay(unsigned int ms) +{ + SDL_Delay(ms); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/util.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,61 @@ +/* + * util.h -- utilities + * + * 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_UTIL_H +#define MOLKO_UTIL_H + +#include <stddef.h> + +/** + * Get the number of elements in a static array. + * + * \param x the array + * \return the number of elements + */ +#define nelem(x) sizeof ((x)) / sizeof ((x)[0]) + +/** + * Wrapper around malloc(3) that exits on allocation failure. + * + * \param size the size + * \return a pointer + * \post returned pointer will never be NULL + */ +void * +emalloc(size_t size); + +/** + * Wrapper around calloc(3) that exits on allocation failure. + * + * \param n the number of objects to allocate + * \param size the size per n + * \return a pointer + * \post returned pointer will never be NULL + */ +void * +ecalloc(size_t n, size_t size); + +/** + * Put the thread to sleep for a given amount of milliseconds. + * + * \param ms the number of milliseconds to wait + */ +void +delay(unsigned int ms); + +#endif /* !MOLKO_UTIL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/walksprite.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,60 @@ +/* + * walksprite.c -- sprite designed for walking entities + * + * 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 <string.h> + +#include "walksprite.h" +#include "sprite.h" + +void +walksprite_init(struct walksprite *ws, struct sprite *sprite, unsigned int delay) +{ + assert(ws); + assert(sprite); + + memset(ws, 0, sizeof (struct walksprite)); + ws->sprite = sprite; + ws->delay = delay; +} + +void +walksprite_update(struct walksprite *ws, unsigned int ticks) +{ + assert(ws); + + ws->elapsed += ticks; + + if (ws->elapsed >= ws->delay) { + ws->index += 1; + + if (ws->index >= ws->sprite->ncols) + ws->index = 0; + + ws->elapsed = 0; + } +} + +void +walksprite_draw(struct walksprite *ws, unsigned int orientation, int x, int y) +{ + assert(ws); + assert(orientation < 8); + + sprite_draw(ws->sprite, orientation, ws->index, x, y); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/walksprite.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,102 @@ +/* + * walksprite.h -- sprite designed for walking entities + * + * 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_WALKSPRITE_H +#define MOLKO_WALKSPRITE_H + +/** + * \file walksprite.h + * \brief Sprite designed for walking entities. + */ + +struct sprite; + +/** + * \brief Sprite designed for walking entities. + * + * This structure works with sprite images that are defined as using the + * following conventions: + * + * ``` + * 7 0 1 + * ↖ ↑ ↗ + * 6 ← → 2 + * ↙ ↓ ↘ + * 5 4 3 + * ``` + * + * Where numbers define row in the sprite according to the character + * orientation. In other terms, your image sprite should look like this: + * + * ``` + * row columns in your image + * ---|--------------------- + * 0 | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + * 1 | ↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗ + * 2 | →→→→→→→→→→→→→→→→→→→→ + * 3 | ↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘ + * 4 | ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ + * 5 | ↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙ + * 6 | ←←←←←←←←←←←←←←←←←←←← + * 7 | ↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖ + * ``` + */ +struct walksprite { + struct sprite *sprite; /*!< (RW) The sprite to use */ + unsigned int delay; /*!< (RW) The delay between frames */ + unsigned int index; /*!< (RO) Current column index */ + unsigned int elapsed; /*!< (RO) Elapsed time since last frame */ +}; + +/** + * Initialize the walking sprite. + * + * \pre ws != NULL + * \pre sprite != NULL + * \param ws the walking sprite + * \param sprite the sprite to use + * \param delay the delay between sprites + */ +void +walksprite_init(struct walksprite *ws, struct sprite *sprite, unsigned int delay); + +/** + * Update the walking sprite + * + * \pre ws != NULL + * \param ws the walking sprite + * \param ticks the number of milliseconds between last frame + */ +void +walksprite_update(struct walksprite *ws, unsigned int ticks); + +/** + * Draw the appropriate sprite cell to the screen according to the orientation + * given. + * + * \pre ws != NULL + * \pre orientation < 8 + * \param ws the walking sprite + * \param orientation the orientation (or the row between 0 and 7) + * \param x the x coordinate + * \param y the y coordinate + */ +void +walksprite_draw(struct walksprite *ws, unsigned int orientation, int x, int y); + +#endif /* !MOLKO_WALKSPRITE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/window.c Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,72 @@ +/* + * window.c -- basic window management + * + * 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 <SDL.h> + +#include "error_p.h" +#include "window.h" +#include "window_p.h" + +/* global object, used by textures */ +struct window win = { + .win = NULL, + .renderer = NULL +}; + +bool +window_init(const char *title, unsigned int width, unsigned int height) +{ + assert(title); + + if (SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL, + &win.win, &win.renderer) < 0) + return error_sdl(); + + SDL_SetWindowTitle(win.win, title); + + return true; +} + +unsigned int +window_width(void) +{ + int width; + + SDL_GetWindowSize(win.win, &width, NULL); + + return width; +} + +unsigned int +window_height(void) +{ + int height; + + SDL_GetWindowSize(win.win, NULL, &height); + + return height; +} + +void +window_close(void) +{ + SDL_DestroyRenderer(win.renderer); + SDL_DestroyWindow(win.win); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/window.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,63 @@ +/* + * window.h -- basic window management + * + * 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_WINDOW_H +#define MOLKO_WINDOW_H + +/** + * \file window.h + * \brief Basic window management. + */ + +#include <stdbool.h> + +/** + * Initialize window. + * + * \pre title != NULL + * \param title the window title + * \param width the desired width + * \param height the desired height + * \return true on success + */ +bool +window_init(const char *title, unsigned int width, unsigned int height); + +/** + * Get the current window's width. + * + * \return the width + */ +unsigned int +window_width(void); + +/** + * Get the current window's height. + * + * \return the height + */ +unsigned int +window_height(void); + +/** + * Close the window and destroy associated resources. + */ +void +window_close(void); + +#endif /* !MOLKO_WINDOW_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/window_p.h Tue Jan 21 12:42:33 2020 +0100 @@ -0,0 +1,32 @@ +/* + * window.c -- (PRIVATE) basic window management + * + * 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_WINDOW_P_H +#define MOLKO_WINDOW_P_H + +#include <SDL.h> + +struct window { + SDL_Window *win; + SDL_Renderer *renderer; +}; + +/* Global window object */ +extern struct window win; + +#endif /* !MOLKO_WINDOW_P_H */
--- a/src/error.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * error.c -- error routines - * - * 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 <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "error.h" -#include "error_p.h" - -#include <SDL.h> - -static char buffer[2048]; - -const char * -error(void) -{ - return buffer; -} - -bool -error_errno(void) -{ - error_printf("%s", strerror(errno)); - - return false; -} - -bool -error_printf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - error_vprintf(fmt, ap); - va_end(ap); - - return false; -} - -bool -error_vprintf(const char *fmt, va_list ap) -{ - vsnprintf(buffer, sizeof (buffer), fmt, ap); - - return false; -} - -noreturn void -error_fatal(void) -{ - fprintf(stderr, "%s\n", buffer); - exit(1); -} - -noreturn void -error_fatalf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - error_vfatalf(fmt, ap); - va_end(ap); -} - -noreturn void -error_vfatalf(const char *fmt, va_list ap) -{ - fprintf(stderr, fmt, ap); - exit(1); -} - -/* private: error_p.h */ - -bool -error_sdl(void) -{ - error_printf("%s", SDL_GetError()); - - return false; -}
--- a/src/error.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * error.h -- error routines - * - * 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_ERROR_H -#define MOLKO_ERROR_H - -/** - * \file error.h - * \brief Error routines. - */ - -#include <stdarg.h> -#include <stdbool.h> -#include <stdnoreturn.h> - -/** - * Get the last error returned. - * - * \return the error string - */ -const char * -error(void); - -/** - * Convenient handler that sets last error from global C errno and then return - * false. - * - * \return false - */ -bool -error_errno(void); - -/** - * Set the game error with a printf-like format. - * - * \param fmt the format string - * \return false - */ -bool -error_printf(const char *fmt, ...); - -/** - * Similar to \a error_printf. - * - * \param fmt the format stinrg - * \param ap the variadic arguments pointer - * \return false - */ -bool -error_vprintf(const char *fmt, va_list ap); - -/** - * Print last registered error and exit with code 1. - */ -noreturn void -error_fatal(void); - -/** - * Prints an error to stderr and exit. - * - * \param fmt the format string - */ -noreturn void -error_fatalf(const char *fmt, ...); - -/** - * Similar to \a error_fatalf - * - * \param fmt the format string - * \param ap the variadic arguments pointer - */ -noreturn void -error_vfatalf(const char *fmt, va_list ap); - -#endif /* !MOLKO_ERROR_H */
--- a/src/error_p.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * error.h -- (PRIVATE) error routines - * - * 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_ERROR_P_H -#define MOLKO_ERROR_P_H - -#include <stdbool.h> - -/** - * Convenient handler that sets the game error to the last SDL error and then - * return false. - * - * \return false - */ -bool -error_sdl(void); - -#endif /* !MOLKO_ERROR_P_H */
--- a/src/event.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,255 +0,0 @@ -/* - * event.c -- event management - * - * 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 <SDL.h> - -#include "event.h" - -/* Maintain with enum key constants in key.h */ -static const struct { - SDL_Keycode key; - enum key value; -} keymap[] = { - { SDLK_RETURN, KEY_ENTER }, - { SDLK_ESCAPE, KEY_ESCAPE }, - { SDLK_BACKSPACE, KEY_BACKSPACE }, - { SDLK_TAB, KEY_TAB }, - { SDLK_SPACE, KEY_SPACE }, - { SDLK_EXCLAIM, KEY_EXCLAIM }, - { SDLK_QUOTEDBL, KEY_DOUBLE_QUOTE }, - { SDLK_HASH, KEY_HASH }, - { SDLK_PERCENT, KEY_PERCENT }, - { SDLK_DOLLAR, KEY_DOLLAR }, - { SDLK_AMPERSAND, KEY_AMPERSAND }, - { SDLK_QUOTE, KEY_QUOTE }, - { SDLK_LEFTPAREN, KEY_LEFT_PAREN }, - { SDLK_RIGHTPAREN, KEY_RIGHT_PAREN }, - { SDLK_ASTERISK, KEY_ASTERISK }, - { SDLK_PLUS, KEY_PLUS }, - { SDLK_COMMA, KEY_COMMA }, - { SDLK_MINUS, KEY_MINUS }, - { SDLK_PERIOD, KEY_PERIOD }, - { SDLK_SLASH, KEY_SLASH }, - { SDLK_0, KEY_0 }, - { SDLK_1, KEY_1 }, - { SDLK_2, KEY_2 }, - { SDLK_3, KEY_3 }, - { SDLK_4, KEY_4 }, - { SDLK_5, KEY_5 }, - { SDLK_6, KEY_6 }, - { SDLK_7, KEY_7 }, - { SDLK_8, KEY_8 }, - { SDLK_9, KEY_9 }, - { SDLK_COLON, KEY_COLON }, - { SDLK_SEMICOLON, KEY_SEMICOLON }, - { SDLK_LESS, KEY_LESS }, - { SDLK_EQUALS, KEY_EQUALS }, - { SDLK_GREATER, KEY_GREATER }, - { SDLK_QUESTION, KEY_QUESTION }, - { SDLK_AT, KEY_AT }, - { SDLK_LEFTBRACKET, KEY_LEFT_BRACKET }, - { SDLK_BACKSLASH, KEY_BACKSLASH }, - { SDLK_RIGHTBRACKET, KEY_RIGHT_BRACKET }, - { SDLK_CARET, KEY_CARET }, - { SDLK_UNDERSCORE, KEY_UNDERSCORE }, - { SDLK_BACKQUOTE, KEY_BACKQUOTE }, - { SDLK_a, KEY_a }, - { SDLK_b, KEY_b }, - { SDLK_c, KEY_c }, - { SDLK_d, KEY_d }, - { SDLK_e, KEY_e }, - { SDLK_f, KEY_f }, - { SDLK_g, KEY_g }, - { SDLK_h, KEY_h }, - { SDLK_i, KEY_i }, - { SDLK_j, KEY_j }, - { SDLK_k, KEY_k }, - { SDLK_l, KEY_l }, - { SDLK_m, KEY_m }, - { SDLK_n, KEY_n }, - { SDLK_o, KEY_o }, - { SDLK_p, KEY_p }, - { SDLK_q, KEY_q }, - { SDLK_r, KEY_r }, - { SDLK_s, KEY_s }, - { SDLK_t, KEY_t }, - { SDLK_u, KEY_u }, - { SDLK_v, KEY_v }, - { SDLK_w, KEY_w }, - { SDLK_x, KEY_x }, - { SDLK_y, KEY_y }, - { SDLK_z, KEY_z }, - { SDLK_CAPSLOCK, KEY_CAPSLOCK }, - { SDLK_F1, KEY_F1 }, - { SDLK_F2, KEY_F2 }, - { SDLK_F3, KEY_F3 }, - { SDLK_F4, KEY_F4 }, - { SDLK_F5, KEY_F5 }, - { SDLK_F6, KEY_F6 }, - { SDLK_F7, KEY_F7 }, - { SDLK_F8, KEY_F8 }, - { SDLK_F9, KEY_F9 }, - { SDLK_F10, KEY_F10 }, - { SDLK_F11, KEY_F11 }, - { SDLK_F12, KEY_F12 }, - { SDLK_F13, KEY_F13 }, - { SDLK_F14, KEY_F14 }, - { SDLK_F15, KEY_F15 }, - { SDLK_F16, KEY_F16 }, - { SDLK_F17, KEY_F17 }, - { SDLK_F18, KEY_F18 }, - { SDLK_F19, KEY_F19 }, - { SDLK_F20, KEY_F20 }, - { SDLK_F21, KEY_F21 }, - { SDLK_F22, KEY_F22 }, - { SDLK_F23, KEY_F23 }, - { SDLK_F24, KEY_F24 }, - { SDLK_PRINTSCREEN, KEY_PRINTSCREEN }, - { SDLK_SCROLLLOCK, KEY_SCROLLLOCK }, - { SDLK_PAUSE, KEY_PAUSE }, - { SDLK_INSERT, KEY_INSERT }, - { SDLK_HOME, KEY_HOME }, - { SDLK_PAGEUP, KEY_PAGEUP }, - { SDLK_DELETE, KEY_DELETE }, - { SDLK_END, KEY_END }, - { SDLK_PAGEDOWN, KEY_PAGEDOWN }, - { SDLK_RIGHT, KEY_RIGHT }, - { SDLK_LEFT, KEY_LEFT }, - { SDLK_DOWN, KEY_DOWN }, - { SDLK_UP, KEY_UP }, - { SDLK_KP_DIVIDE, KEY_KP_DIVIDE }, - { SDLK_KP_MULTIPLY, KEY_KP_MULTIPLY }, - { SDLK_KP_MINUS, KEY_KP_MINUS }, - { SDLK_KP_PLUS, KEY_KP_PLUS }, - { SDLK_KP_ENTER, KEY_KP_ENTER }, - { SDLK_KP_1, KEY_KP_1 }, - { SDLK_KP_2, KEY_KP_2 }, - { SDLK_KP_3, KEY_KP_3 }, - { SDLK_KP_4, KEY_KP_4 }, - { SDLK_KP_5, KEY_KP_5 }, - { SDLK_KP_6, KEY_KP_6 }, - { SDLK_KP_7, KEY_KP_7 }, - { SDLK_KP_8, KEY_KP_8 }, - { SDLK_KP_9, KEY_KP_9 }, - { SDLK_KP_0, KEY_KP_0 }, - { SDLK_KP_PERIOD, KEY_KP_PERIOD }, - { SDLK_KP_COMMA, KEY_KP_COMMA }, - { SDLK_MENU, KEY_MENU }, - { SDLK_MUTE, KEY_MUTE }, - { SDLK_VOLUMEUP, KEY_VOLUME_UP }, - { SDLK_VOLUMEDOWN, KEY_VOLUME_DOWN }, - { SDLK_LCTRL, KEY_LCTRL }, - { SDLK_LSHIFT, KEY_LSHIFT }, - { SDLK_LALT, KEY_LALT }, - { SDLK_LGUI, KEY_LSUPER }, - { SDLK_RCTRL, KEY_RCTRL }, - { SDLK_RSHIFT, KEY_RSHIFT }, - { SDLK_RALT, KEY_RALT }, - { SDLK_RGUI, KEY_RSUPER }, - { 0, -1 } -}; - -/* Maintain with enum mouse_button constants in mouse.h */ -static const struct { - int key; - enum mouse_button value; -} buttons[] = { - { SDL_BUTTON_LEFT, MOUSE_BUTTON_LEFT }, - { SDL_BUTTON_MIDDLE, MOUSE_BUTTON_MIDDLE }, - { SDL_BUTTON_RIGHT, MOUSE_BUTTON_RIGHT }, - { -1, MOUSE_BUTTON_UNKNOWN } -}; - -static void -convert_key(const SDL_Event *event, union event *ev) -{ - ev->type = event->type == SDL_KEYDOWN ? EVENT_KEYDOWN : EVENT_KEYUP; - ev->key.key = KEY_UNKNOWN; - - for (size_t i = 0; keymap[i].key != 0; ++i) { - if (keymap[i].key == event->key.keysym.sym) { - ev->key.key = keymap[i].value; - break; - } - } -} - -static void -convert_mouse(const SDL_Event *event, union event *ev) -{ - ev->type = EVENT_MOUSE; - ev->mouse.buttons = 0; - ev->mouse.x = event->motion.x; - ev->mouse.y = event->motion.y; - - if (event->motion.state & SDL_BUTTON_LMASK) - ev->mouse.buttons |= MOUSE_BUTTON_LEFT; - if (event->motion.state & SDL_BUTTON_MMASK) - ev->mouse.buttons |= MOUSE_BUTTON_MIDDLE; - if (event->motion.state & SDL_BUTTON_RMASK) - ev->mouse.buttons |= MOUSE_BUTTON_RIGHT; -} - -static void -convert_click(const SDL_Event *event, union event *ev) -{ - ev->type = event->type == SDL_MOUSEBUTTONDOWN ? EVENT_CLICKDOWN : EVENT_CLICKUP; - ev->click.button = MOUSE_BUTTON_UNKNOWN; - ev->click.x = event->button.x; - ev->click.y = event->button.y; - - for (size_t i = 0; buttons[i].value != MOUSE_BUTTON_UNKNOWN; ++i) { - if (buttons[i].key == event->button.button) { - ev->click.button = buttons[i].value; - break; - } - } -} - -bool -event_poll(union event *ev) -{ - SDL_Event event; - - /* - * Loop until we find an event we want to report, we skip unneeded - * ones. - */ - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_QUIT: - ev->type = EVENT_QUIT; - return true; - case SDL_KEYDOWN: - case SDL_KEYUP: - convert_key(&event, ev); - return true; - case SDL_MOUSEMOTION: - convert_mouse(&event, ev); - return true; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - convert_click(&event, ev); - return true; - default: - continue; - } - } - - return false; -}
--- a/src/event.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * event.h -- event management - * - * 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_EVENT_H -#define MOLKO_EVENT_H - -/** - * \file event.h - * \brief Event management. - */ - -#include <stdbool.h> - -#include "key.h" -#include "mouse.h" - -/** - * \brief Kind of event. - */ -enum event_type { - EVENT_CLICKDOWN, /*!< Mouse click down */ - EVENT_CLICKUP, /*!< Mouse click released */ - EVENT_KEYDOWN, /*!< Single key down */ - EVENT_KEYUP, /*!< Single key released */ - EVENT_MOUSE, /*!< Mouse moved */ - EVENT_QUIT, /*!< Quit request */ -}; - -/** - * \brief Store events. - */ -union event { - enum event_type type; /*!< Which kind of event */ - - /** - * Store key down/up event. - */ - struct { - enum event_type type; /*!< EVENT_KEYDOWN or EVENT_KEYUP */ - enum key key; /*!< Which key */ - } key; - - /** - * Store mouse motion event. - */ - struct { - enum event_type type; /*!< EVENT_MOUSE */ - enum mouse_button buttons; /*!< OR'ed buttons that are pressed */ - int x; /*!< Mouse position in x */ - int y; /*!< Mouse position in y */ - } mouse; - - /** - * Store mouse click event. - */ - struct { - enum event_type type; /*!< EVENT_CLICKDOWN or EVENT_CLICKUP */ - enum mouse_button button; /*!< Unique button that was pressed */ - int x; /*!< Mouse position in x */ - int y; /*!< Mouse position in y */ - } click; -}; - -/** - * Fetch the next event or return false if there are not. - * - * \param ev the event - * \return true if the event was filled or false otherwise - */ -bool -event_poll(union event *ev); - -#endif /* !MOLKO_EVENT_H */
--- a/src/font.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * font.c -- basic font management - * - * 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 <stdbool.h> -#include <stdio.h> - -#include <SDL_ttf.h> - -#include "color.h" -#include "error.h" -#include "error_p.h" -#include "font.h" -#include "texture_p.h" -#include "util.h" - -struct font { - TTF_Font *handle; -}; - -struct font * -font_openf(const char *path, unsigned int size) -{ - assert(path); - - struct font *f; - - f = ecalloc(1, sizeof (struct font)); - - if (!(f->handle = TTF_OpenFont(path, size))) { - error_sdl(); - free(f); - return NULL; - } - - return f; -} - -struct font * -font_openb(const void *buffer, size_t buflen, unsigned int size) -{ - assert(buffer); - - struct font *f; - SDL_RWops *ops; - - f = ecalloc(1, sizeof (struct font)); - - if (!(ops = SDL_RWFromConstMem(buffer, buflen)) || - (!(f->handle = TTF_OpenFontRW(ops, true, size)))) { - error_sdl(); - free(f); - return NULL; - } - - return f; -} - -struct texture * -font_render(struct font *font, const char *text, unsigned long color) -{ - assert(font); - assert(text); - - SDL_Color fg = { - .r = COLOR_R(color), - .g = COLOR_G(color), - .b = COLOR_B(color), - .a = COLOR_A(color) - }; - - SDL_Surface *surface; - - if (!(surface = TTF_RenderUTF8_Blended(font->handle, text, fg))) { - error_sdl(); - return NULL; - } - - return texture_from_surface(surface); -} - -void -font_close(struct font *font) -{ - assert(font); - - TTF_CloseFont(font->handle); - free(font); -}
--- a/src/font.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * font.h -- basic font management - * - * 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_FONT_H -#define MOLKO_FONT_H - -/** - * \file font.h - * \brief Basic font management. - */ - -#include <stddef.h> - -/** - * \brief Font object. - * - * This object is not publicly defined because it contains - * implementation-defined data. - */ -struct font; -struct texture; - -/** - * Open font from path file. - * - * \pre path != NULL - * \param path the path to the font - * \param size the desired size - * \return the font or NULL on error - */ -struct font * -font_openf(const char *path, unsigned int size); - -/** - * Open font from memory buffer. - * - * \pre buffer != NULL - * \param buffer the memory buffer - * \param buflen the memory buffer length - * \param size the desired size - * \warning The buffer must remain valid until font is closed - * \return the font or NULL on error - */ -struct font * -font_openb(const void *buffer, size_t buflen, unsigned int size); - -/** - * Render a text. - * - * \pre font != NULL - * \pre text != NULL - * \param font the font handle - * \param text the text in UTF-8 - * \param color the color - */ -struct texture * -font_render(struct font *font, const char *text, unsigned long color); - -/** - * Close the font. - * - * \pre font != NULL - * \param font the font handle - */ -void -font_close(struct font *font); - -#endif /* !MOLKO_FONT_H */
--- a/src/game.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -/* - * game.c -- main game object - * - * 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 <stddef.h> -#include <string.h> - -#include "game.h" -#include "state.h" - -struct game game = { - .state = NULL, - .state_next = NULL -}; - -static struct action * -find_empty_action(void) -{ - static struct action null; - - for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) - if (memcmp(&game.actions[i], &null, sizeof (struct action)) == 0) - return &game.actions[i]; - - return NULL; -} - -static void -clear_actions(void) -{ - for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) { - struct action *a = &game.actions[i]; - - /* These actions are removed on state change. */ - if (a->flags & ACTION_AUTO_LEAVE) { - if (a->finish) - a->finish(a); - - memset(a, 0, sizeof (struct action)); - } - } -} - -static void -handle_actions(const union event *event) -{ - for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) - if (game.actions[i].handle) - game.actions[i].handle(&game.actions[i], event); -} - -static void -update_actions(unsigned int ticks) -{ - for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) { - struct action *a = &game.actions[i]; - - if (!a->update) - continue; - - if (a->update(a, ticks)) { - if (a->finish) - a->finish(a); - - memset(&game.actions[i], 0, sizeof (struct action)); - } - } -} - -static void -draw_actions(void) -{ - for (size_t i = 0; i < GAME_ACTIONS_MAX; ++i) - if (game.actions[i].draw) - game.actions[i].draw(&game.actions[i]); -} - - -void -game_switch(struct state *state, bool quick) -{ - assert(state); - - if (quick) { - game.state = state; - game.state->enter(); - } else - game.state_next = state; -} - -void -game_handle(const union event *event) -{ - assert(event); - - if (game.state) - game.state->handle(event); - - handle_actions(event); -} - -void -game_update(unsigned int ticks) -{ - /* Change state if any. */ - if (game.state_next) { - /* Inform the current state we're gonna leave it. */ - if (game.state) - game.state->leave(); - - game.state = game.state_next; - game.state->enter(); - game.state_next = NULL; - - /* Remove any actions that must be deleted. */ - clear_actions(); - } - - if (game.state) - game.state->update(ticks); - - update_actions(ticks); -} - -void -game_draw(void) -{ - if (game.state) - game.state->draw(); - - draw_actions(); -} - -void -game_add_action(const struct action *action) -{ - assert(action); - - struct action *pos; - - if ((pos = find_empty_action())) - memcpy(pos, action, sizeof (struct action)); -}
--- a/src/game.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/* - * game.h -- main game object - * - * 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_GAME_H -#define MOLKO_GAME_H - -/** - * \file game.h - * \brief Main game object. - */ - -#include <stdbool.h> - -#include "action.h" - -/** - * \brief Max number of actions allowed at the same time. - */ -#define GAME_ACTIONS_MAX 32 - -struct state; - -union event; - -/** - * \brief Main game object. - */ -struct game { - /* Game states. */ - struct state *state; /*!< (RO) Current state */ - struct state *state_next; /*!< (RO) Next state */ - - /** Array of actions. */ - struct action actions[GAME_ACTIONS_MAX]; -}; - -/** - * Global game object. - */ -extern struct game game; - -/** - * Request to change state. - * - * This function will only update state after the next \a game_update call. - * - * If quick is true, change state immediately. - * - * \pre state != NULL - * \param state the new state - * \param quick quickly change the state - */ -void -game_switch(struct state *state, bool quick); - -/** - * Handle input event. - * - * \param event the event - */ -void -game_handle(const union event *event); - -/** - * Update the game state. - * - * \param ticks the number of milliseconds between last frame - */ -void -game_update(unsigned int ticks); - -/** - * Draw the game using the current state. - */ -void -game_draw(void); - -/** - * Add an action to the game. - * - * If there are no room for the action, action is discarded. Make sure to not - * exceed the limit GAME_ACTIONS_MAX. - * - * \pre action != NULL - * \param action the action to copy - */ -void -game_add_action(const struct action *action); - -#endif /* !MOLKO_GAME_H */
--- a/src/image.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * image.c -- basic image management - * - * 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 <stdbool.h> - -#include <SDL_image.h> - -#include "error_p.h" -#include "texture_p.h" - -struct texture * -image_openf(const char *path) -{ - assert(path); - - SDL_Surface *surface = IMG_Load(path); - - if (!surface) { - error_sdl(); - return NULL; - } - - return texture_from_surface(surface); -} - -struct texture * -image_openb(const void *buffer, size_t size) -{ - assert(buffer); - - SDL_RWops *ops = SDL_RWFromConstMem(buffer, size); - SDL_Surface *surface; - - if (!ops || !(surface = IMG_Load_RW(ops, true))) { - error_sdl(); - return NULL; - } - - return texture_from_surface(surface); -}
--- a/src/image.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * image.h -- basic image management - * - * 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_IMAGE_H -#define MOLKO_IMAGE_H - -/** - * \file image.h - * \brief Basic image management. - */ - -#include <stddef.h> - -struct texture; - -/** - * Open a file from a path. - * - * \pre path != NULL - * \param path the path to the file - * \return the texture or NULL on error - */ -struct texture * -image_openf(const char *path); - -/** - * Open a file from a memory buffer. - * - * \pre buffer != NULL - * \param buffer the memory buffer - * \param size the memory size - * \return the texture or NULL on error - */ -struct texture * -image_openb(const void *buffer, size_t size); - -#endif /* !MOLKO_IMAGE_H */
--- a/src/key.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/* - * key.h -- keyboard definitions - * - * 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_KEY_H -#define MOLKO_KEY_H - -/** - * \file key.h - * \brief Keyboard definitions. - */ - -/** - * \brief Key codes. - */ -enum key { - KEY_UNKNOWN, - KEY_ENTER, - KEY_ESCAPE, - KEY_BACKSPACE, - KEY_TAB, - KEY_SPACE, - KEY_EXCLAIM, - KEY_DOUBLE_QUOTE, - KEY_HASH, - KEY_PERCENT, - KEY_DOLLAR, - KEY_AMPERSAND, - KEY_QUOTE, - KEY_LEFT_PAREN, - KEY_RIGHT_PAREN, - KEY_ASTERISK, - KEY_PLUS, - KEY_COMMA, - KEY_MINUS, - KEY_PERIOD, - KEY_SLASH, - KEY_0, - KEY_1, - KEY_2, - KEY_3, - KEY_4, - KEY_5, - KEY_6, - KEY_7, - KEY_8, - KEY_9, - KEY_COLON, - KEY_SEMICOLON, - KEY_LESS, - KEY_EQUALS, - KEY_GREATER, - KEY_QUESTION, - KEY_AT, - KEY_LEFT_BRACKET, - KEY_BACKSLASH, - KEY_RIGHT_BRACKET, - KEY_CARET, - KEY_UNDERSCORE, - KEY_BACKQUOTE, - KEY_a, - KEY_b, - KEY_c, - KEY_d, - KEY_e, - KEY_f, - KEY_g, - KEY_h, - KEY_i, - KEY_j, - KEY_k, - KEY_l, - KEY_m, - KEY_n, - KEY_o, - KEY_p, - KEY_q, - KEY_r, - KEY_s, - KEY_t, - KEY_u, - KEY_v, - KEY_w, - KEY_x, - KEY_y, - KEY_z, - KEY_CAPSLOCK, - KEY_F1, - KEY_F2, - KEY_F3, - KEY_F4, - KEY_F5, - KEY_F6, - KEY_F7, - KEY_F8, - KEY_F9, - KEY_F10, - KEY_F11, - KEY_F12, - KEY_F13, - KEY_F14, - KEY_F15, - KEY_F16, - KEY_F17, - KEY_F18, - KEY_F19, - KEY_F20, - KEY_F21, - KEY_F22, - KEY_F23, - KEY_F24, - KEY_PRINTSCREEN, - KEY_SCROLLLOCK, - KEY_PAUSE, - KEY_INSERT, - KEY_HOME, - KEY_PAGEUP, - KEY_DELETE, - KEY_END, - KEY_PAGEDOWN, - KEY_RIGHT, - KEY_LEFT, - KEY_DOWN, - KEY_UP, - KEY_NUMLOCKCLEAR, - KEY_KP_DIVIDE, - KEY_KP_MULTIPLY, - KEY_KP_MINUS, - KEY_KP_PLUS, - KEY_KP_ENTER, - KEY_KP_00, - KEY_KP_000, - KEY_KP_1, - KEY_KP_2, - KEY_KP_3, - KEY_KP_4, - KEY_KP_5, - KEY_KP_6, - KEY_KP_7, - KEY_KP_8, - KEY_KP_9, - KEY_KP_0, - KEY_KP_PERIOD, - KEY_KP_COMMA, - KEY_MENU, - KEY_MUTE, - KEY_VOLUME_UP, - KEY_VOLUME_DOWN, - KEY_LCTRL, - KEY_LSHIFT, - KEY_LALT, - KEY_LSUPER, - KEY_RCTRL, - KEY_RSHIFT, - KEY_RALT, - KEY_RSUPER, -}; - -/** - * \brief Keybord modifiers. - * - * This enumeration is usually stored as OR'ed flags as several modifiers can - * be pressed at a time. - */ -enum keymod { - KEYMOD_LSHIFT = 1 << 0, /*!< Left shift */ - KEYMOD_LCTRL = 1 << 1, /*!< Left control */ - KEYMOD_LALT = 1 << 2, /*!< Left alt */ - KEYMOD_LSUPER = 1 << 3, /*!< Left super (logo) */ - KEYMOD_RSHIFT = 1 << 4, /*!< Right shift */ - KEYMOD_RCTRL = 1 << 5, /*!< Right control */ - KEYMOD_RALT = 1 << 6, /*!< Right alt */ - KEYMOD_RSUPER = 1 << 7 /*!< Right super (logo) */ -}; - -#endif /* !MOLKO_KEY_H */
--- a/src/main.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * main.c -- Molko's Adventure - * - * 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 "clock.h" -#include "error.h" -#include "event.h" -#include "game.h" -#include "image.h" -#include "map.h" -#include "map_state.h" -#include "splashscreen.h" -#include "sprite.h" -#include "sys.h" -#include "util.h" -#include "window.h" - -#define WINDOW_WIDTH 1280 -#define WINDOW_HEIGHT 720 - -static void -init(void) -{ - if (!sys_init()) - error_fatal(); - if (!window_init("Molko's Adventure", WINDOW_WIDTH, WINDOW_HEIGHT)) - error_fatal(); - - /* Default state is splash screen */ - game_switch(&splashscreen_state, true); -} - -static void -run(void) -{ - union event ev; - struct clock clock; - - clock_start(&clock); - - for (;;) { - unsigned int elapsed = clock_elapsed(&clock); - - clock_start(&clock); - - while (event_poll(&ev)) { - /* TODO: this must be handled by states. */ - if (ev.type == EVENT_QUIT) - return; - - game_handle(&ev); - } - - game_update(elapsed); - game_draw(); - - if ((elapsed = clock_elapsed(&clock)) < 20) - delay(20 - elapsed); - } -} - -static void -close(void) -{ - window_close(); - sys_close(); -} - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - init(); - run(); - close(); - - return 0; -}
--- a/src/map.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -/* - * map.c -- game map - * - * 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 "error.h" -#include "error_p.h" -#include "image.h" -#include "map.h" -#include "painter.h" -#include "sprite.h" -#include "sys.h" -#include "texture.h" -#include "window.h" - -#include <SDL.h> - -/* Create %<v>c string literal for scanf */ -#define MAX_F(v) MAX_F_(v) -#define MAX_F_(v) "%" #v "c" - -static void -parse_layer(struct map *map, const char *line, FILE *fp) -{ - char layer_name[32 + 1] = { 0 }; - struct map_layer *layer; - size_t amount, current; - - /* Determine layer. */ - if (sscanf(line, "layer|%32s", layer_name) <= 0) - return; - if (strcmp(layer_name, "background") == 0) - layer = &map->layers[0]; - else if (strcmp(layer_name, "foreground") == 0) - layer = &map->layers[1]; - else - return; - - /* Check if weight/height has been specified. */ - if (map->width == 0 || map->height == 0) - return; - - amount = map->width * map->height; - current = 0; - - if (!(layer->tiles = calloc(amount, sizeof (unsigned short)))) - return; - - for (int tile; fscanf(fp, "%d", &tile) && current < amount; ++current) - layer->tiles[current] = tile; -} - -static void -parse_tileset(struct map *map, const char *line) -{ - char filename[128 + 1] = { 0 }; - - sscanf(line, "tileset|%128s", filename); - - if (map->tilewidth == 0 || map->tileheight == 0) - return; - if (!(map->tileset = image_openf(sys_datapath("tilesets/%s", filename)))) - return; - - sprite_init(&map->sprite, map->tileset, map->tilewidth, map->tileheight); -} - -static void -parse(struct map *map, const char *line, FILE *fp) -{ - if (strncmp(line, "title", 5) == 0) - sscanf(line, "title|" MAX_F(MAP_TITLE_MAX), map->title); - else if (strncmp(line, "width", 5) == 0) - sscanf(line, "width|%u", &map->width); - else if (strncmp(line, "height", 6) == 0) - sscanf(line, "height|%u", &map->height); - else if (strncmp(line, "tilewidth", 9) == 0) - sscanf(line, "tilewidth|%hu", &map->tilewidth); - else if (strncmp(line, "tileheight", 10) == 0) - sscanf(line, "tileheight|%hu", &map->tileheight); - else if (strncmp(line, "origin", 6) == 0) - sscanf(line, "origin|%d|%d", &map->origin_x, &map->origin_y); - else if (strncmp(line, "tileset", 7) == 0) - parse_tileset(map, line); - else if (strncmp(line, "layer", 5) == 0) - parse_layer(map, line, fp); -} - -static bool -check(struct map *map) -{ - if (strlen(map->title) == 0) - return error_printf("map has no title"); - if (!map->tileset) - return error_printf("unable to open tileset"); - if (map->width == 0 || map->height == 0) - return error_printf("map has null sizes"); - if (map->tilewidth == 0 || map->tileheight == 0) - return error_printf("map has null tile sizes"); - if (!map->layers[0].tiles || !map->layers[1].tiles) - return error_printf("could not allocate data"); - - return true; -} - -static void -draw_layer(struct map *map, const struct map_layer *layer) -{ - assert(map); - assert(layer); - - int x = 0, y = 0; - - for (unsigned int r = 0; r < map->width; ++r) { - for (unsigned int c = 0; c < map->height; ++c) { - unsigned int si = r * map->width + c; - unsigned int sr = (layer->tiles[si] - 1) / map->sprite.ncols; - unsigned int sc = (layer->tiles[si] - 1) % map->sprite.nrows; - - if (layer->tiles[si] != 0) - sprite_draw(&map->sprite, sr, sc, x, y); - - x += map->tilewidth; - } - - x = 0; - y += map->tileheight; - } -} - -bool -map_open(struct map *map, const char *path) -{ - assert(map); - assert(path); - - memset(map, 0, sizeof (struct map)); - - FILE *fp = fopen(path, "r"); - char line[BUFSIZ]; - - if (!fp) - return false; - - while (fgets(line, sizeof (line), fp)) { - /* Remove \n if any */ - line[strcspn(line, "\n")] = '\0'; - parse(map, line, fp); - } - - fclose(fp); - - if (!check(map)) { - map_close(map); - return false; - } - - size_t pw = map->width * map->tilewidth; - size_t ph = map->height * map->tileheight; - - if (!(map->picture = texture_new(pw, ph))) - return error_sdl(); - - return true; -} - -void -map_draw(struct map *map, int srcx, int srcy) -{ - texture_draw_ex( - map->picture, - srcx, - srcy, - window_width(), - window_height(), - 0, - 0, - window_width(), - window_height(), - 0 - ); -} - -void -map_repaint(struct map *map) -{ - PAINTER_BEGIN(map->picture); - draw_layer(map, &map->layers[0]); - draw_layer(map, &map->layers[1]); - PAINTER_END(); -} - -void -map_close(struct map *map) -{ - assert(map); - - if (map->tileset) - texture_close(map->tileset); - if (map->picture) - texture_close(map->picture); - - free(map->layers[0].tiles); - free(map->layers[1].tiles); - - memset(map, 0, sizeof (struct map)); -}
--- a/src/map.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * map.h -- game map - * - * 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_MAP_H -#define MOLKO_MAP_H - -/** - * \file map.h - * \brief Game map. - */ - -#include <stdbool.h> - -#include "sprite.h" - -/** - * \brief Max title length for a map. - */ -#define MAP_TITLE_MAX 32 - -struct texture; - -/** - * \brief Map layer. - */ -struct map_layer { - unsigned short *tiles; /*!< (RO) Array of tiles, depending on the map size. */ -}; - -/** - * \brief Map object. - * - * This structure only defines the map characteristics. It does not have any - * logic and is left for game state. - */ -struct map { - char title[MAP_TITLE_MAX]; /*!< (RW) The map title */ - struct texture *tileset; /*!< (RW) Tileset to use */ - struct texture *picture; /*!< (RO) Map drawn into a picture */ - struct sprite sprite; /*!< (RO) Sprite to render */ - int origin_x; /*!< (RO) Where the player starts in X */ - int origin_y; /*!< (RO) Where the player starts in Y */ - unsigned int width; /*!< (RO) Map width in cells */ - unsigned int height; /*!< (RO) Map height in cells */ - unsigned short tilewidth; /*!< (RO) Pixels per cell (width) */ - unsigned short tileheight; /*!< (RO) Pixels per cell (height) */ - struct map_layer layers[2]; /*!< (RO) Layers (background, foreground) */ -}; - -/** - * Open a map. - * - * \pre map != NULL - * \pre path != NULL - * \param map the map to fill - * \param path the path to the map - * \return true if successfully loaded - */ -bool -map_open(struct map *map, const char *path); - -/** - * Render a map. - * - * \pre map != NULL - * \param map the map to render - * \param srcx the x coordinate region - * \param srcy the y coordinate region - */ -void -map_draw(struct map *map, int srcx, int srcy); - -/** - * Force map repaint on its texture. - * - * \pre map != NULL - * \param map the map to repaint - * \warning This function does not render anything on the screen - */ -void -map_repaint(struct map *map); - -/** - * Close the map and its resources. - * - * \pre map != NULL - * \param map the map to render - */ -void -map_close(struct map *map); - -#endif /* !MOLKO_MAP_H */
--- a/src/map_state.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,341 +0,0 @@ -/* - * map_state.c -- state when player is on a map - * - * 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 "event.h" -#include "game.h" -#include "map.h" -#include "map_state.h" -#include "painter.h" -#include "state.h" -#include "texture.h" -#include "walksprite.h" -#include "window.h" - -/* - * This is the speed the player moves on the map. - * - * SPEED represents the number of pixels it must move per SEC. - * SEC simply represends the number of milliseconds in one second. - */ -#define SPEED 100 -#define SEC 1000 - -/* - * Those are margins within the edge of the screen. The camera always try to - * keep those padding between the player and the screen. - */ -#define MARGIN_WIDTH 80 -#define MARGIN_HEIGHT 80 - -/* - * This structure defines the possible movement of the player as flags since - * it's possible to make diagonal movements. - */ -enum movement { - MOVING_UP = 1 << 0, - MOVING_RIGHT = 1 << 1, - MOVING_DOWN = 1 << 2, - MOVING_LEFT = 1 << 3 -}; - -/* - * A bit of explanation within this array. The structure walksprite requires - * an orientation between 0-7 depending on the user direction. - * - * Since keys for moving the character may be pressed at the same time, we need - * a conversion table from "key pressed" to "orientation". - * - * When an orientation is impossible, it is set to -1. Example, when both left - * and right are pressed. - * - * MOVING_UP = 0001 = 0x1 - * MOVING_RIGHT = 0010 = 0x2 - * MOVING_DOWN = 0100 = 0x3 - * MOVING_LEFT = 1000 = 0x4 - */ -static unsigned int orientations[16] = { - [0x1] = 0, - [0x2] = 2, - [0x3] = 1, - [0x4] = 4, - [0x6] = 3, - [0x8] = 6, - [0x9] = 7, - [0xC] = 5 -}; - -/* - * Additional data that is not necessary to expose in map_state_data. - */ -static struct { - struct { - enum movement moving; - struct walksprite ws; - } player; - - struct { - int x; - int y; - unsigned int w; - unsigned int h; - } margin; -} cache; - -static void -center(void) -{ - map_state_data.view.x = map_state_data.player.x - (map_state_data.view.w / 2); - map_state_data.view.y = map_state_data.player.y - (map_state_data.view.h / 2); - - if (map_state_data.view.x < 0) - map_state_data.view.x = 0; - else if ((unsigned int)map_state_data.view.x > map_state_data.map.w - map_state_data.view.w) - map_state_data.view.x = map_state_data.map.w - map_state_data.view.w; - - if (map_state_data.view.y < 0) - map_state_data.view.y = 0; - else if ((unsigned int)map_state_data.view.y > map_state_data.map.h - map_state_data.view.h) - map_state_data.view.y = map_state_data.map.h - map_state_data.view.h; -} - -static void -enter(void) -{ - /* Adjust map properties. */ - struct map *m = &map_state_data.map.map; - - if (!m->picture) - map_repaint(m); - - map_repaint(m); - map_state_data.map.w = texture_width(m->picture); - map_state_data.map.h = texture_height(m->picture); - - /* Adjust view. */ - map_state_data.view.w = window_width(); - map_state_data.view.h = window_height(); - - /* Adjust margin. */ - cache.margin.w = map_state_data.view.w - (MARGIN_WIDTH * 2); - cache.margin.h = map_state_data.view.h - (MARGIN_HEIGHT * 2); - - /* Center the view by default. */ - center(); - - /* Final bits. */ - walksprite_init(&cache.player.ws, &map_state_data.player.sprite, 300); -} - -static void -leave(void) -{ -} - -static void -handle_keydown(const union event *event) -{ - switch (event->key.key) { - case KEY_UP: - cache.player.moving |= MOVING_UP; - break; - case KEY_RIGHT: - cache.player.moving |= MOVING_RIGHT; - break; - case KEY_DOWN: - cache.player.moving |= MOVING_DOWN; - break; - case KEY_LEFT: - cache.player.moving |= MOVING_LEFT; - break; - default: - break; - } - - map_state_data.player.angle = orientations[cache.player.moving]; -} - -static void -handle_keyup(const union event *event) -{ - switch (event->key.key) { - case KEY_UP: - cache.player.moving &= ~(MOVING_UP); - break; - case KEY_RIGHT: - cache.player.moving &= ~(MOVING_RIGHT); - break; - case KEY_DOWN: - cache.player.moving &= ~(MOVING_DOWN); - break; - case KEY_LEFT: - cache.player.moving &= ~(MOVING_LEFT); - break; - default: - break; - } -} - -static void -move_right(unsigned int delta) -{ - map_state_data.player.x += delta; - - if (map_state_data.player.x > (int)(cache.margin.x + cache.margin.w)) { - map_state_data.view.x = (map_state_data.player.x - map_state_data.view.w) + MARGIN_WIDTH; - - if (map_state_data.view.x >= (int)(map_state_data.map.w - map_state_data.view.w)) - map_state_data.view.x = map_state_data.map.w - map_state_data.view.w; - } - - if (map_state_data.player.x > (int)map_state_data.map.w - 48) - map_state_data.player.x = map_state_data.map.w - 48; -} - -static void -move_left(unsigned int delta) -{ - map_state_data.player.x -= delta; - - if (map_state_data.player.x < cache.margin.x) { - map_state_data.view.x = map_state_data.player.x - MARGIN_WIDTH; - - if (map_state_data.view.x < 0) - map_state_data.view.x = 0; - } - - if (map_state_data.player.x < 0) - map_state_data.player.x = 0; -} - -static void -move_down(unsigned int delta) -{ - map_state_data.player.y += delta; - - if (map_state_data.player.y > (int)(cache.margin.y + cache.margin.h)) { - map_state_data.view.y = (map_state_data.player.y - map_state_data.view.h) + MARGIN_HEIGHT; - - if (map_state_data.view.y >= (int)(map_state_data.map.h - map_state_data.view.h)) - map_state_data.view.y = map_state_data.map.h - map_state_data.view.h; - } - - if (map_state_data.player.y > (int)map_state_data.map.h - 48) - map_state_data.player.y = map_state_data.map.h - 48; -} - -static void -move_up(unsigned int delta) -{ - map_state_data.player.y -= delta; - - if (map_state_data.player.y < cache.margin.y) { - map_state_data.view.y = map_state_data.player.y - MARGIN_HEIGHT; - - if (map_state_data.view.y < 0) - map_state_data.view.y = 0; - } - - if (map_state_data.player.y < 0) - map_state_data.player.y = 0; -} - -static void -move(unsigned int ticks) -{ - /* This is the amount of pixels the player must move. */ - const int delta = SPEED * ticks / SEC; - - /* This is the rectangle within the view where users must be. */ - cache.margin.x = map_state_data.view.x + MARGIN_WIDTH; - cache.margin.y = map_state_data.view.y + MARGIN_HEIGHT; - - int dx = 0; - int dy = 0; - - if (cache.player.moving == 0) - return; - - if (cache.player.moving & MOVING_UP) - dy = -1; - if (cache.player.moving & MOVING_DOWN) - dy = 1; - if (cache.player.moving & MOVING_LEFT) - dx = -1; - if (cache.player.moving & MOVING_RIGHT) - dx = 1; - - /* Move the player and adjust view if needed. */ - if (dx > 0) - move_right(delta); - else if (dx < 0) - move_left(delta); - - if (dy > 0) - move_down(delta); - else if (dy < 0) - move_up(delta); - - walksprite_update(&cache.player.ws, ticks); -} - -static void -handle(const union event *event) -{ - switch (event->type) { - case EVENT_KEYDOWN: - handle_keydown(event); - break; - case EVENT_KEYUP: - handle_keyup(event); - break; - default: - break; - } -} - -static void -update(unsigned int ticks) -{ - move(ticks); -} - -static void -draw(void) -{ - painter_set_color(0x000000ff); - painter_clear(); - map_draw(&map_state_data.map.map, map_state_data.view.x, map_state_data.view.y); - walksprite_draw( - &cache.player.ws, - map_state_data.player.angle, - map_state_data.player.x - map_state_data.view.x, - map_state_data.player.y - map_state_data.view.y); - painter_present(); -} - -struct map_state_data map_state_data; - -struct state map_state = { - .enter = enter, - .leave = leave, - .update = update, - .handle = handle, - .draw = draw -};
--- a/src/map_state.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * map_state.h -- state when player is on a map - * - * 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_MAP_STATE_H -#define MOLKO_MAP_STATE_H - -/** - * \file map_state.h - * \brief State when player is on a map. - */ - -#include "map.h" -#include "sprite.h" - -/** - * \brief Data for the state. - * - * Update this structure before switching to this state. - */ -extern struct map_state_data { - /** - * Map properties. - */ - struct { - struct map map; /*!< (RO) The map definition */ - unsigned int w; /*!< (RO) Map width */ - unsigned int h; /*!< (RO) Map height */ - } map; - - /** - * Player position. - * - * If you adjust this structure, it is strictly encouraged to update - * the view as well. - */ - struct { - struct sprite sprite; /*!< (RW) The sprite to use */ - int x; /*!< (RO) Player position in x */ - int y; /*!< (RO) Player position in y */ - int angle; /*!< (RO) Player angle (see walksprite) */ - } player; - - /** - * Position and size of the view. - */ - struct { - int x; /*!< (RW) Position in x */ - int y; /*!< (RW) Position in y */ - unsigned int w; /*!< (RO) View width */ - unsigned int h; /*!< (RO) View height */ - } view; -} map_state_data; /*!< Access to data. */ - -/** - * \brief State when player is on a map. - */ -extern struct state map_state; - -#endif /* !MOLKO_MAP_STATE_H */
--- a/src/message.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * message.c -- message 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 <assert.h> - -#include "font.h" -#include "message.h" -#include "painter.h" -#include "sprite.h" -#include "texture.h" - -#define MESSAGE_SPEED 1000 /* Time delay for animations */ -#define MESSAGE_TIMEOUT 5000 /* Time for auto-closing */ - -void -message_start(struct message *msg) -{ - assert(msg); - - msg->elapsed = 0; - msg->state = MESSAGE_OPENING; -} - -void -message_update(struct message *msg, unsigned int ticks) -{ - assert(msg); - - msg->elapsed += ticks; - - switch (msg->state) { - case MESSAGE_OPENING: - if (msg->elapsed >= MESSAGE_SPEED) - msg->state = MESSAGE_SHOWING; - break; - case MESSAGE_SHOWING: - /* Do automatically switch state if requested by the user. */ - if (msg->flags & MESSAGE_AUTOMATIC && msg->elapsed >= MESSAGE_TIMEOUT) - msg->state = MESSAGE_HIDING; - - break; - default: - break; - } -} - -void -message_draw(struct message *msg) -{ - assert(msg); - - /* TODO: more constant variables. */ - struct texture *lines[3]; - int x = 160; - int y = 80; - - painter_set_color(0xff0000ff); - painter_draw_rectangle(true, x, y, 960, 160); - - for (int i = 0; msg->text[i]; ++i) { - lines[i] = font_render(msg->font, msg->text[i], 0xffffffff); - - if (!lines[i]) - continue; - - texture_draw(lines[i], x, y); - texture_close(lines[i]); - y += 53; - } -} - -void -message_hide(struct message *msg) -{ - assert(msg); - - msg->elapsed = 0; -} - -bool -message_is_complete(struct message *msg) -{ - assert(msg); - - return msg->state == MESSAGE_HIDING && msg->elapsed >= MESSAGE_SPEED; -}
--- a/src/message.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * message.h -- message 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. - */ - -#ifndef MOLKO_MESSAGE_H -#define MOLKO_MESSAGE_H - -/** - * \file message.h - * \brief Message dialog. - */ - -#include <stdbool.h> - -struct sprite; -struct font; - -/** - * \brief Message flags. - */ -enum message_flags { - MESSAGE_AUTOMATIC = (1 << 0) /*!< Message will automatically close */ -}; - -/** - * \brief Message state. - */ -enum message_state { - MESSAGE_OPENING, /*!< Message animation is opening */ - MESSAGE_SHOWING, /*!< Message is displaying */ - MESSAGE_HIDING /*!< Message animation for hiding */ -}; - -/** - * \brief Message object. - */ -struct message { - const char *text[3]; /*!< (RW) lines of text to show */ - struct sprite *theme; /*!< (RW) sprite to use for the frame */ - struct texture *avatar; /*!< (RW) optional avatar */ - struct font *font; /*!< (RW) font to use */ - enum message_flags flags; /*!< (RW) message flags */ - enum message_state state; /*!< (RO) current state */ - unsigned int elapsed; /*!< (RW) elapsed time while displaying */ -}; - -/** - * Start opening the message. This function will reset the message state and - * elapsed time. - * - * \pre msg != NULL - * \param msg the message - */ -void -message_start(struct message *msg); - -/** - * Update the message state and elapsed time.. - * - * \pre msg != NULL - * \param msg the message - * \param ticks the elapsed delay since last frame - */ -void -message_update(struct message *msg, unsigned int ticks); - -/** - * Draw the message into the screen. - * - * \pre msg != NULL - * \param msg the message - */ -void -message_draw(struct message *msg); - -/** - * Start hiding the message. - * - * \pre msg != NULL - * \param msg the message - * \note You should still continue to draw the message as the animation is not - * finished! - */ -void -message_hide(struct message *msg); - -/** - * Tells if the message is complete. - * - * \pre msg != NULL - * \param msg the message - */ -bool -message_is_complete(struct message *msg); - -#endif /* !MOLKO_MESSAGE_H */
--- a/src/mouse.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * mouse.h -- mouse definitions - * - * 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_MOUSE_H -#define MOLKO_MOUSE_H - -/** - * \file mouse.h - * \brief Mouse definitions. - */ - -/** - * \brief Buttons from mouse. - * - * This enumeration is used as both flags or constants. For example when the - * user press one button on the mouse it generates one constant event. On the - * other hand, while moving the mouse the user may have one or more buttons - * pressed, thus the OR'ed combination. - */ -enum mouse_button { - MOUSE_BUTTON_UNKNOWN = 0, /*!< No buttons pressed */ - MOUSE_BUTTON_LEFT = (1 << 0), /*!< Left button pressed */ - MOUSE_BUTTON_MIDDLE = (1 << 1), /*!< Middle button pressed */ - MOUSE_BUTTON_RIGHT = (1 << 2) /*!< Right button pressed */ -}; - -#endif /* !MOLKO_MOUSE_H */
--- a/src/painter.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * painter.c -- basic drawing routines - * - * 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 "color.h" -#include "painter.h" -#include "texture_p.h" -#include "window_p.h" - -static struct texture *renderer; - -struct texture * -painter_get_target(void) -{ - return renderer; -} - -void -painter_set_target(struct texture *tex) -{ - renderer = tex; - SDL_SetRenderTarget(win.renderer, tex ? tex->handle : NULL); -} - -unsigned long -painter_get_color(void) -{ - Uint8 r = 0, g = 0, b = 0, a = 0; - - SDL_GetRenderDrawColor(win.renderer, &r, &g, &b, &a); - - return COLOR_HEX(r, g, b, a); -} - -void -painter_set_color(unsigned long color) -{ - SDL_SetRenderDrawColor( - win.renderer, - COLOR_R(color), - COLOR_G(color), - COLOR_B(color), - COLOR_A(color) - ); -} - -void -painter_draw_line(int x1, int y1, int x2, int y2) -{ - SDL_RenderDrawLine(win.renderer, x1, y1, x2, y2); -} - -void -painter_draw_point(int x1, int y1) -{ - SDL_RenderDrawPoint(win.renderer, x1, y1); -} - -void -painter_draw_rectangle(bool fill, int x, int y, unsigned int width, unsigned int height) -{ - const SDL_Rect rect = { - .w = width, - .h = height, - .x = x, - .y = y - }; - - if (fill) - SDL_RenderFillRect(win.renderer, &rect); - else - SDL_RenderDrawRect(win.renderer, &rect); -} - -void -painter_clear(void) -{ - SDL_RenderClear(win.renderer); -} - -void -painter_present(void) -{ - SDL_RenderPresent(win.renderer); -}
--- a/src/painter.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* - * painter.h -- basic drawing routines - * - * 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_PAINTER_H -#define MOLKO_PAINTER_H - -/** - * \file painter.h - * \brief Basic drawing routines. - */ - -#include <stdbool.h> - -struct texture; - -/** - * Give the current texture being used for rendering, maybe NULL if the - * rendering is on root. - * - * \return texture or NULL - */ -struct texture * -painter_get_target(void); - -/** - * Set the rendering context to the given texture. - * - * Since this function change an internal global variable it is strongly - * encouraged to store a local backup of the current texture using \a - * painter_get_target and call this function with it afterwards. - * - * If texture is NULL, use default context aka the window. - * - * \param tex the texture - * \see PAINTER_BEGIN - * \see PAINTER_END - */ -void -painter_set_target(struct texture *tex); - -/** - * Get the current drawing color. - * - * \return the color in RRGGBBAA format - */ -unsigned long -painter_get_color(void); - -/** - * Set the rendering drawing color. - * - * \param color in RRGGBBAA format - */ -void -painter_set_color(unsigned long color); - -/** - * Draw a line. - * - * \param x1 first X coordinate - * \param y1 first Y coordinate - * \param x2 second X coordinate - * \param y2 second Y coordinate - */ -void -painter_draw_line(int x1, int y1, int x2, int y2); - -/** - * Draw a pixel point. - * - * \param x the X coordinate - * \param y the Y coordinate - */ -void -painter_draw_point(int x, int y); - -/** - * Draw a rectangle - * - * \param fill set to true to fill the rectangle - * \param x the X coordinate - * \param y the Y coordinate - * \param w the rectangle width - * \param h the rectangle height - */ -void -painter_draw_rectangle(bool fill, int x, int y, unsigned int w, unsigned int h); - -/** - * Clear the window. - */ -void -painter_clear(void); - -/** - * Present the window, only call this function one time in the main loop. - */ -void -painter_present(void); - -/** - * Use this macro to start painting on the texture to store the current - * rendering context and put it back afterwards. - * - * \pre tex != NULL - * \param tex the texture to use - * \see PAINTER_END - */ -#define PAINTER_BEGIN(tex ) \ -do { \ - struct texture *__current_texture__; \ - \ - __current_texture__ = painter_get_target(); \ - painter_set_target((tex)) - -/** - * Use this macro at the end of rendering into a given texture. - * - * \see PAINTER_BEGIN - */ -#define PAINTER_END() \ - painter_set_target(__current_texture__); \ -} while (0) - -#endif /* !MOLKO_PAINTER_H */
--- a/src/splashscreen.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * splashscreen.c -- splash screen state - * - * 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 "error.h" -#include "font.h" -#include "game.h" -#include "image.h" -#include "map.h" -#include "map_state.h" -#include "painter.h" -#include "splashscreen.h" -#include "state.h" -#include "sys.h" -#include "texture.h" -#include "window.h" - -#define DELAY 3000 - -static unsigned int elapsed; -static struct font *font; -static struct texture *text; -static int x; -static int y; - -static void -enter(void) -{ - if (!(font = font_openf(sys_datapath("fonts/knights-quest.ttf"), 160))) - error_fatal(); - if (!(text = font_render(font, "Molko's Adventure", 0x000000ff))) - error_fatal(); - - /* Compute position. */ - const unsigned int w = texture_width(text); - const unsigned int h = texture_height(text); - - x = (window_width() / 2) - (w / 2); - y = (window_height() / 2) - (h / 2) - 100; -} - -static void -leave(void) -{ - font_close(font); -} - -static void -handle(const union event *event) -{ - (void)event; -} - -static void -update(unsigned int ticks) -{ - elapsed += ticks; - - /* TODO: change this once map is done. */ - if (elapsed >= DELAY) { - /* TODO: this will be removed too. */ - static struct texture *image; - - if (!map_open(&map_state_data.map.map, sys_datapath("maps/test.map"))) - error_fatal(); - if (!(image = image_openf(sys_datapath("sprites/test-walk.png")))) - error_fatal(); - - sprite_init(&map_state_data.player.sprite, image, 48, 48); - game_switch(&map_state, false); - } -} - -static void -draw(void) -{ - painter_set_color(0xffffffff); - painter_clear(); - texture_draw(text, x, y); - painter_present(); -} - -struct state splashscreen_state = { - .enter = enter, - .leave = leave, - .handle = handle, - .update = update, - .draw = draw -};
--- a/src/splashscreen.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * splashscreen.h -- splash screen state - * - * 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_SPLASHSCREEN_H -#define MOLKO_SPLASHSCREEN_H - -/** - * \file splashscreen.h - * \brief Splash screen state. - */ - -/** - * \brief Splash screen state. - */ -extern struct state splashscreen_state; - -#endif /* !MOLKO_SPLASHSCREEN_H */
--- a/src/sprite.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * sprite.c -- image 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 <assert.h> - -#include "sprite.h" -#include "texture_p.h" -#include "texture.h" - -void -sprite_init(struct sprite *sprite, - struct texture *tex, - unsigned int cellw, - unsigned int cellh) -{ - int w = 0; - int h = 0; - - assert(sprite); - assert(tex); - - /* TODO: use texture_get_size */ - SDL_QueryTexture(tex->handle, NULL, NULL, &w, &h); - - sprite->texture = tex; - sprite->cellw = cellw; - sprite->cellh = cellh; - sprite->nrows = h / cellh; - sprite->ncols = w / cellw; -} - -void -sprite_draw(struct sprite *sprite, unsigned int r, unsigned int c, int x, int y) -{ - assert(sprite); - - texture_draw_ex( - sprite->texture, - c * sprite->cellw, /* src y */ - r * sprite->cellh, /* src x */ - sprite->cellw, /* src width */ - sprite->cellh, /* src height */ - x, /* dst x */ - y, /* dst y */ - sprite->cellw, /* dst width */ - sprite->cellh, /* dst height */ - 0.0 /* angle */ - ); -}
--- a/src/sprite.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * sprite.h -- image 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. - */ - -#ifndef MOLKO_SPRITE_H -#define MOLKO_SPRITE_H - -/** - * \file sprite.h - * \brief Image sprites. - */ - -struct texture; - -/** - * \brief Sprite structure. - */ -struct sprite { - struct texture *texture; /*!< Texture to access (RO) */ - unsigned int cellw; /*!< Width per cell (RW) */ - unsigned int cellh; /*!< Height per cell (RW) */ - unsigned int nrows; /*!< Number of rows (RW) */ - unsigned int ncols; /*!< Number of columns (RW) */ -}; - -/** - * Initialize a sprite. - * - * The sprite does not take ownership of texture and must be valid until the - * sprite is no longer used. - * - * This function is only provided as convenience, user may initialize the - * sprite by itself if wanted. - * - * The fields `nrows' and `ncols' will be determined automatically from the - * texture size. - * - * \pre sprite != NULL - * \pre tex != NULL - * \param sprite the sprite to initialize - * \param tex the texture - * \param cellw the width per cell in pixels - * \param cellh the height per cell in pixels - */ -void -sprite_init(struct sprite *sprite, - struct texture *tex, - unsigned int cellw, - unsigned int cellh); - -/** - * Draw the sprite component from row `r' and column `c'. - * - * \pre sprite != NULL - * \param sprite the sprite to draw - * \param r the row number - * \param c the column number - * \param x the X destination - * \param y the Y destination - * \warning No bounds checking - */ -void -sprite_draw(struct sprite *sprite, unsigned int r, unsigned int c, int x, int y); - -#endif /* !MOLKO_SPRITE_H */
--- a/src/state.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * state.h -- abstract state - * - * 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_STATE_H -#define MOLKO_STATE_H - -/** - * \file state.h - * \brief Abstract state. - */ - -union event; - -/** - * \brief Abstract state. - */ -struct state { - /** - * This function is called when the state is entered. - */ - void (*enter)(void); - - /** - * This function is called when the state is about to be left. - */ - void (*leave)(void); - - /** - * This function is called for each event that happened. - */ - void (*handle)(const union event *); - - /** - * This function is called to update the game, with the number of - * milliseconds since the last frame. - */ - void (*update)(unsigned int ticks); - - /** - * This function is supposed to draw the game. - */ - void (*draw)(void); -}; - -#endif /* !MOLKO_STATE_H */
--- a/src/sys.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -/* - * sys.c -- system routines - * - * 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 <SDL.h> -#include <SDL_image.h> -#include <SDL_mixer.h> -#include <SDL_ttf.h> - -#if !defined(_WIN32) /* Assuming POSIX */ -# include <sys/types.h> -# include <dirent.h> -#endif - -#include "error.h" -#include "error_p.h" -#include "sys.h" - -#if defined(_WIN32) - -static void -determine(char path[], size_t pathlen) -{ - char *base = SDL_GetBasePath(); - - /* On Windows, the data hierarchy is the same as the project. */ - snprintf(path, pathlen, "%sassets", base); - SDL_free(base); -} - -#else /* Assuming POSIX */ - -static bool -is_absolute(const char *path) -{ - assert(path); - - return path[0] == '/'; -} - -static void -determine(char path[], size_t pathlen) -{ - char localassets[FILENAME_MAX]; - char *base = SDL_GetBasePath(); - DIR *dp; - - /* Try assets directory where executable lives. */ - snprintf(localassets, sizeof (localassets), "%sassets", base); - - if ((dp = opendir(localassets))) { - snprintf(path, pathlen, "%sassets", base); - closedir(dp); - } else { - /* We are not in the project source directory. */ - if (is_absolute(SHAREDIR)) { - /* SHAREDIR is absolute */ - snprintf(path, pathlen, "%s/molko", SHAREDIR); - } else if (is_absolute(BINDIR)) { - /* SHAREDIR is relative but BINDIR is absolute */ - snprintf(path, pathlen, "%s/%s/molko", PREFIX, SHAREDIR); - } else { - /* SHAREDIR, BINDIR are both relative */ - char *ptr = strstr(base, BINDIR); - - if (ptr) { - *ptr = '\0'; - snprintf(path, pathlen, "%s%s/molko", base, SHAREDIR); - } else { - /* Unable to determine. */ - snprintf(path, pathlen, "."); - } - } - } - - SDL_free(base); -} - -#endif - -bool -sys_init(void) -{ -#if defined(__MINGW64__) - /* On MinGW buffering leads to painful debugging. */ - setvbuf(stdout, NULL, _IONBF, 0); -#endif - - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) - return error_sdl(); - if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) - return error_sdl(); - if (TTF_Init() < 0) - return error_sdl(); - if (Mix_Init(MIX_INIT_OGG) != MIX_INIT_OGG) - return error_sdl(); - - return true; -} - -const char * -sys_datadir(void) -{ - static char path[1024]; - - if (path[0] == '\0') - determine(path, sizeof (path)); - - return path; -} - -const char * -sys_datapath(const char *fmt, ...) -{ - const char *ret; - va_list ap; - - va_start(ap, fmt); - ret = sys_datapathv(fmt, ap); - va_end(ap); - - return ret; -} - -const char * -sys_datapathv(const char *fmt, va_list ap) -{ - static char path[2048 + FILENAME_MAX]; - char filename[FILENAME_MAX]; - - vsnprintf(filename, sizeof (filename), fmt, ap); - snprintf(path, sizeof (path), "%s/%s", sys_datadir(), filename); - - return path; -} - -void -sys_close(void) -{ - Mix_Quit(); - TTF_Quit(); - IMG_Quit(); - SDL_Quit(); -}
--- a/src/sys.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * sys.h -- system routines - * - * 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_SYS_H -#define MOLKO_SYS_H - -/** - * \file sys.h - * \brief System routines. - */ - -#include <stdarg.h> -#include <stdbool.h> - -/** - * Initialize the system, should be called in the beginning of the main. - */ -bool -sys_init(void); - -/** - * Get the base system directory path. - * - * \return the path where the executable lives - */ -const char * -sys_datadir(void); - -/** - * Construct path to assets directory using printf-like format. - * - * \param fmt the format string - * \return the path to the file - * \note This function returns pointer to static string. - */ -const char * -sys_datapath(const char *fmt, ...); - -/** - * Similar to \a sys_datapath. - * - * \param fmt the format string - * \param ap the variadic arguments pointer - * \return the path to the file - * \note This function returns pointer to static string. - */ -const char * -sys_datapathv(const char *fmt, va_list ap); - -/** - * Close the system. - */ -void -sys_close(void); - -#endif /* !MOLKO_SYS_H */
--- a/src/texture.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* - * texture.c -- basic texture management - * - * 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 "error.h" -#include "error_p.h" -#include "texture.h" -#include "texture_p.h" -#include "util.h" -#include "window_p.h" - -struct texture * -texture_new(unsigned int w, unsigned int h) -{ - struct texture *tex = emalloc(sizeof (struct texture)); - - if (!(tex->handle = SDL_CreateTexture(win.renderer, - SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h))) { - error_sdl(); - free(tex); - return NULL; - } - - return tex; -} - -unsigned int -texture_width(struct texture *tex) -{ - assert(tex); - - int width; - - if (SDL_QueryTexture(tex->handle, NULL, NULL, &width, NULL) < 0) - return 0; - - return width; -} - -unsigned int -texture_height(struct texture *tex) -{ - assert(tex); - - int height; - - if (SDL_QueryTexture(tex->handle, NULL, NULL, NULL, &height) < 0) - return 0; - - return height; -} - -void -texture_draw(struct texture *tex, int x, int y) -{ - SDL_Rect dst = { - .x = x, - .y = y, - .w = 0, - .h = 0 - }; - - assert(tex); - - /* We need to determine size */ - SDL_QueryTexture(tex->handle, NULL, NULL, &dst.w, &dst.h); - SDL_RenderCopy(win.renderer, tex->handle, NULL, &dst); -} - -void -texture_draw_ex(struct texture *tex, - int src_x, - int src_y, - unsigned src_w, - unsigned src_h, - int dst_x, - int dst_y, - unsigned dst_w, - unsigned dst_h, - double angle) -{ - const SDL_Rect src = { - .x = src_x, - .y = src_y, - .w = src_w, - .h = src_h - }; - const SDL_Rect dst = { - .x = dst_x, - .y = dst_y, - .w = dst_w, - .h = dst_h - }; - - SDL_RenderCopyEx(win.renderer, tex->handle, &src, &dst, angle, NULL, SDL_FLIP_NONE); -} - -void -texture_close(struct texture *tex) -{ - assert(tex); - - SDL_DestroyTexture(tex->handle); - free(tex); -} - -/* private */ - -struct texture * -texture_from_surface(SDL_Surface *surface) -{ - assert(surface); - - struct texture *texture = ecalloc(1, sizeof (struct texture)); - - if (!(texture->handle = SDL_CreateTextureFromSurface(win.renderer, surface))) { - error_sdl(); - free(texture); - return NULL; - } - - return texture; -}
--- a/src/texture.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * texture.h -- basic texture management - * - * 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_TEXTURE_H -#define MOLKO_TEXTURE_H - -/** - * \file texture.h - * \brief Basic texture management. - * - * See also \a image.h for usage of textures. - */ - -#include <stdbool.h> - -/** - * \brief Texture object. - * - * This object is not publicly defined because it contains - * implementation-defined data. - */ -struct texture; - -/** - * Create a new texture. - * - * \param w the width - * \param h the height - * \return the texture or NULL on error - */ -struct texture * -texture_new(unsigned int w, unsigned int h); - -/** - * Get texture width. - * - * \pre tex != NULL - * \param tex the texture - * \return the width - */ -unsigned int -texture_width(struct texture *tex); - -/** - * Get texture height. - * - * \pre tex != NULL - * \param tex the texture - * \return the height - */ -unsigned int -texture_height(struct texture *tex); - -/** - * Simple texture drawing. - * - * \pre tex != NULL - * \param tex the texture - * \param x the X coordinate - * \param y the Y coordinate - */ -void -texture_draw(struct texture *tex, int x, int y); - -/** - * Advanced texture drawing. - * - * \pre tex != NULL - * \param tex the texture - * \param src_x the source rectangle X coordinate - * \param src_y the source rectangle Y coordinate - * \param src_w the source rectangle width - * \param src_h the source rectangle height - * \param dst_x the destination rectangle X coordinate - * \param dst_y the destination rectangle Y coordinate - * \param dst_w the destination rectangle width - * \param dst_h the destination rectangle height - * \param angle the angle - */ -void -texture_draw_ex(struct texture *tex, - int src_x, - int src_y, - unsigned src_w, - unsigned src_h, - int dst_x, - int dst_y, - unsigned dst_w, - unsigned dst_h, - double angle); - -/** - * Close the texture, do not use afterwards. - * - * \pre tex != NULL - * \param tex the texture - */ -void -texture_close(struct texture *tex); - -#endif /* !MOLKO_TEXTURE_H */
--- a/src/texture_p.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * texture_p.h -- (PRIVATE) basic texture management - * - * 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_TEXTURE_P_H -#define MOLKO_TEXTURE_P_H - -#include <SDL.h> - -struct texture { - SDL_Texture *handle; -}; - -struct texture * -texture_from_surface(SDL_Surface *surface); - -#endif /* !MOLKO_TEXTURE_P_H */
--- a/src/util.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * util.c -- utilities - * - * 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 <errno.h> -#include <stdlib.h> -#include <string.h> - -#include <SDL.h> - -#include "util.h" -#include "error.h" - -void * -emalloc(size_t size) -{ - void *mem; - - if (!(mem = malloc(size))) - error_fatalf("%s\n", strerror(errno)); - - return mem; -} - -void * -ecalloc(size_t n, size_t size) -{ - void *mem; - - if (!(mem = calloc(n, size))) - error_fatalf("%s\n", strerror(errno)); - - return mem; -} - -void -delay(unsigned int ms) -{ - SDL_Delay(ms); -}
--- a/src/util.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * util.h -- utilities - * - * 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_UTIL_H -#define MOLKO_UTIL_H - -#include <stddef.h> - -/** - * Get the number of elements in a static array. - * - * \param x the array - * \return the number of elements - */ -#define nelem(x) sizeof ((x)) / sizeof ((x)[0]) - -/** - * Wrapper around malloc(3) that exits on allocation failure. - * - * \param size the size - * \return a pointer - * \post returned pointer will never be NULL - */ -void * -emalloc(size_t size); - -/** - * Wrapper around calloc(3) that exits on allocation failure. - * - * \param n the number of objects to allocate - * \param size the size per n - * \return a pointer - * \post returned pointer will never be NULL - */ -void * -ecalloc(size_t n, size_t size); - -/** - * Put the thread to sleep for a given amount of milliseconds. - * - * \param ms the number of milliseconds to wait - */ -void -delay(unsigned int ms); - -#endif /* !MOLKO_UTIL_H */
--- a/src/walksprite.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * walksprite.c -- sprite designed for walking entities - * - * 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 <string.h> - -#include "walksprite.h" -#include "sprite.h" - -void -walksprite_init(struct walksprite *ws, struct sprite *sprite, unsigned int delay) -{ - assert(ws); - assert(sprite); - - memset(ws, 0, sizeof (struct walksprite)); - ws->sprite = sprite; - ws->delay = delay; -} - -void -walksprite_update(struct walksprite *ws, unsigned int ticks) -{ - assert(ws); - - ws->elapsed += ticks; - - if (ws->elapsed >= ws->delay) { - ws->index += 1; - - if (ws->index >= ws->sprite->ncols) - ws->index = 0; - - ws->elapsed = 0; - } -} - -void -walksprite_draw(struct walksprite *ws, unsigned int orientation, int x, int y) -{ - assert(ws); - assert(orientation < 8); - - sprite_draw(ws->sprite, orientation, ws->index, x, y); -}
--- a/src/walksprite.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * walksprite.h -- sprite designed for walking entities - * - * 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_WALKSPRITE_H -#define MOLKO_WALKSPRITE_H - -/** - * \file walksprite.h - * \brief Sprite designed for walking entities. - */ - -struct sprite; - -/** - * \brief Sprite designed for walking entities. - * - * This structure works with sprite images that are defined as using the - * following conventions: - * - * ``` - * 7 0 1 - * ↖ ↑ ↗ - * 6 ← → 2 - * ↙ ↓ ↘ - * 5 4 3 - * ``` - * - * Where numbers define row in the sprite according to the character - * orientation. In other terms, your image sprite should look like this: - * - * ``` - * row columns in your image - * ---|--------------------- - * 0 | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ - * 1 | ↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗↗ - * 2 | →→→→→→→→→→→→→→→→→→→→ - * 3 | ↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘↘ - * 4 | ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ - * 5 | ↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙↙ - * 6 | ←←←←←←←←←←←←←←←←←←←← - * 7 | ↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖↖ - * ``` - */ -struct walksprite { - struct sprite *sprite; /*!< (RW) The sprite to use */ - unsigned int delay; /*!< (RW) The delay between frames */ - unsigned int index; /*!< (RO) Current column index */ - unsigned int elapsed; /*!< (RO) Elapsed time since last frame */ -}; - -/** - * Initialize the walking sprite. - * - * \pre ws != NULL - * \pre sprite != NULL - * \param ws the walking sprite - * \param sprite the sprite to use - * \param delay the delay between sprites - */ -void -walksprite_init(struct walksprite *ws, struct sprite *sprite, unsigned int delay); - -/** - * Update the walking sprite - * - * \pre ws != NULL - * \param ws the walking sprite - * \param ticks the number of milliseconds between last frame - */ -void -walksprite_update(struct walksprite *ws, unsigned int ticks); - -/** - * Draw the appropriate sprite cell to the screen according to the orientation - * given. - * - * \pre ws != NULL - * \pre orientation < 8 - * \param ws the walking sprite - * \param orientation the orientation (or the row between 0 and 7) - * \param x the x coordinate - * \param y the y coordinate - */ -void -walksprite_draw(struct walksprite *ws, unsigned int orientation, int x, int y); - -#endif /* !MOLKO_WALKSPRITE_H */
--- a/src/window.c Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * window.c -- basic window management - * - * 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 <SDL.h> - -#include "error_p.h" -#include "window.h" -#include "window_p.h" - -/* global object, used by textures */ -struct window win = { - .win = NULL, - .renderer = NULL -}; - -bool -window_init(const char *title, unsigned int width, unsigned int height) -{ - assert(title); - - if (SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL, - &win.win, &win.renderer) < 0) - return error_sdl(); - - SDL_SetWindowTitle(win.win, title); - - return true; -} - -unsigned int -window_width(void) -{ - int width; - - SDL_GetWindowSize(win.win, &width, NULL); - - return width; -} - -unsigned int -window_height(void) -{ - int height; - - SDL_GetWindowSize(win.win, NULL, &height); - - return height; -} - -void -window_close(void) -{ - SDL_DestroyRenderer(win.renderer); - SDL_DestroyWindow(win.win); -}
--- a/src/window.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * window.h -- basic window management - * - * 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_WINDOW_H -#define MOLKO_WINDOW_H - -/** - * \file window.h - * \brief Basic window management. - */ - -#include <stdbool.h> - -/** - * Initialize window. - * - * \pre title != NULL - * \param title the window title - * \param width the desired width - * \param height the desired height - * \return true on success - */ -bool -window_init(const char *title, unsigned int width, unsigned int height); - -/** - * Get the current window's width. - * - * \return the width - */ -unsigned int -window_width(void); - -/** - * Get the current window's height. - * - * \return the height - */ -unsigned int -window_height(void); - -/** - * Close the window and destroy associated resources. - */ -void -window_close(void); - -#endif /* !MOLKO_WINDOW_H */
--- a/src/window_p.h Tue Jan 21 12:31:56 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * window.c -- (PRIVATE) basic window management - * - * 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_WINDOW_P_H -#define MOLKO_WINDOW_P_H - -#include <SDL.h> - -struct window { - SDL_Window *win; - SDL_Renderer *renderer; -}; - -/* Global window object */ -extern struct window win; - -#endif /* !MOLKO_WINDOW_P_H */