User prompt
Say the word tutorial on the top of the screen
User prompt
Please fix the bug: 'Timeout.tick error: Cannot read properties of null (reading 'gridX')' in or related to this line: 'var originalX1 = tempFood1.gridX;' Line Number: 449
User prompt
When u swipe and don't match the food goes back to where it was with an animation ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the screen bigger
User prompt
Make swipe controls
Code edit (1 edits merged)
Please save this source code
User prompt
Food Frenzy Match
Initial prompt
Make a candy crush based game with all kinds of foods if you match the same foods 3 in a row it breaks and u get closer to finishing
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var FoodItem = Container.expand(function (foodType) { var self = Container.call(this); self.foodType = foodType; self.gridX = -1; self.gridY = -1; self.isMatched = false; self.isAnimating = false; var foodGraphics = self.attachAsset(foodType, { anchorX: 0.5, anchorY: 0.5 }); self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2; self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2; }; self.animateToPosition = function (targetX, targetY, callback) { self.isAnimating = true; tween(self, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.isAnimating = false; if (callback) callback(); } }); }; self.animateMatch = function (callback) { self.isMatched = true; tween(self, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 200, easing: tween.easeIn, onFinish: callback }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c1810 }); /**** * Game Code ****/ var GRID_SIZE = 8; var CELL_SIZE = 200; var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2; var GRID_START_Y = 400; var FOOD_TYPES = ['apple', 'banana', 'orange', 'grape', 'cherry', 'lemon']; var grid = []; var selectedFood = null; var isProcessingMatches = false; var movesLeft = 30; var currentScore = 0; var targetMatches = 50; var matchesCleared = 0; // Initialize grid array for (var x = 0; x < GRID_SIZE; x++) { grid[x] = []; for (var y = 0; y < GRID_SIZE; y++) { grid[x][y] = null; } } // Create grid background var gridBackground = new Container(); game.addChild(gridBackground); for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { var cell = LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5 }); cell.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2; cell.y = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2; cell.alpha = 0.3; gridBackground.addChild(cell); } } // Create UI var scoreText = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 150; var movesText = new Text2('Moves: 30', { size: 60, fill: 0xFFFFFF }); movesText.anchor.set(0, 0); LK.gui.topLeft.addChild(movesText); movesText.x = 150; movesText.y = 50; var targetText = new Text2('Target: 0/50', { size: 60, fill: 0xFFFFFF }); targetText.anchor.set(1, 0); LK.gui.topRight.addChild(targetText); targetText.y = 50; function getRandomFoodType() { return FOOD_TYPES[Math.floor(Math.random() * FOOD_TYPES.length)]; } function createFoodItem(x, y) { var foodType = getRandomFoodType(); var food = new FoodItem(foodType); food.setGridPosition(x, y); grid[x][y] = food; game.addChild(food); return food; } function initializeGrid() { for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { createFoodItem(x, y); } } // Remove initial matches var foundMatches = true; while (foundMatches) { var matches = findAllMatches(); if (matches.length > 0) { for (var i = 0; i < matches.length; i++) { var match = matches[i]; if (grid[match.x] && grid[match.x][match.y]) { grid[match.x][match.y].destroy(); grid[match.x][match.y] = null; } } fillEmptySpaces(); } else { foundMatches = false; } } } function isValidPosition(x, y) { return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE; } function isAdjacent(x1, y1, x2, y2) { var dx = Math.abs(x1 - x2); var dy = Math.abs(y1 - y2); return dx === 1 && dy === 0 || dx === 0 && dy === 1; } function swapFoods(food1, food2) { if (!food1 || !food2) return false; var x1 = food1.gridX; var y1 = food1.gridY; var x2 = food2.gridX; var y2 = food2.gridY; // Swap in grid grid[x1][y1] = food2; grid[x2][y2] = food1; // Update grid positions food1.setGridPosition(x2, y2); food2.setGridPosition(x1, y1); // Animate swap var targetX1 = GRID_START_X + x2 * CELL_SIZE + CELL_SIZE / 2; var targetY1 = GRID_START_Y + y2 * CELL_SIZE + CELL_SIZE / 2; var targetX2 = GRID_START_X + x1 * CELL_SIZE + CELL_SIZE / 2; var targetY2 = GRID_START_Y + y1 * CELL_SIZE + CELL_SIZE / 2; food1.animateToPosition(targetX1, targetY1); food2.animateToPosition(targetX2, targetY2); return true; } function findMatches(x, y) { var matches = []; if (!grid[x] || !grid[x][y]) return matches; var foodType = grid[x][y].foodType; // Check horizontal matches var horizontalMatches = [{ x: x, y: y }]; // Check left for (var i = x - 1; i >= 0; i--) { if (grid[i] && grid[i][y] && grid[i][y].foodType === foodType) { horizontalMatches.push({ x: i, y: y }); } else { break; } } // Check right for (var i = x + 1; i < GRID_SIZE; i++) { if (grid[i] && grid[i][y] && grid[i][y].foodType === foodType) { horizontalMatches.push({ x: i, y: y }); } else { break; } } if (horizontalMatches.length >= 3) { matches = matches.concat(horizontalMatches); } // Check vertical matches var verticalMatches = [{ x: x, y: y }]; // Check up for (var i = y - 1; i >= 0; i--) { if (grid[x] && grid[x][i] && grid[x][i].foodType === foodType) { verticalMatches.push({ x: x, y: i }); } else { break; } } // Check down for (var i = y + 1; i < GRID_SIZE; i++) { if (grid[x] && grid[x][i] && grid[x][i].foodType === foodType) { verticalMatches.push({ x: x, y: i }); } else { break; } } if (verticalMatches.length >= 3) { matches = matches.concat(verticalMatches); } return matches; } function findAllMatches() { var allMatches = []; var processed = {}; for (var x = 0; x < GRID_SIZE; x++) { for (var y = 0; y < GRID_SIZE; y++) { if (grid[x] && grid[x][y] && !processed[x + ',' + y]) { var matches = findMatches(x, y); for (var i = 0; i < matches.length; i++) { var match = matches[i]; var key = match.x + ',' + match.y; if (!processed[key]) { allMatches.push(match); processed[key] = true; } } } } } return allMatches; } function processMatches() { if (isProcessingMatches) return; var matches = findAllMatches(); if (matches.length === 0) return; isProcessingMatches = true; LK.getSound('match').play(); var matchCount = matches.length; currentScore += matchCount * 10; matchesCleared += matchCount; updateUI(); var animationsCompleted = 0; for (var i = 0; i < matches.length; i++) { var match = matches[i]; if (grid[match.x] && grid[match.x][match.y]) { grid[match.x][match.y].animateMatch(function () { animationsCompleted++; if (animationsCompleted === matchCount) { // Remove matched foods for (var j = 0; j < matches.length; j++) { var m = matches[j]; if (grid[m.x] && grid[m.x][m.y]) { grid[m.x][m.y].destroy(); grid[m.x][m.y] = null; } } fillEmptySpaces(); LK.setTimeout(function () { isProcessingMatches = false; processMatches(); // Check for cascade matches }, 300); } }); } } if (matchCount === 0) { isProcessingMatches = false; } } function fillEmptySpaces() { // Drop existing foods for (var x = 0; x < GRID_SIZE; x++) { var writeIndex = GRID_SIZE - 1; for (var y = GRID_SIZE - 1; y >= 0; y--) { if (grid[x][y] !== null) { if (y !== writeIndex) { grid[x][writeIndex] = grid[x][y]; grid[x][y] = null; grid[x][writeIndex].setGridPosition(x, writeIndex); var targetY = GRID_START_Y + writeIndex * CELL_SIZE + CELL_SIZE / 2; grid[x][writeIndex].animateToPosition(grid[x][writeIndex].x, targetY); } writeIndex--; } } // Create new foods for empty spaces at top for (var y = 0; y <= writeIndex; y++) { var food = new FoodItem(getRandomFoodType()); food.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2; food.y = GRID_START_Y - (writeIndex - y + 1) * CELL_SIZE + CELL_SIZE / 2; food.gridX = x; food.gridY = y; grid[x][y] = food; game.addChild(food); var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2; food.animateToPosition(food.x, targetY); } } } function updateUI() { scoreText.setText('Score: ' + currentScore); movesText.setText('Moves: ' + movesLeft); targetText.setText('Target: ' + matchesCleared + '/' + targetMatches); } function checkGameEnd() { if (matchesCleared >= targetMatches) { LK.showYouWin(); } else if (movesLeft <= 0) { LK.showGameOver(); } } function getFoodAtPosition(x, y) { var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE); var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE); if (isValidPosition(gridX, gridY) && grid[gridX] && grid[gridX][gridY]) { return grid[gridX][gridY]; } return null; } game.down = function (x, y, obj) { if (isProcessingMatches) return; var food = getFoodAtPosition(x, y); if (food && !food.isAnimating) { if (selectedFood === food) { selectedFood.alpha = 1; selectedFood = null; } else if (selectedFood === null) { selectedFood = food; selectedFood.alpha = 0.7; } else { if (isAdjacent(selectedFood.gridX, selectedFood.gridY, food.gridX, food.gridY)) { var oldSelectedFood = selectedFood; selectedFood.alpha = 1; selectedFood = null; LK.getSound('swap').play(); // Try swap swapFoods(oldSelectedFood, food); LK.setTimeout(function () { var matches = findAllMatches(); if (matches.length === 0) { // Invalid move, swap back swapFoods(oldSelectedFood, food); } else { // Valid move movesLeft--; updateUI(); processMatches(); checkGameEnd(); } }, 350); } else { selectedFood.alpha = 1; selectedFood = food; selectedFood.alpha = 0.7; } } } }; // Initialize the game initializeGrid(); updateUI();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,401 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+var FoodItem = Container.expand(function (foodType) {
+ var self = Container.call(this);
+ self.foodType = foodType;
+ self.gridX = -1;
+ self.gridY = -1;
+ self.isMatched = false;
+ self.isAnimating = false;
+ var foodGraphics = self.attachAsset(foodType, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.setGridPosition = function (gridX, gridY) {
+ self.gridX = gridX;
+ self.gridY = gridY;
+ self.x = GRID_START_X + gridX * CELL_SIZE + CELL_SIZE / 2;
+ self.y = GRID_START_Y + gridY * CELL_SIZE + CELL_SIZE / 2;
+ };
+ self.animateToPosition = function (targetX, targetY, callback) {
+ self.isAnimating = true;
+ tween(self, {
+ x: targetX,
+ y: targetY
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ self.isAnimating = false;
+ if (callback) callback();
+ }
+ });
+ };
+ self.animateMatch = function (callback) {
+ self.isMatched = true;
+ tween(self, {
+ scaleX: 0,
+ scaleY: 0,
+ alpha: 0
+ }, {
+ duration: 200,
+ easing: tween.easeIn,
+ onFinish: callback
+ });
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2c1810
+});
+
+/****
+* Game Code
+****/
+var GRID_SIZE = 8;
+var CELL_SIZE = 200;
+var GRID_START_X = (2048 - GRID_SIZE * CELL_SIZE) / 2;
+var GRID_START_Y = 400;
+var FOOD_TYPES = ['apple', 'banana', 'orange', 'grape', 'cherry', 'lemon'];
+var grid = [];
+var selectedFood = null;
+var isProcessingMatches = false;
+var movesLeft = 30;
+var currentScore = 0;
+var targetMatches = 50;
+var matchesCleared = 0;
+// Initialize grid array
+for (var x = 0; x < GRID_SIZE; x++) {
+ grid[x] = [];
+ for (var y = 0; y < GRID_SIZE; y++) {
+ grid[x][y] = null;
+ }
+}
+// Create grid background
+var gridBackground = new Container();
+game.addChild(gridBackground);
+for (var x = 0; x < GRID_SIZE; x++) {
+ for (var y = 0; y < GRID_SIZE; y++) {
+ var cell = LK.getAsset('gridCell', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ cell.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
+ cell.y = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
+ cell.alpha = 0.3;
+ gridBackground.addChild(cell);
+ }
+}
+// Create UI
+var scoreText = new Text2('Score: 0', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreText);
+scoreText.y = 150;
+var movesText = new Text2('Moves: 30', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+movesText.anchor.set(0, 0);
+LK.gui.topLeft.addChild(movesText);
+movesText.x = 150;
+movesText.y = 50;
+var targetText = new Text2('Target: 0/50', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+targetText.anchor.set(1, 0);
+LK.gui.topRight.addChild(targetText);
+targetText.y = 50;
+function getRandomFoodType() {
+ return FOOD_TYPES[Math.floor(Math.random() * FOOD_TYPES.length)];
+}
+function createFoodItem(x, y) {
+ var foodType = getRandomFoodType();
+ var food = new FoodItem(foodType);
+ food.setGridPosition(x, y);
+ grid[x][y] = food;
+ game.addChild(food);
+ return food;
+}
+function initializeGrid() {
+ for (var x = 0; x < GRID_SIZE; x++) {
+ for (var y = 0; y < GRID_SIZE; y++) {
+ createFoodItem(x, y);
+ }
+ }
+ // Remove initial matches
+ var foundMatches = true;
+ while (foundMatches) {
+ var matches = findAllMatches();
+ if (matches.length > 0) {
+ for (var i = 0; i < matches.length; i++) {
+ var match = matches[i];
+ if (grid[match.x] && grid[match.x][match.y]) {
+ grid[match.x][match.y].destroy();
+ grid[match.x][match.y] = null;
+ }
+ }
+ fillEmptySpaces();
+ } else {
+ foundMatches = false;
+ }
+ }
+}
+function isValidPosition(x, y) {
+ return x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE;
+}
+function isAdjacent(x1, y1, x2, y2) {
+ var dx = Math.abs(x1 - x2);
+ var dy = Math.abs(y1 - y2);
+ return dx === 1 && dy === 0 || dx === 0 && dy === 1;
+}
+function swapFoods(food1, food2) {
+ if (!food1 || !food2) return false;
+ var x1 = food1.gridX;
+ var y1 = food1.gridY;
+ var x2 = food2.gridX;
+ var y2 = food2.gridY;
+ // Swap in grid
+ grid[x1][y1] = food2;
+ grid[x2][y2] = food1;
+ // Update grid positions
+ food1.setGridPosition(x2, y2);
+ food2.setGridPosition(x1, y1);
+ // Animate swap
+ var targetX1 = GRID_START_X + x2 * CELL_SIZE + CELL_SIZE / 2;
+ var targetY1 = GRID_START_Y + y2 * CELL_SIZE + CELL_SIZE / 2;
+ var targetX2 = GRID_START_X + x1 * CELL_SIZE + CELL_SIZE / 2;
+ var targetY2 = GRID_START_Y + y1 * CELL_SIZE + CELL_SIZE / 2;
+ food1.animateToPosition(targetX1, targetY1);
+ food2.animateToPosition(targetX2, targetY2);
+ return true;
+}
+function findMatches(x, y) {
+ var matches = [];
+ if (!grid[x] || !grid[x][y]) return matches;
+ var foodType = grid[x][y].foodType;
+ // Check horizontal matches
+ var horizontalMatches = [{
+ x: x,
+ y: y
+ }];
+ // Check left
+ for (var i = x - 1; i >= 0; i--) {
+ if (grid[i] && grid[i][y] && grid[i][y].foodType === foodType) {
+ horizontalMatches.push({
+ x: i,
+ y: y
+ });
+ } else {
+ break;
+ }
+ }
+ // Check right
+ for (var i = x + 1; i < GRID_SIZE; i++) {
+ if (grid[i] && grid[i][y] && grid[i][y].foodType === foodType) {
+ horizontalMatches.push({
+ x: i,
+ y: y
+ });
+ } else {
+ break;
+ }
+ }
+ if (horizontalMatches.length >= 3) {
+ matches = matches.concat(horizontalMatches);
+ }
+ // Check vertical matches
+ var verticalMatches = [{
+ x: x,
+ y: y
+ }];
+ // Check up
+ for (var i = y - 1; i >= 0; i--) {
+ if (grid[x] && grid[x][i] && grid[x][i].foodType === foodType) {
+ verticalMatches.push({
+ x: x,
+ y: i
+ });
+ } else {
+ break;
+ }
+ }
+ // Check down
+ for (var i = y + 1; i < GRID_SIZE; i++) {
+ if (grid[x] && grid[x][i] && grid[x][i].foodType === foodType) {
+ verticalMatches.push({
+ x: x,
+ y: i
+ });
+ } else {
+ break;
+ }
+ }
+ if (verticalMatches.length >= 3) {
+ matches = matches.concat(verticalMatches);
+ }
+ return matches;
+}
+function findAllMatches() {
+ var allMatches = [];
+ var processed = {};
+ for (var x = 0; x < GRID_SIZE; x++) {
+ for (var y = 0; y < GRID_SIZE; y++) {
+ if (grid[x] && grid[x][y] && !processed[x + ',' + y]) {
+ var matches = findMatches(x, y);
+ for (var i = 0; i < matches.length; i++) {
+ var match = matches[i];
+ var key = match.x + ',' + match.y;
+ if (!processed[key]) {
+ allMatches.push(match);
+ processed[key] = true;
+ }
+ }
+ }
+ }
+ }
+ return allMatches;
+}
+function processMatches() {
+ if (isProcessingMatches) return;
+ var matches = findAllMatches();
+ if (matches.length === 0) return;
+ isProcessingMatches = true;
+ LK.getSound('match').play();
+ var matchCount = matches.length;
+ currentScore += matchCount * 10;
+ matchesCleared += matchCount;
+ updateUI();
+ var animationsCompleted = 0;
+ for (var i = 0; i < matches.length; i++) {
+ var match = matches[i];
+ if (grid[match.x] && grid[match.x][match.y]) {
+ grid[match.x][match.y].animateMatch(function () {
+ animationsCompleted++;
+ if (animationsCompleted === matchCount) {
+ // Remove matched foods
+ for (var j = 0; j < matches.length; j++) {
+ var m = matches[j];
+ if (grid[m.x] && grid[m.x][m.y]) {
+ grid[m.x][m.y].destroy();
+ grid[m.x][m.y] = null;
+ }
+ }
+ fillEmptySpaces();
+ LK.setTimeout(function () {
+ isProcessingMatches = false;
+ processMatches(); // Check for cascade matches
+ }, 300);
+ }
+ });
+ }
+ }
+ if (matchCount === 0) {
+ isProcessingMatches = false;
+ }
+}
+function fillEmptySpaces() {
+ // Drop existing foods
+ for (var x = 0; x < GRID_SIZE; x++) {
+ var writeIndex = GRID_SIZE - 1;
+ for (var y = GRID_SIZE - 1; y >= 0; y--) {
+ if (grid[x][y] !== null) {
+ if (y !== writeIndex) {
+ grid[x][writeIndex] = grid[x][y];
+ grid[x][y] = null;
+ grid[x][writeIndex].setGridPosition(x, writeIndex);
+ var targetY = GRID_START_Y + writeIndex * CELL_SIZE + CELL_SIZE / 2;
+ grid[x][writeIndex].animateToPosition(grid[x][writeIndex].x, targetY);
+ }
+ writeIndex--;
+ }
+ }
+ // Create new foods for empty spaces at top
+ for (var y = 0; y <= writeIndex; y++) {
+ var food = new FoodItem(getRandomFoodType());
+ food.x = GRID_START_X + x * CELL_SIZE + CELL_SIZE / 2;
+ food.y = GRID_START_Y - (writeIndex - y + 1) * CELL_SIZE + CELL_SIZE / 2;
+ food.gridX = x;
+ food.gridY = y;
+ grid[x][y] = food;
+ game.addChild(food);
+ var targetY = GRID_START_Y + y * CELL_SIZE + CELL_SIZE / 2;
+ food.animateToPosition(food.x, targetY);
+ }
+ }
+}
+function updateUI() {
+ scoreText.setText('Score: ' + currentScore);
+ movesText.setText('Moves: ' + movesLeft);
+ targetText.setText('Target: ' + matchesCleared + '/' + targetMatches);
+}
+function checkGameEnd() {
+ if (matchesCleared >= targetMatches) {
+ LK.showYouWin();
+ } else if (movesLeft <= 0) {
+ LK.showGameOver();
+ }
+}
+function getFoodAtPosition(x, y) {
+ var gridX = Math.floor((x - GRID_START_X) / CELL_SIZE);
+ var gridY = Math.floor((y - GRID_START_Y) / CELL_SIZE);
+ if (isValidPosition(gridX, gridY) && grid[gridX] && grid[gridX][gridY]) {
+ return grid[gridX][gridY];
+ }
+ return null;
+}
+game.down = function (x, y, obj) {
+ if (isProcessingMatches) return;
+ var food = getFoodAtPosition(x, y);
+ if (food && !food.isAnimating) {
+ if (selectedFood === food) {
+ selectedFood.alpha = 1;
+ selectedFood = null;
+ } else if (selectedFood === null) {
+ selectedFood = food;
+ selectedFood.alpha = 0.7;
+ } else {
+ if (isAdjacent(selectedFood.gridX, selectedFood.gridY, food.gridX, food.gridY)) {
+ var oldSelectedFood = selectedFood;
+ selectedFood.alpha = 1;
+ selectedFood = null;
+ LK.getSound('swap').play();
+ // Try swap
+ swapFoods(oldSelectedFood, food);
+ LK.setTimeout(function () {
+ var matches = findAllMatches();
+ if (matches.length === 0) {
+ // Invalid move, swap back
+ swapFoods(oldSelectedFood, food);
+ } else {
+ // Valid move
+ movesLeft--;
+ updateUI();
+ processMatches();
+ checkGameEnd();
+ }
+ }, 350);
+ } else {
+ selectedFood.alpha = 1;
+ selectedFood = food;
+ selectedFood.alpha = 0.7;
+ }
+ }
+ }
+};
+// Initialize the game
+initializeGrid();
+updateUI();
\ No newline at end of file