wiki:it:dream_of_enc:metaverse:phaser
์ฐจ์ด
๋ฌธ์์ ์ ํํ ๋ ํ ์ฌ์ด์ ์ฐจ์ด๋ฅผ ๋ณด์ฌ์ค๋๋ค.
๋ค์ ํ | ์ด์ ํ | ||
wiki:it:dream_of_enc:metaverse:phaser [2025/07/28 05:57] โ ๋ง๋ฆ - ๋ฐ๊นฅ ํธ์ง 127.0.0.1 | wiki:it:dream_of_enc:metaverse:phaser [2025/07/30 06:43] (ํ์ฌ) โ ๋ฐ๊นฅ ํธ์ง 127.0.0.1 | ||
---|---|---|---|
์ค 1: | ์ค 1: | ||
====== ๐ฎ Phaser.js ๊ฒ์ ์์ง ====== | ====== ๐ฎ Phaser.js ๊ฒ์ ์์ง ====== | ||
- | Phaser Baduk Metaverse ํ๋ก์ ํธ์ Phaser.js ๊ฒ์ ์์ง ๊ตฌํ์ ๋ํด ์ค๋ช ํฉ๋๋ค. | + | Phaser Baduk Metaverse ํ๋ก์ ํธ์์ ์ฌ์ฉ๋๋ |
+ | ---- | ||
===== ๐ ๊ฐ์ ===== | ===== ๐ ๊ฐ์ ===== | ||
- | Phaser.js๋ HTML5 ๊ฒ์ ๊ฐ๋ฐ์ ์ํ JavaScript ํ๋ ์์ํฌ๋ก, ๋ฐ๋ ๊ฒ์์ ์๊ฐ์ ์์์ ์ธํฐ๋์
์ | + | Phaser.js๋ HTML5 ๊ฒ์ ๊ฐ๋ฐ์ ํนํ๋ ๊ฐ๋ ฅํ JavaScript ํ๋ ์์ํฌ์
๋๋ค. ์ด ํ๋ ์์ํฌ๋ |
- | ===== ๐๏ธ | + | * '' |
+ | * '' | ||
+ | * '' | ||
- | **๋ฉ์ธ ๊ฒ์ ํ์ผ (game.js):**ย | + | ----ย |
- | <code javascript> | + | ==== 1. ๊ฒ์ ์์ง ๊ธฐ๋ณธ ๊ตฌ์กฐ ๋ฐ ์ค์ ====ย |
+ | ย | ||
+ | Phaser.js ๊ฒ์ ์์ง์ ํต์ฌ ์ง์
์ ์ธ '' | ||
+ | ย | ||
+ | === 1) ๋ฉ์ธ ๊ฒ์ ํ์ผ (game.js) | ||
+ | ย | ||
+ | '' | ||
+ | ย | ||
+ | <file javascript> | ||
import Phaser from ' | import Phaser from ' | ||
import BadukScene from ' | import BadukScene from ' | ||
import MenuScene from ' | import MenuScene from ' | ||
+ | // 1. ๊ฒ์ ์ค์ ๊ฐ์ฒด ์ ์ | ||
const config = { | const config = { | ||
- | type: Phaser.AUTO, | + | type: Phaser.AUTO, |
- | width: 1200,ย | + | width: 1200, // ๊ฒ์ ํ๋ฉด ๋๋น (ํฝ์ )ย |
- | height: 800,ย | + | height: 800, // ๊ฒ์ ํ๋ฉด ๋์ด (ํฝ์ )ย |
- | parent: ' | + | parent: ' |
- | backgroundColor: | + | backgroundColor: |
- | scene: [MenuScene, BadukScene], | + | scene: [MenuScene, BadukScene], |
- | physics: {ย | + | physics: { // ๋ฌผ๋ฆฌ ์์ง ์ค์ ย |
- | default: ' | + | default: ' |
arcade: { | arcade: { | ||
- | gravity: { y: 0 },ย | + | gravity: { y: 0 }, // y์ถ ์ค๋ ฅ ์์ย |
- | debug: false | + | debug: false // ๋ฌผ๋ฆฌ ๊ฐ์ฒด ๋๋ฒ๊ทธ ์ ๋ณด ๋นํ์ฑํ |
} | } | ||
}, | }, | ||
- | scale: {ย | + | scale: { // ์ค์ผ์ผ๋ง ์ค์ ย |
- | mode: Phaser.Scale.FIT, | + | mode: Phaser.Scale.FIT, |
- | autoCenter: Phaser.Scale.CENTER_BOTH | + | autoCenter: Phaser.Scale.CENTER_BOTH |
} | } | ||
}; | }; | ||
+ | // 2. Phaser ๊ฒ์ ์ธ์คํด์ค ์์ฑ | ||
const game = new Phaser.Game(config); | const game = new Phaser.Game(config); | ||
+ | |||
+ | // 3. ๊ฒ์ ์ธ์คํด์ค ๋ด๋ณด๋ด๊ธฐ (๋ค๋ฅธ ํ์ผ์์ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก) | ||
export default game; | export default game; | ||
- | </code> | + | </file>ย |
+ | ย | ||
+ | '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | ย | ||
+ | ----ย | ||
+ | ==== 2. ์ฌ(Scene) ๊ด๋ฆฌ ๋ฐ ์ ํ ==== | ||
- | ===== ๐ฏ ์ฌ(Scene) | + | Phaser.js์์ '' |
- | **๋ฉ๋ด ์ฌ (MenuScene.js):**ย | + | === 2) ๋ฉ๋ด ์ฌ (MenuScene.js) |
- | <code javascript> | + | ย |
+ | '' | ||
+ | ย | ||
+ | <file javascript> | ||
import Phaser from ' | import Phaser from ' | ||
export default class MenuScene extends Phaser.Scene { | export default class MenuScene extends Phaser.Scene { | ||
constructor() { | constructor() { | ||
- | super({ key: ' | + | super({ key: ' |
} | } | ||
preload() { | preload() { | ||
- | // ๋ฉ๋ด ๋ฐฐ๊ฒฝ ๋ฐ ๋ฒํผ | + | // 1. ํ์ํ |
this.load.image(' | this.load.image(' | ||
this.load.image(' | this.load.image(' | ||
์ค 58: | ์ค 92: | ||
create() { | create() { | ||
- | // ๋ฐฐ๊ฒฝ | + | // 2. ๋ฐฐ๊ฒฝ |
this.add.image(600, | this.add.image(600, | ||
| | ||
- | // ์ ๋ชฉ ํ ์คํธย | + | // 3. ๊ฒ์ |
- | this.add.text(600, | + | this.add.text(600, |
fontSize: ' | fontSize: ' | ||
- | fill: '# | + | fill: '# |
fontFamily: ' | fontFamily: ' | ||
- | }).setOrigin(0.5); | + | }).setOrigin(0.5); |
- | ย | + | ย |
- | // ํ๋ ์ด ๋ฒํผ | + | // 4. ํ๋ ์ด ๋ฒํผ |
const playButton = this.add.image(600, | const playButton = this.add.image(600, | ||
- | .setInteractive(); | + | .setInteractive(); |
| | ||
- | playButton.on(' | + | playButton.on(' |
- | this.scene.start(' | + | this.scene.start(' |
}); | }); | ||
| | ||
- | // ์ค์ ๋ฒํผ | + | // 5. ์ค์ ๋ฒํผ |
const settingsButton = this.add.image(600, | const settingsButton = this.add.image(600, | ||
.setInteractive(); | .setInteractive(); | ||
| | ||
settingsButton.on(' | settingsButton.on(' | ||
- | | + | console.log(' |
- | | + | |
}); | }); | ||
} | } | ||
} | } | ||
- | </code> | + | </file>ย |
+ | ย | ||
+ | '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | ย | ||
+ | ----ย | ||
+ | === 2) ๋ฐ๋ ๊ฒ์ ์ฌ (BadukScene.js) ===ย | ||
+ | ย | ||
+ | '' | ||
- | **๋ฐ๋ ๊ฒ์ ์ฌ (BadukScene.js): | + | <file javascript> |
- | <code javascript> | + | |
import Phaser from ' | import Phaser from ' | ||
- | import BadukBoard from ' | + | import BadukBoard from ' |
- | import BadukStone from ' | + | import BadukStone from ' |
export default class BadukScene extends Phaser.Scene { | export default class BadukScene extends Phaser.Scene { | ||
constructor() { | constructor() { | ||
super({ key: ' | super({ key: ' | ||
- | this.board = null;ย | + | this.board = null; // ๋ฐ๋ํ ๊ฐ์ฒดย |
- | this.stones = [];ย | + | this.stones = []; // ๋์ฌ์ง ๋ฐ๋๋ ๋ฐฐ์ดย |
- | this.currentPlayer = ' | + | this.currentPlayer = ' |
+ | this.gameId = null; // ํ์ฌ ๊ฒ์ ID | ||
} | } | ||
preload() { | preload() { | ||
- | // ๋ฐ๋ํ๊ณผ ๋ ์ด๋ฏธ์ง ๋ก๋ | + | // 1. ๋ฐ๋ํ |
this.load.image(' | this.load.image(' | ||
this.load.image(' | this.load.image(' | ||
this.load.image(' | this.load.image(' | ||
- | this.load.image(' | + | this.load.image(' |
} | } | ||
create() { | create() { | ||
- | // ๋ฐ๋ํ ์์ฑย | + | // 2. ๋ฐ๋ํ ์์ฑ |
- | this.board = new BadukBoard(this, | + | this.board = new BadukBoard(this, |
- | | + | |
- | | + | this.add.image(600, |
- | this.add.image(600, | + | ย |
- | ย | + | // 3. ํด๋ฆญ ์ด๋ฒคํธ ์ค์ : ๋ฐ๋ํ ํด๋ฆญ ์ ์ฐฉ์ ์ฒ๋ฆฌ |
- | // ํด๋ฆญ ์ด๋ฒคํธ ์ค์ | + | |
this.input.on(' | this.input.on(' | ||
this.handleBoardClick(pointer); | this.handleBoardClick(pointer); | ||
}); | }); | ||
| | ||
- | // ํ๋ ์ด์ด ํ์ | + | // 4. ํ์ฌ |
this.createPlayerIndicator(); | this.createPlayerIndicator(); | ||
+ | |||
+ | // 5. (์ต์ ) ๊ฒ์ ์์ ์ ์๋ฒ๋ก๋ถํฐ ๊ฒ์ ID ์์ | ||
+ | if (window.socket) { | ||
+ | window.socket.on(' | ||
+ | console.log(' | ||
+ | this.gameId = data.gameId; | ||
+ | // ๊ฒ์ ์ํ ๋๊ธฐํ ๋ฐ ์์ ๋ก์ง ์ถ๊ฐ ๊ฐ๋ฅ | ||
+ | }); | ||
+ | window.socket.on(' | ||
+ | // ๋ค๋ฅธ ํ๋ ์ด์ด์ ์ฐฉ์ ์ ๋ณด ์์ ๋ฐ ์ฒ๋ฆฌ | ||
+ | if (data.player !== this.currentPlayer) { // ์์ ์ ํด์ด ์๋ ๊ฒฝ์ฐ์๋ง ์ฒ๋ฆฌ | ||
+ | this.placeStone(data.x, | ||
+ | } | ||
+ | }); | ||
+ | } | ||
} | } | ||
+ | // 6. ๋ฐ๋ํ ํด๋ฆญ ์ฒ๋ฆฌ ํจ์ | ||
handleBoardClick(pointer) { | handleBoardClick(pointer) { | ||
- | const boardX = pointer.x - 600;ย | + | |
- | const boardY = pointer.y - 400; | + | |
+ | const boardY = pointer.y - this.board.y; | ||
| | ||
- | // ๋ฐ๋ํ ์ขํ๋ก ๋ณํย | + | // ์๋ ์ขํ๋ฅผ ๊ทธ๋ฆฌ๋(๋ฐ๋ํ |
- | const gridX = Math.round(boardX / 40);ย | + | const gridX = Math.round(boardX / this.board.gridSize) + 9; // 0~18 ๋ฒ์๋ก ์กฐ์ ย |
- | const gridY = Math.round(boardY / 40);ย | + | const gridY = Math.round(boardY / this.board.gridSize) + 9;ย |
- | ย | + | ย |
- | // ์ ํจํ ์์น์ธ์ง ํ์ธ | + | // ์ ํจํ |
if (this.isValidMove(gridX, | if (this.isValidMove(gridX, | ||
- | this.placeStone(gridX, | + | this.placeStone(gridX, |
} | } | ||
} | } | ||
+ | // 7. ์ฐฉ์ ์์น ์ ํจ์ฑ ๊ฒ์ฌ | ||
isValidMove(x, | isValidMove(x, | ||
- | // ๋ฐ๋ํ ๋ฒ์ ๋ด์ธ์ง ํ์ธ | + | // ๋ฐ๋ํ ๋ฒ์ |
if (x < 0 || x > 18 || y < 0 || y > 18) { | if (x < 0 || x > 18 || y < 0 || y > 18) { | ||
return false; | return false; | ||
์ค 150: | ์ค 214: | ||
stone.gridX === x && stone.gridY === y | stone.gridX === x && stone.gridY === y | ||
); | ); | ||
+ | // TODO: ์์ถฉ, ์ฝ ๊ท์น ๋ฑ ์ถ๊ฐ์ ์ธ ๋ฐ๋ ๊ท์น ๊ฒ์ฌ ํ์ | ||
} | } | ||
- | placeStone(x, | + | |
- | const stoneImage = this.currentPlayer | + | |
- | const stone = new BadukStone(this, | + | // ํ์ฌ ํด ํ๋ ์ด์ด์ ๋ ์ด๋ฏธ์ง ์ ํย |
+ | const stoneImage = playerColor | ||
+ | // BadukStone ์คํ๋ผ์ดํธ ์์ฑ (์ ๋๋ฉ์ด์ ํฌํจ)ย | ||
+ | const stone = new BadukStone(this, | ||
| | ||
- | this.stones.push(stone); | + | this.stones.push(stone); |
| | ||
- | // ํ๋ ์ด์ด ๋ณ๊ฒฝ | + | // ํ๋ ์ด์ด |
this.currentPlayer = this.currentPlayer === ' | this.currentPlayer = this.currentPlayer === ' | ||
| | ||
- | // UI ์ ๋ฐ์ดํธ | + | // UI ์
๋ฐ์ดํธ |
this.updatePlayerIndicator(); | this.updatePlayerIndicator(); | ||
| | ||
- | // ์๋ฒ์ | + | // ์๋ฒ์ |
- | this.sendMoveToServer(x, | + | this.sendMoveToServer(x, |
} | } | ||
+ | // 9. ํ์ฌ ํ๋ ์ด์ด ํ์ UI ์์ฑ | ||
createPlayerIndicator() { | createPlayerIndicator() { | ||
this.playerText = this.add.text(50, | this.playerText = this.add.text(50, | ||
์ค 175: | ์ค 244: | ||
} | } | ||
+ | // 10. ํ์ฌ ํ๋ ์ด์ด ํ์ UI ์ ๋ฐ์ดํธ | ||
updatePlayerIndicator() { | updatePlayerIndicator() { | ||
const playerName = this.currentPlayer === ' | const playerName = this.currentPlayer === ' | ||
์ค 180: | ์ค 250: | ||
} | } | ||
+ | // 11. ์๋ฒ์ ์ฐฉ์ ์ ๋ณด ์ ์ก | ||
sendMoveToServer(x, | sendMoveToServer(x, | ||
- | | + | if (window.socket |
- | | + | window.socket.emit(' |
- | window.socket.emit(' | + | |
x: x, | x: x, | ||
y: y, | y: y, | ||
player: player, | player: player, | ||
- | gameId: this.gameId | + | gameId: this.gameId |
}); | }); | ||
} | } | ||
} | } | ||
} | } | ||
- | </code> | + | </file> |
- | ===== ๐จ ์คํ๋ผ์ดํธ(Sprite) ๊ตฌํ ===== | + | '' |
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
- | **๋ฐ๋ํ ์คํ๋ผ์ดํธ (BadukBoard.js):**ย | + | ----ย |
- | <code javascript> | + | ==== 3. ํต์ฌ ์คํ๋ผ์ดํธ(Sprite) ๊ตฌํ ====ย |
+ | ย | ||
+ | Phaser.js์์ '' | ||
+ | ย | ||
+ | === 3) ๋ฐ๋ํ ์คํ๋ผ์ดํธ (BadukBoard.js) | ||
+ | ย | ||
+ | '' | ||
+ | ย | ||
+ | <file javascript> | ||
import Phaser from ' | import Phaser from ' | ||
export default class BadukBoard extends Phaser.GameObjects.Sprite { | export default class BadukBoard extends Phaser.GameObjects.Sprite { | ||
constructor(scene, | constructor(scene, | ||
- | super(scene, | + | super(scene, |
| | ||
- | this.setOrigin(0.5); | + | this.setOrigin(0.5); |
- | this.setInteractive(); | + | this.setInteractive(); |
| | ||
- | | + | this.setScale(1.0); |
- | | + | |
| | ||
- | // ๊ทธ๋ฆฌ๋ ์ขํ ์์คํ ย | + | // ๋ฐ๋ํ |
- | this.gridSize = 40; | + | this.gridSize = 40; // ํ ์นธ์ ํฝ์ ํฌ๊ธฐ |
this.boardSize = 19; // 19x19 ๋ฐ๋ํ | this.boardSize = 19; // 19x19 ๋ฐ๋ํ | ||
} | } | ||
- | // ๊ทธ๋ฆฌ๋ ์ขํ๋ฅผ ํฝ์ ์ขํ๋ก ๋ณํ | + | // 1. ๊ทธ๋ฆฌ๋ ์ขํ(0~18)๋ฅผ ๊ฒ์ ํ๋ฉด์ |
gridToPixel(gridX, | gridToPixel(gridX, | ||
- | const pixelX = this.x + (gridX - 9) * this.gridSize; | + | |
- | const pixelY = this.y + (gridY - 9) * this.gridSize; | + | // ์: gridX 9๋ ๋ฐ๋ํ์ ์ค์ x์ถ์ ํด๋นย |
+ | | ||
+ | const pixelY = this.y + (gridY - (this.boardSize - 1) / 2) * this.gridSize; | ||
return { x: pixelX, y: pixelY }; | return { x: pixelX, y: pixelY }; | ||
} | } | ||
- | // ํฝ์ ์ขํ๋ฅผ ๊ทธ๋ฆฌ๋ ์ขํ๋ก ๋ณํ | + | // 2. ๊ฒ์ ํ๋ฉด์ |
pixelToGrid(pixelX, | pixelToGrid(pixelX, | ||
- | const gridX = Math.round((pixelX - this.x) / this.gridSize) + 9;ย | + | |
- | const gridY = Math.round((pixelY - this.y) / this.gridSize) + 9; | + | |
+ | const gridY = Math.round((pixelY - this.y) / this.gridSize) + (this.boardSize - 1) / 2; | ||
return { x: gridX, y: gridY }; | return { x: gridX, y: gridY }; | ||
} | } | ||
} | } | ||
- | </code> | + | </file> |
- | **๋ฐ๋๋ ์คํ๋ผ์ดํธ (BadukStone.js):**ย | + | '' |
- | <code javascript> | + | |
+ | | ||
+ | * '' | ||
+ | | ||
+ | | ||
+ | * '' | ||
+ | * '' | ||
+ | ย | ||
+ | ----ย | ||
+ | === 3) ๋ฐ๋๋ ์คํ๋ผ์ดํธ (BadukStone.js) ===ย | ||
+ | ย | ||
+ | '' | ||
+ | ย | ||
+ | <file javascript> | ||
import Phaser from ' | import Phaser from ' | ||
export default class BadukStone extends Phaser.GameObjects.Sprite { | export default class BadukStone extends Phaser.GameObjects.Sprite { | ||
constructor(scene, | constructor(scene, | ||
+ | // ๋ ์ด๋ฏธ์ง ํค ์ ํ (' | ||
const imageKey = color === ' | const imageKey = color === ' | ||
+ | // ๋ฐ๋ํ ๊ฐ์ฒด์ gridToPixel ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ๋ฆฌ๋ ์ขํ๋ฅผ ํฝ์ ์ขํ๋ก ๋ณํ | ||
const { x, y } = scene.board.gridToPixel(gridX, | const { x, y } = scene.board.gridToPixel(gridX, | ||
| | ||
- | super(scene, | + | super(scene, |
| | ||
- | this.gridX = gridX;ย | + | this.gridX = gridX; |
- | this.gridY = gridY;ย | + | this.gridY = gridY; |
- | this.color = color; | + | this.color = color; |
| | ||
- | this.setOrigin(0.5); | + | this.setOrigin(0.5); |
- | this.setScale(0.8); | + | this.setScale(0.8); |
| | ||
- | // ์ ๋๋ฉ์ด์ ํจ๊ณผย | + | // 1. ์ฐฉ์ ์ ๋์ด ์ปค์ง๋ |
- | this.setScale(0);ย | + | this.setScale(0); // ์ฒ์์๋ ํฌ๊ธฐ๋ฅผ 0์ผ๋ก |
- | scene.tweens.add({ย | + | scene.tweens.add({ // ํธ์(์ ๋๋ฉ์ด์ ) ์ถ๊ฐย |
- | targets: this,ย | + | |
- | scaleX: | + | |
- | scaleY: 0.8,ย | + | |
- | duration: 200,ย | + | |
- | ease: ' | + | |
- | });ย | + | |
- | ย | + | |
- | scene.add.existing(this); | + | |
- | }ย | + | |
- | ย | + | |
- | // ๋ ์ ๊ฑฐ (์ฐฉ์)ย | + | |
- | remove() {ย | + | |
- | this.scene.tweens.add({ย | + | |
- | targets: this,ย | + | |
- | scaleX: | + | |
- | scaleY: 0,ย | + | |
- | duration: 150,ย | + | |
- | ease: ' | + | |
- | onComplete: () => {ย | + | |
- | this.destroy();ย | + | |
- | }ย | + | |
- | });ย | + | |
- | }ย | + | |
- | }ย | + | |
- | </code>ย | + | |
- | ย | + | |
- | ===== ๐ Socket.IO ํต์ =====ย | + | |
- | ย | + | |
- | **์ค์๊ฐ ํต์ ์ค์ :**ย | + | |
- | <code javascript> | + | |
- | // game.js์์ Socket.IO ์ฐ๊ฒฐย | + | |
- | import io from ' | + | |
- | ย | + | |
- | const socket = io(' | + | |
- | ย | + | |
- | socket.on(' | + | |
- | console.log(' | + | |
- | });ย | + | |
- | ย | + | |
- | socket.on(' | + | |
- | // ๋ค๋ฅธ ํ๋ ์ด์ด์ ์ด๋ | + | |
- | if (data.player !== currentPlayer) {ย | + | |
- | scene.placeStoneFromServer(data.x, | + | |
- | }ย | + | |
- | });ย | + | |
- | ย | + | |
- | socket.on(' | + | |
- | console.log(' | + | |
- | scene.startGame(data.gameId); | + | |
- | });ย | + | |
- | ย | + | |
- | // ์ ์ญ์์ ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก | + | |
- | window.socket = socket;ย | + | |
- | </ | + | |
- | ย | + | |
- | ===== ๐จ UI/UX ๊ตฌํ =====ย | + | |
- | ย | + | |
- | **๊ฒ์ UI ์ปดํฌ๋ํธ: | + | |
- | <code javascript> | + | |
- | export default class GameUI {ย | + | |
- | constructor(scene) {ย | + | |
- | | + | |
- | this.createUI(); | + | |
- | }ย | + | |
- | ย | + | |
- | createUI() {ย | + | |
- | // ํจ์ค ๋ฒํผย | + | |
- | this.passButton = this.scene.add.text(50, 150, ' | + | |
- | fontSize: ' | + | |
- | fill: '# | + | |
- | backgroundColor: | + | |
- | padding: { x: 10, y: 5 }ย | + | |
- | }).setInteractive(); | + | |
- | ย | + | |
- | this.passButton.on(' | + | |
- | this.handlePass(); | + | |
- | });ย | + | |
- | ย | + | |
- | | + | |
- | this.surrenderButton = this.scene.add.text(50, 200, ' | + | |
- | fontSize: ' | + | |
- | fill: '# | + | |
- | backgroundColor: | + | |
- | padding: { x: 10, y: 5 }ย | + | |
- | }).setInteractive(); | + | |
- | ย | + | |
- | this.surrenderButton.on(' | + | |
- | | + | |
- | });ย | + | |
- | ย | + | |
- | // ์ ์ ํ์ย | + | |
- | this.scoreText = this.scene.add.text(50, | + | |
- | fontSize: ' | + | |
- | fill: '# | + | |
- | });ย | + | |
- | }ย | + | |
- | ย | + | |
- | handlePass() {ย | + | |
- | // ํจ์ค ์ฒ๋ฆฌย | + | |
- | if (window.socket) {ย | + | |
- | window.socket.emit(' | + | |
- | gameId: this.scene.gameId,ย | + | |
- | player: this.scene.currentPlayerย | + | |
- | });ย | + | |
- | }ย | + | |
- | }ย | + | |
- | ย | + | |
- | handleSurrender() {ย | + | |
- | | + | |
- | if (window.socket) {ย | + | |
- | | + | |
- | gameId: this.scene.gameId, | + | |
- | player: this.scene.currentPlayerย | + | |
- | });ย | + | |
- | }ย | + | |
- | }ย | + | |
- | ย | + | |
- | updateScore(blackScore, | + | |
- | this.scoreText.setText(`์ ์: | + | |
- | }ย | + | |
- | }ย | + | |
- | </ | + | |
- | ย | + | |
- | ===== ๐ฎ ๊ฒ์ ๋ก์ง =====ย | + | |
- | ย | + | |
- | **๋ฐ๋ ๊ท์น ๊ตฌํ:**ย | + | |
- | <code javascript> | + | |
- | export default class BadukRules {ย | + | |
- | constructor() {ย | + | |
- | this.board = Array(19).fill().map(() => Array(19).fill(null)); | + | |
- | this.capturedStones = { black: 0, white: 0 };ย | + | |
- | }ย | + | |
- | ย | + | |
- | // ๋ ๋๊ธฐย | + | |
- | placeStone(x, | + | |
- | if (this.isValidMove(x, y, color)) {ย | + | |
- | this.board[y][x] = color;ย | + | |
- | ย | + | |
- | | + | |
- | const captured = this.checkCapture(x, | + | |
- | this.capturedStones[color] += captured;ย | + | |
- | ย | + | |
- | return true;ย | + | |
- | }ย | + | |
- | return false;ย | + | |
- | }ย | + | |
- | ย | + | |
- | // ์ ํจํ ์ด๋์ธ์ง ํ์ธย | + | |
- | isValidMove(x, | + | |
- | if (x < 0 || x >= 19 || y < 0 || y >= 19) {ย | + | |
- | return false;ย | + | |
- | }ย | + | |
- | ย | + | |
- | if (this.board[y][x] !== null) {ย | + | |
- | | + | |
- | }ย | + | |
- | ย | + | |
- | // ์์ถฉ ํ์ธย | + | |
- | this.board[y][x] = color;ย | + | |
- | const hasLiberties = this.hasLiberties(x, | + | |
- | this.board[y][x] = null;ย | + | |
- | ย | + | |
- | return hasLiberties; | + | |
- | }ย | + | |
- | ย | + | |
- | // ์์ ๋ ํ์ธย | + | |
- | hasLiberties(x, | + | |
- | const color = this.board[y][x]; | + | |
- | const visited = new Set();ย | + | |
- | ย | + | |
- | return this.checkGroupLiberties(x, | + | |
- | }ย | + | |
- | ย | + | |
- | checkGroupLiberties(x, | + | |
- | const key = `${x}, | + | |
- | if (visited.has(key)) return false;ย | + | |
- | visited.add(key); | + | |
- | ย | + | |
- | // ์ํ์ข์ฐ ํ์ธย | + | |
- | const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];ย | + | |
- | ย | + | |
- | for (const [dx, dy] of directions) {ย | + | |
- | const nx = x + dx;ย | + | |
- | const ny = y + dy;ย | + | |
- | ย | + | |
- | if (nx < 0 || nx >= 19 || ny < 0 || ny >= 19) {ย | + | |
- | continue;ย | + | |
- | }ย | + | |
- | ย | + | |
- | if (this.board[ny][nx] === null) {ย | + | |
- | return true; // ์์ ๋ ๋ฐ๊ฒฌย | + | |
- | }ย | + | |
- | ย | + | |
- | if (this.board[ny][nx] === color) {ย | + | |
- | if (this.checkGroupLiberties(nx, ny, color, visited)) {ย | + | |
- | return true;ย | + | |
- | }ย | + | |
- | }ย | + | |
- | }ย | + | |
- | ย | + | |
- | return false;ย | + | |
- | }ย | + | |
- | ย | + | |
- | | + | |
- | checkCapture(x, | + | |
- | const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];ย | + | |
- | let captured = 0;ย | + | |
- | ย | + | |
- | for (const [dx, dy] of directions) {ย | + | |
- | const nx = x + dx;ย | + | |
- | const ny = y + dy;ย | + | |
- | ย | + | |
- | if (nx < 0 || nx >= 19 || ny < 0 || ny >= 19) {ย | + | |
- | continue;ย | + | |
- | }ย | + | |
- | ย | + | |
- | const opponentColor = color === ' | + | |
- | ย | + | |
- | if (this.board[ny][nx] === opponentColor) {ย | + | |
- | if (!this.hasLiberties(nx, | + | |
- | captured += this.removeGroup(nx, | + | |
- | }ย | + | |
- | }ย | + | |
- | }ย | + | |
- | ย | + | |
- | return captured;ย | + | |
- | }ย | + | |
- | ย | + | |
- | // ๊ทธ๋ฃน ์ ๊ฑฐย | + | |
- | removeGroup(x, | + | |
- | const color = this.board[y][x]; | + | |
- | if (!color) return 0;ย | + | |
- | ย | + | |
- | let count = 0;ย | + | |
- | const stack = [[x, y]];ย | + | |
- | ย | + | |
- | while (stack.length > 0) {ย | + | |
- | const [cx, cy] = stack.pop(); | + | |
- | ย | + | |
- | if (this.board[cy][cx] === color) {ย | + | |
- | this.board[cy][cx] = null;ย | + | |
- | count++;ย | + | |
- | ย | + | |
- | const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];ย | + | |
- | for (const [dx, dy] of directions) {ย | + | |
- | const nx = cx + dx;ย | + | |
- | const ny = cy + dy;ย | + | |
- | ย | + | |
- | if (nx >= 0 && nx < 19 && ny >= 0 && ny < 19) {ย | + | |
- | if (this.board[ny][nx] === color) {ย | + | |
- | stack.push([nx, | + | |
- | }ย | + | |
- | }ย | + | |
- | }ย | + | |
- | }ย | + | |
- | }ย | + | |
- | ย | + | |
- | return count;ย | + | |
- | }ย | + | |
- | }ย | + | |
- | </ | + | |
- | ย | + | |
- | ===== ๐ ๊ด๋ จ ๋ฌธ์ =====ย | + | |
- | ย | + | |
- | * [[wiki: | + | |
- | * [[wiki: | + | |
- | * [[wiki: | + | |
- | --- | ||
- | //์ด ํ์ด์ง๋ ์๋์ผ๋ก ์์ฑ๋์์ต๋๋ค.// |
wiki/it/dream_of_enc/metaverse/phaser.1753682235.txt.gz ยท ๋ง์ง๋ง์ผ๋ก ์์ ๋จ: ์ ์ 127.0.0.1