import { TILE } from '../core/constants.js'; import { BLOCKS } from '../data/blocks.js'; import { state } from '../core/state.js'; import { getBlock, isSolid } from '../world/world-storage.js'; import { calculateDamage } from '../entities/player.js'; function resolveY(e) { // Всегда пересчитываем grounded (не держим "липким") e.grounded = false; const x1 = e.x + 2; const x2 = e.x + e.w - 2; // Проверяем, находится ли игрок на лестнице (по центру) const cx = e.x + e.w / 2; const cy = e.y + e.h / 2; const gx = Math.floor(cx / TILE); const gy = Math.floor(cy / TILE); const b = getBlock(gx, gy); const onLadder = b && BLOCKS[b.t] && BLOCKS[b.t].climbable; // Если на лестнице - можно двигаться вверх/вниз if (onLadder) { e.grounded = true; // Если нажимаем прыжок на лестнице - поднимаемся if (state.inp.jump) { e.vy = -200; } // Если нажимаем вниз - спускаемся else if (state.inp.down) { e.vy = 100; } // Иначе - остаёмся на месте (нет гравитации) else { e.vy = 0; } return; } // Проверяем, можно ли запрыгнуть на лестницу рядом (слева или справа) const leftGX = Math.floor((e.x - 4) / TILE); const rightGX = Math.floor((e.x + e.w + 4) / TILE); const playerGY = Math.floor((e.y + e.h / 2) / TILE); const leftBlock = getBlock(leftGX, playerGY); const rightBlock = getBlock(rightGX, playerGY); const leftLadder = leftBlock && BLOCKS[leftBlock.t] && BLOCKS[leftBlock.t].climbable; const rightLadder = rightBlock && BLOCKS[rightBlock.t] && BLOCKS[rightBlock.t].climbable; // Если рядом есть лестница и игрок прыгает - притягиваем к ней if ((leftLadder || rightLadder) && state.inp.jump && e.vy < 0) { // Перемещаем игрока к лестнице if (leftLadder && e.x > leftGX * TILE + TILE / 2) { e.x = leftGX * TILE + TILE / 2 - e.w / 2; } else if (rightLadder && e.x < rightGX * TILE + TILE / 2) { e.x = rightGX * TILE + TILE / 2 - e.w / 2; } e.grounded = true; e.vy = -150; // меньший прыжок при запрыгивании на лестницу return; } // 1) Если движемся вниз ИЛИ стоим (vy >= 0) — проверяем опору под ногами // Берём точку на 1px ниже стопы, чтобы не зависеть от ровного попадания в границу тайла. if (e.vy >= 0) { const probeY = e.y + e.h + 1; const gy = Math.floor(probeY / TILE); const gxA = Math.floor(x1 / TILE); const gxB = Math.floor(x2 / TILE); if (isSolid(gxA, gy) || isSolid(gxB, gy)) { e.y = gy * TILE - e.h; // прижимаем к полу e.vy = 0; e.grounded = true; // урон от падения — только игроку и только не в воде if (e === state.player && !state.player.inWater) { const fallTiles = (e.y - e.fallStartY) / TILE; if (fallTiles > 6) { const damage = calculateDamage((fallTiles - 6) * 10); state.player.hp -= damage; } } if (e === state.player) e.fallStartY = e.y; } } // 2) Проверка на возможность запрыгнуть на блок, если игрок рядом с ним if (e.vy < 0 && e === state.player) { const gy = Math.floor(e.y / TILE); const gxA = Math.floor(x1 / TILE); const gxB = Math.floor(x2 / TILE); // Проверяем, есть ли блок рядом с игроком if ((isSolid(gxA, gy) || isSolid(gxB, gy)) && !isSolid(gxA, gy - 1) && !isSolid(gxB, gy - 1)) { e.y = (gy + 1) * TILE; e.vy = 0; e.grounded = true; if (e === state.player) e.fallStartY = e.y; console.log("Jumped onto block!"); } } // 2) Если движемся вверх — проверяем потолок if (e.vy < 0) { const gy = Math.floor(e.y / TILE); const gxA = Math.floor(x1 / TILE); const gxB = Math.floor(x2 / TILE); if (isSolid(gxA, gy) || isSolid(gxB, gy)) { e.y = (gy + 1) * TILE; e.vy = 0; } } } function resolveX(e) { const y1 = e.y + 2; const y2 = e.y + e.h - 2; // Проверяем, находимся ли мы на лестнице const cx = e.x + e.w / 2; const cy = e.y + e.h / 2; const gx = Math.floor(cx / TILE); const gy = Math.floor(cy / TILE); const b = getBlock(gx, gy); const onLadder = b && BLOCKS[b.t] && BLOCKS[b.t].climbable; if (e.vx > 0) { const gx = Math.floor((e.x + e.w) / TILE); const gyA = Math.floor(y1 / TILE); const gyB = Math.floor(y2 / TILE); const solidA = isSolid(gx, gyA); const solidB = isSolid(gx, gyB); if (solidA || solidB) { e.x = gx * TILE - e.w; e.vx = 0; } } else if (e.vx < 0) { const gx = Math.floor(e.x / TILE); const gyA = Math.floor(y1 / TILE); const gyB = Math.floor(y2 / TILE); const solidA = isSolid(gx, gyA); const solidB = isSolid(gx, gyB); if (solidA || solidB) { e.x = (gx + 1) * TILE; e.vx = 0; } } } export { resolveY, resolveX };