116 lines
3.7 KiB
C++
116 lines
3.7 KiB
C++
#include "baby_idle_behavior.h"
|
|
#include "esp_log.h"
|
|
#include "esp_random.h"
|
|
#include "esp_timer.h"
|
|
|
|
static const char* TAG = "BabyIdleBehavior";
|
|
|
|
namespace sweekar {
|
|
namespace demo7 {
|
|
|
|
namespace {
|
|
constexpr int64_t kFirstRandomIdleDelayUs = 5000000; // 5s after entering idle
|
|
constexpr int64_t kRandomIdleCooldownUs = 7000000; // 7s after a random idle script
|
|
constexpr const char* kBaseIdleScript = "baby/idle/look_around";
|
|
constexpr const char* kCuriousIdleScript = "baby/interaction/curious";
|
|
constexpr const char* kShyIdleScript = "baby/interaction/shy";
|
|
} // namespace
|
|
|
|
void BabyIdleBehavior::OnEnter(IPetContext* ctx) {
|
|
PlayBaseIdle(ctx);
|
|
ScheduleRandomIdle(kFirstRandomIdleDelayUs);
|
|
phase_ = Phase::WAITING_RANDOM_IDLE;
|
|
}
|
|
|
|
void BabyIdleBehavior::OnExit(IPetContext* ctx) {
|
|
ctx->StopScript();
|
|
next_random_idle_us_ = 0;
|
|
phase_ = Phase::PLAYING_BASE_IDLE;
|
|
}
|
|
|
|
bool BabyIdleBehavior::HandleEvent(IPetContext* ctx, const Event& evt) {
|
|
switch (evt.type) {
|
|
case EventType::EVT_TOUCH_TAP:
|
|
ESP_LOGI(TAG, "Baby got touched. Play surprised.");
|
|
ctx->PlayScript("interaction/surprised");
|
|
phase_ = Phase::PLAYING_RANDOM_IDLE;
|
|
return true;
|
|
|
|
case EventType::EVT_KEY_LEFT_CLICK:
|
|
ESP_LOGI(TAG, "Left clicked in BabyIdle. Opening Baby Menu.");
|
|
ctx->RequestModeSwitch(PetModeType::MODE_MENU);
|
|
return true;
|
|
|
|
case EventType::EVT_KEY_RIGHT_CLICK:
|
|
ESP_LOGI(TAG, "Right clicked in BabyIdle. Learn to talk.");
|
|
ctx->PlayScript("interaction/learned_to_talk");
|
|
phase_ = Phase::PLAYING_RANDOM_IDLE;
|
|
return true;
|
|
|
|
case EventType::EVT_GYRO_SHAKE:
|
|
ESP_LOGI(TAG, "Baby shaken. Play dizzy.");
|
|
ctx->PlayScript("interaction/dizzy");
|
|
phase_ = Phase::PLAYING_RANDOM_IDLE;
|
|
return true;
|
|
|
|
case EventType::EVT_TOUCH_SWIPE_LEFT:
|
|
ESP_LOGI(TAG, "Baby touch swipe left. Play hurt.");
|
|
ctx->PlayScript("baby/interaction/hurt");
|
|
phase_ = Phase::PLAYING_RANDOM_IDLE;
|
|
return true;
|
|
|
|
case EventType::EVT_TOUCH_SWIPE_RIGHT:
|
|
ESP_LOGI(TAG, "Baby touch swipe right. Play curious.");
|
|
ctx->PlayScript(kCuriousIdleScript);
|
|
phase_ = Phase::PLAYING_RANDOM_IDLE;
|
|
return true;
|
|
|
|
case EventType::EVT_SCRIPT_DONE:
|
|
ESP_LOGI(TAG, "Baby idle script done.");
|
|
PlayBaseIdle(ctx);
|
|
if (phase_ == Phase::PLAYING_RANDOM_IDLE) {
|
|
ScheduleRandomIdle(kRandomIdleCooldownUs);
|
|
phase_ = Phase::COOLDOWN_AFTER_RANDOM;
|
|
}
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void BabyIdleBehavior::OnTick(IPetContext* ctx) {
|
|
if (!IsRandomIdleDue()) {
|
|
return;
|
|
}
|
|
|
|
PlayRandomIdle(ctx);
|
|
phase_ = Phase::PLAYING_RANDOM_IDLE;
|
|
}
|
|
|
|
void BabyIdleBehavior::PlayBaseIdle(IPetContext* ctx) {
|
|
ESP_LOGI(TAG, "Play base idle script: %s", kBaseIdleScript);
|
|
ctx->PlayScript(kBaseIdleScript);
|
|
}
|
|
|
|
void BabyIdleBehavior::PlayRandomIdle(IPetContext* ctx) {
|
|
uint32_t roll = esp_random() % 100;
|
|
const char* script = roll < 50 ? kCuriousIdleScript : kShyIdleScript;
|
|
ESP_LOGI(TAG, "Play random idle script: %s, roll=%lu", script, static_cast<unsigned long>(roll));
|
|
ctx->PlayScript(script);
|
|
}
|
|
|
|
void BabyIdleBehavior::ScheduleRandomIdle(int64_t delay_us) {
|
|
next_random_idle_us_ = esp_timer_get_time() + delay_us;
|
|
}
|
|
|
|
bool BabyIdleBehavior::IsRandomIdleDue() const {
|
|
if (phase_ != Phase::WAITING_RANDOM_IDLE && phase_ != Phase::COOLDOWN_AFTER_RANDOM) {
|
|
return false;
|
|
}
|
|
return next_random_idle_us_ > 0 && esp_timer_get_time() >= next_random_idle_us_;
|
|
}
|
|
|
|
} // namespace demo7
|
|
} // namespace sweekar
|