뷰포트(Viewport) 구현의 핵심: drawImage() 메서드
HTML5 Canvas에서 카메라 또는 뷰포트 효과를 구현하려면 drawImage() 메서드를 활용하는 것이 가장 효율적입니다. 이 메서드는 원본 이미지의 특정 영역(크롭 영역)을 잘라내어 캔버스의 원하는 위치와 크기로 그릴 수 있게 해주기 때문에, 넓은 게임 월드 중 플레이어가 보고 있는 부분만 화면에 렌더링하는 카메라 기능을 손쉽게 만들 수 있습니다.
먼저 이전 프레임의 잔상을 제거하기 위해 clearRect()로 캔버스 전체를 지운 뒤, 배경 이미지를 크롭하여 그리는 기본 패턴은 다음과 같습니다.
ctx.clearRect(0, 0, game.width, game.height); // 배경 이미지 전체 중 필요한 영역만 잘라내어 그리기 ctx.drawImage( background, // 원본 이미지 cropLeft, cropTop, // 잘라낼 시작 좌표 (소스 X, Y) cropWidth, cropHeight, // 잘라낼 영역의 크기 (소스 W, H) 0, 0, // 캔버스에 그릴 위치 (목적지 X, Y) viewWidth, viewHeight // 캔버스에 그려질 크기 (목적지 W, H) );
drawImage() 파라미터 이해하기
뷰포트 구현의 핵심은 drawImage()의 아홉 개 인자를 정확히 이해하는 것입니다.
- 원본 이미지: 배경이나 게임 맵 이미지
- 소스 좌표(cropLeft, cropTop): 카메라가 바라보는 월드 상의 위치
- 소스 크기(cropWidth, cropHeight): 화면에 보여줄 영역의 크기
- 목적지 좌표 및 크기: 캔버스 어디에, 어떤 크기로 그릴지 결정
카메라를 이동시키고 싶다면 cropLeft와 cropTop 값을 변경하면 되며, 이 값이 곧 카메라의 위치 역할을 하게 됩니다.
실제 게임에 적용한 예제 코드
아래는 실제 게임 캔버스에 위 개념을 적용한 예제입니다. 배경 이미지를 뷰포트 크기에 맞게 그린 후, 원형 오브젝트를 추가로 렌더링합니다.
var myGame = document.getElementById("game");
var myCtx = myGame.getContext("2d");
// 매 프레임 캔버스 초기화
myCtx.clearRect(0, 0, game.width, game.height);
// drawImage() 메서드로 배경의 특정 영역을 뷰포트에 렌더링
myCtx.drawImage(background, left, top, 350, 250, 0, 0, 250, 150);
// 원형 오브젝트 그리기
myCtx.beginPath();
myCtx.arc(130, 80, 12, 0, Math.PI * 2, false);
myCtx.closePath();
myCtx.fill();
myCtx.stroke();코드 동작 방식 살펴보기
- 캔버스 요소 가져오기:
getElementById()로 게임 캔버스를 선택하고getContext("2d")로 2D 드로잉 컨텍스트를 얻습니다. - 화면 클리어:
clearRect()로 이전 프레임을 지워 잔상을 방지합니다. - 배경 렌더링:
drawImage()를 통해 소스 이미지의 (left, top) 위치에서 350×250 크기의 영역을 잘라내어, 캔버스의 (0, 0) 위치에 250×150 크기로 축소하여 그립니다. - 오브젝트 렌더링:
arc()로 반지름 12px의 원을 그리고fill()과stroke()로 채우기와 외곽선을 적용합니다.
마무리
이처럼 drawImage() 메서드의 소스 크롭 기능을 활용하면 별도의 복잡한 변환 행렬 없이도 간단하게 카메라·뷰포트 시스템을 구축할 수 있습니다. 여기에 플레이어 좌표에 따라 크롭 좌표를 갱신하고, 캔버스 경계를 벗어나지 않도록 최솟값·최댓값으로 좌표를 제한(clamping)하면 더욱 완성도 높은 스크롤링 카메라를 만들 수 있습니다.