/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Cell = Container.expand(function () {
var self = Container.call(this);
var cellBg = self.attachAsset('cell', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
self.row = 0;
self.col = 0;
self.value = 0; // 0 = empty, 1 = X, 2 = O
self.marker = null;
self.highlight = function () {
tween(cellBg, {
alpha: 1
}, {
duration: 200
});
};
self.unhighlight = function () {
tween(cellBg, {
alpha: 0.8
}, {
duration: 200
});
};
self.setMarker = function (playerValue) {
if (self.value !== 0) {
return false;
}
self.value = playerValue;
if (playerValue === 1) {
self.marker = self.attachAsset('x_marker', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
} else {
self.marker = self.attachAsset('o_marker', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
}
tween(self.marker, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
return true;
};
self.reset = function () {
self.value = 0;
if (self.marker) {
tween(self.marker, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
if (self.marker) {
self.marker.destroy();
self.marker = null;
}
}
});
}
};
self.down = function (x, y, obj) {
if (gameState === STATE_PLAYER_TURN && self.value === 0 && (isTwoPlayerMode || currentPlayer === 1)) {
if (self.setMarker(currentPlayer)) {
LK.getSound('place').play();
checkGameState();
if (gameState === STATE_PLAYER_TURN) {
// Game continues, switch player
currentPlayer = currentPlayer === 1 ? 2 : 1;
updateTurnIndicator();
}
}
}
};
return self;
});
var WinLine = Container.expand(function () {
var self = Container.call(this);
var line = self.attachAsset('board_bg', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0,
tint: 0x00ff00
});
line.width = 800;
line.height = 20;
self.showLine = function (startX, startY, endX, endY) {
self.x = (startX + endX) / 2;
self.y = (startY + endY) / 2;
// Calculate rotation and length
var dx = endX - startX;
var dy = endY - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
var angle = Math.atan2(dy, dx);
line.width = distance;
line.rotation = angle;
tween(line, {
alpha: 0.7
}, {
duration: 500
});
};
self.hide = function () {
tween(line, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x004488
});
/****
* Game Code
****/
// Game constants
var AIPlayer = function AIPlayer() {
this.makeMove = function () {
if (gameState !== STATE_PLAYER_TURN) {
return;
}
// Simple AI: choose the first available cell
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (gameBoard[row][col].value === 0) {
gameBoard[row][col].setMarker(currentPlayer);
LK.getSound('place').play();
checkGameState();
if (gameState === STATE_PLAYER_TURN) {
currentPlayer = currentPlayer === 1 ? 2 : 1;
updateTurnIndicator();
}
return;
}
}
}
};
};
var GRID_SIZE = 4;
var CELL_SIZE = 180;
var CELL_SPACING = 10;
var BOARD_SIZE = CELL_SIZE * GRID_SIZE + CELL_SPACING * (GRID_SIZE - 1);
// Game states
var STATE_PLAYER_TURN = 0;
var STATE_GAME_OVER = 1;
// AI player
var aiPlayer = new AIPlayer();
var gameBoard = [];
var gameState = STATE_PLAYER_TURN;
var currentPlayer = 1; // 1 = X, 2 = O
var isTwoPlayerMode = true; // Toggle for two player mode
var winningCombos = [];
// GUI elements
var turnIndicator;
var gameOverText;
// Create board background
var boardBg = LK.getAsset('board_bg', {
anchorX: 0.5,
anchorY: 0.5,
width: BOARD_SIZE + 40,
height: BOARD_SIZE + 40
});
boardBg.x = 2048 / 2;
boardBg.y = 2732 / 2;
game.addChild(boardBg);
// Initialize turn indicator
turnIndicator = new Text2('X\'s Turn', {
size: 80,
fill: 0xFFFFFF
});
turnIndicator.anchor.set(0.5, 0);
LK.gui.top.addChild(turnIndicator);
turnIndicator.y = 100;
// Initialize game over text (hidden initially)
gameOverText = new Text2('', {
size: 100,
fill: 0xFFFFFF
});
gameOverText.anchor.set(0.5, 0.5);
gameOverText.visible = false;
LK.gui.center.addChild(gameOverText);
function initializeBoard() {
// Clear any existing board
if (gameBoard.length > 0) {
for (var i = 0; i < gameBoard.length; i++) {
for (var j = 0; j < gameBoard[i].length; j++) {
if (gameBoard[i][j]) {
gameBoard[i][j].destroy();
}
}
}
}
// Create new board
gameBoard = [];
var startX = 2048 / 2 - BOARD_SIZE / 2 + CELL_SIZE / 2;
var startY = 2732 / 2 - BOARD_SIZE / 2 + CELL_SIZE / 2;
for (var row = 0; row < GRID_SIZE; row++) {
gameBoard[row] = [];
for (var col = 0; col < GRID_SIZE; col++) {
var cell = new Cell();
cell.row = row;
cell.col = col;
cell.x = startX + col * (CELL_SIZE + CELL_SPACING);
cell.y = startY + row * (CELL_SIZE + CELL_SPACING);
gameBoard[row][col] = cell;
game.addChild(cell);
}
}
// Define winning combinations
defineWinningCombinations();
}
function defineWinningCombinations() {
winningCombos = [];
// Rows
for (var row = 0; row < GRID_SIZE; row++) {
winningCombos.push([{
row: row,
col: 0
}, {
row: row,
col: 1
}, {
row: row,
col: 2
}, {
row: row,
col: 3
}]);
}
// Columns
for (var col = 0; col < GRID_SIZE; col++) {
winningCombos.push([{
row: 0,
col: col
}, {
row: 1,
col: col
}, {
row: 2,
col: col
}, {
row: 3,
col: col
}]);
}
// Diagonals
winningCombos.push([{
row: 0,
col: 0
}, {
row: 1,
col: 1
}, {
row: 2,
col: 2
}, {
row: 3,
col: 3
}]);
winningCombos.push([{
row: 0,
col: 3
}, {
row: 1,
col: 2
}, {
row: 2,
col: 1
}, {
row: 3,
col: 0
}]);
}
function checkGameState() {
// Check for win
var winResult = checkForWin();
if (winResult) {
gameState = STATE_GAME_OVER;
showWinLine(winResult.combo);
updateGameOverText(currentPlayer === 1 ? "X Wins!" : "O Wins!");
LK.getSound('win').play();
LK.setScore(LK.getScore() + 1);
return;
}
// Check for draw
if (checkForDraw()) {
gameState = STATE_GAME_OVER;
updateGameOverText("Draw!");
LK.getSound('draw').play();
return;
}
}
function checkForWin() {
for (var i = 0; i < winningCombos.length; i++) {
var combo = winningCombos[i];
var first = gameBoard[combo[0].row][combo[0].col].value;
if (first !== 0) {
var isWin = true;
for (var j = 1; j < combo.length; j++) {
if (gameBoard[combo[j].row][combo[j].col].value !== first) {
isWin = false;
break;
}
}
if (isWin) {
return {
player: first,
combo: combo
};
}
}
}
return null;
}
function checkForDraw() {
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
if (gameBoard[row][col].value === 0) {
return false; // Still empty cells
}
}
}
return true;
}
function showWinLine(combo) {
var startCell = gameBoard[combo[0].row][combo[0].col];
var endCell = gameBoard[combo[combo.length - 1].row][combo[combo.length - 1].col];
var winLine = new WinLine();
game.addChild(winLine);
winLine.showLine(startCell.x, startCell.y, endCell.x, endCell.y);
}
function updateTurnIndicator() {
turnIndicator.setText(currentPlayer === 1 ? "X's Turn" : "O's Turn");
}
function updateGameOverText(text) {
gameOverText.setText(text);
gameOverText.visible = true;
// Show restart button after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
}
function restartGame() {
// Reset game state
gameState = STATE_PLAYER_TURN;
currentPlayer = 1;
// Reset board
for (var row = 0; row < GRID_SIZE; row++) {
for (var col = 0; col < GRID_SIZE; col++) {
gameBoard[row][col].reset();
}
}
// Update UI
updateTurnIndicator();
gameOverText.visible = false;
}
// Game setup
initializeBoard();
updateTurnIndicator();
// Play background music
LK.playMusic('bgmusic', {
loop: true,
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
// Game main loop
game.update = function () {
// This is called every frame
if (!isTwoPlayerMode && currentPlayer === 2 && gameState === STATE_PLAYER_TURN) {
aiPlayer.makeMove();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -76,9 +76,9 @@
});
}
};
self.down = function (x, y, obj) {
- if (gameState === STATE_PLAYER_TURN && self.value === 0) {
+ if (gameState === STATE_PLAYER_TURN && self.value === 0 && (isTwoPlayerMode || currentPlayer === 1)) {
if (self.setMarker(currentPlayer)) {
LK.getSound('place').play();
checkGameState();
if (gameState === STATE_PLAYER_TURN) {
@@ -174,8 +174,9 @@
var aiPlayer = new AIPlayer();
var gameBoard = [];
var gameState = STATE_PLAYER_TURN;
var currentPlayer = 1; // 1 = X, 2 = O
+var isTwoPlayerMode = true; // Toggle for two player mode
var winningCombos = [];
// GUI elements
var turnIndicator;
var gameOverText;
@@ -394,8 +395,8 @@
});
// Game main loop
game.update = function () {
// This is called every frame
- if (currentPlayer === 2 && gameState === STATE_PLAYER_TURN) {
+ if (!isTwoPlayerMode && currentPlayer === 2 && gameState === STATE_PLAYER_TURN) {
aiPlayer.makeMove();
}
};
\ No newline at end of file