/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Arrow = Container.expand(function (colorType) {
	var self = Container.call(this);
	self.colorType = colorType;
	self.directionX = 0;
	self.directionY = 0;
	self.speed = 400;
	self.isDestroyed = false;
	self.hasProcessedBlocks = false;
	self.connectedBlocks = [];
	// Create arrow graphics - long white arrow (invisible)
	var arrowGraphics = self.attachAsset('arrow', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 0.8,
		alpha: 0
	});
	self.setDirection = function (targetX, targetY) {
		// Calculate normalized direction vector
		var dx = targetX - self.x;
		var dy = targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance > 0) {
			self.directionX = dx / distance;
			self.directionY = dy / distance;
			arrowGraphics.rotation = Math.atan2(dy, dx);
		}
	};
	self.update = function () {
		if (self.isDestroyed) {
			return;
		}
		// Check if we have enough connected blocks to stop
		if (self.connectedBlocks && self.connectedBlocks.length >= 3 && !self.hasProcessedBlocks) {
			self.hasProcessedBlocks = true;
			// Process connected blocks immediately
			clearSelection();
			selectedBlocks = self.connectedBlocks;
			blastSelectedBlocks();
			// Keep arrow visible for a moment before destroying
			LK.setTimeout(function () {
				self.destroyArrow();
			}, 500);
			return;
		}
		// Move in straight line using direction vector only if we haven't processed blocks yet
		// Stop moving if we have any connected blocks to keep arrow visible
		if (!self.hasProcessedBlocks && (!self.connectedBlocks || self.connectedBlocks.length === 0)) {
			self.x += self.directionX * self.speed * (1 / 60);
			self.y += self.directionY * self.speed * (1 / 60);
		}
		// Arrow is invisible, no pulsing effect needed
		// Check collision with blocks only if we haven't processed blocks yet
		if (!self.hasProcessedBlocks) {
			self.checkBlockCollision();
		}
		// Remove arrow if it goes off screen
		if (self.x < -200 || self.x > 2248 || self.y < -200 || self.y > 2932) {
			// Only destroy if we haven't processed blocks or if no blocks were connected
			if (!self.hasProcessedBlocks) {
				// Clear selection for any connected blocks
				if (self.connectedBlocks && self.connectedBlocks.length > 0) {
					for (var i = 0; i < self.connectedBlocks.length; i++) {
						self.connectedBlocks[i].setSelected(false);
					}
				}
				self.destroyArrow();
			}
		}
	};
	self.connectAdjacentBlocks = function (centerBlock) {
		if (!centerBlock || centerBlock.isDestroyed) {
			return;
		}
		var directions = [[0, -1], [0, 1], [-1, 0], [1, 0]]; // up, down, left, right
		for (var i = 0; i < directions.length; i++) {
			var newX = centerBlock.gridX + directions[i][0];
			var newY = centerBlock.gridY + directions[i][1];
			if (newX >= 0 && newX < GRID_WIDTH && newY >= 0 && newY < GRID_HEIGHT) {
				var adjacentBlock = grid[newX][newY];
				if (adjacentBlock && adjacentBlock.colorType === self.colorType && !adjacentBlock.isDestroyed) {
					// Check if we already connected this block
					var alreadyConnected = false;
					for (var j = 0; j < self.connectedBlocks.length; j++) {
						if (self.connectedBlocks[j] === adjacentBlock) {
							alreadyConnected = true;
							break;
						}
					}
					if (!alreadyConnected) {
						self.connectedBlocks.push(adjacentBlock);
						adjacentBlock.setSelected(true);
						// Recursively connect blocks adjacent to this one
						self.connectAdjacentBlocks(adjacentBlock);
					}
				}
			}
		}
	};
	self.checkBlockCollision = function () {
		var gridX = Math.floor((self.x - GRID_START_X) / BLOCK_SIZE);
		var gridY = Math.floor((self.y - GRID_START_Y) / BLOCK_SIZE);
		if (gridX >= 0 && gridX < GRID_WIDTH && gridY >= 0 && gridY < GRID_HEIGHT) {
			var hitBlock = grid[gridX][gridY];
			if (hitBlock && hitBlock.colorType === self.colorType && !hitBlock.isDestroyed) {
				// Mark this block as connected by the arrow
				if (!self.connectedBlocks) {
					self.connectedBlocks = [];
				}
				// Check if we already connected this block
				var alreadyConnected = false;
				for (var i = 0; i < self.connectedBlocks.length; i++) {
					if (self.connectedBlocks[i] === hitBlock) {
						alreadyConnected = true;
						break;
					}
				}
				if (!alreadyConnected) {
					self.connectedBlocks.push(hitBlock);
					// Visual feedback for connected block
					hitBlock.setSelected(true);
					// Connect all adjacent blocks of the same color
					self.connectAdjacentBlocks(hitBlock);
					// If we have less than 3 blocks after connecting, set a timeout to destroy arrow
					if (self.connectedBlocks.length < 3) {
						LK.setTimeout(function () {
							if (!self.isDestroyed && !self.hasProcessedBlocks) {
								// Clear selection for connected blocks
								for (var i = 0; i < self.connectedBlocks.length; i++) {
									self.connectedBlocks[i].setSelected(false);
								}
								self.destroyArrow();
							}
						}, 1500); // Give 1.5 seconds to potentially connect more blocks
					}
				}
			}
		}
	};
	self.destroyArrow = function () {
		if (!self.isDestroyed) {
			self.isDestroyed = true;
			self.destroy();
			var index = activeArrows.indexOf(self);
			if (index !== -1) {
				activeArrows.splice(index, 1);
			}
		}
	};
	return self;
});
var Block = Container.expand(function (colorType) {
	var self = Container.call(this);
	self.colorType = colorType;
	self.gridX = 0;
	self.gridY = 0;
	self.isSelected = false;
	self.isDragging = false;
	self.originalX = 0;
	self.originalY = 0;
	self.isDestroyed = false;
	var blockAssets = ['blockRed', 'blockBlue', 'blockGreen', 'blockYellow', 'blockPurple'];
	var blockGraphics = self.attachAsset(blockAssets[colorType], {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.setSelected = function (selected) {
		self.isSelected = selected;
		if (selected) {
			blockGraphics.alpha = 0.8;
			blockGraphics.scaleX = 1.05;
			blockGraphics.scaleY = 1.05;
			tween(blockGraphics, {
				tint: 0xFFFFAA
			}, {
				duration: 200
			});
		} else {
			blockGraphics.alpha = 1.0;
			blockGraphics.scaleX = 1.0;
			blockGraphics.scaleY = 1.0;
			tween(blockGraphics, {
				tint: 0xFFFFFF
			}, {
				duration: 200
			});
		}
	};
	self.blast = function () {
		if (self.isDestroyed) {
			return;
		}
		self.isDestroyed = true;
		// No individual point effect - will be handled by blastSelectedBlocks
		tween(blockGraphics, {
			scaleX: 1.5,
			scaleY: 1.5,
			alpha: 0
		}, {
			duration: 300,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	return self;
});
var PointEffect = Container.expand(function (points, x, y) {
	var self = Container.call(this);
	self.x = x;
	self.y = y;
	// Randomly choose between point effect assets
	var effectAssets = ['pointEffect', 'pointEffect2'];
	var randomAsset = effectAssets[Math.floor(Math.random() * effectAssets.length)];
	// Create point effect graphics - bigger for combo effects
	var effectGraphics = self.attachAsset(randomAsset, {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.1,
		scaleY: 0.1,
		alpha: 0
	});
	// No text needed - just visual effect
	// Appear with bigger effect for combos
	var maxScale = Math.min(3.0, 1.0 + points / 500);
	tween(effectGraphics, {
		scaleX: maxScale,
		scaleY: maxScale,
		alpha: 1.0
	}, {
		duration: 300,
		easing: tween.bounceOut,
		onFinish: function onFinish() {
			// Move up and fade out
			tween(self, {
				y: self.y - 150
			}, {
				duration: 1000,
				easing: tween.easeOut
			});
			tween(effectGraphics, {
				alpha: 0,
				scaleX: maxScale * 1.5,
				scaleY: maxScale * 1.5
			}, {
				duration: 1000,
				easing: tween.easeOut
			});
			// Destroy effect after animation completes
			LK.setTimeout(function () {
				self.destroy();
			}, 1000);
		}
	});
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2c3e50
});
/**** 
* Game Code
****/ 
var GRID_WIDTH = 8;
var GRID_HEIGHT = 10;
var BLOCK_SIZE = 200;
var GRID_START_X = (2048 - GRID_WIDTH * BLOCK_SIZE) / 2;
var GRID_START_Y = 400;
var grid = [];
var selectedBlocks = [];
var currentLevel = 1;
var currentScore = 0;
var targetScore = 1000;
var gameActive = true;
var activeArrows = [];
var shootingBlock = null;
// Initialize grid array
for (var x = 0; x < GRID_WIDTH; x++) {
	grid[x] = [];
	for (var y = 0; y < GRID_HEIGHT; y++) {
		grid[x][y] = null;
	}
}
// Add white background - bigger scale to fill more screen
var background = game.attachAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0,
	scaleX: 1.2,
	scaleY: 1.2
});
// UI Elements
// Add background shape for score text
var scoreBackground = game.attachAsset('scoreBackground', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 180,
	alpha: 0.8
});
var scoreText = new Text2('Score: 0', {
	size: 80,
	fill: 0x000000
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 1024;
scoreText.y = 180;
game.addChild(scoreText);
// Add background shape for target text
var targetBackground = game.attachAsset('targetBackground', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 280,
	alpha: 0.8
});
var targetText = new Text2('Target: 1000', {
	size: 70,
	fill: 0x0066CC
});
targetText.anchor.set(0.5, 0.5);
targetText.x = 1024;
targetText.y = 280;
game.addChild(targetText);
// Add background shape for level text
var levelBackground = game.attachAsset('levelBackground', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 100,
	alpha: 0.8
});
var levelText = new Text2('Level 1', {
	size: 90,
	fill: 0x000000
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 1024;
levelText.y = 100;
game.addChild(levelText);
function createBlock(x, y) {
	var colorType = Math.floor(Math.random() * 5);
	var block = new Block(colorType);
	block.gridX = x;
	block.gridY = y;
	block.x = GRID_START_X + x * BLOCK_SIZE + BLOCK_SIZE / 2;
	block.y = GRID_START_Y + y * BLOCK_SIZE + BLOCK_SIZE / 2;
	grid[x][y] = block;
	game.addChild(block);
	return block;
}
function initializeGrid() {
	for (var x = 0; x < GRID_WIDTH; x++) {
		for (var y = 0; y < GRID_HEIGHT; y++) {
			createBlock(x, y);
		}
	}
}
function getConnectedBlocks(startX, startY, colorType, visited) {
	if (!visited) {
		visited = [];
	}
	var key = startX + ',' + startY;
	if (visited.indexOf(key) !== -1) {
		return [];
	}
	if (startX < 0 || startX >= GRID_WIDTH || startY < 0 || startY >= GRID_HEIGHT) {
		return [];
	}
	if (!grid[startX][startY] || grid[startX][startY].colorType !== colorType) {
		return [];
	}
	visited.push(key);
	var connected = [grid[startX][startY]];
	// Check adjacent blocks (up, down, left, right)
	var directions = [[0, -1], [0, 1], [-1, 0], [1, 0]];
	for (var i = 0; i < directions.length; i++) {
		var newX = startX + directions[i][0];
		var newY = startY + directions[i][1];
		var adjacentBlocks = getConnectedBlocks(newX, newY, colorType, visited);
		connected = connected.concat(adjacentBlocks);
	}
	return connected;
}
function clearSelection() {
	for (var i = 0; i < selectedBlocks.length; i++) {
		selectedBlocks[i].setSelected(false);
	}
	selectedBlocks = [];
}
function selectBlockGroup(block) {
	clearSelection();
	selectedBlocks = getConnectedBlocks(block.gridX, block.gridY, block.colorType);
	if (selectedBlocks.length >= 3) {
		for (var i = 0; i < selectedBlocks.length; i++) {
			selectedBlocks[i].setSelected(true);
		}
		return true;
	} else {
		selectedBlocks = [];
		return false;
	}
}
function blastSelectedBlocks() {
	if (selectedBlocks.length < 3 || !gameActive) {
		return;
	}
	var points = calculateScore(selectedBlocks.length);
	currentScore += points;
	LK.getSound('blockBlast').play();
	LK.effects.flashScreen(0xffffff, 200);
	// Calculate center position of all selected blocks for big effect
	var centerX = 0;
	var centerY = 0;
	for (var i = 0; i < selectedBlocks.length; i++) {
		centerX += selectedBlocks[i].x;
		centerY += selectedBlocks[i].y;
	}
	centerX /= selectedBlocks.length;
	centerY /= selectedBlocks.length;
	// Create single big point effect at center
	var bigPointEffect = new PointEffect(points, centerX, centerY);
	game.addChild(bigPointEffect);
	// Remove blocks from grid and blast them
	for (var i = 0; i < selectedBlocks.length; i++) {
		var block = selectedBlocks[i];
		grid[block.gridX][block.gridY] = null;
		block.blast();
	}
	selectedBlocks = [];
	// Apply gravity after a short delay
	LK.setTimeout(function () {
		applyGravity();
		updateUI();
		checkGameState();
	}, 400);
}
function calculateScore(blockCount) {
	return blockCount * blockCount * 10;
}
function applyGravity() {
	for (var x = 0; x < GRID_WIDTH; x++) {
		var writeY = GRID_HEIGHT - 1;
		// Move existing blocks down
		for (var y = GRID_HEIGHT - 1; y >= 0; y--) {
			if (grid[x][y] !== null) {
				if (writeY !== y) {
					grid[x][writeY] = grid[x][y];
					grid[x][y] = null;
					grid[x][writeY].gridY = writeY;
					// Animate block falling
					var targetY = GRID_START_Y + writeY * BLOCK_SIZE + BLOCK_SIZE / 2;
					tween(grid[x][writeY], {
						y: targetY
					}, {
						duration: 300,
						easing: tween.easeOut
					});
				}
				writeY--;
			}
		}
		// Fill empty spaces at top with new blocks
		for (var y = writeY; y >= 0; y--) {
			var newBlock = createBlock(x, y);
			newBlock.y = GRID_START_Y - (writeY - y + 1) * BLOCK_SIZE + BLOCK_SIZE / 2;
			var targetY = GRID_START_Y + y * BLOCK_SIZE + BLOCK_SIZE / 2;
			tween(newBlock, {
				y: targetY
			}, {
				duration: 500,
				easing: tween.bounceOut
			});
		}
	}
}
function updateUI() {
	scoreText.setText('Score: ' + currentScore);
	LK.setScore(currentScore);
}
function checkGameState() {
	if (currentScore >= targetScore) {
		gameActive = false;
		LK.getSound('levelComplete').play();
		LK.setTimeout(function () {
			nextLevel();
		}, 1000);
	}
}
function nextLevel() {
	currentLevel++;
	targetScore = currentScore + 500 * currentLevel;
	gameActive = true;
	levelText.setText('Level ' + currentLevel);
	targetText.setText('Target: ' + targetScore);
	updateUI();
	if (currentLevel >= 10) {
		LK.showYouWin();
	}
}
game.down = function (x, y, obj) {
	if (!gameActive) {
		return;
	}
	var gridX = Math.floor((x - GRID_START_X) / BLOCK_SIZE);
	var gridY = Math.floor((y - GRID_START_Y) / BLOCK_SIZE);
	if (gridX >= 0 && gridX < GRID_WIDTH && gridY >= 0 && gridY < GRID_HEIGHT) {
		var block = grid[gridX][gridY];
		if (block) {
			shootingBlock = block;
		}
	}
};
game.move = function (x, y, obj) {
	// No dragging mechanics needed for arrow shooting
};
game.up = function (x, y, obj) {
	if (!gameActive || !shootingBlock) {
		return;
	}
	// Shoot arrow in direction of target
	var arrow = new Arrow(shootingBlock.colorType);
	arrow.x = shootingBlock.x;
	arrow.y = shootingBlock.y;
	arrow.setDirection(x, y);
	activeArrows.push(arrow);
	game.addChild(arrow);
	// Arrow is invisible, no spawn animation needed
	// Clear shooting state
	shootingBlock = null;
	clearSelection();
};
game.update = function () {
	// Update all active arrows
	for (var i = activeArrows.length - 1; i >= 0; i--) {
		var arrow = activeArrows[i];
		if (arrow.update) {
			arrow.update();
		}
	}
};
// Initialize the game
initializeGrid();
updateUI(); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
var Arrow = Container.expand(function (colorType) {
	var self = Container.call(this);
	self.colorType = colorType;
	self.directionX = 0;
	self.directionY = 0;
	self.speed = 400;
	self.isDestroyed = false;
	self.hasProcessedBlocks = false;
	self.connectedBlocks = [];
	// Create arrow graphics - long white arrow (invisible)
	var arrowGraphics = self.attachAsset('arrow', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.5,
		scaleY: 0.8,
		alpha: 0
	});
	self.setDirection = function (targetX, targetY) {
		// Calculate normalized direction vector
		var dx = targetX - self.x;
		var dy = targetY - self.y;
		var distance = Math.sqrt(dx * dx + dy * dy);
		if (distance > 0) {
			self.directionX = dx / distance;
			self.directionY = dy / distance;
			arrowGraphics.rotation = Math.atan2(dy, dx);
		}
	};
	self.update = function () {
		if (self.isDestroyed) {
			return;
		}
		// Check if we have enough connected blocks to stop
		if (self.connectedBlocks && self.connectedBlocks.length >= 3 && !self.hasProcessedBlocks) {
			self.hasProcessedBlocks = true;
			// Process connected blocks immediately
			clearSelection();
			selectedBlocks = self.connectedBlocks;
			blastSelectedBlocks();
			// Keep arrow visible for a moment before destroying
			LK.setTimeout(function () {
				self.destroyArrow();
			}, 500);
			return;
		}
		// Move in straight line using direction vector only if we haven't processed blocks yet
		// Stop moving if we have any connected blocks to keep arrow visible
		if (!self.hasProcessedBlocks && (!self.connectedBlocks || self.connectedBlocks.length === 0)) {
			self.x += self.directionX * self.speed * (1 / 60);
			self.y += self.directionY * self.speed * (1 / 60);
		}
		// Arrow is invisible, no pulsing effect needed
		// Check collision with blocks only if we haven't processed blocks yet
		if (!self.hasProcessedBlocks) {
			self.checkBlockCollision();
		}
		// Remove arrow if it goes off screen
		if (self.x < -200 || self.x > 2248 || self.y < -200 || self.y > 2932) {
			// Only destroy if we haven't processed blocks or if no blocks were connected
			if (!self.hasProcessedBlocks) {
				// Clear selection for any connected blocks
				if (self.connectedBlocks && self.connectedBlocks.length > 0) {
					for (var i = 0; i < self.connectedBlocks.length; i++) {
						self.connectedBlocks[i].setSelected(false);
					}
				}
				self.destroyArrow();
			}
		}
	};
	self.connectAdjacentBlocks = function (centerBlock) {
		if (!centerBlock || centerBlock.isDestroyed) {
			return;
		}
		var directions = [[0, -1], [0, 1], [-1, 0], [1, 0]]; // up, down, left, right
		for (var i = 0; i < directions.length; i++) {
			var newX = centerBlock.gridX + directions[i][0];
			var newY = centerBlock.gridY + directions[i][1];
			if (newX >= 0 && newX < GRID_WIDTH && newY >= 0 && newY < GRID_HEIGHT) {
				var adjacentBlock = grid[newX][newY];
				if (adjacentBlock && adjacentBlock.colorType === self.colorType && !adjacentBlock.isDestroyed) {
					// Check if we already connected this block
					var alreadyConnected = false;
					for (var j = 0; j < self.connectedBlocks.length; j++) {
						if (self.connectedBlocks[j] === adjacentBlock) {
							alreadyConnected = true;
							break;
						}
					}
					if (!alreadyConnected) {
						self.connectedBlocks.push(adjacentBlock);
						adjacentBlock.setSelected(true);
						// Recursively connect blocks adjacent to this one
						self.connectAdjacentBlocks(adjacentBlock);
					}
				}
			}
		}
	};
	self.checkBlockCollision = function () {
		var gridX = Math.floor((self.x - GRID_START_X) / BLOCK_SIZE);
		var gridY = Math.floor((self.y - GRID_START_Y) / BLOCK_SIZE);
		if (gridX >= 0 && gridX < GRID_WIDTH && gridY >= 0 && gridY < GRID_HEIGHT) {
			var hitBlock = grid[gridX][gridY];
			if (hitBlock && hitBlock.colorType === self.colorType && !hitBlock.isDestroyed) {
				// Mark this block as connected by the arrow
				if (!self.connectedBlocks) {
					self.connectedBlocks = [];
				}
				// Check if we already connected this block
				var alreadyConnected = false;
				for (var i = 0; i < self.connectedBlocks.length; i++) {
					if (self.connectedBlocks[i] === hitBlock) {
						alreadyConnected = true;
						break;
					}
				}
				if (!alreadyConnected) {
					self.connectedBlocks.push(hitBlock);
					// Visual feedback for connected block
					hitBlock.setSelected(true);
					// Connect all adjacent blocks of the same color
					self.connectAdjacentBlocks(hitBlock);
					// If we have less than 3 blocks after connecting, set a timeout to destroy arrow
					if (self.connectedBlocks.length < 3) {
						LK.setTimeout(function () {
							if (!self.isDestroyed && !self.hasProcessedBlocks) {
								// Clear selection for connected blocks
								for (var i = 0; i < self.connectedBlocks.length; i++) {
									self.connectedBlocks[i].setSelected(false);
								}
								self.destroyArrow();
							}
						}, 1500); // Give 1.5 seconds to potentially connect more blocks
					}
				}
			}
		}
	};
	self.destroyArrow = function () {
		if (!self.isDestroyed) {
			self.isDestroyed = true;
			self.destroy();
			var index = activeArrows.indexOf(self);
			if (index !== -1) {
				activeArrows.splice(index, 1);
			}
		}
	};
	return self;
});
var Block = Container.expand(function (colorType) {
	var self = Container.call(this);
	self.colorType = colorType;
	self.gridX = 0;
	self.gridY = 0;
	self.isSelected = false;
	self.isDragging = false;
	self.originalX = 0;
	self.originalY = 0;
	self.isDestroyed = false;
	var blockAssets = ['blockRed', 'blockBlue', 'blockGreen', 'blockYellow', 'blockPurple'];
	var blockGraphics = self.attachAsset(blockAssets[colorType], {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.setSelected = function (selected) {
		self.isSelected = selected;
		if (selected) {
			blockGraphics.alpha = 0.8;
			blockGraphics.scaleX = 1.05;
			blockGraphics.scaleY = 1.05;
			tween(blockGraphics, {
				tint: 0xFFFFAA
			}, {
				duration: 200
			});
		} else {
			blockGraphics.alpha = 1.0;
			blockGraphics.scaleX = 1.0;
			blockGraphics.scaleY = 1.0;
			tween(blockGraphics, {
				tint: 0xFFFFFF
			}, {
				duration: 200
			});
		}
	};
	self.blast = function () {
		if (self.isDestroyed) {
			return;
		}
		self.isDestroyed = true;
		// No individual point effect - will be handled by blastSelectedBlocks
		tween(blockGraphics, {
			scaleX: 1.5,
			scaleY: 1.5,
			alpha: 0
		}, {
			duration: 300,
			easing: tween.easeOut,
			onFinish: function onFinish() {
				self.destroy();
			}
		});
	};
	return self;
});
var PointEffect = Container.expand(function (points, x, y) {
	var self = Container.call(this);
	self.x = x;
	self.y = y;
	// Randomly choose between point effect assets
	var effectAssets = ['pointEffect', 'pointEffect2'];
	var randomAsset = effectAssets[Math.floor(Math.random() * effectAssets.length)];
	// Create point effect graphics - bigger for combo effects
	var effectGraphics = self.attachAsset(randomAsset, {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 0.1,
		scaleY: 0.1,
		alpha: 0
	});
	// No text needed - just visual effect
	// Appear with bigger effect for combos
	var maxScale = Math.min(3.0, 1.0 + points / 500);
	tween(effectGraphics, {
		scaleX: maxScale,
		scaleY: maxScale,
		alpha: 1.0
	}, {
		duration: 300,
		easing: tween.bounceOut,
		onFinish: function onFinish() {
			// Move up and fade out
			tween(self, {
				y: self.y - 150
			}, {
				duration: 1000,
				easing: tween.easeOut
			});
			tween(effectGraphics, {
				alpha: 0,
				scaleX: maxScale * 1.5,
				scaleY: maxScale * 1.5
			}, {
				duration: 1000,
				easing: tween.easeOut
			});
			// Destroy effect after animation completes
			LK.setTimeout(function () {
				self.destroy();
			}, 1000);
		}
	});
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x2c3e50
});
/**** 
* Game Code
****/ 
var GRID_WIDTH = 8;
var GRID_HEIGHT = 10;
var BLOCK_SIZE = 200;
var GRID_START_X = (2048 - GRID_WIDTH * BLOCK_SIZE) / 2;
var GRID_START_Y = 400;
var grid = [];
var selectedBlocks = [];
var currentLevel = 1;
var currentScore = 0;
var targetScore = 1000;
var gameActive = true;
var activeArrows = [];
var shootingBlock = null;
// Initialize grid array
for (var x = 0; x < GRID_WIDTH; x++) {
	grid[x] = [];
	for (var y = 0; y < GRID_HEIGHT; y++) {
		grid[x][y] = null;
	}
}
// Add white background - bigger scale to fill more screen
var background = game.attachAsset('background', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0,
	scaleX: 1.2,
	scaleY: 1.2
});
// UI Elements
// Add background shape for score text
var scoreBackground = game.attachAsset('scoreBackground', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 180,
	alpha: 0.8
});
var scoreText = new Text2('Score: 0', {
	size: 80,
	fill: 0x000000
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 1024;
scoreText.y = 180;
game.addChild(scoreText);
// Add background shape for target text
var targetBackground = game.attachAsset('targetBackground', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 280,
	alpha: 0.8
});
var targetText = new Text2('Target: 1000', {
	size: 70,
	fill: 0x0066CC
});
targetText.anchor.set(0.5, 0.5);
targetText.x = 1024;
targetText.y = 280;
game.addChild(targetText);
// Add background shape for level text
var levelBackground = game.attachAsset('levelBackground', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 1024,
	y: 100,
	alpha: 0.8
});
var levelText = new Text2('Level 1', {
	size: 90,
	fill: 0x000000
});
levelText.anchor.set(0.5, 0.5);
levelText.x = 1024;
levelText.y = 100;
game.addChild(levelText);
function createBlock(x, y) {
	var colorType = Math.floor(Math.random() * 5);
	var block = new Block(colorType);
	block.gridX = x;
	block.gridY = y;
	block.x = GRID_START_X + x * BLOCK_SIZE + BLOCK_SIZE / 2;
	block.y = GRID_START_Y + y * BLOCK_SIZE + BLOCK_SIZE / 2;
	grid[x][y] = block;
	game.addChild(block);
	return block;
}
function initializeGrid() {
	for (var x = 0; x < GRID_WIDTH; x++) {
		for (var y = 0; y < GRID_HEIGHT; y++) {
			createBlock(x, y);
		}
	}
}
function getConnectedBlocks(startX, startY, colorType, visited) {
	if (!visited) {
		visited = [];
	}
	var key = startX + ',' + startY;
	if (visited.indexOf(key) !== -1) {
		return [];
	}
	if (startX < 0 || startX >= GRID_WIDTH || startY < 0 || startY >= GRID_HEIGHT) {
		return [];
	}
	if (!grid[startX][startY] || grid[startX][startY].colorType !== colorType) {
		return [];
	}
	visited.push(key);
	var connected = [grid[startX][startY]];
	// Check adjacent blocks (up, down, left, right)
	var directions = [[0, -1], [0, 1], [-1, 0], [1, 0]];
	for (var i = 0; i < directions.length; i++) {
		var newX = startX + directions[i][0];
		var newY = startY + directions[i][1];
		var adjacentBlocks = getConnectedBlocks(newX, newY, colorType, visited);
		connected = connected.concat(adjacentBlocks);
	}
	return connected;
}
function clearSelection() {
	for (var i = 0; i < selectedBlocks.length; i++) {
		selectedBlocks[i].setSelected(false);
	}
	selectedBlocks = [];
}
function selectBlockGroup(block) {
	clearSelection();
	selectedBlocks = getConnectedBlocks(block.gridX, block.gridY, block.colorType);
	if (selectedBlocks.length >= 3) {
		for (var i = 0; i < selectedBlocks.length; i++) {
			selectedBlocks[i].setSelected(true);
		}
		return true;
	} else {
		selectedBlocks = [];
		return false;
	}
}
function blastSelectedBlocks() {
	if (selectedBlocks.length < 3 || !gameActive) {
		return;
	}
	var points = calculateScore(selectedBlocks.length);
	currentScore += points;
	LK.getSound('blockBlast').play();
	LK.effects.flashScreen(0xffffff, 200);
	// Calculate center position of all selected blocks for big effect
	var centerX = 0;
	var centerY = 0;
	for (var i = 0; i < selectedBlocks.length; i++) {
		centerX += selectedBlocks[i].x;
		centerY += selectedBlocks[i].y;
	}
	centerX /= selectedBlocks.length;
	centerY /= selectedBlocks.length;
	// Create single big point effect at center
	var bigPointEffect = new PointEffect(points, centerX, centerY);
	game.addChild(bigPointEffect);
	// Remove blocks from grid and blast them
	for (var i = 0; i < selectedBlocks.length; i++) {
		var block = selectedBlocks[i];
		grid[block.gridX][block.gridY] = null;
		block.blast();
	}
	selectedBlocks = [];
	// Apply gravity after a short delay
	LK.setTimeout(function () {
		applyGravity();
		updateUI();
		checkGameState();
	}, 400);
}
function calculateScore(blockCount) {
	return blockCount * blockCount * 10;
}
function applyGravity() {
	for (var x = 0; x < GRID_WIDTH; x++) {
		var writeY = GRID_HEIGHT - 1;
		// Move existing blocks down
		for (var y = GRID_HEIGHT - 1; y >= 0; y--) {
			if (grid[x][y] !== null) {
				if (writeY !== y) {
					grid[x][writeY] = grid[x][y];
					grid[x][y] = null;
					grid[x][writeY].gridY = writeY;
					// Animate block falling
					var targetY = GRID_START_Y + writeY * BLOCK_SIZE + BLOCK_SIZE / 2;
					tween(grid[x][writeY], {
						y: targetY
					}, {
						duration: 300,
						easing: tween.easeOut
					});
				}
				writeY--;
			}
		}
		// Fill empty spaces at top with new blocks
		for (var y = writeY; y >= 0; y--) {
			var newBlock = createBlock(x, y);
			newBlock.y = GRID_START_Y - (writeY - y + 1) * BLOCK_SIZE + BLOCK_SIZE / 2;
			var targetY = GRID_START_Y + y * BLOCK_SIZE + BLOCK_SIZE / 2;
			tween(newBlock, {
				y: targetY
			}, {
				duration: 500,
				easing: tween.bounceOut
			});
		}
	}
}
function updateUI() {
	scoreText.setText('Score: ' + currentScore);
	LK.setScore(currentScore);
}
function checkGameState() {
	if (currentScore >= targetScore) {
		gameActive = false;
		LK.getSound('levelComplete').play();
		LK.setTimeout(function () {
			nextLevel();
		}, 1000);
	}
}
function nextLevel() {
	currentLevel++;
	targetScore = currentScore + 500 * currentLevel;
	gameActive = true;
	levelText.setText('Level ' + currentLevel);
	targetText.setText('Target: ' + targetScore);
	updateUI();
	if (currentLevel >= 10) {
		LK.showYouWin();
	}
}
game.down = function (x, y, obj) {
	if (!gameActive) {
		return;
	}
	var gridX = Math.floor((x - GRID_START_X) / BLOCK_SIZE);
	var gridY = Math.floor((y - GRID_START_Y) / BLOCK_SIZE);
	if (gridX >= 0 && gridX < GRID_WIDTH && gridY >= 0 && gridY < GRID_HEIGHT) {
		var block = grid[gridX][gridY];
		if (block) {
			shootingBlock = block;
		}
	}
};
game.move = function (x, y, obj) {
	// No dragging mechanics needed for arrow shooting
};
game.up = function (x, y, obj) {
	if (!gameActive || !shootingBlock) {
		return;
	}
	// Shoot arrow in direction of target
	var arrow = new Arrow(shootingBlock.colorType);
	arrow.x = shootingBlock.x;
	arrow.y = shootingBlock.y;
	arrow.setDirection(x, y);
	activeArrows.push(arrow);
	game.addChild(arrow);
	// Arrow is invisible, no spawn animation needed
	// Clear shooting state
	shootingBlock = null;
	clearSelection();
};
game.update = function () {
	// Update all active arrows
	for (var i = activeArrows.length - 1; i >= 0; i--) {
		var arrow = activeArrows[i];
		if (arrow.update) {
			arrow.update();
		}
	}
};
// Initialize the game
initializeGrid();
updateUI();