feat: add baby and teen projects, update sample data

This commit is contained in:
mac committed 2026-05-21 20:51:32 +08:00
1 parent 9d0261fcd7
commit 895629a007
18 files changed
+5587 -1946

No files matched your search

+115
View File
@@ -0,0 +1,115 @@
#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
+443
View File
@@ -0,0 +1,443 @@
{
"$override": {
},
"custom": {
},
"desc": "宝宝待机行为树 v2:Selector 优先级级联 + 效用曲线 + 双层脑信号(WARNING/CRITICAL)。优先级:精力耗尽 > 饥饿 > 悲伤 > 开心 > 好奇 > 默认待机。",
"export": true,
"group": [
],
"import": [
],
"name": "example",
"prefix": "",
"root": {
"$id": "root001",
"children": [
{
"$id": "idleRepeat001",
"args": {
},
"children": [
{
"$id": "idleSeq001",
"children": [
{
"$id": "idleWaitRhythm",
"args": {
"random": 1.5,
"time": 2
},
"id": "40",
"name": "Wait"
},
{
"$id": "idleSelector001",
"children": [
{
"$id": "exhaustedSeq",
"children": [
{
"$id": "exhaustedCheck",
"args": { "attr": "energy", "op": "<=", "value": 15 },
"id": "43",
"name": "CheckPhysio"
},
{
"$id": "exhaustedScript",
"args": { "script": "baby/need/sleepy" },
"id": "44",
"name": "PlayScript"
}
],
"id": "42",
"name": "Sequence"
},
{
"$id": "hungrySeq",
"children": [
{
"$id": "hungryCheck",
"args": { "attr": "fullness", "op": "<=", "value": 25 },
"id": "46",
"name": "CheckPhysio"
},
{
"$id": "hungryScript",
"args": { "script": "baby/need/hungry" },
"id": "48",
"name": "PlayScript"
},
{
"$id": "hungryMoodDrop",
"args": { "attr": "happiness", "amount": -2 },
"id": "49",
"name": "AddPhysio"
}
],
"id": "45",
"name": "Sequence"
},
{
"$id": "sadSeq",
"children": [
{
"$id": "sadCheck",
"args": { "attr": "sad", "op": ">", "value": 0.5 },
"id": "51",
"name": "CheckUtility"
},
{
"$id": "sadScript",
"args": { "script": "baby/need/sad_mild" },
"id": "52",
"name": "PlayScript"
}
],
"id": "50",
"name": "Sequence"
},
{
"$id": "laughSeq",
"children": [
{
"$id": "laughCheck",
"args": { "attr": "laugh", "op": ">", "value": 0.5 },
"id": "54",
"name": "CheckUtility"
},
{
"$id": "laughScript",
"args": { "script": "baby/interaction/laugh" },
"id": "55",
"name": "PlayScript"
}
],
"id": "53",
"name": "Sequence"
},
{
"$id": "curiousSeq",
"children": [
{
"$id": "curiousCheck",
"args": { "attr": "curious", "op": ">", "value": 0.4 },
"id": "57",
"name": "CheckUtility"
},
{
"$id": "curiousScript",
"args": { "script": "baby/interaction/curious" },
"id": "58",
"name": "PlayScript"
}
],
"id": "56",
"name": "Sequence"
},
{
"$id": "idleFallback",
"args": { "script": "baby/interaction/shy" },
"id": "59",
"name": "PlayScript"
}
],
"id": "41",
"name": "Selector"
}
],
"id": "3",
"name": "Sequence"
}
],
"id": "2",
"name": "Repeat"
},
{
"$id": "listenTriple001",
"args": {
"event": "EVT_TOUCH_TRIPLE_TAP"
},
"children": [
{
"$id": "shyScript001",
"args": {
"script": "baby/interaction/shy"
},
"id": "17",
"name": "PlayScript"
}
],
"id": "16",
"name": "Listen"
},
{
"$id": "listenTap001",
"args": {
"event": "EVT_TOUCH_TAP"
},
"children": [
{
"$id": "tapSelector001",
"children": [
{
"$id": "dirtyTapSeq",
"children": [
{
"$id": "dirtyTapCheck",
"args": { "attr": "cleanliness", "op": "<=", "value": 20 },
"id": "62",
"name": "CheckPhysio"
},
{
"$id": "dirtyTapScript",
"args": { "script": "baby/interaction/hurt" },
"id": "64",
"name": "PlayScript"
},
{
"$id": "dirtyTapMoodDrop",
"args": { "attr": "happiness", "amount": -1 },
"id": "65",
"name": "AddPhysio"
}
],
"id": "61",
"name": "Sequence"
},
{
"$id": "curiousTapSeq",
"children": [
{
"$id": "curiousTapCheck",
"args": { "attr": "curious", "op": ">", "value": 0.55 },
"id": "67",
"name": "CheckUtility"
},
{
"$id": "wantedScript001",
"args": { "script": "baby/interaction/wanted" },
"id": "69",
"name": "PlayScript"
},
{
"$id": "tapHappinessUp",
"args": { "attr": "happiness", "amount": 3 },
"id": "70",
"name": "AddPhysio"
}
],
"id": "66",
"name": "Sequence"
},
{
"$id": "sadTapSeq",
"children": [
{
"$id": "sadTapCheck",
"args": { "attr": "sad", "op": ">", "value": 0.4 },
"id": "72",
"name": "CheckUtility"
},
{
"$id": "comfortScript",
"args": { "script": "baby/need/sad_mild" },
"id": "73",
"name": "PlayScript"
}
],
"id": "71",
"name": "Sequence"
},
{
"$id": "tapFallback",
"args": { "script": "baby/interaction/hurt" },
"id": "74",
"name": "PlayScript"
}
],
"id": "60",
"name": "Selector"
}
],
"id": "18",
"name": "Listen"
},
{
"$id": "listenLeftEar001",
"args": {
"abortType": "interrupt",
"event": "EVT_KEY_LEFT_CLICK"
},
"children": [
{
"$id": "openMenu001",
"args": {
"mode": "MODE_MENU"
},
"id": "24",
"name": "RequestModeSwitch"
}
],
"id": "23",
"name": "Listen"
},
{
"$id": "listenBrainFullnessWarning",
"args": { "event": "EVT_INTERNAL_BRAIN_FULLNESS_WARNING" },
"children": [
{
"$id": "hungryWarnScript",
"args": { "script": "baby/need/hungry" },
"id": "30",
"name": "PlayScript"
}
],
"id": "29",
"name": "Listen"
},
{
"$id": "listenBrainEnergyWarning",
"args": { "event": "EVT_INTERNAL_BRAIN_ENERGY_WARNING" },
"children": [
{
"$id": "sleepyWarnScript",
"args": { "script": "baby/need/sleepy" },
"id": "32",
"name": "PlayScript"
}
],
"id": "31",
"name": "Listen"
},
{
"$id": "listenBrainHappinessWarning",
"args": { "event": "EVT_INTERNAL_BRAIN_HAPPINESS_WARNING" },
"children": [
{
"$id": "sadWarnScript",
"args": { "script": "baby/need/sad_mild" },
"id": "34",
"name": "PlayScript"
}
],
"id": "33",
"name": "Listen"
},
{
"$id": "listenBrainCleanlinessWarning",
"args": { "event": "EVT_INTERNAL_BRAIN_CLEANLINESS_WARNING" },
"children": [
{
"$id": "dirtyWarnScript",
"args": { "script": "baby/need/dirty" },
"id": "36",
"name": "PlayScript"
}
],
"id": "35",
"name": "Listen"
},
{
"$id": "listenBrainFullnessCritical",
"args": { "event": "EVT_INTERNAL_BRAIN_FULLNESS_CRITICAL", "abortType": "interrupt" },
"children": [
{
"$id": "hungryCriticalSeq",
"children": [
{
"$id": "hungryCriticalScript",
"args": { "script": "baby/need/hungry" },
"id": "82",
"name": "PlayScript"
},
{
"$id": "hungryCriticalMoodDrop",
"args": { "attr": "happiness", "amount": -5 },
"id": "83",
"name": "AddPhysio"
}
],
"id": "81",
"name": "Sequence"
}
],
"id": "80",
"name": "Listen"
},
{
"$id": "listenBrainEnergyCritical",
"args": { "event": "EVT_INTERNAL_BRAIN_ENERGY_CRITICAL", "abortType": "interrupt" },
"children": [
{
"$id": "energyCriticalSeq",
"children": [
{
"$id": "energyCriticalScript",
"args": { "script": "baby/need/sleepy" },
"id": "86",
"name": "PlayScript"
},
{
"$id": "energyCriticalMoodDrop",
"args": { "attr": "happiness", "amount": -5 },
"id": "87",
"name": "AddPhysio"
}
],
"id": "85",
"name": "Sequence"
}
],
"id": "84",
"name": "Listen"
},
{
"$id": "listenBrainHappinessCritical",
"args": { "event": "EVT_INTERNAL_BRAIN_HAPPINESS_CRITICAL", "abortType": "interrupt" },
"children": [
{
"$id": "sadCriticalScript",
"args": { "script": "baby/need/sad_mild" },
"id": "89",
"name": "PlayScript"
}
],
"id": "88",
"name": "Listen"
},
{
"$id": "listenBrainCleanlinessCritical",
"args": { "event": "EVT_INTERNAL_BRAIN_CLEANLINESS_CRITICAL", "abortType": "interrupt" },
"children": [
{
"$id": "dirtyCriticalSeq",
"children": [
{
"$id": "dirtyCriticalScript",
"args": { "script": "baby/need/dirty" },
"id": "92",
"name": "PlayScript"
},
{
"$id": "dirtyCriticalMoodDrop",
"args": { "attr": "happiness", "amount": -3 },
"id": "93",
"name": "AddPhysio"
}
],
"id": "91",
"name": "Sequence"
}
],
"id": "90",
"name": "Listen"
}
],
"id": "1",
"name": "Parallel"
},
"vars": [
],
"version": "2.0.0"
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+13
View File
@@ -0,0 +1,13 @@
{
"nodeConf": "node-config.b3-setting",
"metadata": [],
"files": [
{
"path": "example.json",
"desc": "最小宠物养成行为树"
}
],
"settings": {
"checkExpr": true
}
}