Update project files
This commit is contained in:
@@ -408,8 +408,31 @@ function move(role,x,y){
|
||||
ch.style.left=x+'px';
|
||||
ch.style.top=y+'px';
|
||||
}
|
||||
setInterval(()=>{Object.keys(chars).forEach(k=>{const a=anim[k];if(a.mode==='walk'){a.frame=(a.frame+1)%5;setSprite(k,'walk',a.frame,a.dir)}else if(a.mode==='work'){a.frame=(a.frame+1)%4;setSprite(k,'work',a.frame)} });},286)
|
||||
setInterval(()=>{Object.keys(chars).forEach(k=>{const a=anim[k];if(a.mode==='sit'){a.frame=(a.frame+1)%2;setSprite(k,'sit',a.frame)} });},700)
|
||||
// ── Managed intervals (pause while the office view is hidden) ──
|
||||
// The pixel-office runs several animation/roam/banter intervals. While the
|
||||
// webview tab is not visible they do invisible work and keep timers hot —
|
||||
// wasteful. _managedInterval registers each one; a visibilitychange handler
|
||||
// pauses them all when the document is hidden and resumes them when shown.
|
||||
// Behavior while visible is unchanged (same callbacks, same periods).
|
||||
const _managedIntervals=[];
|
||||
function _managedInterval(fn,ms){
|
||||
const rec={fn:fn,ms:ms,id:null};
|
||||
rec.id=setInterval(fn,ms);
|
||||
_managedIntervals.push(rec);
|
||||
return rec;
|
||||
}
|
||||
function _pauseManagedIntervals(){
|
||||
for(const rec of _managedIntervals){ if(rec.id!==null){ clearInterval(rec.id); rec.id=null; } }
|
||||
}
|
||||
function _resumeManagedIntervals(){
|
||||
for(const rec of _managedIntervals){ if(rec.id===null){ rec.id=setInterval(rec.fn,rec.ms); } }
|
||||
}
|
||||
document.addEventListener('visibilitychange',()=>{
|
||||
if(document.hidden) _pauseManagedIntervals();
|
||||
else _resumeManagedIntervals();
|
||||
});
|
||||
_managedInterval(()=>{Object.keys(chars).forEach(k=>{const a=anim[k];if(a.mode==='walk'){a.frame=(a.frame+1)%5;setSprite(k,'walk',a.frame,a.dir)}else if(a.mode==='work'){a.frame=(a.frame+1)%4;setSprite(k,'work',a.frame)} });},286)
|
||||
_managedInterval(()=>{Object.keys(chars).forEach(k=>{const a=anim[k];if(a.mode==='sit'){a.frame=(a.frame+1)%2;setSprite(k,'sit',a.frame)} });},700)
|
||||
// ── 책상 회피 path planner ──
|
||||
// walkPath의 각 leg를 직선이 아닌 *책상을 우회하는* L자 또는 corridor 경로로
|
||||
// 펴서 캐릭터가 책상을 가로지르지 않게. 책상이 회전됐을 때를 대비해 padding
|
||||
@@ -498,7 +521,7 @@ function sendHome(role,mode='sit'){
|
||||
if(Math.abs(cx-hx)<1&&Math.abs(cy-hy)<1){setSprite(role,mode);return;}
|
||||
walkPath(role,[st.dock,[hx,hy]],()=>setSprite(role,mode));
|
||||
}
|
||||
setInterval(()=>{
|
||||
_managedInterval(()=>{
|
||||
if(!['idle','done'].includes(_prevStatus || 'idle')) return;
|
||||
const free=Object.keys(chars).filter(k=>anim[k]?.mode==='sit'&&!chars[k].classList.contains('active'));
|
||||
if(!free.length)return;
|
||||
@@ -725,7 +748,7 @@ function _innerThoughtTick(){
|
||||
const text = _innerThoughtFor(st.agentKey, anim[role].mode);
|
||||
if(text) _bubbleFromLog(role, text);
|
||||
}
|
||||
setInterval(_innerThoughtTick, 7500);
|
||||
_managedInterval(_innerThoughtTick, 7500);
|
||||
|
||||
// ── Webtoon-style 티키타카 banter (refactor: pipeline-aware) ──
|
||||
// 각 phase 에 *시퀀스화된 대화 script* 가 있어 phase 진입 시 한 줄씩 시간 차로 emit.
|
||||
|
||||
Reference in New Issue
Block a user