/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var GameSquare = Container.expand(function (row, col) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.occupied = false;
self.piece = null;
var square = self.attachAsset('gameSquare', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1
});
self.down = function (x, y, obj) {
if (!self.occupied && !gameEnded) {
self.placePiece(currentPlayer);
LK.getSound('place').play();
if (checkWin()) {
endGame(currentPlayer + ' Wins!');
} else if (checkDraw()) {
endGame('Draw!');
} else {
switchPlayer();
}
}
};
self.placePiece = function (player) {
if (self.occupied) return;
self.occupied = true;
self.piece = player;
gameBoard[self.row][self.col] = player;
var pieceAsset = player === 'X' ? 'xPiece' : 'oPiece';
var piece = self.attachAsset(pieceAsset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0
});
tween(piece, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
};
self.reset = function () {
self.occupied = false;
self.piece = null;
// Remove piece graphics
for (var i = self.children.length - 1; i >= 0; i--) {
var child = self.children[i];
if (child !== square) {
self.removeChild(child);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xffffff
});
/****
* Game Code
****/
// Game state variables
var gameBoard = [[null, null, null], [null, null, null], [null, null, null]];
var currentPlayer = 'X';
var gameEnded = false;
var squares = [];
// Player data and leaderboard
var playerName = storage.playerName || 'Player';
var playerWins = storage.playerWins || 0;
var playerLosses = storage.playerLosses || 0;
var showingNameInput = false;
// Create decorative background
var bgDecor1 = game.addChild(LK.getAsset('backgroundDecor', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: 500,
alpha: 0.1,
scaleX: 1.5,
scaleY: 1.5
}));
var bgDecor2 = game.addChild(LK.getAsset('backgroundDecor', {
anchorX: 0.5,
anchorY: 0.5,
x: 1600,
y: 1800,
alpha: 0.1,
scaleX: 2,
scaleY: 2
}));
// Create game grid container
var gridContainer = game.addChild(new Container());
gridContainer.x = 2048 / 2;
gridContainer.y = 2732 / 2;
// Create grid squares
for (var row = 0; row < 3; row++) {
squares[row] = [];
for (var col = 0; col < 3; col++) {
var square = gridContainer.addChild(new GameSquare(row, col));
square.x = (col - 1) * 200;
square.y = (row - 1) * 200;
squares[row][col] = square;
}
;
}
// Create grid lines
// Vertical lines
var vLine1 = gridContainer.addChild(LK.getAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: -100,
y: 0
}));
var vLine2 = gridContainer.addChild(LK.getAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 100,
y: 0
}));
// Horizontal lines
var hLine1 = gridContainer.addChild(LK.getAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -100,
rotation: Math.PI / 2
}));
var hLine2 = gridContainer.addChild(LK.getAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 100,
rotation: Math.PI / 2
}));
// Create UI elements
var currentPlayerText = new Text2('Your Turn', {
size: 80,
fill: 0x333333
});
currentPlayerText.anchor.set(0.5, 0);
LK.gui.top.addChild(currentPlayerText);
currentPlayerText.y = 200;
var gameStatusText = new Text2('', {
size: 100,
fill: 0xFF4444
});
gameStatusText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(gameStatusText);
gameStatusText.y = -400;
var restartButton = new Text2('Restart Game', {
size: 60,
fill: 0x4444FF
});
restartButton.anchor.set(0.5, 1);
LK.gui.bottom.addChild(restartButton);
restartButton.y = -100;
// Player name display
var playerNameText = new Text2('Player: ' + playerName, {
size: 50,
fill: 0x333333
});
playerNameText.anchor.set(0, 0);
LK.gui.topRight.addChild(playerNameText);
playerNameText.x = -300;
playerNameText.y = 150;
// Leaderboard display
var leaderboardText = new Text2('Wins: ' + playerWins + ' | Losses: ' + playerLosses, {
size: 40,
fill: 0x666666
});
leaderboardText.anchor.set(0, 0);
LK.gui.topRight.addChild(leaderboardText);
leaderboardText.x = -300;
leaderboardText.y = 200;
// Change name button
var changeNameButton = new Text2('Change Name', {
size: 40,
fill: 0x4444FF
});
changeNameButton.anchor.set(0, 0);
LK.gui.topRight.addChild(changeNameButton);
changeNameButton.x = -300;
changeNameButton.y = 250;
// Name input overlay (initially hidden)
var nameInputOverlay = new Container();
nameInputOverlay.visible = false;
LK.gui.center.addChild(nameInputOverlay);
var nameInputBg = nameInputOverlay.addChild(LK.getAsset('gameSquare', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 2,
alpha: 0.9
}));
var nameInputPrompt = new Text2('Enter your name:', {
size: 60,
fill: 0x333333
});
nameInputPrompt.anchor.set(0.5, 0.5);
nameInputOverlay.addChild(nameInputPrompt);
nameInputPrompt.y = -80;
var currentNameInput = new Text2(playerName, {
size: 80,
fill: 0x000000
});
currentNameInput.anchor.set(0.5, 0.5);
nameInputOverlay.addChild(currentNameInput);
currentNameInput.y = 0;
var nameConfirmButton = new Text2('Confirm', {
size: 50,
fill: 0x44FF44
});
nameConfirmButton.anchor.set(0.5, 0.5);
nameInputOverlay.addChild(nameConfirmButton);
nameConfirmButton.y = 80;
// Game functions
function switchPlayer() {
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
if (currentPlayer === 'X') {
currentPlayerText.setText('Your Turn');
} else {
currentPlayerText.setText('AI Turn');
}
// If it's AI's turn (O), make AI move after a short delay
if (currentPlayer === 'O' && !gameEnded) {
LK.setTimeout(function () {
makeAIMove();
}, 500);
}
}
function checkWin() {
// Check rows
for (var i = 0; i < 3; i++) {
if (gameBoard[i][0] && gameBoard[i][0] === gameBoard[i][1] && gameBoard[i][1] === gameBoard[i][2]) {
return true;
}
}
// Check columns
for (var j = 0; j < 3; j++) {
if (gameBoard[0][j] && gameBoard[0][j] === gameBoard[1][j] && gameBoard[1][j] === gameBoard[2][j]) {
return true;
}
}
// Check diagonals
if (gameBoard[0][0] && gameBoard[0][0] === gameBoard[1][1] && gameBoard[1][1] === gameBoard[2][2]) {
return true;
}
if (gameBoard[0][2] && gameBoard[0][2] === gameBoard[1][1] && gameBoard[1][1] === gameBoard[2][0]) {
return true;
}
return false;
}
function checkDraw() {
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (!gameBoard[i][j]) {
return false;
}
}
}
return true;
}
function endGame(message) {
gameEnded = true;
var displayMessage = message;
if (message === 'X Wins!') {
displayMessage = 'You Win!';
playerWins++;
storage.playerWins = playerWins;
} else if (message === 'O Wins!' || message === 'AI Wins!') {
displayMessage = 'AI Wins!';
playerLosses++;
storage.playerLosses = playerLosses;
}
// Update leaderboard display
leaderboardText.setText('Wins: ' + playerWins + ' | Losses: ' + playerLosses);
gameStatusText.setText(displayMessage);
currentPlayerText.setText('Game Over');
if (message.indexOf('Wins') !== -1) {
LK.getSound('win').play();
if (message === 'X Wins!') {
LK.effects.flashScreen(0x44ff44, 500);
} else {
LK.effects.flashScreen(0xff4444, 500);
}
}
tween(gameStatusText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.easeOut
});
}
function makeAIMove() {
if (gameEnded) return;
// First, try to win
var winMove = findWinningMove('O');
if (winMove) {
squares[winMove.row][winMove.col].placePiece('O');
LK.getSound('place').play();
if (checkWin()) {
endGame('AI Wins!');
return;
} else if (checkDraw()) {
endGame('Draw!');
return;
} else {
switchPlayer();
}
return;
}
// Then, try to block player from winning
var blockMove = findWinningMove('X');
if (blockMove) {
squares[blockMove.row][blockMove.col].placePiece('O');
LK.getSound('place').play();
if (checkWin()) {
endGame('AI Wins!');
return;
} else if (checkDraw()) {
endGame('Draw!');
return;
} else {
switchPlayer();
}
return;
}
// Strategic AI: prioritize center, then corners, then edges
var bestMove = null;
// Try to take center if available
if (!gameBoard[1][1]) {
bestMove = {
row: 1,
col: 1
};
} else {
// Try corners first
var corners = [{
row: 0,
col: 0
}, {
row: 0,
col: 2
}, {
row: 2,
col: 0
}, {
row: 2,
col: 2
}];
for (var i = 0; i < corners.length; i++) {
if (!gameBoard[corners[i].row][corners[i].col]) {
bestMove = corners[i];
break;
}
}
}
// If no strategic move found, try edges or any available move
if (!bestMove) {
var availableMoves = [];
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (!gameBoard[i][j]) {
availableMoves.push({
row: i,
col: j
});
}
}
}
if (availableMoves.length > 0) {
bestMove = availableMoves[Math.floor(Math.random() * availableMoves.length)];
}
}
if (bestMove) {
squares[bestMove.row][bestMove.col].placePiece('O');
LK.getSound('place').play();
if (checkWin()) {
endGame('AI Wins!');
return;
} else if (checkDraw()) {
endGame('Draw!');
return;
} else {
switchPlayer();
}
}
}
function findWinningMove(player) {
// Check all empty squares to see if placing the player's piece would win
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (!gameBoard[i][j]) {
// Temporarily place the piece
gameBoard[i][j] = player;
var isWin = checkWin();
// Remove the temporary piece
gameBoard[i][j] = null;
if (isWin) {
return {
row: i,
col: j
};
}
}
}
}
return null;
}
function resetGame() {
gameEnded = false;
currentPlayer = 'X';
// Reset board array
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
gameBoard[i][j] = null;
}
}
// Reset squares
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
squares[row][col].reset();
}
}
// Reset UI
currentPlayerText.setText('Your Turn');
gameStatusText.setText('');
gameStatusText.scaleX = 1;
gameStatusText.scaleY = 1;
}
// Restart button event
restartButton.down = function (x, y, obj) {
resetGame();
LK.getSound('place').play();
};
// Change name button event
changeNameButton.down = function (x, y, obj) {
if (!showingNameInput && !gameEnded) {
showingNameInput = true;
nameInputOverlay.visible = true;
currentNameInput.setText(playerName);
LK.getSound('place').play();
}
};
// Name confirm button event
nameConfirmButton.down = function (x, y, obj) {
var currentText = currentNameInput.getText ? currentNameInput.getText() : '';
var newName = currentText.trim();
if (newName.length > 0 && newName.length <= 15) {
playerName = newName;
storage.playerName = playerName;
playerNameText.setText('Player: ' + playerName);
showingNameInput = false;
nameInputOverlay.visible = false;
LK.getSound('place').play();
}
};
// Simple name input system
var nameChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ';
var currentCharIndex = 0;
// Name input navigation (tap to cycle through characters)
currentNameInput.down = function (x, y, obj) {
if (showingNameInput) {
currentCharIndex = (currentCharIndex + 1) % nameChars.length;
var currentName = currentNameInput.getText ? currentNameInput.getText() : '';
if (currentName.length < 15) {
currentNameInput.setText(currentName + nameChars[currentCharIndex]);
}
LK.getSound('place').play();
}
};
// Backspace functionality - tap background to remove last character
nameInputBg.down = function (x, y, obj) {
if (showingNameInput) {
var currentName = currentNameInput.getText ? currentNameInput.getText() : '';
if (currentName.length > 0) {
currentNameInput.setText(currentName.slice(0, -1));
LK.getSound('place').play();
}
}
};
// Add subtle animation to background elements
game.update = function () {
if (LK.ticks % 300 === 0) {
tween(bgDecor1, {
rotation: bgDecor1.rotation + 0.1
}, {
duration: 3000,
easing: tween.linear
});
}
if (LK.ticks % 400 === 0) {
tween(bgDecor2, {
rotation: bgDecor2.rotation - 0.08
}, {
duration: 4000,
easing: tween.linear
});
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var GameSquare = Container.expand(function (row, col) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.occupied = false;
self.piece = null;
var square = self.attachAsset('gameSquare', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1
});
self.down = function (x, y, obj) {
if (!self.occupied && !gameEnded) {
self.placePiece(currentPlayer);
LK.getSound('place').play();
if (checkWin()) {
endGame(currentPlayer + ' Wins!');
} else if (checkDraw()) {
endGame('Draw!');
} else {
switchPlayer();
}
}
};
self.placePiece = function (player) {
if (self.occupied) return;
self.occupied = true;
self.piece = player;
gameBoard[self.row][self.col] = player;
var pieceAsset = player === 'X' ? 'xPiece' : 'oPiece';
var piece = self.attachAsset(pieceAsset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0
});
tween(piece, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
};
self.reset = function () {
self.occupied = false;
self.piece = null;
// Remove piece graphics
for (var i = self.children.length - 1; i >= 0; i--) {
var child = self.children[i];
if (child !== square) {
self.removeChild(child);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xffffff
});
/****
* Game Code
****/
// Game state variables
var gameBoard = [[null, null, null], [null, null, null], [null, null, null]];
var currentPlayer = 'X';
var gameEnded = false;
var squares = [];
// Player data and leaderboard
var playerName = storage.playerName || 'Player';
var playerWins = storage.playerWins || 0;
var playerLosses = storage.playerLosses || 0;
var showingNameInput = false;
// Create decorative background
var bgDecor1 = game.addChild(LK.getAsset('backgroundDecor', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: 500,
alpha: 0.1,
scaleX: 1.5,
scaleY: 1.5
}));
var bgDecor2 = game.addChild(LK.getAsset('backgroundDecor', {
anchorX: 0.5,
anchorY: 0.5,
x: 1600,
y: 1800,
alpha: 0.1,
scaleX: 2,
scaleY: 2
}));
// Create game grid container
var gridContainer = game.addChild(new Container());
gridContainer.x = 2048 / 2;
gridContainer.y = 2732 / 2;
// Create grid squares
for (var row = 0; row < 3; row++) {
squares[row] = [];
for (var col = 0; col < 3; col++) {
var square = gridContainer.addChild(new GameSquare(row, col));
square.x = (col - 1) * 200;
square.y = (row - 1) * 200;
squares[row][col] = square;
}
;
}
// Create grid lines
// Vertical lines
var vLine1 = gridContainer.addChild(LK.getAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: -100,
y: 0
}));
var vLine2 = gridContainer.addChild(LK.getAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 100,
y: 0
}));
// Horizontal lines
var hLine1 = gridContainer.addChild(LK.getAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -100,
rotation: Math.PI / 2
}));
var hLine2 = gridContainer.addChild(LK.getAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 100,
rotation: Math.PI / 2
}));
// Create UI elements
var currentPlayerText = new Text2('Your Turn', {
size: 80,
fill: 0x333333
});
currentPlayerText.anchor.set(0.5, 0);
LK.gui.top.addChild(currentPlayerText);
currentPlayerText.y = 200;
var gameStatusText = new Text2('', {
size: 100,
fill: 0xFF4444
});
gameStatusText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(gameStatusText);
gameStatusText.y = -400;
var restartButton = new Text2('Restart Game', {
size: 60,
fill: 0x4444FF
});
restartButton.anchor.set(0.5, 1);
LK.gui.bottom.addChild(restartButton);
restartButton.y = -100;
// Player name display
var playerNameText = new Text2('Player: ' + playerName, {
size: 50,
fill: 0x333333
});
playerNameText.anchor.set(0, 0);
LK.gui.topRight.addChild(playerNameText);
playerNameText.x = -300;
playerNameText.y = 150;
// Leaderboard display
var leaderboardText = new Text2('Wins: ' + playerWins + ' | Losses: ' + playerLosses, {
size: 40,
fill: 0x666666
});
leaderboardText.anchor.set(0, 0);
LK.gui.topRight.addChild(leaderboardText);
leaderboardText.x = -300;
leaderboardText.y = 200;
// Change name button
var changeNameButton = new Text2('Change Name', {
size: 40,
fill: 0x4444FF
});
changeNameButton.anchor.set(0, 0);
LK.gui.topRight.addChild(changeNameButton);
changeNameButton.x = -300;
changeNameButton.y = 250;
// Name input overlay (initially hidden)
var nameInputOverlay = new Container();
nameInputOverlay.visible = false;
LK.gui.center.addChild(nameInputOverlay);
var nameInputBg = nameInputOverlay.addChild(LK.getAsset('gameSquare', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 2,
alpha: 0.9
}));
var nameInputPrompt = new Text2('Enter your name:', {
size: 60,
fill: 0x333333
});
nameInputPrompt.anchor.set(0.5, 0.5);
nameInputOverlay.addChild(nameInputPrompt);
nameInputPrompt.y = -80;
var currentNameInput = new Text2(playerName, {
size: 80,
fill: 0x000000
});
currentNameInput.anchor.set(0.5, 0.5);
nameInputOverlay.addChild(currentNameInput);
currentNameInput.y = 0;
var nameConfirmButton = new Text2('Confirm', {
size: 50,
fill: 0x44FF44
});
nameConfirmButton.anchor.set(0.5, 0.5);
nameInputOverlay.addChild(nameConfirmButton);
nameConfirmButton.y = 80;
// Game functions
function switchPlayer() {
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
if (currentPlayer === 'X') {
currentPlayerText.setText('Your Turn');
} else {
currentPlayerText.setText('AI Turn');
}
// If it's AI's turn (O), make AI move after a short delay
if (currentPlayer === 'O' && !gameEnded) {
LK.setTimeout(function () {
makeAIMove();
}, 500);
}
}
function checkWin() {
// Check rows
for (var i = 0; i < 3; i++) {
if (gameBoard[i][0] && gameBoard[i][0] === gameBoard[i][1] && gameBoard[i][1] === gameBoard[i][2]) {
return true;
}
}
// Check columns
for (var j = 0; j < 3; j++) {
if (gameBoard[0][j] && gameBoard[0][j] === gameBoard[1][j] && gameBoard[1][j] === gameBoard[2][j]) {
return true;
}
}
// Check diagonals
if (gameBoard[0][0] && gameBoard[0][0] === gameBoard[1][1] && gameBoard[1][1] === gameBoard[2][2]) {
return true;
}
if (gameBoard[0][2] && gameBoard[0][2] === gameBoard[1][1] && gameBoard[1][1] === gameBoard[2][0]) {
return true;
}
return false;
}
function checkDraw() {
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (!gameBoard[i][j]) {
return false;
}
}
}
return true;
}
function endGame(message) {
gameEnded = true;
var displayMessage = message;
if (message === 'X Wins!') {
displayMessage = 'You Win!';
playerWins++;
storage.playerWins = playerWins;
} else if (message === 'O Wins!' || message === 'AI Wins!') {
displayMessage = 'AI Wins!';
playerLosses++;
storage.playerLosses = playerLosses;
}
// Update leaderboard display
leaderboardText.setText('Wins: ' + playerWins + ' | Losses: ' + playerLosses);
gameStatusText.setText(displayMessage);
currentPlayerText.setText('Game Over');
if (message.indexOf('Wins') !== -1) {
LK.getSound('win').play();
if (message === 'X Wins!') {
LK.effects.flashScreen(0x44ff44, 500);
} else {
LK.effects.flashScreen(0xff4444, 500);
}
}
tween(gameStatusText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.easeOut
});
}
function makeAIMove() {
if (gameEnded) return;
// First, try to win
var winMove = findWinningMove('O');
if (winMove) {
squares[winMove.row][winMove.col].placePiece('O');
LK.getSound('place').play();
if (checkWin()) {
endGame('AI Wins!');
return;
} else if (checkDraw()) {
endGame('Draw!');
return;
} else {
switchPlayer();
}
return;
}
// Then, try to block player from winning
var blockMove = findWinningMove('X');
if (blockMove) {
squares[blockMove.row][blockMove.col].placePiece('O');
LK.getSound('place').play();
if (checkWin()) {
endGame('AI Wins!');
return;
} else if (checkDraw()) {
endGame('Draw!');
return;
} else {
switchPlayer();
}
return;
}
// Strategic AI: prioritize center, then corners, then edges
var bestMove = null;
// Try to take center if available
if (!gameBoard[1][1]) {
bestMove = {
row: 1,
col: 1
};
} else {
// Try corners first
var corners = [{
row: 0,
col: 0
}, {
row: 0,
col: 2
}, {
row: 2,
col: 0
}, {
row: 2,
col: 2
}];
for (var i = 0; i < corners.length; i++) {
if (!gameBoard[corners[i].row][corners[i].col]) {
bestMove = corners[i];
break;
}
}
}
// If no strategic move found, try edges or any available move
if (!bestMove) {
var availableMoves = [];
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (!gameBoard[i][j]) {
availableMoves.push({
row: i,
col: j
});
}
}
}
if (availableMoves.length > 0) {
bestMove = availableMoves[Math.floor(Math.random() * availableMoves.length)];
}
}
if (bestMove) {
squares[bestMove.row][bestMove.col].placePiece('O');
LK.getSound('place').play();
if (checkWin()) {
endGame('AI Wins!');
return;
} else if (checkDraw()) {
endGame('Draw!');
return;
} else {
switchPlayer();
}
}
}
function findWinningMove(player) {
// Check all empty squares to see if placing the player's piece would win
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (!gameBoard[i][j]) {
// Temporarily place the piece
gameBoard[i][j] = player;
var isWin = checkWin();
// Remove the temporary piece
gameBoard[i][j] = null;
if (isWin) {
return {
row: i,
col: j
};
}
}
}
}
return null;
}
function resetGame() {
gameEnded = false;
currentPlayer = 'X';
// Reset board array
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
gameBoard[i][j] = null;
}
}
// Reset squares
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
squares[row][col].reset();
}
}
// Reset UI
currentPlayerText.setText('Your Turn');
gameStatusText.setText('');
gameStatusText.scaleX = 1;
gameStatusText.scaleY = 1;
}
// Restart button event
restartButton.down = function (x, y, obj) {
resetGame();
LK.getSound('place').play();
};
// Change name button event
changeNameButton.down = function (x, y, obj) {
if (!showingNameInput && !gameEnded) {
showingNameInput = true;
nameInputOverlay.visible = true;
currentNameInput.setText(playerName);
LK.getSound('place').play();
}
};
// Name confirm button event
nameConfirmButton.down = function (x, y, obj) {
var currentText = currentNameInput.getText ? currentNameInput.getText() : '';
var newName = currentText.trim();
if (newName.length > 0 && newName.length <= 15) {
playerName = newName;
storage.playerName = playerName;
playerNameText.setText('Player: ' + playerName);
showingNameInput = false;
nameInputOverlay.visible = false;
LK.getSound('place').play();
}
};
// Simple name input system
var nameChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ';
var currentCharIndex = 0;
// Name input navigation (tap to cycle through characters)
currentNameInput.down = function (x, y, obj) {
if (showingNameInput) {
currentCharIndex = (currentCharIndex + 1) % nameChars.length;
var currentName = currentNameInput.getText ? currentNameInput.getText() : '';
if (currentName.length < 15) {
currentNameInput.setText(currentName + nameChars[currentCharIndex]);
}
LK.getSound('place').play();
}
};
// Backspace functionality - tap background to remove last character
nameInputBg.down = function (x, y, obj) {
if (showingNameInput) {
var currentName = currentNameInput.getText ? currentNameInput.getText() : '';
if (currentName.length > 0) {
currentNameInput.setText(currentName.slice(0, -1));
LK.getSound('place').play();
}
}
};
// Add subtle animation to background elements
game.update = function () {
if (LK.ticks % 300 === 0) {
tween(bgDecor1, {
rotation: bgDecor1.rotation + 0.1
}, {
duration: 3000,
easing: tween.linear
});
}
if (LK.ticks % 400 === 0) {
tween(bgDecor2, {
rotation: bgDecor2.rotation - 0.08
}, {
duration: 4000,
easing: tween.linear
});
}
};