export class TicTacToe { gamestate_variable = 'gamestate'; layer_moves = 'moves'; layer_overlay = 'overlay'; layer_game = 'game'; layer_blue = 'blue'; layer_green = 'green'; layer_board = 'board'; layer_exit = 'exit'; popup = 'popup'; board_x = 4; board_y = 3; blue_x = 3; blue_y = 2; green_x = 3; green_y = 6; gamestate = {}; is_player = false; on_board = false; on_game = false; welcome = false; move_message; color; game_message; constructor(config) { this.gamestate_variable = config.gamestate_variable || 'gamestate'; this.layer_moves = config.layer_moves || 'moves'; this.layer_overlay = config.layer_overlay || 'overlay'; this.layer_game = config.layer_game || 'game'; this.layer_blue = config.layer_blue || 'blue'; this.layer_green = config.layer_green || 'green'; this.layer_board = config.layer_board || 'board'; this.layer_exit = config.layer_exit || 'exit'; this.popup = config.popup || 'popup'; this.board_x = config.board_x || 4; this.board_y = config.board_y || 3; this.blue_x = config.blue_x || 3; this.blue_y = config.blue_y || 2; this.green_x = config.green_x || 3; this.green_y = config.green_y || 6; WA.onInit().then(() => { this.waInit(); }); } applyGameState = function () { this.is_player = false; this.color = ''; if (this.gamestate.blue) { if (this.gamestate.blue == WA.player.id) { this.color = 'blue'; this.is_player = true; } WA.room.setTiles([ { x: this.blue_x, y: this.blue_y, tile: null, layer: this.layer_blue } ]); } else { WA.room.setTiles([ { x: this.blue_x, y: this.blue_y, tile: 'blue', layer: this.layer_blue } ]); } if (this.gamestate.green) { if (this.gamestate.green == WA.player.id) { this.color = 'green'; this.is_player = true; } WA.room.setTiles([ { x: this.green_x, y: this.green_y, tile: null, layer: this.layer_green } ]); } else { WA.room.setTiles([ { x: this.green_x, y: this.green_y, tile: 'green', layer: this.layer_green } ]); } for (let x = 0; x < 3; x++) { for (let y = 0; y < 3; y++) { let index = x + y * 3; if (this.gamestate.board && this.gamestate.board[index]) { if (this.gamestate.board[index] == 'blue' || this.gamestate.board[index] == 'green') { WA.room.setTiles([ { x: this.board_x + x, y: this.board_y + y, tile: this.gamestate.board[index], layer: this.layer_moves } ]); } } else { WA.room.setTiles([ { x: this.board_x + x, y: this.board_y + y, tile: null, layer: this.layer_moves } ]); } } } if (this.gamestate.win) { let win_text = this.gamestate.win_name + ' wins!'; if (this.is_player) { if (this.gamestate.win_player == WA.player.id) { win_text = 'You win!' } else { win_text = 'You loose! ' + win_text; } this.newGame(); } this.game_message = WA.ui.openPopup(this.popup, win_text, [{ label: 'New Game', className: '', callback: (popup) => { popup.close(); } }]); } else if (this.gamestate.deuce) { if (this.is_player) { this.newGame(); } this.game_message = WA.ui.openPopup(this.popup, 'Deuce!', [{ label: 'New Game', className: '', callback: (popup) => { popup.close(); } }]); } } newGame = function () { this.gamestate = {}; WA.state.saveVariable(this.gamestate_variable, this.gamestate); } waInit = function () { this.gamestate = WA.state.loadVariable(this.gamestate_variable) || {}; this.applyGameState(); WA.state.onVariableChange(this.gamestate_variable).subscribe((value) => { console.log("gamestate", value); this.gamestate = value || {}; this.applyGameState(); }); WA.room.onEnterLayer(this.layer_game).subscribe(() => { this.on_game = true; if (!this.welcome && !this.is_player && (!this.gamestate.blue || !this.gamestate.green)) { this.welcome = true; let pickText = 'Pick a color to start game.'; if (this.gamestate.blue) { pickText = 'Pick green to join game.'; } else if (this.gamestate.green) { pickText = 'Pick blue to join game.'; } this.game_message = WA.ui.openPopup(this.popup, pickText, [{ label: 'Ok', className: '', callback: (popup) => { popup.close(); this.game_message = null; } }]); } }); WA.room.onLeaveLayer(this.layer_game).subscribe(() => { if (this.game_message) { this.game_message.close(); this.game_message = null; } }) WA.room.onEnterLayer(this.layer_exit).subscribe(() => { if (this.is_player && this.on_game) { this.newGame(); } this.welcome = false; }); WA.room.onEnterLayer(this.layer_blue).subscribe(() => { if (!this.gamestate.green || this.gamestate.green != WA.player.id) { this.gamestate.blue = WA.player.id; if (this.game_message) { this.game_message.close(); this.game_message = null; } if (this.gamestate.green) { this.gamestate.current = this.gamestate.green; } WA.state.saveVariable(this.gamestate_variable, this.gamestate); } }); WA.room.onEnterLayer(this.layer_green).subscribe(() => { if (!this.gamestate.blue || this.gamestate.blue != WA.player.id) { this.gamestate.green = WA.player.id; if (this.game_message) { this.game_message.close(); this.game_message = null; } if (this.gamestate.blue) { this.gamestate.current = this.gamestate.blue; } WA.state.saveVariable(this.gamestate_variable, this.gamestate); } }); WA.room.onEnterLayer(this.layer_board).subscribe(() => { this.on_board = true; }); WA.room.onLeaveLayer(this.layer_board).subscribe(() => { this.on_board = false; }); WA.player.onPlayerMove((event) => { if (this.on_board && WA.player.id) { for (let x = 0; x < 3; x++) { for (let y = 0; y < 3; y++) { WA.room.setTiles([ { x: this.board_x + x, y: this.board_y + y, tile: null, layer: this.layer_overlay } ]); } } if (!event.moving && this.on_board && this.gamestate.current == WA.player.id && !this.gamestate.win) { const x = Math.ceil(event.x / 32) - this.board_x - 1; const y = Math.ceil(event.y / 32) - this.board_y - 1; const index = x + y * 3; if (!this.gamestate.board) { this.gamestate.board = []; } if (index >= 0 && index < 9 && !this.gamestate.board[index]) { if (this.move_message) { this.move_message.remove(); } WA.room.setTiles([ { x: this.board_x + (index % 3), y: this.board_y + Math.floor(index / 3), tile: this.color + '_overlay', layer: this.layer_overlay } ]); this.move_message = WA.ui.displayActionMessage({ message: 'Press SPACE or touch here to place move', callback: () => { this.gamestate.board[index] = this.color; if (this.color == 'blue') { this.gamestate.current = this.gamestate.green; } else if (this.color == 'green') { this.gamestate.current = this.gamestate.blue; } var wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]] let win_move = false; for (var i = 0; i < wins.length; i++) { let win = wins[i]; let matches = 0; for (var j = 0; j < win.length; j++) { if (this.gamestate.board[win[j]] === this.color) { matches++ } } if (matches == 3) { win_move = true; break; } } if (win_move) { this.gamestate.win = true; this.gamestate.win_player = WA.player.id; this.gamestate.win_name = WA.player.name; this.gamestate.win_color = this.color; } if (!this.gamestate.win) { let moves = 0; for (let i = 0; i < 9; i++) { if (this.gamestate.board[i]) { moves++; } } if (moves == 9) { this.gamestate.deuce = true; } } WA.state.saveVariable(this.gamestate_variable, this.gamestate); } }); } } else if (this.move_message) { this.move_message.remove(); } } }); } }