User prompt
Meyveler ekranın altından gelsin
User prompt
Meyveler hepsi aynı yükseklikte farklı yerlere fırlasınlar.
User prompt
Combo yazmıyor
User prompt
Oyun ilerledikçe hızlansın. Oyuna combo ekle
User prompt
Meyvelerin kesilme animasyodunda ikiye ayrılsınlar ama üst parçasıyla alt parçası farklı olsun.
User prompt
Meyvelerin kesilme animasyonunu değiştir. Meyveleri ikiye böl animasyon öyle olsun.
User prompt
Meyveyi kesemeden aşşağı düşünce lose soundu çalsın
User prompt
Satma işlemini bir kez yapalım.
User prompt
Meyveleri sattıktan sonra oyun eski haline dönmüyor ve meyveleri kesemiyorum.
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'parent')' in or related to this line: 'if (draggingFruit.parent) {' Line Number: 929
User prompt
Meyveleri soyduktan sonra yeni bir ekran ve yeni bir arkaplan gelsin burda müşteriler gelsin ve yaptığım meyveleri para karşılığında alsınlar.
User prompt
Meyveleri hayla soyamıyorum.
User prompt
Meyveleri soyduktan sonra meyveleri kesemiyorum.
User prompt
Meyveleri soyma işlemini bir kez yapalım
User prompt
Meyveleri soyma ekranı varken oyun dursun.
User prompt
Meyveleri yıkadıktan sonra onları soyma işlemine getirelim.
User prompt
Meyveleri bir muslukta yıkayalım ama ekran farklı olsun arkaplanda tahta olmasın.
User prompt
Oyun 30 puana gelince farklı bir ekran açılsın burda kestiğimiz meyveleri yıkayalım.
User prompt
Reset game state and UI on new game
User prompt
Bombaya değersek bomb soundu başlasın.
User prompt
Meyveleri kesince sound sesi gelsin.
User prompt
Please fix the bug: 'Uncaught ReferenceError: juiceColor is not defined' in or related to this line: 'var stain = LK.getAsset('juice_stain_' + type.id, {' Line Number: 235
User prompt
Parçacıklar daha fazla ve meyvenin rengine göre renkleri daha belli olsun.
User prompt
Create stains on the background when a fruit is sliced
User prompt
Arkaplan gözükmüyor
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
// Bomb class
var Bomb = Container.expand(function () {
	var self = Container.call(this);
	// Bomb asset: black circle with red border
	var assetId = 'bomb';
	var bombGfx = self.attachAsset(assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Add a red border by overlaying a slightly larger ellipse
	var borderId = 'bomb_border';
	var borderGfx = self.attachAsset(borderId, {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.3
	});
	// Physics
	self.vx = 0;
	self.vy = 0;
	self.gravity = 0.35 + Math.random() * 0.1;
	self.sliced = false;
	self.slice = function () {
		if (self.sliced) return;
		self.sliced = true;
		// Animate: flash and fade out
		tween(self, {
			scaleX: 1.5,
			scaleY: 1.5,
			alpha: 0
		}, {
			duration: 250,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	self.update = function () {
		if (self.sliced) return;
		self.x += self.vx;
		self.y += self.vy;
		self.vy += self.gravity;
		// Prevent from leaving left/right screen edges
		if (self.x < 0 + self.width * 0.5) {
			self.x = self.width * 0.5;
			self.vx = -self.vx * 0.55;
		}
		if (self.x > 2048 - self.width * 0.5) {
			self.x = 2048 - self.width * 0.5;
			self.vx = -self.vx * 0.55;
		}
	};
	return self;
});
// Fruit class
var Fruit = Container.expand(function () {
	var self = Container.call(this);
	// Fruit types: apple, banana, orange, watermelon, etc.
	// Each type has a color and shape
	// We'll use 'ellipse' for round fruits, 'box' for banana
	// We'll randomize type on creation
	var types = [{
		id: 'apple',
		color: 0xff2d2d,
		shape: 'ellipse',
		width: 320,
		height: 320,
		points: 1
	}, {
		id: 'orange',
		color: 0xffa500,
		shape: 'ellipse',
		width: 300,
		height: 300,
		points: 1
	}, {
		id: 'banana',
		color: 0xfff700,
		shape: 'box',
		width: 420,
		height: 160,
		points: 2
	}, {
		id: 'watermelon',
		color: 0x2ecc40,
		shape: 'ellipse',
		width: 420,
		height: 420,
		points: 3
	}, {
		id: 'kiwi',
		color: 0x8ee53f,
		shape: 'ellipse',
		width: 270,
		height: 270,
		points: 2
	}];
	var type = types[Math.floor(Math.random() * types.length)];
	// Asset id is unique per type
	var assetId = 'fruit_' + type.id;
	// Initialize asset if not already
	var fruitGfx = self.attachAsset(assetId, {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Physics
	self.vx = 0;
	self.vy = 0;
	self.gravity = 0.35 + Math.random() * 0.1;
	self.sliced = false;
	self.points = type.points;
	// For arc motion, we set vx, vy on spawn
	// Slicing animation
	self.slice = function () {
		if (self.sliced) return;
		self.sliced = true;
		// Play slicing sound
		LK.getSound('Ninjasword').play();
		// --- Split fruit into two visually distinct halves animation ---
		// Top half (slightly lighter, with a white highlight)
		var halfTop = LK.getAsset(assetId, {
			anchorX: 0.5,
			anchorY: 1.0,
			x: self.x,
			y: self.y,
			rotation: self.rotation,
			scaleY: 0.52,
			tint: 0xffffff // white tint for highlight
		});
		var halfBottom = LK.getAsset(assetId, {
			anchorX: 0.5,
			anchorY: 0.0,
			x: self.x,
			y: self.y,
			rotation: self.rotation,
			scaleY: 0.52,
			tint: type.color // original fruit color for bottom
		});
		game.addChild(halfTop);
		game.addChild(halfBottom);
		// Animate halves flying apart, rotating and fading out
		tween(halfTop, {
			x: self.x - 60,
			y: self.y - 80,
			rotation: self.rotation - 0.32,
			alpha: 0
		}, {
			duration: 420,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				halfTop.destroy();
			}
		});
		tween(halfBottom, {
			x: self.x + 60,
			y: self.y + 80,
			rotation: self.rotation + 0.32,
			alpha: 0
		}, {
			duration: 420,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				halfBottom.destroy();
			}
		});
		// Juice splash effect (ellipse, color based on fruit)
		// More vivid color for splash (slightly saturated)
		var vividJuiceColor = function (c) {
			// Slightly brighten and saturate the color
			var r = Math.min(255, (c >> 16 & 0xff) * 1.15 + 32) | 0;
			var g = Math.min(255, (c >> 8 & 0xff) * 1.15 + 32) | 0;
			var b = Math.min(255, (c & 0xff) * 1.15 + 32) | 0;
			return r << 16 | g << 8 | b;
		}(type.color || 0xff2d2d);
		// Create multiple juice particles for a juicier effect
		var juiceParticles = [];
		var juiceParticleCount = 12 + Math.floor(Math.random() * 7); // 12-18 particles
		for (var jp = 0; jp < juiceParticleCount; jp++) {
			var angle = Math.random() * Math.PI * 2;
			var dist = 40 + Math.random() * 60;
			var scale = 0.22 + Math.random() * 0.22;
			var alpha = 0.55 + Math.random() * 0.25;
			var splash = LK.getAsset('juice_splash_' + type.id, {
				anchorX: 0.5,
				anchorY: 0.5,
				x: self.x,
				y: self.y,
				scaleX: scale * (0.8 + Math.random() * 0.7),
				scaleY: scale * (0.5 + Math.random() * 1.1),
				alpha: alpha,
				tint: vividJuiceColor
			});
			game.addChild(splash);
			juiceParticles.push(splash);
			// Animate each particle outward and fade
			tween(splash, {
				x: self.x + Math.cos(angle) * dist,
				y: self.y + Math.sin(angle) * dist,
				scaleX: scale * (1.2 + Math.random() * 1.2),
				scaleY: scale * (1.1 + Math.random() * 1.2),
				alpha: 0
			}, {
				duration: 320 + Math.random() * 120,
				easing: tween.easeOut,
				onFinish: function (s) {
					return function () {
						s.destroy();
					};
				}(splash)
			});
		}
		// --- Add stain to background ---
		if (typeof background !== "undefined" && background && background.parent) {
			// Create a stain asset (ellipse, color based on fruit, random rotation/scale)
			var stain = LK.getAsset('juice_stain_' + type.id, {
				anchorX: 0.5,
				anchorY: 0.5,
				x: self.x,
				y: self.y,
				scaleX: 0.7 + Math.random() * 0.7,
				scaleY: 0.5 + Math.random() * 0.7,
				alpha: 0.32 + Math.random() * 0.18,
				rotation: Math.random() * Math.PI * 2,
				tint: vividJuiceColor
			});
			// Insert stain just above the background (so it stays under fruit halves/splashes)
			var bgParent = background.parent;
			var bgIndex = bgParent.getChildIndex(background);
			bgParent.addChildAt(stain, bgIndex + 1);
		}
		// --- End stain ---
		// Hide original fruit immediately
		self.alpha = 0;
		tween(self, {
			alpha: 0
		}, {
			duration: 1,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	// Update per frame
	self.update = function () {
		if (self.sliced) return;
		self.x += self.vx;
		self.y += self.vy;
		self.vy += self.gravity;
		// Prevent from leaving left/right screen edges
		if (self.x < 0 + self.width * 0.5) {
			self.x = self.width * 0.5;
			self.vx = -self.vx * 0.55; // bounce back with some energy loss
		}
		if (self.x > 2048 - self.width * 0.5) {
			self.x = 2048 - self.width * 0.5;
			self.vx = -self.vx * 0.55;
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x1a1a1a
});
/**** 
* Game Code
****/ 
// Add background image
// Game variables 
var background = LK.getAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
});
game.addChild(background);
var fruits = [];
var bombs = [];
var fruitSpawnTimer = 0;
var bombSpawnTimer = 0;
var fruitSpawnInterval = 120; // 2 seconds at 60fps
var bombSpawnInterval = 300; // 5 seconds at 60fps
var score = 0;
var highScore = storage.highScore || 0;
var missed = 0;
var maxMissed = 3;
var isGameOver = false;
// Score display
var scoreTxt = new Text2('0', {
	size: 120,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Combo system
var comboCount = 0;
var comboTimer = 0;
var comboTimeout = 36; // 0.6s at 60fps
var maxCombo = 0;
var comboTxt = new Text2('', {
	size: 90,
	fill: 0xFFFA00
});
comboTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(comboTxt);
// High score display (smaller, top right)
var highScoreTxt = new Text2('Best: ' + highScore, {
	size: 60,
	fill: "#fff"
});
highScoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(highScoreTxt);
// Missed fruits display (bottom left, as X icons)
var missTxt = new Text2('', {
	size: 90,
	fill: 0xFF4444
});
missTxt.anchor.set(0, 1);
LK.gui.bottomLeft.addChild(missTxt);
// Helper: update score
function updateScore(val) {
	score = val;
	scoreTxt.setText(score);
	if (score > highScore) {
		highScore = score;
		storage.highScore = highScore;
		highScoreTxt.setText('Best: ' + highScore);
	}
}
// Helper: update missed display
function updateMissed() {
	var s = '';
	for (var i = 0; i < missed; i++) s += '✗ ';
	missTxt.setText(s);
}
// (spawning is now handled by fruit/bomb timers in game.update)
// Slicing logic
var swipePath = [];
var swipeMaxLength = 12; // Number of points to keep in swipe trail
var swipeRadius = 90; // How close swipe must be to slice
// Draw swipe trail (for visual feedback)
var swipeTrail = [];
function drawSwipeTrail() {
	// Remove old
	for (var i = 0; i < swipeTrail.length; i++) {
		swipeTrail[i].destroy();
	}
	swipeTrail = [];
	// Draw new
	for (var i = 1; i < swipePath.length; i++) {
		var p1 = swipePath[i - 1];
		var p2 = swipePath[i];
		// Draw a short white ellipse between points
		var dx = p2.x - p1.x,
			dy = p2.y - p1.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		if (dist < 10) continue;
		var angle = Math.atan2(dy, dx);
		var id = 'swipe_' + i;
		var seg = LK.getAsset(id, {
			anchorX: 0,
			anchorY: 0.5,
			x: p1.x,
			y: p1.y,
			rotation: angle,
			alpha: 0.22
		});
		game.addChild(seg);
		swipeTrail.push(seg);
	}
}
// Handle swipe start
game.down = function (x, y, obj) {
	if (isGameOver) return;
	swipePath = [{
		x: x,
		y: y
	}];
	drawSwipeTrail();
};
// Handle swipe move
game.move = function (x, y, obj) {
	if (isGameOver) return;
	swipePath.push({
		x: x,
		y: y
	});
	if (swipePath.length > swipeMaxLength) swipePath.shift();
	drawSwipeTrail();
	// For each segment in swipe, check for intersection with fruits/bombs
	for (var i = 1; i < swipePath.length; i++) {
		var p1 = swipePath[i - 1],
			p2 = swipePath[i];
		// Fruits
		for (var f = fruits.length - 1; f >= 0; f--) {
			var fruit = fruits[f];
			if (fruit.sliced) continue;
			// If fruit already off screen, skip
			if (fruit.y > 2732 + 120) continue;
			// Check if swipe segment is close to fruit center
			var cx = fruit.x,
				cy = fruit.y;
			var dist = pointToSegmentDistance(cx, cy, p1.x, p1.y, p2.x, p2.y);
			if (dist < swipeRadius) {
				fruit.slice();
				updateScore(score + fruit.points); // Increase score by fruit's point value
				fruits.splice(f, 1);
				// Flash effect
				LK.effects.flashObject(fruit, 0xffffff, 120);
				// --- Combo logic ---
				comboCount++;
				comboTimer = comboTimeout;
				if (comboCount > maxCombo) maxCombo = comboCount;
				if (comboCount > 1) {
					comboTxt.setText(comboCount + " Combo!");
					comboTxt.alpha = 1;
					// Animate combo text alpha in case it was faded out
					tween(comboTxt, {
						alpha: 1
					}, {
						duration: 60
					});
					// Bonus points for combos (e.g. +2 for 3-combo, +4 for 4-combo, etc)
					if (comboCount >= 3) {
						var bonus = (comboCount - 2) * 2;
						updateScore(score + bonus);
						// Animate combo text
						tween(comboTxt, {
							scaleX: 1.3,
							scaleY: 1.3
						}, {
							duration: 120,
							yoyo: true,
							repeat: 1
						});
					}
				}
			}
		}
		// Bombs
		for (var b = bombs.length - 1; b >= 0; b--) {
			var bomb = bombs[b];
			if (bomb.sliced) continue;
			if (bomb.y > 2732 + 120) continue;
			var cx = bomb.x,
				cy = bomb.y;
			var dist = pointToSegmentDistance(cx, cy, p1.x, p1.y, p2.x, p2.y);
			if (dist < swipeRadius) {
				bomb.slice();
				bombs.splice(b, 1);
				// Play bomb sound
				LK.getSound('Bomb').play();
				// Increase score by 1 when bomb is sliced
				updateScore(score + 1);
				// Flash screen red, then game over
				LK.effects.flashScreen(0xff2222, 800);
				isGameOver = true;
				LK.setTimeout(function () {
					LK.showGameOver();
				}, 600);
				return;
			}
		}
	}
};
// Handle swipe end
game.up = function (x, y, obj) {
	swipePath = [];
	drawSwipeTrail();
};
// Helper: distance from point to segment
function pointToSegmentDistance(px, py, x1, y1, x2, y2) {
	var dx = x2 - x1,
		dy = y2 - y1;
	if (dx === 0 && dy === 0) {
		dx = px - x1;
		dy = py - y1;
		return Math.sqrt(dx * dx + dy * dy);
	}
	var t = ((px - x1) * dx + (py - y1) * dy) / (dx * dx + dy * dy);
	t = Math.max(0, Math.min(1, t));
	var lx = x1 + t * dx,
		ly = y1 + t * dy;
	dx = px - lx;
	dy = py - ly;
	return Math.sqrt(dx * dx + dy * dy);
}
// Main game update
game.update = function () {
	if (isGameOver) return;
	// --- Dynamic difficulty: speed up game as score increases ---
	var minFruitInterval = 36; // minimum interval (0.6s)
	var minBombInterval = 120; // minimum interval (2s)
	var fruitIntervalStep = Math.max(0, fruitSpawnInterval - Math.floor(score / 10) * 10);
	fruitSpawnInterval = Math.max(minFruitInterval, 120 - Math.floor(score / 10) * 10);
	bombSpawnInterval = Math.max(minBombInterval, 300 - Math.floor(score / 15) * 15);
	// Spawn logic
	fruitSpawnTimer++;
	bombSpawnTimer++;
	if (fruitSpawnTimer >= fruitSpawnInterval) {
		// Spawn a fruit only
		var obj = new Fruit();
		// All fruits spawn at the same Y (bottom), but random X across the screen (leaving margin for fruit width)
		var fruitMargin = 200;
		var x = fruitMargin + Math.random() * (2048 - 2 * fruitMargin);
		var y = 2732 + 60; // All fruits spawn just below the bottom of the screen
		// Launch angle is always straight up
		var angle = -Math.PI / 2;
		var speed = 17 + Math.random() * 5.5 + score * 0.055;
		// vx is 0 (no side velocity), vy is always up
		var vx = 0;
		var vy = -Math.abs(Math.sin(angle) * speed) * 1.32;
		obj.x = x;
		obj.y = y;
		obj.vx = vx;
		obj.vy = vy;
		obj.scaleX = obj.scaleY = 1;
		obj.alpha = 1;
		// Increase gravity for fruit as score increases
		obj.gravity += Math.min(0.18, score * 0.012);
		fruits.push(obj);
		game.addChild(obj);
		fruitSpawnTimer = 0;
	}
	if (bombSpawnTimer >= bombSpawnInterval) {
		// Spawn a bomb only
		var obj = new Bomb();
		// All bombs spawn at the same Y (bottom), but random X across the screen (leaving margin for bomb width)
		var bombMargin = 200;
		var x = bombMargin + Math.random() * (2048 - 2 * bombMargin);
		var y = 2732 + 60; // All bombs spawn just below the bottom of the screen
		// Launch angle is always straight up
		var angle = -Math.PI / 2;
		var speed = 17 + Math.random() * 5.5 + score * 0.055;
		// vx is 0 (no side velocity), vy is always up
		var vx = 0;
		var vy = -Math.abs(Math.sin(angle) * speed) * 1.32;
		obj.x = x;
		obj.y = y;
		obj.vx = vx;
		obj.vy = vy;
		obj.scaleX = obj.scaleY = 1;
		obj.alpha = 1;
		// Increase gravity for bomb as score increases
		obj.gravity += Math.min(0.18, score * 0.012);
		bombs.push(obj);
		game.addChild(obj);
		bombSpawnTimer = 0;
	}
	// Update fruits
	for (var i = fruits.length - 1; i >= 0; i--) {
		var fruit = fruits[i];
		fruit.update();
		// Remove if off screen
		if (!fruit.sliced && fruit.y > 2732 + 120) {
			// Play lose sound when fruit is missed
			LK.getSound('Lose').play();
			fruit.destroy();
			fruits.splice(i, 1);
			missed++;
			updateMissed();
			// Flash screen if missed
			LK.effects.flashScreen(0x2222ff, 200);
			if (missed >= maxMissed) {
				isGameOver = true;
				LK.setTimeout(function () {
					LK.showGameOver();
				}, 500);
			}
			// Do NOT increase score here; only bomb slice increases score now
		}
	}
	// Update bombs
	for (var i = bombs.length - 1; i >= 0; i--) {
		var bomb = bombs[i];
		bomb.update();
		if (bomb.y > 2732 + 120) {
			bomb.destroy();
			bombs.splice(i, 1);
		}
	}
	// Fade out swipe trail
	for (var i = 0; i < swipeTrail.length; i++) {
		swipeTrail[i].alpha *= 0.85;
		if (swipeTrail[i].alpha < 0.05) {
			swipeTrail[i].destroy();
			swipeTrail.splice(i, 1);
			i--;
		}
	}
	// --- Combo timer logic ---
	if (comboTimer > 0) {
		comboTimer--;
		if (comboTimer === 0) {
			// Combo ended
			comboCount = 0;
			tween(comboTxt, {
				alpha: 0
			}, {
				duration: 320
			});
		}
	}
};
// Reset game state on new game
game.on('reset', function () {
	// Remove all fruits and bombs
	for (var i = 0; i < fruits.length; i++) fruits[i].destroy();
	for (var i = 0; i < bombs.length; i++) bombs[i].destroy();
	fruits = [];
	bombs = [];
	fruitSpawnTimer = 0;
	bombSpawnTimer = 0;
	score = 0;
	missed = 0;
	isGameOver = false;
	updateScore(0);
	updateMissed();
	swipePath = [];
	drawSwipeTrail();
	comboCount = 0;
	comboTimer = 0;
	comboTxt.setText('');
	comboTxt.alpha = 0;
	maxCombo = 0;
	highScore = storage.highScore || 0;
	highScoreTxt.setText('Best: ' + highScore);
});
// Initial state
updateScore(0);
updateMissed();
// Fruit assets
// Bomb asset: black circle
// Bomb border: red, slightly larger, semi-transparent ===================================================================
--- original.js
+++ change.js
@@ -512,12 +512,12 @@
 	bombSpawnTimer++;
 	if (fruitSpawnTimer >= fruitSpawnInterval) {
 		// Spawn a fruit only
 		var obj = new Fruit();
-		// All fruits spawn at the same Y, but random X across the screen (leaving margin for fruit width)
+		// All fruits spawn at the same Y (bottom), but random X across the screen (leaving margin for fruit width)
 		var fruitMargin = 200;
 		var x = fruitMargin + Math.random() * (2048 - 2 * fruitMargin);
-		var y = 1800; // All fruits spawn at this fixed height
+		var y = 2732 + 60; // All fruits spawn just below the bottom of the screen
 		// Launch angle is always straight up
 		var angle = -Math.PI / 2;
 		var speed = 17 + Math.random() * 5.5 + score * 0.055;
 		// vx is 0 (no side velocity), vy is always up
@@ -537,12 +537,12 @@
 	}
 	if (bombSpawnTimer >= bombSpawnInterval) {
 		// Spawn a bomb only
 		var obj = new Bomb();
-		// All bombs spawn at the same Y, but random X across the screen (leaving margin for bomb width)
+		// All bombs spawn at the same Y (bottom), but random X across the screen (leaving margin for bomb width)
 		var bombMargin = 200;
 		var x = bombMargin + Math.random() * (2048 - 2 * bombMargin);
-		var y = 1800; // All bombs spawn at this fixed height
+		var y = 2732 + 60; // All bombs spawn just below the bottom of the screen
 		// Launch angle is always straight up
 		var angle = -Math.PI / 2;
 		var speed = 17 + Math.random() * 5.5 + score * 0.055;
 		// vx is 0 (no side velocity), vy is always up