์‚ฌ์šฉ์ž ๋„๊ตฌ

์‚ฌ์ดํŠธ ๋„๊ตฌ


wiki:glossary:game_development:phaser

๐ŸŽฎ Phaser.js

Phaser.js๋Š” HTML5 ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ JavaScript ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ฒŒ์ž„์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

๐Ÿ“‹ ์ •์˜

Phaser.js๋Š” HTML5 Canvas์™€ WebGL์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์˜คํ”ˆ์†Œ์Šค ๊ฒŒ์ž„ ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ์Šคํ”„๋ผ์ดํŠธ, ์• ๋‹ˆ๋ฉ”์ด์…˜, ์‚ฌ์šด๋“œ, ๋ฌผ๋ฆฌ ์—”์ง„ ๋“ฑ ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽฏ ์ฃผ์š” ํŠน์ง•

1. ํฌ๋กœ์Šค ํ”Œ๋žซํผ ์ง€์› - ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰๋˜๋Š” HTML5 ๊ฒŒ์ž„์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - ๋ชจ๋ฐ”์ผ, ๋ฐ์Šคํฌํ†ฑ, ํƒœ๋ธ”๋ฆฟ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๊ธฐ์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

2. ํ’๋ถ€ํ•œ ๊ฒŒ์ž„ ๊ธฐ๋Šฅ - ์Šคํ”„๋ผ์ดํŠธ ๊ด€๋ฆฌ ๋ฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ - ์‚ฌ์šด๋“œ ๋ฐ ์Œ์•… ์žฌ์ƒ - ๋ฌผ๋ฆฌ ์—”์ง„ (Arcade Physics, Matter.js) - ์ž…๋ ฅ ์ฒ˜๋ฆฌ (ํ‚ค๋ณด๋“œ, ๋งˆ์šฐ์Šค, ํ„ฐ์น˜) - ์นด๋ฉ”๋ผ ๋ฐ ์‹œ๊ฐ ํšจ๊ณผ

3. ์ง๊ด€์ ์ธ API - ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์— ํŠนํ™”๋œ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. - ์”ฌ(Scene) ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ๋กœ ๊ฒŒ์ž„ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ—๏ธ ๊ธฐ๋ณธ ๊ตฌ์กฐ

Phaser ๊ฒŒ์ž„ ์„ค์ •:

import Phaser from 'phaser';
 
const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'game-container',
    backgroundColor: '#2c3e50',
    scene: {
        preload: preload,
        create: create,
        update: update
    },
    physics: {
        default: 'arcade',
        arcade: {
            gravity: { y: 300 },
            debug: false
        }
    }
};
 
const game = new Phaser.Game(config);

๊ธฐ๋ณธ ๊ฒŒ์ž„ ์”ฌ:

function preload() {
    // ์—์…‹ ๋กœ๋“œ
    this.load.image('player', 'assets/player.png');
    this.load.image('background', 'assets/background.png');
    this.load.audio('jump', 'assets/jump.wav');
}
 
function create() {
    // ๊ฒŒ์ž„ ๊ฐ์ฒด ์ƒ์„ฑ
    this.add.image(400, 300, 'background');
    this.player = this.physics.add.sprite(100, 450, 'player');
 
    // ์ž…๋ ฅ ์„ค์ •
    this.cursors = this.input.keyboard.createCursorKeys();
 
    // ์‚ฌ์šด๋“œ ์„ค์ •
    this.jumpSound = this.sound.add('jump');
}
 
function update() {
    // ๊ฒŒ์ž„ ๋กœ์ง ์—…๋ฐ์ดํŠธ
    if (this.cursors.left.isDown) {
        this.player.setVelocityX(-160);
    } else if (this.cursors.right.isDown) {
        this.player.setVelocityX(160);
    } else {
        this.player.setVelocityX(0);
    }
 
    if (this.cursors.up.isDown && this.player.body.touching.down) {
        this.player.setVelocityY(-330);
        this.jumpSound.play();
    }
}

