128 lines
4.2 KiB
JavaScript
128 lines
4.2 KiB
JavaScript
import { TILE, SEA_GY } from '../core/constants.js';
|
||
import { state } from '../core/state.js';
|
||
import { grid, blocks, k, isSolid } from './world-storage.js';
|
||
|
||
// Физика жидкости
|
||
const waterUpdateQueue = new Set();
|
||
let waterUpdateTimer = 0;
|
||
const WATER_UPDATE_INTERVAL = 0.05; // Обновляем воду каждые 0.05 секунды
|
||
|
||
function updateWaterPhysics(dt) {
|
||
waterUpdateTimer += dt;
|
||
if (waterUpdateTimer < WATER_UPDATE_INTERVAL) return;
|
||
waterUpdateTimer = 0;
|
||
|
||
// Ограничиваем количество водных блоков для обработки (оптимизация)
|
||
const MAX_WATER_BLOCKS_PER_UPDATE = 50;
|
||
let processedCount = 0;
|
||
|
||
// Собираем только видимые водные блоки в очередь (оптимизация)
|
||
waterUpdateQueue.clear();
|
||
const W = state.W;
|
||
const H = state.H;
|
||
const minGX = Math.floor(state.camX / TILE) - 10;
|
||
const maxGX = Math.floor((state.camX + W) / TILE) + 10;
|
||
const minGY = Math.floor(state.camY / TILE) - 10;
|
||
const maxGY = Math.floor((state.camY + H) / TILE) + 10;
|
||
|
||
for (const b of blocks) {
|
||
if (processedCount >= MAX_WATER_BLOCKS_PER_UPDATE) break;
|
||
if (!b.dead && b.t === 'water' &&
|
||
b.gx >= minGX && b.gx <= maxGX &&
|
||
b.gy >= minGY && b.gy <= maxGY) {
|
||
waterUpdateQueue.add(k(b.gx, b.gy));
|
||
processedCount++;
|
||
}
|
||
}
|
||
|
||
// Обновляем воду с ограничением глубины распространения
|
||
const processed = new Set();
|
||
const toAdd = [];
|
||
const MAX_WATER_DEPTH = 20; // Максимальная глубина распространения воды
|
||
|
||
for (const key of waterUpdateQueue) {
|
||
if (processed.has(key)) continue;
|
||
const b = grid.get(key);
|
||
if (!b || b.dead) continue;
|
||
processed.add(key);
|
||
|
||
const gx = b.gx;
|
||
const gy = b.gy;
|
||
|
||
// Проверяем глубину - не распространяем воду слишком глубоко
|
||
if (gy > SEA_GY + MAX_WATER_DEPTH) continue;
|
||
|
||
// Проверяем, можно ли воде упасть вниз
|
||
const belowKey = k(gx, gy + 1);
|
||
const below = grid.get(belowKey);
|
||
|
||
// Внизу пусто - вода создаёт новый блок внизу (но не удаляется сверху)
|
||
if (!below || below.dead) {
|
||
// Ограничиваем создание новых водных блоков
|
||
if (toAdd.length < 20) { // Максимум 20 новых блоков за обновление
|
||
toAdd.push({ gx, gy: gy + 1, t: 'water' });
|
||
processed.add(belowKey);
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// Если внизу не вода и не твёрдый блок - вода может течь вниз
|
||
if (!isSolid(gx, gy + 1) && below && below.t !== 'water') {
|
||
if (toAdd.length < 20) {
|
||
toAdd.push({ gx, gy: gy + 1, t: 'water' });
|
||
processed.add(belowKey);
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// Если внизу твёрдый блок или вода - вода растекается горизонтально
|
||
// Проверяем левую сторону
|
||
const leftKey = k(gx - 1, gy);
|
||
const left = grid.get(leftKey);
|
||
if (!left || left.dead) {
|
||
if (toAdd.length < 20) {
|
||
toAdd.push({ gx: gx - 1, gy, t: 'water' });
|
||
processed.add(leftKey);
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// Проверяем правую сторону
|
||
const rightKey = k(gx + 1, gy);
|
||
const right = grid.get(rightKey);
|
||
if (!right || right.dead) {
|
||
if (toAdd.length < 20) {
|
||
toAdd.push({ gx: gx + 1, gy, t: 'water' });
|
||
processed.add(rightKey);
|
||
}
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// Применяем изменения (только добавляем новые блоки)
|
||
for (const newData of toAdd) {
|
||
const key = k(newData.gx, newData.gy);
|
||
if (!grid.has(key)) {
|
||
const b = {
|
||
gx: newData.gx,
|
||
gy: newData.gy,
|
||
t: newData.t,
|
||
dead: false,
|
||
active: false,
|
||
fuse: 0
|
||
};
|
||
grid.set(key, b);
|
||
blocks.push(b);
|
||
}
|
||
}
|
||
|
||
// Очищаем мёртвые блоки из массива
|
||
for (let i = blocks.length - 1; i >= 0; i--) {
|
||
if (blocks[i].dead) {
|
||
blocks.splice(i, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
export { updateWaterPhysics };
|