강물 텍스처 교체: 수면 전용 이미지 + 한 방향 흐름
- 순수 수면 텍스처로 교체 (900px JPEG, 137KB) - 컨텍스트를 강 방향으로 회전 후 미러 타일링 스크롤 → 이음매 없는 단방향 흐름 - 상류(북동) → 하류(남서) 22px/초 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
이 커밋은 다음에 포함됨:
@@ -253,25 +253,33 @@ export default function VillageView() {
|
||||
|
||||
const water = waterImgRef.current;
|
||||
if (water) {
|
||||
// 물 영역 바운딩 박스를 덮도록 cover 배치 + 흐르는 방향으로 느린 드리프트
|
||||
const left = isoX(COLS - 1, ROWS - 1) - TW / 2;
|
||||
const right = isoX(COLS - 1, 0) + TW / 2;
|
||||
const top = isoY(COLS - 1, 0);
|
||||
const bottom = isoY(COLS - 1, ROWS - 1) + TH;
|
||||
const boxW = right - left;
|
||||
const boxH = bottom - top;
|
||||
const scale = Math.max(boxW / water.width, boxH / water.height) * 1.15;
|
||||
const w = water.width * scale;
|
||||
const h = water.height * scale;
|
||||
// 강 줄기 방향(좌하향)으로 왕복 드리프트
|
||||
const drift = Math.sin(now / 4000) * 14;
|
||||
ctx.drawImage(
|
||||
water,
|
||||
left + (boxW - w) / 2 - drift,
|
||||
top + (boxH - h) / 2 + drift / 2,
|
||||
w,
|
||||
h,
|
||||
);
|
||||
// 강 줄기 방향(상류→하류, 좌하향)으로 한 방향 흐름:
|
||||
// 컨텍스트를 강 방향으로 회전시킨 뒤 텍스처를 미러 타일링하며 스크롤
|
||||
const sx = isoX(COLS - 1, 0);
|
||||
const sy = isoY(COLS - 1, 0) + TH / 2;
|
||||
const ex = isoX(COLS - 1, ROWS - 1);
|
||||
const ey = isoY(COLS - 1, ROWS - 1) + TH / 2;
|
||||
const angle = Math.atan2(ey - sy, ex - sx);
|
||||
const riverLen = Math.hypot(ex - sx, ey - sy);
|
||||
|
||||
const h = 220; // 강 폭 방향 커버 (클리핑되므로 넉넉히)
|
||||
const w = (water.width / water.height) * h;
|
||||
const FLOW_SPEED = 22; // px/초
|
||||
const offset = ((now / 1000) * FLOW_SPEED) % (2 * w);
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(sx, sy);
|
||||
ctx.rotate(angle);
|
||||
const copies = Math.ceil((riverLen + TW * 3) / w) + 2;
|
||||
for (let k = -2; k < copies; k++) {
|
||||
const xk = k * w - offset;
|
||||
ctx.save();
|
||||
ctx.translate(xk + w / 2, 0);
|
||||
if (((k % 2) + 2) % 2 === 1) ctx.scale(-1, 1); // 미러 타일링으로 이음매 제거
|
||||
ctx.drawImage(water, -w / 2, -h / 2, w, h);
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.restore();
|
||||
} else {
|
||||
ctx.fillStyle = "#60a5fa";
|
||||
ctx.fillRect(0, 0, CANVAS_W, CANVAS_H);
|
||||
|
||||
새 이슈에서 참조
사용자 차단