Mercurial > molko
changeset 7:fbb7101b7bd8
core: implement animations, closes #2439
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 06 Jan 2020 21:39:16 +0100 |
parents | 3054723e53d7 |
children | 106620648160 |
files | Makefile src/animation.c src/animation.h src/main.c src/sprite.c src/sprite.h src/window.c |
diffstat | 7 files changed, 249 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Mon Jan 06 21:27:45 2020 +0100 +++ b/Makefile Mon Jan 06 21:39:16 2020 +0100 @@ -21,7 +21,8 @@ CC= clang CFLAGS= -O3 -DNDEBUG -std=c99 -Wall -Wextra CPPFLAGS= -MMD -SRCS= src/clock.c \ +SRCS= src/animation.c \ + src/clock.c \ src/image.c \ src/main.c \ src/sprite.c \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/animation.c Mon Jan 06 21:39:16 2020 +0100 @@ -0,0 +1,82 @@ +/* + * 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, uint16_t 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 ticks) +{ + assert(an); + + an->elapsed += ticks; + + if (an->elapsed < an->delay) + return; + + an->elapsed = 0; + an->column += 1; + + if (an->column >= an->sprite->ncols) { + an->column = 0; + + if (++an->row >= an->sprite->nrows) + an->row = 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/animation.h Mon Jan 06 21:39:16 2020 +0100 @@ -0,0 +1,101 @@ +/* + * 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> +#include <stdint.h> + +struct sprite; + +/** + * \brief Animation object + */ +struct animation { + struct sprite *sprite; /* Sprite to use (RW) */ + uint16_t row; /* current row (RO) */ + uint16_t column; /* current column (RO) */ + uint16_t delay; /* delay between frames (RW) */ + uint16_t 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, uint16_t 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 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/main.c Mon Jan 06 21:27:45 2020 +0100 +++ b/src/main.c Mon Jan 06 21:39:16 2020 +0100 @@ -18,10 +18,12 @@ #include <stdio.h> -#include "window.h" +#include "animation.h" +#include "clock.h" #include "image.h" +#include "sprite.h" #include "texture.h" -#include "sprite.h" +#include "window.h" #include <SDL.h> @@ -33,10 +35,46 @@ struct texture *logo; struct sprite sprite; + struct clock clock; + struct animation animation; window_init("Molko's Adventure", 640, 480); window_set_color(0x667788ff); - window_clear(); + + clock_start(&clock); + + logo = image_openf("E:\\dev\\molko\\explosion.png"); + + if (!logo) + exit(1); + + sprite_init(&sprite, logo, 256, 256); + animation_init(&animation, &sprite, 20); + setvbuf(stdout, NULL, _IONBF, 0); + + for (;;) { + uint64_t ticks = clock_elapsed(&clock); + + clock_start(&clock); + + SDL_Event ev; + while (SDL_PollEvent(&ev)) { + switch (ev.type) { + case SDL_QUIT: + return 0; + } + } + + //animation_update(&animation, ticks); + window_clear(); + sprite_draw(&sprite, 4, 0, 10, 10); + //animation_draw(&animation, 10, 10); + window_present(); + printf("%llu\n", ticks); + SDL_Delay(50); + } + +#if 0 window_set_color(0xffffffff); window_draw_line(50, 50, 100, 100); window_draw_point(60, 60); @@ -44,9 +82,7 @@ logo = image_openf("E:\\Charactervector.png"); sprite_init(&sprite, logo, 65, 100); sprite_draw(&sprite, 1, 2, 400, 400); - - window_present(); - SDL_Delay(5000); +#endif return 0; }
--- a/src/sprite.c Mon Jan 06 21:27:45 2020 +0100 +++ b/src/sprite.c Mon Jan 06 21:39:16 2020 +0100 @@ -23,25 +23,32 @@ #include "texture.h" void -sprite_init(struct sprite *sprite, struct texture *tex, uint8_t cellw, uint8_t cellh) +sprite_init(struct sprite *sprite, struct texture *tex, uint16_t cellw, uint16_t cellh) { + int w = 0; + int h = 0; + assert(sprite); assert(tex); + 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 r, unsigned c, int x, int y) +sprite_draw(struct sprite *sprite, uint16_t r, uint16_t c, int x, int y) { assert(sprite); texture_draw_ex( sprite->texture, - r * sprite->cellw, /* src x */ - c * sprite->cellh, /* src y */ + c * sprite->cellw, /* src y */ + r * sprite->cellh, /* src x */ sprite->cellw, /* src width */ sprite->cellh, /* src height */ x, /* dst x */
--- a/src/sprite.h Mon Jan 06 21:27:45 2020 +0100 +++ b/src/sprite.h Mon Jan 06 21:39:16 2020 +0100 @@ -33,8 +33,11 @@ */ struct sprite { struct texture *texture; /* Texture to access (RO) */ - uint8_t cellw; /* Width per cell (RW) */ - uint8_t cellh; /* Hieight per cell (RW) */ + uint16_t cellw; /* Width per cell (RW) */ + uint16_t cellh; /* Height per cell (RW) */ + uint16_t nrows; /* Number of rows (RW) */ + uint16_t ncols; /* Number of columns (RW) */ + }; /** @@ -46,6 +49,9 @@ * 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 @@ -56,8 +62,8 @@ void sprite_init(struct sprite *sprite, struct texture *tex, - uint8_t cellw, - uint8_t cellh); + uint16_t cellw, + uint16_t cellh); /** * Draw the sprite component from row `r' and column `c'. @@ -70,6 +76,6 @@ * \warning No bounds checking */ void -sprite_draw(struct sprite *sprite, unsigned r, unsigned c, int x, int y); +sprite_draw(struct sprite *sprite, uint16_t r, uint16_t c, int x, int y); #endif /* !MOLKO_SPRITE_H */