diff --git a/src/badguy/granito.cpp b/src/badguy/granito.cpp index e14361417f8..0bc26f6ede7 100644 --- a/src/badguy/granito.cpp +++ b/src/badguy/granito.cpp @@ -1,15 +1,17 @@ #include "granito.hpp" #include "math/random.hpp" - -static const float WALK_SPEED = 80.f; +#include "supertux/sector.hpp" +#include "object/player.hpp" Granito::Granito(const ReaderMapping& reader): - WalkingBadguy(reader, "images/creatures/granito/granito.sprite", "left", "right") + WalkingBadguy(reader, "images/creatures/granito/granito.sprite", "left", "right"), + m_state(STATE_STAND), + m_has_waved(false) { parse_type(reader); - walk_speed = WALK_SPEED; + walk_speed = 0; max_drop_height = 600; m_countMe = false; @@ -18,12 +20,55 @@ Granito::Granito(const ReaderMapping& reader): void Granito::active_update(float dt_sec) { - switch (m_type) { - case WALK: { - if (!m_walk_interval.started() && !m_walk_interval.check()) + if (m_type == SIT) + { + // Sit type does nothing + WalkingBadguy::active_update(dt_sec); + return; + } + + if (!m_has_waved) + { + if (m_state == STATE_WAVE) + { + if (!m_sprite->animation_done()) { - m_walk_interval.start(gameRandom.randf(1.f, 4.f)); + // Still waving + WalkingBadguy::active_update(dt_sec); + return; + } + else + { + // Finished waving + m_state = STATE_STAND; + set_action("stand", m_dir); + m_has_waved = true; + } + } + else + { + try_wave(); + } + } + + if (!m_walk_interval.started() && !m_walk_interval.check()) + { + m_walk_interval.start(gameRandom.randf(1.f, 4.f)); + + switch (m_type) + { + case STAND: + if (gameRandom.rand(100) > 50) + { + // turn around + m_dir = m_dir == Direction::LEFT ? Direction::RIGHT : Direction::LEFT; + set_action("stand", m_dir); + } + + break; + case WALK: + { if (gameRandom.rand(100) > 50 && walk_speed == 0) { // turn around @@ -36,6 +81,7 @@ void Granito::active_update(float dt_sec) if (walk_speed > 0) { walk_speed = 0; + m_state = STATE_STAND; m_physic.set_velocity_x(0); set_action("stand", m_dir); } @@ -43,14 +89,18 @@ void Granito::active_update(float dt_sec) { // FIXME: Why do I need to add 1??? Grumbel, you... m_dir = (gameRandom.rand(1 + 1) == 0 ? Direction::LEFT : Direction::RIGHT); - walk_speed = WALK_SPEED; - m_physic.set_velocity_x(WALK_SPEED * (m_dir == Direction::LEFT ? -1 : 1)); + walk_speed = 80; + m_state = STATE_WALK; + m_physic.set_velocity_x(80 * (m_dir == Direction::LEFT ? -1 : 1)); set_action(m_dir); } } + + break; } - break; + default: + break; } } @@ -74,5 +124,62 @@ GameObjectTypes Granito::get_types() const void Granito::initialize() { WalkingBadguy::initialize(); + + switch (m_type) + { + case WALK: + set_action(m_dir); + break; + + case SIT: + // TODO: sit animation + set_action("stand", m_dir); + break; + + case STAND: + set_action("stand", m_dir); + break; + } + set_colgroup_active(COLGROUP_MOVING_ONLY_STATIC); } + +void Granito::on_type_change(__attribute__((unused)) int old_type) +{ + // FIXME: change action for type in editor +} + +bool Granito::try_wave() +{ + using RaycastResult = CollisionSystem::RaycastResult; + + Player* plr = get_nearest_player(); + RaycastResult result = Sector::get().get_first_line_intersection(get_bbox().get_middle(), + plr->get_bbox().get_middle(), + false, + get_collision_object()); + + if (result.hit.object != nullptr && result.hit.object == plr->get_collision_object()) + { + float dist = glm::distance(result.box.get_middle(), get_bbox().get_middle()); + if (std::abs(dist) < 32.f*4.f) + { + wave(); + return true; + } + } + + return false; +} + +void Granito::wave() +{ + walk_speed = 0; + m_physic.set_velocity_x(0); + m_state = STATE_WAVE; + + float xdist = get_bbox().get_middle().x - get_nearest_player()->get_bbox().get_middle().x; + + m_dir = (xdist > 0 ? Direction::LEFT : Direction::RIGHT); + set_action("wave", m_dir, 1); +} diff --git a/src/badguy/granito.hpp b/src/badguy/granito.hpp index fee9361b2ac..17b2e036a92 100644 --- a/src/badguy/granito.hpp +++ b/src/badguy/granito.hpp @@ -25,13 +25,25 @@ class Granito : public WalkingBadguy protected: virtual void initialize() override; - //virtual void on_type_change(int old_type) override; + virtual void on_type_change(int old_type) override; + + bool try_wave(); + void wave(); private: enum Type { WALK, SIT, STAND }; + enum State { + STATE_STAND, + STATE_WALK, + STATE_WAVE + }; private: Timer m_walk_interval; + State m_state; + + bool m_has_waved; + private: Granito(const Granito&) = delete;