diff --git a/public/assets/cats/idle.png b/public/assets/cats/idle.png new file mode 100644 index 0000000..7ef3049 Binary files /dev/null and b/public/assets/cats/idle.png differ diff --git a/public/assets/cats/walk1.png b/public/assets/cats/walk1.png new file mode 100644 index 0000000..b6bf8b9 Binary files /dev/null and b/public/assets/cats/walk1.png differ diff --git a/public/assets/cats/walk2.png b/public/assets/cats/walk2.png new file mode 100644 index 0000000..9adbec2 Binary files /dev/null and b/public/assets/cats/walk2.png differ diff --git a/public/assets/cats/work.png b/public/assets/cats/work.png new file mode 100644 index 0000000..6cce7b2 Binary files /dev/null and b/public/assets/cats/work.png differ diff --git a/src/components/game/VillageView.tsx b/src/components/game/VillageView.tsx index 62197da..940b387 100644 --- a/src/components/game/VillageView.tsx +++ b/src/components/game/VillageView.tsx @@ -90,6 +90,7 @@ export default function VillageView() { const toolImagesRef = useRef>(new Map()); const waterImgRef = useRef(null); const grassImgRef = useRef(null); + const catFramesRef = useRef>(new Map()); const hitRectsRef = useRef< Array<{ id: string; x: number; y: number; w: number; h: number }> >([]); @@ -119,6 +120,12 @@ export default function VillageView() { const grass = new Image(); grass.src = "/assets/grass.jpg"; grass.onload = () => (grassImgRef.current = grass); + // 고양이 스프라이트 4프레임 + for (const frame of ["idle", "walk1", "walk2", "work"]) { + const catImg = new Image(); + catImg.src = `/assets/cats/${frame}.png`; + catImg.onload = () => catFramesRef.current.set(frame, catImg); + } } let raf = 0; @@ -403,13 +410,31 @@ export default function VillageView() { sprites.push({ y: anim.y, draw: () => { - shadow(anim.x, anim.y + 2, 10); - drawEmoji(cat.emoji, anim.x, anim.y + bob, 30, anim.flip); + shadow(anim.x, anim.y + 2, 11); + const frameName = working + ? "work" + : moving + ? Math.floor(now / 180) % 2 === 0 + ? "walk1" + : "walk2" + : "idle"; + const sprite = catFramesRef.current.get(frameName); + if (sprite) { + const sh = 42; + const sw = (sprite.width / sprite.height) * sh; + ctx.save(); + ctx.translate(anim.x, anim.y + bob); + if (anim.flip) ctx.scale(-1, 1); + ctx.drawImage(sprite, -sw / 2, -sh + 4, sw, sh); + ctx.restore(); + } else { + drawEmoji(cat.emoji, anim.x, anim.y + bob, 30, anim.flip); + } ctx.font = "10px sans-serif"; ctx.textAlign = "center"; ctx.fillStyle = "rgba(55,65,81,0.85)"; - ctx.fillText(cat.name, anim.x, anim.y + 12); - if (working) drawEmoji("💦", anim.x + 12, anim.y - 20 + bob, 10); + ctx.fillText(cat.name, anim.x, anim.y + 14); + if (working) drawEmoji("💦", anim.x + 14, anim.y - 30 + bob, 11); }, }); }