Add directional arrow hint on map, green grass path border, SELECT/START side by side with larger tap targets
This commit is contained in:
1 parent
9f7a449e3d
commit
deb0dcba92
3 files changed
+76
-6
No files matched your search
@@ -207,6 +207,38 @@ class Game {
|
|||||||
hint.style.bottom= (this.state.playerY + 11) + '%';
|
hint.style.bottom= (this.state.playerY + 11) + '%';
|
||||||
}
|
}
|
||||||
if (bub) bub.style.opacity = near ? '0' : '1';
|
if (bub) bub.style.opacity = near ? '0' : '1';
|
||||||
|
|
||||||
|
this._updateDirArrow(near);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Point a blinking arrow toward the NPC so players know which way to walk */
|
||||||
|
_updateDirArrow(nearNPC) {
|
||||||
|
const arrow = document.getElementById('map-dir-arrow');
|
||||||
|
if (!arrow) return;
|
||||||
|
|
||||||
|
/* Hide arrow once the player is close enough — "Press A" takes over */
|
||||||
|
if (nearNPC) { arrow.style.display = 'none'; return; }
|
||||||
|
|
||||||
|
const dx = this.state.npcX - this.state.playerX;
|
||||||
|
const dy = this.state.npcY - this.state.playerY;
|
||||||
|
|
||||||
|
/* Pick the dominant axis and set the arrow character + animation direction */
|
||||||
|
let glyph = '▶', rotation = '0deg';
|
||||||
|
if (Math.abs(dx) >= Math.abs(dy)) {
|
||||||
|
glyph = dx > 0 ? '▶' : '◀';
|
||||||
|
rotation = dx > 0 ? '0deg' : '180deg';
|
||||||
|
} else {
|
||||||
|
glyph = dy > 0 ? '▲' : '▼';
|
||||||
|
rotation = dy > 0 ? '270deg' : '90deg';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Position arrow near the player, offset so it doesn't overlap the sprite */
|
||||||
|
const offsetX = dx > 0 ? 8 : -6;
|
||||||
|
const offsetY = dy > 0 ? 8 : -6;
|
||||||
|
arrow.textContent = glyph;
|
||||||
|
arrow.style.display = 'block';
|
||||||
|
arrow.style.left = Math.max(2, Math.min(90, this.state.playerX + offsetX)) + '%';
|
||||||
|
arrow.style.bottom = Math.max(28, Math.min(70, this.state.playerY + offsetY)) + '%';
|
||||||
}
|
}
|
||||||
|
|
||||||
_nearNPC() {
|
_nearNPC() {
|
||||||
@@ -215,7 +247,11 @@ class Game {
|
|||||||
return dx < 12 && dy < 12;
|
return dx < 12 && dy < 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
_talkToNPC() { this.startQuestion(); }
|
_talkToNPC() {
|
||||||
|
const arrow = document.getElementById('map-dir-arrow');
|
||||||
|
if (arrow) arrow.style.display = 'none';
|
||||||
|
this.startQuestion();
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Position player & NPC on map ──────────────────────── */
|
/* ── Position player & NPC on map ──────────────────────── */
|
||||||
_placeMapSprites() {
|
_placeMapSprites() {
|
||||||
@@ -497,6 +533,7 @@ class Game {
|
|||||||
if (q && npcEl) npcEl.textContent = NPC[q.npc]||'🧑';
|
if (q && npcEl) npcEl.textContent = NPC[q.npc]||'🧑';
|
||||||
|
|
||||||
this._placeMapSprites();
|
this._placeMapSprites();
|
||||||
|
this._updateDirArrow(false); /* show arrow immediately on map entry */
|
||||||
saveGame(this.state);
|
saveGame(this.state);
|
||||||
this.flashSaveDot();
|
this.flashSaveDot();
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,8 @@
|
|||||||
<div class="map-player" id="map-player">🧢</div>
|
<div class="map-player" id="map-player">🧢</div>
|
||||||
<!-- interaction speech bubble -->
|
<!-- interaction speech bubble -->
|
||||||
<div class="map-talk-hint" id="map-talk-hint" style="display:none">Press A</div>
|
<div class="map-talk-hint" id="map-talk-hint" style="display:none">Press A</div>
|
||||||
|
<!-- directional nudge arrow — points player toward NPC -->
|
||||||
|
<div class="map-dir-arrow" id="map-dir-arrow" style="display:none">▶</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="map-hud">
|
<div class="map-hud">
|
||||||
<div class="hud-cell"><div class="hud-lbl">TRAINER</div><div class="hud-val" id="hud-name">ASH</div></div>
|
<div class="hud-cell"><div class="hud-lbl">TRAINER</div><div class="hud-val" id="hud-name">ASH</div></div>
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ html, body {
|
|||||||
@keyframes abPress { 0%{transform:scale(1)}40%{transform:scale(.82)}100%{transform:scale(1)} }
|
@keyframes abPress { 0%{transform:scale(1)}40%{transform:scale(.82)}100%{transform:scale(1)} }
|
||||||
@keyframes choiceCursor { 0%,100%{box-shadow:0 0 0 3px var(--yellow), 2px 2px 0 var(--darkgray)}50%{box-shadow:0 0 0 3px #ffe878, 2px 2px 0 var(--darkgray)} }
|
@keyframes choiceCursor { 0%,100%{box-shadow:0 0 0 3px var(--yellow), 2px 2px 0 var(--darkgray)}50%{box-shadow:0 0 0 3px #ffe878, 2px 2px 0 var(--darkgray)} }
|
||||||
@keyframes talkBubble { 0%{transform:translateY(0)}50%{transform:translateY(-3px)} }
|
@keyframes talkBubble { 0%{transform:translateY(0)}50%{transform:translateY(-3px)} }
|
||||||
|
@keyframes arrowPulse { 0%,100%{transform:scale(1) translateX(0);opacity:1} 50%{transform:scale(1.25) translateX(4px);opacity:.7} }
|
||||||
|
|
||||||
.blink { animation: blink 1s step-end infinite; }
|
.blink { animation: blink 1s step-end infinite; }
|
||||||
|
|
||||||
@@ -238,22 +239,25 @@ html, body {
|
|||||||
/* ── SELECT / START (center strip) ───────────────────────── */
|
/* ── SELECT / START (center strip) ───────────────────────── */
|
||||||
.gba-mid-btns {
|
.gba-mid-btns {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
gap: 6px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.gba-mid-btn {
|
.gba-mid-btn {
|
||||||
background: #2a1a5e;
|
background: #2a1a5e;
|
||||||
border: 2px solid rgba(255,255,255,.2);
|
border: 2px solid rgba(255,255,255,.2);
|
||||||
border-radius: 20px;
|
border-radius: 30px;
|
||||||
color: rgba(255,255,255,.6);
|
color: rgba(255,255,255,.6);
|
||||||
font-family: var(--font);
|
font-family: var(--font);
|
||||||
font-size: clamp(4.5px, 1.2vw, 6px);
|
font-size: clamp(4.5px, 1.2vw, 6px);
|
||||||
padding: 4px 10px;
|
padding: clamp(8px, 2vw, 11px) clamp(10px, 2.5vw, 14px);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
letter-spacing: .5px;
|
letter-spacing: .5px;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
transition: background .08s;
|
transition: background .08s;
|
||||||
|
min-width: 52px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
.gba-mid-btn:active { background: #3d2f99; }
|
.gba-mid-btn:active { background: #3d2f99; }
|
||||||
|
|
||||||
@@ -385,7 +389,34 @@ html, body {
|
|||||||
.map-trees { position:absolute; top:12%; left:0; right:0; display:flex; justify-content:space-around; padding:0 8px; }
|
.map-trees { position:absolute; top:12%; left:0; right:0; display:flex; justify-content:space-around; padding:0 8px; }
|
||||||
.tree { font-size:clamp(24px,7vw,36px); display:inline-block; animation:treeSway 3s ease-in-out infinite; filter:drop-shadow(1px 2px 0 rgba(0,0,0,.3)); }
|
.tree { font-size:clamp(24px,7vw,36px); display:inline-block; animation:treeSway 3s ease-in-out infinite; filter:drop-shadow(1px 2px 0 rgba(0,0,0,.3)); }
|
||||||
.tree:nth-child(2){animation-delay:.5s;} .tree:nth-child(3){animation-delay:1s;} .tree:nth-child(4){animation-delay:1.5s;} .tree:nth-child(5){animation-delay:2s;}
|
.tree:nth-child(2){animation-delay:.5s;} .tree:nth-child(3){animation-delay:1s;} .tree:nth-child(4){animation-delay:1.5s;} .tree:nth-child(5){animation-delay:2s;}
|
||||||
.map-ground { position:absolute; bottom:0; left:0; right:0; height:32%; background:linear-gradient(180deg,#c0a060 0%,#a89050 100%); border-top:3px solid #907840; }
|
.map-ground {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0; left: 0; right: 0;
|
||||||
|
height: 32%;
|
||||||
|
/* layered: green grass strip at top, then dirt path */
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
#4a9e30 0%, /* bright grass edge */
|
||||||
|
#3d8a28 6%, /* darker grass */
|
||||||
|
#c0a060 6%, /* dirt path starts */
|
||||||
|
#b89858 50%,
|
||||||
|
#a08848 100%
|
||||||
|
);
|
||||||
|
border-top: 4px solid #2d6e1a; /* crisp grass line */
|
||||||
|
box-shadow: inset 0 4px 0 rgba(80,160,30,.35); /* soft green glow into path */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Directional nudge arrow — floats at bottom of map, points toward NPC */
|
||||||
|
.map-dir-arrow {
|
||||||
|
position: absolute;
|
||||||
|
font-size: clamp(20px, 6vw, 28px);
|
||||||
|
color: var(--yellow);
|
||||||
|
text-shadow: 0 0 6px rgba(248,192,48,.8), 2px 2px 0 rgba(0,0,0,.5);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 20;
|
||||||
|
animation: arrowPulse .7s ease-in-out infinite;
|
||||||
|
filter: drop-shadow(0 0 4px rgba(248,192,48,.6));
|
||||||
|
}
|
||||||
|
|
||||||
/* NPC on map */
|
/* NPC on map */
|
||||||
.map-npc-wrap { position:absolute; text-align:center; transition: left .4s ease, bottom .4s ease; }
|
.map-npc-wrap { position:absolute; text-align:center; transition: left .4s ease, bottom .4s ease; }
|
||||||
|
|||||||
Reference in new issue
Block a user