러너 게임(달리기 게임)은 플레이어가 자동으로 전진하면서 장애물을 회피하고, 점수를 획득하는 게임 유형이다. 간단한 러너 게임은 캔버스 없이 JavaScript, HTML, CSS 만으로도 구현할 수 있다. 러너 게임 구현은 크게 ①이동(전진), ②점프, ③장애물 배치, ④장애물 충돌 감지로 나눌 수 있다. 슈퍼 마리오는 플레이어가 캐릭터를 직접 조종하는 플랫포머 장르에 속하지만 친숙한 마리오 캐릭터와 구조물을 이용해서 러너 게임으로 만들어보자.
class DomManager {
static instance = null;
constructor() {
if (DomManager.instance) return DomManager.instance;
this.gameArea = document.querySelector('.game');
this.dialog = document.querySelector('.dialog-failed');
// ...
DomManager.instance = this;
}
static getInstance() {
if (!DomManager.instance) DomManager.instance = new DomManager();
return DomManager.instance;
}
}
export default DomManager.getInstance();
게임 영역, 스코어, 시작 버튼 등 게임에서 자주 사용하는 요소들은 DomManager
라는 클래스에서 관리한다. 이렇게 DOM 관련 작업을 한 곳에 중앙화하면 반복적인 쿼리와 조작을 피할 수 있다.
클래스의 인스턴스를 오직 하나만 생성하여 어플리케이션 전체에 공유하는 방식을 싱글톤 패턴이라고 부른다. 돔 매니저를 싱글톤으로 내보내면 프로젝트 어디서든 동일한 인스턴스에 접근하기 때문에 일관성을 높일 수 있다.
getInstance()
정적 메서드를 처음 호출하면 생성한 인스턴스가 없기 때문에 constructor
를 실행해서 새로운 인스턴스를 만들고, DomManager.instance
정적 프로퍼티에 할당한다. 그 후 getInstance()
를 다시 호출하면 DomManager.instance
프로퍼티에 할당했던 기존 인스턴스를 반환한다.
<aside> <img src="/icons/search_gray.svg" alt="/icons/search_gray.svg" width="40px" /> 생성자(constructor) 함수는 기본적으로 새로 생성된 인스턴스(this)를 반환하지만 위처럼 명시적으로 반환 값을 지정할 수도 있다.
</aside>
게임내 구조물들이 게임 화면을 기준으로 움직일 수 있도록, 게임 화면 요소의 position
값은 relative
로 설정하고, 마리오나 장애물 등은 absolute
로 설정한다.
.game {
width: 100%;
min-height: 440px;
overflow: hidden;
position: relative;
background-image: url('./assets/background.png');
background-size: 600px 500px;
background-position: center;
}
background-position-x
는 배경 이미지의 수평 위치를 조절할 때 사용하는 스타일 속성이다. 이 속성을 이용해 배경 이미지의 수평 위치를 주기적으로 왼쪽으로 이동 시키면 앞으로 전진하는 듯한 효과를 구현할 수 있다. 이 속성의 기본값은 왼쪽 가장 자리를 나타내는 0%
다.