User prompt
Sometimes the columns get frozen at a position and the logic works (following pieces detec they are frozen at the right place) but they render on top of the screen. Fix it.
User prompt
Fix an issue when the columns, when frozen, they move to the top of the screen instead of stucking in place. This seems to happen when they stuck / get frozen and you still rotate them.
User prompt
Sometimes if i click on the gems as they change from falling to getting stuck, there is a weird behaviour where then are rendered on the top of the screen / cells instead of on the place where they were stuck. Please fix.
User prompt
Sometimes the gems match and they disappear and everything is ok except that the screen does not flash or the sound is not played. Can you fix?
User prompt
If my click / tap on the screen is not on the falling gems, the falling gems should fall at 10x speed during the duration of the tap.
User prompt
By tapping anywhere else when there is no falling gems (it may be existing stuck / frozen gems, that's fine!) make the falling gems fall at a 10x speed
User prompt
If you click on a falling gems now it rotates the gems. Thats good. But I want another behaviour as well: if you don't release the mouse / untap the screen, it will fall down at a 10x speed instead of rotating gems. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
If you click / tap a falling gem but dont' release the button, it will fall at a 10x speed instead of rotating gems.
Code edit (5 edits merged)
Please save this source code
User prompt
Add a text2 "Next" above the next gems
User prompt
If I click on the bottom part of the screen, like the 10% percent of the bottom, the currently falling gems should fall at a much higher speed, like 10x
User prompt
Right now only 3 equal gems in vertical or horizontal "match". Please make it so that three equal color gems in diagonal also match.
Code edit (1 edits merged)
Please save this source code
Code edit (13 edits merged)
Please save this source code
User prompt
Do it
Code edit (1 edits merged)
Please save this source code
User prompt
No! The other way around, don't destory boardBg! It should be shown still after starting the game
User prompt
Fix: by clickin on titleImage, the boardBg is destroyed?
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: titleImage.Destroy is not a function' in or related to this line: 'titleImage.Destroy();' Line Number: 833
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'blackBg is not defined' in or related to this line: 'game.addChild(blackBg);' Line Number: 809
/**** * 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; } } 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 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 = 25; 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 = {}; // 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: 0x000000 // Changed to black }); scoreText.anchor.set(0.5, 0); scoreText.y = 50; LK.gui.top.addChild(scoreText); // Level text levelText = new Text2('LEVEL: 1', { size: 50, fill: 0x000000 // Changed to black }); 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: 0x800080 // Changed to purple }); 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() { 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: 0x000000 }); 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 = {}; // Create the preview for the next column if (nextColumnPreview) { game.removeChild(nextColumnPreview); } createNextColumnPreview(); // Set up UI setupUI(); // Create initial columns activeColumn = createNewColumn(); nextColumn = createNewColumn(); updateNextColumnPreview(); // Position active column columnPositionX = Math.floor(COLS / 2); 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); 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 () { 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 the board if (board) { game.removeChild(board); } createBoard(); // 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 }); var blackBg = LK.getAsset('blackBg', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.75 }); 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('Press on the logo to start...', { size: 150, fill: 0xffffff // Changed to black, }); startGameText.y = 2732 / 2 + 400; startGameText.x = 2048 / 2 - 400; startGameText.addChild(startGameText2); startGameText2.y = 200; 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(); };
===================================================================
--- original.js
+++ change.js
@@ -150,8 +150,20 @@
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);
@@ -170,15 +182,30 @@
// Remove gem from column container first to avoid parent hierarchy issues
if (gem.parent === column) {
column.removeChild(gem);
}
- // Update the gem's position
- gem.x = col * CELL_SIZE + CELL_SIZE / 2;
- gem.y = row * CELL_SIZE + CELL_SIZE / 2;
+ // 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();