feat(vida): 20 atividades e necessidades no estilo The Sims
Quatorze cenas novas para o bonequinho: cochilar na caminha (cobertor respirando e Zzz), café (vapor e gole), cozinhar (vira a panqueca no fogão), regar a plantinha (cresce e dá flor), violão, dançar (globo espelhado), pular corda, meditar flutuando, telescópio (céu estrelado e estrela cadente), pipa com rabiola, bolhas de sabão, skate (com ollie), computador (código aparecendo) e pescar (o peixe pula preso na linha). Necessidades puxam comportamento, como no The Sims: - energia < 40%: às vezes cochila; < 20%: dorme de verdade com sono respeitado (som comum, movimento e PIR não acordam) até 95%; acordar de propósito (toque, painel) encerra o sono pesado; - alegria abaixo de 60%: o rosto vai ficando emburrado (zanga 0 a 1: testa franzida, boca para baixo, olhos bravos); < 30%: mal-humorado; - diversão < 45%: faz uma atividade de 2 a 5 min escolhida pelo pique (cansado prefere calmas, café dá energia); pode ser interrompido; - durante a atividade a diversão sobe e a energia cai conforme o tipo. Com o modo vida ligado o celular não adormece mais por 20 s de silêncio: quem decide o sono é a energia. A cor escolhida nunca muda com a zanga. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -212,7 +212,7 @@ function caminhoBoca(tipo) {
|
||||
// repouso: leve, com as microexpressões (canto que sobe, boca de lado, entreaberta)
|
||||
const f = FEICAO.atual, w = l * 0.30, mx = cx + f.dx * l * 0.10;
|
||||
const yE = cy - Math.max(0, f.lado) * l * 0.12, yD = cy - Math.max(0, -f.lado) * l * 0.12;
|
||||
const curva = l * (0.18 + f.curva * 0.35);
|
||||
const curva = l * (0.18 + f.curva * 0.35 - ZANGA * 0.3);
|
||||
let d = "M " + (mx - w) + "," + yE + " Q " + mx + "," + (cy + curva - f.abre * l * 0.12) + " " + (mx + w) + "," + yD;
|
||||
if (f.abre > 0.04) d += " Q " + mx + "," + (cy + curva + f.abre * l * 0.30) + " " + (mx - w) + "," + yE;
|
||||
return d;
|
||||
@@ -224,7 +224,8 @@ function caminhoSobrancelha(i, esc) {
|
||||
const ab = i === 0 ? r.ab : (r.ab2 === null ? r.ab : r.ab2);
|
||||
const piscando = 1 - Math.min(1, Math.max(0, ab));
|
||||
const y = c[1] - metadeOlho(esc) - (EXTRAS.distSobrancelha + 4) * ESC - (f.sob[i] - piscando * 3) * ESC;
|
||||
const inc = ((r.forma === 'bravo' ? 18 : r.forma === 'triste' ? -14 : 0) + f.inc[i]) * lado * ESC;
|
||||
const base = r.forma === 'bravo' ? 18 : r.forma === 'triste' ? -14 : ZANGA * 14; // zanga franze a testa
|
||||
const inc = (base + f.inc[i]) * lado * ESC;
|
||||
const ele = r.esc > 1.1 ? -15 * ESC : 0;
|
||||
return 'M ' + (c[0] - largura) + ',' + (y - inc + ele) + ' Q ' + c[0] + ',' + (y - 10 * ESC + ele) + ' ' + (c[0] + largura) + ',' + (y + inc + ele);
|
||||
}
|
||||
@@ -401,12 +402,17 @@ const LIVRES = ["feliz", "olhar_esq", "olhar_dir", "olhar_baixo",
|
||||
const LIVRES_HUMOR = {
|
||||
feliz: ["feliz", "alegre", "piscadinha", "coracao", "olhar_esq", "olhar_dir"],
|
||||
tranquilo: ["olhar_esq", "olhar_dir", "feliz", "piscadinha", "olhar_baixo", "timido"],
|
||||
bravo: ["bravo", "olhar_baixo", "olhar_esq", "olhar_dir", "confuso"],
|
||||
entediado: ["olhar_esq", "olhar_dir", "olhar_baixo", "pensar", "bocejar", "confuso"],
|
||||
carente: ["olhar_baixo", "triste", "olhar_esq", "olhar_dir", "timido"],
|
||||
triste: ["triste", "olhar_baixo", "olhar_baixo"],
|
||||
cansado: ["olhar_baixo", "piscar2", "bocejar"],
|
||||
};
|
||||
let HUMOR = "normal";
|
||||
/* Modo vida: zanga (0 a 1) deixa o rosto emburrado aos poucos quando a alegria cai; sono profundo =
|
||||
dormiu de cansaço, e aí som, movimento e câmera não acordam (como na madrugada). */
|
||||
let ZANGA = 0;
|
||||
let SONO_PROFUNDO = false;
|
||||
|
||||
/* Microexpressões acordado: de vez em quando a boca e as sobrancelhas mexem sozinhas (um canto
|
||||
da boca sobe, uma sobrancelha arqueia, um suspiro) e voltam devagar ao neutro. O humor do modo
|
||||
@@ -431,6 +437,7 @@ const MICRO_HUMOR = {
|
||||
carente: ["preocupado", "preocupado", "suspiro", "meioSorriso"],
|
||||
triste: ["preocupado", "suspiro", "pensativo"],
|
||||
cansado: ["suspiro", "suspiro", "ladinho"],
|
||||
bravo: ["pensativo", "pensativo", "ladinho", "suspiro"],
|
||||
normal: ["meioSorriso", "arquear", "sorrisinho", "ladinho", "interesse", "pensativo", "suspiro"],
|
||||
};
|
||||
function atualizarFeicao(s) {
|
||||
@@ -495,11 +502,11 @@ function passo(dt) { // avanca a fila; true se ha gesto em
|
||||
|
||||
/* Atividade em andamento (rosto-motor.js): para onde olhar e que cara fazer. Atualizado por quadro. */
|
||||
let ATIV = null;
|
||||
function atividade(nome) {
|
||||
function atividade(nome, segundos) {
|
||||
if (!window.MotorRosto || !window.MotorRosto.atividade) return;
|
||||
if (nome === "parar" || !nome) { window.MotorRosto.atividade(null); return; }
|
||||
if (r.dormindo) { r.dormindo = false; animar("surpreso"); }
|
||||
if (window.MotorRosto.atividade(nome) && nome === "cantar") tocarSom("musica");
|
||||
if (window.MotorRosto.atividade(nome, segundos) && nome === "cantar") tocarSom("musica");
|
||||
}
|
||||
|
||||
function repouso(t) { // pose calma: olha devagar, "respira"
|
||||
@@ -526,6 +533,8 @@ function repouso(t) { // pose calma: olha devagar, "respira
|
||||
if (ATIV.forma) r.forma = ATIV.forma;
|
||||
if (ATIV.boca) r.boca = ATIV.boca;
|
||||
if (ATIV.ab) r.ab = ATIV.ab;
|
||||
} else if (ZANGA >= 0.7) { // alegria caindo: emburrado (a cor escolhida fica)
|
||||
r.forma = "bravo";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,7 +643,13 @@ function trata(ordem) {
|
||||
} else if (ordem.indexOf("ritmo ") === 0) {
|
||||
PERFIL = PERFIS[ordem.slice(6).trim()] || PERFIS.normal;
|
||||
} else if (ordem.indexOf("atividade ") === 0) {
|
||||
atividade(ordem.slice(10).trim());
|
||||
const [nome, seg] = ordem.slice(10).trim().split(/\s+/); // "atividade bola 180"
|
||||
atividade(nome, parseFloat(seg) || 0);
|
||||
} else if (ordem.indexOf("zanga ") === 0) {
|
||||
const z = parseFloat(ordem.slice(6));
|
||||
if (!isNaN(z)) ZANGA = Math.max(0, Math.min(1, z));
|
||||
} else if (ordem === "sono profundo" || ordem === "sono leve") {
|
||||
SONO_PROFUNDO = ordem === "sono profundo";
|
||||
} else if (ordem === "dormir" || ordem === "sono") {
|
||||
r.dormindo = true;
|
||||
atividade(null);
|
||||
@@ -790,6 +805,7 @@ const MIC = {
|
||||
/* Acordar com som: precisa de N barulhos em 1 minuto (ajuste "Sons para acordar"). Na madrugada
|
||||
silenciosa só barulho ALTO conta, e movimento/câmera não acordam (alguém se mexendo na cama). */
|
||||
const DESPERTAR = { sons: 3, noite: true, ini: 23, fim: 7 };
|
||||
function sonoRespeitado() { return madrugada() || SONO_PROFUNDO; }
|
||||
function madrugada() {
|
||||
if (!DESPERTAR.noite || DESPERTAR.ini === DESPERTAR.fim) return false;
|
||||
const h = new Date().getHours();
|
||||
@@ -855,7 +871,7 @@ function som(nivel) {
|
||||
|
||||
if (r.dormindo) {
|
||||
const precisa = Math.max(1, Math.round(DESPERTAR.sons * PERFIL.acordarSom));
|
||||
if (contar(CONTA.somAcordar, madrugada() ? alto : temSom, agora, precisa, "ouvido: barulho")) { // acordou
|
||||
if (contar(CONTA.somAcordar, sonoRespeitado() ? alto : temSom, agora, precisa, "ouvido: barulho")) { // acordou
|
||||
r.dormindo = false;
|
||||
animar("surpreso");
|
||||
MIC.proxSurpresa = agora + MIC.cooldown;
|
||||
@@ -878,6 +894,7 @@ function checarSilencio(agora) {
|
||||
if (!MIC.ativo) return; // telinha do Pi: sem ouvido
|
||||
if (agora - MIC.visto > 2) return; // o ouvido parou de mandar dado
|
||||
if (r.dormindo) return;
|
||||
if (HUMOR !== "normal") return; // modo vida ligado: quem manda dormir é a energia
|
||||
// movimento tambem conta como "tem alguem aqui": nao adormece com gente passando
|
||||
const atividade = Math.max(MIC.ultimoSom, MOV.ativo ? MOV.ultimoMov : 0);
|
||||
if (agora - atividade >= MIC.segSilencio) {
|
||||
@@ -949,7 +966,7 @@ function rastrear(t) {
|
||||
MOV.olharY+=((t.y-.5)*2*MOV.olharMax*.6-MOV.olharY)*.65;
|
||||
if(t.atividade===true) {
|
||||
MOV.ultimoMov=agora;
|
||||
if(r.dormindo && !madrugada() && PERFIL !== PERFIS.calmo) { r.dormindo=false;animar('surpreso'); }
|
||||
if(r.dormindo && !sonoRespeitado() && PERFIL !== PERFIS.calmo) { r.dormindo=false;animar('surpreso'); }
|
||||
}
|
||||
}
|
||||
function movimento(vel, cx, cy) {
|
||||
@@ -981,7 +998,7 @@ function movimento(vel, cx, cy) {
|
||||
const forte = v >= limiar(MOV.limiarForte);
|
||||
if (r.dormindo) {
|
||||
// acordou: algo se mexeu na frente (de dia; calmo precisa de vários movimentos)
|
||||
if (!madrugada() && contar(CONTA.movAcordar, mexeu, agora, PERFIL.acordarMov, "presenca: movimento")) {
|
||||
if (!sonoRespeitado() && contar(CONTA.movAcordar, mexeu, agora, PERFIL.acordarMov, "presenca: movimento")) {
|
||||
r.dormindo = false;
|
||||
animar("surpreso");
|
||||
MOV.proxSurpresa = agora + MOV.cooldown;
|
||||
|
||||
Reference in New Issue
Block a user