add basic water/chemical slimes

This commit is contained in:
Lephenixnoir 2023-01-16 10:37:48 +01:00
parent cfb92c175d
commit c786d35388
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
9 changed files with 99 additions and 18 deletions

View File

@ -156,6 +156,12 @@ set(ASSETS
# Enemies: Washing machine
assets-cg/enemies/washing_machine_left.aseprite
assets-cg/enemies/washing_machine_right.aseprite
# Enemies: Water slime
assets-cg/enemies/water_slime_left.txt
assets-cg/enemies/water_slime_right.txt
# Enemies: Chemical slime
assets-cg/enemies/chemical_slime_left.txt
assets-cg/enemies/chemical_slime_right.txt
# Misc
assets-cg/font_damage_red.png
assets-cg/font_damage_white.png

2
TODO
View File

@ -39,6 +39,8 @@ Core mechanics:
Content:
* Additional skills
* Give the chemical slime a magic attack
* Jump attacks for elemental slimes
Infrastructure:
* Better end screen

View File

@ -35,6 +35,8 @@ MONSTER_IDS = {
"fire_slime/4": 3,
"albinos_bat/6": 4,
"gunslinger/8": 5,
"water_slime/8": 6,
"chemical_slime/10": 7,
}
ITEM_IDS = {
"life": 0,

View File

@ -87,7 +87,9 @@ entity_t *aoe_make_attack(uint16_t type, entity_t *origin, vec2 dir)
distance = fix(0.375);
lifetime = fix(999.0);
}
else if(type == AOE_FIRE_CHARGE) {
else if(type == AOE_FIRE_CHARGE
|| type == AOE_WATER_CHARGE
|| type == AOE_CHEMICAL_CHARGE) {
anim = NULL;
hitbox = (rect){ -fix(12)/16, fix(12)/16, -fix(13)/16, fix(2)/16 };
distance = fix(0);
@ -147,7 +149,9 @@ entity_t *aoe_make_attack(uint16_t type, entity_t *origin, vec2 dir)
v->z = fix(0.5);
v->shadow_size = 4;
}
else if(type == AOE_FIRE_CHARGE) {
else if(type == AOE_FIRE_CHARGE
|| type == AOE_WATER_CHARGE
|| type == AOE_CHEMICAL_CHARGE) {
aoe->data.charge.element = 0;
aoe->data.charge.power = f->MAG;
aoe->data.charge.origin = physical_pos(origin);
@ -234,7 +238,9 @@ static bool attack_apply(game_t *game, aoe_t *aoe, entity_t *target)
/* TODO: Sideways knockback */
damage = aoe->data.bullet.strength * 3 / 2;
}
else if(aoe->type == AOE_FIRE_CHARGE) {
else if(aoe->type == AOE_FIRE_CHARGE
|| aoe->type == AOE_WATER_CHARGE
|| aoe->type == AOE_CHEMICAL_CHARGE) {
dir.x = target_p->x - aoe->data.charge.origin.x;
dir.y = target_p->y - aoe->data.charge.origin.y;
dir = fnormalize(dir);
@ -292,7 +298,9 @@ void aoe_apply(game_t *game, entity_t *entity, entity_t *e)
|| aoe->type == AOE_IMPALE
|| aoe->type == AOE_SHOCK
|| aoe->type == AOE_BULLET
|| aoe->type == AOE_FIRE_CHARGE)
|| aoe->type == AOE_FIRE_CHARGE
|| aoe->type == AOE_WATER_CHARGE
|| aoe->type == AOE_CHEMICAL_CHARGE)
was_hit = attack_apply(game, aoe, e);
if(aoe->type == AOE_JUDGEMENT) {

View File

@ -25,6 +25,8 @@ enum {
AOE_JUDGEMENT,
AOE_BULLET,
AOE_FIRE_CHARGE,
AOE_WATER_CHARGE,
AOE_CHEMICAL_CHARGE,
/* Spawn effect */
EFFECT_SPAWN,
};

View File

@ -118,12 +118,54 @@ static enemy_t const gunslinger_8 = {
.ai_data_size = 0,
};
static enemy_t const water_slime_8 = {
.name = "Water slime",
.level = 8,
ANIMS(water_slime, Idle, Walking, Attack, Hit, Death),
.hitbox = (rect){ -fix(3)/16, fix(4)/16, -fix(2)/16, fix(3)/16 },
.limits = {
.max_speed = fix(1.2),
.friction = fix(0.4),
.max_disruption_speed = fix(999.0),
},
/* Same as slime/1 */
.stats_base = { .HP=10, .ATK=8, .MAG=5, .DEF=5 },
.stats_growth = { .HP=8, .ATK=4, .MAG=4, .DEF=2 },
.shadow_size = 4,
.xp = 24,
.z = 0,
.ai_data_size = 0,
};
static enemy_t const chemical_slime_10 = {
.name = "Chemical slime",
.level = 10,
ANIMS(chemical_slime, Idle, Walking, Attack, Hit, Death),
.hitbox = (rect){ -fix(3)/16, fix(4)/16, -fix(2)/16, fix(3)/16 },
.limits = {
.max_speed = fix(0.6),
.friction = fix(0.8),
.max_disruption_speed = fix(999.0),
},
/* Like as slime/1 but boosted MAG over ATK */
.stats_base = { .HP=10, .ATK=8, .MAG=5, .DEF=5 },
.stats_growth = { .HP=8, .ATK=2, .MAG=6, .DEF=2 },
.shadow_size = 4,
.xp = 41,
.z = 0,
.ai_data_size = 0,
};
static enemy_t const * const enemies[] = {
[ENEMY_SLIME_1] = &slime_1,
[ENEMY_BAT_2] = &bat_2,
[ENEMY_FIRE_SLIME_4] = &fire_slime_4,
[ENEMY_ALBINOS_BAT_6] = &albinos_bat_6,
[ENEMY_GUNSLINGER_8] = &gunslinger_8,
[ENEMY_SLIME_1] = &slime_1,
[ENEMY_BAT_2] = &bat_2,
[ENEMY_FIRE_SLIME_4] = &fire_slime_4,
[ENEMY_ALBINOS_BAT_6] = &albinos_bat_6,
[ENEMY_GUNSLINGER_8] = &gunslinger_8,
[ENEMY_WATER_SLIME_8] = &water_slime_8,
[ENEMY_CHEMICAL_SLIME_10] = &chemical_slime_10,
};
enemy_t const *enemy_data(int enemy_id)
@ -195,6 +237,12 @@ entity_t *enemy_make(int enemy_id)
else if(enemy_id == ENEMY_GUNSLINGER_8) {
f->skills[0] = AOE_PROJECTILE;
}
else if(enemy_id == ENEMY_WATER_SLIME_8) {
f->skills[1] = AOE_WATER_CHARGE;
}
else if(enemy_id == ENEMY_CHEMICAL_SLIME_10) {
f->skills[1] = AOE_CHEMICAL_CHARGE;
}
return e;
}
@ -338,11 +386,17 @@ void enemy_ai(game_t *g, entity_t *e, fixed_t dt)
}
}
else if(f->enemy->id == &fire_slime_4) {
else if(f->enemy->id == &fire_slime_4 || f->enemy->id == &water_slime_8
|| f->enemy->id == &chemical_slime_10) {
if(move_within_range_of_player(g, e, fix(0.75), dt)) {
/* Use the fire charge attack; if it fails, normal attack */
if(use_skill_towards_player(g, e, 1)) {
visible_set_anim(e, &anims_fire_slime_Fire, 2);
if(f->enemy->id == &fire_slime_4)
visible_set_anim(e, &anims_fire_slime_Fire, 2);
if(f->enemy->id == &water_slime_8)
visible_set_anim(e, &anims_water_slime_Fire, 2);
if(f->enemy->id == &chemical_slime_10)
visible_set_anim(e, &anims_chemical_slime_Fire, 2);
}
else {
contact_attack(g, e);

View File

@ -40,11 +40,13 @@ typedef struct
/* List of enemies */
enum {
/* ID 0 is used for the player! */
ENEMY_SLIME_1 = 1,
ENEMY_BAT_2 = 2,
ENEMY_FIRE_SLIME_4 = 3,
ENEMY_ALBINOS_BAT_6 = 4,
ENEMY_GUNSLINGER_8 = 5,
ENEMY_SLIME_1 = 1,
ENEMY_BAT_2 = 2,
ENEMY_FIRE_SLIME_4 = 3,
ENEMY_ALBINOS_BAT_6 = 4,
ENEMY_GUNSLINGER_8 = 5,
ENEMY_WATER_SLIME_8 = 6,
ENEMY_CHEMICAL_SLIME_10 = 7,
};
/* Dynamic enemy information. */

View File

@ -22,7 +22,9 @@ fixed_t skill_cooldown(int skill)
return fix(3.0);
else if(skill == AOE_BULLET)
return fix(4.0);
else if(skill == AOE_FIRE_CHARGE)
else if(skill == AOE_FIRE_CHARGE
|| skill == AOE_WATER_CHARGE
|| skill == AOE_CHEMICAL_CHARGE)
return fix(3.0);
return fix(0.0);
@ -108,7 +110,8 @@ bool skill_use(game_t *game, entity_t *e, int slot, vec2 dir)
visible_set_anim(e, f->enemy->id->anim_attack, 2);
}
else if(skill == AOE_FIRE_CHARGE
/* || skill == AOE_WATER_CHARGE */) {
|| skill == AOE_WATER_CHARGE
|| skill == AOE_CHEMICAL_CHARGE) {
if(f->current_attack)
return false;
entity_t *aoe = aoe_make_attack(skill, e, dir);

View File

@ -18,6 +18,8 @@ enum {
// AOE_JUDGEMENT,
// AOE_BULLET,
// AOE_FIRE_CHARGE,
// AOE_WATER_CHARGE,
// AOE_CHEMICAL_CHARGE,
};
/* Fixed cooldown for a skill */