User prompt
create squares for the grids where we put the levels
User prompt
levelleri koyduğumuz yerler için yuvalar yap
User prompt
make the background black
User prompt
create squares for where we put the coins
User prompt
draw a line for where we put the money
User prompt
When all slots are filled, the restart screen will appear.
User prompt
make design
User prompt
Make slots to put the levels and put their colors in the asset
User prompt
next tile preview little more down
User prompt
Move the grid you made below and move the next level image under the restart button.
User prompt
draw slots for levels on the game screen
User prompt
If there are people from the same level on the right, left or above each level, they should merge.
User prompt
little more bigger restart button like pause button
User prompt
fix restart button
User prompt
Make the resolution of the restart button the same as the stop button
User prompt
Title10 is not visible in the game, please fix it
User prompt
You have introduced the restart button incorrectly. It uses the same introduction as 10TL. Open a new introduction for the restart button and add an asset for the restart button.
User prompt
Add a restart button to the top right of the screen and also create a frame for where we will put the money
User prompt
Please fix the bug: 'Uncaught TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 392
Code edit (1 edits merged)
Please save this source code
User prompt
Merge TL Mania
Initial prompt
I want a game similar to merge fellas. There will be 6 levels. When the same levels merge, you will move on to the next level. When the last level merges, the game will end. When each level merges, 5,10,20,50,100,200 coins will be given as a donation to the merged levels from smallest to largest. These 6 levels are 5TL,10TL,20TL,50TL,100TL,200TL from smallest to largest. You don't need to create visuals for these levels. I will handle them.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Tile class var TLTile = Container.expand(function () { var self = Container.call(this); // Properties self.levelIdx = 0; // 0-5 self.gridX = 0; self.gridY = 0; self.asset = null; // Set tile level and update asset self.setLevel = function (levelIdx) { self.levelIdx = levelIdx; if (self.asset) { self.removeChild(self.asset); self.asset.destroy(); } var assetId = TL_LEVELS[levelIdx].asset; self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; // Animate merge pop self.mergePop = function () { tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 80, easing: tween.easeIn }); } }); }; // Animate spawn self.spawnPop = function () { self.scaleX = self.scaleY = 0.2; tween(self, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.bounceOut }); }; // Animate move to (x, y) in px self.moveTo = function (x, y, onFinish) { tween(self, { x: x, y: y }, { duration: 120, easing: tween.cubicOut, onFinish: onFinish }); }; // Animate coin pop at this tile self.coinPop = function (amount) { var coin = LK.getAsset('coinpop', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y - 60 }); coin.alpha = 0.9; game.addChild(coin); var txt = new Text2('+' + amount, { size: 60, fill: '#fff700', font: "Alfa Slab One" }); txt.anchor.set(0.5, 0.5); txt.x = self.x; txt.y = self.y - 60; game.addChild(txt); tween(coin, { y: coin.y - 80, alpha: 0 }, { duration: 600, easing: tween.linear }); tween(txt, { y: txt.y - 80, alpha: 0 }, { duration: 600, easing: tween.linear, onFinish: function onFinish() { coin.destroy(); txt.destroy(); } }); }; // Set grid position (not pixel position) self.setGrid = function (gx, gy) { self.gridX = gx; self.gridY = gy; var pos = getTilePixelPos(gx, gy); self.x = pos.x; self.y = pos.y; }; // For drag highlight self.setHighlight = function (on) { if (on) { self.asset.alpha = 0.7; } else { self.asset.alpha = 1; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xf7f7f7 }); /**** * Game Code ****/ // --- General background image --- /* We use 6 TL tile images, one for each denomination. Asset IDs: 'tile5', 'tile10', 'tile20', 'tile50', 'tile100', 'tile200' Each tile is a square, 300x300 px. */ /* Coin pop effect */ // TL tile levels and their properties var generalBg = LK.getAsset('generalBg', { width: 2048, height: 2732, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); generalBg.alpha = 1; game.addChild(generalBg); // --- Grid setup --- var TL_LEVELS = [{ value: 5, asset: 'tile5', donation: 5, color: 0xf7d13d // yellow }, { value: 10, asset: 'tile10', donation: 10, color: 0xf7a13d // orange }, { value: 20, asset: 'tile20', donation: 20, color: 0xf76d3d // red-orange }, { value: 50, asset: 'tile50', donation: 50, color: 0x3db8f7 // blue }, { value: 100, asset: 'tile100', donation: 100, color: 0x44de83 // green }, { value: 200, asset: 'tile200', donation: 200, color: 0xb8b031 // gold }]; // Helper: get next level index, or null if max function getNextLevelIndex(levelIdx) { if (levelIdx < TL_LEVELS.length - 1) return levelIdx + 1; return null; } var GRID_SIZE = 4; // 4x4 var TILE_SIZE = 320; // px, including margin var TILE_MARGIN = 20; // px var gridOriginX = Math.floor((2048 - (GRID_SIZE * TILE_SIZE + (GRID_SIZE - 1) * TILE_MARGIN)) / 2); var gridOriginY = 700; // 2D array of tiles (null or TLTile) // --- Grid background highlight --- // Use a dedicated grid background asset to avoid name conflict with 200 TL asset var gridAsset = LK.getAsset('gridBg', { width: GRID_SIZE * TILE_SIZE + (GRID_SIZE - 1) * TILE_MARGIN + 40, height: GRID_SIZE * TILE_SIZE + (GRID_SIZE - 1) * TILE_MARGIN + 40, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: gridOriginY + (GRID_SIZE * TILE_SIZE + (GRID_SIZE - 1) * TILE_MARGIN) / 2 }); gridAsset.alpha = 1; game.addChild(gridAsset); var grid = []; for (var i = 0; i < GRID_SIZE; ++i) { grid[i] = []; for (var j = 0; j < GRID_SIZE; ++j) grid[i][j] = null; } // Helper: get pixel position for grid cell function getTilePixelPos(gx, gy) { return { x: gridOriginX + gx * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2, y: gridOriginY + gy * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2 }; } // --- Score and donation --- // --- Donation Frame --- var donationFrame = LK.getAsset('tile200', { width: 600, height: 120, anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: 0 }); donationFrame.alpha = 0.18; LK.gui.top.addChild(donationFrame); // Use persistent storage for donation (money) var donation = storage.donation || 0; var donationTxt = new Text2('Sermaye: ' + donation + ' TL', { size: 90, fill: '#1a1a1a', font: "Alfa Slab One" }); donationTxt.anchor.set(0.5, 0); donationTxt.y = 20; LK.gui.top.addChild(donationTxt); // --- Draw a line for where we put the money --- // We'll use a very thin, wide box as a line, just below the grid var lineY = gridOriginY + GRID_SIZE * (TILE_SIZE + TILE_MARGIN) + 40; var line = LK.getAsset('box', { width: 1200, height: 12, color: 0x1a1a1a, anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: lineY }); line.alpha = 0.18; game.addChild(line); // --- Next tile preview --- var nextLevelIdx = 0; function randomLevelIdx() { // --- Level Bar UI --- // Draw a horizontal bar of all TL tile levels at the bottom of the game area var levelBarTiles = []; var levelBarLabels = []; var levelBarTileSize = 120; var levelBarSpacing = 32; var totalBarWidth = TL_LEVELS.length * levelBarTileSize + (TL_LEVELS.length - 1) * levelBarSpacing; var barStartX = Math.floor((2048 - totalBarWidth) / 2) + levelBarTileSize / 2; var levelBarY = 2732 - 320 - levelBarTileSize / 2; // Move up: 320px margin from bottom, centered on tile (2x more up) for (var i = 0; i < TL_LEVELS.length; ++i) { // Draw colored slot behind the tile var slot = LK.getAsset('coinpop', { width: levelBarTileSize + 24, height: levelBarTileSize + 24, color: TL_LEVELS[i].color, anchorX: 0.5, anchorY: 0.5, x: barStartX + i * (levelBarTileSize + levelBarSpacing), y: levelBarY }); slot.alpha = 0.32; game.addChild(slot); var tileAsset = LK.getAsset(TL_LEVELS[i].asset, { width: levelBarTileSize, height: levelBarTileSize, anchorX: 0.5, anchorY: 0.5, x: barStartX + i * (levelBarTileSize + levelBarSpacing), y: levelBarY }); tileAsset.alpha = 0.92; game.addChild(tileAsset); levelBarTiles.push(tileAsset); var label = new Text2(TL_LEVELS[i].value + " TL", { size: 38, fill: 0x1A1A1A, font: "Alfa Slab One" }); label.anchor.set(0.5, 0); label.x = tileAsset.x; label.y = tileAsset.y + levelBarTileSize / 2 + 6; game.addChild(label); levelBarLabels.push(label); } // Only 5TL, 10TL, 20TL as next tile (0,1,2) return Math.floor(Math.random() * 3); } nextLevelIdx = randomLevelIdx(); // Place next tile preview and label 2x further up (closer to Sermaye text) var nextTilePreviewY = donationTxt.y + donationTxt.height + 180; var nextTilePreview = LK.getAsset(TL_LEVELS[nextLevelIdx].asset, { anchorX: 0.5, anchorY: 0.0, x: 2048 / 2, // centered horizontally y: nextTilePreviewY // 2x further up below Sermaye text }); var nextTileTxt = new Text2('Next', { size: 60, fill: '#1a1a1a', font: "Alfa Slab One" }); nextTileTxt.anchor.set(0.5, 1); nextTileTxt.x = 2048 / 2; nextTileTxt.y = nextTilePreview.y - 10; // above the preview image, with a small gap game.addChild(nextTilePreview); game.addChild(nextTileTxt); // --- Restart Button --- // Use a custom asset for the restart button, top right, larger size (like pause button), margin 30 from top/right var restartBtn = LK.getAsset('restartBtn', { width: 360, height: 180, anchorX: 1, anchorY: 0, x: 2048 - 30, y: 30 }); restartBtn.alpha = 0.85; game.addChild(restartBtn); // Button interaction restartBtn.interactive = true; restartBtn.down = function (x, y, obj) { // Call LK reset (will restart the game) LK.showGameOver(); }; // --- Custom Tab Button removed --- // Tab popup container (hidden by default) var tabPopup = new Container(); tabPopup.visible = false; tabPopup.width = 1820; tabPopup.height = 1800; // Center the popup in the game area tabPopup.x = (2048 - 1820) / 2; tabPopup.y = (2732 - 1800) / 2; // Add a background to the popup var tabBg = LK.getAsset('generalBg2', { width: 1820, height: 1800, anchorX: 0, anchorY: 0, x: 0, y: 0 }); tabBg.alpha = 0.98; tabPopup.addChild(tabBg); // Add a close button to the popup (top right of popup) var closeBtn = LK.getAsset('shop3', { width: 120, height: 120, anchorX: 1, anchorY: 0, x: 1820 - 20, y: 20 }); closeBtn.alpha = 0.95; closeBtn.interactive = true; closeBtn.down = function () { tabPopup.visible = false; isMarketOpen = false; }; tabPopup.addChild(closeBtn); // Add a label to the popup var tabPopupLabel = new Text2('Tab Content', { size: 90, fill: '#1a1a1a', font: "Alfa Slab One" }); tabPopupLabel.anchor.set(0.5, 0); tabPopupLabel.x = 1820 / 2; tabPopupLabel.y = 60; tabPopup.addChild(tabPopupLabel); // --- 3x3 grid of squares with assets game1 to game9 --- var tabGridRows = 3; var tabGridCols = 3; var tabCellSize = 400; // px, fits 3x3 in 1820x1800 with margin var tabCellMargin = 40; var tabGridOriginX = Math.floor((1820 - (tabGridCols * tabCellSize + (tabGridCols - 1) * tabCellMargin)) / 2); var tabGridOriginY = 220; // below the label // Store references to tab squares for later use if needed var tabSquares = []; for (var row = 0; row < tabGridRows; ++row) { for (var col = 0; col < tabGridCols; ++col) { var idx = row * tabGridCols + col + 1; // 1..9 // Draw square background using game1..game9 asset var square = LK.getAsset('game' + idx, { width: tabCellSize, height: tabCellSize, anchorX: 0, anchorY: 0, x: tabGridOriginX + col * (tabCellSize + tabCellMargin), y: tabGridOriginY + row * (tabCellSize + tabCellMargin) }); square.interactive = true; // Add a simple down handler for demonstration (replace with your logic) square.down = function (index) { return function (x, y, obj) { // Flash the square when pressed LK.effects.flashObject(this, 0xffffff, 200); // If this is the game1 button, save and open Merge TL Mania if (index === 1) { // Save the current game as "Merge TL Mania" storage.saveGame && storage.saveGame("Merge TL Mania"); // Open the Merge TL Mania game (if supported by the platform) if (typeof LK.openGame === "function") { LK.openGame("Merge TL Mania"); } } // If this is the game2 button, open the external TLeater game if (index === 2) { // Open the external game in a new tab/window if (typeof window !== "undefined" && typeof window.open === "function") { window.open("https://upit.com/create/-jjol2nG8v/history", "_blank"); } } }; }(idx); tabPopup.addChild(square); tabSquares.push(square); } } // Add the popup to the game game.addChild(tabPopup); // Button interaction to open the tab removed // --- Helper: update next tile preview --- function updateNextTilePreview() { if (nextTilePreview) { nextTilePreview.destroy(); } if (nextTileTxt) { nextTileTxt.destroy(); } var nextTilePreviewY = donationTxt.y + donationTxt.height + 180; nextTilePreview = LK.getAsset(TL_LEVELS[nextLevelIdx].asset, { anchorX: 0.5, anchorY: 0.0, x: 2048 / 2, y: nextTilePreviewY }); nextTileTxt = new Text2('Next', { size: 60, fill: '#1a1a1a', font: "Alfa Slab One" }); nextTileTxt.anchor.set(0.5, 1); nextTileTxt.x = 2048 / 2; nextTileTxt.y = nextTilePreview.y - 10; game.addChild(nextTilePreview); game.addChild(nextTileTxt); } // --- Spawn a new tile at (gx,gy) with levelIdx --- function spawnTile(gx, gy, levelIdx) { var tile = new TLTile(); tile.setLevel(levelIdx); tile.setGrid(gx, gy); tile.spawnPop(); grid[gx][gy] = tile; game.addChild(tile); return tile; } // --- Find empty cells --- function getEmptyCells() { var arr = []; for (var i = 0; i < GRID_SIZE; ++i) { for (var j = 0; j < GRID_SIZE; ++j) { if (!grid[i][j]) arr.push({ gx: i, gy: j }); } } return arr; } // --- Merge logic --- // Returns true if a merge happened function tryMergeAt(gx, gy) { var tile = grid[gx][gy]; if (!tile) return false; var merged = false; // Find all adjacent (left, right, above) same-level tiles var mergeGroup = [{ gx: gx, gy: gy, tile: tile }]; // Left if (gx > 0 && grid[gx - 1][gy] && grid[gx - 1][gy].levelIdx === tile.levelIdx) { mergeGroup.push({ gx: gx - 1, gy: gy, tile: grid[gx - 1][gy] }); } // Right if (gx < GRID_SIZE - 1 && grid[gx + 1][gy] && grid[gx + 1][gy].levelIdx === tile.levelIdx) { mergeGroup.push({ gx: gx + 1, gy: gy, tile: grid[gx + 1][gy] }); } // Above if (gy > 0 && grid[gx][gy - 1] && grid[gx][gy - 1].levelIdx === tile.levelIdx) { mergeGroup.push({ gx: gx, gy: gy - 1, tile: grid[gx][gy - 1] }); } // Only merge if there are at least 2 of the same level (including self) if (mergeGroup.length > 1) { // Find the "main" tile to upgrade (choose the first in mergeGroup) var main = mergeGroup[0]; var nextIdx = getNextLevelIndex(tile.levelIdx); if (nextIdx === null) return false; // Already max, can't merge // Remove all tiles in mergeGroup from grid for (var i = 0; i < mergeGroup.length; ++i) { var g = mergeGroup[i]; grid[g.gx][g.gy] = null; } // Animate all but main tile to move to main, then destroy for (var i = 1; i < mergeGroup.length; ++i) { var g = mergeGroup[i]; g.tile.setHighlight(false); g.tile.moveTo(main.tile.x, main.tile.y, function (t) { return function () { t.destroy(); }; }(g.tile)); } main.tile.setHighlight(false); // Upgrade main tile main.tile.setLevel(nextIdx); main.tile.mergePop(); // Coin pop var donationAmt = TL_LEVELS[nextIdx].donation; main.tile.coinPop(donationAmt); donation += donationAmt; storage.donation = donation; donationTxt.setText('Sermaye: ' + donation + ' TL'); // Place upgraded tile in grid grid[main.gx][main.gy] = main.tile; // Check win: if merged to 200TL if (nextIdx === 5) { // Win if two 200TL tiles merged LK.showYouWin(); return true; } // After merge, try to merge again at main LK.setTimeout(function () { tryMergeAt(main.gx, main.gy); }, 180); merged = true; } return merged; } // --- Drag and drop logic --- var draggingTile = null; var dragOrigin = null; // {gx,gy} var dragOffset = { x: 0, y: 0 }; var dragValid = false; var dragTarget = null; // Helper: get grid cell from px function getGridCellFromPos(x, y) { for (var i = 0; i < GRID_SIZE; ++i) { for (var j = 0; j < GRID_SIZE; ++j) { var pos = getTilePixelPos(i, j); var dx = Math.abs(x - pos.x); var dy = Math.abs(y - pos.y); if (dx < TILE_SIZE / 2 && dy < TILE_SIZE / 2) { return { gx: i, gy: j }; } } } return null; } // --- Game events --- // Place next tile on tap/click // --- Track if market is open globally --- var isMarketOpen = false; game.down = function (x, y, obj) { if (isMarketOpen) return; // Don't allow placing in top 100px if (y < 100) return; // If dragging, ignore if (draggingTile) return; // Only allow placing if empty cell var cell = getGridCellFromPos(x, y); if (!cell) return; if (grid[cell.gx][cell.gy]) return; // Place tile var tile = spawnTile(cell.gx, cell.gy, nextLevelIdx); // Try merge LK.setTimeout(function () { tryMergeAt(cell.gx, cell.gy); // After merge, check if all slots are filled var allFilled = true; for (var i = 0; i < GRID_SIZE; ++i) { for (var j = 0; j < GRID_SIZE; ++j) { if (!grid[i][j]) { allFilled = false; break; } } if (!allFilled) break; } if (allFilled) { LK.showGameOver(); } }, 120); // Next tile nextLevelIdx = randomLevelIdx(); updateNextTilePreview(); }; // --- Drag to move tiles (optional, for more fun) --- game.move = function (x, y, obj) { if (isMarketOpen) return; // If not dragging, check if user is holding on a tile if (!draggingTile && obj && obj.event && obj.event.type === 'pointerdown') { var cell = getGridCellFromPos(x, y); if (!cell) return; var tile = grid[cell.gx][cell.gy]; if (!tile) return; draggingTile = tile; dragOrigin = { gx: cell.gx, gy: cell.gy }; dragOffset.x = tile.x - x; dragOffset.y = tile.y - y; tile.setHighlight(true); } // If dragging if (draggingTile) { draggingTile.x = x + dragOffset.x; draggingTile.y = y + dragOffset.y; // Highlight valid drop var cell = getGridCellFromPos(x, y); if (cell && (!grid[cell.gx][cell.gy] || cell.gx === dragOrigin.gx && cell.gy === dragOrigin.gy)) { dragValid = true; dragTarget = cell; draggingTile.setHighlight(true); } else { dragValid = false; dragTarget = null; draggingTile.setHighlight(false); } } }; game.up = function (x, y, obj) { if (isMarketOpen) return; if (draggingTile) { // Drop if (dragValid && dragTarget && (dragTarget.gx !== dragOrigin.gx || dragTarget.gy !== dragOrigin.gy)) { // Move tile grid[dragOrigin.gx][dragOrigin.gy] = null; grid[dragTarget.gx][dragTarget.gy] = draggingTile; draggingTile.setGrid(dragTarget.gx, dragTarget.gy); draggingTile.setHighlight(false); // Try merge LK.setTimeout(function () { tryMergeAt(dragTarget.gx, dragTarget.gy); }, 120); } else { // Snap back draggingTile.setGrid(dragOrigin.gx, dragOrigin.gy); draggingTile.setHighlight(false); } draggingTile = null; dragOrigin = null; dragValid = false; dragTarget = null; } }; // --- Game update (not used for logic, but required) --- game.update = function () { // No per-frame logic needed }; // --- Start: spawn 2 random tiles --- function startGame() { var empties = getEmptyCells(); for (var i = 0; i < 2; ++i) { if (empties.length === 0) break; var idx = Math.floor(Math.random() * empties.length); var cell = empties[idx]; var lvl = randomLevelIdx(); spawnTile(cell.gx, cell.gy, lvl); empties.splice(idx, 1); } } startGame(); ; // Save this scene as MergeTL and open a new scene named TLeater // Scene change to 'TLeater' would happen here if supported
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Tile class
var TLTile = Container.expand(function () {
var self = Container.call(this);
// Properties
self.levelIdx = 0; // 0-5
self.gridX = 0;
self.gridY = 0;
self.asset = null;
// Set tile level and update asset
self.setLevel = function (levelIdx) {
self.levelIdx = levelIdx;
if (self.asset) {
self.removeChild(self.asset);
self.asset.destroy();
}
var assetId = TL_LEVELS[levelIdx].asset;
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
// Animate merge pop
self.mergePop = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 80,
easing: tween.easeIn
});
}
});
};
// Animate spawn
self.spawnPop = function () {
self.scaleX = self.scaleY = 0.2;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.bounceOut
});
};
// Animate move to (x, y) in px
self.moveTo = function (x, y, onFinish) {
tween(self, {
x: x,
y: y
}, {
duration: 120,
easing: tween.cubicOut,
onFinish: onFinish
});
};
// Animate coin pop at this tile
self.coinPop = function (amount) {
var coin = LK.getAsset('coinpop', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y - 60
});
coin.alpha = 0.9;
game.addChild(coin);
var txt = new Text2('+' + amount, {
size: 60,
fill: '#fff700',
font: "Alfa Slab One"
});
txt.anchor.set(0.5, 0.5);
txt.x = self.x;
txt.y = self.y - 60;
game.addChild(txt);
tween(coin, {
y: coin.y - 80,
alpha: 0
}, {
duration: 600,
easing: tween.linear
});
tween(txt, {
y: txt.y - 80,
alpha: 0
}, {
duration: 600,
easing: tween.linear,
onFinish: function onFinish() {
coin.destroy();
txt.destroy();
}
});
};
// Set grid position (not pixel position)
self.setGrid = function (gx, gy) {
self.gridX = gx;
self.gridY = gy;
var pos = getTilePixelPos(gx, gy);
self.x = pos.x;
self.y = pos.y;
};
// For drag highlight
self.setHighlight = function (on) {
if (on) {
self.asset.alpha = 0.7;
} else {
self.asset.alpha = 1;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf7f7f7
});
/****
* Game Code
****/
// --- General background image ---
/*
We use 6 TL tile images, one for each denomination.
Asset IDs: 'tile5', 'tile10', 'tile20', 'tile50', 'tile100', 'tile200'
Each tile is a square, 300x300 px.
*/
/* Coin pop effect */
// TL tile levels and their properties
var generalBg = LK.getAsset('generalBg', {
width: 2048,
height: 2732,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
generalBg.alpha = 1;
game.addChild(generalBg);
// --- Grid setup ---
var TL_LEVELS = [{
value: 5,
asset: 'tile5',
donation: 5,
color: 0xf7d13d // yellow
}, {
value: 10,
asset: 'tile10',
donation: 10,
color: 0xf7a13d // orange
}, {
value: 20,
asset: 'tile20',
donation: 20,
color: 0xf76d3d // red-orange
}, {
value: 50,
asset: 'tile50',
donation: 50,
color: 0x3db8f7 // blue
}, {
value: 100,
asset: 'tile100',
donation: 100,
color: 0x44de83 // green
}, {
value: 200,
asset: 'tile200',
donation: 200,
color: 0xb8b031 // gold
}];
// Helper: get next level index, or null if max
function getNextLevelIndex(levelIdx) {
if (levelIdx < TL_LEVELS.length - 1) return levelIdx + 1;
return null;
}
var GRID_SIZE = 4; // 4x4
var TILE_SIZE = 320; // px, including margin
var TILE_MARGIN = 20; // px
var gridOriginX = Math.floor((2048 - (GRID_SIZE * TILE_SIZE + (GRID_SIZE - 1) * TILE_MARGIN)) / 2);
var gridOriginY = 700;
// 2D array of tiles (null or TLTile)
// --- Grid background highlight ---
// Use a dedicated grid background asset to avoid name conflict with 200 TL asset
var gridAsset = LK.getAsset('gridBg', {
width: GRID_SIZE * TILE_SIZE + (GRID_SIZE - 1) * TILE_MARGIN + 40,
height: GRID_SIZE * TILE_SIZE + (GRID_SIZE - 1) * TILE_MARGIN + 40,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: gridOriginY + (GRID_SIZE * TILE_SIZE + (GRID_SIZE - 1) * TILE_MARGIN) / 2
});
gridAsset.alpha = 1;
game.addChild(gridAsset);
var grid = [];
for (var i = 0; i < GRID_SIZE; ++i) {
grid[i] = [];
for (var j = 0; j < GRID_SIZE; ++j) grid[i][j] = null;
}
// Helper: get pixel position for grid cell
function getTilePixelPos(gx, gy) {
return {
x: gridOriginX + gx * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2,
y: gridOriginY + gy * (TILE_SIZE + TILE_MARGIN) + TILE_SIZE / 2
};
}
// --- Score and donation ---
// --- Donation Frame ---
var donationFrame = LK.getAsset('tile200', {
width: 600,
height: 120,
anchorX: 0.5,
anchorY: 0,
x: 2048 / 2,
y: 0
});
donationFrame.alpha = 0.18;
LK.gui.top.addChild(donationFrame);
// Use persistent storage for donation (money)
var donation = storage.donation || 0;
var donationTxt = new Text2('Sermaye: ' + donation + ' TL', {
size: 90,
fill: '#1a1a1a',
font: "Alfa Slab One"
});
donationTxt.anchor.set(0.5, 0);
donationTxt.y = 20;
LK.gui.top.addChild(donationTxt);
// --- Draw a line for where we put the money ---
// We'll use a very thin, wide box as a line, just below the grid
var lineY = gridOriginY + GRID_SIZE * (TILE_SIZE + TILE_MARGIN) + 40;
var line = LK.getAsset('box', {
width: 1200,
height: 12,
color: 0x1a1a1a,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: lineY
});
line.alpha = 0.18;
game.addChild(line);
// --- Next tile preview ---
var nextLevelIdx = 0;
function randomLevelIdx() {
// --- Level Bar UI ---
// Draw a horizontal bar of all TL tile levels at the bottom of the game area
var levelBarTiles = [];
var levelBarLabels = [];
var levelBarTileSize = 120;
var levelBarSpacing = 32;
var totalBarWidth = TL_LEVELS.length * levelBarTileSize + (TL_LEVELS.length - 1) * levelBarSpacing;
var barStartX = Math.floor((2048 - totalBarWidth) / 2) + levelBarTileSize / 2;
var levelBarY = 2732 - 320 - levelBarTileSize / 2; // Move up: 320px margin from bottom, centered on tile (2x more up)
for (var i = 0; i < TL_LEVELS.length; ++i) {
// Draw colored slot behind the tile
var slot = LK.getAsset('coinpop', {
width: levelBarTileSize + 24,
height: levelBarTileSize + 24,
color: TL_LEVELS[i].color,
anchorX: 0.5,
anchorY: 0.5,
x: barStartX + i * (levelBarTileSize + levelBarSpacing),
y: levelBarY
});
slot.alpha = 0.32;
game.addChild(slot);
var tileAsset = LK.getAsset(TL_LEVELS[i].asset, {
width: levelBarTileSize,
height: levelBarTileSize,
anchorX: 0.5,
anchorY: 0.5,
x: barStartX + i * (levelBarTileSize + levelBarSpacing),
y: levelBarY
});
tileAsset.alpha = 0.92;
game.addChild(tileAsset);
levelBarTiles.push(tileAsset);
var label = new Text2(TL_LEVELS[i].value + " TL", {
size: 38,
fill: 0x1A1A1A,
font: "Alfa Slab One"
});
label.anchor.set(0.5, 0);
label.x = tileAsset.x;
label.y = tileAsset.y + levelBarTileSize / 2 + 6;
game.addChild(label);
levelBarLabels.push(label);
}
// Only 5TL, 10TL, 20TL as next tile (0,1,2)
return Math.floor(Math.random() * 3);
}
nextLevelIdx = randomLevelIdx();
// Place next tile preview and label 2x further up (closer to Sermaye text)
var nextTilePreviewY = donationTxt.y + donationTxt.height + 180;
var nextTilePreview = LK.getAsset(TL_LEVELS[nextLevelIdx].asset, {
anchorX: 0.5,
anchorY: 0.0,
x: 2048 / 2,
// centered horizontally
y: nextTilePreviewY // 2x further up below Sermaye text
});
var nextTileTxt = new Text2('Next', {
size: 60,
fill: '#1a1a1a',
font: "Alfa Slab One"
});
nextTileTxt.anchor.set(0.5, 1);
nextTileTxt.x = 2048 / 2;
nextTileTxt.y = nextTilePreview.y - 10; // above the preview image, with a small gap
game.addChild(nextTilePreview);
game.addChild(nextTileTxt);
// --- Restart Button ---
// Use a custom asset for the restart button, top right, larger size (like pause button), margin 30 from top/right
var restartBtn = LK.getAsset('restartBtn', {
width: 360,
height: 180,
anchorX: 1,
anchorY: 0,
x: 2048 - 30,
y: 30
});
restartBtn.alpha = 0.85;
game.addChild(restartBtn);
// Button interaction
restartBtn.interactive = true;
restartBtn.down = function (x, y, obj) {
// Call LK reset (will restart the game)
LK.showGameOver();
};
// --- Custom Tab Button removed ---
// Tab popup container (hidden by default)
var tabPopup = new Container();
tabPopup.visible = false;
tabPopup.width = 1820;
tabPopup.height = 1800;
// Center the popup in the game area
tabPopup.x = (2048 - 1820) / 2;
tabPopup.y = (2732 - 1800) / 2;
// Add a background to the popup
var tabBg = LK.getAsset('generalBg2', {
width: 1820,
height: 1800,
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
tabBg.alpha = 0.98;
tabPopup.addChild(tabBg);
// Add a close button to the popup (top right of popup)
var closeBtn = LK.getAsset('shop3', {
width: 120,
height: 120,
anchorX: 1,
anchorY: 0,
x: 1820 - 20,
y: 20
});
closeBtn.alpha = 0.95;
closeBtn.interactive = true;
closeBtn.down = function () {
tabPopup.visible = false;
isMarketOpen = false;
};
tabPopup.addChild(closeBtn);
// Add a label to the popup
var tabPopupLabel = new Text2('Tab Content', {
size: 90,
fill: '#1a1a1a',
font: "Alfa Slab One"
});
tabPopupLabel.anchor.set(0.5, 0);
tabPopupLabel.x = 1820 / 2;
tabPopupLabel.y = 60;
tabPopup.addChild(tabPopupLabel);
// --- 3x3 grid of squares with assets game1 to game9 ---
var tabGridRows = 3;
var tabGridCols = 3;
var tabCellSize = 400; // px, fits 3x3 in 1820x1800 with margin
var tabCellMargin = 40;
var tabGridOriginX = Math.floor((1820 - (tabGridCols * tabCellSize + (tabGridCols - 1) * tabCellMargin)) / 2);
var tabGridOriginY = 220; // below the label
// Store references to tab squares for later use if needed
var tabSquares = [];
for (var row = 0; row < tabGridRows; ++row) {
for (var col = 0; col < tabGridCols; ++col) {
var idx = row * tabGridCols + col + 1; // 1..9
// Draw square background using game1..game9 asset
var square = LK.getAsset('game' + idx, {
width: tabCellSize,
height: tabCellSize,
anchorX: 0,
anchorY: 0,
x: tabGridOriginX + col * (tabCellSize + tabCellMargin),
y: tabGridOriginY + row * (tabCellSize + tabCellMargin)
});
square.interactive = true;
// Add a simple down handler for demonstration (replace with your logic)
square.down = function (index) {
return function (x, y, obj) {
// Flash the square when pressed
LK.effects.flashObject(this, 0xffffff, 200);
// If this is the game1 button, save and open Merge TL Mania
if (index === 1) {
// Save the current game as "Merge TL Mania"
storage.saveGame && storage.saveGame("Merge TL Mania");
// Open the Merge TL Mania game (if supported by the platform)
if (typeof LK.openGame === "function") {
LK.openGame("Merge TL Mania");
}
}
// If this is the game2 button, open the external TLeater game
if (index === 2) {
// Open the external game in a new tab/window
if (typeof window !== "undefined" && typeof window.open === "function") {
window.open("https://upit.com/create/-jjol2nG8v/history", "_blank");
}
}
};
}(idx);
tabPopup.addChild(square);
tabSquares.push(square);
}
}
// Add the popup to the game
game.addChild(tabPopup);
// Button interaction to open the tab removed
// --- Helper: update next tile preview ---
function updateNextTilePreview() {
if (nextTilePreview) {
nextTilePreview.destroy();
}
if (nextTileTxt) {
nextTileTxt.destroy();
}
var nextTilePreviewY = donationTxt.y + donationTxt.height + 180;
nextTilePreview = LK.getAsset(TL_LEVELS[nextLevelIdx].asset, {
anchorX: 0.5,
anchorY: 0.0,
x: 2048 / 2,
y: nextTilePreviewY
});
nextTileTxt = new Text2('Next', {
size: 60,
fill: '#1a1a1a',
font: "Alfa Slab One"
});
nextTileTxt.anchor.set(0.5, 1);
nextTileTxt.x = 2048 / 2;
nextTileTxt.y = nextTilePreview.y - 10;
game.addChild(nextTilePreview);
game.addChild(nextTileTxt);
}
// --- Spawn a new tile at (gx,gy) with levelIdx ---
function spawnTile(gx, gy, levelIdx) {
var tile = new TLTile();
tile.setLevel(levelIdx);
tile.setGrid(gx, gy);
tile.spawnPop();
grid[gx][gy] = tile;
game.addChild(tile);
return tile;
}
// --- Find empty cells ---
function getEmptyCells() {
var arr = [];
for (var i = 0; i < GRID_SIZE; ++i) {
for (var j = 0; j < GRID_SIZE; ++j) {
if (!grid[i][j]) arr.push({
gx: i,
gy: j
});
}
}
return arr;
}
// --- Merge logic ---
// Returns true if a merge happened
function tryMergeAt(gx, gy) {
var tile = grid[gx][gy];
if (!tile) return false;
var merged = false;
// Find all adjacent (left, right, above) same-level tiles
var mergeGroup = [{
gx: gx,
gy: gy,
tile: tile
}];
// Left
if (gx > 0 && grid[gx - 1][gy] && grid[gx - 1][gy].levelIdx === tile.levelIdx) {
mergeGroup.push({
gx: gx - 1,
gy: gy,
tile: grid[gx - 1][gy]
});
}
// Right
if (gx < GRID_SIZE - 1 && grid[gx + 1][gy] && grid[gx + 1][gy].levelIdx === tile.levelIdx) {
mergeGroup.push({
gx: gx + 1,
gy: gy,
tile: grid[gx + 1][gy]
});
}
// Above
if (gy > 0 && grid[gx][gy - 1] && grid[gx][gy - 1].levelIdx === tile.levelIdx) {
mergeGroup.push({
gx: gx,
gy: gy - 1,
tile: grid[gx][gy - 1]
});
}
// Only merge if there are at least 2 of the same level (including self)
if (mergeGroup.length > 1) {
// Find the "main" tile to upgrade (choose the first in mergeGroup)
var main = mergeGroup[0];
var nextIdx = getNextLevelIndex(tile.levelIdx);
if (nextIdx === null) return false; // Already max, can't merge
// Remove all tiles in mergeGroup from grid
for (var i = 0; i < mergeGroup.length; ++i) {
var g = mergeGroup[i];
grid[g.gx][g.gy] = null;
}
// Animate all but main tile to move to main, then destroy
for (var i = 1; i < mergeGroup.length; ++i) {
var g = mergeGroup[i];
g.tile.setHighlight(false);
g.tile.moveTo(main.tile.x, main.tile.y, function (t) {
return function () {
t.destroy();
};
}(g.tile));
}
main.tile.setHighlight(false);
// Upgrade main tile
main.tile.setLevel(nextIdx);
main.tile.mergePop();
// Coin pop
var donationAmt = TL_LEVELS[nextIdx].donation;
main.tile.coinPop(donationAmt);
donation += donationAmt;
storage.donation = donation;
donationTxt.setText('Sermaye: ' + donation + ' TL');
// Place upgraded tile in grid
grid[main.gx][main.gy] = main.tile;
// Check win: if merged to 200TL
if (nextIdx === 5) {
// Win if two 200TL tiles merged
LK.showYouWin();
return true;
}
// After merge, try to merge again at main
LK.setTimeout(function () {
tryMergeAt(main.gx, main.gy);
}, 180);
merged = true;
}
return merged;
}
// --- Drag and drop logic ---
var draggingTile = null;
var dragOrigin = null; // {gx,gy}
var dragOffset = {
x: 0,
y: 0
};
var dragValid = false;
var dragTarget = null;
// Helper: get grid cell from px
function getGridCellFromPos(x, y) {
for (var i = 0; i < GRID_SIZE; ++i) {
for (var j = 0; j < GRID_SIZE; ++j) {
var pos = getTilePixelPos(i, j);
var dx = Math.abs(x - pos.x);
var dy = Math.abs(y - pos.y);
if (dx < TILE_SIZE / 2 && dy < TILE_SIZE / 2) {
return {
gx: i,
gy: j
};
}
}
}
return null;
}
// --- Game events ---
// Place next tile on tap/click
// --- Track if market is open globally ---
var isMarketOpen = false;
game.down = function (x, y, obj) {
if (isMarketOpen) return;
// Don't allow placing in top 100px
if (y < 100) return;
// If dragging, ignore
if (draggingTile) return;
// Only allow placing if empty cell
var cell = getGridCellFromPos(x, y);
if (!cell) return;
if (grid[cell.gx][cell.gy]) return;
// Place tile
var tile = spawnTile(cell.gx, cell.gy, nextLevelIdx);
// Try merge
LK.setTimeout(function () {
tryMergeAt(cell.gx, cell.gy);
// After merge, check if all slots are filled
var allFilled = true;
for (var i = 0; i < GRID_SIZE; ++i) {
for (var j = 0; j < GRID_SIZE; ++j) {
if (!grid[i][j]) {
allFilled = false;
break;
}
}
if (!allFilled) break;
}
if (allFilled) {
LK.showGameOver();
}
}, 120);
// Next tile
nextLevelIdx = randomLevelIdx();
updateNextTilePreview();
};
// --- Drag to move tiles (optional, for more fun) ---
game.move = function (x, y, obj) {
if (isMarketOpen) return;
// If not dragging, check if user is holding on a tile
if (!draggingTile && obj && obj.event && obj.event.type === 'pointerdown') {
var cell = getGridCellFromPos(x, y);
if (!cell) return;
var tile = grid[cell.gx][cell.gy];
if (!tile) return;
draggingTile = tile;
dragOrigin = {
gx: cell.gx,
gy: cell.gy
};
dragOffset.x = tile.x - x;
dragOffset.y = tile.y - y;
tile.setHighlight(true);
}
// If dragging
if (draggingTile) {
draggingTile.x = x + dragOffset.x;
draggingTile.y = y + dragOffset.y;
// Highlight valid drop
var cell = getGridCellFromPos(x, y);
if (cell && (!grid[cell.gx][cell.gy] || cell.gx === dragOrigin.gx && cell.gy === dragOrigin.gy)) {
dragValid = true;
dragTarget = cell;
draggingTile.setHighlight(true);
} else {
dragValid = false;
dragTarget = null;
draggingTile.setHighlight(false);
}
}
};
game.up = function (x, y, obj) {
if (isMarketOpen) return;
if (draggingTile) {
// Drop
if (dragValid && dragTarget && (dragTarget.gx !== dragOrigin.gx || dragTarget.gy !== dragOrigin.gy)) {
// Move tile
grid[dragOrigin.gx][dragOrigin.gy] = null;
grid[dragTarget.gx][dragTarget.gy] = draggingTile;
draggingTile.setGrid(dragTarget.gx, dragTarget.gy);
draggingTile.setHighlight(false);
// Try merge
LK.setTimeout(function () {
tryMergeAt(dragTarget.gx, dragTarget.gy);
}, 120);
} else {
// Snap back
draggingTile.setGrid(dragOrigin.gx, dragOrigin.gy);
draggingTile.setHighlight(false);
}
draggingTile = null;
dragOrigin = null;
dragValid = false;
dragTarget = null;
}
};
// --- Game update (not used for logic, but required) ---
game.update = function () {
// No per-frame logic needed
};
// --- Start: spawn 2 random tiles ---
function startGame() {
var empties = getEmptyCells();
for (var i = 0; i < 2; ++i) {
if (empties.length === 0) break;
var idx = Math.floor(Math.random() * empties.length);
var cell = empties[idx];
var lvl = randomLevelIdx();
spawnTile(cell.gx, cell.gy, lvl);
empties.splice(idx, 1);
}
}
startGame();
;
// Save this scene as MergeTL and open a new scene named TLeater
// Scene change to 'TLeater' would happen here if supported
white restart button but no have text. In-Game asset. 2d. High contrast. No shadows
round money board. In-Game asset. 2d. High contrast. No shadows
black wallpaper,no text. In-Game asset. 2d. High contrast. No shadows
4x4 grid no emoji no text , dark,black,shadow. In-Game asset. 2d. High contrast. No shadows
360x120 market text black,shadow,white. In-Game asset. 2d. High contrast. No shadows