[HTML5 Game] Moving Object Ⅱ
이전 글(http://m.mkexdev.net/246)에서 키보드에 반응해 게임 오브젝트가 이동하는 예를 살펴 보았다.
당시 제기했던 문제점을 해결해서 완성도를 높여 보자.
이전 글에서 제기한 문제점을 다시 가져와 본다.
먼저 제일 문제가 되는 것은 '동시 키 입력'이 되지 않는다는 것이다.
예를 들어 대각선 방향으로 이동하기 위해 '→, ↑' 두 키를 동시 누르고 있더라도 뒤에 눌러진 키에만 반응하여 한쪽 방향으로만 이동하게 된다. 이것은 PC에서 Sift, Alt 키와 같은 보조키를 제외하고는 동시키 입력을 지원하지 않기 때문에 발생하는 현상이다. 따라서 이에 대한 처리를 별도로 해 줘야 한다.
두 번째 문제는, 전투기 이동의 시작이 매끄럽지 못하다는 것이다. 전투기를 끊김 없이 이동 시키기위해 키를 떼지 않고 계속 누르고 있을 경우 처음 이동이 끊기는 현상을 볼 수 있다. 이것은 키 입력이 지속될 때 발생하는 최초 지연 현상 때문인데 실제로 키 입력의 초당 실행수를 측정해 보면 최초 시작시점에 1~5사의 값이 나오고 이후부터는 최대 30정도로 유지되는 것을 확인할 수 있었다.
두 가지 문제의 해결책은 바로 게임 루프이다.
키보드의 키 입력 이벤트가 발생할 때 UI를 갱신하는 것이 아니라 게임 루프 상에서 빠르고도 지속적으로 UI를 갱신하도록 하며 키 이벤트는 키 입력 상태 값을 업데이트 해 주는 용도로만 그치게 하는 것이 핵심이다.
이렇게 하면 동시 키 입력이나 초기 지연 현상을 극복할 수 있게 되는 것이다.
Character 객체는 이전 코드와 동일하다.
this.canvasSize = {width: canvasElement.width, height: canvasElement.height};
this.canvasContext = canvasElement.getContext('2d');
this.asset = asset;
this.position = {x: x, y: y}
this.drawCharacter = function(){
this.canvasContext.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
this.canvasContext.drawImage(asset, this.position.x, this.position.y);
}
}
이어지는 코드는 이전 코드이 문제점을 개선한 것인데, 먼저 UI를 갱신시키는 부분을 키 이벤트가 아닌 게임 루프에서 처리하는 것을 주의깊게 보자. 키 이벤트에서는 isKeyDown이라는 배열에 키 입력 여부를 삽입하고 게임루프에서 이 값을 기반으로 오브젝트 이동을 처리한다. 키 입력을 해제하기 위해 keyup 이벤트도 사용하고 있다.
var fps = 30;
var canvasElement;
var gameContext;
var character;
var asset;
var speed = 10;
var isKeyDown = [];
function init(){
canvasElement = document.getElementById('GameCanvas');
gameContext = canvasElement.getContext('2d');
asset = new Image();
asset.src = 'image/fighter.png';
asset.onload = onAssetLoadComplete;
}
function onAssetLoadComplete(){
character = new Character(asset, 200, 200, canvasElement);
character.drawCharacter();
setInterval(gameLoop, 1000/fps);
}
function gameLoop(){
if(isKeyDown[37]){
character.position.x -= speed;
}
if(isKeyDown[38]){
character.position.y -= speed;
}
if(isKeyDown[39]){
character.position.x += speed;
}
if(isKeyDown[40]){
character.position.y += speed;
}
character.drawCharacter();
}
function onKeyDown(e){
isKeyDown[e.keyCode] = true;
}
function onKeyUp(e){
isKeyDown[e.keyCode] = false;
}
window.addEventListener("load", init, false);
window.addEventListener("keydown",onKeyDown,false);
window.addEventListener("keyup",onKeyUp,false);
브라우저로 결과를 확인해 보면 이전 샘플에서 발생했던 동시키 입력 문제나 초반 지연 현상이 개선된 것을 확인할 수 있다.