/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScore: 0,
	currentLevel: 1
});
/**** 
* Classes
****/ 
var Card = Container.expand(function (cardValue) {
	var self = Container.call(this);
	// The card's value (which determines its matching pair)
	self.cardValue = cardValue;
	// Card state
	self.isFlipped = false;
	self.isMatched = false;
	// Create card back (visible when card is face down)
	var back = self.attachAsset('cardBack', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Create card front (visible when card is face up)
	var front = self.attachAsset('cardFront', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false
	});
	// Create card symbol (identifies the card)
	var symbol = self.attachAsset('cardMatch' + (cardValue % 10 + 1), {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false
	});
	// Center the symbol on the card
	symbol.x = 0;
	symbol.y = 0;
	// Method to flip card face up
	self.flipUp = function () {
		if (self.isFlipped || self.isMatched) {
			return false;
		}
		LK.getSound('flip').play();
		self.isFlipped = true;
		// Hide back, show front and symbol
		tween(back, {
			scaleX: 0
		}, {
			duration: 150,
			onFinish: function onFinish() {
				back.visible = false;
				front.visible = true;
				symbol.visible = true;
				tween(front, {
					scaleX: 1
				}, {
					duration: 150
				});
				tween(symbol, {
					scaleX: 1
				}, {
					duration: 150
				});
			}
		});
		return true;
	};
	// Method to flip card face down
	self.flipDown = function () {
		if (!self.isFlipped || self.isMatched) {
			return;
		}
		self.isFlipped = false;
		// Hide front and symbol, show back
		tween(front, {
			scaleX: 0
		}, {
			duration: 150,
			onFinish: function onFinish() {
				front.visible = false;
				symbol.visible = false;
				back.visible = true;
				tween(back, {
					scaleX: 1
				}, {
					duration: 150
				});
			}
		});
	};
	// Method to mark card as matched
	self.setMatched = function () {
		self.isMatched = true;
		tween(self, {
			alpha: 0.7
		}, {
			duration: 300
		});
	};
	// Event handler for card click/tap
	self.down = function (x, y, obj) {
		if (!gameActive || self.isMatched || self.isFlipped) {
			return;
		}
		var flipped = self.flipUp();
		if (flipped) {
			cardsFlipped.push(self);
			checkForMatch();
		}
	};
	// Pre-scale the back to ensure proper initial state
	front.scaleX = 0;
	symbol.scaleX = 0;
	return self;
});
var Timer = Container.expand(function (duration) {
	var self = Container.call(this);
	self.duration = duration || 60000; // Default 60 seconds
	self.timeRemaining = self.duration;
	self.isRunning = false;
	// Create timer background
	var background = self.attachAsset('timerBarBg', {
		anchorX: 0,
		anchorY: 0.5
	});
	// Create timer bar that will shrink
	var bar = self.attachAsset('timerBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	// Method to start the timer
	self.start = function () {
		self.timeRemaining = self.duration;
		self.isRunning = true;
		self.updateDisplay();
	};
	// Method to stop the timer
	self.stop = function () {
		self.isRunning = false;
	};
	// Method to reset the timer
	self.reset = function (newDuration) {
		if (newDuration) {
			self.duration = newDuration;
		}
		self.timeRemaining = self.duration;
		self.updateDisplay();
	};
	// Update timer display based on time remaining
	self.updateDisplay = function () {
		var percentRemaining = self.timeRemaining / self.duration;
		bar.scale.x = Math.max(0, percentRemaining);
	};
	// Method to update timer each frame
	self.update = function () {
		if (!self.isRunning) {
			return;
		}
		self.timeRemaining -= 16.67; // Approximate ms per frame at 60fps
		if (self.timeRemaining <= 0) {
			self.timeRemaining = 0;
			self.isRunning = false;
			if (gameActive) {
				gameActive = false;
				LK.showGameOver();
			}
		}
		self.updateDisplay();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x34495e
});
/**** 
* Game Code
****/ 
// Game state variables
var gameActive = false;
var cards = [];
var cardsFlipped = [];
var pairsFound = 0;
var totalPairs = 0;
var currentLevel = storage.currentLevel || 1;
var score = 0;
var moves = 0;
var gridSize = 4; // Initial grid size (4x4)
var previewTime = 3000; // Initial preview time in ms
// UI elements
var timer;
var scoreTxt;
var levelTxt;
var movesTxt;
// Initialize the game
function initGame() {
	// Play background music
	LK.playMusic('gameMusic');
	// Set up UI elements
	setupUI();
	// Determine level settings
	calculateLevelSettings();
	// Create card grid
	createCardGrid();
	// Start the level with preview phase
	startLevel();
}
// Set up UI elements
function setupUI() {
	// Create timer
	timer = new Timer(60000); // 60 seconds
	timer.x = 2048 / 2 - 900; // Center timer horizontally
	timer.y = 100;
	game.addChild(timer);
	// Create score text
	scoreTxt = new Text2('Score: 0', {
		size: 60,
		fill: 0xFFFFFF
	});
	scoreTxt.anchor.set(1, 0);
	LK.gui.topRight.addChild(scoreTxt);
	// Create level text
	levelTxt = new Text2('Level: ' + currentLevel, {
		size: 60,
		fill: 0xFFFFFF
	});
	levelTxt.anchor.set(0, 0);
	LK.gui.topRight.addChild(levelTxt);
	levelTxt.y = 70;
	// Create moves text
	movesTxt = new Text2('Moves: 0', {
		size: 60,
		fill: 0xFFFFFF
	});
	movesTxt.anchor.set(0, 0);
	LK.gui.topRight.addChild(movesTxt);
	movesTxt.y = 140;
}
// Calculate settings based on current level
function calculateLevelSettings() {
	// Increase grid size every 3 levels
	if (currentLevel <= 3) {
		gridSize = 4; // 4x4 grid (16 cards, 8 pairs)
	} else if (currentLevel <= 6) {
		gridSize = 6; // 6x6 grid (36 cards, 18 pairs)
	} else {
		gridSize = 8; // 8x8 grid (64 cards, 32 pairs)
	}
	// Decrease preview time as levels increase
	previewTime = Math.max(1000, 3000 - (currentLevel - 1) * 300);
	// Adjust timer based on grid size
	var timerDuration = 30000 + gridSize * gridSize * 500;
	timer.reset(timerDuration);
	// Reset moves counter
	moves = 0;
	updateMovesText();
}
// Create the grid of cards for the current level
function createCardGrid() {
	// Clear any existing cards
	for (var i = 0; i < cards.length; i++) {
		if (cards[i].parent) {
			cards[i].parent.removeChild(cards[i]);
		}
	}
	cards = [];
	cardsFlipped = [];
	pairsFound = 0;
	// Calculate total pairs based on grid size
	totalPairs = gridSize * gridSize / 2;
	// Create array of card values (pairs)
	var cardValues = [];
	for (var i = 0; i < totalPairs; i++) {
		cardValues.push(i);
		cardValues.push(i);
	}
	// Shuffle the card values
	shuffleArray(cardValues);
	// Calculate card size and spacing based on grid size
	var cardSpacing = 20;
	var cardWidth = 200;
	var cardHeight = 280;
	// Calculate total grid width and height
	var gridWidth = gridSize * cardWidth + (gridSize - 1) * cardSpacing;
	var gridHeight = gridSize * cardHeight + (gridSize - 1) * cardSpacing;
	// Starting position for the grid (centered on screen)
	var startX = (2048 - gridWidth) / 2 + cardWidth / 2;
	var startY = (2732 - gridHeight) / 2 + cardHeight / 2;
	// Create and position cards
	var index = 0;
	for (var row = 0; row < gridSize; row++) {
		for (var col = 0; col < gridSize; col++) {
			// Ensure we don't try to create more cards than we have values
			if (index < cardValues.length) {
				var card = new Card(cardValues[index]);
				card.x = startX + col * (cardWidth + cardSpacing);
				card.y = startY + row * (cardHeight + cardSpacing);
				game.addChild(card);
				cards.push(card);
				index++;
			}
		}
	}
}
// Start a new level
function startLevel() {
	// Reset state
	cardsFlipped = [];
	pairsFound = 0;
	// Update level text
	levelTxt.setText('Level: ' + currentLevel);
	// Preview phase - show all cards briefly
	for (var i = 0; i < cards.length; i++) {
		cards[i].flipUp();
	}
	// After preview, flip all cards face down and start gameplay
	LK.setTimeout(function () {
		for (var i = 0; i < cards.length; i++) {
			cards[i].flipDown();
		}
		// Start the timer
		timer.start();
		// Activate gameplay
		gameActive = true;
	}, previewTime);
}
// Check if the two flipped cards match
function checkForMatch() {
	if (cardsFlipped.length !== 2) {
		return;
	}
	// Increment moves
	moves++;
	updateMovesText();
	// Get the two flipped cards
	var card1 = cardsFlipped[0];
	var card2 = cardsFlipped[1];
	// Disable further interactions temporarily
	gameActive = false;
	// Check if cards match
	if (card1.cardValue === card2.cardValue) {
		// Cards match!
		LK.getSound('match').play();
		// Mark both cards as matched
		card1.setMatched();
		card2.setMatched();
		// Increment pairs found
		pairsFound++;
		// Add score
		score += 100 + Math.floor(timer.timeRemaining / 100);
		updateScoreText();
		// Check if level is complete
		if (pairsFound >= totalPairs) {
			levelComplete();
		} else {
			// Re-enable gameplay for next move
			cardsFlipped = [];
			gameActive = true;
		}
	} else {
		// Cards don't match, flip them back
		LK.getSound('noMatch').play();
		LK.setTimeout(function () {
			card1.flipDown();
			card2.flipDown();
			cardsFlipped = [];
			gameActive = true;
		}, 1000);
	}
}
// Handle level completion
function levelComplete() {
	// Stop the timer
	timer.stop();
	// Play level complete sound
	LK.getSound('levelComplete').play();
	// Add time bonus
	var timeBonus = Math.floor(timer.timeRemaining / 10);
	score += timeBonus;
	updateScoreText();
	// Update high score if needed
	if (score > storage.highScore) {
		storage.highScore = score;
	}
	// Increment level
	currentLevel++;
	storage.currentLevel = currentLevel;
	// Show you win screen or proceed to next level
	LK.setTimeout(function () {
		if (currentLevel > 10) {
			// Player completed all levels
			LK.showYouWin();
		} else {
			// Set up next level
			calculateLevelSettings();
			createCardGrid();
			startLevel();
		}
	}, 1500);
}
// Update the score text
function updateScoreText() {
	scoreTxt.setText('Score: ' + score);
}
// Update the moves text
function updateMovesText() {
	movesTxt.setText('Moves: ' + moves);
}
// Utility function to shuffle an array
function shuffleArray(array) {
	for (var i = array.length - 1; i > 0; i--) {
		var j = Math.floor(Math.random() * (i + 1));
		var temp = array[i];
		array[i] = array[j];
		array[j] = temp;
	}
	return array;
}
// Game update function
game.update = function () {
	// Update timer if it exists
	if (timer) {
		timer.update();
	}
};
// Initialize game when loaded
initGame(); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScore: 0,
	currentLevel: 1
});
/**** 
* Classes
****/ 
var Card = Container.expand(function (cardValue) {
	var self = Container.call(this);
	// The card's value (which determines its matching pair)
	self.cardValue = cardValue;
	// Card state
	self.isFlipped = false;
	self.isMatched = false;
	// Create card back (visible when card is face down)
	var back = self.attachAsset('cardBack', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	// Create card front (visible when card is face up)
	var front = self.attachAsset('cardFront', {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false
	});
	// Create card symbol (identifies the card)
	var symbol = self.attachAsset('cardMatch' + (cardValue % 10 + 1), {
		anchorX: 0.5,
		anchorY: 0.5,
		visible: false
	});
	// Center the symbol on the card
	symbol.x = 0;
	symbol.y = 0;
	// Method to flip card face up
	self.flipUp = function () {
		if (self.isFlipped || self.isMatched) {
			return false;
		}
		LK.getSound('flip').play();
		self.isFlipped = true;
		// Hide back, show front and symbol
		tween(back, {
			scaleX: 0
		}, {
			duration: 150,
			onFinish: function onFinish() {
				back.visible = false;
				front.visible = true;
				symbol.visible = true;
				tween(front, {
					scaleX: 1
				}, {
					duration: 150
				});
				tween(symbol, {
					scaleX: 1
				}, {
					duration: 150
				});
			}
		});
		return true;
	};
	// Method to flip card face down
	self.flipDown = function () {
		if (!self.isFlipped || self.isMatched) {
			return;
		}
		self.isFlipped = false;
		// Hide front and symbol, show back
		tween(front, {
			scaleX: 0
		}, {
			duration: 150,
			onFinish: function onFinish() {
				front.visible = false;
				symbol.visible = false;
				back.visible = true;
				tween(back, {
					scaleX: 1
				}, {
					duration: 150
				});
			}
		});
	};
	// Method to mark card as matched
	self.setMatched = function () {
		self.isMatched = true;
		tween(self, {
			alpha: 0.7
		}, {
			duration: 300
		});
	};
	// Event handler for card click/tap
	self.down = function (x, y, obj) {
		if (!gameActive || self.isMatched || self.isFlipped) {
			return;
		}
		var flipped = self.flipUp();
		if (flipped) {
			cardsFlipped.push(self);
			checkForMatch();
		}
	};
	// Pre-scale the back to ensure proper initial state
	front.scaleX = 0;
	symbol.scaleX = 0;
	return self;
});
var Timer = Container.expand(function (duration) {
	var self = Container.call(this);
	self.duration = duration || 60000; // Default 60 seconds
	self.timeRemaining = self.duration;
	self.isRunning = false;
	// Create timer background
	var background = self.attachAsset('timerBarBg', {
		anchorX: 0,
		anchorY: 0.5
	});
	// Create timer bar that will shrink
	var bar = self.attachAsset('timerBar', {
		anchorX: 0,
		anchorY: 0.5
	});
	// Method to start the timer
	self.start = function () {
		self.timeRemaining = self.duration;
		self.isRunning = true;
		self.updateDisplay();
	};
	// Method to stop the timer
	self.stop = function () {
		self.isRunning = false;
	};
	// Method to reset the timer
	self.reset = function (newDuration) {
		if (newDuration) {
			self.duration = newDuration;
		}
		self.timeRemaining = self.duration;
		self.updateDisplay();
	};
	// Update timer display based on time remaining
	self.updateDisplay = function () {
		var percentRemaining = self.timeRemaining / self.duration;
		bar.scale.x = Math.max(0, percentRemaining);
	};
	// Method to update timer each frame
	self.update = function () {
		if (!self.isRunning) {
			return;
		}
		self.timeRemaining -= 16.67; // Approximate ms per frame at 60fps
		if (self.timeRemaining <= 0) {
			self.timeRemaining = 0;
			self.isRunning = false;
			if (gameActive) {
				gameActive = false;
				LK.showGameOver();
			}
		}
		self.updateDisplay();
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x34495e
});
/**** 
* Game Code
****/ 
// Game state variables
var gameActive = false;
var cards = [];
var cardsFlipped = [];
var pairsFound = 0;
var totalPairs = 0;
var currentLevel = storage.currentLevel || 1;
var score = 0;
var moves = 0;
var gridSize = 4; // Initial grid size (4x4)
var previewTime = 3000; // Initial preview time in ms
// UI elements
var timer;
var scoreTxt;
var levelTxt;
var movesTxt;
// Initialize the game
function initGame() {
	// Play background music
	LK.playMusic('gameMusic');
	// Set up UI elements
	setupUI();
	// Determine level settings
	calculateLevelSettings();
	// Create card grid
	createCardGrid();
	// Start the level with preview phase
	startLevel();
}
// Set up UI elements
function setupUI() {
	// Create timer
	timer = new Timer(60000); // 60 seconds
	timer.x = 2048 / 2 - 900; // Center timer horizontally
	timer.y = 100;
	game.addChild(timer);
	// Create score text
	scoreTxt = new Text2('Score: 0', {
		size: 60,
		fill: 0xFFFFFF
	});
	scoreTxt.anchor.set(1, 0);
	LK.gui.topRight.addChild(scoreTxt);
	// Create level text
	levelTxt = new Text2('Level: ' + currentLevel, {
		size: 60,
		fill: 0xFFFFFF
	});
	levelTxt.anchor.set(0, 0);
	LK.gui.topRight.addChild(levelTxt);
	levelTxt.y = 70;
	// Create moves text
	movesTxt = new Text2('Moves: 0', {
		size: 60,
		fill: 0xFFFFFF
	});
	movesTxt.anchor.set(0, 0);
	LK.gui.topRight.addChild(movesTxt);
	movesTxt.y = 140;
}
// Calculate settings based on current level
function calculateLevelSettings() {
	// Increase grid size every 3 levels
	if (currentLevel <= 3) {
		gridSize = 4; // 4x4 grid (16 cards, 8 pairs)
	} else if (currentLevel <= 6) {
		gridSize = 6; // 6x6 grid (36 cards, 18 pairs)
	} else {
		gridSize = 8; // 8x8 grid (64 cards, 32 pairs)
	}
	// Decrease preview time as levels increase
	previewTime = Math.max(1000, 3000 - (currentLevel - 1) * 300);
	// Adjust timer based on grid size
	var timerDuration = 30000 + gridSize * gridSize * 500;
	timer.reset(timerDuration);
	// Reset moves counter
	moves = 0;
	updateMovesText();
}
// Create the grid of cards for the current level
function createCardGrid() {
	// Clear any existing cards
	for (var i = 0; i < cards.length; i++) {
		if (cards[i].parent) {
			cards[i].parent.removeChild(cards[i]);
		}
	}
	cards = [];
	cardsFlipped = [];
	pairsFound = 0;
	// Calculate total pairs based on grid size
	totalPairs = gridSize * gridSize / 2;
	// Create array of card values (pairs)
	var cardValues = [];
	for (var i = 0; i < totalPairs; i++) {
		cardValues.push(i);
		cardValues.push(i);
	}
	// Shuffle the card values
	shuffleArray(cardValues);
	// Calculate card size and spacing based on grid size
	var cardSpacing = 20;
	var cardWidth = 200;
	var cardHeight = 280;
	// Calculate total grid width and height
	var gridWidth = gridSize * cardWidth + (gridSize - 1) * cardSpacing;
	var gridHeight = gridSize * cardHeight + (gridSize - 1) * cardSpacing;
	// Starting position for the grid (centered on screen)
	var startX = (2048 - gridWidth) / 2 + cardWidth / 2;
	var startY = (2732 - gridHeight) / 2 + cardHeight / 2;
	// Create and position cards
	var index = 0;
	for (var row = 0; row < gridSize; row++) {
		for (var col = 0; col < gridSize; col++) {
			// Ensure we don't try to create more cards than we have values
			if (index < cardValues.length) {
				var card = new Card(cardValues[index]);
				card.x = startX + col * (cardWidth + cardSpacing);
				card.y = startY + row * (cardHeight + cardSpacing);
				game.addChild(card);
				cards.push(card);
				index++;
			}
		}
	}
}
// Start a new level
function startLevel() {
	// Reset state
	cardsFlipped = [];
	pairsFound = 0;
	// Update level text
	levelTxt.setText('Level: ' + currentLevel);
	// Preview phase - show all cards briefly
	for (var i = 0; i < cards.length; i++) {
		cards[i].flipUp();
	}
	// After preview, flip all cards face down and start gameplay
	LK.setTimeout(function () {
		for (var i = 0; i < cards.length; i++) {
			cards[i].flipDown();
		}
		// Start the timer
		timer.start();
		// Activate gameplay
		gameActive = true;
	}, previewTime);
}
// Check if the two flipped cards match
function checkForMatch() {
	if (cardsFlipped.length !== 2) {
		return;
	}
	// Increment moves
	moves++;
	updateMovesText();
	// Get the two flipped cards
	var card1 = cardsFlipped[0];
	var card2 = cardsFlipped[1];
	// Disable further interactions temporarily
	gameActive = false;
	// Check if cards match
	if (card1.cardValue === card2.cardValue) {
		// Cards match!
		LK.getSound('match').play();
		// Mark both cards as matched
		card1.setMatched();
		card2.setMatched();
		// Increment pairs found
		pairsFound++;
		// Add score
		score += 100 + Math.floor(timer.timeRemaining / 100);
		updateScoreText();
		// Check if level is complete
		if (pairsFound >= totalPairs) {
			levelComplete();
		} else {
			// Re-enable gameplay for next move
			cardsFlipped = [];
			gameActive = true;
		}
	} else {
		// Cards don't match, flip them back
		LK.getSound('noMatch').play();
		LK.setTimeout(function () {
			card1.flipDown();
			card2.flipDown();
			cardsFlipped = [];
			gameActive = true;
		}, 1000);
	}
}
// Handle level completion
function levelComplete() {
	// Stop the timer
	timer.stop();
	// Play level complete sound
	LK.getSound('levelComplete').play();
	// Add time bonus
	var timeBonus = Math.floor(timer.timeRemaining / 10);
	score += timeBonus;
	updateScoreText();
	// Update high score if needed
	if (score > storage.highScore) {
		storage.highScore = score;
	}
	// Increment level
	currentLevel++;
	storage.currentLevel = currentLevel;
	// Show you win screen or proceed to next level
	LK.setTimeout(function () {
		if (currentLevel > 10) {
			// Player completed all levels
			LK.showYouWin();
		} else {
			// Set up next level
			calculateLevelSettings();
			createCardGrid();
			startLevel();
		}
	}, 1500);
}
// Update the score text
function updateScoreText() {
	scoreTxt.setText('Score: ' + score);
}
// Update the moves text
function updateMovesText() {
	movesTxt.setText('Moves: ' + moves);
}
// Utility function to shuffle an array
function shuffleArray(array) {
	for (var i = array.length - 1; i > 0; i--) {
		var j = Math.floor(Math.random() * (i + 1));
		var temp = array[i];
		array[i] = array[j];
		array[j] = temp;
	}
	return array;
}
// Game update function
game.update = function () {
	// Update timer if it exists
	if (timer) {
		timer.update();
	}
};
// Initialize game when loaded
initGame();
:quality(85)/https://cdn.frvr.ai/67e1284877774dc7dfcee84b.png%3F3) 
 mg. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e1287777774dc7dfcee855.png%3F3) 
 cardfront mg. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e1291d77774dc7dfcee863.png%3F3) 
 mg. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
:quality(85)/https://cdn.frvr.ai/67e1298977774dc7dfcee86e.png%3F3) 
 cardback mg. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows