items on the floor

This commit is contained in:
Lephenixnoir 2022-02-16 17:42:05 +01:00
parent e87fa3b6ec
commit bca71726db
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
17 changed files with 135 additions and 20 deletions

View File

@ -20,6 +20,7 @@ set(SOURCES
src/enemies.c
src/game.c
src/geometry.c
src/item.c
src/main.c
src/map.c
src/menu.c
@ -56,6 +57,9 @@ set(ASSETS
assets-cg/hud_xp.ase
assets-cg/skillicons.png
assets-cg/font_hud.png
# Items
assets-cg/items/life.aseprite
assets-cg/items/sword1.aseprite
# Player animations
assets-cg/player/player_up.aseprite
assets-cg/player/player_right.aseprite

View File

@ -0,0 +1,5 @@
*.aseprite:
custom-type: aseprite-anim
name_regex: (.*)\.aseprite frames_item_\1
next: Item=Item
profile: p4

Binary file not shown.

Binary file not shown.

View File

@ -75,6 +75,10 @@ ANIM1(hud_xp_Idle);
ANIM1(hud_xp_Shine);
ANIM1(hud_xp_Explode);
/* Items */
ANIM1(item_life);
ANIM1(item_sword1);
/* Animation functions. */
fixed_t (anim_duration)(anim_t const *anim)

View File

@ -106,3 +106,7 @@ extern anim_t anims_player_Hit;
extern anim_t anims_hud_xp_Idle;
extern anim_t anims_hud_xp_Shine;
extern anim_t anims_hud_xp_Explode;
/* Items */
extern anim_t anims_item_life;
extern anim_t anims_item_sword1;

View File

@ -235,6 +235,14 @@ void aoe_apply(game_t *game, entity_t *entity, entity_t *e)
bool was_hit = false;
aoe_t *aoe = getcomp(entity, aoe);
aoe_record_t *rec = aoe_record(aoe, e);
fighter_t *e_f = getcomp(e, fighter);
if(aoe->type == AOE_ITEM && e_f && e_f->player) {
item_pick_up(&aoe->data.item.data, e);
aoe->lifetime = 0;
/* Don't bother recording the hit since the item will disappear */
was_hit = false;
}
/* Don't hit entities that have been recently hit */
if(rec && aoe->repeat_delay == 0) return;

View File

@ -6,9 +6,11 @@
#include "geometry.h"
#include "anim.h"
#include "item.h"
enum {
/* Item */
AOE_ITEM,
/* Bare-hand fist/close-contact attack */
AOE_HIT,
/* Simple ranged attack */
@ -51,6 +53,8 @@ typedef struct
uint16_t type;
/* Effect data (type-dependent) */
union {
/* Item: item info */
struct { item_data_t data; } item;
/* Generic attacks: source and ATK strength */
struct { int strength; int dir; } generic;
/* AOE_PROJECTILE: speed and direction of movement */

View File

@ -189,7 +189,7 @@ void game_remove_dead_entities(game_t *g)
if(f && f->HP == 0 && f->enemy != NULL && anim_finished) {
/* Give XP points to player */
bool lvup = player_add_xp(g->player_data, f->enemy->id->xp);
bool lvup = player_add_xp(g->player, f->enemy->id->xp);
if(lvup) {
g->hud_xp_anim.frame = anims_hud_xp_Explode.start[0];

View File

@ -39,8 +39,6 @@ typedef struct game {
int entity_count;
/* Player; this must be one of the entities loaded in the game */
entity_t *player;
/* Associated player data */
player_t *player_data;
/* Field of movement to reach the player (used by most enemy AIs) */
pfg_all2one_t paths_to_player;

42
src/item.c Normal file
View File

@ -0,0 +1,42 @@
#include "item.h"
#include "aoe.h"
#include "comp/fighter.h"
#include "comp/physical.h"
#include "comp/visible.h"
#include <gint/defs/util.h>
entity_t *item_make(item_data_t const *data, vec2 position)
{
entity_t *e = aoe_make(AOE_ITEM, position, fix(9999.0));
visible_t *v = getcomp(e, visible);
v->sprite_plane = VERTICAL;
v->shadow_size = 3;
v->z = fix(0.35);
physical_t *p = getcomp(e, physical);
p->hitbox = (rect){ -fix(4)/16, fix(3)/16, -fix(2)/16, fix(1)/16 };
aoe_t *aoe = getcomp(e, aoe);
aoe->origin = NULL;
aoe->repeat_delay = 0;
aoe->data.item.data = *data;
if(data->type == ITEM_LIFE) {
visible_set_anim(e, &anims_item_life, 1);
}
// else if(data->type == ITEM_X) {
// visible_set_anim(e, &anims_item_x, 1);
// }
return e;
}
void item_pick_up(item_data_t const *data, entity_t *player)
{
fighter_t *f = getcomp(player, fighter);
if(data->type == ITEM_LIFE && f) {
f->HP = min(f->HP + data->life.HP, f->HP_max);
}
}

28
src/item.h Normal file
View File

@ -0,0 +1,28 @@
//---
// items: Dropped objects that can be picked up from the ground
//---
#pragma once
#include "comp/entity.h"
#include "geometry.h"
enum {
ITEM_LIFE = 0,
};
typedef struct {
int type;
union {
/* ITEM_LIFE: Amount of HP restored */
struct { int HP; } life;
};
} item_data_t;
/* Create an item. This is just an AOE with a particular type. */
entity_t *item_make(item_data_t const *data, vec2 position);
/* Give an item to a player entity. */
void item_pick_up(item_data_t const *data, entity_t *player);

View File

@ -10,6 +10,7 @@
#include "enemies.h"
#include "game.h"
#include "geometry.h"
#include "item.h"
#include "level.h"
#include "map.h"
#include "menu.h"
@ -86,7 +87,7 @@ int main(void)
// Spawn player
//---
player_t player_data = {
player_data_t player_data = {
.entity = NULL,
.mechanical_limits = {
.max_speed = fix(4.5),
@ -105,7 +106,6 @@ int main(void)
.xp_to_next_level = 0,
.xp_current = 0,
};
game.player_data = &player_data;
entity_t *player = entity_make(physical, visible, mechanical, fighter);
player_data.entity = player;
@ -119,8 +119,7 @@ int main(void)
player_f->combo_next = 0;
player_f->combo_delay = fix(0);
player_f->enemy = NULL;
// TODO: Set link to player data in entity
// player_f->player = &player_data;
player_f->player = &player_data;
player_f->skills[1] = SKILL_DASH;
player_f->skills[2] = AOE_SHOCK;
player_f->skills[3] = AOE_JUDGEMENT;
@ -128,7 +127,7 @@ int main(void)
for(int i = 0; i < 5; i++)
player_f->actions_cooldown[i] = fix(0.0);
/* Initialize stats. This will level up to level 1 */
player_add_xp(&player_data, 0);
player_add_xp(player, 0);
player_f->HP = player_f->HP_max;
player_p->x = fix(game.level->player_spawn_x) + fix(0.5);
@ -145,6 +144,22 @@ int main(void)
game_add_entity(&game, player);
game.player = player;
int x=0, y=0;
for(int i = 0; i < 100; i++) {
y = rand() % game.map->height;
x = rand() % game.map->width;
map_cell_t const *cell = map_cell(game.map, x, y);
__auto_type tiles = game.map->tileset->tiles;
if(!tiles[cell->base].solid &&
(!cell->decor || !tiles[cell->decor].solid))
break;
}
item_data_t data = { .type = ITEM_LIFE, .life.HP = 50 };
entity_t *item = item_make(&data, (vec2){ fix(x)+fix(0.5), fix(y)+fix(0.5) });
game_add_entity(&game, item);
//---
// Main loop
//---

View File

@ -6,8 +6,10 @@ static int xp_to_next_level(int level)
return 3 * (level + 2) * (level + 2);
}
bool player_add_xp(player_t *p, int points)
bool player_add_xp(entity_t *e, int points)
{
player_data_t *p = getcomp(e, fighter)->player;
bool leveled_up = false;
p->xp_current += max(points, 0);

View File

@ -9,7 +9,7 @@
#include "comp/fighter.h"
#include <stdbool.h>
typedef struct {
typedef struct player_data {
/* Associated entity */
entity_t *entity;
/* Mechanical limits (dynamically recomputed) */
@ -21,7 +21,7 @@ typedef struct {
int xp_to_next_level;
int xp_current;
} player_t;
} player_data_t;
/* Add XP points to a player. Returns true if levels up */
bool player_add_xp(player_t *p, int points);
bool player_add_xp(entity_t *p, int points);

View File

@ -434,16 +434,17 @@ void render_game(game_t const *g, bool show_hitboxes)
extern bopti_image_t img_hud;
dimage(0, HUD_Y - img_hud.height, &img_hud);
fighter_t *player_f = getcomp(g->player, fighter);
extern font_t font_hud;
player_data_t *player_data = player_f->player;
dfont(&font_hud);
dprint_opt(349, HUD_Y - 5, RGB24(0x15171a), C_NONE, DTEXT_CENTER,
DTEXT_TOP, "%d", g->player_data->xp_level);
DTEXT_TOP, "%d", player_data->xp_level);
dprint_opt(349, HUD_Y - 6, RGB24(0xabb1ba), C_NONE, DTEXT_CENTER,
DTEXT_TOP, "%d", g->player_data->xp_level);
DTEXT_TOP, "%d", player_data->xp_level);
dfont(&font_rogue);
fighter_t *player_f = getcomp(g->player, fighter);
/* Render life bar */
extern bopti_image_t img_hud_life;
int fill_height = (img_hud_life.height * player_f->HP) / player_f->HP_max;
@ -458,8 +459,8 @@ void render_game(game_t const *g, bool show_hitboxes)
}
else {
static int const XP_FULL=22;
int xp_current = g->player_data->xp_current;
int xp_total = max(g->player_data->xp_to_next_level, 1);
int xp_current = player_data->xp_current;
int xp_total = max(player_data->xp_to_next_level, 1);
int fill_height = XP_FULL * xp_current / xp_total;
anim_frame_subrender(343, HUD_Y-32, g->hud_xp_anim.frame,
0, XP_FULL - fill_height, -1, fill_height);

View File

@ -10,7 +10,7 @@
enum {
SKILL_DASH = 0x100,
/* Other skills: */
/* Other skills in the AOE enumeration that are valid here: */
// AOE_PROJECTILE,
// AOE_SHOCK,
// AOE_JUDGEMENT,