diff --git a/public/assets/grass.jpg b/public/assets/grass.jpg new file mode 100644 index 0000000..380c91b Binary files /dev/null and b/public/assets/grass.jpg differ diff --git a/src/components/game/VillageView.tsx b/src/components/game/VillageView.tsx index a05b1e2..61fef3a 100644 --- a/src/components/game/VillageView.tsx +++ b/src/components/game/VillageView.tsx @@ -89,6 +89,7 @@ export default function VillageView() { const bubblesRef = useRef([]); const toolImagesRef = useRef>(new Map()); const waterImgRef = useRef(null); + const grassImgRef = useRef(null); const hitRectsRef = useRef< Array<{ id: string; x: number; y: number; w: number; h: number }> >([]); @@ -110,11 +111,14 @@ export default function VillageView() { img.src = src; img.onload = () => toolImagesRef.current.set(key as AptitudeKey, img); } - // 강물 텍스처 (로드 전에는 단색 폴백) + // 강물·잔디 텍스처 (로드 전에는 단색 폴백) { const img = new Image(); img.src = "/assets/water.jpg"; img.onload = () => (waterImgRef.current = img); + const grass = new Image(); + grass.src = "/assets/grass.jpg"; + grass.onload = () => (grassImgRef.current = grass); } let raf = 0; @@ -205,16 +209,38 @@ export default function VillageView() { ctx.closePath(); }; - for (let j = 0; j < ROWS; j++) { - for (let i = 0; i < COLS; i++) { - if (isWater(i, j)) continue; - ctx.beginPath(); - tilePath(i, j); - ctx.fillStyle = (i + j) % 2 === 0 ? "#86c66b" : "#7dbd62"; - ctx.fill(); - ctx.strokeStyle = "rgba(255,255,255,0.10)"; - ctx.stroke(); + // 잔디 — 일러스트 텍스처를 잔디 타일 영역에 클리핑해서 채움 + { + ctx.save(); + ctx.beginPath(); + for (let j = 0; j < ROWS; j++) + for (let i = 0; i < COLS; i++) if (!isWater(i, j)) tilePath(i, j); + ctx.clip(); + + const grass = grassImgRef.current; + if (grass) { + const scale = Math.max(CANVAS_W / grass.width, CANVAS_H / grass.height); + ctx.drawImage(grass, 0, 0, grass.width * scale, grass.height * scale); + } else { + ctx.fillStyle = "#82c368"; + ctx.fillRect(0, 0, CANVAS_W, CANVAS_H); } + + // 타일 격자 힌트 (배치 가독성 유지) + for (let j = 0; j < ROWS; j++) { + for (let i = 0; i < COLS; i++) { + if (isWater(i, j)) continue; + ctx.beginPath(); + tilePath(i, j); + if ((i + j) % 2 === 0) { + ctx.fillStyle = "rgba(255,255,255,0.045)"; + ctx.fill(); + } + ctx.strokeStyle = "rgba(255,255,255,0.08)"; + ctx.stroke(); + } + } + ctx.restore(); } // 강물 — 일러스트 텍스처를 물 타일 영역에 클리핑해서 채움