Code edit (1 edits merged)
Please save this source code
User prompt
Margin cells are not visible, not created, and not working at all. Please fix / redo.
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'marginCells[i].parent.removeChild(marginCells[i]);' Line Number: 916
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'marginCells[i].parent.addChild(marginCells[i]);' Line Number: 916
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'marginCells[i].parent.addChild(marginCells[i]);' Line Number: 916
User prompt
First three cols should be impassable. Last three cols also. For those impassable cells, use the margin_cell asset. It hsould be visible and renderer last, on top (after) everything in the game, to be visible.
User prompt
Fix, show them on top
User prompt
It's not working. I can move my columns all the way left to the border of the screen.
Code edit (14 edits merged)
Please save this source code
User prompt
The play space is too big, it's using all the screen. Please, add margins to the left and to the right, maybe 2-3 rows on both sides. Place a "margin" asset on those cells.
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
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.
/****
* 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() {
// 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;
}
// 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
});
// Update the gem's position
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
// If it's the last gem, notify callback
if (i === gems.length - 1) {
// 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();
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) {
tween(self, {
y: targetY
}, {
duration: 300 + delay,
easing: tween.bounceOut,
onFinish: function onFinish() {
if (callback) {
callback();
}
}
});
};
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;
}
activeColumn.x = board.x + columnPositionX * CELL_SIZE + CELL_SIZE / 2;
activeColumn.isActive = false;
board.placeColumn(activeColumn, columnPositionX, function (success, placedGems) {
if (success) {
// Store the positions of the frozen gems
placedGems.forEach(function (placedGem) {
frozenGems[placedGem.row + ',' + placedGem.col] = placedGem.gem;
});
game.removeChild(activeColumn);
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
// The bottom-most gem in the column is at position nextRow
// So we need to check if this position is beyond the board
if (nextRow >= ROWS) {
canMoveDown = false;
}
if (canMoveDown) {
activeColumn.y = nextRow * CELL_SIZE; // Move down
} else {
// Column has hit something or reached the bottom
dropColumn();
return;
}
}
// Check for immediate collisions (for fast drops or manual movements)
var checkRow = Math.floor(activeColumn.y / CELL_SIZE);
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
// Only freeze the column if the bottom-most gem has reached the bottom row
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
@@ -167,8 +167,10 @@
self.grid[row][col] = gem;
frozenGems[row + ',' + col] = gem; // Store gem in the dictionary
// If it's the last gem, notify callback
if (i === gems.length - 1) {
+ // Make sure drop sound always plays
+ LK.getSound('drop').stop();
LK.getSound('drop').play();
if (callback) {
callback(true, placedGems);
}
@@ -331,13 +333,13 @@
return;
}
var remainingAnimations = matches.length;
var points = matches.length * 10;
- // Always play match sound and flash effect when matches are found
- // Force sound to play even if it's already playing
+ // 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 for any match (3 or more gems)
+ // 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) {
@@ -546,8 +548,9 @@
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);
}
@@ -638,13 +641,15 @@
}
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();
@@ -764,31 +769,8 @@
activeColumn.fastDrop = true;
}
return;
}
- // Check if touch is on the active column
- var isOnActiveColumn = false;
- if (activeColumn && activeColumn.isActive) {
- var touchCol = Math.floor((x - board.x) / CELL_SIZE);
- var currentRow = Math.floor(activeColumn.y / CELL_SIZE);
- // Check if touch is within the active column's bounds
- if (touchCol === columnPositionX) {
- // Check if the touch is within the vertical range of the gems
- for (var i = 0; i < activeColumn.gems.length; i++) {
- var gemRow = currentRow - i;
- var gemY = board.y + gemRow * CELL_SIZE;
- // Check if touch is within this gem's vertical range (with some padding)
- if (y >= gemY - CELL_SIZE / 2 && y <= gemY + CELL_SIZE / 2) {
- isOnActiveColumn = true;
- break;
- }
- }
- }
- // If touch is not on the active column, apply fast drop
- if (!isOnActiveColumn) {
- activeColumn.fastDrop = true;
- }
- }
// 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) {
@@ -811,9 +793,9 @@
// Optional: handle drag for more fluid control
};
game.up = function (x, y, obj) {
// Optional: implement swipe detection for quick drop
- if (gameActive && obj.event && obj.event.down && y > obj.event.down.y + 100) {
+ if (gameActive && y > game.down.y + 100) {
dropColumn();
}
// Reset fast drop when touch is released
if (activeColumn && activeColumn.isActive) {