/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // BoardCell: Represents a single cell in the Tic Tac Toe grid var BoardCell = Container.expand(function () { var self = Container.call(this); // Cell highlight background (grikutu, hidden by default) var grikutuBg = self.attachAsset('grikutu', { anchorX: 0.5, anchorY: 0.5 }); grikutuBg.visible = false; self.addChild(grikutuBg); // Cell background (box) var cellBg = self.attachAsset('cellBg', { anchorX: 0.5, anchorY: 0.5 }); // Symbol image for X or O var xImage = LK.getAsset('x', { anchorX: 0.5, anchorY: 0.5 }); xImage.visible = false; self.addChild(xImage); var oImage = LK.getAsset('y', { anchorX: 0.5, anchorY: 0.5 }); oImage.visible = false; self.addChild(oImage); self.symbol = ''; // '', 'X', or 'O' self.row = 0; self.col = 0; self.isActive = true; // Can be tapped self.setSymbol = function (sym) { self.symbol = sym; if (sym === 'X') { grikutuBg.visible = true; xImage.visible = true; oImage.visible = false; } else if (sym === 'O') { grikutuBg.visible = true; xImage.visible = false; oImage.visible = true; } else { grikutuBg.visible = false; xImage.visible = false; oImage.visible = false; } }; self.clear = function () { self.symbol = ''; grikutuBg.visible = false; xImage.visible = false; oImage.visible = false; self.isActive = true; }; self.flash = function (color, duration) { tween(cellBg, { tint: color }, { duration: duration / 2, easing: tween.easeIn, onFinish: function onFinish() { tween(cellBg, { tint: 0xffffff }, { duration: duration / 2, easing: tween.easeOut }); } }); }; return self; }); // Health bar class var HealthBar = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('healthBarBg', { anchorX: 0.5, anchorY: 0.5 }); var bar = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0.5 }); self.set = function (val, max) { // Use the background width for dynamic sizing, and clamp value between 0 and max var percent = Math.max(0, Math.min(1, val / max)); bar.width = bg.width * percent; if (percent < 0.3) bar.tint = 0xff4444;else if (percent < 0.6) bar.tint = 0xffcc00;else bar.tint = 0x4caf50; }; self.set(1, 1); return self; }); /**** * Initialize Game ****/ // Create vikings var game = new LK.Game({ backgroundColor: 0xffffff }); /**** * Game Code ****/ // O symbol asset (green ellipse, could be replaced with image for stylized O) // X symbol asset (blue box, could be replaced with image for stylized X) // Cell background for Tic Tac Toe // Tic Tac Toe Game State var BOARD_SIZE = 3; var CELL_SIZE = 320; var CELL_MARGIN = 24; var board = []; var currentPlayer = 'X'; var gameActive = true; var statusText = new Text2('Sıra: X', { size: 110, fill: 0x333333 }); statusText.anchor.set(0.5, 0); LK.gui.top.addChild(statusText); // Center the board var boardWidth = BOARD_SIZE * CELL_SIZE + (BOARD_SIZE - 1) * CELL_MARGIN; var boardHeight = BOARD_SIZE * CELL_SIZE + (BOARD_SIZE - 1) * CELL_MARGIN; var boardOriginX = (2048 - boardWidth) / 2; var boardOriginY = (2732 - boardHeight) / 2 + 60; // Create board cells for (var row = 0; row < BOARD_SIZE; row++) { board[row] = []; for (var col = 0; col < BOARD_SIZE; col++) { var cell = new BoardCell(); cell.x = boardOriginX + col * (CELL_SIZE + CELL_MARGIN) + CELL_SIZE / 2; cell.y = boardOriginY + row * (CELL_SIZE + CELL_MARGIN) + CELL_SIZE / 2; cell.row = row; cell.col = col; cell.setSymbol(''); cell.isActive = true; // Cell tap handler cell.down = function (cell) { return function (x, y, obj) { if (!gameActive || !cell.isActive) return; cell.setSymbol(currentPlayer); cell.isActive = false; if (checkWin(currentPlayer)) { gameActive = false; statusText.setText('Kazanan: ' + currentPlayer); highlightWin(currentPlayer); LK.setTimeout(function () { LK.showYouWin(); }, 1200); } else if (isBoardFull()) { gameActive = false; statusText.setText('Berabere!'); LK.setTimeout(function () { LK.showGameOver(); }, 1200); } else { // If X just played, make a smart O move if game is still active if (currentPlayer === 'X') { currentPlayer = 'O'; statusText.setText('Sıra: O'); var oPlaced = false; // 1. Check for two Xs in a row with an empty cell next to them (horizontal) for (var r = 0; r < BOARD_SIZE && !oPlaced; r++) { for (var c = 0; c < BOARD_SIZE - 1 && !oPlaced; c++) { // X X _ if (board[r][c].symbol === 'X' && board[r][c + 1].symbol === 'X') { // Try to place O to the right if (c + 2 < BOARD_SIZE && board[r][c + 2].symbol === '') { board[r][c + 2].setSymbol('O'); board[r][c + 2].isActive = false; oPlaced = true; } // Try to place O to the left else if (c - 1 >= 0 && board[r][c - 1].symbol === '') { board[r][c - 1].setSymbol('O'); board[r][c - 1].isActive = false; oPlaced = true; } } } } // 2. Check for two Xs in a column with an empty cell next to them (vertical) for (var c = 0; c < BOARD_SIZE && !oPlaced; c++) { for (var r = 0; r < BOARD_SIZE - 1 && !oPlaced; r++) { // X // X // _ if (board[r][c].symbol === 'X' && board[r + 1][c].symbol === 'X') { // Try to place O below if (r + 2 < BOARD_SIZE && board[r + 2][c].symbol === '') { board[r + 2][c].setSymbol('O'); board[r + 2][c].isActive = false; oPlaced = true; } // Try to place O above else if (r - 1 >= 0 && board[r - 1][c].symbol === '') { board[r - 1][c].setSymbol('O'); board[r - 1][c].isActive = false; oPlaced = true; } } } } // 3. Check for two Xs in a diagonal (\) with an empty cell next to them for (var i = 0; i < BOARD_SIZE - 1 && !oPlaced; i++) { // X X _ if (board[i][i].symbol === 'X' && board[i + 1][i + 1].symbol === 'X') { // Try to place O after if (i + 2 < BOARD_SIZE && board[i + 2][i + 2].symbol === '') { board[i + 2][i + 2].setSymbol('O'); board[i + 2][i + 2].isActive = false; oPlaced = true; } // Try to place O before else if (i - 1 >= 0 && board[i - 1][i - 1].symbol === '') { board[i - 1][i - 1].setSymbol('O'); board[i - 1][i - 1].isActive = false; oPlaced = true; } } } // 4. Check for two Xs in a diagonal (/) with an empty cell next to them for (var i = 0; i < BOARD_SIZE - 1 && !oPlaced; i++) { var row1 = i, col1 = BOARD_SIZE - 1 - i; var row2 = i + 1, col2 = BOARD_SIZE - 2 - i; if (board[row1][col1].symbol === 'X' && board[row2][col2].symbol === 'X') { // Try to place O after if (i + 2 < BOARD_SIZE && board[i + 2][BOARD_SIZE - 1 - (i + 2)].symbol === '') { board[i + 2][BOARD_SIZE - 1 - (i + 2)].setSymbol('O'); board[i + 2][BOARD_SIZE - 1 - (i + 2)].isActive = false; oPlaced = true; } // Try to place O before else if (i - 1 >= 0 && board[i - 1][BOARD_SIZE - 1 - (i - 1)].symbol === '') { board[i - 1][BOARD_SIZE - 1 - (i - 1)].setSymbol('O'); board[i - 1][BOARD_SIZE - 1 - (i - 1)].isActive = false; oPlaced = true; } } } // 5. If no such pattern, pick a random empty cell for O if (!oPlaced) { // Find all empty cells var emptyCells = []; for (var r = 0; r < BOARD_SIZE; r++) { for (var c = 0; c < BOARD_SIZE; c++) { if (board[r][c].symbol === '') { emptyCells.push(board[r][c]); } } } if (emptyCells.length > 0) { var idx = Math.floor(Math.random() * emptyCells.length); var oCell = emptyCells[idx]; oCell.setSymbol('O'); oCell.isActive = false; } } // Check if O wins if (checkWin('O')) { gameActive = false; statusText.setText('Kazanan: O'); highlightWin('O'); LK.setTimeout(function () { LK.showYouWin(); }, 1200); } else if (isBoardFull()) { gameActive = false; statusText.setText('Berabere!'); LK.setTimeout(function () { LK.showGameOver(); }, 1200); } else { currentPlayer = 'X'; statusText.setText('Sıra: X'); } } else { currentPlayer = 'X'; statusText.setText('Sıra: X'); } } }; }(cell); board[row][col] = cell; game.addChild(cell); } } // Check for win function checkWin(player) { // Rows for (var r = 0; r < BOARD_SIZE; r++) { var win = true; for (var c = 0; c < BOARD_SIZE; c++) { if (board[r][c].symbol !== player) win = false; } if (win) return true; } // Columns for (var c = 0; c < BOARD_SIZE; c++) { var win = true; for (var r = 0; r < BOARD_SIZE; r++) { if (board[r][c].symbol !== player) win = false; } if (win) return true; } // Diagonal \ var win = true; for (var i = 0; i < BOARD_SIZE; i++) { if (board[i][i].symbol !== player) win = false; } if (win) return true; // Diagonal / win = true; for (var i = 0; i < BOARD_SIZE; i++) { if (board[i][BOARD_SIZE - 1 - i].symbol !== player) win = false; } if (win) return true; return false; } // Highlight winning cells function highlightWin(player) { // Rows for (var r = 0; r < BOARD_SIZE; r++) { var win = true; for (var c = 0; c < BOARD_SIZE; c++) { if (board[r][c].symbol !== player) win = false; } if (win) { for (var c = 0; c < BOARD_SIZE; c++) { board[r][c].flash(0x00ff00, 800); } return; } } // Columns for (var c = 0; c < BOARD_SIZE; c++) { var win = true; for (var r = 0; r < BOARD_SIZE; r++) { if (board[r][c].symbol !== player) win = false; } if (win) { for (var r = 0; r < BOARD_SIZE; r++) { board[r][c].flash(0x00ff00, 800); } return; } } // Diagonal \ var win = true; for (var i = 0; i < BOARD_SIZE; i++) { if (board[i][i].symbol !== player) win = false; } if (win) { for (var i = 0; i < BOARD_SIZE; i++) { board[i][i].flash(0x00ff00, 800); } return; } // Diagonal / win = true; for (var i = 0; i < BOARD_SIZE; i++) { if (board[i][BOARD_SIZE - 1 - i].symbol !== player) win = false; } if (win) { for (var i = 0; i < BOARD_SIZE; i++) { board[i][BOARD_SIZE - 1 - i].flash(0x00ff00, 800); } return; } } // Check if board is full function isBoardFull() { for (var r = 0; r < BOARD_SIZE; r++) { for (var c = 0; c < BOARD_SIZE; c++) { if (board[r][c].symbol === '') return false; } } return true; } // Reset game on LK reset (handled automatically) function resetBoard() { for (var r = 0; r < BOARD_SIZE; r++) { for (var c = 0; c < BOARD_SIZE; c++) { board[r][c].clear(); } } currentPlayer = 'X'; gameActive = true; statusText.setText('Sıra: X'); } resetBoard();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// BoardCell: Represents a single cell in the Tic Tac Toe grid
var BoardCell = Container.expand(function () {
var self = Container.call(this);
// Cell highlight background (grikutu, hidden by default)
var grikutuBg = self.attachAsset('grikutu', {
anchorX: 0.5,
anchorY: 0.5
});
grikutuBg.visible = false;
self.addChild(grikutuBg);
// Cell background (box)
var cellBg = self.attachAsset('cellBg', {
anchorX: 0.5,
anchorY: 0.5
});
// Symbol image for X or O
var xImage = LK.getAsset('x', {
anchorX: 0.5,
anchorY: 0.5
});
xImage.visible = false;
self.addChild(xImage);
var oImage = LK.getAsset('y', {
anchorX: 0.5,
anchorY: 0.5
});
oImage.visible = false;
self.addChild(oImage);
self.symbol = ''; // '', 'X', or 'O'
self.row = 0;
self.col = 0;
self.isActive = true; // Can be tapped
self.setSymbol = function (sym) {
self.symbol = sym;
if (sym === 'X') {
grikutuBg.visible = true;
xImage.visible = true;
oImage.visible = false;
} else if (sym === 'O') {
grikutuBg.visible = true;
xImage.visible = false;
oImage.visible = true;
} else {
grikutuBg.visible = false;
xImage.visible = false;
oImage.visible = false;
}
};
self.clear = function () {
self.symbol = '';
grikutuBg.visible = false;
xImage.visible = false;
oImage.visible = false;
self.isActive = true;
};
self.flash = function (color, duration) {
tween(cellBg, {
tint: color
}, {
duration: duration / 2,
easing: tween.easeIn,
onFinish: function onFinish() {
tween(cellBg, {
tint: 0xffffff
}, {
duration: duration / 2,
easing: tween.easeOut
});
}
});
};
return self;
});
// Health bar class
var HealthBar = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
var bar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5
});
self.set = function (val, max) {
// Use the background width for dynamic sizing, and clamp value between 0 and max
var percent = Math.max(0, Math.min(1, val / max));
bar.width = bg.width * percent;
if (percent < 0.3) bar.tint = 0xff4444;else if (percent < 0.6) bar.tint = 0xffcc00;else bar.tint = 0x4caf50;
};
self.set(1, 1);
return self;
});
/****
* Initialize Game
****/
// Create vikings
var game = new LK.Game({
backgroundColor: 0xffffff
});
/****
* Game Code
****/
// O symbol asset (green ellipse, could be replaced with image for stylized O)
// X symbol asset (blue box, could be replaced with image for stylized X)
// Cell background for Tic Tac Toe
// Tic Tac Toe Game State
var BOARD_SIZE = 3;
var CELL_SIZE = 320;
var CELL_MARGIN = 24;
var board = [];
var currentPlayer = 'X';
var gameActive = true;
var statusText = new Text2('Sıra: X', {
size: 110,
fill: 0x333333
});
statusText.anchor.set(0.5, 0);
LK.gui.top.addChild(statusText);
// Center the board
var boardWidth = BOARD_SIZE * CELL_SIZE + (BOARD_SIZE - 1) * CELL_MARGIN;
var boardHeight = BOARD_SIZE * CELL_SIZE + (BOARD_SIZE - 1) * CELL_MARGIN;
var boardOriginX = (2048 - boardWidth) / 2;
var boardOriginY = (2732 - boardHeight) / 2 + 60;
// Create board cells
for (var row = 0; row < BOARD_SIZE; row++) {
board[row] = [];
for (var col = 0; col < BOARD_SIZE; col++) {
var cell = new BoardCell();
cell.x = boardOriginX + col * (CELL_SIZE + CELL_MARGIN) + CELL_SIZE / 2;
cell.y = boardOriginY + row * (CELL_SIZE + CELL_MARGIN) + CELL_SIZE / 2;
cell.row = row;
cell.col = col;
cell.setSymbol('');
cell.isActive = true;
// Cell tap handler
cell.down = function (cell) {
return function (x, y, obj) {
if (!gameActive || !cell.isActive) return;
cell.setSymbol(currentPlayer);
cell.isActive = false;
if (checkWin(currentPlayer)) {
gameActive = false;
statusText.setText('Kazanan: ' + currentPlayer);
highlightWin(currentPlayer);
LK.setTimeout(function () {
LK.showYouWin();
}, 1200);
} else if (isBoardFull()) {
gameActive = false;
statusText.setText('Berabere!');
LK.setTimeout(function () {
LK.showGameOver();
}, 1200);
} else {
// If X just played, make a smart O move if game is still active
if (currentPlayer === 'X') {
currentPlayer = 'O';
statusText.setText('Sıra: O');
var oPlaced = false;
// 1. Check for two Xs in a row with an empty cell next to them (horizontal)
for (var r = 0; r < BOARD_SIZE && !oPlaced; r++) {
for (var c = 0; c < BOARD_SIZE - 1 && !oPlaced; c++) {
// X X _
if (board[r][c].symbol === 'X' && board[r][c + 1].symbol === 'X') {
// Try to place O to the right
if (c + 2 < BOARD_SIZE && board[r][c + 2].symbol === '') {
board[r][c + 2].setSymbol('O');
board[r][c + 2].isActive = false;
oPlaced = true;
}
// Try to place O to the left
else if (c - 1 >= 0 && board[r][c - 1].symbol === '') {
board[r][c - 1].setSymbol('O');
board[r][c - 1].isActive = false;
oPlaced = true;
}
}
}
}
// 2. Check for two Xs in a column with an empty cell next to them (vertical)
for (var c = 0; c < BOARD_SIZE && !oPlaced; c++) {
for (var r = 0; r < BOARD_SIZE - 1 && !oPlaced; r++) {
// X
// X
// _
if (board[r][c].symbol === 'X' && board[r + 1][c].symbol === 'X') {
// Try to place O below
if (r + 2 < BOARD_SIZE && board[r + 2][c].symbol === '') {
board[r + 2][c].setSymbol('O');
board[r + 2][c].isActive = false;
oPlaced = true;
}
// Try to place O above
else if (r - 1 >= 0 && board[r - 1][c].symbol === '') {
board[r - 1][c].setSymbol('O');
board[r - 1][c].isActive = false;
oPlaced = true;
}
}
}
}
// 3. Check for two Xs in a diagonal (\) with an empty cell next to them
for (var i = 0; i < BOARD_SIZE - 1 && !oPlaced; i++) {
// X X _
if (board[i][i].symbol === 'X' && board[i + 1][i + 1].symbol === 'X') {
// Try to place O after
if (i + 2 < BOARD_SIZE && board[i + 2][i + 2].symbol === '') {
board[i + 2][i + 2].setSymbol('O');
board[i + 2][i + 2].isActive = false;
oPlaced = true;
}
// Try to place O before
else if (i - 1 >= 0 && board[i - 1][i - 1].symbol === '') {
board[i - 1][i - 1].setSymbol('O');
board[i - 1][i - 1].isActive = false;
oPlaced = true;
}
}
}
// 4. Check for two Xs in a diagonal (/) with an empty cell next to them
for (var i = 0; i < BOARD_SIZE - 1 && !oPlaced; i++) {
var row1 = i,
col1 = BOARD_SIZE - 1 - i;
var row2 = i + 1,
col2 = BOARD_SIZE - 2 - i;
if (board[row1][col1].symbol === 'X' && board[row2][col2].symbol === 'X') {
// Try to place O after
if (i + 2 < BOARD_SIZE && board[i + 2][BOARD_SIZE - 1 - (i + 2)].symbol === '') {
board[i + 2][BOARD_SIZE - 1 - (i + 2)].setSymbol('O');
board[i + 2][BOARD_SIZE - 1 - (i + 2)].isActive = false;
oPlaced = true;
}
// Try to place O before
else if (i - 1 >= 0 && board[i - 1][BOARD_SIZE - 1 - (i - 1)].symbol === '') {
board[i - 1][BOARD_SIZE - 1 - (i - 1)].setSymbol('O');
board[i - 1][BOARD_SIZE - 1 - (i - 1)].isActive = false;
oPlaced = true;
}
}
}
// 5. If no such pattern, pick a random empty cell for O
if (!oPlaced) {
// Find all empty cells
var emptyCells = [];
for (var r = 0; r < BOARD_SIZE; r++) {
for (var c = 0; c < BOARD_SIZE; c++) {
if (board[r][c].symbol === '') {
emptyCells.push(board[r][c]);
}
}
}
if (emptyCells.length > 0) {
var idx = Math.floor(Math.random() * emptyCells.length);
var oCell = emptyCells[idx];
oCell.setSymbol('O');
oCell.isActive = false;
}
}
// Check if O wins
if (checkWin('O')) {
gameActive = false;
statusText.setText('Kazanan: O');
highlightWin('O');
LK.setTimeout(function () {
LK.showYouWin();
}, 1200);
} else if (isBoardFull()) {
gameActive = false;
statusText.setText('Berabere!');
LK.setTimeout(function () {
LK.showGameOver();
}, 1200);
} else {
currentPlayer = 'X';
statusText.setText('Sıra: X');
}
} else {
currentPlayer = 'X';
statusText.setText('Sıra: X');
}
}
};
}(cell);
board[row][col] = cell;
game.addChild(cell);
}
}
// Check for win
function checkWin(player) {
// Rows
for (var r = 0; r < BOARD_SIZE; r++) {
var win = true;
for (var c = 0; c < BOARD_SIZE; c++) {
if (board[r][c].symbol !== player) win = false;
}
if (win) return true;
}
// Columns
for (var c = 0; c < BOARD_SIZE; c++) {
var win = true;
for (var r = 0; r < BOARD_SIZE; r++) {
if (board[r][c].symbol !== player) win = false;
}
if (win) return true;
}
// Diagonal \
var win = true;
for (var i = 0; i < BOARD_SIZE; i++) {
if (board[i][i].symbol !== player) win = false;
}
if (win) return true;
// Diagonal /
win = true;
for (var i = 0; i < BOARD_SIZE; i++) {
if (board[i][BOARD_SIZE - 1 - i].symbol !== player) win = false;
}
if (win) return true;
return false;
}
// Highlight winning cells
function highlightWin(player) {
// Rows
for (var r = 0; r < BOARD_SIZE; r++) {
var win = true;
for (var c = 0; c < BOARD_SIZE; c++) {
if (board[r][c].symbol !== player) win = false;
}
if (win) {
for (var c = 0; c < BOARD_SIZE; c++) {
board[r][c].flash(0x00ff00, 800);
}
return;
}
}
// Columns
for (var c = 0; c < BOARD_SIZE; c++) {
var win = true;
for (var r = 0; r < BOARD_SIZE; r++) {
if (board[r][c].symbol !== player) win = false;
}
if (win) {
for (var r = 0; r < BOARD_SIZE; r++) {
board[r][c].flash(0x00ff00, 800);
}
return;
}
}
// Diagonal \
var win = true;
for (var i = 0; i < BOARD_SIZE; i++) {
if (board[i][i].symbol !== player) win = false;
}
if (win) {
for (var i = 0; i < BOARD_SIZE; i++) {
board[i][i].flash(0x00ff00, 800);
}
return;
}
// Diagonal /
win = true;
for (var i = 0; i < BOARD_SIZE; i++) {
if (board[i][BOARD_SIZE - 1 - i].symbol !== player) win = false;
}
if (win) {
for (var i = 0; i < BOARD_SIZE; i++) {
board[i][BOARD_SIZE - 1 - i].flash(0x00ff00, 800);
}
return;
}
}
// Check if board is full
function isBoardFull() {
for (var r = 0; r < BOARD_SIZE; r++) {
for (var c = 0; c < BOARD_SIZE; c++) {
if (board[r][c].symbol === '') return false;
}
}
return true;
}
// Reset game on LK reset (handled automatically)
function resetBoard() {
for (var r = 0; r < BOARD_SIZE; r++) {
for (var c = 0; c < BOARD_SIZE; c++) {
board[r][c].clear();
}
}
currentPlayer = 'X';
gameActive = true;
statusText.setText('Sıra: X');
}
resetBoard();