Replace hat emoji with player.png sprite sheet — directional walk animations from 24-frame sheet
This commit is contained in:
@@ -346,8 +346,10 @@ class Game {
|
|||||||
const p = document.getElementById('map-player');
|
const p = document.getElementById('map-player');
|
||||||
if (p) {
|
if (p) {
|
||||||
p.className = 'map-player idle';
|
p.className = 'map-player idle';
|
||||||
/* keep facing the last direction moved */
|
/* Show the idle/middle frame for the last direction walked
|
||||||
p.style.transform = this.state.lastDir === 'right' ? 'scaleX(-1)' : 'scaleX(1)';
|
Frames at 2× scale (32px each): down=32, up=128, left=224, right=320 */
|
||||||
|
const idleFrames = { down:'-32px', up:'-128px', left:'-224px', right:'-320px' };
|
||||||
|
p.style.backgroundPositionX = idleFrames[this.state.lastDir] || '-32px';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -382,7 +384,7 @@ class Game {
|
|||||||
/* Player sprite stays horizontally centred; only Y shifts */
|
/* Player sprite stays horizontally centred; only Y shifts */
|
||||||
const p = document.getElementById('map-player');
|
const p = document.getElementById('map-player');
|
||||||
if (p) {
|
if (p) {
|
||||||
const centreX = viewW / 2 - 20;
|
const centreX = viewW / 2 - 16;
|
||||||
const centreY = viewH * 0.57 + this.state.worldY;
|
const centreY = viewH * 0.57 + this.state.worldY;
|
||||||
p.style.left = centreX + 'px';
|
p.style.left = centreX + 'px';
|
||||||
p.style.bottom = (viewH - centreY - 40) + 'px';
|
p.style.bottom = (viewH - centreY - 40) + 'px';
|
||||||
@@ -463,9 +465,9 @@ class Game {
|
|||||||
|
|
||||||
const p = document.getElementById('map-player');
|
const p = document.getElementById('map-player');
|
||||||
if (p) {
|
if (p) {
|
||||||
p.style.left = (viewW / 2 - 20) + 'px';
|
p.style.left = (viewW / 2 - 16) + 'px';
|
||||||
p.style.bottom = (viewH * 0.36) + 'px';
|
p.style.bottom = (viewH * 0.36) + 'px';
|
||||||
p.style.transform = 'scaleX(-1)';
|
|
||||||
p.className = 'map-player idle';
|
p.className = 'map-player idle';
|
||||||
}
|
}
|
||||||
this._applyCamera();
|
this._applyCamera();
|
||||||
|
|||||||
+1
-1
@@ -109,7 +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="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>
|
||||||
<div class="map-dir-arrow" id="map-dir-arrow" style="display:none">▶</div>
|
<div class="map-dir-arrow" id="map-dir-arrow" style="display:none">▶</div>
|
||||||
|
|||||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
@@ -100,10 +100,12 @@ html, body {
|
|||||||
@keyframes wrongShake { 0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)} }
|
@keyframes wrongShake { 0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)} }
|
||||||
@keyframes npcFloat { 0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)} }
|
@keyframes npcFloat { 0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)} }
|
||||||
@keyframes treeSway { 0%,100%{transform:rotate(-2deg)}50%{transform:rotate(2deg)} }
|
@keyframes treeSway { 0%,100%{transform:rotate(-2deg)}50%{transform:rotate(2deg)} }
|
||||||
@keyframes walkLeft { 0%,100%{transform:scaleX(1) translateY(0)}50%{transform:scaleX(1) translateY(-4px)} }
|
/* Sprite walk — player.png 384x32px, 24 frames at 16x32px each
|
||||||
@keyframes walkRight { 0%,100%{transform:scaleX(-1) translateY(0)}50%{transform:scaleX(-1) translateY(-4px)} }
|
Layout: 0-2=down 3-5=up 6-8=left 9-11=right */
|
||||||
@keyframes walkUp { 0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)} }
|
@keyframes walkDown { from{background-position-x: 0px} to{background-position-x: -96px} }
|
||||||
@keyframes walkDown { 0%,100%{transform:translateY(0)}50%{transform:translateY(4px)} }
|
@keyframes walkUp { from{background-position-x: -96px} to{background-position-x: -192px} }
|
||||||
|
@keyframes walkLeft { from{background-position-x:-192px} to{background-position-x: -288px} }
|
||||||
|
@keyframes walkRight { from{background-position-x:-288px} to{background-position-x: -384px} }
|
||||||
@keyframes dpadPress { 0%{transform:scale(1)}50%{transform:scale(.88)}100%{transform:scale(1)} }
|
@keyframes dpadPress { 0%{transform:scale(1)}50%{transform:scale(.88)}100%{transform:scale(1)} }
|
||||||
@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)} }
|
||||||
@@ -469,16 +471,23 @@ html, body {
|
|||||||
/* Player is fixed to the viewport centre horizontally; only Y moves */
|
/* Player is fixed to the viewport centre horizontally; only Y moves */
|
||||||
.map-player {
|
.map-player {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
font-size: clamp(28px, 8vw, 40px);
|
width: 32px;
|
||||||
|
height: 64px;
|
||||||
|
background-image: url('./player.png');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 768px 64px;
|
||||||
|
background-position: 0 0;
|
||||||
|
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: 10;
|
z-index: 10;
|
||||||
line-height: 1;
|
font-size: 0;
|
||||||
|
color: transparent;
|
||||||
}
|
}
|
||||||
.map-player.walk-left { animation: walkLeft .25s steps(1) infinite; }
|
.map-player.walk-down { animation: walkDown .32s steps(3) infinite; }
|
||||||
.map-player.walk-right { animation: walkRight .25s steps(1) infinite; }
|
.map-player.walk-up { animation: walkUp .32s steps(3) infinite; }
|
||||||
.map-player.walk-up { animation: walkUp .25s steps(1) infinite; }
|
.map-player.walk-left { animation: walkLeft .32s steps(3) infinite; }
|
||||||
.map-player.walk-down { animation: walkDown .25s steps(1) infinite; }
|
.map-player.walk-right { animation: walkRight .32s steps(3) infinite; }
|
||||||
.map-player.idle { animation: none; }
|
.map-player.idle { animation: none; background-position-x: 0px; }
|
||||||
|
|
||||||
/* Talk hint that floats above player when near NPC */
|
/* Talk hint that floats above player when near NPC */
|
||||||
.map-talk-hint {
|
.map-talk-hint {
|
||||||
|
|||||||
Reference in New Issue
Block a user