여러분이 사용하고 계신 브라우저는 HTML5를 지원하지 않기 때문에 몇몇 요소가 제대로 보이도록 JScript를 사용하고 있습니다. 하지만 여러분의 브라우저 설정에서 스크립트 기능이 꺼져있으므로, 현재 페이지를 제대로 확인하시려면 스크립트 기능을 켜주셔야 합니다. HTML 게임 - 이동

HTML 게임 – 이동

1개월전 작성

게임 이동

HTML5 Canvas 게임에서 게임 구성 요소를 이동시키는 방법을 배워보자. 이동 기능은 모든 게임의 기본이 되는 핵심 요소로, 플레이어 캐릭터부터 적, 아이템까지 다양한 오브젝트의 움직임을 제어한다.

기본 이동 개념

게임에서 이동을 구현하려면 다음과 같은 요소들이 필요하다.

  • 위치 좌표 (x, y)
  • 이동 속도 (speedX, speedY)
  • 입력 처리 (키보드, 마우스 등)
  • 위치 업데이트 함수

간단한 이동 예제

먼저 빨간색 사각형이 자동으로 이동하는 기본 예제를 만들어보자.

<canvas id="myCanvas1" width="400" height="200" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece;
function startGame() {
myGameArea.start();
myGamePiece = new component(30, 30, "red", 10, 120);
}
var myGameArea = {
canvas : document.getElementById("myCanvas1"),
start : function() {
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea, 20);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.speedX = 1;
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
</script>

이 예제에서는 빨간색 사각형이 오른쪽으로 계속 이동한다. speedX 속성을 1로 설정하여 매 프레임마다 x 좌표가 1픽셀씩 증가한다.

경계 처리가 있는 이동

화면 경계에서 반대편으로 나타나는 랩어라운드 효과를 추가해보자.

<canvas id="myCanvas2" width="400" height="200" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var myGamePiece2;
function startGame2() {
myGameArea2.start();
myGamePiece2 = new component2(30, 30, "red", 10, 120);
}
var myGameArea2 = {
canvas : document.getElementById("myCanvas2"),
start : function() {
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea2, 20);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component2(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea2.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
if (this.x > myGameArea2.canvas.width) {
this.x = -this.width;
}
if (this.x < -this.width) { this.x = myGameArea2.canvas.width; } if (this.y > myGameArea2.canvas.height) {
this.y = -this.height;
}
if (this.y < -this.height) { this.y = myGameArea2.canvas.height; } } } function updateGameArea2() { myGameArea2.clear(); myGamePiece2.speedX = 2; myGamePiece2.speedY = 1; myGamePiece2.newPos(); myGamePiece2.update(); } startGame2(); </script>[/code]

이 예제에서는 사각형이 화면 경계를 벗어나면 반대편에서 다시 나타난다. speedX와 speedY를 모두 설정하여 대각선 방향으로 이동한다.

키보드로 이동 제어하기

이제 키보드 입력으로 게임 오브젝트의 이동을 제어해보자.

[code lang="markup"]<canvas id="myCanvas3" width="400" height="200" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<p>화살표 키를 사용하여 빨간색 사각형을 이동시키세요.</p>
<script>
var myGamePiece3;
function startGame3() {
myGameArea3.start();
myGamePiece3 = new component3(30, 30, "red", 200, 100);
}
var myGameArea3 = {
canvas : document.getElementById("myCanvas3"),
start : function() {
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea3, 20);
window.addEventListener('keydown', function (e) {
myGameArea3.key = e.keyCode;
})
window.addEventListener('keyup', function (e) {
myGameArea3.key = false;
})
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component3(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea3.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function updateGameArea3() {
myGameArea3.clear();
myGamePiece3.speedX = 0;
myGamePiece3.speedY = 0;
if (myGameArea3.key && myGameArea3.key == 37) {myGamePiece3.speedX = -1; }
if (myGameArea3.key && myGameArea3.key == 39) {myGamePiece3.speedX = 1; }
if (myGameArea3.key && myGameArea3.key == 38) {myGamePiece3.speedY = -1; }
if (myGameArea3.key && myGameArea3.key == 40) {myGamePiece3.speedY = 1; }
myGamePiece3.newPos();
myGamePiece3.update();
}
startGame3();
</script>

이 예제에서는 화살표 키로 사각형을 이동시킬 수 있다. keyCode 37(왼쪽), 38(위), 39(오른쪽), 40(아래)을 사용하여 방향을 제어한다.

다중 키 입력 처리

여러 키를 동시에 눌렀을 때도 정상적으로 작동하도록 개선해보자.

<canvas id="myCanvas4" width="400" height="200" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<p>여러 화살표 키를 동시에 눌러서 대각선 이동을 해보세요.</p>
<script>
var myGamePiece4;
function startGame4() {
myGameArea4.start();
myGamePiece4 = new component4(30, 30, "blue", 200, 100);
}
var myGameArea4 = {
canvas : document.getElementById("myCanvas4"),
start : function() {
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea4, 20);
window.addEventListener('keydown', function (e) {
myGameArea4.keys = (myGameArea4.keys || []);
myGameArea4.keys[e.keyCode] = true;
})
window.addEventListener('keyup', function (e) {
myGameArea4.keys[e.keyCode] = false;
})
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component4(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea4.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
if (this.x > myGameArea4.canvas.width - this.width) this.x = myGameArea4.canvas.width - this.width;
if (this.x < 0) this.x = 0; if (this.y > myGameArea4.canvas.height - this.height) this.y = myGameArea4.canvas.height - this.height;
if (this.y < 0) this.y = 0; } } function updateGameArea4() { myGameArea4.clear(); myGamePiece4.speedX = 0; myGamePiece4.speedY = 0; if (myGameArea4.keys && myGameArea4.keys[37]) {myGamePiece4.speedX = -2; } if (myGameArea4.keys && myGameArea4.keys[39]) {myGamePiece4.speedX = 2; } if (myGameArea4.keys && myGameArea4.keys[38]) {myGamePiece4.speedY = -2; } if (myGameArea4.keys && myGameArea4.keys[40]) {myGamePiece4.speedY = 2; } myGamePiece4.newPos(); myGamePiece4.update(); } startGame4(); </script>[/code]

이 예제에서는 keys 배열을 사용하여 여러 키의 상태를 동시에 추적한다. 또한 화면 경계에서 멈추도록 경계 처리를 추가했다.

가속도와 관성이 있는 이동

더 현실적인 물리 효과를 위해 가속도와 관성을 구현해보자.

[code lang="markup"]<canvas id="myCanvas5" width="400" height="200" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<p>화살표 키로 가속도와 관성이 적용된 이동을 경험하세요.</p>
<script>
var myGamePiece5;
function startGame5() {
myGameArea5.start();
myGamePiece5 = new component5(30, 30, "green", 200, 100);
}
var myGameArea5 = {
canvas : document.getElementById("myCanvas5"),
start : function() {
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea5, 20);
window.addEventListener('keydown', function (e) {
myGameArea5.keys = (myGameArea5.keys || []);
myGameArea5.keys[e.keyCode] = true;
})
window.addEventListener('keyup', function (e) {
myGameArea5.keys[e.keyCode] = false;
})
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component5(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.acceleration = 0.2;
this.friction = 0.95;
this.maxSpeed = 5;
this.update = function() {
ctx = myGameArea5.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.speedX *= this.friction;
this.speedY *= this.friction;
this.x += this.speedX;
this.y += this.speedY;
if (this.x > myGameArea5.canvas.width - this.width) {
this.x = myGameArea5.canvas.width - this.width;
this.speedX = 0;
}
if (this.x < 0) { this.x = 0; this.speedX = 0; } if (this.y > myGameArea5.canvas.height - this.height) {
this.y = myGameArea5.canvas.height - this.height;
this.speedY = 0;
}
if (this.y < 0) { this.y = 0; this.speedY = 0; } } } function updateGameArea5() { myGameArea5.clear(); if (myGameArea5.keys && myGameArea5.keys[37]) { myGamePiece5.speedX -= myGamePiece5.acceleration; if (myGamePiece5.speedX < -myGamePiece5.maxSpeed) myGamePiece5.speedX = -myGamePiece5.maxSpeed; } if (myGameArea5.keys && myGameArea5.keys[39]) { myGamePiece5.speedX += myGamePiece5.acceleration; if (myGamePiece5.speedX > myGamePiece5.maxSpeed) myGamePiece5.speedX = myGamePiece5.maxSpeed;
}
if (myGameArea5.keys && myGameArea5.keys[38]) {
myGamePiece5.speedY -= myGamePiece5.acceleration;
if (myGamePiece5.speedY < -myGamePiece5.maxSpeed) myGamePiece5.speedY = -myGamePiece5.maxSpeed; } if (myGameArea5.keys && myGameArea5.keys[40]) { myGamePiece5.speedY += myGamePiece5.acceleration; if (myGamePiece5.speedY > myGamePiece5.maxSpeed) myGamePiece5.speedY = myGamePiece5.maxSpeed;
}
myGamePiece5.newPos();
myGamePiece5.update();
}
startGame5();
</script>

이 예제에서는 다음과 같은 물리 효과를 구현했다.

  • 가속도 (acceleration): 키를 누르면 점진적으로 속도가 증가한다
  • 마찰력 (friction): 키를 놓으면 점진적으로 감속한다
  • 최대 속도 (maxSpeed): 속도에 제한을 둔다
  • 경계에서 정지: 벽에 부딪히면 해당 방향의 속도가 0이 된다

마우스를 따라가는 이동

마우스 커서를 따라 이동하는 오브젝트를 만들어보자.

<canvas id="myCanvas6" width="400" height="200" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<p>마우스를 캔버스 위에서 움직여보세요. 보라색 사각형이 따라옵니다.</p>
<script>
var myGamePiece6;
function startGame6() {
myGameArea6.start();
myGamePiece6 = new component6(20, 20, "purple", 200, 100);
}
var myGameArea6 = {
canvas : document.getElementById("myCanvas6"),
start : function() {
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea6, 20);
this.canvas.addEventListener('mousemove', function (e) {
var rect = myGameArea6.canvas.getBoundingClientRect();
myGameArea6.mouseX = e.clientX - rect.left;
myGameArea6.mouseY = e.clientY - rect.top;
})
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component6(width, height, color, x, y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speed = 2;
this.update = function() {
ctx = myGameArea6.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.moveTowards = function(targetX, targetY) {
var dx = targetX - (this.x + this.width / 2);
var dy = targetY - (this.y + this.height / 2);
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > this.speed) {
this.x += (dx / distance) * this.speed;
this.y += (dy / distance) * this.speed;
} else {
this.x = targetX - this.width / 2;
this.y = targetY - this.height / 2;
}
}
}
function updateGameArea6() {
myGameArea6.clear();
if (myGameArea6.mouseX !== undefined && myGameArea6.mouseY !== undefined) {
myGamePiece6.moveTowards(myGameArea6.mouseX, myGameArea6.mouseY);
}
myGamePiece6.update();
}
startGame6();
</script>

이 예제에서는 마우스 위치를 추적하고, 오브젝트가 마우스 커서를 향해 일정한 속도로 이동한다. 벡터 정규화를 사용하여 거리에 관계없이 일정한 속도를 유지한다.

패턴 이동

미리 정의된 패턴에 따라 이동하는 오브젝트를 만들어보자.

<canvas id="myCanvas7" width="400" height="200" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<p>원형 패턴으로 이동하는 오브젝트를 관찰하세요.</p>
<script>
var myGamePiece7;
function startGame7() {
myGameArea7.start();
myGamePiece7 = new component7(20, 20, "orange", 200, 100);
}
var myGameArea7 = {
canvas : document.getElementById("myCanvas7"),
start : function() {
this.context = this.canvas.getContext("2d");
this.interval = setInterval(updateGameArea7, 20);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component7(width, height, color, x, y) {
this.width = width;
this.height = height;
this.centerX = x;
this.centerY = y;
this.x = x;
this.y = y;
this.angle = 0;
this.radius = 50;
this.speed = 0.05;
this.update = function() {
ctx = myGameArea7.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.strokeStyle = "rgba(255, 165, 0, 0.3)";
ctx.beginPath();
ctx.arc(this.centerX, this.centerY, this.radius, 0, 2 * Math.PI);
ctx.stroke();
}
this.move = function() {
this.angle += this.speed;
this.x = this.centerX + Math.cos(this.angle) * this.radius - this.width / 2;
this.y = this.centerY + Math.sin(this.angle) * this.radius - this.height / 2;
}
}
function updateGameArea7() {
myGameArea7.clear();
myGamePiece7.move();
myGamePiece7.update();
}
startGame7();
</script>

이 예제에서는 삼각함수를 사용하여 원형 패턴으로 이동하는 오브젝트를 만들었다. 궤도를 시각적으로 표시하여 이동 패턴을 명확히 보여준다.

💡 게임 이동 구현 팁:
• 프레임 레이트에 독립적인 이동을 위해 deltaTime을 사용하는 것이 좋다
• 대각선 이동 시 속도가 증가하지 않도록 벡터를 정규화하자
• 경계 처리는 게임의 특성에 맞게 선택하자 (정지, 반사, 랩어라운드 등)
• 부드러운 이동을 위해 선형 보간(lerp)이나 이징 함수를 활용할 수 있다

게임에서 이동 시스템은 플레이어의 조작감과 게임성에 직접적인 영향을 준다. 이러한 기본적인 이동 원리를 이해하고 게임의 특성에 맞게 응용하면 다양한 장르의 게임에서 활용할 수 있는 이동 시스템을 구축할 수 있다.

참고
Mingg`s Diary
밍구
공부 목적 블로그