/**** * 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(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: 0x9370DB }); /**** * Game Code ****/ // Game state variables var cards = []; var gridWidth = 4; var gridHeight = 3; var cardWidth = 180; var cardHeight = 250; var cardSpacing = 200; // Increased vertical spacing between cards var flippedCards = []; var gameActive = false; var processingMatch = false; var moves = 0; var pairsFound = 0; var level = 1; var totalPairs = gridWidth * gridHeight / 2; var gameStartTime; // UI Elements var titleText = new Text2("Crypto Match Game", { size: 80, fill: 0xFFA500, fontWeight: 'bolder' }); 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 levelSelectBtn = new Container(); var levelSelectBtnBg = levelSelectBtn.attachAsset('startButton', { anchorX: 0.5, anchorY: 0.5 }); var levelSelectBtnText = new Text2('Select Level', { size: 60, fill: 0xFFFFFF }); levelSelectBtnText.anchor.set(0.5, 0.5); levelSelectBtn.addChild(levelSelectBtnText); levelSelectBtn.x = 2048 / 2; levelSelectBtn.y = 2732 / 2 + 250; game.addChild(levelSelectBtn); var startBtn = new Container(); var startBtnBg = startBtn.attachAsset('startButton', { anchorX: 0.5, anchorY: 0.5 }); 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 = 4; gridHeight = 4; } else if (level === 4) { gridWidth = 5; gridHeight = 4; } else if (level >= 5) { gridWidth = 5; gridHeight = 4; if (level === 5) { gridWidth = 5; gridHeight = 4; } } 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 = 'pair' + String.fromCharCode(65 + p % Math.min(totalPairs, 15)); 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 + (level >= 5 ? 100 : 0); // 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 && flippedCards.length === 0) { 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; levelText.setText('Level: ' + level); // Automatically start the next level initializeBoard(); }, 1500); } // Start button interaction startBtn.down = function (x, y, obj) { game.removeChild(startBtn); game.removeChild(levelSelectBtn); initializeBoard(); }; // Level select button interaction levelSelectBtn.down = function (x, y, obj) { game.removeChild(startBtn); game.removeChild(levelSelectBtn); showLevelSelection(); }; function showLevelSelection() { var levelOptions = []; for (var i = 1; i <= 5; i++) { (function (levelNum) { var levelOption = new Text2('Level ' + levelNum, { size: 70, // Increased size for emphasis fill: 0xFFD700, // Gold color for standout effect fontWeight: 'bolder', // Make text bolder shadow: { blur: 15, // Increased blur for more pronounced shadow color: 0x000000, offsetX: 7, // Slightly larger offset for shadow offsetY: 7 } // Add shadow for depth }); levelOption.anchor.set(0.5, 0.5); levelOption.x = 2048 / 2; levelOption.y = 2732 / 2 - 200 + levelNum * 100; levelOption.down = function () { level = levelNum; storage.level = level; levelText.setText('Level: ' + level); initializeBoard(); for (var j = 0; j < levelOptions.length; j++) { game.removeChild(levelOptions[j]); } }; // Add hover effect levelOption.over = function () { tween(levelOption, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, easing: tween.easeOut }); }; levelOption.out = function () { tween(levelOption, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.easeIn }); }; game.addChild(levelOption); levelOptions.push(levelOption); })(i); } } // 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(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: 0x9370DB
});
/****
* Game Code
****/
// Game state variables
var cards = [];
var gridWidth = 4;
var gridHeight = 3;
var cardWidth = 180;
var cardHeight = 250;
var cardSpacing = 200; // Increased vertical spacing between cards
var flippedCards = [];
var gameActive = false;
var processingMatch = false;
var moves = 0;
var pairsFound = 0;
var level = 1;
var totalPairs = gridWidth * gridHeight / 2;
var gameStartTime;
// UI Elements
var titleText = new Text2("Crypto Match Game", {
size: 80,
fill: 0xFFA500,
fontWeight: 'bolder'
});
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 levelSelectBtn = new Container();
var levelSelectBtnBg = levelSelectBtn.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5
});
var levelSelectBtnText = new Text2('Select Level', {
size: 60,
fill: 0xFFFFFF
});
levelSelectBtnText.anchor.set(0.5, 0.5);
levelSelectBtn.addChild(levelSelectBtnText);
levelSelectBtn.x = 2048 / 2;
levelSelectBtn.y = 2732 / 2 + 250;
game.addChild(levelSelectBtn);
var startBtn = new Container();
var startBtnBg = startBtn.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5
});
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 = 4;
gridHeight = 4;
} else if (level === 4) {
gridWidth = 5;
gridHeight = 4;
} else if (level >= 5) {
gridWidth = 5;
gridHeight = 4;
if (level === 5) {
gridWidth = 5;
gridHeight = 4;
}
}
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 = 'pair' + String.fromCharCode(65 + p % Math.min(totalPairs, 15));
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 + (level >= 5 ? 100 : 0);
// 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 && flippedCards.length === 0) {
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;
levelText.setText('Level: ' + level);
// Automatically start the next level
initializeBoard();
}, 1500);
}
// Start button interaction
startBtn.down = function (x, y, obj) {
game.removeChild(startBtn);
game.removeChild(levelSelectBtn);
initializeBoard();
};
// Level select button interaction
levelSelectBtn.down = function (x, y, obj) {
game.removeChild(startBtn);
game.removeChild(levelSelectBtn);
showLevelSelection();
};
function showLevelSelection() {
var levelOptions = [];
for (var i = 1; i <= 5; i++) {
(function (levelNum) {
var levelOption = new Text2('Level ' + levelNum, {
size: 70,
// Increased size for emphasis
fill: 0xFFD700,
// Gold color for standout effect
fontWeight: 'bolder',
// Make text bolder
shadow: {
blur: 15,
// Increased blur for more pronounced shadow
color: 0x000000,
offsetX: 7,
// Slightly larger offset for shadow
offsetY: 7
} // Add shadow for depth
});
levelOption.anchor.set(0.5, 0.5);
levelOption.x = 2048 / 2;
levelOption.y = 2732 / 2 - 200 + levelNum * 100;
levelOption.down = function () {
level = levelNum;
storage.level = level;
levelText.setText('Level: ' + level);
initializeBoard();
for (var j = 0; j < levelOptions.length; j++) {
game.removeChild(levelOptions[j]);
}
};
// Add hover effect
levelOption.over = function () {
tween(levelOption, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
easing: tween.easeOut
});
};
levelOption.out = function () {
tween(levelOption, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeIn
});
};
game.addChild(levelOption);
levelOptions.push(levelOption);
})(i);
}
}
// Handle game update
game.update = function () {
// Nothing needed here as the game logic is event-driven
};