/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { bestScore: 0, level: 1 }); /**** * Classes ****/ var Card = Container.expand(function (cardId, pairId) { var self = Container.call(this); self.cardId = cardId; self.pairId = pairId; self.isFlipped = false; self.isMatched = false; // Card back (shown when not flipped) var cardBack = self.attachAsset('cardBack', { anchorX: 0.5, anchorY: 0.5 }); // Card front (the actual pattern/color) var cardFront = self.attachAsset('pair' + pairId, { anchorX: 0.5, anchorY: 0.5, visible: false }); self.back = cardBack; self.front = cardFront; // Method to flip the card self.flip = function () { if (self.isMatched || self.isFlipped) { return false; } LK.getSound('flip').play(); self.isFlipped = true; // Animate the flip tween(cardBack, { scaleX: 0 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { cardBack.visible = false; cardFront.visible = true; tween(cardFront, { scaleX: 1 }, { duration: 150, easing: tween.easeOut }); } }); return true; }; // Method to flip back self.flipBack = function () { if (self.isMatched || !self.isFlipped) { return; } self.isFlipped = false; tween(cardFront, { scaleX: 0 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { cardFront.visible = false; cardBack.visible = true; tween(cardBack, { scaleX: 1 }, { duration: 150, easing: tween.easeOut }); } }); }; // Method to mark card as matched self.setMatched = function () { self.isMatched = true; // Create a matched effect var matchEffect = self.attachAsset('cardMatch', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); tween(matchEffect, { alpha: 0.7 }, { duration: 300, easing: tween.easeOut }); }; // Handle card selection self.down = function (x, y, obj) { if (!gameActive || processingMatch || self.isMatched) { return; } var flipped = self.flip(); if (flipped) { checkForMatch(self); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x34495e }); /**** * Game Code ****/ // New pair // New pair // New pair // New pair // New pair // New pair // New pair // New pair // Game state variables var cards = []; var gridWidth = 4; var gridHeight = 3; var cardWidth = 180; var cardHeight = 250; var cardSpacing = 20; var flippedCards = []; var gameActive = false; var processingMatch = false; var moves = 0; var pairsFound = 0; var level = storage.level || 1; var totalPairs = gridWidth * gridHeight / 2; var gameStartTime; // UI Elements var titleText = new Text2('Memory Match Challenge', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); LK.gui.top.addChild(titleText); titleText.y = 50; var movesText = new Text2('Moves: 0', { size: 60, fill: 0xFFFFFF }); movesText.anchor.set(0, 0); LK.gui.topLeft.addChild(movesText); movesText.x = 120; movesText.y = 150; var levelText = new Text2('Level: ' + level, { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(1, 0); LK.gui.topRight.addChild(levelText); levelText.x = -120; levelText.y = 150; var timerText = new Text2('Time: 0s', { size: 60, fill: 0xFFFFFF }); timerText.anchor.set(0.5, 0); LK.gui.top.addChild(timerText); timerText.y = 150; var startBtn = new Container(); var startBtnBg = startBtn.attachAsset('cardBack', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1.2 }); var startBtnText = new Text2('Start Game', { size: 60, fill: 0xFFFFFF }); startBtnText.anchor.set(0.5, 0.5); startBtn.addChild(startBtnText); startBtn.x = 2048 / 2; startBtn.y = 2732 / 2; game.addChild(startBtn); // Timer update var timerInterval; function startTimer() { gameStartTime = Date.now(); timerInterval = LK.setInterval(function () { var elapsed = Math.floor((Date.now() - gameStartTime) / 1000); timerText.setText('Time: ' + elapsed + 's'); }, 1000); } // Initialize the game board function initializeBoard() { // Clear existing cards for (var i = 0; i < cards.length; i++) { cards[i].destroy(); } cards = []; flippedCards = []; pairsFound = 0; moves = 0; processingMatch = false; gameActive = true; movesText.setText('Moves: 0'); // Set level-based grid size if (level === 1) { gridWidth = 4; gridHeight = 3; } else if (level === 2) { gridWidth = 4; gridHeight = 4; } else if (level === 3) { gridWidth = 5; gridHeight = 4; } else if (level === 4) { gridWidth = 6; gridHeight = 4; } else if (level >= 5) { gridWidth = 6; gridHeight = 5; } totalPairs = gridWidth * gridHeight / 2; // Create cards and assign pairs var pairIds = []; for (var p = 0; p < totalPairs; p++) { // Use letters for pair IDs (A, B, C, etc.) var pairLetter = String.fromCharCode(65 + p % 8); pairIds.push(pairLetter); pairIds.push(pairLetter); } // Shuffle pairs for (var s = pairIds.length - 1; s > 0; s--) { var j = Math.floor(Math.random() * (s + 1)); var temp = pairIds[s]; pairIds[s] = pairIds[j]; pairIds[j] = temp; } // Determine the grid layout positioning var gridTotalWidth = gridWidth * cardWidth + (gridWidth - 1) * cardSpacing; var gridTotalHeight = gridHeight * cardHeight + (gridHeight - 1) * cardSpacing; var startX = (2048 - gridTotalWidth) / 2; var startY = (2732 - gridTotalHeight) / 2; // Create and position the cards var cardIndex = 0; for (var row = 0; row < gridHeight; row++) { for (var col = 0; col < gridWidth; col++) { var x = startX + col * (cardWidth + cardSpacing) + cardWidth / 2; var y = startY + row * (cardHeight + cardSpacing) + cardHeight / 2; var card = new Card(cardIndex, pairIds[cardIndex]); card.x = x; card.y = y; cards.push(card); game.addChild(card); cardIndex++; } } // Start the timer startTimer(); // Play background music LK.playMusic('bgmusic'); } // Check for matching cards function checkForMatch(card) { flippedCards.push(card); if (flippedCards.length === 2) { processingMatch = true; moves++; movesText.setText('Moves: ' + moves); var card1 = flippedCards[0]; var card2 = flippedCards[1]; if (card1.pairId === card2.pairId) { // Match found LK.setTimeout(function () { LK.getSound('match').play(); card1.setMatched(); card2.setMatched(); flippedCards = []; processingMatch = false; // Increment pairs found pairsFound++; // Check for win condition if (pairsFound === totalPairs) { gameWon(); } }, 500); } else { // No match LK.setTimeout(function () { LK.getSound('nomatch').play(); card1.flipBack(); card2.flipBack(); flippedCards = []; processingMatch = false; }, 1000); } } } // Handle game win function gameWon() { gameActive = false; // Calculate score based on moves and time var timeElapsed = Math.floor((Date.now() - gameStartTime) / 1000); LK.clearInterval(timerInterval); // Calculate score (fewer moves and less time = higher score) var baseScore = 1000; var movePenalty = moves * 10; var timePenalty = timeElapsed * 2; var score = Math.max(100, baseScore - movePenalty - timePenalty); // Update best score if (score > storage.bestScore) { storage.bestScore = score; } // Set the score LK.setScore(score); // Play win sound LK.getSound('win').play(); // Show win message LK.setTimeout(function () { // Level up level++; storage.level = level; // Show you win screen LK.showYouWin(); }, 1500); } // Start button interaction startBtn.down = function (x, y, obj) { game.removeChild(startBtn); initializeBoard(); }; // Handle game update game.update = function () { // Nothing needed here as the game logic is event-driven };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
bestScore: 0,
level: 1
});
/****
* Classes
****/
var Card = Container.expand(function (cardId, pairId) {
var self = Container.call(this);
self.cardId = cardId;
self.pairId = pairId;
self.isFlipped = false;
self.isMatched = false;
// Card back (shown when not flipped)
var cardBack = self.attachAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5
});
// Card front (the actual pattern/color)
var cardFront = self.attachAsset('pair' + pairId, {
anchorX: 0.5,
anchorY: 0.5,
visible: false
});
self.back = cardBack;
self.front = cardFront;
// Method to flip the card
self.flip = function () {
if (self.isMatched || self.isFlipped) {
return false;
}
LK.getSound('flip').play();
self.isFlipped = true;
// Animate the flip
tween(cardBack, {
scaleX: 0
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
cardBack.visible = false;
cardFront.visible = true;
tween(cardFront, {
scaleX: 1
}, {
duration: 150,
easing: tween.easeOut
});
}
});
return true;
};
// Method to flip back
self.flipBack = function () {
if (self.isMatched || !self.isFlipped) {
return;
}
self.isFlipped = false;
tween(cardFront, {
scaleX: 0
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
cardFront.visible = false;
cardBack.visible = true;
tween(cardBack, {
scaleX: 1
}, {
duration: 150,
easing: tween.easeOut
});
}
});
};
// Method to mark card as matched
self.setMatched = function () {
self.isMatched = true;
// Create a matched effect
var matchEffect = self.attachAsset('cardMatch', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
tween(matchEffect, {
alpha: 0.7
}, {
duration: 300,
easing: tween.easeOut
});
};
// Handle card selection
self.down = function (x, y, obj) {
if (!gameActive || processingMatch || self.isMatched) {
return;
}
var flipped = self.flip();
if (flipped) {
checkForMatch(self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
// New pair
// New pair
// New pair
// New pair
// New pair
// New pair
// New pair
// New pair
// Game state variables
var cards = [];
var gridWidth = 4;
var gridHeight = 3;
var cardWidth = 180;
var cardHeight = 250;
var cardSpacing = 20;
var flippedCards = [];
var gameActive = false;
var processingMatch = false;
var moves = 0;
var pairsFound = 0;
var level = storage.level || 1;
var totalPairs = gridWidth * gridHeight / 2;
var gameStartTime;
// UI Elements
var titleText = new Text2('Memory Match Challenge', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
titleText.y = 50;
var movesText = new Text2('Moves: 0', {
size: 60,
fill: 0xFFFFFF
});
movesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(movesText);
movesText.x = 120;
movesText.y = 150;
var levelText = new Text2('Level: ' + level, {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(1, 0);
LK.gui.topRight.addChild(levelText);
levelText.x = -120;
levelText.y = 150;
var timerText = new Text2('Time: 0s', {
size: 60,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
timerText.y = 150;
var startBtn = new Container();
var startBtnBg = startBtn.attachAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1.2
});
var startBtnText = new Text2('Start Game', {
size: 60,
fill: 0xFFFFFF
});
startBtnText.anchor.set(0.5, 0.5);
startBtn.addChild(startBtnText);
startBtn.x = 2048 / 2;
startBtn.y = 2732 / 2;
game.addChild(startBtn);
// Timer update
var timerInterval;
function startTimer() {
gameStartTime = Date.now();
timerInterval = LK.setInterval(function () {
var elapsed = Math.floor((Date.now() - gameStartTime) / 1000);
timerText.setText('Time: ' + elapsed + 's');
}, 1000);
}
// Initialize the game board
function initializeBoard() {
// Clear existing cards
for (var i = 0; i < cards.length; i++) {
cards[i].destroy();
}
cards = [];
flippedCards = [];
pairsFound = 0;
moves = 0;
processingMatch = false;
gameActive = true;
movesText.setText('Moves: 0');
// Set level-based grid size
if (level === 1) {
gridWidth = 4;
gridHeight = 3;
} else if (level === 2) {
gridWidth = 4;
gridHeight = 4;
} else if (level === 3) {
gridWidth = 5;
gridHeight = 4;
} else if (level === 4) {
gridWidth = 6;
gridHeight = 4;
} else if (level >= 5) {
gridWidth = 6;
gridHeight = 5;
}
totalPairs = gridWidth * gridHeight / 2;
// Create cards and assign pairs
var pairIds = [];
for (var p = 0; p < totalPairs; p++) {
// Use letters for pair IDs (A, B, C, etc.)
var pairLetter = String.fromCharCode(65 + p % 8);
pairIds.push(pairLetter);
pairIds.push(pairLetter);
}
// Shuffle pairs
for (var s = pairIds.length - 1; s > 0; s--) {
var j = Math.floor(Math.random() * (s + 1));
var temp = pairIds[s];
pairIds[s] = pairIds[j];
pairIds[j] = temp;
}
// Determine the grid layout positioning
var gridTotalWidth = gridWidth * cardWidth + (gridWidth - 1) * cardSpacing;
var gridTotalHeight = gridHeight * cardHeight + (gridHeight - 1) * cardSpacing;
var startX = (2048 - gridTotalWidth) / 2;
var startY = (2732 - gridTotalHeight) / 2;
// Create and position the cards
var cardIndex = 0;
for (var row = 0; row < gridHeight; row++) {
for (var col = 0; col < gridWidth; col++) {
var x = startX + col * (cardWidth + cardSpacing) + cardWidth / 2;
var y = startY + row * (cardHeight + cardSpacing) + cardHeight / 2;
var card = new Card(cardIndex, pairIds[cardIndex]);
card.x = x;
card.y = y;
cards.push(card);
game.addChild(card);
cardIndex++;
}
}
// Start the timer
startTimer();
// Play background music
LK.playMusic('bgmusic');
}
// Check for matching cards
function checkForMatch(card) {
flippedCards.push(card);
if (flippedCards.length === 2) {
processingMatch = true;
moves++;
movesText.setText('Moves: ' + moves);
var card1 = flippedCards[0];
var card2 = flippedCards[1];
if (card1.pairId === card2.pairId) {
// Match found
LK.setTimeout(function () {
LK.getSound('match').play();
card1.setMatched();
card2.setMatched();
flippedCards = [];
processingMatch = false;
// Increment pairs found
pairsFound++;
// Check for win condition
if (pairsFound === totalPairs) {
gameWon();
}
}, 500);
} else {
// No match
LK.setTimeout(function () {
LK.getSound('nomatch').play();
card1.flipBack();
card2.flipBack();
flippedCards = [];
processingMatch = false;
}, 1000);
}
}
}
// Handle game win
function gameWon() {
gameActive = false;
// Calculate score based on moves and time
var timeElapsed = Math.floor((Date.now() - gameStartTime) / 1000);
LK.clearInterval(timerInterval);
// Calculate score (fewer moves and less time = higher score)
var baseScore = 1000;
var movePenalty = moves * 10;
var timePenalty = timeElapsed * 2;
var score = Math.max(100, baseScore - movePenalty - timePenalty);
// Update best score
if (score > storage.bestScore) {
storage.bestScore = score;
}
// Set the score
LK.setScore(score);
// Play win sound
LK.getSound('win').play();
// Show win message
LK.setTimeout(function () {
// Level up
level++;
storage.level = level;
// Show you win screen
LK.showYouWin();
}, 1500);
}
// Start button interaction
startBtn.down = function (x, y, obj) {
game.removeChild(startBtn);
initializeBoard();
};
// Handle game update
game.update = function () {
// Nothing needed here as the game logic is event-driven
};