Code edit (3 edits merged)
Please save this source code
User prompt
Apply the same stroke stroke width fill etc to the startGameText2 text
Code edit (5 edits merged)
Please save this source code
User prompt
Apply to Score and Level Text2 the same style as previewLabel (NEXT)
Code edit (8 edits merged)
Please save this source code
User prompt
The text2 NEXT should have a bigger stroke, it's super thin
Code edit (4 edits merged)
Please save this source code
User prompt
The margin_cell at row 0 in the differnet collumns should be asset of type margin_cell_top and not margin_cell
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Column = Container.expand(function (gemTypes) { var self = Container.call(this); self.gems = []; self.isActive = false; // Create the three gems that form the column for (var i = 0; i < 3; i++) { var type = gemTypes && gemTypes[i] ? gemTypes[i] : null; var gem = new Gem(type); gem.y = -i * CELL_SIZE; self.gems.push(gem); self.addChild(gem); } self.rotate = function () { if (!self.isActive) { return; } // Move the last gem to a temporary position for animation var lastGem = self.gems.pop(); var firstGem = self.gems[0]; var middleGem = self.gems[1]; // Animate the rotation LK.getSound('rotate').play(); // Update the gems array with the new order self.gems = [lastGem, firstGem, middleGem]; // Update positions to match new order tween(lastGem, { y: firstGem.y }, { duration: 150 }); tween(firstGem, { y: middleGem.y }, { duration: 150 }); tween(middleGem, { y: lastGem.y + 2 * CELL_SIZE }, { duration: 150, onFinish: function onFinish() { // Make sure to only reposition if the column is still active if (self.isActive) { // Reset positions after animation for (var i = 0; i < 3; i++) { self.gems[i].y = -i * CELL_SIZE; } } } }); }; self.getTypes = function () { return self.gems.map(function (gem) { return gem.type; }); }; return self; }); var GameBoard = Container.expand(function () { var self = Container.call(this); self.grid = []; self.cellContainer = self.addChild(new Container()); self.gemContainer = self.addChild(new Container()); // Create background var boardBg = self.cellContainer.attachAsset('board_bg', { anchorX: 0.5, // Center horizontally anchorY: 0.5 // Center vertically }); boardBg.x = COLS * CELL_SIZE / 2; // Center the background on the board boardBg.y = ROWS * CELL_SIZE / 2; // Center the background on the board // Create grid cells for (var row = 0; row < ROWS; row++) { self.grid[row] = []; for (var col = 0; col < COLS; col++) { // Create cell background var cell = LK.getAsset('board_cell', { anchorX: 0.5, anchorY: 0.5, x: col * CELL_SIZE + CELL_SIZE / 2, y: row * CELL_SIZE + CELL_SIZE / 2, alpha: 0 }); self.cellContainer.addChild(cell); self.grid[row][col] = null; // Create margin cells for impassable columns (first 3 and last 3) if (col < 3 || col >= COLS - 3) { // Use 'margin_cell_top' for row 0, 'margin_cell' for others var marginCellAssetId = row === 0 ? 'margin_cell_top' : row == ROWS - 1 ? 'margin_cell_bottom' : 'margin_cell'; var marginCell = LK.getAsset(marginCellAssetId, { anchorX: 0.5, anchorY: 0.5, x: col * CELL_SIZE + CELL_SIZE / 2, y: row * CELL_SIZE + CELL_SIZE / 2, alpha: 1 }); self.cellContainer.addChild(marginCell); // Add visual to board container // Use the GLOBAL arrays marginCells.push(marginCell); // Add cell object to global list // Mark column as impassable globally if (!impassableCols.includes(col)) { // Check global list impassableCols.push(col); // Add to global list } // Simulate a frozen cell by adding an entry to frozenGems frozenGems[row + ',' + col] = true; // frozenGems is already global } } } self.addGemToGrid = function (gem, row, col) { if (row < 0 || row >= ROWS || col < 0 || col >= COLS) { return false; } if (self.grid[row][col] !== null) { return false; } gem.x = col * CELL_SIZE + CELL_SIZE / 2; gem.y = row * CELL_SIZE + CELL_SIZE / 2; self.gemContainer.addChild(gem); self.grid[row][col] = gem; return true; }; self.removeGemFromGrid = function (row, col) { if (row < 0 || row >= ROWS || col < 0 || col >= COLS) { return null; } var gem = self.grid[row][col]; if (gem) { self.grid[row][col] = null; delete frozenGems[row + ',' + col]; // Remove gem from the dictionary return gem; } return null; }; self.isColumnFull = function (col) { return self.grid[0][col] !== null; }; self.canPlaceColumn = function (col) { // Check if column is in the impassable zone if (impassableCols.includes(col)) { return false; } // Check if any of the top 3 rows in the column are occupied for (var row = 0; row < 3; row++) { if (col < 0 || col >= COLS) { return false; } if (row < ROWS && self.grid[row][col] !== null) { return false; } } return true; }; self.findFirstEmptyRow = function (col) { for (var row = ROWS - 1; row >= 0; row--) { if (self.grid[row][col] === null) { return row; } } return -1; // Column is full }; self.placeColumn = function (column, col, callback) { var gems = column.gems; var placedGems = []; var firstEmptyRow = self.findFirstEmptyRow(col); if (firstEmptyRow < 0 || firstEmptyRow < gems.length - 1) { if (callback) { callback(false); } return; } // Calculate the current positions for each gem before removing the column var currentPositions = []; for (var i = 0; i < gems.length; i++) { var gem = gems[i]; if (column.parent) { var globalPos = column.parent.toGlobal({ x: gem.x + column.x, y: gem.y + column.y }); currentPositions.push(globalPos); } } // Remove gems from their current parent before placing them // This prevents them from being manipulated during the transition if (column.parent) { column.parent.removeChild(column); } // Place gems from bottom to top for (var i = 0; i < gems.length; i++) { var row = firstEmptyRow - i; if (row >= 0) { // Use the existing gem instead of creating a new one var gem = gems[i]; placedGems.push({ gem: gem, row: row, col: col }); // Remove gem from column container first to avoid parent hierarchy issues if (gem.parent === column) { column.removeChild(gem); } // Use the captured position if available to ensure smooth transition if (currentPositions[i]) { var localPos = self.gemContainer.toLocal(currentPositions[i]); gem.x = localPos.x; gem.y = localPos.y; // Animate to final position tween(gem, { x: col * CELL_SIZE + CELL_SIZE / 2, y: row * CELL_SIZE + CELL_SIZE / 2 }, { duration: 100 }); } else { // Fallback if position wasn't captured gem.x = col * CELL_SIZE + CELL_SIZE / 2; gem.y = row * CELL_SIZE + CELL_SIZE / 2; } // Add the gem to the grid self.gemContainer.addChild(gem); self.grid[row][col] = gem; frozenGems[row + ',' + col] = gem; // Store gem in the dictionary gem.isPlaced = true; // Mark gem as placed to prevent further interaction } } // Make sure drop sound always plays LK.getSound('drop').stop(); LK.getSound('drop').play(); if (callback) { callback(true, placedGems); } }; self.checkMatches = function () { var matchedCells = []; // Check horizontal matches for (var row = 0; row < ROWS; row++) { var count = 1; var type = null; for (var col = 0; col < COLS; col++) { var gem = self.grid[row][col]; if (gem && type === gem.type) { count++; } else { if (count >= 3) { for (var i = 0; i < count; i++) { matchedCells.push({ row: row, col: col - 1 - i }); } } count = 1; type = gem ? gem.type : null; } } if (count >= 3) { for (var i = 0; i < count; i++) { matchedCells.push({ row: row, col: COLS - 1 - i }); } } } // Check vertical matches for (var col = 0; col < COLS; col++) { var count = 1; var type = null; for (var row = 0; row < ROWS; row++) { var gem = self.grid[row][col]; if (gem && type === gem.type) { count++; } else { if (count >= 3) { for (var i = 0; i < count; i++) { matchedCells.push({ row: row - 1 - i, col: col }); } } count = 1; type = gem ? gem.type : null; } } if (count >= 3) { for (var i = 0; i < count; i++) { matchedCells.push({ row: ROWS - 1 - i, col: col }); } } } // Check diagonal matches (top-left to bottom-right) for (var startRow = 0; startRow <= ROWS - 3; startRow++) { for (var startCol = 0; startCol <= COLS - 3; startCol++) { var count = 1; var type = null; // Check diagonal starting at [startRow, startCol] for (var i = 0; i < Math.min(ROWS - startRow, COLS - startCol); i++) { var gem = self.grid[startRow + i][startCol + i]; if (gem && type === gem.type) { count++; } else { if (count >= 3) { // Add matching gems to matchedCells for (var j = 0; j < count; j++) { matchedCells.push({ row: startRow + i - 1 - j, col: startCol + i - 1 - j }); } } count = 1; type = gem ? gem.type : null; } } // Check if there's a match at the end of the diagonal if (count >= 3) { var endI = Math.min(ROWS - startRow, COLS - startCol); for (var j = 0; j < count; j++) { matchedCells.push({ row: startRow + endI - 1 - j, col: startCol + endI - 1 - j }); } } } } // Check diagonal matches (top-right to bottom-left) for (var startRow = 0; startRow <= ROWS - 3; startRow++) { for (var startCol = COLS - 1; startCol >= 2; startCol--) { var count = 1; var type = null; // Check diagonal starting at [startRow, startCol] for (var i = 0; i < Math.min(ROWS - startRow, startCol + 1); i++) { var gem = self.grid[startRow + i][startCol - i]; if (gem && type === gem.type) { count++; } else { if (count >= 3) { // Add matching gems to matchedCells for (var j = 0; j < count; j++) { matchedCells.push({ row: startRow + i - 1 - j, col: startCol - i + 1 + j }); } } count = 1; type = gem ? gem.type : null; } } // Check if there's a match at the end of the diagonal if (count >= 3) { var endI = Math.min(ROWS - startRow, startCol + 1); for (var j = 0; j < count; j++) { matchedCells.push({ row: startRow + endI - 1 - j, col: startCol - endI + 1 + j }); } } } } // Remove duplicates from matchedCells var uniqueMatches = []; var matchMap = {}; for (var i = 0; i < matchedCells.length; i++) { var cell = matchedCells[i]; var key = cell.row + "," + cell.col; if (!matchMap[key]) { matchMap[key] = true; uniqueMatches.push(cell); } } return uniqueMatches; }; self.removeMatches = function (matches, callback) { if (matches.length === 0) { if (callback) { callback(0); } return; } var remainingAnimations = matches.length; var points = matches.length * 10; // Make sure to stop any previously playing match sound to avoid conflicts LK.getSound('match').stop(); // Play the match sound fresh LK.getSound('match').play(); // Flash screen effect for matches - ensure it always triggers LK.effects.flashScreen(0xFFFFFF, 300); matches.forEach(function (match) { var gem = self.grid[match.row][match.col]; if (gem) { self.grid[match.row][match.col] = null; delete frozenGems[match.row + ',' + match.col]; // Remove gem from the dictionary gem.highlight(); LK.setTimeout(function () { gem.animateMatch(function () { self.gemContainer.removeChild(gem); remainingAnimations--; if (remainingAnimations === 0) { if (callback) { callback(points); } } }); }, 100); } else { remainingAnimations--; if (remainingAnimations === 0 && callback) { callback(points); } } }); }; self.applyGravity = function (callback) { var movedGems = false; var animationsRunning = 0; // Iterate bottom to top, right to left for (var col = 0; col < COLS; col++) { for (var row = ROWS - 1; row > 0; row--) { if (self.grid[row][col] === null) { // Find the first non-null gem above this position for (var checkRow = row - 1; checkRow >= 0; checkRow--) { if (self.grid[checkRow][col] !== null) { var gem = self.grid[checkRow][col]; self.grid[checkRow][col] = null; self.grid[row][col] = gem; // Update the frozenGems dictionary delete frozenGems[checkRow + ',' + col]; frozenGems[row + ',' + col] = gem; movedGems = true; animationsRunning++; gem.animateDrop(row * CELL_SIZE + CELL_SIZE / 2, 0, function () { animationsRunning--; if (animationsRunning === 0 && callback) { callback(movedGems); } }); break; } } } } } if (animationsRunning === 0 && callback) { callback(movedGems); } }; return self; }); var Gem = Container.expand(function (type) { var self = Container.call(this); self.type = type || getRandomGemType(); self.isPlaced = false; // Track if gem is part of a placed column var gemSprite = self.attachAsset('gem_' + self.type, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.95, scaleY: 0.95 }); self.setType = function (newType) { self.type = newType; self.removeChildren(); gemSprite = self.attachAsset('gem_' + newType, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.95, scaleY: 0.95 }); }; self.highlight = function () { tween(gemSprite, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200, easing: tween.easeOut }); }; self.unhighlight = function () { tween(gemSprite, { scaleX: 0.95, scaleY: 0.95 }, { duration: 200, easing: tween.easeOut }); }; self.animateMatch = function (callback) { tween(gemSprite, { alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { if (callback) { callback(); } } }); }; self.animateDrop = function (targetY, delay, callback) { // Mark gem as being animated to prevent user interaction during animation self.isAnimating = true; tween(self, { y: targetY }, { duration: 300 + delay, easing: tween.bounceOut, onFinish: function onFinish() { self.isAnimating = false; if (callback) { callback(); } } }); }; // Add down handler to prevent interaction during transition self.down = function (x, y, obj) { // Prevent interaction if gem is being animated or is already placed if (self.isAnimating || self.isPlaced) { return; } // Default behavior for interaction with gems // (This can be expanded if you want gems to be interactive in a certain way) }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x111122 }); /**** * Game Code ****/ // Constants var CELL_SIZE = 120; var COLS = 19; var ROWS = Math.floor(2732 / CELL_SIZE); //var ROWS = 25; var GEM_TYPES = ['red', 'blue', 'green', 'yellow', 'purple']; var DROP_INTERVAL_START = 60; // ms var DROP_INTERVAL_MIN = 60; // ms var DROP_DELTA = 20; var LEVEL_THRESHOLD = 50; // Points needed to level up // Game state var board; var activeColumn; var nextColumn; var dropInterval; var dropTimer = 0; var fallSpeed = DROP_INTERVAL_START; var gameActive = false; var score = 0; var level = 1; var nextColumnPreview; var columnPositionX = 0; // Dictionary to track frozen gems var frozenGems = {}; // Arrays to track impassable columns and their visual representation var impassableCols = []; // Stores column indices that are impassable var marginCells = []; // Stores the Container objects for margin cell visuals // UI elements var scoreText; var levelText; var highScoreText; function getRandomGemType() { var index = Math.floor(Math.random() * GEM_TYPES.length); return GEM_TYPES[index]; } function setupUI() { // Score text scoreText = new Text2('SCORE: 0', { size: 50, fill: 0xFFFFFF, // Changed to white stroke: 0xFFFFFF, // Add white stroke strokeThickness: 5 // Thicker stroke for better visibility }); scoreText.anchor.set(0.5, 0); scoreText.y = 50; LK.gui.top.addChild(scoreText); // Level text levelText = new Text2('LEVEL: 1', { size: 50, fill: 0xFFFFFF, // Changed to white stroke: 0xFFFFFF, // Add white stroke strokeThickness: 5 // Thicker stroke for better visibility }); levelText.anchor.set(0.5, 0); levelText.y = 100; LK.gui.top.addChild(levelText); // High score text var highScore = storage.highScore || 0; highScoreText = new Text2('BEST: ' + highScore, { size: 40, fill: 0x00FF00, // Changed to white stroke: 0xFFFFFF, // Add white stroke strokeThickness: 5 // Thicker stroke for better visibility }); highScoreText.anchor.set(0.5, 0); highScoreText.y = 150; LK.gui.top.addChild(highScoreText); } function updateScore(points) { score += points; scoreText.setText('SCORE: ' + score); // Check if player leveled up var newLevel = Math.floor(score / LEVEL_THRESHOLD) + 1; if (newLevel > level) { level = newLevel; levelText.setText('LEVEL: ' + level); // Increase game speed fallSpeed = Math.max(DROP_INTERVAL_MIN, DROP_INTERVAL_START - (level - 1) * DROP_DELTA); // Adjust fallSpeed based on the current level // Play level up sound LK.getSound('levelup').stop(); // Stop first to ensure it plays fresh LK.getSound('levelup').play(); // Flash effect for level up LK.effects.flashScreen(0x00FFFF, 500); } // Update high score if needed var highScore = storage.highScore || 0; if (score > highScore) { storage.highScore = score; highScoreText.setText('BEST: ' + score); } } function createBoard() { // Clear previous margin cells visually and from the array marginCells.forEach(function (cell) { if (cell && cell.parent) { cell.parent.removeChild(cell); } // Optionally destroy: cell.destroy(); }); marginCells = []; // Reset the global array // Reset impassable columns list impassableCols = []; // Remove old board instance if it exists if (board && board.parent) { board.parent.removeChild(board); // Optionally destroy: board.destroy(); } // Create and position the new board board = new GameBoard(); board.x = (2048 - COLS * CELL_SIZE) / 2; board.y = (2732 - ROWS * CELL_SIZE) / 2; game.addChild(board); } function createNextColumnPreview() { nextColumnPreview = new Container(); nextColumnPreview.x = 2048 - 120; nextColumnPreview.y = 200; // Create the "NEXT" label var previewLabel = new Text2('NEXT', { size: 80, fill: 0xFFFF00, stroke: 0xFFFFFF, // White stroke strokeThickness: 5 // Thicker stroke for better visibility }); previewLabel.anchor.set(0.5, 0); previewLabel.y = -80; // Position at the top of the container nextColumnPreview.addChild(previewLabel); game.addChild(nextColumnPreview); } function updateNextColumnPreview() { // Clear previous preview for (var i = nextColumnPreview.children.length - 1; i > 0; i--) { nextColumnPreview.removeChild(nextColumnPreview.children[i]); } // Add new gems to preview in the correct order if (nextColumn) { // Loop through gems in reverse order to match the visual appearance in the game for (var i = nextColumn.gems.length - 1; i >= 0; i--) { var previewGem = new Gem(nextColumn.gems[i].type); previewGem.x = 0; // Position from top to bottom in the preview previewGem.y = 80 + (nextColumn.gems.length - 1 - i) * CELL_SIZE; previewGem.scale.set(0.8); nextColumnPreview.addChild(previewGem); } } } function createNewColumn() { var column = new Column(); column.isActive = true; column.fastDrop = false; // Initialize fastDrop property for speed control return column; } function startGame() { // Reset game state score = 0; level = 1; fallSpeed = DROP_INTERVAL_START; // Initialize fallSpeed with the starting drop interval gameActive = true; dropTimer = 0; // Clear frozen gems dictionary frozenGems = {}; // --- Start Cleanup --- // Remove title screen elements safely if (typeof titleImage !== 'undefined' && titleImage && titleImage.parent) { titleImage.destroy(); // Use destroy to free resources titleImage = null; // Nullify reference } if (typeof startGameText !== 'undefined' && startGameText && startGameText.parent) { startGameText.destroy(); startGameText = null; } if (typeof blackBg !== 'undefined' && blackBg && blackBg.parent) { blackBg.destroy(); blackBg = null; } // --- End Cleanup --- // Create the game board (handles its own cleanup now) createBoard(); // Create the preview for the next column if (nextColumnPreview && nextColumnPreview.parent) { // Check parent before removing game.removeChild(nextColumnPreview); // nextColumnPreview.destroy(); // Consider if needed } createNextColumnPreview(); // Set up UI (ensure setupUI handles potential existing UI elements if necessary) setupUI(); // Create initial columns activeColumn = createNewColumn(); nextColumn = createNewColumn(); updateNextColumnPreview(); // Position active column (avoid impassable columns) columnPositionX = Math.floor(COLS / 2); // Ensure starting position is not in an impassable column while (impassableCols.includes(columnPositionX)) { columnPositionX = Math.min(COLS - 4, Math.max(3, columnPositionX)); } activeColumn.x = board.x + columnPositionX * CELL_SIZE + CELL_SIZE / 2; activeColumn.y = 0; game.addChild(activeColumn); // Start music LK.playMusic('bgmusic', { fade: { start: 0, end: 0.4, duration: 1000 } }); } function processMatches(callback) { var matches = board.checkMatches(); if (matches.length > 0) { // Ensure sound and visual feedback triggers for every match board.removeMatches(matches, function (points) { updateScore(points); board.applyGravity(function (movedGems) { // Check for chain reactions if (movedGems) { // For chain reactions, process additional matches processMatches(callback); } else { if (callback) { callback(); } } }); }); } else { if (callback) { callback(); } } } function spawnNewColumn() { activeColumn = nextColumn; nextColumn = createNewColumn(); updateNextColumnPreview(); columnPositionX = Math.floor(COLS / 2); // Ensure new column doesn't spawn in an impassable column while (impassableCols.includes(columnPositionX)) { columnPositionX = Math.min(COLS - 4, Math.max(3, columnPositionX)); } activeColumn.x = board.x + columnPositionX * CELL_SIZE + CELL_SIZE / 2; activeColumn.y = 0; game.addChild(activeColumn); // Check if game over if (!board.canPlaceColumn(columnPositionX)) { gameActive = false; LK.showGameOver(); } else { activeColumn.isActive = true; // Reactivate the new column } } function moveColumnLeft() { if (!gameActive || !activeColumn || !activeColumn.isActive) { return; } if (columnPositionX > 0) { // Check if there's a collision in the new position var canMove = true; var currentRow = Math.floor(activeColumn.y / CELL_SIZE); for (var i = 0; i < activeColumn.gems.length; i++) { var gemRow = currentRow - i; if (gemRow >= 0 && gemRow < ROWS) { var gemKey = gemRow + ',' + (columnPositionX - 1); if (frozenGems[gemKey]) { canMove = false; break; } } } if (canMove) { columnPositionX--; activeColumn.x = board.x + columnPositionX * CELL_SIZE + CELL_SIZE / 2; } } } function moveColumnRight() { if (!gameActive || !activeColumn || !activeColumn.isActive) { return; } if (columnPositionX < COLS - 1) { // Check if there's a collision in the new position var canMove = true; var currentRow = Math.floor(activeColumn.y / CELL_SIZE); for (var i = 0; i < activeColumn.gems.length; i++) { var gemRow = currentRow - i; if (gemRow >= 0 && gemRow < ROWS) { var gemKey = gemRow + ',' + (columnPositionX + 1); if (frozenGems[gemKey]) { canMove = false; break; } } } if (canMove) { columnPositionX++; activeColumn.x = board.x + columnPositionX * CELL_SIZE + CELL_SIZE / 2; } } } function rotateColumn() { if (!gameActive || !activeColumn) { return; } activeColumn.rotate(); } function dropColumn() { if (!gameActive || !activeColumn || !activeColumn.isActive) { return; } // First, make it inactive to prevent further user interaction activeColumn.isActive = false; // Update column position activeColumn.x = board.x + columnPositionX * CELL_SIZE + CELL_SIZE / 2; // Make sure the column is not interactive during the placement process // by making all gems non-interactive activeColumn.gems.forEach(function (gem) { gem.interactive = false; }); // Begin the placement process board.placeColumn(activeColumn, columnPositionX, function (success, placedGems) { if (success) { // We don't need to remove activeColumn here as it's already handled in placeColumn // But we do process matches processMatches(function () { spawnNewColumn(); // Spawn a new column after processing matches }); } else { // Failed to place column, game over gameActive = false; LK.showGameOver(); } }); } // Input handlers game.down = function (x, y, obj) { if (!gameActive) { return; } // Check if touch is in the bottom 10% of the screen if (y > 2732 * 0.9) { // If active column exists and is active, apply fast drop (10x speed) if (activeColumn && activeColumn.isActive) { // Set a flag for fast dropping activeColumn.fastDrop = true; } return; } // Determine which action to take based on touch position var boardX = x - board.x; // If touch is on the board if (boardX >= 0 && boardX < COLS * CELL_SIZE) { var touchCol = Math.floor(boardX / CELL_SIZE); // If touch is on the left side of the active column, move left if (touchCol < columnPositionX) { moveColumnLeft(); } // If touch is on the right side of the active column, move right else if (touchCol > columnPositionX) { moveColumnRight(); } // If touch is on the active column, rotate it else { rotateColumn(); } } }; game.move = function (x, y, obj) { // Optional: handle drag for more fluid control }; game.up = function (x, y, obj) { // Optional: implement swipe detection for quick drop if (gameActive && y > game.down.y + 100) { dropColumn(); } // Reset fast drop when touch is released if (activeColumn && activeColumn.isActive) { activeColumn.fastDrop = false; } }; game.update = function () { // Ensure margin cells are always rendered on top within their container (board.cellContainer) // This needs to run even when the game isn't "active" if the board is visible before start if (marginCells && marginCells.length > 0) { for (var i = 0; i < marginCells.length; i++) { var cell = marginCells[i]; // Check if cell and its parent container exist before manipulating if (cell && cell.parent) { var parentContainer = cell.parent; // Store parent reference try { // Bring cell to the top of its parent's display list // This ensures it draws over other cells in the cellContainer parentContainer.removeChild(cell); parentContainer.addChild(cell); } catch (e) { // Log error if manipulation fails, but don't crash console.log("Error updating margin cell rendering:", e); } } } } // Only run game logic updates if the game is active if (!gameActive || !activeColumn || !activeColumn.isActive) { return; } // Update column position using rows var currentRow = Math.floor(activeColumn.y / CELL_SIZE); // Apply 10x speed multiplier if fast drop is active var currentFallSpeed = activeColumn.fastDrop ? fallSpeed * 10 : fallSpeed; // Calculate the next row position based on the current fall speed dropTimer += currentFallSpeed; // Increment dropTimer by fallSpeed (or fast fallSpeed) if (dropTimer >= 1000) { // Check if dropTimer has reached the threshold for a drop // 1000ms is the base interval for a row drop dropTimer = 0; // Check if the column can move down var canMoveDown = true; var nextRow = currentRow + 1; // Check if any gem in the column would collide with a frozen gem for (var i = 0; i < activeColumn.gems.length; i++) { var gemRow = nextRow - i; if (gemRow >= 0 && gemRow < ROWS) { var gemKey = gemRow + ',' + columnPositionX; if (frozenGems[gemKey]) { canMoveDown = false; break; } } } // Check if column reached the bottom if (nextRow >= ROWS) { canMoveDown = false; } if (canMoveDown) { activeColumn.y = nextRow * CELL_SIZE; // Move down } else { // If the column can't move down anymore, trigger the placement immediately // but make sure we prevent further direct manipulation if (activeColumn && activeColumn.isActive) { dropColumn(); } return; } } // Check for immediate collisions (for fast drops or manual movements) // Only perform these checks if the column is still active if (activeColumn && activeColumn.isActive) { var checkRow = Math.floor(activeColumn.y / CELL_SIZE); // Check if any gem in the column is colliding with a frozen gem for (var i = 0; i < activeColumn.gems.length; i++) { var gemRow = checkRow - i; if (gemRow >= 0 && gemRow < ROWS) { var gemKey = gemRow + ',' + columnPositionX; if (frozenGems[gemKey]) { // Move column back up to avoid overlap activeColumn.y = (gemRow + i) * CELL_SIZE; dropColumn(); return; } } } // Check if column reached the bottom if (checkRow >= ROWS) { activeColumn.y = (ROWS - 1) * CELL_SIZE; dropColumn(); return; } } }; // Initialize empty arrays before creating the board impassableCols = []; marginCells = []; // Initialize the board if (board) { game.removeChild(board); } // Create and display the title image in the center of the screen var titleImage = LK.getAsset('title', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 - 300 }); var blackBg = LK.getAsset('blackBg', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.25 }); game.addChild(blackBg); game.addChild(titleImage); startGameText = new Text2('COLUMNI', { size: 150, fill: 0xFFFFFF, align: "center", font: "Comic Sans MS", fontWeight: "bold" }); // Rainbow color array var rainbowColors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x8B00FF]; var colorIndex = 0; // Function to cycle through rainbow colors function cycleRainbowColors() { startGameText.tint = rainbowColors[colorIndex]; colorIndex = (colorIndex + 1) % rainbowColors.length; } // Set interval to change color every 500ms LK.setInterval(cycleRainbowColors, 500); startGameText2 = new Text2('š Tap on the column to š \nš Tap on the bottom of the screen to ā¬ļø\nš Collect gems of the same color in a row', { size: 90, align: 'left', anchorX: 0.5, anchorY: 0.5, fill: 0xFFFFFF, stroke: 0xFFFFFF, strokeThickness: 5 }); startGameText.y = 2732 / 2 + 100; startGameText.x = 2048 / 2 - 400; startGameText.addChild(startGameText2); startGameText2.y = 250; startGameText2.x = -400; game.addChild(startGameText); // Function to start the game // Start the game when the title image is clicked titleImage.down = function (x, y, obj) { titleImage.destroy(); startGameText.destroy(); blackBg.destroy(); startGame(); }; // createBoard(); // Removed: Board creation is now handled by startGame
===================================================================
--- original.js
+++ change.js
@@ -1050,9 +1050,9 @@
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
- alpha: 0.75
+ alpha: 0.25
});
game.addChild(blackBg);
game.addChild(titleImage);
startGameText = new Text2('COLUMNI', {