User prompt
Oyundaki siyah arkaplan her gem yok olduğunda renk değiştirsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyundan sariiii tuşunu kaldır
User prompt
Bo1 in işlevini sadece sarıgem yerine bütün gemler için yap ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Farklı bir dönüş animasyonu ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Timeout.tick error: self.startBo1Animation is not a function' in or related to this line: 'self.startBo1Animation();' Line Number: 77
User prompt
Bo1 farklı bir animasyonu olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Bo1 patladığı Zaman oyun tahtası ve gemler biraz sağ sola titresin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Bo1 patladığı Zaman 5x6 bölümlük gem patlatsin
User prompt
Bo1 sadece bir kere haraket edebilsin ve sonrasinda oda patlasın
User prompt
Bo1 ekrana geldiğinde arkasında çıkan gem iconunu sil
User prompt
Bo1 sarı patladığı Zaman ekrana gelmiyor bunu cöž
User prompt
Bo1 yanlizca 1 adet çıksın ve 5 adet yanyana sarı gem patladığı Zaman patlayan sarı mücevher yerinde çıksın
User prompt
Bo1 lolo1 katmanına yerleştir
User prompt
5 adet yanyana sarıgem patladığı Zaman 3 kısımdaki sarıgem yerine bo1 gelsin ekrana
User prompt
Sariiii düğmesine basınca gelen 5x5 sadece yanyana 5 adet gelicek şekilde yap
User prompt
Sarı gem 5x5 olduğu zaman bo1 gelmesi yerine sadece 5 adet yanyana geldiği zaman orta kısımda gelsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyun tahtasının hemen yan tarafına getir ve rengini siyah yap
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Gem = Container.expand(function (gemType, gridX, gridY) {
var self = Container.call(this);
self.gemType = gemType;
self.gridX = gridX;
self.gridY = gridY;
self.isAnimating = false;
self.hasMoved = false; // Track if bo1 gem has been moved
var gemAssets = ['gemRed', 'gemBlue', 'gemGreen', 'gemYellow', 'gemPurple', 'gemOrange', 'bo1'];
var gemGraphics = self.attachAsset(gemAssets[gemType], {
anchorX: 0.5,
anchorY: 0.5
});
self.setGridPosition = function (x, y) {
self.gridX = x;
self.gridY = y;
};
self.animateToPosition = function (targetX, targetY, duration, onComplete) {
if (!duration) duration = 200;
self.isAnimating = true;
tween(self, {
x: targetX,
y: targetY
}, {
duration: duration,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
if (onComplete) onComplete();
}
});
};
self.startBo1Animation = function () {
if (self.gemType !== 6) return;
function createPulseEffect() {
if (!self.parent) return;
// Pulsing scale effect
tween(self, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!self.parent) return;
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent && self.gemType === 6) {
createPulseEffect();
}
}
});
}
});
}
function createGlowEffect() {
if (!self.parent) return;
// Glowing tint effect
tween(self, {
tint: 0xFFD700
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!self.parent) return;
tween(self, {
tint: 0xFFFFFF
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent && self.gemType === 6) {
createGlowEffect();
}
}
});
}
});
}
function createRotationEffect() {
if (!self.parent) return;
// Gentle rotating effect
var currentRotation = self.rotation || 0;
tween(self, {
rotation: currentRotation + Math.PI * 2
}, {
duration: 3000,
easing: tween.linear,
onFinish: function onFinish() {
if (self.parent && self.gemType === 6) {
createRotationEffect();
}
}
});
}
// Start all bo1 effects with slight delays
LK.setTimeout(function () {
if (self.parent && self.gemType === 6) {
createPulseEffect();
}
}, 100);
LK.setTimeout(function () {
if (self.parent && self.gemType === 6) {
createGlowEffect();
}
}, 200);
LK.setTimeout(function () {
if (self.parent && self.gemType === 6) {
createRotationEffect();
}
}, 300);
};
// Special animation for bo1 gems - call after function is defined
if (self.gemType === 6) {
self.startBo1Animation();
}
self.destroy = function () {
// Play gem-specific destruction sound
var gemSounds = ['gemRedDestroy', 'gemBlueDestroy', 'gemGreenDestroy', 'gemYellowDestroy', 'gemPurpleDestroy', 'gemOrangeDestroy', 'gemPinkDestroy'];
if (self.gemType >= 0 && self.gemType < gemSounds.length) {
try {
LK.getSound(gemSounds[self.gemType]).play();
} catch (e) {
console.log('Sound not found:', gemSounds[self.gemType]);
}
}
// Special animation for red gems (gemType 0)
if (self.gemType === 0) {
self.createFlameExplosion();
}
// Special animation for blue gems (gemType 1)
if (self.gemType === 1) {
self.createWaterExplosion();
}
// Special animation for green gems (gemType 2)
if (self.gemType === 2) {
self.createLeafSpiral();
}
// Special animation for yellow gems (gemType 3)
if (self.gemType === 3) {
self.createStarExplosion();
}
// Special animation for purple gems (gemType 4)
if (self.gemType === 4) {
self.createPurpleImplosion();
}
// Special animation for orange gems (gemType 5)
if (self.gemType === 5) {
self.createLavaMelting();
}
// Special animation for pink gems (gemType 6)
if (self.gemType === 6) {
self.createHeartExplosion();
}
// Create tween effect before actually destroying
tween(self, {
alpha: 0,
scaleX: 0.2,
scaleY: 0.2
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
};
self.createFlameExplosion = function () {
var flameCount = 6; // Reduced from 8
var radius = 100;
for (var i = 0; i < flameCount; i++) {
var angle = i / flameCount * Math.PI * 2;
var flameParticle = LK.getAsset('flameParticle', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position at gem center
flameParticle.x = self.x;
flameParticle.y = self.y;
flameParticle.zIndex = 5;
// Add to game
if (self.parent) {
self.parent.addChild(flameParticle);
}
// Calculate spiral target position
var targetX = self.x + Math.cos(angle) * radius;
var targetY = self.y + Math.sin(angle) * radius;
// Create spiral rotation and movement animation
tween(flameParticle, {
x: targetX,
y: targetY,
rotation: Math.PI * 4,
// 2 full rotations
scaleX: 3.0,
scaleY: 3.0
}, {
duration: 400,
easing: tween.easeOut
});
// Fade out and disappear
tween(flameParticle, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (flameParticle.parent) {
flameParticle.parent.removeChild(flameParticle);
}
}
});
// Add flame color transition from orange to red
tween(flameParticle, {
tint: 0xff0000
}, {
duration: 300,
easing: tween.easeInOut
});
}
};
self.createWaterExplosion = function () {
var dropletCount = 8; // Reduced from 12
var maxRadius = 120;
for (var i = 0; i < dropletCount; i++) {
var angle = i / dropletCount * Math.PI * 2;
var waterDroplet = LK.getAsset('waterDroplet', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position at gem center
waterDroplet.x = self.x;
waterDroplet.y = self.y;
waterDroplet.zIndex = 5;
// Random radius for scattered effect
var radius = 60 + Math.random() * 60;
// Add to game
if (self.parent) {
self.parent.addChild(waterDroplet);
}
// Calculate target position for water droplet
var targetX = self.x + Math.cos(angle) * radius;
var targetY = self.y + Math.sin(angle) * radius;
// Create bouncing water droplet movement
tween(waterDroplet, {
x: targetX,
y: targetY,
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 350,
easing: tween.bounceOut
});
// Create ripple effect with scaling
tween(waterDroplet, {
scaleX: 0.8,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeInOut
});
// Fade out like evaporating water
tween(waterDroplet, {
alpha: 0,
scaleY: 0.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (waterDroplet.parent) {
waterDroplet.parent.removeChild(waterDroplet);
}
}
});
// Add water color transition from light blue to transparent
tween(waterDroplet, {
tint: 0x00aaff
}, {
duration: 250,
easing: tween.easeInOut
});
}
};
self.createPurpleImplosion = function () {
var vortexCount = 10; // Reduced from 16
var initialRadius = 150;
for (var i = 0; i < vortexCount; i++) {
var angle = i / vortexCount * Math.PI * 2;
var purpleVortex = LK.getAsset('purpleVortex', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position in a circle around the gem
var startX = self.x + Math.cos(angle) * initialRadius;
var startY = self.y + Math.sin(angle) * initialRadius;
purpleVortex.x = startX;
purpleVortex.y = startY;
purpleVortex.zIndex = 5;
// Add purple tint and initial scale
purpleVortex.tint = 0x8B00FF;
purpleVortex.scaleX = 0.5;
purpleVortex.scaleY = 0.5;
// Add to game
if (self.parent) {
self.parent.addChild(purpleVortex);
}
// Create spiral inward movement animation
tween(purpleVortex, {
x: self.x,
y: self.y,
rotation: Math.PI * 6,
// 3 full rotations inward
scaleX: 3.5,
scaleY: 3.5
}, {
duration: 600,
easing: tween.easeIn
});
// Fade in then fade out with implosion effect
tween(purpleVortex, {
alpha: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
// Final implosion - scale down and disappear
tween(purpleVortex, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 400,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (purpleVortex.parent) {
purpleVortex.parent.removeChild(purpleVortex);
}
}
});
// Color transition from purple to dark purple
tween(purpleVortex, {
tint: 0x4B0082
}, {
duration: 300,
easing: tween.easeInOut
});
}
};
self.createLeafSpiral = function () {
var leafCount = 6; // Reduced from 10
var spiralRadius = 140;
for (var i = 0; i < leafCount; i++) {
var angle = i / leafCount * Math.PI * 2;
var leafParticle = LK.getAsset('leafParticle', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position at gem center
leafParticle.x = self.x;
leafParticle.y = self.y;
leafParticle.zIndex = 5;
// Add natural green tint and initial scale
leafParticle.tint = 0x228B22;
leafParticle.scaleX = 0.8;
leafParticle.scaleY = 0.8;
leafParticle.rotation = angle; // Initial rotation based on position
// Add to game
if (self.parent) {
self.parent.addChild(leafParticle);
}
// Create spiral outward movement with natural floating motion
var targetX = self.x + Math.cos(angle) * spiralRadius;
var targetY = self.y + Math.sin(angle) * spiralRadius;
// Add some randomness for natural leaf movement
targetX += (Math.random() - 0.5) * 60;
targetY += (Math.random() - 0.5) * 60;
// Create floating leaf movement animation
tween(leafParticle, {
x: targetX,
y: targetY,
rotation: angle + Math.PI * 3,
// 1.5 full rotations
scaleX: 2.8,
scaleY: 2.8
}, {
duration: 500,
easing: tween.easeOut
});
// Add gentle swaying motion like leaves in wind
tween(leafParticle, {
x: targetX + Math.sin(angle * 2) * 30,
y: targetY + Math.cos(angle * 2) * 20
}, {
duration: 800,
easing: tween.easeInOut
});
// Fade out like autumn leaves
tween(leafParticle, {
alpha: 0,
scaleX: 0.3,
scaleY: 0.3,
rotation: angle + Math.PI * 5 // Continue rotating as it fades
}, {
duration: 700,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (leafParticle.parent) {
leafParticle.parent.removeChild(leafParticle);
}
}
});
// Add leaf color transition from green to brown
tween(leafParticle, {
tint: 0x8B4513 // Brown color
}, {
duration: 400,
easing: tween.easeInOut
});
}
};
self.createStarExplosion = function () {
var starCount = 8; // Reduced from 14
var maxRadius = 160;
for (var i = 0; i < starCount; i++) {
var angle = i / starCount * Math.PI * 2;
var starParticle = LK.getAsset('starParticle', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position at gem center
starParticle.x = self.x;
starParticle.y = self.y;
starParticle.zIndex = 5;
// Add golden yellow tint and initial scale
starParticle.tint = 0xFFD700;
starParticle.scaleX = 0.3;
starParticle.scaleY = 0.3;
starParticle.rotation = angle;
// Add to game
if (self.parent) {
self.parent.addChild(starParticle);
}
// Create spiral outward sun burst movement
var radius = 80 + Math.random() * 80;
var targetX = self.x + Math.cos(angle) * radius;
var targetY = self.y + Math.sin(angle) * radius;
// Add sparkle randomness for star effect
targetX += (Math.random() - 0.5) * 40;
targetY += (Math.random() - 0.5) * 40;
// Create explosive star movement animation
tween(starParticle, {
x: targetX,
y: targetY,
rotation: angle + Math.PI * 4,
// 2 full rotations
scaleX: 5.0,
scaleY: 5.0
}, {
duration: 450,
easing: tween.easeOut
});
// Add pulsing sparkle effect
tween(starParticle, {
scaleX: 6.5,
scaleY: 6.5
}, {
duration: 150,
easing: tween.easeInOut
});
// Create secondary sparkle pulse
tween(starParticle, {
scaleX: 4.5,
scaleY: 4.5,
rotation: angle + Math.PI * 6 // Continue rotating
}, {
duration: 300,
easing: tween.easeInOut
});
// Fade out like fading starlight
tween(starParticle, {
alpha: 0,
scaleX: 0.2,
scaleY: 0.2,
rotation: angle + Math.PI * 8 // Final rotation burst
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (starParticle.parent) {
starParticle.parent.removeChild(starParticle);
}
}
});
// Add star color transition from gold to bright white
tween(starParticle, {
tint: 0xFFFFFF // Bright white
}, {
duration: 350,
easing: tween.easeInOut
});
}
};
self.createLavaMelting = function () {
var lavaCount = 8; // Reduced from 12
var meltRadius = 130;
for (var i = 0; i < lavaCount; i++) {
var angle = i / lavaCount * Math.PI * 2;
var lavaParticle = LK.getAsset('lavaParticle', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position at gem center
lavaParticle.x = self.x;
lavaParticle.y = self.y;
lavaParticle.zIndex = 5;
// Add molten orange-red tint and initial scale
lavaParticle.tint = 0xFF4500;
lavaParticle.scaleX = 0.6;
lavaParticle.scaleY = 0.6;
lavaParticle.rotation = Math.random() * Math.PI * 2;
// Add to game
if (self.parent) {
self.parent.addChild(lavaParticle);
}
// Create melting downward movement with spiral motion
var radius = 70 + Math.random() * 60;
var targetX = self.x + Math.cos(angle) * radius;
var targetY = self.y + Math.sin(angle) * radius;
// Add downward melting bias
targetY += Math.random() * 80 + 40;
// Add some randomness for natural lava flow
targetX += (Math.random() - 0.5) * 50;
// Create lava melting movement animation
tween(lavaParticle, {
x: targetX,
y: targetY,
rotation: angle + Math.PI * 3,
// 1.5 full rotations
scaleX: 3.2,
scaleY: 3.2
}, {
duration: 550,
easing: tween.easeOut
});
// Add viscous lava dripping effect
tween(lavaParticle, {
y: targetY + 60,
scaleY: 4.0 // Stretch vertically like dripping lava
}, {
duration: 400,
easing: tween.easeIn
});
// Create molten glow pulsing effect
tween(lavaParticle, {
scaleX: 4.0,
tint: 0xFF6600 // Brighter orange
}, {
duration: 300,
easing: tween.easeInOut
});
// Cool down and solidify effect
tween(lavaParticle, {
alpha: 0,
scaleX: 0.4,
scaleY: 0.2,
tint: 0x8B0000,
// Dark red when cooling
rotation: angle + Math.PI * 5 // Continue rotating as it cools
}, {
duration: 650,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (lavaParticle.parent) {
lavaParticle.parent.removeChild(lavaParticle);
}
}
});
// Add secondary heat shimmer effect
tween(lavaParticle, {
scaleX: 2.8,
scaleY: 3.5
}, {
duration: 200,
easing: tween.easeInOut
});
}
};
self.createHeartExplosion = function () {
var heartCount = 8; // Heart-shaped particles
var maxRadius = 140;
for (var i = 0; i < heartCount; i++) {
var angle = i / heartCount * Math.PI * 2;
var heartParticle = LK.getAsset('starParticle', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial position at gem center
heartParticle.x = self.x;
heartParticle.y = self.y;
heartParticle.zIndex = 5;
// Add pink tint and initial scale
heartParticle.tint = 0xFF69B4; // Hot pink color
heartParticle.scaleX = 0.4;
heartParticle.scaleY = 0.4;
heartParticle.rotation = angle;
// Add to game
if (self.parent) {
self.parent.addChild(heartParticle);
}
// Create heart-shaped movement pattern
var radius = 80 + Math.random() * 60;
var targetX = self.x + Math.cos(angle) * radius;
var targetY = self.y + Math.sin(angle) * radius;
// Add heart-like floating effect
targetX += Math.sin(angle * 2) * 30;
targetY += Math.cos(angle * 2) * 20;
// Create romantic floating movement animation
tween(heartParticle, {
x: targetX,
y: targetY,
rotation: angle + Math.PI * 3,
// 1.5 full rotations
scaleX: 4.0,
scaleY: 4.0
}, {
duration: 500,
easing: tween.easeOut
});
// Add gentle floating motion like floating hearts
tween(heartParticle, {
y: targetY - 40,
scaleX: 5.0,
scaleY: 5.0
}, {
duration: 400,
easing: tween.easeInOut
});
// Fade out like disappearing love
tween(heartParticle, {
alpha: 0,
scaleX: 0.3,
scaleY: 0.3,
rotation: angle + Math.PI * 5 // Continue romantic spinning
}, {
duration: 700,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (heartParticle.parent) {
heartParticle.parent.removeChild(heartParticle);
}
}
});
// Add color transition from hot pink to light pink
tween(heartParticle, {
tint: 0xFFB6C1 // Light pink color
}, {
duration: 350,
easing: tween.easeInOut
});
}
};
return self;
});
var Particle = Container.expand(function (x, y, color) {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.reset = function (x, y, color) {
// Set particle color
particleGraphics.tint = color;
// Set initial position
self.x = x;
self.y = y;
// Random velocity - increased for more dramatic effect
self.velocityX = (Math.random() - 0.5) * 300;
self.velocityY = (Math.random() - 0.5) * 300;
self.gravity = 600;
self.life = 1.0;
self.fadeSpeed = 1.0;
self.scale = 1.0;
self.scaleSpeed = 0.5;
self.alpha = 1.0;
self.scaleX = 1.0;
self.scaleY = 1.0;
};
// Initialize with provided values
self.reset(x, y, color);
self.update = function () {
// Update position based on velocity
self.x += self.velocityX * (1 / 60);
self.y += self.velocityY * (1 / 60);
// Apply gravity (positive for flipped board - particles fall down visually)
self.velocityY += self.gravity * (1 / 60);
// Fade out over time
self.life -= self.fadeSpeed * (1 / 60);
self.alpha = Math.max(0, self.life);
// Scale down over time for dramatic effect
self.scale -= self.scaleSpeed * (1 / 60);
if (self.scale > 0) {
self.scaleX = self.scale;
self.scaleY = self.scale;
}
// Remove when fully faded
if (self.life <= 0) {
self.destroy();
}
};
self.destroy = function () {
if (self.parent) {
self.parent.removeChild(self);
// Remove from active particles array
for (var i = 0; i < activeParticles.length; i++) {
if (activeParticles[i] === self) {
activeParticles.splice(i, 1);
break;
}
}
// Return to pool for reuse
if (particlePool.length < 50) {
particlePool.push(self);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var particlePool = [];
var activeParticles = [];
function createParticle(x, y, color) {
var particle;
if (particlePool.length > 0) {
particle = particlePool.pop();
particle.reset(x, y, color);
} else {
particle = new Particle(x, y, color);
}
activeParticles.push(particle);
return particle;
}
var GRID_SIZE_X = 6;
var GRID_SIZE_Y = 9;
var CELL_SIZE = 250;
var BOARD_OFFSET_X = (2048 - GRID_SIZE_X * CELL_SIZE) / 2;
var BOARD_OFFSET_Y = (2732 - GRID_SIZE_Y * CELL_SIZE) / 2;
var gameBoard = [];
var selectedGem = null;
var draggedGem = null;
var dragStartPos = null;
var isDragging = false;
var isSwapping = false;
var score = 0;
var comboMultiplier = 1;
var consecutiveGemsDestroyed = 0;
// Timer system - 7.5 minutes in seconds
var gameTimeLimit = 7.5 * 60; // 7.5 minutes = 450 seconds
var remainingTime = gameTimeLimit;
var gameTimer = null;
// Background removed - using plain black background
// Update timer display
function updateTimer() {
var minutes = Math.floor(remainingTime / 60);
var seconds = remainingTime % 60;
var timeText = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timerTxt.setText(timeText);
}
// Update health bar display
function updateHealthBar() {
// Calculate how many segments should be visible (10 segments total)
var visibleSegments = Math.ceil(playerHealth / 10);
// Update health text
healthTxt.setText('HEALTH: ' + playerHealth);
// Remove segments that should no longer be visible
for (var i = 0; i < healthSegments.length; i++) {
var segment = healthSegments[i];
if (i >= visibleSegments && segment.parent) {
// Animate segment removal with cutting effect
tween(segment, {
scaleX: 0,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function (segmentToRemove) {
return function () {
if (segmentToRemove.parent) {
segmentToRemove.parent.removeChild(segmentToRemove);
}
};
}(segment)
});
}
}
// Add back segments that should be visible but are missing
for (var i = 0; i < visibleSegments; i++) {
var segment = healthSegments[i];
if (segment && !segment.parent) {
// Re-add the segment to the GUI
segment.scaleX = 1;
segment.alpha = 1;
segment.tint = 0x00ff00;
lolo1.addChild(segment);
// Animate segment restoration with growing effect
tween(segment, {
scaleX: 1,
alpha: 1
}, {
duration: 300,
easing: tween.easeOut
});
}
}
// Flash remaining segments red when taking damage
if (playerHealth < maxHealth) {
for (var j = 0; j < visibleSegments; j++) {
if (healthSegments[j] && healthSegments[j].parent) {
tween(healthSegments[j], {
tint: 0xff6666
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function (segmentToFlash) {
return function () {
tween(segmentToFlash, {
tint: 0x00ff00
}, {
duration: 200,
easing: tween.easeInOut
});
};
}(healthSegments[j])
});
}
}
}
}
// Reduce player health
function reduceHealth(amount) {
playerHealth = Math.max(0, playerHealth - amount);
updateHealthBar();
// Flash screen red when taking damage
LK.effects.flashScreen(0xff0000, 300);
// Check for game over
if (playerHealth <= 0) {
LK.showGameOver();
}
}
// Create explosion effect at gem position
function createExplosion(x, y, gemColor) {
var particleCount = 8; // Reduced from 15
var gemColors = [0xff2222, 0x2222ff, 0x22ff22, 0xffff22, 0xff22ff, 0xff6622, 0xFF69B4];
var color = gemColors[gemColor] || 0xffffff;
for (var i = 0; i < particleCount; i++) {
var particle = createParticle(x, y, color);
game.addChild(particle);
}
}
// Board frame removed - using plain black background
// Create background layer
var lolo0 = new Container();
game.addChild(lolo0);
lolo0.zIndex = 1; // Behind all other elements
// Add black background to background layer
var blackBg = lolo0.attachAsset('blackBackground', {
anchorX: 0,
anchorY: 0
});
blackBg.x = 0;
blackBg.y = 0;
// Create UI container for all game elements
var lolo1 = new Container();
game.addChild(lolo1);
lolo1.zIndex = 2; // In front of lolo0 layer
// Create score display
var scoreTxt = new Text2('SCORE: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
// Add purple shadow effect and purple border stroke
if (scoreTxt.style) {
scoreTxt.style.dropShadow = true;
scoreTxt.style.dropShadowColor = "#8B00FF";
scoreTxt.style.dropShadowBlur = 3;
scoreTxt.style.dropShadowDistance = 3;
scoreTxt.style.stroke = "#8B00FF";
scoreTxt.style.strokeThickness = 4;
}
lolo1.addChild(scoreTxt);
scoreTxt.x = BOARD_OFFSET_X + GRID_SIZE_X * CELL_SIZE / 2;
scoreTxt.y = BOARD_OFFSET_Y + GRID_SIZE_Y * CELL_SIZE + 100;
// Create health system
var playerHealth = 100;
var maxHealth = 100;
// Create health bar background (red)
var healthBarBg = LK.getAsset('healthBarBg', {
anchorX: 0,
anchorY: 0.5
});
healthBarBg.x = BOARD_OFFSET_X;
healthBarBg.y = BOARD_OFFSET_Y - 150;
lolo1.addChild(healthBarBg);
// Create segmented health bar with 10 individual pieces
var healthSegments = [];
var segmentWidth = 40; // Each segment is 40px wide (400px total / 10 segments)
for (var i = 0; i < 10; i++) {
var healthSegment = LK.getAsset('healthBarFg', {
anchorX: 0,
anchorY: 0.5
});
healthSegment.width = segmentWidth;
healthSegment.x = BOARD_OFFSET_X + i * segmentWidth;
healthSegment.y = BOARD_OFFSET_Y - 150;
healthSegment.segmentIndex = i;
healthSegments.push(healthSegment);
lolo1.addChild(healthSegment);
}
// Create health text
var healthTxt = new Text2('HEALTH: 100', {
size: 50,
fill: 0x8B00FF
});
// Make text bold and add styling for better visibility
if (healthTxt.style) {
healthTxt.style.fontWeight = "bold";
healthTxt.style.stroke = "#ffffff";
healthTxt.style.strokeThickness = 2;
}
healthTxt.anchor.set(0, 0.5);
healthTxt.x = BOARD_OFFSET_X;
healthTxt.y = BOARD_OFFSET_Y - 100;
lolo1.addChild(healthTxt);
// Create timer display
var timerTxt = new Text2('7:30', {
size: 60,
fill: 0xFFFF00
});
// Make timer text bold and add styling for better visibility
if (timerTxt.style) {
timerTxt.style.fontWeight = "bold";
timerTxt.style.stroke = "#ffffff";
timerTxt.style.strokeThickness = 2;
timerTxt.style.dropShadow = true;
timerTxt.style.dropShadowColor = "#8B00FF";
timerTxt.style.dropShadowBlur = 3;
timerTxt.style.dropShadowDistance = 3;
}
timerTxt.anchor.set(1, 0); // Anchor to top-right for positioning
lolo1.addChild(timerTxt);
timerTxt.x = BOARD_OFFSET_X + GRID_SIZE_X * CELL_SIZE;
timerTxt.y = BOARD_OFFSET_Y - 250;
// Initialize empty board
function initializeBoard() {
gameBoard = [];
for (var x = 0; x < GRID_SIZE_X; x++) {
gameBoard[x] = [];
for (var y = 0; y < GRID_SIZE_Y; y++) {
gameBoard[x][y] = null;
}
}
}
// Fill board with random gems
function fillBoard() {
for (var x = 0; x < GRID_SIZE_X; x++) {
for (var y = 0; y < GRID_SIZE_Y; y++) {
if (!gameBoard[x][y]) {
var gemType = Math.floor(Math.random() * 6); // Only generate gems 0-5, excluding bo1
var gem = new Gem(gemType, x, y);
var worldPos = gridToWorld(x, y);
gem.x = worldPos.x;
gem.y = worldPos.y;
gem.zIndex = 4;
gameBoard[x][y] = gem;
lolo1.addChild(gem);
}
}
}
}
// Convert grid coordinates to world coordinates
function gridToWorld(gridX, gridY) {
return {
x: BOARD_OFFSET_X + gridX * CELL_SIZE + CELL_SIZE / 2,
y: BOARD_OFFSET_Y + (GRID_SIZE_Y - 1 - gridY) * CELL_SIZE + CELL_SIZE / 2
};
}
// Convert world coordinates to grid coordinates
function worldToGrid(worldX, worldY) {
var gridX = Math.floor((worldX - BOARD_OFFSET_X) / CELL_SIZE);
var gridY = GRID_SIZE_Y - 1 - Math.floor((worldY - BOARD_OFFSET_Y) / CELL_SIZE);
if (gridX < 0 || gridX >= GRID_SIZE_X || gridY < 0 || gridY >= GRID_SIZE_Y) {
return null;
}
return {
x: gridX,
y: gridY
};
}
// Check if two grid positions are adjacent
function areAdjacent(pos1, pos2) {
var dx = Math.abs(pos1.x - pos2.x);
var dy = Math.abs(pos1.y - pos2.y);
return dx === 1 && dy === 0 || dx === 0 && dy === 1;
}
// Check for matches starting at position (2x2 squares and 3-in-a-row)
function checkMatches(startX, startY) {
var gem = gameBoard[startX][startY];
if (!gem) return [];
var matches = [];
var gemType = gem.gemType;
// Check horizontal 3-in-a-row matches
var horizontalCount = 1;
var horizontalGems = [gem];
// Check right direction
for (var x = startX + 1; x < GRID_SIZE_X; x++) {
var rightGem = gameBoard[x][startY];
if (rightGem && rightGem.gemType === gemType) {
horizontalCount++;
horizontalGems.push(rightGem);
} else {
break;
}
}
// Check left direction
for (var x = startX - 1; x >= 0; x--) {
var leftGem = gameBoard[x][startY];
if (leftGem && leftGem.gemType === gemType) {
horizontalCount++;
horizontalGems.unshift(leftGem);
} else {
break;
}
}
// Add horizontal matches if 3 or more
if (horizontalCount >= 3) {
for (var h = 0; h < horizontalGems.length; h++) {
matches.push(horizontalGems[h]);
}
}
// Check vertical 3-in-a-row matches
var verticalCount = 1;
var verticalGems = [gem];
// Check up direction
for (var y = startY + 1; y < GRID_SIZE_Y; y++) {
var upGem = gameBoard[startX][y];
if (upGem && upGem.gemType === gemType) {
verticalCount++;
verticalGems.push(upGem);
} else {
break;
}
}
// Check down direction
for (var y = startY - 1; y >= 0; y--) {
var downGem = gameBoard[startX][y];
if (downGem && downGem.gemType === gemType) {
verticalCount++;
verticalGems.unshift(downGem);
} else {
break;
}
}
// Add vertical matches if 3 or more
if (verticalCount >= 3) {
for (var v = 0; v < verticalGems.length; v++) {
var found = false;
for (var m = 0; m < matches.length; m++) {
if (matches[m] === verticalGems[v]) {
found = true;
break;
}
}
if (!found) {
matches.push(verticalGems[v]);
}
}
}
// Check if this gem is part of a 2x2 square
// Check all possible 2x2 squares this gem could be part of
var squarePositions = [
// Top-left corner
[{
x: startX,
y: startY
}, {
x: startX + 1,
y: startY
}, {
x: startX,
y: startY + 1
}, {
x: startX + 1,
y: startY + 1
}],
// Top-right corner
[{
x: startX - 1,
y: startY
}, {
x: startX,
y: startY
}, {
x: startX - 1,
y: startY + 1
}, {
x: startX,
y: startY + 1
}],
// Bottom-left corner
[{
x: startX,
y: startY - 1
}, {
x: startX + 1,
y: startY - 1
}, {
x: startX,
y: startY
}, {
x: startX + 1,
y: startY
}],
// Bottom-right corner
[{
x: startX - 1,
y: startY - 1
}, {
x: startX,
y: startY - 1
}, {
x: startX - 1,
y: startY
}, {
x: startX,
y: startY
}]];
for (var s = 0; s < squarePositions.length; s++) {
var square = squarePositions[s];
var validSquare = true;
var squareGems = [];
// Check if all positions in this square are valid and contain same gem type
for (var p = 0; p < square.length; p++) {
var pos = square[p];
if (pos.x < 0 || pos.x >= GRID_SIZE_X || pos.y < 0 || pos.y >= GRID_SIZE_Y) {
validSquare = false;
break;
}
var squareGem = gameBoard[pos.x][pos.y];
if (!squareGem || squareGem.gemType !== gemType) {
validSquare = false;
break;
}
squareGems.push(squareGem);
}
// If we found a valid 2x2 square, add all gems to matches
if (validSquare) {
for (var g = 0; g < squareGems.length; g++) {
var found = false;
for (var m = 0; m < matches.length; m++) {
if (matches[m] === squareGems[g]) {
found = true;
break;
}
}
if (!found) {
matches.push(squareGems[g]);
}
}
}
}
return matches;
}
// Check if any valid moves exist on the board
function hasValidMoves() {
for (var x = 0; x < GRID_SIZE_X; x++) {
for (var y = 0; y < GRID_SIZE_Y; y++) {
var currentGem = gameBoard[x][y];
if (!currentGem) continue;
// Check all adjacent positions for potential swaps
var adjacentPositions = [{
x: x + 1,
y: y
},
// Right
{
x: x - 1,
y: y
},
// Left
{
x: x,
y: y + 1
},
// Up
{
x: x,
y: y - 1
} // Down
];
for (var i = 0; i < adjacentPositions.length; i++) {
var adjPos = adjacentPositions[i];
if (adjPos.x >= 0 && adjPos.x < GRID_SIZE_X && adjPos.y >= 0 && adjPos.y < GRID_SIZE_Y) {
var adjacentGem = gameBoard[adjPos.x][adjPos.y];
if (adjacentGem) {
// Temporarily swap gems to check if it creates matches
var tempGem1Type = currentGem.gemType;
var tempGem2Type = adjacentGem.gemType;
currentGem.gemType = tempGem2Type;
adjacentGem.gemType = tempGem1Type;
// Check if this swap creates any matches
var matches1 = checkMatches(x, y);
var matches2 = checkMatches(adjPos.x, adjPos.y);
// Restore original gem types
currentGem.gemType = tempGem1Type;
adjacentGem.gemType = tempGem2Type;
// If either position has matches after swap, it's a valid move
if (matches1.length > 0 || matches2.length > 0) {
return true;
}
}
}
}
}
}
return false;
}
// Shuffle gems on the board when no valid moves exist
function shuffleBoard() {
var gemTypes = [];
// Collect all gem types currently on the board
for (var x = 0; x < GRID_SIZE_X; x++) {
for (var y = 0; y < GRID_SIZE_Y; y++) {
if (gameBoard[x][y]) {
gemTypes.push(gameBoard[x][y].gemType);
}
}
}
// Shuffle the gem types array
for (var i = gemTypes.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = gemTypes[i];
gemTypes[i] = gemTypes[j];
gemTypes[j] = temp;
}
// Assign shuffled gem types back to the board
var typeIndex = 0;
for (var x = 0; x < GRID_SIZE_X; x++) {
for (var y = 0; y < GRID_SIZE_Y; y++) {
if (gameBoard[x][y]) {
var gem = gameBoard[x][y];
var newGemType = gemTypes[typeIndex];
typeIndex++;
// Create new gem with shuffled type
var newGem = new Gem(newGemType, x, y);
var worldPos = gridToWorld(x, y);
newGem.x = worldPos.x;
newGem.y = worldPos.y;
newGem.zIndex = 4;
// Remove old gem and add new one
gem.destroy();
gameBoard[x][y] = newGem;
lolo1.addChild(newGem);
}
}
}
}
// Find all matches on the board
function findAllMatches() {
var allMatches = [];
var processedGems = [];
for (var x = 0; x < GRID_SIZE_X; x++) {
for (var y = 0; y < GRID_SIZE_Y; y++) {
if (gameBoard[x][y]) {
var matches = checkMatches(x, y);
for (var i = 0; i < matches.length; i++) {
var gem = matches[i];
var found = false;
for (var j = 0; j < processedGems.length; j++) {
if (processedGems[j] === gem) {
found = true;
break;
}
}
if (!found) {
allMatches.push(gem);
processedGems.push(gem);
}
}
}
}
}
return allMatches;
}
// Clear matched gems
function clearMatches(matches) {
if (matches.length === 0) return;
LK.getSound('match').play();
var points = matches.length * 10 * comboMultiplier;
var oldScore = score;
score += points;
scoreTxt.setText('SCORE: ' + score);
// Health gain system - check if player should gain health every 1500 points
var oldHealthGainLevel = Math.floor(oldScore / 1500);
var newHealthGainLevel = Math.floor(score / 1500);
if (newHealthGainLevel > oldHealthGainLevel && playerHealth < maxHealth) {
// Player gains health, but don't exceed max health
var healthToGain = Math.min(10, maxHealth - playerHealth);
playerHealth += healthToGain;
updateHealthBar();
// Flash screen green to show health gain
LK.effects.flashScreen(0x00ff00, 500);
}
// Check for win condition - player reaches 10000 points
if (score >= 10000) {
LK.clearInterval(gameTimer);
LK.showYouWin();
return;
}
// Store destroyed gems for bo1 placement detection
var destroyedGems = [];
for (var i = 0; i < matches.length; i++) {
var gem = matches[i];
// Store gem info before destroying
destroyedGems.push({
gridX: gem.gridX,
gridY: gem.gridY,
gemType: gem.gemType
});
// Create explosion effect at gem position
createExplosion(gem.x, gem.y, gem.gemType);
gameBoard[gem.gridX][gem.gridY] = null;
gem.destroy();
// Change background color when gem is destroyed
var backgroundColors = [0x1a1a2e, 0x16213e, 0x0f3460, 0x533483, 0x7209b7, 0x2d1b69];
var newColor = backgroundColors[Math.floor(Math.random() * backgroundColors.length)];
tween(blackBg, {
tint: newColor
}, {
duration: 500,
easing: tween.easeInOut
});
}
// After clearing gems, apply gravity and fill empty spaces
LK.setTimeout(function () {
// Apply gravity repeatedly until no more gems fall
function applyGravityRepeatedly() {
var moved = applyGravity();
if (moved) {
LK.setTimeout(applyGravityRepeatedly, 100);
} else {
fillEmptySpaces(destroyedGems);
// Check for new matches after falling gems settle
LK.setTimeout(function () {
var newMatches = findAllMatches();
if (newMatches.length > 0) {
comboMultiplier++;
clearMatches(newMatches);
} else {
comboMultiplier = 1;
consecutiveGemsDestroyed = 0; // Reset counter when no more matches
isSwapping = false;
// Check if any valid moves exist, if not shuffle the board
if (!hasValidMoves()) {
shuffleBoard();
}
}
}, 500);
}
}
applyGravityRepeatedly();
}, 200);
}
// Apply gravity to make gems fall
function applyGravity() {
var moved = false;
for (var x = 0; x < GRID_SIZE_X; x++) {
// Collect all non-null gems in this column from bottom to top
var gemsInColumn = [];
for (var y = 0; y < GRID_SIZE_Y; y++) {
if (gameBoard[x][y]) {
gemsInColumn.push(gameBoard[x][y]);
}
gameBoard[x][y] = null; // Clear the position
}
// Place gems back from bottom (index 0) upward, filling gaps
for (var i = 0; i < gemsInColumn.length; i++) {
var gem = gemsInColumn[i];
var newY = i; // Place at bottom-most available position
if (gem.gridY !== newY) {
gem.setGridPosition(x, newY);
var worldPos = gridToWorld(x, newY);
gem.animateToPosition(worldPos.x, worldPos.y, 300);
moved = true;
}
gameBoard[x][newY] = gem;
}
}
return moved;
}
// Check if 5 consecutive gems of any type were just destroyed and return position for 1 bo1 gem
function has5ConsecutivePattern(destroyedGems) {
if (!destroyedGems || destroyedGems.length < 5) return null;
// Check for horizontal 5-in-a-row pattern of any gem type in destroyed gems
for (var y = 0; y < GRID_SIZE_Y; y++) {
for (var startX = 0; startX <= GRID_SIZE_X - 5; startX++) {
// Try each gem type (0-5, excluding bo1)
for (var gemType = 0; gemType < 6; gemType++) {
var gemCount = 0;
var consecutivePositions = [];
// Check if 5 consecutive horizontal positions had gems of this type destroyed
for (var x = startX; x < startX + 5; x++) {
var wasGemDestroyed = false;
for (var i = 0; i < destroyedGems.length; i++) {
var destroyedGem = destroyedGems[i];
if (destroyedGem.gridX === x && destroyedGem.gridY === y && destroyedGem.gemType === gemType) {
wasGemDestroyed = true;
break;
}
}
if (wasGemDestroyed) {
gemCount++;
consecutivePositions.push({
x: x,
y: y
});
} else {
break; // Not consecutive
}
}
if (gemCount === 5) {
// Return 1 position for bo1 gem at center of the 5-gem pattern
return [{
x: startX + 2,
y: y
}];
}
}
}
}
// Check for vertical 5-in-a-row pattern of any gem type in destroyed gems
for (var x = 0; x < GRID_SIZE_X; x++) {
for (var startY = 0; startY <= GRID_SIZE_Y - 5; startY++) {
// Try each gem type (0-5, excluding bo1)
for (var gemType = 0; gemType < 6; gemType++) {
var gemCount = 0;
var consecutivePositions = [];
// Check if 5 consecutive vertical positions had gems of this type destroyed
for (var y = startY; y < startY + 5; y++) {
var wasGemDestroyed = false;
for (var i = 0; i < destroyedGems.length; i++) {
var destroyedGem = destroyedGems[i];
if (destroyedGem.gridX === x && destroyedGem.gridY === y && destroyedGem.gemType === gemType) {
wasGemDestroyed = true;
break;
}
}
if (wasGemDestroyed) {
gemCount++;
consecutivePositions.push({
x: x,
y: y
});
} else {
break; // Not consecutive
}
}
if (gemCount === 5) {
// Return 1 position for bo1 gem at center of the 5-gem pattern
return [{
x: x,
y: startY + 2
}];
}
}
}
}
return null;
}
// Fill empty spaces with new gems
function fillEmptySpaces(lastDestroyedGems) {
var bo1Positions = has5ConsecutivePattern(lastDestroyedGems);
// First, place bo1 gems if any 5-consecutive pattern was detected
if (bo1Positions && bo1Positions.length > 0) {
for (var i = 0; i < bo1Positions.length; i++) {
var bo1Pos = bo1Positions[i];
// Remove existing gem at bo1 position if there is one
if (gameBoard[bo1Pos.x][bo1Pos.y]) {
gameBoard[bo1Pos.x][bo1Pos.y].destroy();
gameBoard[bo1Pos.x][bo1Pos.y] = null;
}
var bo1Gem = new Gem(6, bo1Pos.x, bo1Pos.y); // gemType 6 is bo1
var worldPos = gridToWorld(bo1Pos.x, bo1Pos.y);
bo1Gem.x = worldPos.x;
bo1Gem.y = worldPos.y;
bo1Gem.zIndex = 4;
gameBoard[bo1Pos.x][bo1Pos.y] = bo1Gem;
lolo1.addChild(bo1Gem);
// Add visual effect to highlight bo1 appearance
tween(bo1Gem, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function (gem) {
return function () {
tween(gem, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
};
}(bo1Gem)
});
}
}
for (var x = 0; x < GRID_SIZE_X; x++) {
// Count how many empty spaces exist in this column
var emptyCount = 0;
for (var y = 0; y < GRID_SIZE_Y; y++) {
if (!gameBoard[x][y]) {
emptyCount++;
}
}
// Fill empty spaces from top of column downward
var fillIndex = 0;
for (var y = 0; y < GRID_SIZE_Y; y++) {
if (!gameBoard[x][y]) {
var gemType = Math.floor(Math.random() * 6); // Only generate gems 0-5, excluding bo1
var gem = new Gem(gemType, x, y);
var worldPos = gridToWorld(x, y);
gem.x = worldPos.x;
// Start new gems from above the visible area
gem.y = BOARD_OFFSET_Y - CELL_SIZE * (emptyCount - fillIndex + 1);
gem.zIndex = 4;
gameBoard[x][y] = gem;
lolo1.addChild(gem);
gem.animateToPosition(worldPos.x, worldPos.y, 200 + fillIndex * 50); // Staggered timing
fillIndex++;
}
}
}
}
// Swap two gems
// Function to destroy gems in 5x6 area around bo1 gem
function destroyGemsInDirections(bo1X, bo1Y) {
var gemsToDestroy = [];
// Define 5x6 area around bo1 gem (2 left, 2 right, 2 up, 3 down from bo1)
var startX = Math.max(0, bo1X - 2);
var endX = Math.min(GRID_SIZE_X - 1, bo1X + 2);
var startY = Math.max(0, bo1Y - 2);
var endY = Math.min(GRID_SIZE_Y - 1, bo1Y + 3);
// Collect all gems in the 5x6 area
for (var x = startX; x <= endX; x++) {
for (var y = startY; y <= endY; y++) {
// Skip the bo1 gem itself
if (x === bo1X && y === bo1Y) continue;
var gem = gameBoard[x][y];
if (gem && gem.gemType !== 6) {
// Don't destroy other bo1 gems
gemsToDestroy.push(gem);
}
}
}
// Destroy all collected gems with animation
for (var i = 0; i < gemsToDestroy.length; i++) {
var gem = gemsToDestroy[i];
// Create explosion effect
createExplosion(gem.x, gem.y, gem.gemType);
// Clear from board
gameBoard[gem.gridX][gem.gridY] = null;
// Destroy gem with tween effect
gem.destroy();
}
// Add screen shake effect when bo1 explodes
if (gemsToDestroy.length > 0) {
// Create shake effect on game board and gems
tween(lolo1, {
x: lolo1.x + 15
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(lolo1, {
x: lolo1.x - 30
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(lolo1, {
x: lolo1.x + 30
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(lolo1, {
x: lolo1.x - 15
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
}
});
}
// Add points for destroyed gems
if (gemsToDestroy.length > 0) {
var points = gemsToDestroy.length * 50; // Higher points for bo1 destruction
score += points;
scoreTxt.setText('SCORE: ' + score);
}
return gemsToDestroy.length;
}
function swapGems(gem1, gem2) {
if (isSwapping) return;
// Check if either gem is bo1 and has already been moved
if (gem1.gemType === 6 && gem1.hasMoved || gem2.gemType === 6 && gem2.hasMoved) {
return; // Don't allow swap if bo1 has already been moved
}
isSwapping = true;
// Store original positions
var originalGem1X = gem1.gridX;
var originalGem1Y = gem1.gridY;
var originalGem2X = gem2.gridX;
var originalGem2Y = gem2.gridY;
// Mark bo1 gems as moved
if (gem1.gemType === 6) {
gem1.hasMoved = true;
}
if (gem2.gemType === 6) {
gem2.hasMoved = true;
}
// Update grid positions
gem1.setGridPosition(gem2.gridX, gem2.gridY);
gem2.setGridPosition(originalGem1X, originalGem1Y);
gameBoard[gem1.gridX][gem1.gridY] = gem1;
gameBoard[gem2.gridX][gem2.gridY] = gem2;
var pos1 = gridToWorld(gem1.gridX, gem1.gridY);
var pos2 = gridToWorld(gem2.gridX, gem2.gridY);
// Animate the swap
gem1.animateToPosition(pos1.x, pos1.y, 200);
gem2.animateToPosition(pos2.x, pos2.y, 200);
LK.setTimeout(function () {
// Check if either gem is bo1 and trigger directional destruction
var bo1Activated = false;
var bo1GemsToDestroy = [];
if (gem1.gemType === 6) {
// bo1 gem type
var destroyedCount = destroyGemsInDirections(gem1.gridX, gem1.gridY);
if (destroyedCount > 0) bo1Activated = true;
// Mark bo1 for destruction after it has moved
if (gem1.hasMoved) {
bo1GemsToDestroy.push(gem1);
}
}
if (gem2.gemType === 6) {
// bo1 gem type
var destroyedCount = destroyGemsInDirections(gem2.gridX, gem2.gridY);
if (destroyedCount > 0) bo1Activated = true;
// Mark bo1 for destruction after it has moved
if (gem2.hasMoved) {
bo1GemsToDestroy.push(gem2);
}
}
// Destroy bo1 gems that have been moved
for (var i = 0; i < bo1GemsToDestroy.length; i++) {
var bo1Gem = bo1GemsToDestroy[i];
createExplosion(bo1Gem.x, bo1Gem.y, bo1Gem.gemType);
gameBoard[bo1Gem.gridX][bo1Gem.gridY] = null;
bo1Gem.destroy();
}
var matches = findAllMatches();
if (matches.length > 0 || bo1Activated) {
// Valid swap - process matches
if (matches.length > 0) {
clearMatches(matches);
} else if (bo1Activated) {
// Only bo1 was activated, apply gravity and fill spaces
LK.setTimeout(function () {
function applyGravityRepeatedly() {
var moved = applyGravity();
if (moved) {
LK.setTimeout(applyGravityRepeatedly, 100);
} else {
fillEmptySpaces();
LK.setTimeout(function () {
var newMatches = findAllMatches();
if (newMatches.length > 0) {
comboMultiplier++;
clearMatches(newMatches);
} else {
comboMultiplier = 1;
isSwapping = false;
if (!hasValidMoves()) {
shuffleBoard();
}
}
}, 500);
}
}
applyGravityRepeatedly();
}, 200);
}
} else {
// Invalid move - reduce health by 10 and animate back to original positions
reduceHealth(10);
gem1.setGridPosition(originalGem1X, originalGem1Y);
gem2.setGridPosition(originalGem2X, originalGem2Y);
gameBoard[gem1.gridX][gem1.gridY] = gem1;
gameBoard[gem2.gridX][gem2.gridY] = gem2;
var pos1 = gridToWorld(gem1.gridX, gem1.gridY);
var pos2 = gridToWorld(gem2.gridX, gem2.gridY);
gem1.animateToPosition(pos1.x, pos1.y, 200);
gem2.animateToPosition(pos2.x, pos2.y, 200);
LK.setTimeout(function () {
isSwapping = false;
// Check if any valid moves exist after invalid swap
if (!hasValidMoves()) {
shuffleBoard();
}
}, 200);
}
}, 200);
}
// Game input handling
game.down = function (x, y, obj) {
if (isSwapping) return;
var gridPos = worldToGrid(x, y);
if (!gridPos) return;
var clickedGem = gameBoard[gridPos.x][gridPos.y];
if (!clickedGem) return;
draggedGem = clickedGem;
dragStartPos = {
x: x,
y: y
};
isDragging = true;
draggedGem.alpha = 0.7;
};
game.move = function (x, y, obj) {
if (!isDragging || !draggedGem || isSwapping) return;
// Calculate drag distance
var dragDeltaX = x - dragStartPos.x;
var dragDeltaY = y - dragStartPos.y;
var dragDistance = Math.sqrt(dragDeltaX * dragDeltaX + dragDeltaY * dragDeltaY);
// Only process if drag distance is significant enough
if (dragDistance > CELL_SIZE * 0.3) {
// Determine drag direction
var targetGridX = draggedGem.gridX;
var targetGridY = draggedGem.gridY;
if (Math.abs(dragDeltaX) > Math.abs(dragDeltaY)) {
// Horizontal drag
if (dragDeltaX > 0) {
targetGridX = Math.min(GRID_SIZE_X - 1, draggedGem.gridX + 1);
} else {
targetGridX = Math.max(0, draggedGem.gridX - 1);
}
} else {
// Vertical drag (flipped coordinate system)
if (dragDeltaY > 0) {
targetGridY = Math.max(0, draggedGem.gridY - 1);
} else {
targetGridY = Math.min(GRID_SIZE_Y - 1, draggedGem.gridY + 1);
}
}
// Update visual position to show intended swap
var targetWorldPos = gridToWorld(targetGridX, targetGridY);
draggedGem.x = targetWorldPos.x;
draggedGem.y = targetWorldPos.y;
// Store target position for later use
draggedGem.targetGridX = targetGridX;
draggedGem.targetGridY = targetGridY;
}
};
game.up = function (x, y, obj) {
if (!isDragging || !draggedGem || isSwapping) return;
var startGridPos = {
x: draggedGem.gridX,
y: draggedGem.gridY
};
// Check if we have a target position from dragging
if (draggedGem.targetGridX !== undefined && draggedGem.targetGridY !== undefined) {
var targetGridPos = {
x: draggedGem.targetGridX,
y: draggedGem.targetGridY
};
// Check if target position is valid and adjacent
if (areAdjacent(startGridPos, targetGridPos) && gameBoard[targetGridPos.x][targetGridPos.y]) {
var targetGem = gameBoard[targetGridPos.x][targetGridPos.y];
// Attempt swap
swapGems(draggedGem, targetGem);
} else {
// Invalid swap - animate back to original position
var worldPos = gridToWorld(draggedGem.gridX, draggedGem.gridY);
draggedGem.animateToPosition(worldPos.x, worldPos.y, 200);
}
// Clean up target position
draggedGem.targetGridX = undefined;
draggedGem.targetGridY = undefined;
} else {
// No significant drag - just return to original position
var worldPos = gridToWorld(draggedGem.gridX, draggedGem.gridY);
draggedGem.animateToPosition(worldPos.x, worldPos.y, 200);
}
draggedGem.alpha = 1.0;
draggedGem = null;
dragStartPos = null;
isDragging = false;
};
// Create grid lines around gems
function createGridLines() {
// Create vertical lines
for (var x = 0; x <= GRID_SIZE_X; x++) {
for (var lineY = 0; lineY < GRID_SIZE_Y * CELL_SIZE; lineY += 20) {
var verticalLine = LK.getAsset('particle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.05,
scaleY: 0.5
});
verticalLine.tint = 0x8B4513;
verticalLine.x = BOARD_OFFSET_X + x * CELL_SIZE;
verticalLine.y = BOARD_OFFSET_Y + lineY + 10;
verticalLine.zIndex = 3;
game.addChild(verticalLine);
}
}
// Create horizontal lines
for (var y = 0; y <= GRID_SIZE_Y; y++) {
for (var lineX = 0; lineX < GRID_SIZE_X * CELL_SIZE; lineX += 20) {
var horizontalLine = LK.getAsset('particle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.05
});
horizontalLine.tint = 0x8B4513;
horizontalLine.x = BOARD_OFFSET_X + lineX + 10;
horizontalLine.y = BOARD_OFFSET_Y + y * CELL_SIZE;
horizontalLine.zIndex = 3;
game.addChild(horizontalLine);
}
}
}
// Initialize the game
initializeBoard();
fillBoard();
createGridLines();
// Add game update loop for continuous animations
game.update = function () {
// Clean up particles that are off-screen or dead
for (var i = activeParticles.length - 1; i >= 0; i--) {
var particle = activeParticles[i];
if (!particle.parent || particle.y > 3000 || particle.y < -500) {
if (particle.parent) {
particle.destroy();
}
}
}
// Add smooth swaying rotation animation to all gems
for (var x = 0; x < GRID_SIZE_X; x++) {
for (var y = 0; y < GRID_SIZE_Y; y++) {
var gem = gameBoard[x][y];
if (gem && !gem.isAnimating && !gem.rotationStarted) {
// Create smooth swaying rotation effect
gem.rotationStarted = true;
var delay = (x + y) * 50; // Stagger the rotation animation
var maxRotation = Math.PI / 6 + Math.random() * Math.PI / 12; // Random sway amount between 30-45 degrees
LK.setTimeout(function (currentGem, maxRot) {
return function () {
function createSwayRotation(direction) {
if (currentGem.parent && !currentGem.isAnimating) {
var targetRotation = direction * maxRot;
tween(currentGem, {
rotation: targetRotation
}, {
duration: 2000 + Math.random() * 1000,
// Random duration between 2-3 seconds
easing: tween.easeInOut,
onFinish: function onFinish() {
if (currentGem.parent && !currentGem.isAnimating) {
createSwayRotation(-direction); // Reverse direction for back-and-forth motion
}
}
});
}
}
createSwayRotation(Math.random() > 0.5 ? 1 : -1); // Start with random direction
};
}(gem, maxRotation), delay);
}
}
}
};
// Start countdown timer
gameTimer = LK.setInterval(function () {
remainingTime--;
updateTimer();
// Game over when time runs out
if (remainingTime <= 0) {
LK.clearInterval(gameTimer);
LK.showGameOver();
}
}, 1000); // Update every 1000ms (1 second)
// Start background music
LK.playMusic('background');
// Initialize timer display
updateTimer();
// Initial match clearing
LK.setTimeout(function () {
var matches = findAllMatches();
if (matches.length > 0) {
clearMatches(matches);
}
}, 100); ===================================================================
--- original.js
+++ change.js
@@ -1354,8 +1354,17 @@
// Create explosion effect at gem position
createExplosion(gem.x, gem.y, gem.gemType);
gameBoard[gem.gridX][gem.gridY] = null;
gem.destroy();
+ // Change background color when gem is destroyed
+ var backgroundColors = [0x1a1a2e, 0x16213e, 0x0f3460, 0x533483, 0x7209b7, 0x2d1b69];
+ var newColor = backgroundColors[Math.floor(Math.random() * backgroundColors.length)];
+ tween(blackBg, {
+ tint: newColor
+ }, {
+ duration: 500,
+ easing: tween.easeInOut
+ });
}
// After clearing gems, apply gravity and fill empty spaces
LK.setTimeout(function () {
// Apply gravity repeatedly until no more gems fall
Alev spiral parçacık. In-Game asset. 2d. High contrast. No shadows
Su damlası patlama parçacık. In-Game asset. 2d. High contrast. No shadows
Karadelik vortex parçacık spiral. In-Game asset. 2d. High contrast. No shadows
Yeşil yaprak süzülen. In-Game asset. 2d. High contrast. No shadows
Yıldız patlama parlak. In-Game asset. 2d. High contrast. No shadows
Lav topu erimiş. In-Game asset. 2d. High contrast. No shadows
Health bar, grandyan, green,. In-Game asset. 2d. High contrast. No shadows
Hiç birşeye dokunma sadece yeşil olan kısımları kırmızı ile yer değiştir
Bomba şeklinide grandyan ama çizgili rengarenk olsun