User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'var fruitGraphics = self.attachAsset(self.type.id, {' Line Number: 39
User prompt
the game goes to game over randomly after releasing balls, fix this bug
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'var fruitGraphics = self.attachAsset(self.type.id, {' Line Number: 39
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'var fruitGraphics = self.attachAsset(self.type.id, {' Line Number: 36
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'setText')' in or related to this line: 'scoreText.setText("SCORE: " + LK.getScore());' Line Number: 303
Code edit (1 edits merged)
Please save this source code
User prompt
Fruit Fusion: Bouncy Merge Mania
Initial prompt
Fruit merge - physics based game with bouncing balls
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Fruit = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || FruitTypes.CHERRY;
self.vx = 0;
self.vy = 0;
self.gravity = 0.5;
self.friction = 0.98;
self.elasticity = 0.7;
self.merging = false;
self.isStatic = false;
var fruitGraphics = self.attachAsset(self.type.id, {
anchorX: 0.5,
anchorY: 0.5
});
// Show point value on fruit
var pointsText = new Text2(self.type.points.toString(), {
size: self.type.size * 0.4,
fill: 0xFFFFFF
});
pointsText.anchor.set(0.5, 0.5);
self.addChild(pointsText);
self.update = function () {
if (self.isStatic || self.merging) {
return;
}
// Apply gravity
self.vy += self.gravity;
// Apply velocity
self.x += self.vx;
self.y += self.vy;
// Apply friction
self.vx *= self.friction;
self.vy *= self.friction;
// Wall collision
if (self.x < wallLeft.x + wallLeft.width / 2 + self.type.size / 2) {
self.x = wallLeft.x + wallLeft.width / 2 + self.type.size / 2;
self.vx = -self.vx * self.elasticity;
if (Math.abs(self.vx) > 1) {
LK.getSound('bounce').play();
}
}
if (self.x > wallRight.x - wallRight.width / 2 - self.type.size / 2) {
self.x = wallRight.x - wallRight.width / 2 - self.type.size / 2;
self.vx = -self.vx * self.elasticity;
if (Math.abs(self.vx) > 1) {
LK.getSound('bounce').play();
}
}
// Floor collision
if (self.y > gameFloor.y - gameFloor.height / 2 - self.type.size / 2) {
self.y = gameFloor.y - gameFloor.height / 2 - self.type.size / 2;
self.vy = -self.vy * self.elasticity;
// If we're barely moving, stop completely
if (Math.abs(self.vy) < 2) {
self.vy = 0;
}
if (Math.abs(self.vy) > 1) {
LK.getSound('bounce').play();
}
}
};
self.merge = function (otherFruit) {
if (self.merging || !self.type.next) {
return;
}
self.merging = true;
otherFruit.merging = true;
// Calculate midpoint between fruits for new fruit position
var midX = (self.x + otherFruit.x) / 2;
var midY = (self.y + otherFruit.y) / 2;
// Create merge animation
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
easing: tween.easeOut
});
tween(otherFruit, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Create new merged fruit
var newFruit = new Fruit(self.type.next);
newFruit.x = midX;
newFruit.y = midY;
newFruit.scaleX = 0.5;
newFruit.scaleY = 0.5;
game.addChild(newFruit);
fruits.push(newFruit);
// Add merge points
LK.setScore(LK.getScore() + self.type.next.points);
updateScoreDisplay();
// Animate new fruit growing
tween(newFruit, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.bounceOut
});
// Remove old fruits
var indexSelf = fruits.indexOf(self);
if (indexSelf !== -1) {
fruits.splice(indexSelf, 1);
}
self.destroy();
var indexOther = fruits.indexOf(otherFruit);
if (indexOther !== -1) {
fruits.splice(indexOther, 1);
}
otherFruit.destroy();
// Play merge sound
LK.getSound('merge').play();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf6e58d
});
/****
* Game Code
****/
// Game variables
var FruitTypes = {
CHERRY: {
id: 'cherry',
size: 70,
points: 1,
next: 'grape'
},
GRAPE: {
id: 'grape',
size: 90,
points: 3,
next: 'apple'
},
APPLE: {
id: 'apple',
size: 120,
points: 6,
next: 'orange'
},
ORANGE: {
id: 'orange',
size: 150,
points: 10,
next: 'watermelon'
},
WATERMELON: {
id: 'watermelon',
size: 200,
points: 15,
next: null
}
};
var gameWidth = 2048;
var gameHeight = 2732;
var fruits = [];
var nextFruit = null;
var nextFruitDisplay = null;
var canDropFruit = true;
var wallLeft, wallRight, gameFloor;
var dropPoint = {
x: gameWidth / 2,
y: 200
};
var gameOver = false;
var scoreText;
// Setup game boundaries
function setupBoundaries() {
// Left wall
wallLeft = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
}));
wallLeft.x = 0;
wallLeft.y = gameHeight / 2;
// Right wall
wallRight = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
}));
wallRight.x = gameWidth;
wallRight.y = gameHeight / 2;
// Floor
gameFloor = game.addChild(LK.getAsset('floor', {
anchorX: 0.5,
anchorY: 0.5
}));
gameFloor.x = gameWidth / 2;
gameFloor.y = gameHeight;
}
// Create new next fruit
function createNextFruit() {
// Determine which fruit to spawn (for now just start with smaller fruits)
var fruitProbability = Math.random();
var fruitType;
if (fruitProbability < 0.6) {
fruitType = FruitTypes.CHERRY;
} else if (fruitProbability < 0.85) {
fruitType = FruitTypes.GRAPE;
} else {
fruitType = FruitTypes.APPLE;
}
nextFruit = fruitType;
// Update display
if (nextFruitDisplay) {
nextFruitDisplay.destroy();
}
// Background for next fruit
var nextBg = LK.getAsset('nextFruitBg', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.top.addChild(nextBg);
nextBg.x = 150;
nextBg.y = 150;
// The next fruit preview
var fruitPreview = LK.getAsset(fruitType.id, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
// Next label
var nextLabel = new Text2("NEXT", {
size: 40,
fill: 0xFFFFFF
});
nextLabel.anchor.set(0.5, 0.5);
nextLabel.y = -100;
nextFruitDisplay = new Container();
nextFruitDisplay.addChild(nextBg);
nextFruitDisplay.addChild(fruitPreview);
nextFruitDisplay.addChild(nextLabel);
LK.gui.topLeft.addChild(nextFruitDisplay);
nextFruitDisplay.x = 150;
nextFruitDisplay.y = 150;
}
// Drop fruit at specified position
function dropFruit(x) {
if (!canDropFruit || gameOver) {
return;
}
// Create new fruit
var newFruit = new Fruit(nextFruit);
newFruit.x = x;
newFruit.y = dropPoint.y;
// Add small random x velocity to make it interesting
newFruit.vx = (Math.random() - 0.5) * 3;
game.addChild(newFruit);
fruits.push(newFruit);
// Play drop sound
LK.getSound('drop').play();
// Prepare next fruit
createNextFruit();
// Prevent spam dropping
canDropFruit = false;
LK.setTimeout(function () {
canDropFruit = true;
}, 500);
}
// Update score display
function updateScoreDisplay() {
scoreText.setText("SCORE: " + LK.getScore());
}
// Setup UI
function setupUI() {
// Score display
scoreText = new Text2("SCORE: 0", {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 30;
}
// Check for fruit collisions
function checkFruitCollisions() {
for (var i = 0; i < fruits.length; i++) {
for (var j = i + 1; j < fruits.length; j++) {
var fruit1 = fruits[i];
var fruit2 = fruits[j];
// Skip if either fruit is already merging
if (fruit1.merging || fruit2.merging) {
continue;
}
// Check if fruits are the same type
if (fruit1.type === fruit2.type) {
// Calculate distance between centers
var dx = fruit2.x - fruit1.x;
var dy = fruit2.y - fruit1.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if they are overlapping
var combinedRadius = (fruit1.type.size + fruit2.type.size) / 2;
if (distance < combinedRadius * 0.8) {
// Merge fruits
fruit1.merge(fruit2);
break;
}
}
}
}
}
// Check if game is over (too many fruits on screen or stacked too high)
function checkGameOver() {
if (gameOver) {
return;
}
if (fruits.length > 30) {
gameOver = true;
LK.showGameOver();
return;
}
// Check if any fruits are too high
for (var i = 0; i < fruits.length; i++) {
if (fruits[i].y < 300 && !fruits[i].merging && fruits[i].vy < 1) {
var isFruitMoving = Math.abs(fruits[i].vx) > 0.5 || Math.abs(fruits[i].vy) > 0.5;
if (!isFruitMoving) {
gameOver = true;
LK.showGameOver();
return;
}
}
}
}
// Initialize game
function initGame() {
LK.setScore(0);
gameOver = false;
fruits = [];
// Start background music
LK.playMusic('bgmusic');
// Setup game elements
setupBoundaries();
setupUI();
updateScoreDisplay();
createNextFruit();
}
// Event handlers
game.down = function (x, y) {
// Don't allow drops too close to the edges
var minX = wallLeft.x + wallLeft.width / 2 + 100;
var maxX = wallRight.x - wallRight.width / 2 - 100;
if (x > minX && x < maxX) {
dropFruit(x);
}
};
// Game update loop
game.update = function () {
// Check for fruit collisions
checkFruitCollisions();
// Check game over conditions
checkGameOver();
};
// Initialize the game
initGame(); ===================================================================
--- original.js
+++ change.js
@@ -348,16 +348,16 @@
}
// Initialize game
function initGame() {
LK.setScore(0);
- updateScoreDisplay();
gameOver = false;
fruits = [];
// Start background music
LK.playMusic('bgmusic');
// Setup game elements
setupBoundaries();
setupUI();
+ updateScoreDisplay();
createNextFruit();
}
// Event handlers
game.down = function (x, y) {