본문 바로가기
JavaScript

[Javascript] Phaser로 게임 만들기 (1)

by teamnova 2023. 9. 17.

안녕하세요

이번 시간에는 Phaser를 사용하여 간단한 게임을 만들어보겠습니다.

 

1. Phaser란?

Phaser는 JavaScript 또는 TypeScript로 데스크톱 및 모바일용 HTML5 게임을 만드는데 사용되는 2D 게임 프레임워크입니다.

 

2. Phaser 기본 구조

Phaser의 기본 구조는 다음과 같습니다. 해당 예제는 JavaScript를 사용했습니다.

// phaser.js

// 게임의 설정을 저장하는 객체를 생성합니다.
// 게임의 유형, 화면 너비와 높이, 게임 씬(scene)을 정의하는 속성이 들어갑니다.
var config = {
    type: Phaser.AUTO, // 게임의 유형. Phaser.AUTO는 자동으로 WebGL 또는 Canvas를 선택.
    width: 800, // 게임 화면 너비
    height: 600, // 게임 화면 높이
    scene: { // 게임에 사용할 씬. 아래 세가지로 정의.
        preload: preload,
        create: create,
        update: update
    }
};

var game = new Phaser.Game(config); // 설정된 게임 구성을 사용하여 Phaser 게임 객체 생성.

// 리소스(이미지, 사운드 등)을 미리 로드할때 사용.
// 게임이 시작되기 전에 실행됩니다.
function preload () 
{
}

// 게임 씬을 초기화하고 게임 객체를 만드는데 사용.
// 게임이 시작된 후에 한번 실행됩니다.
function create ()
{
}

// 게임 루프(loop)동안 게임 상테를 업데이트하는데 사용됩니다.
// 게임이 실행되는 동안 반복적으로 호출됩니다.
function update ()
{
}

 

 

3. 게임 만들기

필요한 리소스들을 아래 웹페이지에서 다운 받아서 assets파일을 가져와줍니다.

https://phaser.io/tutorials/making-your-first-phaser-3-game/part1

그리고 html 파일과 js 파일을 만들겠습니다.

 

디렉토리 구조

 

index.html

<!doctype html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8" />
    <title>Phaser Game</title>
    <script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
    <style type="text/css">
        body {
            margin: 0;
        }
    </style>
</head>
<body>

<script src="./phaser.js"></script>

</body>
</html>

 

phaser.js

var config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    scene: {
        preload: preload,
        create: create,
        update: update
    }
};

var game = new Phaser.Game(config);

function preload ()
{
}

function create ()
{
}

function update ()
{
}

 

게임에 필요한 리소스들을 로드해보겠습니다. 

preload() 함수 내에서 코드 작성합니다.

function preload ()
{
    this.load.image('sky', 'assets/sky.png');
    this.load.image('ground', 'assets/platform.png');
    this.load.image('star', 'assets/star.png');
    this.load.image('bomb', 'assets/bomb.png');
    this.load.spritesheet('dude', 
        'assets/dude.png',
        { frameWidth: 32, frameHeight: 48 }
    );
}

 

그 다음 게임 화면에 표시해보겠습니다.

create() 함수 내에서 코드 작성합니다.

function create(){
	// preload()에서 로드한 'sky' 이미지를 화면에 추가하는 코드입니다.
	// 전체 게임화면 800X600 에서 중앙에 위치시키기 위해 x, y 좌표를 각각 400, 300 으로 설정합니다.
	this.add.image(400, 300, 'sky');
}

 

index.html 파일에 들어가면 브라우저에는 다음과 같이 표시됩니다.

 

 

여기까지 잘 완료되었으면 플랫폼을 만들어보겠습니다.

create() 함수 내부에서 물리 속성을 부여하여 플랫폼을 만들어줍니다.

function create ()
{
    this.add.image(400, 300, 'sky');

    platforms = this.physics.add.staticGroup();

    platforms.create(400, 568, 'ground').setScale(2).refreshBody();

    platforms.create(600, 400, 'ground');
    platforms.create(50, 250, 'ground');
    platforms.create(750, 220, 'ground');
}

 

결과는 다음과 같습니다.

 

캐릭터를 추가해보겠습니다.

먼저 config에 physics 속성을 추가해서 중력을 부여해줍니다.

var config = {
        type: Phaser.AUTO,
        width: 800,
        height: 600,
        physics: { // 물리 엔진 설정
            default: 'arcade', 기본 물리 엔진으로 'arcade' 사용
            arcade: {
                gravity: { y: 300 }, // 중력 설정. y방향으로 +300 단위의 중력
                debug: false // 디버그 모드 설정
            }
        },
        scene: {
            preload: preload,
            create: create,
            update: update
        }
    };

 

create() 함수 내부에 캐릭터를 추가하고 바운스 설정, 충돌 설정(게임 , 애니메이션 설정까지 해줍니다.

var player; // 플레이어 변수 선언
var platforms;

function create ()
{
    this.add.image(400, 300, 'sky');

    platforms = this.physics.add.staticGroup();

    platforms.create(400, 568, 'ground').setScale(2).refreshBody();

    platforms.create(600, 400, 'ground');
    platforms.create(50, 250, 'ground');
    platforms.create(750, 220, 'ground');

	// 캐릭터 추가
    player = this.physics.add.sprite(100, 450, 'dude');

	// 바운스 설정. 충돌했을때 얼마나 튕길지
    player.setBounce(0.2);
   // 충돌 설정
    player.setCollideWorldBounds(true);


	// 애니메이션 설정
    this.anims.create({
        key: 'left',
        frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
        frameRate: 10,
        repeat: -1
    });

    this.anims.create({
        key: 'turn',
        frames: [ { key: 'dude', frame: 4 } ],
        frameRate: 20
    });

    this.anims.create({
        key: 'right',
        frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
        frameRate: 10,
        repeat: -1
    });
    
    // 캐릭터와 플랫폼 사이 충돌되도록 설정
    this.physics.add.collider(player, platforms);
}

 

결과는 다음과 같습니다.

 

 

현재까지 작성한 phaser.js 전체 코드입니다.

var config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 300 },
            debug: false
        }
    },
    scene: {
        preload: preload,
        create: create,
        update: update
    }
};

var player;
var platforms;

var game = new Phaser.Game(config);

function preload ()
{
    this.load.image('sky', 'assets/sky.png');
    this.load.image('ground', 'assets/platform.png');
    this.load.image('star', 'assets/star.png');
    this.load.image('bomb', 'assets/bomb.png');
    this.load.spritesheet('dude', 'assets/dude.png', { frameWidth: 32, frameHeight: 48 });
}

function create ()
{
    this.add.image(400, 300, 'sky');

    platforms = this.physics.add.staticGroup();

    platforms.create(400, 568, 'ground').setScale(2).refreshBody();

    platforms.create(600, 400, 'ground');
    platforms.create(50, 250, 'ground');
    platforms.create(750, 220, 'ground');

    player = this.physics.add.sprite(100, 450, 'dude');

    player.setBounce(0.2);
    player.setCollideWorldBounds(true);

    this.anims.create({
        key: 'left',
        frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
        frameRate: 10,
        repeat: -1
    });

    this.anims.create({
        key: 'turn',
        frames: [ { key: 'dude', frame: 4 } ],
        frameRate: 20
    });

    this.anims.create({
        key: 'right',
        frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
        frameRate: 10,
        repeat: -1
    });

    this.physics.add.collider(player, platforms);
}

function update ()
{
}