diff --git a/game.js b/game.js index 87d4c48..39fb9d0 100644 --- a/game.js +++ b/game.js @@ -205,7 +205,7 @@ class Game { const p = document.getElementById('map-player'); if (p) { const centreX = viewW / 2 - 20; - const centreY = viewH * 0.60 + this.state.worldY; + const centreY = viewH * 0.75 + this.state.worldY; p.style.left = centreX + 'px'; p.style.bottom = (viewH - centreY - 40) + 'px'; p.className = `map-player walk-${dir}`; @@ -214,10 +214,22 @@ class Game { this._checkNPCProximity(); } - /* Slide the world so the camera follows the player */ + /* Slide the world and reposition NPC in screen-space every tick */ _applyCamera() { const world = document.getElementById('map-inner'); if (world) world.style.transform = `translateX(${-this.state.worldX}px)`; + this._positionNPCOnScreen(); + } + + _positionNPCOnScreen() { + const world = document.getElementById('map-inner'); + const viewH = world ? world.parentElement.offsetHeight : 300; + const npcWrap = document.getElementById('map-npc-wrap'); + if (npcWrap) { + const screenX = this.state.npcWorldX - this.state.worldX; + npcWrap.style.left = (screenX - 24) + 'px'; + npcWrap.style.bottom = (viewH * 0.18) + 'px'; + } } _checkNPCProximity() { @@ -233,7 +245,7 @@ class Game { if (hint) { hint.style.display = near ? 'block' : 'none'; hint.style.left = (viewW / 2 - 28) + 'px'; - hint.style.bottom = (viewH * 0.46) + 'px'; + hint.style.bottom = (viewH * 0.32) + 'px'; } if (bub) bub.style.opacity = near ? '0' : '1'; this._updateDirArrow(near); @@ -250,7 +262,7 @@ class Game { arrow.textContent = npcScreenX >= viewW / 2 ? 'โ–ถ' : 'โ—€'; arrow.style.display = 'block'; arrow.style.left = (viewW / 2 + 30) + 'px'; - arrow.style.bottom = (viewH * 0.40) + 'px'; + arrow.style.bottom = (viewH * 0.28) + 'px'; } _nearNPC() { @@ -266,7 +278,7 @@ class Game { this.startQuestion(); } - /* Place player at viewport centre, NPC at world-px position */ + /* Place player at viewport centre, NPC via screen-space conversion */ _placeMapSprites() { const world = document.getElementById('map-inner'); const viewW = world ? world.parentElement.offsetWidth : 420; @@ -275,15 +287,10 @@ class Game { const p = document.getElementById('map-player'); if (p) { p.style.left = (viewW / 2 - 20) + 'px'; - p.style.bottom = (viewH * 0.32) + 'px'; + p.style.bottom = (viewH * 0.18) + 'px'; p.style.transform = 'scaleX(-1)'; p.className = 'map-player idle'; } - const npcWrap = document.getElementById('map-npc-wrap'); - if (npcWrap) { - npcWrap.style.left = (this.state.npcWorldX - 24) + 'px'; - npcWrap.style.bottom = (viewH * 0.32) + 'px'; - } this._applyCamera(); const hint = document.getElementById('map-talk-hint'); if (hint) hint.style.display = 'none'; diff --git a/index.html b/index.html index e6f5d43..09d2db5 100644 --- a/index.html +++ b/index.html @@ -107,14 +107,14 @@ ๐ŸŒฒ๐ŸŒณ๐ŸŒฒ ๐ŸŒณ๐ŸŒฒ๐ŸŒณ - -
-
!
-
-
+ +
+
!
+
+
๐Ÿงข
diff --git a/style.css b/style.css index 452c6b3..5bd6cb5 100644 --- a/style.css +++ b/style.css @@ -395,6 +395,7 @@ html, body { top: 0; bottom: 0; left: 0; width: 400%; will-change: transform; + z-index: 5; } .map-trees { position: absolute; @@ -436,7 +437,7 @@ html, body { filter: drop-shadow(0 0 4px rgba(248,192,48,.6)); } /* NPC lives inside .map-inner, positioned in world-px via JS */ -.map-npc-wrap { position:absolute; text-align:center; } +.map-npc-wrap { position:absolute; text-align:center; z-index: 30; } .npc-bubble { font-size:14px; font-family:var(--font); color:var(--black); background:var(--yellow); border:2px solid var(--black); width:20px; height:20px; display:flex; align-items:center; justify-content:center; margin:0 auto 2px; animation:bounce .7s ease-in-out infinite; } .map-npc { font-size:clamp(36px,10vw,52px); filter:drop-shadow(2px 3px 0 rgba(0,0,0,.35)); cursor:pointer; } /* Player is fixed to the viewport centre horizontally; only Y moves */