๐ŸŽจ ์Šคํ”„๋ผ์ดํŠธ ๊ด€๋ฆฌ

์Šคํ”„๋ผ์ดํŠธ๋Š” ๋น„๋””์˜ค ๊ฒŒ์ž„์ด๋‚˜ ์ปดํ“จํ„ฐ ๊ทธ๋ž˜ํ”ฝ์—์„œ ์‚ฌ์šฉ๋˜๋Š” 2D ๋น„ํŠธ๋งต ์ด๋ฏธ์ง€ ๋˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” ์บ๋ฆญํ„ฐ, ์˜ค๋ธŒ์ ํŠธ ๋˜๋Š” ๋ฐฐ๊ฒฝ ์š”์†Œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์Šคํ”„๋ผ์ดํŠธ ์ƒ์„ฑ:

// ์ด๋ฏธ์ง€ ์Šคํ”„๋ผ์ดํŠธ
const sprite = this.add.sprite(x, y, 'spriteKey');
 
// ๋ฌผ๋ฆฌ ๋ฐ”๋”” ์ถ”๊ฐ€
const physicsSprite = this.physics.add.sprite(x, y, 'spriteKey');
 
// ๊ทธ๋ฃน ์ƒ์„ฑ
const group = this.add.group();
group.add(sprite1);
group.add(sprite2);

์• ๋‹ˆ๋ฉ”์ด์…˜ ์„ค์ •:

// ์Šคํ”„๋ผ์ดํŠธ ์‹œํŠธ์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ƒ์„ฑ
this.anims.create({
    key: 'walk',
    frames: this.anims.generateFrameNumbers('player', { start: 0, end: 3 }),
    frameRate: 10,
    repeat: -1
});
 
// ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ
sprite.play('walk');

๐ŸŽต ์‚ฌ์šด๋“œ ์‹œ์Šคํ…œ

์‚ฌ์šด๋“œ ๊ด€๋ฆฌ:

// ์‚ฌ์šด๋“œ ๋กœ๋“œ
this.load.audio('bgMusic', 'assets/music.mp3');
this.load.audio('jumpSound', 'assets/jump.wav');
 
// ์‚ฌ์šด๋“œ ์žฌ์ƒ
const bgMusic = this.sound.add('bgMusic', { loop: true, volume: 0.5 });
bgMusic.play();
 
// ํšจ๊ณผ์Œ ์žฌ์ƒ
this.sound.play('jumpSound');

๐ŸŽฎ ์ž…๋ ฅ ์ฒ˜๋ฆฌ

ํ‚ค๋ณด๋“œ ์ž…๋ ฅ:

// ์ปค์„œ ํ‚ค ์„ค์ •
this.cursors = this.input.keyboard.createCursorKeys();
 
// ํŠน์ • ํ‚ค ์„ค์ •
this.spaceKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
 
// ํ‚ค ์ด๋ฒคํŠธ
this.input.keyboard.on('keydown-A', function() {
    console.log('A ํ‚ค๊ฐ€ ๋ˆŒ๋ ธ์Šต๋‹ˆ๋‹ค!');
});

๋งˆ์šฐ์Šค/ํ„ฐ์น˜ ์ž…๋ ฅ:

// ํด๋ฆญ ์ด๋ฒคํŠธ
this.input.on('pointerdown', function(pointer) {
    console.log('ํด๋ฆญ ์œ„์น˜:', pointer.x, pointer.y);
});
 
// ์Šคํ”„๋ผ์ดํŠธ ํด๋ฆญ ์ด๋ฒคํŠธ
sprite.setInteractive();
sprite.on('pointerdown', function() {
    console.log('์Šคํ”„๋ผ์ดํŠธ๊ฐ€ ํด๋ฆญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!');
});

๐Ÿƒ ๋ฌผ๋ฆฌ ์—”์ง„

Arcade Physics:

// ๋ฌผ๋ฆฌ ๋ฐ”๋”” ์ถ”๊ฐ€
this.player = this.physics.add.sprite(100, 450, 'player');
 
