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
