td

blob.rs at [1c4f2f89eb]
Login

blob.rs at [1c4f2f89eb]

File src/enemies/blob.rs artifact 2391cb4c21 part of check-in 1c4f2f89eb


//! Blob — the basic enemy. Mirrors `crate::weapons::impact::Impact` on the weapon side.

use std::collections::HashMap;

use macroquad::{color::Color, math::Vec2, shapes::draw_circle};

use crate::{
    animations::AnimationTypes,
    enemies::{EnemyKind, behaviors::SplitOnDeath, movement::SeekCenter},
    enemy::Enemy,
    registry::EnemyID,
    types::Source,
};

pub struct Blob;

impl Blob {
    const BASE_XP: f32 = 1.0;
    const BASE_HP: f32 = 1.0;
    const HP_GROWTH: f32 = 1.6;
    const XP_GROWTH: f32 = 1.3;
}

impl EnemyKind for Blob {
    fn create(tier: u32) -> Enemy {
        let hp = (Self::BASE_HP * Self::HP_GROWTH.powf(tier as f32)).round();
        let xp = (Self::BASE_XP * Self::XP_GROWTH.powf(tier as f32)).round();
        let mut template = Enemy {
            id: 0,
            pos: Vec2::ZERO,
            hp,
            tier,
            radius: 10.,
            kind: EnemyID::PLACEHOLDER, // stamped with the real id by EnemyRegistry::make
            death_anim: AnimationTypes::EnemeyDeathAnimation,
            statuses: Vec::new(),
            killer: Source::None,
            resists: HashMap::new(),
            xp: xp as u32,
            behaviors: Vec::new(),
            draw: Blob::animation(),
            max_hp: hp,
            vel: Vec2::ZERO,
        };
        template.behaviors.push(SplitOnDeath::create(3));
        template.behaviors.push(SeekCenter::create(0));
        template
    }

    fn animation() -> Box<fn(&Enemy) -> ()> {
        let animation = |enemy: &Enemy| {
            let hp_frac = (enemy.hp / enemy.max_hp).clamp(0.0, 1.0);
            let col = Color::new(0.3, hp_frac * 0.2, hp_frac * 0.2, 1.0);
            draw_circle(enemy.pos.x, enemy.pos.y, enemy.radius, col);
        };
        Box::new(animation)
    }
}