User prompt
Top düşme sesi ekle
User prompt
Zeminden sürekli yeni toplar dogsun
User prompt
Oyun başlangıcında konteynerın yarısı topla dolu olsun
User prompt
Toplar durdukları yerde titriyor titremesinler
User prompt
Toplar durdukları yerde titriyor
User prompt
Oyun başlangıcta 5 sıra top dizilimiyle başlasın
User prompt
Top boyutlarını geri al
User prompt
Topları büyült
User prompt
Birleşme animasyonunu degiştir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Birleşme animasyonunu farklı bir animasyonla degiştir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Birleşme animasyonu ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Birleşme hassasiyeti arrtır
User prompt
Fizik kuralları çerçevesinde toplar birbirinin üzerinde yıgılabilir
User prompt
Her sıra için em fazla 12 top olabilir sıra dolduysa top diger topun üstünde durum devam eder
User prompt
Düzelt ozaöam
User prompt
Toplar birbirinin üzerinde durabilir
User prompt
Top birleşme sesi arttır
User prompt
Top birleşme sesi ekle
User prompt
Tehlike bölgesi varlıgını görünmez yap
User prompt
Oyın bitti alanı görünmez yap
User prompt
Tehlike alanı çizgisini görünmez yap
User prompt
Top birleşimleri hassaslaştır aynı numaralı toplar birbirine cok azda temas etse birleşsin
User prompt
Çözüm
User prompt
Topları biraz daha büyült
User prompt
Hepsini uygula
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Ball = Container.expand(function (value) {
var self = Container.call(this);
self.value = value || 2;
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.8;
self.bounce = 0.4;
self.friction = 0.98;
self.radius = 60;
self.isStatic = false;
self.mergeTimer = 0;
self.hasBeenMerged = false;
var ballAsset = self.attachAsset('ball' + self.value, {
anchorX: 0.5,
anchorY: 0.5
});
var valueText = new Text2(self.value.toString(), {
size: 42,
fill: 0xFFFFFF
});
valueText.anchor.set(0.5, 0.5);
self.addChild(valueText);
self.update = function () {
if (self.hasBeenMerged) return;
if (self.mergeTimer > 0) {
self.mergeTimer--;
return;
}
// Apply physics only if not static
if (!self.isStatic) {
// Store previous position for continuous collision detection
var prevX = self.x;
var prevY = self.y;
// Apply gravity
self.velocityY += self.gravity;
// Calculate intended new position
var newX = self.x + self.velocityX;
var newY = self.y + self.velocityY;
// Continuous collision detection - check path from current to intended position
var stepCount = Math.max(1, Math.ceil(Math.abs(self.velocityX) + Math.abs(self.velocityY)) / (self.radius * 0.5));
var stepX = (newX - self.x) / stepCount;
var stepY = (newY - self.y) / stepCount;
var collisionOccurred = false;
// Check each step along the movement path
for (var step = 1; step <= stepCount && !collisionOccurred; step++) {
var testX = self.x + stepX * step;
var testY = self.y + stepY * step;
// Test collision with other balls
for (var i = 0; i < balls.length; i++) {
var otherBall = balls[i];
if (otherBall === self || otherBall.hasBeenMerged || otherBall.mergeTimer > 0) continue;
var dx = otherBall.x - testX;
var dy = otherBall.y - testY;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = self.radius + otherBall.radius;
if (distance < minDistance) {
// Collision detected - stop at safe position
var safeDistance = minDistance + 2; // Add small buffer
if (distance > 0) {
var normalX = dx / distance;
var normalY = dy / distance;
self.x = otherBall.x - normalX * safeDistance;
self.y = otherBall.y - normalY * safeDistance;
// Check for merge first - increased sensitivity for same-numbered balls
var mergeDistance = self.value === otherBall.value ? minDistance * 1.4 : minDistance;
if (self.value === otherBall.value && self.mergeTimer === 0 && otherBall.mergeTimer === 0 && distance < mergeDistance) {
var newValue = self.value * 2;
if (newValue <= 2048) {
var newBall = new Ball(newValue);
newBall.x = (self.x + otherBall.x) / 2;
newBall.y = (self.y + otherBall.y) / 2;
newBall.velocityX = (self.velocityX + otherBall.velocityX) / 2;
newBall.velocityY = (self.velocityY + otherBall.velocityY) / 2;
newBall.mergeTimer = 10;
balls.push(newBall);
gameArea.addChild(newBall);
// Mark for removal
self.hasBeenMerged = true;
otherBall.hasBeenMerged = true;
LK.getSound('merge').play();
LK.setScore(LK.getScore() + newValue);
scoreText.setText(LK.getScore());
// Check win condition
if (newValue === 2048) {
LK.showYouWin();
}
return;
}
}
// Enhanced collision response for better stacking
var relativeVelX = self.velocityX - otherBall.velocityX;
var relativeVelY = self.velocityY - otherBall.velocityY;
var relativeSpeed = relativeVelX * normalX + relativeVelY * normalY;
if (relativeSpeed > 0) {
// Calculate mass-based collision response (assume equal mass)
var restitution = 0.3; // Lower restitution for more stable stacking
var impulse = (1 + restitution) * relativeSpeed * 0.5;
self.velocityX -= impulse * normalX;
self.velocityY -= impulse * normalY;
otherBall.velocityX += impulse * normalX;
otherBall.velocityY += impulse * normalY;
// Apply different friction based on collision angle
var collisionAngle = Math.atan2(normalY, normalX);
var frictionFactor = Math.abs(Math.sin(collisionAngle)) * 0.8 + 0.2;
self.velocityX *= self.friction * frictionFactor;
self.velocityY *= self.friction * frictionFactor;
otherBall.velocityX *= otherBall.friction * frictionFactor;
otherBall.velocityY *= otherBall.friction * frictionFactor;
// Enhanced static detection for stacking
if (Math.abs(self.velocityY) < 0.5 && Math.abs(self.velocityX) < 0.5) {
// Check if ball is supported (has another ball below it or touching ground)
var supportFound = false;
var localBottom = gameAreaHeight - 20;
// Check ground support
if (self.y + self.radius >= localBottom - 5) {
supportFound = true;
} else {
// Check support from other balls
for (var j = 0; j < balls.length; j++) {
var supportBall = balls[j];
if (supportBall === self || supportBall.hasBeenMerged) continue;
var supportDx = supportBall.x - self.x;
var supportDy = supportBall.y - self.y;
var supportDistance = Math.sqrt(supportDx * supportDx + supportDy * supportDy);
// Check if this ball is resting on another ball (other ball is below)
if (supportDistance < (self.radius + supportBall.radius) * 1.1 && supportDy > 0) {
supportFound = true;
break;
}
}
}
if (supportFound) {
self.isStatic = true;
self.velocityX = 0;
self.velocityY = 0;
}
}
}
}
collisionOccurred = true;
break;
}
}
}
// If no collision occurred, move to intended position
if (!collisionOccurred) {
self.x = newX;
self.y = newY;
}
// Boundary collisions after position update
var localWidth = gameAreaRight - gameAreaLeft;
var localBottom = gameAreaHeight - 20; // gameAreaHeight minus bottom wall height
// Ground collision
if (self.y + self.radius > localBottom) {
self.y = localBottom - self.radius;
self.velocityY *= -self.bounce;
self.velocityX *= self.friction;
if (Math.abs(self.velocityY) < 1) {
self.velocityY = 0;
self.isStatic = true;
}
}
// Side walls collision
if (self.x - self.radius < 0) {
self.x = self.radius;
self.velocityX *= -self.bounce;
}
if (self.x + self.radius > localWidth) {
self.x = localWidth - self.radius;
self.velocityX *= -self.bounce;
}
}
// Enhanced merge detection pass - check for nearby same-numbered balls
for (var i = 0; i < balls.length; i++) {
var otherBall = balls[i];
if (otherBall === self || otherBall.hasBeenMerged || otherBall.mergeTimer > 0 || self.mergeTimer > 0) continue;
var dx = otherBall.x - self.x;
var dy = otherBall.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = self.radius + otherBall.radius;
// Enhanced merge sensitivity for same-numbered balls
if (self.value === otherBall.value) {
var mergeTriggerDistance = minDistance * 1.3; // 30% more sensitive
if (distance < mergeTriggerDistance) {
var newValue = self.value * 2;
if (newValue <= 2048) {
var newBall = new Ball(newValue);
newBall.x = (self.x + otherBall.x) / 2;
newBall.y = (self.y + otherBall.y) / 2;
newBall.velocityX = (self.velocityX + otherBall.velocityX) / 2;
newBall.velocityY = (self.velocityY + otherBall.velocityY) / 2;
newBall.mergeTimer = 10;
balls.push(newBall);
gameArea.addChild(newBall);
// Mark for removal
self.hasBeenMerged = true;
otherBall.hasBeenMerged = true;
LK.getSound('merge').play();
LK.setScore(LK.getScore() + newValue);
scoreText.setText(LK.getScore());
// Check win condition
if (newValue === 2048) {
LK.showYouWin();
}
return;
}
}
}
// Enhanced separation for stable stacking
if (distance < minDistance && distance > 0) {
var overlap = minDistance - distance;
var normalX = dx / distance;
var normalY = dy / distance;
// Different separation strategies based on ball positions
var separationForce = overlap * 0.5;
// If one ball is static and the other is moving, adjust separation
if (self.isStatic && !otherBall.isStatic) {
// Static ball moves less
self.x -= normalX * separationForce * 0.2;
self.y -= normalY * separationForce * 0.2;
otherBall.x += normalX * separationForce * 0.8;
otherBall.y += normalY * separationForce * 0.8;
} else if (!self.isStatic && otherBall.isStatic) {
// Other ball is static
self.x -= normalX * separationForce * 0.8;
self.y -= normalY * separationForce * 0.8;
otherBall.x += normalX * separationForce * 0.2;
otherBall.y += normalY * separationForce * 0.2;
} else {
// Both moving or both static - equal separation
self.x -= normalX * separationForce;
self.y -= normalY * separationForce;
otherBall.x += normalX * separationForce;
otherBall.y += normalY * separationForce;
}
// Ensure balls stay within bounds after separation
var localWidth = gameAreaRight - gameAreaLeft;
var localBottom = gameAreaHeight - 20; // gameAreaHeight minus bottom wall height
self.x = Math.max(self.radius, Math.min(localWidth - self.radius, self.x));
self.y = Math.max(self.radius, Math.min(localBottom - self.radius, self.y));
// Re-check static state after separation
if (self.isStatic && (Math.abs(self.x - (self.x - normalX * separationForce)) > 1 || Math.abs(self.y - (self.y - normalY * separationForce)) > 1)) {
self.isStatic = false; // Ball was moved significantly, make it dynamic again
}
}
}
// Periodic re-evaluation of static state for better stacking
if (LK.ticks % 10 === 0 && !self.hasBeenMerged) {
// Check every 10 frames
if (!self.isStatic && Math.abs(self.velocityX) < 0.3 && Math.abs(self.velocityY) < 0.3) {
// Check if ball should become static
var supportFound = false;
var localBottom = gameAreaHeight - 20;
// Check ground support
if (self.y + self.radius >= localBottom - 2) {
supportFound = true;
} else {
// Check support from other static balls
for (var k = 0; k < balls.length; k++) {
var checkBall = balls[k];
if (checkBall === self || checkBall.hasBeenMerged || !checkBall.isStatic) continue;
var checkDx = checkBall.x - self.x;
var checkDy = checkBall.y - self.y;
var checkDistance = Math.sqrt(checkDx * checkDx + checkDy * checkDy);
// Ball is resting on another static ball
if (checkDistance < (self.radius + checkBall.radius) * 1.05 && checkDy > 0) {
supportFound = true;
break;
}
}
}
if (supportFound) {
self.isStatic = true;
self.velocityX = 0;
self.velocityY = 0;
}
} else if (self.isStatic) {
// Check if static ball should become dynamic (lost support)
var stillSupported = false;
var localBottom = gameAreaHeight - 20;
// Check ground support
if (self.y + self.radius >= localBottom - 2) {
stillSupported = true;
} else {
// Check support from other balls
for (var k = 0; k < balls.length; k++) {
var supportBall = balls[k];
if (supportBall === self || supportBall.hasBeenMerged) continue;
var supportDx = supportBall.x - self.x;
var supportDy = supportBall.y - self.y;
var supportDistance = Math.sqrt(supportDx * supportDx + supportDy * supportDy);
if (supportDistance < (self.radius + supportBall.radius) * 1.05 && supportDy > 0) {
stillSupported = true;
break;
}
}
}
if (!stillSupported) {
self.isStatic = false; // Ball lost support, make it fall
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
var balls = [];
var nextBallValue = 2;
var gameAreaLeft = 224;
var gameAreaRight = 1824;
var gameAreaTop = 400;
var gameAreaBottom = 2600;
var dropCooldown = 0;
var gameAreaHeight = gameAreaBottom - gameAreaTop;
// Create game area background
var gameAreaBg = game.addChild(LK.getAsset('gameArea', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
y: gameAreaTop
}));
// Create game area container for balls
var gameArea = new Container();
gameArea.x = gameAreaLeft;
gameArea.y = gameAreaTop;
game.addChild(gameArea);
// Create visible walls
var leftWall = game.addChild(LK.getAsset('leftWall', {
anchorX: 1,
anchorY: 0,
x: gameAreaLeft,
y: gameAreaTop
}));
var rightWall = game.addChild(LK.getAsset('rightWall', {
anchorX: 0,
anchorY: 0,
x: gameAreaRight,
y: gameAreaTop
}));
var bottomWall = game.addChild(LK.getAsset('bottomWall', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
y: gameAreaBottom
}));
// Create danger zone indicator
var dangerZone = game.addChild(LK.getAsset('dangerZone', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
y: gameAreaTop,
alpha: 0
}));
// Create game over line (invisible)
var gameOverLine = game.addChild(LK.getAsset('gameOverLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: gameAreaTop + 100,
alpha: 0,
visible: false
}));
// Create score display
var scoreText = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 100;
// Create next ball preview
var nextBallPreview = LK.getAsset('ball' + nextBallValue, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 300,
scaleX: 0.75,
scaleY: 0.75
});
game.addChild(nextBallPreview);
// Create next ball value text
var nextBallText = new Text2(nextBallValue.toString(), {
size: 24,
fill: 0xFFFFFF
});
nextBallText.anchor.set(0.5, 0.5);
nextBallText.x = 1024;
nextBallText.y = 300;
game.addChild(nextBallText);
// Create instruction text
var instructionText = new Text2('Tap to drop ball', {
size: 40,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.x = 1024;
instructionText.y = 150;
game.addChild(instructionText);
function getRandomNextBallValue() {
var values = [2, 4, 8];
return values[Math.floor(Math.random() * values.length)];
}
function updateNextBallPreview() {
game.removeChild(nextBallPreview);
game.removeChild(nextBallText);
nextBallPreview = LK.getAsset('ball' + nextBallValue, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 300,
scaleX: 0.75,
scaleY: 0.75
});
game.addChild(nextBallPreview);
nextBallText = new Text2(nextBallValue.toString(), {
size: 24,
fill: 0xFFFFFF
});
nextBallText.anchor.set(0.5, 0.5);
nextBallText.x = 1024;
nextBallText.y = 300;
game.addChild(nextBallText);
}
function checkGameOver() {
for (var i = 0; i < balls.length; i++) {
// Check if ball touches the danger zone (first 100 pixels of game area)
// Since balls are in gameArea container, we use local coordinates
// Only trigger game over if ball is static (not actively falling) and in danger zone
if (balls[i].y - balls[i].radius <= 100 && balls[i].isStatic) {
LK.showGameOver();
return;
}
}
}
function cleanupMergedBalls() {
for (var i = balls.length - 1; i >= 0; i--) {
if (balls[i].hasBeenMerged) {
gameArea.removeChild(balls[i]);
balls[i].destroy();
balls.splice(i, 1);
}
}
}
game.down = function (x, y, obj) {
if (dropCooldown > 0) return;
// Constrain drop position to game area (convert to local coordinates)
var localWidth = gameAreaRight - gameAreaLeft;
var localX = x - gameAreaLeft;
var dropX = Math.max(60, Math.min(localWidth - 60, localX));
var newBall = new Ball(nextBallValue);
newBall.x = dropX;
newBall.y = 170; // Start below the danger zone (100px) plus ball radius (60px) plus buffer
newBall.velocityX = 0;
newBall.velocityY = 0;
balls.push(newBall);
gameArea.addChild(newBall);
LK.getSound('drop').play();
// Update next ball
nextBallValue = getRandomNextBallValue();
updateNextBallPreview();
dropCooldown = 30; // 0.5 seconds at 60fps
};
game.update = function () {
if (dropCooldown > 0) {
dropCooldown--;
}
cleanupMergedBalls();
checkGameOver();
// Update score display
scoreText.setText(LK.getScore());
}; ===================================================================
--- original.js
+++ change.js
@@ -69,9 +69,9 @@
var normalY = dy / distance;
self.x = otherBall.x - normalX * safeDistance;
self.y = otherBall.y - normalY * safeDistance;
// Check for merge first - increased sensitivity for same-numbered balls
- var mergeDistance = self.value === otherBall.value ? minDistance * 1.2 : minDistance;
+ var mergeDistance = self.value === otherBall.value ? minDistance * 1.4 : minDistance;
if (self.value === otherBall.value && self.mergeTimer === 0 && otherBall.mergeTimer === 0 && distance < mergeDistance) {
var newValue = self.value * 2;
if (newValue <= 2048) {
var newBall = new Ball(newValue);
@@ -187,9 +187,9 @@
var distance = Math.sqrt(dx * dx + dy * dy);
var minDistance = self.radius + otherBall.radius;
// Enhanced merge sensitivity for same-numbered balls
if (self.value === otherBall.value) {
- var mergeTriggerDistance = minDistance * 1.15; // 15% more sensitive
+ var mergeTriggerDistance = minDistance * 1.3; // 30% more sensitive
if (distance < mergeTriggerDistance) {
var newValue = self.value * 2;
if (newValue <= 2048) {
var newBall = new Ball(newValue);
Koyu yeşil bilye. In-Game asset. 2d. High contrast. No shadows
Kahverengi bilye. In-Game asset. 2d. High contrast. No shadows
Bprdo renk bilye. In-Game asset. 2d. High contrast. No shadows
Açık kahve bilye. In-Game asset. 2d. High contrast. No shadows
Gri bilye. In-Game asset. 2d. High contrast. No shadows