Player animations

This commit is contained in:
KikooDX 2021-04-21 17:51:59 +02:00
parent 795f0ef5c1
commit f9df721d54
20 changed files with 177 additions and 62 deletions

View File

@ -8,6 +8,7 @@ include(GenerateG3A)
include(Fxconv)
find_package(Gint 2.3 REQUIRED)
find_package(LibImg 2.2 REQUIRED)
add_custom_target(filepaths
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
@ -55,7 +56,6 @@ set(SOURCES
set(ASSETS
assets/graphics/tileset.png
assets/graphics/player.png
assets/graphics/burst.png
assets/graphics/coin-particle.png
assets/graphics/switch-particle.png
@ -63,6 +63,10 @@ set(ASSETS
assets/graphics/exit-active-particle.png
assets/graphics/exit-unlock-particle.png
assets/graphics/font.png
assets/graphics/player/blink.png
assets/graphics/player/idle.png
assets/graphics/player/jump.png
assets/graphics/player/walk.png
)
set(FLAGS
@ -77,6 +81,7 @@ add_executable(${PROJECT_NAME} ${SOURCES} ${ASSETS})
add_dependencies(${PROJECT_NAME} filepaths)
target_compile_options(${PROJECT_NAME} PRIVATE ${FLAGS})
target_link_libraries(${PROJECT_NAME} Gint::Gint)
target_link_libraries(${PROJECT_NAME} LibImg::LibImg)
generate_g3a(TARGET ${PROJECT_NAME}
OUTPUT "${PROJECT_NAME}.g3a"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 715 B

View File

@ -1,27 +1,27 @@
# gint bopti_image_t
tileset.png:
type: bopti-image
name: bimg_tileset
player.png:
type: bopti-image
name: bimg_player
burst.png:
type: bopti-image
name: bimg_burst
# libimg img_t
coin-particle.png:
type: bopti-image
name: bimg_coin_particle
type: libimg-image
name: img_coin_particle
switch-particle.png:
type: bopti-image
name: bimg_switch_particle
type: libimg-image
name: img_switch_particle
switch-activated-particle.png:
type: bopti-image
name: bimg_switch_activated_particle
type: libimg-image
name: img_switch_activated_particle
exit-active-particle.png:
type: bopti-image
name: bimg_exit_active_particle
type: libimg-image
name: img_exit_active_particle
exit-unlock-particle.png:
type: bopti-image
name: bimg_exit_unlock_particle
type: libimg-image
name: img_exit_unlock_particle
# Fonts
font.png:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

View File

@ -0,0 +1,12 @@
idle.png:
type: libimg-image
name: img_player_idle
walk.png:
type: libimg-image
name: img_player_walk
blink.png:
type: libimg-image
name: img_player_blink
jump.png:
type: libimg-image
name: img_player_jump

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

View File

@ -2,4 +2,11 @@
/* Copyright (C) 2021 KikooDX */
#pragma once
enum GameState { TitleScreen, MainMenu, LevelSelection, Playing, GamePause, PackDone };
enum GameState {
TitleScreen,
MainMenu,
LevelSelection,
Playing,
GamePause,
PackDone
};

View File

@ -2,12 +2,12 @@
/* Copyright (C) 2021 KikooDX */
#pragma once
#include <gint/display.h>
#include <libimg.h>
#define MAX_PARTICLES 64
struct Particle {
bopti_image_t *texture;
img_t *texture;
int x;
int y;
int frame_width;
@ -17,10 +17,15 @@ struct Particle {
int life_ini;
int life;
int looping;
int flip_h;
};
void particles_init(void);
void particles_update(void);
void particle_update(struct Particle *particle);
void particles_draw(void);
void particle_create(bopti_image_t *texture, int x, int y, int frame_width,
int frame_duration, int particles);
void particle_draw(struct Particle particle);
void particle_create(img_t *texture, int x, int y, int frame_width,
int frame_duration, int looping, int flip_h);
struct Particle particle_init(img_t *texture, int x, int y, int frame_width,
int frame_duration, int looping, int flip_h);

View File

@ -4,6 +4,7 @@
#include "input.h"
#include "level.h"
#include "particles.h"
#define PLAYER_WIDTH 10
#define PLAYER_HEIGHT 10
@ -23,6 +24,12 @@ struct Player {
int jump_grace;
int jumps_left;
enum AirState air_state;
/* animations */
struct Particle anim;
struct Particle blink_anim;
struct Particle idle_anim;
struct Particle jump_anim;
struct Particle walk_anim;
};
/* used for collisions */

View File

@ -19,7 +19,7 @@ int mainmenu_update(struct MainMenu *mainmenu, struct Input input)
}
/* increase selected pack id */
if (input.keystates[K_DOWN] == KS_PRESS ||
input.keystates[K_RIGHT] == KS_PRESS) {
input.keystates[K_RIGHT] == KS_PRESS) {
if (mainmenu->cursor < MENU_ENTRIES - 1)
mainmenu->cursor += 1;
else

View File

@ -6,24 +6,34 @@
extern struct Particle particles[MAX_PARTICLES];
void particle_create(bopti_image_t *texture, int x, int y, int frame_width,
int frame_duration, int looping)
void particle_create(img_t *texture, int x, int y, int frame_width,
int frame_duration, int looping, int flip_h)
{
/* find unused slot */
int i = MAX_PARTICLES;
while (i-- > 0)
if (!particles[i].life)
break;
struct Particle *particle = &particles[i];
particle->texture = texture;
particle->x = x;
particle->y = y;
particle->frame_width = frame_width;
particle->frame_height = texture->height;
particle->frame_duration = frame_duration;
particle->frame = 0;
particle->life_ini = frame_duration * texture->width / frame_width;
particle->life = particle->life_ini;
particle->looping = looping;
particles[i] = particle_init(texture, x, y, frame_width, frame_duration,
looping, flip_h);
}
struct Particle particle_init(img_t *texture, int x, int y, int frame_width,
int frame_duration, int looping, int flip_h)
{
struct Particle particle;
particle.texture = texture;
particle.x = x;
particle.y = y;
particle.frame_width = frame_width;
particle.frame_height = texture->height;
particle.frame_duration = frame_duration;
particle.frame = 0;
particle.life_ini = frame_duration * texture->width / frame_width;
particle.life = particle.life_ini;
particle.looping = looping;
particle.flip_h = flip_h;
return particle;
}

View File

@ -2,12 +2,10 @@
/* Copyright (C) 2021 KikooDX */
#include "particles.h"
#include <gint/display.h>
#include <libimg.h>
extern struct Particle particles[MAX_PARTICLES];
static void particle_draw(struct Particle particle);
void particles_draw(void)
{
int i = MAX_PARTICLES;
@ -15,12 +13,36 @@ void particles_draw(void)
particle_draw(particles[i]);
}
static void particle_draw(struct Particle particle)
void particle_draw(struct Particle particle)
{
if (!particle.life)
return;
dsubimage(particle.x, particle.y, particle.texture,
particle.frame * particle.frame_width, 0,
particle.frame_width, particle.frame_height, DIMAGE_NOCLIP);
/* create image to apply transformations on */
/* alloc */
const img_t transformed_img =
img_create(particle.frame_width, particle.frame_height);
/* check */
if (img_null(transformed_img))
return;
/* fill image with transparent */
img_fill(transformed_img, IMG_ALPHA);
/* get frame subimage */
const img_t frame_simg =
img_sub(*particle.texture, particle.frame * particle.frame_width, 0,
particle.frame_width, particle.frame_height);
/* apply transformations if needed */
if (particle.flip_h)
img_hflip(frame_simg, transformed_img);
else
img_render(frame_simg, transformed_img);
/* render image */
img_render_vram(transformed_img, particle.x, particle.y);
/* free */
img_destroy(transformed_img);
}

View File

@ -5,8 +5,6 @@
extern struct Particle particles[MAX_PARTICLES];
static void particle_update(struct Particle *particle);
void particles_update(void)
{
int i = MAX_PARTICLES;
@ -14,7 +12,7 @@ void particles_update(void)
particle_update(&particles[i]);
}
static void particle_update(struct Particle *particle)
void particle_update(struct Particle *particle)
{
if (!particle->life)
return;

View File

@ -10,11 +10,11 @@
extern struct Level level;
extern bopti_image_t bimg_coin_particle;
extern bopti_image_t bimg_switch_particle;
extern bopti_image_t bimg_switch_activated_particle;
extern bopti_image_t bimg_exit_active_particle;
extern bopti_image_t bimg_exit_unlock_particle;
extern img_t img_coin_particle;
extern img_t img_switch_particle;
extern img_t img_switch_activated_particle;
extern img_t img_exit_active_particle;
extern img_t img_exit_unlock_particle;
static Tile collide_single(int x, int y);
static int collide_sub_single(int x, int y, Tile sub, Tile rep);
@ -88,16 +88,16 @@ static int collide_sub_single(int x, int y, Tile sub, Tile rep)
/* spawn animations */
switch (sub) {
case TILE_GOLD:
particle_create(&bimg_coin_particle, px, py, TILE_WIDTH,
2, 0);
particle_create(&img_coin_particle, px, py, TILE_WIDTH,
2, 0, 0);
break;
case TILE_SWITCH:
/* still image */
particle_create(&bimg_switch_activated_particle, px, py,
TILE_WIDTH, 1, 1);
particle_create(&img_switch_activated_particle, px, py,
TILE_WIDTH, 1, 1, 0);
/* activation animation */
particle_create(&bimg_switch_particle, px, py,
TILE_WIDTH, 8, 0);
particle_create(&img_switch_particle, px, py,
TILE_WIDTH, 8, 0, 0);
/* exit unlock animation */
{
int ty = level.height;
@ -115,10 +115,10 @@ static int collide_sub_single(int x, int y, Tile sub, Tile rep)
found:
tx *= TILE_WIDTH;
ty *= TILE_HEIGHT;
particle_create(&bimg_exit_active_particle, tx,
ty, TILE_WIDTH, 2, 1);
particle_create(&bimg_exit_unlock_particle, tx,
ty, TILE_WIDTH, 4, 0);
particle_create(&img_exit_active_particle, tx,
ty, TILE_WIDTH, 2, 1, 0);
particle_create(&img_exit_unlock_particle, tx,
ty, TILE_WIDTH, 4, 0, 0);
}
break;
default:

View File

@ -4,20 +4,30 @@
#include "conf.h"
#include "filepaths.h"
#include "level.h"
#include "particles.h"
#include "player.h"
#include "zxcolors.h"
#include <gint/display.h>
extern struct Level level;
extern bopti_image_t bimg_player;
extern bopti_image_t bimg_burst;
void player_draw(struct Player player)
{
dimage(player.x, player.y, &bimg_player);
/* set animation position */
struct Particle anim = player.anim;
anim.x = player.x;
anim.y = player.y;
anim.x -= (anim.frame_width - PLAYER_WIDTH) / 2;
anim.y -= (anim.texture->height - PLAYER_HEIGHT) / 2;
/* draw animation */
particle_draw(anim);
/* draw burst */
if (player.air_state == AirRising && player.jumps_left < AIR_JUMPS)
dimage(player.x, player.y + PLAYER_HEIGHT, &bimg_burst);
/* print level name
* this shouldn't be in player code */
dprint_opt(DWIDTH - 4, DHEIGHT, ZX_WHITE, C_NONE, DTEXT_RIGHT,

View File

@ -3,11 +3,18 @@
#include "conf.h"
#include "level.h"
#include "particles.h"
#include "player.h"
#include "tiles.h"
#include <libimg.h>
extern struct Level level;
extern img_t img_player_blink;
extern img_t img_player_idle;
extern img_t img_player_jump;
extern img_t img_player_walk;
struct Player player_init(void)
{
int x = 0;
@ -23,6 +30,13 @@ struct Player player_init(void)
.air_state = AirNeutral,
};
/* initialize animations */
player.blink_anim = particle_init(&img_player_blink, 0, 0, 10, 4, 0, 0);
player.idle_anim = particle_init(&img_player_idle, 0, 0, 10, 1, 1, 1);
player.jump_anim = particle_init(&img_player_jump, 0, 0, 8, 6, 0, 0);
player.walk_anim = particle_init(&img_player_walk, 0, 0, 12, 6, 1, 0);
player.anim = player.idle_anim;
/* find spawn position in level */
x = level.width;
while (x-- > 0) {

View File

@ -4,6 +4,7 @@
#include "conf.h"
#include "input.h"
#include "level.h"
#include "particles.h"
#include "player.h"
#include "tiles.h"
#include <gint/keyboard.h>
@ -12,12 +13,16 @@ static void player_move(struct Player *player, int x, int y);
extern struct Level level;
/* return -1 on pause, return 1 if exit reached, 2 on death/reset and 0 otherwise */
/* return -1 on pause, return 1 if exit reached, 2 on death/reset and 0
* otherwise */
int player_update(struct Player *player, struct Input input)
{
Tile collisions[COLLIDE_POINTS];
const int on_ground = player_collide_solid(player->x, player->y + 1);
int jumped = 0;
const int previous_flip_h = player->anim.flip_h;
/* process input */
const int k_left = input.keystates[K_LEFT] != KS_UP;
const int k_right = input.keystates[K_RIGHT] != KS_UP;
@ -80,6 +85,7 @@ int player_update(struct Player *player, struct Input input)
/* jump (youhou) */
if (k_jump && player->jump_buffer &&
(player->jump_grace || player->jumps_left)) {
jumped = 1;
/* ground jump */
if (player->jump_grace) {
player->jump_grace = 0;
@ -128,6 +134,25 @@ int player_update(struct Player *player, struct Input input)
MARGIN_LETAL, 1)) {
return 2;
}
/* update animation */
if (jumped)
player->anim = player->jump_anim;
particle_update(&player->anim);
if (player->anim.life == 0) {
if (dir_x != 0)
player->anim = player->walk_anim;
else
player->anim = player->idle_anim;
}
/* horizontal flip */
player->anim.flip_h = previous_flip_h;
if (dir_x)
player->anim.flip_h = dir_x == -1;
return 0;
}