Add '...' chat bubble above player when pressing talk before reaching NPC
This commit is contained in:
@@ -388,9 +388,13 @@ class Game {
|
|||||||
if (p) {
|
if (p) {
|
||||||
const centreX = viewW / 2 - 16;
|
const centreX = viewW / 2 - 16;
|
||||||
const centreY = viewH * 0.65 + this.state.worldY;
|
const centreY = viewH * 0.65 + this.state.worldY;
|
||||||
|
const bottomPx = viewH - centreY - 40;
|
||||||
p.style.left = centreX + 'px';
|
p.style.left = centreX + 'px';
|
||||||
p.style.bottom = (viewH - centreY - 40) + 'px';
|
p.style.bottom = bottomPx + 'px';
|
||||||
p.className = `map-player walk-${dir}`;
|
p.className = `map-player walk-${dir}`;
|
||||||
|
/* Keep "..." bubble above player */
|
||||||
|
const bub = document.getElementById('player-bubble');
|
||||||
|
if (bub) { bub.style.left = (centreX - 4) + 'px'; bub.style.bottom = (bottomPx + 66) + 'px'; }
|
||||||
}
|
}
|
||||||
|
|
||||||
this._checkNPCProximity();
|
this._checkNPCProximity();
|
||||||
@@ -453,8 +457,22 @@ class Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_talkToNPC() {
|
_talkToNPC() {
|
||||||
|
if (!this._nearNPC()) {
|
||||||
|
/* Too far away — show "..." bubble above player */
|
||||||
|
const bub = document.getElementById('player-bubble');
|
||||||
|
if (bub) {
|
||||||
|
bub.classList.remove('visible');
|
||||||
|
void bub.offsetWidth;
|
||||||
|
bub.classList.add('visible');
|
||||||
|
clearTimeout(this._bubbleTimer);
|
||||||
|
this._bubbleTimer = setTimeout(() => bub.classList.remove('visible'), 1500);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
const arrow = document.getElementById('map-dir-arrow');
|
const arrow = document.getElementById('map-dir-arrow');
|
||||||
if (arrow) arrow.style.display = 'none';
|
if (arrow) arrow.style.display = 'none';
|
||||||
|
const bub = document.getElementById('player-bubble');
|
||||||
|
if (bub) bub.classList.remove('visible');
|
||||||
SFX.encounter();
|
SFX.encounter();
|
||||||
this.startQuestion();
|
this.startQuestion();
|
||||||
}
|
}
|
||||||
@@ -467,10 +485,13 @@ class Game {
|
|||||||
|
|
||||||
const p = document.getElementById('map-player');
|
const p = document.getElementById('map-player');
|
||||||
if (p) {
|
if (p) {
|
||||||
p.style.left = (viewW / 2 - 16) + 'px';
|
const left = viewW / 2 - 16;
|
||||||
p.style.bottom = (viewH * 0.28) + 'px';
|
const bottom = viewH * 0.28;
|
||||||
|
p.style.left = left + 'px';
|
||||||
|
p.style.bottom = bottom + 'px';
|
||||||
p.className = 'map-player idle';
|
p.className = 'map-player idle';
|
||||||
|
const bub = document.getElementById('player-bubble');
|
||||||
|
if (bub) { bub.style.left = (left - 4) + 'px'; bub.style.bottom = (bottom + 66) + 'px'; }
|
||||||
}
|
}
|
||||||
this._applyCamera();
|
this._applyCamera();
|
||||||
const hint = document.getElementById('map-talk-hint');
|
const hint = document.getElementById('map-talk-hint');
|
||||||
|
|||||||
@@ -109,6 +109,7 @@
|
|||||||
<div class="map-npc" id="map-npc"></div>
|
<div class="map-npc" id="map-npc"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Player stays fixed to viewport, only Y moves -->
|
<!-- Player stays fixed to viewport, only Y moves -->
|
||||||
|
<div class="player-bubble" id="player-bubble">...</div>
|
||||||
<div class="map-player" id="map-player"></div>
|
<div class="map-player" id="map-player"></div>
|
||||||
<!-- Hints overlay the viewport, not the world -->
|
<!-- Hints overlay the viewport, not the world -->
|
||||||
<div class="map-talk-hint" id="map-talk-hint" style="display:none"><span class="hint-pc">Press E</span><span class="hint-touch">Press A</span></div>
|
<div class="map-talk-hint" id="map-talk-hint" style="display:none"><span class="hint-pc">Press E</span><span class="hint-touch">Press A</span></div>
|
||||||
|
|||||||
@@ -483,6 +483,38 @@ html, body {
|
|||||||
.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; }
|
.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; }
|
.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 */
|
/* Player is fixed to the viewport centre horizontally; only Y moves */
|
||||||
|
/* "..." bubble above player when pressing talk away from NPC */
|
||||||
|
.player-bubble {
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: var(--font);
|
||||||
|
color: var(--black);
|
||||||
|
background: #fff;
|
||||||
|
border: 2px solid var(--black);
|
||||||
|
padding: 0 5px;
|
||||||
|
height: 20px;
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 2px;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 100;
|
||||||
|
box-shadow: 1px 1px 0 rgba(0,0,0,.3);
|
||||||
|
}
|
||||||
|
.player-bubble::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -6px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-top-color: var(--black);
|
||||||
|
}
|
||||||
|
.player-bubble.visible {
|
||||||
|
display: flex;
|
||||||
|
animation: bounce .5s ease-in-out 3;
|
||||||
|
}
|
||||||
|
|
||||||
.map-player {
|
.map-player {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
@@ -493,7 +525,7 @@ html, body {
|
|||||||
background-position: 0 0;
|
background-position: 0 0;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
filter: drop-shadow(2px 3px 0 rgba(0,0,0,.4));
|
filter: drop-shadow(2px 3px 0 rgba(0,0,0,.4));
|
||||||
z-index: 99;
|
z-index: 10;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user