add more objects into the game
This commit is contained in:
parent
59bc96beb8
commit
700ab55dc4
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
36
src/game.c
36
src/game.c
|
@ -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
|
||||
//---
|
||||
|
|
71
src/item.c
71
src/item.c
|
@ -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 */
|
||||
}
|
||||
}
|
||||
|
|
27
src/item.h
27
src/item.h
|
@ -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);
|
||||
|
|
25
src/level.h
25
src/level.h
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
//---
|
||||
|
|
Loading…
Reference in New Issue