๋ชฉ์ฐจ
๐ฎ 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 - ์ฝ๋ ์ ์ฅ์
๐ ๊ด๋ จ ๋ฌธ์
โ ์ด ํ์ด์ง๋ ์๋์ผ๋ก ์์ฑ๋์์ต๋๋ค.