개요
Phaser.js는 웹 기반의 비디오 게임을 만들 수 있는 JavaScript 게임 프레임워크입니다. Phaser를 이용하면 프레임워크에서 제공하는 게임 제작에 필요한 유용한 도구들을 활용할 수 있으므로 우리가 모든 것을 처음부터 만들 필요가 없습니다. 이번 포스트에서는 Phaser가 제공하는 기본 기능을 살펴보겠습니다.
- 기본 Phaser 프로젝트 설정
- 도형 그리기
- 사운드 및 음악 재생하기
- 입력장치와 상호작용
이를 활용하면 다음과 같은 퍼즐 게임을 간단히 만들 수 있습니다. (링크)
※ 참고 : 학습한 결과를 바탕으로 제작한 것으로 완벽한(완성된) 게임의 형태를 띠고 있지는 못합니다.
기본 Phaser 프로젝트 설정
Phaser의 기능을 확인하는데 목적이 있으므로 개발환경 구축을 최소화하기 위해 다음 StackBlitz 링크에 접속하여 index.html
를 수정하여 Phaser 모듈을 불러옵니다.
<script src="//cdn.jsdelivr.net/npm/phaser@3.22.0/dist/phaser.min.js"></script>
기존에 작성되어 있던 index.js
파일의 내용은 모두 삭제합니다.
// Write Javascript code!
이후의 아래의 기술된 내용을 // Write Javascript code!
주석의 아래에 추가합니다.
게임 생성
Phaser 게임은 new Phaser.Game()
를 호출하여 생성할 수 있습니다. Phaser.Game()
함수는 새로운 <canvas>
요소를 생성하여 HTML 문서에 삽입하는데, Phaser가 스프라이트, 배경 이미지 등 게임의 구성요소를 여기에 그리면 우리가 볼 수 있습니다.
Phaser.Game()
은 게임과 관련된 정보를 파라미터로 입력받습니다.
일반적으로 해당 정보는 편의를 위해 별도의 변수에 저장하여 사용합니다. 여기서는 변수의 이름을 config
라 하겠습니다.
앞서 보았던 index.js
파일을 다음과 같이 수정합니다.
// Write Javascript code!
const config = {
type: Phaser.AUTO,
width: 300,
height: 600,
backgroundColor: "#18216D",
};
let game = new Phaser.Game(config);
군청색 배경의 300x600 픽셀의 Phaser 게임이 생성되었습니다.
해당 변수에는 다음 항목의 값을 저장할 수 있습니다.
height
,width
: Phaser가 생성하는<canvas>
의 높이와 너비입니다. 단위는 픽셀입니다.parent
: Phaser 가<canvas>
를 내부에 추가할 HTML 요소backgroundColor
: 게임의 배경 색상으로 일반적으로 헥사 데시멀로 입력합니다.type
: Phaser에서 사용할 렌더링 방식입니다. 선택할 수 있는 값은 추가적인 기능을 제공하는Phaser.WEBGL
이나 좀 더 여러 브라우저에서 지원하는Phaser.CANVAS
입니다. 기본값은Phaser.AUTO
입니다. 브라우저에서 WebGL을 지원할 경우 WebGL로 그렇지 않은 경우 canvas로 Phaser가 자동으로 설정합니다.
이 외에도 다양한 항목을 설정할 수 있습니다. 상세한 내용은 Phaser documentation를 참고합니다.
장면(Scene) 구성
앞서 만든 Phaser 게임은 군청색 (#18216D
) 배경을 화면에 출력하는 것 외에는 어떠한 동작도 하지 않습니다. 이제부터 게임을 동작시키기 위해 게임 로직을 추가하겠습니다. 게임 로직은 화면에 캐릭터를 움직이고, 효과음을 내는 등 게임이 동작하기 위해 수행해야 하는 모든 내부 메커니즘을 의미합니다.
Phaser의 경우 게임 로직은 장면(Scene) Class에 추가합니다. 장면은 게임을 구성하는 하나의 단위입니다. 일반적으로 이들 장면이 여러 개 모여 하나의 게임을 구성합니다.
장면(Scene)에는 필요에 따라 다음 세 가지 함수가 포함됩니다.
preload()
: 외부 파일(혹은 "애셋")을 게임상에 불러와야 하는 경우에 포함합니다.create()
: 게임 시작 시 필요한 GameObject를 정의해야 하는 경우에 포함합니다.update()
: 애니메이션을 정의하거나 게임상에서 상호작용을 해야 하는 경우에 포함합니다.
예를 들어 외부 에셋(Asset)을 사용하지 않는 장면에는 preload()
함수를 정의할 필요가 없습니다.
이들 함수가 정의되면 객체로 Phaser 설정(config)에 넘겨줍니다. 이에 대한 예시는 아래와 같습니다.
preload()
와 create()
함수를 추가한 장면을 설정으로 제공하였습니다.
function preload() {
// StackBlitz는 정적 파일을 지원하지 않기 때문에 외부에서 파일을 읽어오도록 합니다.
this.load.setBaseURL("https://cdn.jsdelivr.net/gh/kefik/kenney/Shooter/");
this.load.image("playership1", "playerShip1_blue.png");
}
function create() {
this.add.sprite(130, 130, 'playership1');
}
const config = {
type: Phaser.AUTO,
width: 300,
height: 600,
backgroundColor: "#18216D",
scene: {
preload: preload,
create: create,
}
};
let game = new Phaser.Game(config);
참고
간단한 게임은 하나의 장면으로 충분하겠지만 일반적으로 게임은 그 화면의 역할에 따라 여러 장면을 추가하게 됩니다. 이에 대한 예시는 추후에 살펴보도록 하겠습니다.
const TitleScene = {
key: "GameScene",
create: createTitle,
}
const GameSene = {
key: "GameScene",
create: createGame,
update: updateGame,
}
const config = {
type : auto,
width : 300,
height: 600,
scene: [ TitleScene , GameSene ]
}
Hello Phaser (텍스트 추가)
생성한 장면(Scene)에 필요한 객체를 추가합니다.
게임은 많은 정보를 화면에 표시합니다. 아이콘을 사용하여 정보를 표시하기도 하지만 가장 중요한 정보 제공법은 텍스트를 이용하는 것입니다.
텍스트를 추가하기 위해서는 this.add.text()
메서드를 사용합니다. 앞서 살펴본 것처럼 GameObject는 create()
함수에 추가합니다.
let notice;
function create() {
notice = this.add.text(150, 300, "Press Any Key to Start");
}
const config = {
type: Phaser.AUTO,
width: 300,
height: 600,
backgroundColor: "#18216D",
scene: {
create: create,
}
};
let game = new Phaser.Game(config);
this.add.text()
매서드에 사용된 인자는 다음과 같습니다.
x
는 추가한 도형(텍스트)의 중심의 가로방향 위치입니다.y
는 생성한 도형(텍스트)의 중심의 세로 방향 위치입니다.text
는 화면에 표시할 문자입니다.
따라서 이 코드는 원점(좌측, 위)에서 오른쪽, 아래로 각각 150, 300 픽셀 떨어진 위치에 "Press Any Key to Start"라는 텍스트를 출력합니다.
도형(사각형) 그리기
Phaser는 사각형, 원과 같은 여러 도형을 직접 생성할 수 있는 기능을 제공합니다. 간단한 도형은 이를 이용하여 별도의 외부 객체를 불러오지 않고 게임에 삽입할 수 있습니다. 이번에는 사각형을 추가하도록 하겠습니다. 사각형을 그리기 위해 this.add.rectangle()
매서드를 사용합니다. 이 메서드는 Phaser에서 사각형을 표현하는 GameObject
를 생성합니다.
this.add.rectangle()
매서드는 몇 가지 인자를 사용합니다. 아래의 값은 모두 옵션 값으로 필요에 따라 사용하지 않을 수도 있습니다.
x
는 생성한 도형(사각형)의 중점의 가로방향 위치입니다.x
값이 커진다는 것은 사각형의 중심이 오른쪽으로 이동한다는 뜻입니다.y
는 생성한 도형의 중점의 세로 방향 위치입니다.y
값이 커진다는 것은 사각형의 중심이 아래로 이동한다는 의미입니다.width
는 너비로 사각형의 좌우 길이를 지정하는 데 사용하며, 기본 단위는 픽셀입니다height
는 높이로 사각형의 상하 길이를 지정하는 데 사용하며, 기본 단위는 픽셀입니다.fillColor
항목은 사각형의 색상을 나타냅니다. 값은 16진수(hexdecimal) 표기법으로 지정합니다. 예를 들면,0xFF8030
와 같은 값을 사용할 수 있습니다.fillAlpha
항목은fillColor
로 지정한 색상의 투명도를 의미합니다.
예를 들면 앞서 살펴본 create()
함수에 다음 코드를 사용하여 사각형을 생성할 수 있습니다.
let square;
let notice;
function create() {
notice = this.add.text(150, 300, "Press Any Key to Start");
// (10 10)을 중심 좌표로 하는 각 변의 길이가 10인 빨간색 사각형을 생성합니다.
// 다시말해, (5,5), (5,15), (15,5), (15,15) 에 사각형의 꼭지점이 위치하게 됩니다.
square = this.add.rectangle(10, 10, 10, 10, 0xff0000);
}
const config = {
type: Phaser.AUTO,
width: 300,
height: 600,
backgroundColor: "#18216D",
scene: {
create: create,
}
};
let game = new Phaser.Game(config);
이 코드는 원점(좌측, 위)에서 오른쪽, 아래로 각각 5픽셀 떨어진 위치에 크기가 10이며 빨간 사각형을 생성합니다. (이전에 추가한 Text도 화면에 그대로 표시되어 있습니다.)
참고 - 좌표계
Phaser의 좌표계의 원점 (0,0)은 화면의 좌측, 상단입니다. x축은 오른쪽이 y축은 아래쪽이 양의 값입니다.
반면 사각형과 같은 게임상의 객체(GameObject)는 기본적으로 그들의 원점을 자신의 중앙에 둡니다. 따라서 앞서 살펴본 코드들에서 객체들의 위치를 지정하기 위해 사용한 (x, y) 의 값들은 Phaser 에게 객체의 중앙을 x, y 좌표에 위치하도록 하는 것입니다. (위 결과 그림에서 비교할 수 있듯이 텍스트의 경우는 자신의 원점을 좌측, 상단으로 취하고 있습니다.)
Phaser의 이전버전 (Phaser 2 혹은 Phaser CE)은 좌표계의 원점과 마찬가지로 게임객체의 원점 역시 좌측 상단이었으나 현재 살펴보는 Phaser (Phaser 3) 의 경우는 이와 같이 동작합니다.
참고로 이전버전과 같이 해당객체의 중앙이 아닌 좌측, 상단을 기준으로 위치를 정의하고 싶을 수 있습니다. 이 경우는 setOrigin()
매서드를 사용합니다.
let square;
function create() {
square = this.add.rectangle(0, 0, 0, 10, 0xff0000);
square.setOrigin(0, 0);
}
도형(사각형) 속성 변경하기
update()
함수를 장면에 추가하여 화면을 갱신하겠습니다. 앞서 생성한 사각형이 화면을 가로질러 이동하도록 할 것 입니다.
(10,10) 위치에 생성한 사각형의 위치 값을 update()
함수에서 갱신합니다.
let square;
let notice;
function create() {
notice = this.add.text(150, 300, "Press Any Key to Start");
// (10,10)을 중심 좌표로 하는 각 변의 길이가 10인 사각형을 생성합니다.
// 다시말해, (5,5), (5,15), (15,5), (15,15) 에 사각형의 꼭지점이 위치하게 됩니다.
square = this.add.rectangle(10,10,10,10,0xff0000);
}
function update() {
// 사각형이 오른쪽으로 이동합니다.
square.x += 1;
}
const config = {
type: Phaser.AUTO,
width: 300,
height: 600,
backgroundColor: "#18216D",
scene: {
create: create,
update: update, // update 함수를 장면에 추가합니다.
}
};
let game = new Phaser.Game(config);
생성한 사각형의 속성값을 update()
함수에서 수정할 수 있도록 전역변수 square 를 정의하고, 여기에 생성한 사각형을 저장합니다.
update()
함수에서 매 프레임마다 사각형의 x 좌표를 갱신하도록 코드를 추가합니다.
※ 예시에서 사용하지는 않았지만 사실 update()
함수는 두 가지 인자값을 파라메터를 옵션으로 받습니다. 첫번째 값은 time
으로 게임이 실행 시간을 밀리초 단위로 표시한 값입니다. 두번째 값은 마지막으로 update()
가 호출된 후 경과한 시간을 역시 밀리초 단위로 표시한 것입니다. Phaser 는 1초에 60회 update()
함수를 호출하기 위해 최선을 다하며, 따라서 두번째 파라메터인 delta
는 일반적으로 16.6 근방입니다. 이 값은 특별 경우가 아니라면 사용하는데 문제가 없으므로 대개 문제가 없으므로 update()
는 예시와 같이 별도의 파라메터 없이 호출하여 사용합니다.
상태저장하기
앞서 사각형을 움직이는 예시는 우리가 create()
에서 사각형을 생성하고 update()
함수에서 속성값을 갱신하였습니다. 이러한 객체들이 늘어날수록 장면에 정의된 함수들 사이에서 객체에 대한 정보를 교환하는 것이 중요해질 것입니다. 이를 위해서는 다음 방법을 사용할 수 있습니다.
- 모든것을 전역변수로 생성합니다.
- 장면(Scene) 객체인
this
에 새로운 속성으로 생성하여 저장합니다. - 별도의
gameState
객체를 생성하고 여기에 상태값을 저장합니다.
앞선 사각형 예시의 경우 전역변수(square
)를 통해 정보를 교환하는 방법을 사용했습니다. 이번에는게임의 상태를 저장할 객체를 생성하고 이를 사용도록 하겠습니다.
const gameState = {};
function create() {
gameState.notice = this.add.text(150, 300, "Press Any Key to Start");
gameState.square = this.add.rectangle(140, 160, 100, 100, 0xff00ff00);
}
function update() {
gameState.square.y += 1;
}
const config = {
type: Phaser.AUTO,
width: 300,
height: 600,
backgroundColor: "#18216D",
scene: {
create: create,
update: update, // update 함수를 장면에 추가합니다.
}
};
let game = new Phaser.Game(config);
새로운 JavaScript 객체로 gameState
를 정의했습니다. create()
에서 생성한 사각형을 gameState
의 새로운 속성으로 추가하였습니다. 이제 update()
에서 gameState
로 사각형의 속성을 변경할 수 있습니다.
마우스 입력
Phaser는 마우스 및 키보드 입력 처리 기능을 제공합니다. 입력의 처리는 게임상에서 발생한 이벤트를 시작점으로 하여 이에 대해 게임상에 존재하는 캐릭터, 사물 등의 객체(GameObject)가 반응하도록 연결합니다.
이벤트에 대해 게임의 객체가 반응하도록 하려면, 해당 객체에서 setInteractive()
를 호출하고, event handler를 제공합니다. event handler는 게임상의 객체(GameObject)에서 특정 작용이 발생하면 호출되는 함수입니다. 이번 포스트에서는 4가지 종류의 이벤트를 살펴보겠습니다.
'pointerdown'
: 마우스 버튼이 GameObject 상에서 눌러졌을 때 호출됩니다.'pointerup'
: 마우스 버튼이 GameObject 상에서 눌러졌다가 떼어졌을 때 호출됩니다.'pointerover'
: 마우스 포인트가 GameObject 위로 이동하였을 때 호출됩니다.'pointerout'
: 마우스 포인트가 GameObject 위에서 다른곳으로 이동하였을 때 호출됩니다.
여기서 주의깊게 볼 것은 'pointerdown'
과 'pointerup'
이 별도로 분리된 이벤트라는 것입니다. 얼핏 생각하면 Click은 하나의 동작입니다. 하지만 주의깊게 다시한번 생각해보면 우리가 버튼을 잘못 클릭한 경우 클릭을 취소하기 위해서 마우스 버튼을 누른채 외부로 이동하여 취소를 하는 경우가 있습니다. Click 을 두 가지 동작으로 나누어 놓는다면 이런 경우에 대해서 처리할 수 있을 것입니다.
우리가 마우스를 클릭하였을 때, 사각형 게임 객체의 색상을 변경하고 싶다고 가정하겠습니다.
우리는 앞서 살펴보았던 이벤트 중 마우스 버튼을 눌렀다 뗐을 때 발생하는'pointerup'
이벤트를 사용할 것입니다. 아래의 코드와 같이 색상 변경을 위해 'pointerup'
에 대한 event listener 를 추가합니다.
const gameState = {};
function create() {
gameState.notice = this.add.text(150, 300, "Press Any Key to Start");
gameState.square = this.add.rectangle(150, 150, 100, 100, 0xffFF0000);
gameState.square.setInteractive();
gameState.square.on('pointerup', function() {
this.fillColor = 0x00FF00;
});
}
/*
function update() {
gameState.square. += 1;
}
*/
const config = {
scene: { create }
}
const game = new Phaser.Game(config);
우리는 create()
메서드를 사용하여 사각형을 추가하였습니다. 그리고 setInteractive()
을 호출하여 상호작용을 할 수 있도록 설정하였습니다. 이제 .on()
매소드를 개임객체에서 호출하여 이벤트 핸들러를 등록 할 수 있습니다.
.on()
매서드는 두 개의 인자(arguments)를 받습니다. 이벤트의 명칭 ('pointerup'
) 과 앞서 event handler 라고 불렀던 콜백함수(callback function) 입니다. 앞선 코드에서는 this.fillColor
에 값을 재할당하는 새로운 함수를 두번째 argument로 직접 생성하였습니다. this.fillColor
의 값을 갱신하는 것은 사각형의 색상을 변경하는 것입니다. (여기서 this
는 사각형을 의미합니다.)
주목할 것은 'update()' 함수를 정의하지 않고, 게임의 상태값(this.fillColor
)을 변경했다는 점입니다.
키보드 이벤트
마우스만 사용하는 몇몇 게임을 제외하면 많은 브라우저 게임들은 키보드가 입력장치로 필요 합니다. 앞서 마우스 이벤트를 GameObjects 에 할당했습니다. 이번에는 사용자가 누르는 키보드에 따라 반응해 보도록 하겠습니다.
키보드 이벤트의 처리는 해당하는 게임객체에 이벤트를 할달 하는 것이 아닌 누르는 키에 이벤트를 적용합니다. this.input.keyboard.on()
를 호출하여 키 입력 핸들러를 추가합니다. 이 함수에는 이벤트의 이름과 이벤트가 발생하였을 때 호출할 함수(콜백함수)를 인자로 제공합니다. 함수는 중복된 이름만 사용하지 않는다면 어디에 정의를 해도 상관 없으며 다음 예시에서 보는 것과 같이 무명함수를 사용하여도 괜찮습니다.
const gameState = {};
function create() {
gameState.square = this.add.rectangle(150, 150, 100, 100, 0xFF0000);
this.input.keyboard.on('keydown-W', function() {
console.log(gameState);
gameState.square.fillColor = 0xFFFF00;
});
}
const config = {
type: Phaser.AUTO,
width: 300,
height: 600,
backgroundColor: "#18216D",
scene: {
create: create
}
};
let game = new Phaser.Game(config);
이 코드는 빨간 사각형을 생성합니다. 키보드의 w
키를 사용자가 누르면 해당 사각형은 노란색으로 바뀝니다.
사운드
게임에서 사운드는 화면에 생동감을 추가합니다. 사용자와의 상호작용에 따라 적절히 제공되는 효과음은 사용자가 더욱 게임에 몰입할 수 있는 환경을 제공할 것입니다.
Phaser 역시 사운드 기능을 제공하기 때문에 우리는 다음과 같은 코드를 이용하여 간단히 효과음을 추가할 수 있습니다.
사운드는 이미지와 같은 애셋이기 때문에 일단 preload()
에서 재생할 파일을 불러들여야 합니다. 그리고 create()
함수에서 이것을 추가한 후 필요에 따라 재생 합니다.
const gameState = {};
function preload() {
this.load.audio('theme', 'assets/music/theme.wav');
}
function create() {
gameState.music = this.sound.add('theme');
gameState.music.play();
}
const config = { scene: { preload, create }};
const game = new Phaser.Game(config);
게임의 특정 객체가 상호작용을 하는 것임을 나타낼때는 해당 객체위로 커서가 이동하였을 때 적절한 효과음을 재생하고 싶을 수도 있습니다. 그러한 경우는 다음과 같이 할 수 있습니다.
const gameState = {}
function preload() {
this.load.setBaseURL("https://labs.phaser.io/");
this.load.audio('sfx', 'assets/audio/SoundEffects/magical_horror_audiosprite.mp3');
}
function create() {
gameState.square = this.add.rectangle(150, 150, 100, 100, 0xFF0000);
gameState.square.setInteractive();
gameState.Sound = this.sound.add('sfx');
gameState.square.on('pointerdown', function() {
gameState.Sound.play();
});
}
const config = { scene: { preload, create }};
const game = new Phaser.Game(config);
assets/audio/SoundEffects/magical_horror_audiosprite.mp3
위치의 효과음을 불러들여 'sfx'
이라는 키 값으로 저장하였습니다. 그리고 장면에 사각형 객체를 하나 생성한 후 해당 객체가 상호작용이 가능하도록 설정하였습니다. 그리고 여기에 로드했던 'sfx'
사운드를 추가하였습니다. 이로써 사용자가 해당 사각형 위로 마우스 포인터를 이동하면 사운드가 연주되고 이를 통해 게임을 진행하는데 도움을 받을 수 있을 것 입니다.
스프라이트(Sprite) 그리기
스프라이트는 게임캐릭터, 적 등 게임속에 등장하는 것들을 나타내기 위한 이미지 입니다. 게임은 배경, 아이콘을 포함해 여러곳에서 많은 이미지 파일을 사용합니다. 스프라이트는 게임에 포함되어 있는 사람이나 아이템을 나타냅니다.
스프라이트를 추가하려면 this.add.sprite()
매서드를 호출합니다. 하지만 그 전에 스프라이트로 사용할 이미지를 로드해야합니다. 이런 일은 create()
함수전에 호출되는 preload()
함수를 사용합니다. create()
는 게임에 필요한 모든 오브젝트를 설정하고, preload()
는 우리가 사용할 모든 애셋을 로드하는 기능을 합니다.
function preload() {
// StackBlitz는 정적 파일을 지원하지 않기 때문에 외부에서 파일을 읽어오도록 합니다.
this.load.setBaseURL("https://cdn.jsdelivr.net/gh/kefik/kenney/Shooter/");
this.load.image("playership1", "playerShip1_blue.png");
}
function create() {
this.add.sprite(130, 130, 'playership1');
}
const config = {
type: Phaser.AUTO,
width: 300,
height: 600,
backgroundColor: "#18216D",
scene: {
preload: preload,
create: create,
}
};
let game = new Phaser.Game(config);
배경 이미지 추가
게임에는 사용자와 상호작용을 하지 않는 단순한 이미지들도 사용됩니다. Phaser 에도 앞서 보았던 스프라이트 객체 외에 사용자와 상호작용을 하지 않는 정적인 이미지를 추가할 수 있습니다. 이 경우도 preload()
함수에서 파일을 로드해야 합니다. 다만 마찬가지로 this.add.sprite()
대신 this.add.image()
를 사용해 장면(scene)에 추가합니다.
function preload() {
this.load.image('bg', 'assets/images/bg.png');
}
function create() {
this.add.image(200, 200, 'bg');
}
위 코드는 배경 이미지를 assets/images/bg.png
경로에서 불러옵니다. 불러온 이미지를 이후 참조하기 위해 bg
를 키 값으로 설정하였습니다. In create()
함수에서 해당 이미지(bg
)의 중심을 (200, 200) 에 위치하도록 추가하였습니다.
결론
Phaser 를 사용하여 웹브라우저 게임 WebGame을 제작할 수 있는 기본적인 기능들을 살펴보았습니다. 저는 이번에 학습한 이들 기본 기능을 바탕으로 Nonogram 이라는 간단한 퍼즐 게임을 을 이용하여 만들어 보았습니다. 다음 링크에서 동작하는 예시를 확인할 수 있으며 본 포스트에서 기술하지 못한 내용들도 소스코드를 통해 살펴 볼 수 있습니다.
※ Phaser 라는 프레임 워크를 학습중인 내용을 정리하는 차원에서 구현해 보았으며, JavaScript 를 사용하는 전문가는 아닌 관계로 코드가 개선할 점이 많다고 생각합니다. 지속적으로 학습하여 개선해 볼 생각이지만 혹시나 이용하고자 하는데 개선점 및 요청사항이 있다면 본 포스트에 댓글로 알려주시면 능력이 되는데로 구현해보겠습니다.
※ 노노그램은 워낙 널리 알려진 퍼즐이기 때문에 소스등을 참고하기 좋으며 특별히 그래픽이 필요하지 않아 학습용으로 좋을 것이라고 생각하여 선택하였습니다. 그럼에도 불구하고 여기저기서 참고한 소스 및 애셋(이미지, 아이콘, 효과음, 폰트 등)은 정리하여 게임내에 출처를 밝힐 예정입니다.
'모듈, 프레임웍 > Phaser' 카테고리의 다른 글
Angular - Phaser 통합 (0) | 2020.04.11 |
---|---|
Phaser 3 Preloading 화면 만들기 (0) | 2019.04.08 |
Angular 와 Phaser 함께 사용하기 (2/2) - 벽돌깨기 게임 만들기 (0) | 2019.01.27 |
Angular 와 Phaser 함께 사용하기 (1/2) (0) | 2019.01.06 |