모바일/HTML5

[HTML5 Game] Moving Object Ⅱ

박종명 2013. 10. 2. 21:30
728x90

이전 글(http://m.mkexdev.net/246)에서 키보드에 반응해 게임 오브젝트가 이동하는 예를 살펴 보았다.

당시 제기했던 문제점을 해결해서 완성도를 높여 보자.

 

이전 글에서 제기한 문제점을 다시 가져와 본다.

브라우저로 결과를 확인해 봤다면 뭔가 완전하지 않다는 것을 느꼈을 것이다. 전투기가 방향키에 반응해 원하는 곳으로 이동 하는 것은 분명하지만 완성도 있는 게임으로써는 뭔가 부족하다.

 

먼저 제일 문제가 되는 것은 '동시 키 입력'이 되지 않는다는 것이다.

예를 들어 대각선 방향으로 이동하기 위해 '→, ↑' 두 키를 동시 누르고 있더라도 뒤에 눌러진 키에만 반응하여 한쪽 방향으로만 이동하게 된다. 이것은 PC에서 Sift, Alt 키와 같은 보조키를 제외하고는 동시키 입력을 지원하지 않기 때문에 발생하는 현상이다. 따라서 이에 대한 처리를 별도로 해 줘야 한다.

 

두 번째 문제는, 전투기 이동의 시작이 매끄럽지 못하다는 것이다. 전투기를 끊김 없이 이동 시키기위해 키를 떼지 않고 계속 누르고 있을 경우 처음 이동이 끊기는 현상을 볼 수 있다. 이것은 키 입력이 지속될 때 발생하는 최초 지연 현상 때문인데 실제로 키 입력의 초당 실행수를 측정해 보면 최초 시작시점에 1~5사의 값이 나오고 이후부터는 최대 30정도로 유지되는 것을 확인할 수 있었다.

 

 

두 가지 문제의 해결책은 바로 게임 루프이다.

키보드의 키 입력 이벤트가 발생할 때 UI를 갱신하는 것이 아니라 게임 루프 상에서 빠르고도 지속적으로 UI를 갱신하도록 하며 키 이벤트는 키 입력 상태 값을 업데이트 해 주는 용도로만 그치게 하는 것이 핵심이다.

이렇게 하면 동시 키 입력이나 초기 지연 현상을 극복할 수 있게 되는 것이다.

 

 

 

 

 

Character 객체는 이전 코드와 동일하다.

function Character(asset, x, y, canvasElement){ 
  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);

 

브라우저로 결과를 확인해 보면 이전 샘플에서 발생했던 동시키 입력 문제나 초반 지연 현상이 개선된 것을 확인할 수 있다.