User prompt
5 ve 9 u uygula
User prompt
5 top yerine 3 top ekle kademeli şekilde büyüsünler ama top spawnlamada ilk 4 top spawnlansın daha büyük toplar sadece birleştirerek olsun
User prompt
yeni 5 tane daha büyük top ekle
User prompt
There will be no ball unless you drag and drop the ball
User prompt
Don't let the ball get in your way when you start
Code edit (1 edits merged)
Please save this source code
User prompt
Merge Balls Mania
Initial prompt
Make me a game. Let there be 9 balls of different sizes. When two balls of the same size touch each other, one big ball is formed. Let's lose when we pass a certain limit and let the balls come in random sizes. When I drag and click on a section, a new ball falls there.
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Ball class
var Ball = Container.expand(function () {
	var self = Container.call(this);
	// Ball properties
	self.size = 1; // 1-9
	self.radius = 60; // default, will be set in init
	self.vx = 0;
	self.vy = 0;
	self.isMerging = false; // Prevent double merge
	// Attach asset based on size
	self.setSize = function (size) {
		self.size = size;
		// Remove previous asset if any
		if (self.ballAsset) {
			self.removeChild(self.ballAsset);
		}
		var assetId = 'ball' + size;
		self.ballAsset = self.attachAsset(assetId, {
			anchorX: 0.5,
			anchorY: 0.5
		});
		self.radius = self.ballAsset.width / 2;
	};
	// Set initial size
	self.setSize(1);
	// For merge animation
	self.flash = function () {
		tween(self.ballAsset, {
			scaleX: 1.2,
			scaleY: 1.2
		}, {
			duration: 120,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				tween(self.ballAsset, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 120,
					easing: tween.easeIn
				});
			}
		});
	};
	// For showing value
	self.showValue = function () {
		if (self.valueText) {
			self.removeChild(self.valueText);
		}
		self.valueText = new Text2('' + self.size, {
			size: Math.max(60, self.radius),
			fill: 0xFFFFFF
		});
		self.valueText.anchor.set(0.5, 0.5);
		self.addChild(self.valueText);
	};
	self.showValue();
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x222831
});
/**** 
* Game Code
****/ 
// Game constants
// Ball shapes for different sizes (size1, size2, size3, size4, size5, size6, size7, size8, size9)
// Sound for merging
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var BALL_MIN_SIZE = 1;
var BALL_MAX_SIZE = 12; // Now only up to 3 new big balls (ball10, ball11, ball12)
var BALL_LIMIT = 16; // Max balls allowed on screen before game over
// var INIT_BALLS = 9; // No longer needed, no initial balls
var GRAVITY = 1.2;
var BOUNCE = 0.7;
var FRICTION = 0.995;
var WALL_BOUNCE = 0.8;
var SPAWN_Y = 180; // y position for new balls
// Ball array
var balls = [];
// Score
var score = 0;
var scoreTxt = new Text2('0', {
	size: 120,
	fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Next ball preview
var nextBallSize = BALL_MIN_SIZE + Math.floor(Math.random() * 4); // Only 1-4
var nextBallPreview = LK.getAsset('ball' + nextBallSize, {
	anchorX: 0.5,
	anchorY: 0.5,
	x: GAME_WIDTH / 2,
	y: SPAWN_Y - 100
});
game.addChild(nextBallPreview);
// Helper: get random ball size (only 1-4 for spawn)
function getRandomBallSize() {
	// Weighted random: 1: 45%, 2: 30%, 3: 15%, 4: 10%
	var r = Math.random();
	if (r < 0.45) return 1;
	if (r < 0.75) return 2;
	if (r < 0.90) return 3;
	return 4;
}
// Helper: clamp
function clamp(val, min, max) {
	return Math.max(min, Math.min(max, val));
}
// Helper: distance squared
function dist2(a, b) {
	var dx = a.x - b.x;
	var dy = a.y - b.y;
	return dx * dx + dy * dy;
}
// Helper: check overlap
function isOverlapping(ballA, ballB) {
	var rSum = ballA.radius + ballB.radius;
	return dist2(ballA, ballB) < rSum * rSum - 1;
}
// Helper: resolve overlap
function resolveOverlap(ballA, ballB) {
	var dx = ballB.x - ballA.x;
	var dy = ballB.y - ballA.y;
	var dist = Math.sqrt(dx * dx + dy * dy);
	if (dist === 0) {
		// Random nudge
		dx = 1;
		dy = 0;
		dist = 1;
	}
	var overlap = ballA.radius + ballB.radius - dist;
	if (overlap > 0) {
		var pushX = dx / dist * (overlap / 2);
		var pushY = dy / dist * (overlap / 2);
		ballA.x -= pushX;
		ballA.y -= pushY;
		ballB.x += pushX;
		ballB.y += pushY;
	}
}
// Helper: merge balls
function mergeBalls(ballA, ballB) {
	// Only merge if both are not merging and same size
	if (ballA.isMerging || ballB.isMerging) return false;
	if (ballA.size !== ballB.size) return false;
	ballA.isMerging = true;
	ballB.isMerging = true;
	// New ball at average position
	var newBall = new Ball();
	var newSize = clamp(ballA.size + 1, BALL_MIN_SIZE, BALL_MAX_SIZE);
	newBall.setSize(newSize);
	newBall.x = (ballA.x + ballB.x) / 2;
	newBall.y = (ballA.y + ballB.y) / 2;
	newBall.vx = (ballA.vx + ballB.vx) / 2;
	newBall.vy = (ballA.vy + ballB.vy) / 2;
	newBall.showValue();
	newBall.flash();
	// Remove old balls
	ballA.destroy();
	ballB.destroy();
	var idxA = balls.indexOf(ballA);
	var idxB = balls.indexOf(ballB);
	if (idxA !== -1) balls.splice(idxA, 1);
	if (idxB !== -1) balls.splice(balls.indexOf(ballB), 1); // index may have shifted
	// Add new ball
	balls.push(newBall);
	game.addChild(newBall);
	// Play merge sound
	LK.getSound('merge').play();
	// Add score
	score += Math.pow(2, newSize);
	scoreTxt.setText(score);
	// Animate
	newBall.flash();
	// Feature 9: Shake nearby balls after merge
	var SHAKE_RADIUS = newBall.radius * 3;
	for (var i = 0; i < balls.length; i++) {
		var b = balls[i];
		if (b !== newBall && !b.isMerging) {
			var dx = b.x - newBall.x;
			var dy = b.y - newBall.y;
			var dist = Math.sqrt(dx * dx + dy * dy);
			if (dist < SHAKE_RADIUS) {
				// Give a small random velocity burst
				var angle = Math.atan2(dy, dx);
				var force = 10 + Math.random() * 10;
				b.vx += Math.cos(angle) * force * (0.7 + 0.6 * Math.random());
				b.vy += Math.sin(angle) * force * (0.7 + 0.6 * Math.random());
			}
		}
	}
	return newBall;
}
// Spawn a ball at (x, y) with given size
function spawnBall(x, y, size) {
	var ball = new Ball();
	ball.setSize(size);
	ball.x = clamp(x, ball.radius, GAME_WIDTH - ball.radius);
	ball.y = y;
	ball.vx = (Math.random() - 0.5) * 16;
	ball.vy = 0;
	ball.showValue();
	balls.push(ball);
	game.addChild(ball);
	return ball;
}
// No initial balls function needed
// Drag and drop for new balls
var isDragging = false;
var dragX = GAME_WIDTH / 2;
var dragBall = null;
// Show drag preview
var dragPreview = null;
function showDragPreview(x) {
	if (!dragPreview) {
		dragPreview = LK.getAsset('ball' + nextBallSize, {
			anchorX: 0.5,
			anchorY: 0.5,
			x: x,
			y: SPAWN_Y
		});
		game.addChild(dragPreview);
	}
	dragPreview.x = clamp(x, dragPreview.width / 2, GAME_WIDTH - dragPreview.width / 2);
	dragPreview.y = SPAWN_Y;
}
function hideDragPreview() {
	if (dragPreview) {
		dragPreview.destroy();
		dragPreview = null;
	}
}
// Handle touch/mouse down
game.down = function (x, y, obj) {
	// Only allow drop in top 1/3 of screen
	if (y > GAME_HEIGHT / 2) return;
	isDragging = true;
	dragX = clamp(x, 100, GAME_WIDTH - 100);
	showDragPreview(dragX);
};
// Handle move
game.move = function (x, y, obj) {
	if (isDragging) {
		dragX = clamp(x, 100, GAME_WIDTH - 100);
		showDragPreview(dragX);
	}
};
// Handle up (drop ball)
game.up = function (x, y, obj) {
	if (isDragging) {
		isDragging = false;
		hideDragPreview();
		// Drop ball at dragX
		spawnBall(dragX, SPAWN_Y, nextBallSize);
		// Next ball
		nextBallSize = getRandomBallSize();
		// Update preview
		if (nextBallPreview) {
			nextBallPreview.destroy();
		}
		nextBallPreview = LK.getAsset('ball' + nextBallSize, {
			anchorX: 0.5,
			anchorY: 0.5,
			x: GAME_WIDTH / 2,
			y: SPAWN_Y - 100
		});
		game.addChild(nextBallPreview);
	}
};
// Main update loop
game.update = function () {
	// Physics for each ball
	for (var i = 0; i < balls.length; i++) {
		var ball = balls[i];
		// Gravity
		ball.vy += GRAVITY;
		// Move
		ball.x += ball.vx;
		ball.y += ball.vy;
		// Wall collision
		if (ball.x - ball.radius < 0) {
			ball.x = ball.radius;
			ball.vx = -ball.vx * WALL_BOUNCE;
		}
		if (ball.x + ball.radius > GAME_WIDTH) {
			ball.x = GAME_WIDTH - ball.radius;
			ball.vx = -ball.vx * WALL_BOUNCE;
		}
		// Floor
		if (ball.y + ball.radius > GAME_HEIGHT) {
			ball.y = GAME_HEIGHT - ball.radius;
			ball.vy = -ball.vy * BOUNCE;
			ball.vx *= FRICTION;
			// Stop tiny bounces
			if (Math.abs(ball.vy) < 2) ball.vy = 0;
		}
		// Ceiling
		if (ball.y - ball.radius < 0) {
			ball.y = ball.radius;
			ball.vy = -ball.vy * BOUNCE;
		}
		// Friction
		ball.vx *= FRICTION;
		ball.vy *= FRICTION;
	}
	// Ball-ball collision and merging
	for (var i = 0; i < balls.length; i++) {
		for (var j = i + 1; j < balls.length; j++) {
			var a = balls[i],
				b = balls[j];
			if (isOverlapping(a, b)) {
				// If same size, merge
				if (a.size === b.size && !a.isMerging && !b.isMerging) {
					mergeBalls(a, b);
					break; // balls array changed, restart
				} else {
					// Elastic collision
					resolveOverlap(a, b);
					// Simple velocity swap
					var dx = b.x - a.x;
					var dy = b.y - a.y;
					var dist = Math.sqrt(dx * dx + dy * dy);
					if (dist > 0) {
						var nx = dx / dist,
							ny = dy / dist;
						var p = 2 * (a.vx * nx + a.vy * ny - b.vx * nx - b.vy * ny) / 2;
						a.vx = a.vx - p * nx;
						a.vy = a.vy - p * ny;
						b.vx = b.vx + p * nx;
						b.vy = b.vy + p * ny;
					}
				}
			}
		}
	}
	// Remove balls marked for destroy (already handled in mergeBalls)
	// Check for game over
	if (balls.length > BALL_LIMIT) {
		LK.effects.flashScreen(0xff0000, 800);
		LK.showGameOver();
	}
	// Optionally: win condition (e.g. create a ball of size 12)
	for (var i = 0; i < balls.length; i++) {
		if (balls[i].size === 12) {
			LK.effects.flashScreen(0xffff00, 1000);
			LK.showYouWin();
			break;
		}
	}
}; ===================================================================
--- original.js
+++ change.js
@@ -110,9 +110,14 @@
 });
 game.addChild(nextBallPreview);
 // Helper: get random ball size (only 1-4 for spawn)
 function getRandomBallSize() {
-	return BALL_MIN_SIZE + Math.floor(Math.random() * 4);
+	// Weighted random: 1: 45%, 2: 30%, 3: 15%, 4: 10%
+	var r = Math.random();
+	if (r < 0.45) return 1;
+	if (r < 0.75) return 2;
+	if (r < 0.90) return 3;
+	return 4;
 }
 // Helper: clamp
 function clamp(val, min, max) {
 	return Math.max(min, Math.min(max, val));
@@ -182,8 +187,25 @@
 	score += Math.pow(2, newSize);
 	scoreTxt.setText(score);
 	// Animate
 	newBall.flash();
+	// Feature 9: Shake nearby balls after merge
+	var SHAKE_RADIUS = newBall.radius * 3;
+	for (var i = 0; i < balls.length; i++) {
+		var b = balls[i];
+		if (b !== newBall && !b.isMerging) {
+			var dx = b.x - newBall.x;
+			var dy = b.y - newBall.y;
+			var dist = Math.sqrt(dx * dx + dy * dy);
+			if (dist < SHAKE_RADIUS) {
+				// Give a small random velocity burst
+				var angle = Math.atan2(dy, dx);
+				var force = 10 + Math.random() * 10;
+				b.vx += Math.cos(angle) * force * (0.7 + 0.6 * Math.random());
+				b.vy += Math.sin(angle) * force * (0.7 + 0.6 * Math.random());
+			}
+		}
+	}
 	return newBall;
 }
 // Spawn a ball at (x, y) with given size
 function spawnBall(x, y, size) {
 Pinpon ball. In-Game asset. 2d. High contrast. No shadows
 tennis ball. In-Game asset. 2d. High contrast. No shadows
 american football ball. In-Game asset. 2d. High contrast. No shadows
 volleyball ball. In-Game asset. 2d. High contrast. No shadows
 football ball. In-Game asset. 2d. High contrast. No shadows
 basketball ball. In-Game asset. 2d. High contrast. No shadows
 dodge ball ball. In-Game asset. 2d. High contrast. No shadows
 medicine ball. In-Game asset. 2d. High contrast. No shadows
 yoga ball. In-Game asset. 2d. High contrast. No shadows
 beach ball. In-Game asset. 2d. High contrast. No shadows
 zorbing ball. In-Game asset. 2d. High contrast. No shadows
 flying air balloon. In-Game asset. 2d. High contrast. No shadows