// ์ค‘๋ ฅ ์„ค์ •
this.player.body.setGravityY(300);
 
// ์ถฉ๋Œ ๊ฐ์ง€
this.physics.add.collider(this.player, this.platforms);
 
// ์˜ค๋ฒ„๋žฉ ๊ฐ์ง€
this.physics.add.overlap(this.player, this.coins, this.collectCoin, null, this);

์ถฉ๋Œ ์ฒ˜๋ฆฌ:

function collectCoin(player, coin) {
    coin.disableBody(true, true);
    this.score += 10;
    this.scoreText.setText('Score: ' + this.score);
}

๐Ÿ“ฑ ๋ชจ๋ฐ”์ผ ์ตœ์ ํ™”

๋ฐ˜์‘ํ˜• ๋””์ž์ธ:

const config = {
    type: Phaser.AUTO,
    width: window.innerWidth,
    height: window.innerHeight,
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH
    }
};

ํ„ฐ์น˜ ์ปจํŠธ๋กค:

// ๊ฐ€์ƒ ์กฐ์ด์Šคํ‹ฑ
this.joyStick = this.plugins.get('rexvirtualjoystickplugin').add(this, {
    x: 100,
    y: 500,
    radius: 50,
    base: this.add.circle(0, 0, 50, 0x888888),
    thumb: this.add.circle(0, 0, 25, 0xcccccc),
    // ... ๊ธฐํƒ€ ์„ค์ •
});

๐ŸŽจ ์‹œ๊ฐ ํšจ๊ณผ

ํŒŒํ‹ฐํด ์‹œ์Šคํ…œ:

// ํŒŒํ‹ฐํด ์ƒ์„ฑ
const particles = this.add.particles('particle');
 
const emitter = particles.createEmitter({
    speed: 100,
    scale: { start: 1, end: 0 },
    blendMode: 'ADD'
});
 
// ํŒŒํ‹ฐํด ๋ฐœ์‚ฌ
emitter.setPosition(400, 300);

์นด๋ฉ”๋ผ ํšจ๊ณผ:

// ์นด๋ฉ”๋ผ ํŒ”๋กœ์šฐ
this.cameras.main.startFollow(this.player);
 
// ์นด๋ฉ”๋ผ ํ”๋“ค๊ธฐ
this.cameras.main.shake(500, 0.01);
 
// ํŽ˜์ด๋“œ ํšจ๊ณผ
this.cameras.main.fade(1000, 0, 0, 0);

๐Ÿ“Š ์„ฑ๋Šฅ ์ตœ์ ํ™”

๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ:

// ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ…์Šค์ฒ˜ ์ œ๊ฑฐ
this.textures.remove('unusedSprite');
 
// ์Šคํ”„๋ผ์ดํŠธ ํ’€๋ง
const spritePool = this.add.group();
for (let i = 0; i < 10; i++) {
    const sprite = this.add.sprite(0, 0, 'bullet');
    sprite.setActive(false);
    sprite.setVisible(false);
    spritePool.add(sprite);
}

๋ Œ๋”๋ง ์ตœ์ ํ™”:

// ์ •์  ๊ฐ์ฒด๋Š” ํ•œ ๋ฒˆ๋งŒ ๋ Œ๋”๋ง
this.add.staticGroup();
 
// ๋ฐฐ์น˜ ๋ Œ๋”๋ง ์‚ฌ์šฉ
this.add.batch('sprites');

๐Ÿ“š ๊ด€๋ จ ์šฉ์–ด

  • JavaScript - ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด
  • CSS - ์Šคํƒ€์ผ๋ง
  • GitHub - ์ฝ”๋“œ ์ €์žฅ์†Œ

๐Ÿ”— ๊ด€๋ จ ๋ฌธ์„œ

โ€” ์ด ํŽ˜์ด์ง€๋Š” ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

wiki/glossary/game_development/phaser.txt ยท ๋งˆ์ง€๋ง‰์œผ๋กœ ์ˆ˜์ •๋จ: ์ €์ž 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki