/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
musicVolume: 1
});
/****
* Classes
****/
var Card = Container.expand(function (cardType) {
var self = Container.call(this);
self.cardType = cardType;
self.isFlipped = false;
self.isMatched = false;
self.canFlip = true;
// Create card back
var cardBack = self.attachAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5
});
// Create card front based on type
var frontAssetName = 'cardFront' + cardType;
var cardFront = self.attachAsset(frontAssetName, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.cardBack = cardBack;
self.cardFront = cardFront;
self.flip = function () {
if (!self.canFlip || self.isMatched) return;
LK.getSound('cardFlip').play();
if (!self.isFlipped) {
// Flip to front
tween(self.cardBack, {
alpha: 0
}, {
duration: 150
});
tween(self.cardFront, {
alpha: 1
}, {
duration: 150
});
self.isFlipped = true;
} else {
// Flip to back
tween(self.cardBack, {
alpha: 1
}, {
duration: 150
});
tween(self.cardFront, {
alpha: 0
}, {
duration: 150
});
self.isFlipped = false;
}
};
self.setMatched = function () {
self.isMatched = true;
self.canFlip = false;
// Glow effect for matched cards
tween(self, {
alpha: 0.7
}, {
duration: 300,
easing: tween.easeInOut
});
LK.getSound('match').play();
};
self.down = function (x, y, obj) {
if (self.canFlip && !self.isMatched && !self.isFlipped) {
onCardTapped(self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c5530
});
/****
* Game Code
****/
// Add background
var background = game.attachAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// Game state variables
var currentLevel = storage.currentLevel || 1;
var maxLevel = 10;
var cards = [];
var flippedCards = [];
var gameActive = false;
var moveCount = 0;
var matchedPairs = 0;
var totalPairs = 0;
var isProcessingMatch = false;
var showingMenu = true;
// Level configurations
var levelConfigs = [{
rows: 2,
cols: 4,
pairs: 4
},
// Level 1: 4x2 = 8 cards
{
rows: 3,
cols: 4,
pairs: 6
},
// Level 2: 4x3 = 12 cards
{
rows: 4,
cols: 4,
pairs: 8
},
// Level 3: 4x4 = 16 cards
{
rows: 4,
cols: 5,
pairs: 10
},
// Level 4: 5x4 = 20 cards
{
rows: 4,
cols: 6,
pairs: 12
},
// Level 5: 6x4 = 24 cards
{
rows: 5,
cols: 6,
pairs: 15
},
// Level 6: 6x5 = 30 cards
{
rows: 6,
cols: 6,
pairs: 18
},
// Level 7: 6x6 = 36 cards
{
rows: 7,
cols: 6,
pairs: 21
},
// Level 8: 6x7 = 42 cards
{
rows: 8,
cols: 6,
pairs: 24
},
// Level 9: 6x8 = 48 cards
{
rows: 9,
cols: 6,
pairs: 27
} // Level 10: 6x9 = 54 cards
];
// Menu UI Elements
var menuContainer = new Container();
game.addChild(menuContainer);
var titleText = new Text2('Memory Match Levels', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 800;
menuContainer.addChild(titleText);
var playText = new Text2('START', {
size: 120,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = 2048 / 2;
playText.y = 1400;
menuContainer.addChild(playText);
var volumeText = new Text2('Music: ' + (storage.musicVolume > 0 ? 'ON' : 'OFF'), {
size: 80,
fill: 0xFFFFFF
});
volumeText.anchor.set(0.5, 0.5);
volumeText.x = 2048 / 2;
volumeText.y = 1600;
menuContainer.addChild(volumeText);
// Game UI Elements (initially hidden)
var gameUIContainer = new Container();
gameUIContainer.alpha = 0;
game.addChild(gameUIContainer);
var levelText = new Text2('Level ' + currentLevel, {
size: 80,
fill: 0xFFFF00
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
var moveText = new Text2('Moves: 0', {
size: 60,
fill: 0xFFFF00
});
moveText.anchor.set(0, 0);
moveText.x = 50;
moveText.y = 150;
LK.gui.topLeft.addChild(moveText);
var scoreText = new Text2('Score: ' + LK.getScore(), {
size: 60,
fill: 0xFFFF00
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
function startGame() {
currentLevel = 1; // Reset to level 1 at every start
showingMenu = false;
gameActive = true;
// Hide menu
tween(menuContainer, {
alpha: 0
}, {
duration: 500
});
// Show game UI
tween(gameUIContainer, {
alpha: 1
}, {
duration: 500
});
// Update level text and start the first level
levelText.setText('Level ' + currentLevel);
LK.setTimeout(function () {
setupLevel();
}, 500);
}
function onCardTapped(card) {
if (!gameActive || isProcessingMatch) return;
if (flippedCards.length < 2 && !card.isFlipped) {
card.flip();
flippedCards.push(card);
if (flippedCards.length === 2) {
moveCount++;
moveText.setText('Moves: ' + moveCount);
isProcessingMatch = true;
// Check for match after a delay
LK.setTimeout(function () {
checkForMatch();
}, 1000);
}
}
}
function checkForMatch() {
if (flippedCards.length === 2) {
var card1 = flippedCards[0];
var card2 = flippedCards[1];
if (card1.cardType === card2.cardType) {
// Match found
card1.setMatched();
card2.setMatched();
matchedPairs++;
// Add points
var points = Math.max(10, 50 - moveCount);
LK.setScore(LK.getScore() + points);
scoreText.setText('Score: ' + LK.getScore());
// Check if level is complete
if (matchedPairs === totalPairs) {
LK.setTimeout(function () {
completeLevel();
}, 500);
}
} else {
// No match, flip cards back
card1.flip();
card2.flip();
}
flippedCards = [];
isProcessingMatch = false;
}
}
function completeLevel() {
gameActive = false;
LK.getSound('levelComplete').play();
// Bonus points for completing level
var levelBonus = currentLevel * 100;
LK.setScore(LK.getScore() + levelBonus);
scoreText.setText('Score: ' + LK.getScore());
// Flash screen green
LK.effects.flashScreen(0x00ff00, 1000);
// Progress to next level
currentLevel++;
if (currentLevel > maxLevel) {
// Game completed
LK.setTimeout(function () {
LK.showYouWin();
}, 1500);
} else {
// Save progress and start next level
storage.currentLevel = currentLevel;
LK.setTimeout(function () {
setupLevel();
}, 2000);
}
}
function setupLevel() {
// Clear existing cards
for (var i = 0; i < cards.length; i++) {
cards[i].destroy();
}
cards = [];
flippedCards = [];
matchedPairs = 0;
moveCount = 0;
gameActive = true;
isProcessingMatch = false;
// Update UI
levelText.setText('Level ' + currentLevel);
moveText.setText('Moves: 0');
// Get level configuration
var config = levelConfigs[currentLevel - 1];
totalPairs = config.pairs;
// Create card types array (pairs)
var cardTypes = [];
for (var i = 1; i <= config.pairs; i++) {
cardTypes.push(i);
cardTypes.push(i);
}
// Shuffle cards
for (var i = cardTypes.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = cardTypes[i];
cardTypes[i] = cardTypes[j];
cardTypes[j] = temp;
}
// Calculate grid positioning
var cardWidth = 200;
var cardHeight = 250;
var spacing = 40;
var totalWidth = config.cols * cardWidth + (config.cols - 1) * spacing;
var totalHeight = config.rows * cardHeight + (config.rows - 1) * spacing;
var startX = (2048 - totalWidth) / 2 + cardWidth / 2;
var startY = (2732 - totalHeight) / 2 + cardHeight / 2;
// Create and position cards
var cardIndex = 0;
for (var row = 0; row < config.rows; row++) {
for (var col = 0; col < config.cols; col++) {
if (cardIndex < cardTypes.length) {
var card = new Card(cardTypes[cardIndex]);
card.x = startX + col * (cardWidth + spacing);
card.y = startY + row * (cardHeight + spacing);
cards.push(card);
game.addChild(card);
cardIndex++;
}
}
}
}
// Add click handler for play button and volume control
game.down = function (x, y, obj) {
if (showingMenu) {
var playButtonBounds = {
x: 2048 / 2 - 150,
y: 1400 - 60,
width: 300,
height: 120
};
var volumeButtonBounds = {
x: 2048 / 2 - 150,
y: 1600 - 40,
width: 300,
height: 80
};
if (x >= playButtonBounds.x && x <= playButtonBounds.x + playButtonBounds.width && y >= playButtonBounds.y && y <= playButtonBounds.y + playButtonBounds.height) {
startGame();
} else if (x >= volumeButtonBounds.x && x <= volumeButtonBounds.x + volumeButtonBounds.width && y >= volumeButtonBounds.y && y <= volumeButtonBounds.y + volumeButtonBounds.height) {
// Toggle music volume
storage.musicVolume = storage.musicVolume > 0 ? 0 : 1;
volumeText.setText('Music: ' + (storage.musicVolume > 0 ? 'ON' : 'OFF'));
// Update music volume
if (storage.musicVolume > 0) {
LK.playMusic('song', {
loop: true
});
} else {
LK.stopMusic();
}
}
}
};
// Start background music with saved volume setting
if (storage.musicVolume > 0) {
LK.playMusic('song', {
loop: true
});
}
game.update = function () {
// Game loop - currently no continuous updates needed
// All game logic is event-driven
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
musicVolume: 1
});
/****
* Classes
****/
var Card = Container.expand(function (cardType) {
var self = Container.call(this);
self.cardType = cardType;
self.isFlipped = false;
self.isMatched = false;
self.canFlip = true;
// Create card back
var cardBack = self.attachAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5
});
// Create card front based on type
var frontAssetName = 'cardFront' + cardType;
var cardFront = self.attachAsset(frontAssetName, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.cardBack = cardBack;
self.cardFront = cardFront;
self.flip = function () {
if (!self.canFlip || self.isMatched) return;
LK.getSound('cardFlip').play();
if (!self.isFlipped) {
// Flip to front
tween(self.cardBack, {
alpha: 0
}, {
duration: 150
});
tween(self.cardFront, {
alpha: 1
}, {
duration: 150
});
self.isFlipped = true;
} else {
// Flip to back
tween(self.cardBack, {
alpha: 1
}, {
duration: 150
});
tween(self.cardFront, {
alpha: 0
}, {
duration: 150
});
self.isFlipped = false;
}
};
self.setMatched = function () {
self.isMatched = true;
self.canFlip = false;
// Glow effect for matched cards
tween(self, {
alpha: 0.7
}, {
duration: 300,
easing: tween.easeInOut
});
LK.getSound('match').play();
};
self.down = function (x, y, obj) {
if (self.canFlip && !self.isMatched && !self.isFlipped) {
onCardTapped(self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c5530
});
/****
* Game Code
****/
// Add background
var background = game.attachAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// Game state variables
var currentLevel = storage.currentLevel || 1;
var maxLevel = 10;
var cards = [];
var flippedCards = [];
var gameActive = false;
var moveCount = 0;
var matchedPairs = 0;
var totalPairs = 0;
var isProcessingMatch = false;
var showingMenu = true;
// Level configurations
var levelConfigs = [{
rows: 2,
cols: 4,
pairs: 4
},
// Level 1: 4x2 = 8 cards
{
rows: 3,
cols: 4,
pairs: 6
},
// Level 2: 4x3 = 12 cards
{
rows: 4,
cols: 4,
pairs: 8
},
// Level 3: 4x4 = 16 cards
{
rows: 4,
cols: 5,
pairs: 10
},
// Level 4: 5x4 = 20 cards
{
rows: 4,
cols: 6,
pairs: 12
},
// Level 5: 6x4 = 24 cards
{
rows: 5,
cols: 6,
pairs: 15
},
// Level 6: 6x5 = 30 cards
{
rows: 6,
cols: 6,
pairs: 18
},
// Level 7: 6x6 = 36 cards
{
rows: 7,
cols: 6,
pairs: 21
},
// Level 8: 6x7 = 42 cards
{
rows: 8,
cols: 6,
pairs: 24
},
// Level 9: 6x8 = 48 cards
{
rows: 9,
cols: 6,
pairs: 27
} // Level 10: 6x9 = 54 cards
];
// Menu UI Elements
var menuContainer = new Container();
game.addChild(menuContainer);
var titleText = new Text2('Memory Match Levels', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 800;
menuContainer.addChild(titleText);
var playText = new Text2('START', {
size: 120,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = 2048 / 2;
playText.y = 1400;
menuContainer.addChild(playText);
var volumeText = new Text2('Music: ' + (storage.musicVolume > 0 ? 'ON' : 'OFF'), {
size: 80,
fill: 0xFFFFFF
});
volumeText.anchor.set(0.5, 0.5);
volumeText.x = 2048 / 2;
volumeText.y = 1600;
menuContainer.addChild(volumeText);
// Game UI Elements (initially hidden)
var gameUIContainer = new Container();
gameUIContainer.alpha = 0;
game.addChild(gameUIContainer);
var levelText = new Text2('Level ' + currentLevel, {
size: 80,
fill: 0xFFFF00
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
var moveText = new Text2('Moves: 0', {
size: 60,
fill: 0xFFFF00
});
moveText.anchor.set(0, 0);
moveText.x = 50;
moveText.y = 150;
LK.gui.topLeft.addChild(moveText);
var scoreText = new Text2('Score: ' + LK.getScore(), {
size: 60,
fill: 0xFFFF00
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
function startGame() {
currentLevel = 1; // Reset to level 1 at every start
showingMenu = false;
gameActive = true;
// Hide menu
tween(menuContainer, {
alpha: 0
}, {
duration: 500
});
// Show game UI
tween(gameUIContainer, {
alpha: 1
}, {
duration: 500
});
// Update level text and start the first level
levelText.setText('Level ' + currentLevel);
LK.setTimeout(function () {
setupLevel();
}, 500);
}
function onCardTapped(card) {
if (!gameActive || isProcessingMatch) return;
if (flippedCards.length < 2 && !card.isFlipped) {
card.flip();
flippedCards.push(card);
if (flippedCards.length === 2) {
moveCount++;
moveText.setText('Moves: ' + moveCount);
isProcessingMatch = true;
// Check for match after a delay
LK.setTimeout(function () {
checkForMatch();
}, 1000);
}
}
}
function checkForMatch() {
if (flippedCards.length === 2) {
var card1 = flippedCards[0];
var card2 = flippedCards[1];
if (card1.cardType === card2.cardType) {
// Match found
card1.setMatched();
card2.setMatched();
matchedPairs++;
// Add points
var points = Math.max(10, 50 - moveCount);
LK.setScore(LK.getScore() + points);
scoreText.setText('Score: ' + LK.getScore());
// Check if level is complete
if (matchedPairs === totalPairs) {
LK.setTimeout(function () {
completeLevel();
}, 500);
}
} else {
// No match, flip cards back
card1.flip();
card2.flip();
}
flippedCards = [];
isProcessingMatch = false;
}
}
function completeLevel() {
gameActive = false;
LK.getSound('levelComplete').play();
// Bonus points for completing level
var levelBonus = currentLevel * 100;
LK.setScore(LK.getScore() + levelBonus);
scoreText.setText('Score: ' + LK.getScore());
// Flash screen green
LK.effects.flashScreen(0x00ff00, 1000);
// Progress to next level
currentLevel++;
if (currentLevel > maxLevel) {
// Game completed
LK.setTimeout(function () {
LK.showYouWin();
}, 1500);
} else {
// Save progress and start next level
storage.currentLevel = currentLevel;
LK.setTimeout(function () {
setupLevel();
}, 2000);
}
}
function setupLevel() {
// Clear existing cards
for (var i = 0; i < cards.length; i++) {
cards[i].destroy();
}
cards = [];
flippedCards = [];
matchedPairs = 0;
moveCount = 0;
gameActive = true;
isProcessingMatch = false;
// Update UI
levelText.setText('Level ' + currentLevel);
moveText.setText('Moves: 0');
// Get level configuration
var config = levelConfigs[currentLevel - 1];
totalPairs = config.pairs;
// Create card types array (pairs)
var cardTypes = [];
for (var i = 1; i <= config.pairs; i++) {
cardTypes.push(i);
cardTypes.push(i);
}
// Shuffle cards
for (var i = cardTypes.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = cardTypes[i];
cardTypes[i] = cardTypes[j];
cardTypes[j] = temp;
}
// Calculate grid positioning
var cardWidth = 200;
var cardHeight = 250;
var spacing = 40;
var totalWidth = config.cols * cardWidth + (config.cols - 1) * spacing;
var totalHeight = config.rows * cardHeight + (config.rows - 1) * spacing;
var startX = (2048 - totalWidth) / 2 + cardWidth / 2;
var startY = (2732 - totalHeight) / 2 + cardHeight / 2;
// Create and position cards
var cardIndex = 0;
for (var row = 0; row < config.rows; row++) {
for (var col = 0; col < config.cols; col++) {
if (cardIndex < cardTypes.length) {
var card = new Card(cardTypes[cardIndex]);
card.x = startX + col * (cardWidth + spacing);
card.y = startY + row * (cardHeight + spacing);
cards.push(card);
game.addChild(card);
cardIndex++;
}
}
}
}
// Add click handler for play button and volume control
game.down = function (x, y, obj) {
if (showingMenu) {
var playButtonBounds = {
x: 2048 / 2 - 150,
y: 1400 - 60,
width: 300,
height: 120
};
var volumeButtonBounds = {
x: 2048 / 2 - 150,
y: 1600 - 40,
width: 300,
height: 80
};
if (x >= playButtonBounds.x && x <= playButtonBounds.x + playButtonBounds.width && y >= playButtonBounds.y && y <= playButtonBounds.y + playButtonBounds.height) {
startGame();
} else if (x >= volumeButtonBounds.x && x <= volumeButtonBounds.x + volumeButtonBounds.width && y >= volumeButtonBounds.y && y <= volumeButtonBounds.y + volumeButtonBounds.height) {
// Toggle music volume
storage.musicVolume = storage.musicVolume > 0 ? 0 : 1;
volumeText.setText('Music: ' + (storage.musicVolume > 0 ? 'ON' : 'OFF'));
// Update music volume
if (storage.musicVolume > 0) {
LK.playMusic('song', {
loop: true
});
} else {
LK.stopMusic();
}
}
}
};
// Start background music with saved volume setting
if (storage.musicVolume > 0) {
LK.playMusic('song', {
loop: true
});
}
game.update = function () {
// Game loop - currently no continuous updates needed
// All game logic is event-driven
};