add more objects into the game

This commit is contained in:
Lephenixnoir 2022-03-10 18:34:32 +00:00
parent 59bc96beb8
commit 700ab55dc4
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
13 changed files with 136 additions and 62 deletions

View File

@ -59,7 +59,16 @@ set(ASSETS
assets-cg/font_hud.png
# Items
assets-cg/items/life.aseprite
assets-cg/items/potion_atk.aseprite
assets-cg/items/potion_cooldown.aseprite
assets-cg/items/potion_def.aseprite
assets-cg/items/potion_frz.aseprite
assets-cg/items/potion_hp.aseprite
assets-cg/items/potion_spd.aseprite
assets-cg/items/stick1.aseprite
assets-cg/items/stick2.aseprite
assets-cg/items/sword1.aseprite
assets-cg/items/sword2.aseprite
# Player animations
assets-cg/player/player_up.aseprite
assets-cg/player/player_right.aseprite

View File

@ -77,7 +77,16 @@ ANIM1(hud_xp_Explode);
/* Items */
ANIM1(item_life);
ANIM1(item_potion_atk);
ANIM1(item_potion_cooldown);
ANIM1(item_potion_def);
ANIM1(item_potion_frz);
ANIM1(item_potion_hp);
ANIM1(item_potion_spd);
ANIM1(item_stick1);
ANIM1(item_stick2);
ANIM1(item_sword1);
ANIM1(item_sword2);
/* Animation functions. */

View File

@ -109,4 +109,13 @@ extern anim_t anims_hud_xp_Explode;
/* Items */
extern anim_t anims_item_life;
extern anim_t anims_item_potion_atk;
extern anim_t anims_item_potion_cooldown;
extern anim_t anims_item_potion_def;
extern anim_t anims_item_potion_frz;
extern anim_t anims_item_potion_hp;
extern anim_t anims_item_potion_spd;
extern anim_t anims_item_stick1;
extern anim_t anims_item_stick2;
extern anim_t anims_item_sword1;
extern anim_t anims_item_sword2;

View File

@ -238,7 +238,7 @@ void aoe_apply(game_t *game, entity_t *entity, entity_t *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);
item_pick_up(aoe->data.item.type, e);
aoe->lifetime = 0;
/* Don't bother recording the hit since the item will disappear */
was_hit = false;

View File

@ -54,7 +54,7 @@ typedef struct
/* Effect data (type-dependent) */
union {
/* Item: item info */
struct { item_data_t data; } item;
struct { int type; } item;
/* Generic attacks: source and ATK strength */
struct { int strength; int dir; } generic;
/* AOE_PROJECTILE: speed and direction of movement */

View File

@ -312,6 +312,9 @@ void enemy_ai(game_t *g, entity_t *e, fixed_t dt)
}
else if(f->enemy->id == &fire_slime_4) {
if(move_within_range_of_player(g, e, fix(1.0), dt)) {
contact_attack(g, e);
}
}
else if(f->enemy->id == &gunslinger_8) {

View File

@ -289,42 +289,6 @@ int game_sort_entities(game_t const *g, entity_measure_t *measure,
return count;
}
#if 0
// TODO ECS: New collision/ejection system based on teleports
void game_try_move_entity(game_t *g, entity_t *e,
entity_movement_t const * next)
{
entity_movement_t *m = &e->movement;
rect hitbox = rect_translate(e->hitbox, (vec2){ next->x, next->y });
if(!map_collides(&g->map, hitbox)) {
/* Movement is allowed */
fixed_t dx = next->x - m->x;
fixed_t dy = next->y - m->y;
/* Update attached attack animation */
if(next->facing != m->facing) {
e->attack_follows_movement = false;
}
if(e->current_attack && e->attack_follows_movement) {
e->current_attack->anchor.x += dx;
e->current_attack->anchor.y += dy;
}
*m = *next;
}
else {
/* Movement is denied. Halve speed so that high-speed movement doesn't
halt at a large distance from a wall. */
m->facing = next->facing;
m->vx = next->vx / 2;
m->vy = next->vy / 2;
m->dash = next->dash;
}
}
#endif
//---
// Per-frame update functions
//---

View File

@ -5,7 +5,7 @@
#include "comp/visible.h"
#include <gint/defs/util.h>
entity_t *item_make(item_data_t const *data, vec2 position)
entity_t *item_make(int type, vec2 position)
{
entity_t *e = aoe_make(AOE_ITEM, position, fix(9999.0));
@ -20,23 +20,76 @@ entity_t *item_make(item_data_t const *data, vec2 position)
aoe_t *aoe = getcomp(e, aoe);
aoe->origin = NULL;
aoe->repeat_delay = 0;
aoe->data.item.data = *data;
aoe->data.item.type = type;
if(data->type == ITEM_LIFE) {
if(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);
// }
else if(type == ITEM_POTION_ATK) {
visible_set_anim(e, &anims_item_potion_atk, 1);
}
else if(type == ITEM_POTION_COOLDOWN) {
visible_set_anim(e, &anims_item_potion_cooldown, 1);
}
else if(type == ITEM_POTION_DEF) {
visible_set_anim(e, &anims_item_potion_def, 1);
}
else if(type == ITEM_POTION_FRZ) {
visible_set_anim(e, &anims_item_potion_frz, 1);
}
else if(type == ITEM_POTION_HP) {
visible_set_anim(e, &anims_item_potion_hp, 1);
}
else if(type == ITEM_POTION_SPD) {
visible_set_anim(e, &anims_item_potion_spd, 1);
}
else if(type == ITEM_SCEPTER1) {
visible_set_anim(e, &anims_item_stick1, 1);
}
else if(type == ITEM_SCEPTER2) {
visible_set_anim(e, &anims_item_stick2, 1);
}
else if(type == ITEM_SWORD1) {
visible_set_anim(e, &anims_item_sword1, 1);
}
else if(type == ITEM_SWORD2) {
visible_set_anim(e, &anims_item_sword2, 1);
}
return e;
}
void item_pick_up(item_data_t const *data, entity_t *player)
void item_pick_up(int type, 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);
if(type == ITEM_LIFE && f) {
int added = max(f->HP_max / 2, 8);
f->HP_max += added;
f->HP += added;
}
else if(type == ITEM_POTION_ATK && f) {
/* TODO: Double attack for 10 seconds */
}
else if(type == ITEM_POTION_COOLDOWN && f) {
/* TODO: Restore all cooldowns */
}
else if(type == ITEM_POTION_DEF && f) {
/* TODO: Defense +50% for 10 seconds */
}
else if(type == ITEM_POTION_FRZ && f) {
/* TODO: Freeze all monsters for 5 seconds */
}
else if(type == ITEM_POTION_HP && f) {
int restored = max(f->HP_max / 2, 8);
f->HP = min(f->HP + restored, f->HP_max);
}
else if(type == ITEM_POTION_SPD && f) {
/* TODO: Speed +50% for 10 seconds */
}
else if(type >= ITEM_EQUIPMENT_START && type < ITEM_EQUIPMENT_END
&& f->player) {
/* TODO: Give item to player */
}
}

View File

@ -9,20 +9,23 @@
enum {
ITEM_LIFE = 0,
ITEM_POTION_ATK = 1,
ITEM_POTION_COOLDOWN = 2,
ITEM_POTION_DEF = 3,
ITEM_POTION_FRZ = 4,
ITEM_POTION_HP = 5,
ITEM_POTION_SPD = 6,
/**/ ITEM_EQUIPMENT_START = 100,
ITEM_SCEPTER1,
ITEM_SCEPTER2,
ITEM_SWORD1,
ITEM_SWORD2,
/**/ ITEM_EQUIPMENT_END,
};
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);
entity_t *item_make(int item, vec2 position);
/* Give an item to a player entity. */
void item_pick_up(item_data_t const *data, entity_t *player);
void item_pick_up(int item, entity_t *player);

View File

@ -11,6 +11,7 @@
#include "fixed.h"
#include "map.h"
#include "item.h"
#include <stdint.h>
#include <stdbool.h>
#include <gint/display.h>
@ -34,6 +35,30 @@ typedef struct {
} level_wave_t;
enum {
/* Nothing happens for a short while */
LEVEL_EVENT_DELAY = 0,
/* A wave of monster spawns! */
LEVEL_EVENT_WAVE = 1,
/* An item is dropped at a random position */
LEVEL_EVENT_ITEM = 2,
};
/* Levels are made of a sequence of simple events. */
typedef struct {
int type;
union {
/* LEVEL_EVENT_DELAY */
int delay_s;
/* LEVEL_EVENT_WAVE */
level_wave_t *wave;
/* LEVEL_EVENT_ITEM */
int item;
};
} level_event_t;
typedef struct {
char const *name;

View File

@ -144,7 +144,6 @@ 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;
@ -156,8 +155,8 @@ int main(void)
(!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) });
entity_t *item = item_make(ITEM_LIFE,
(vec2){ fix(x)+fix(0.5), fix(y)+fix(0.5) });
game_add_entity(&game, item);
//---