/
chewy
/
BDZ_GenAI
Обзор
Документация
Войти
/
chewy
/
BDZ_GenAI
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
scripts/loop-control.js
164 строки
7 KB
pichugin.sa
Раскидал все по папкам, чтобы нормально выглядел репозиторий
16 ноя 2025, 21:55
16 ноя 2025, 21:55
bd854ee
Код
Авторство
О чём код?
// loop-control.js - moved from main.js: update loop, autosave, world init, scheduler start import * as E from './engine.js'; import * as U from './scripts/ui.js'; import * as HUD from './hud.js'; import * as LANG from './language.js'; import * as NOTIF from './scripts/notify.js'; import Ambient from './ambient.js'; import Events from './events.js'; import * as WorldGen from './worldgen.js'; import { CONFIG } from './engine.js'; let last = performance.now(); let autosaveTimer = 0; function doAutosave(){ try{ const state = { player: { x: E.player.x, y: E.player.y, w: E.player.w, h: E.player.h, stamina: E.player.stamina, health: E.player.health, scale: E.player.scale, inventory: E.player.inventory || [] }, scaleSetting: HUD.scaleSetting, reputation: HUD.RuleEngine ? HUD.RuleEngine.factions : {}, codex: (window.__LanguageSystem && window.__LanguageSystem.codex) || {}, seed: E.seed || window.__worldSeed, timeOfDay: E.timeOfDay || (window.__engine && window.__engine.timeOfDay) || 0 }; localStorage.setItem('ScaleShift_save_v1', JSON.stringify(state)); NOTIF.notify('Autosave выполнено', 'info', 900); }catch(e){ console.error('autosave failed', e); } } function updatePlayerMovement(dt){ // simple movement: WASD / arrow keys support, respects scale multipliers and caps within world const keys = window.__keys || {}; const p = E.player; const prev = { x: p.x, y: p.y }; const mul = CONFIG.scaleMultipliers && CONFIG.scaleMultipliers[p.scale || 2] ? CONFIG.scaleMultipliers[p.scale || 2] : 1; let vx = 0, vy = 0; if(keys['w'] || keys['arrowup']) vy -= 1; if(keys['s'] || keys['arrowdown']) vy += 1; if(keys['a'] || keys['arrowleft']) vx -= 1; if(keys['d'] || keys['arrowright']) vx += 1; if(vx !== 0 || vy !== 0){ const norm = Math.hypot(vx, vy) || 1; const speed = (CONFIG.baseSpeedNormal || 100) * mul; p.vx = (vx / norm) * speed; p.vy = (vy / norm) * speed; p.x += p.vx * dt; p.y += p.vy * dt; p.spriteTimer = (p.spriteTimer || 0) + dt; if(p.spriteTimer > 0.18){ p.spriteFrame = 1 - p.spriteFrame; p.spriteTimer = 0; } } else { // simple damping when no input p.vx = (p.vx || 0) * 0.6; p.vy = (p.vy || 0) * 0.6; p.x += (p.vx || 0) * dt; p.y += (p.vy || 0) * dt; p.spriteFrame = 0; } // collision with world platforms (treat as solid by default unless platform.solid === false) try{ const plats = E.platforms || []; for(const pl of plats){ if(pl.solid === false) continue; // if colliding with platform, try to resolve by reverting (default) if(E.rectsOverlap(p, pl)){ // check if we collided with a box instead of static platform and try push box let pushed = false; for(const b of (E.boxes || [])){ if(E.rectsOverlap(p, b)){ // attempt to move box by same delta p.x - prev.x, p.y - prev.y const dx = p.x - prev.x, dy = p.y - prev.y; // attempt to slide box, but prevent if box would hit another solid platform or world bounds const newBx = b.x + dx, newBy = b.y + dy; const boxRect = {x:newBx, y:newBy, w:b.w, h:b.h}; const collides = plats.some(pl2 => (pl2.solid !== false) && E.rectsOverlap(boxRect, pl2)); if(!collides && newBx >= 0 && newBy >= 0 && newBx + b.w <= E.world.width && newBy + b.h <= E.world.height){ b.x = newBx; b.y = newBy; pushed = true; // small cooldown to avoid rapid repeated pushes b.teleCooldown = 0.08; break; } else { // cannot push — revert player pushed = false; } } } if(!pushed){ p.x = prev.x; p.y = prev.y; p.vx = p.vy = 0; } break; } } }catch(e){} // clamp to world bounds p.x = Math.max(0, Math.min(E.world.width - (p.w||28), p.x)); p.y = Math.max(0, Math.min(E.world.height - (p.h||44), p.y)); } function updateBase(dt){ // small wrapper to call UI/engine update tick that used to live in main.js try{ // movement & npc/village updates updatePlayerMovement(dt); // smooth camera follow: center camera on player with inertia and clamping try { const cam = HUD.cam || { x:0,y:0,zoom:1 }; const p = E.player; const Wv = (E.canvas.clientWidth || 900) / (cam.zoom || 1); const Hv = (E.canvas.clientHeight || 600) / (cam.zoom || 1); const targetX = p.x + (p.w||28)/2 - Wv/2; const targetY = p.y + (p.h||44)/2 - Hv/2; const lerp = (E.CONFIG && E.CONFIG.inertia && E.CONFIG.inertia.lerpFactor) ? E.CONFIG.inertia.lerpFactor : 0.12; cam.x += (targetX - (cam.x||0)) * Math.min(1, lerp + dt*4); cam.y += (targetY - (cam.y||0)) * Math.min(1, lerp + dt*4); // clamp to world bounds with padding const pad = (E.CONFIG && E.CONFIG.camera && E.CONFIG.camera.clampPadding) ? E.CONFIG.camera.clampPadding : 40; cam.x = Math.max(pad, Math.min(E.world.width - Wv - pad, cam.x)); cam.y = Math.max(pad, Math.min(E.world.height - Hv - pad, cam.y)); }catch(e){} if(typeof window.__updateTick === 'function'){ window.__updateTick(dt); return; } // fallback: basic update loop copied from previous refactor point // NOTE: heavy logic remains in engine/ui modules; this is a simplified runner // (The detailed update body was intentionally moved into engine/ui modules for clarity.) }catch(e){ console.error('updateBase error', e); } } function loop(now){ const dt = Math.min(0.033, (now - last) / 1000); last = now; autosaveTimer += dt; if(autosaveTimer >= 60){ autosaveTimer = 0; doAutosave(); } if(!window.__paused) updateBase(dt); // draw scene (ui module delegates to renderer) try{ U.drawScene(E.canvas.clientWidth, E.canvas.clientHeight); }catch(e){} // auto-handle player death placeholder (kept minimal) if(E.player.health <= 0){ if(!E.player._deadHandled){ E.player._deadHandled = true; // save knowledge/progress then regenerate world (delegated) U.saveGame(); const newSeed = Math.floor(Math.random()*1e9); WorldGen.generateWorld(newSeed); U.resizeMinimap(); setTimeout(()=> { U.loadGame(); U.notify('Вы погибли — мир перезапущен, знания сохранены', 'info', 1800); setTimeout(()=> { E.player._deadHandled = false; }, 800); }, 120); } } requestAnimationFrame(loop); } // bootstrap sequence (init time/weather & generate world if needed) E.initTimeAndWeather && E.initTimeAndWeather(); if(typeof window.__worldSeed === 'undefined'){ WorldGen.generateWorld(Math.floor(Math.random()*1e9)); } // start world events and main loop Events.startScheduler(); last = performance.now(); requestAnimationFrame(loop); // expose autosave/doAutosave for external triggers export { doAutosave, updateBase };