User prompt
Make the default jumble state off.
User prompt
I don’t see any change when clicking the button.
User prompt
Ok let make the button look different when the option is turned on. Maybe giving it a a white sheen. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Create a new asset to add the jumble tile and replace the card selector text with the asset as a button.
User prompt
Move the ? To the end of the text
User prompt
Ok that’s not working. Move the ? To the end of the text.
User prompt
Please move the ? To the left of the [
User prompt
4 more spaces
User prompt
Move it more left about 4 spaces
User prompt
It is not at the start of the mine
User prompt
Please move the ? for the tool tip to the left of the check box (the start of the line) and also make it bold.
User prompt
Move the question mark more to the left and make it bold.
User prompt
Please. I’ve the ? For the tool tip to the left of the check box also make it bold.
User prompt
Ok let add some instructions for how the new shuffle and dud cards work. Create a 1 or 2 sentence help pop up that the player can select on the board selection screen.
User prompt
Ok better but the other card is flipping back over too quickly. We need to have the same delay before the other cards still doesn’t flips back over and the dud card starts to disappear.
User prompt
There’s an issue where the when the dud card and another card are revealed the other cards still doesn’t flip back over.
User prompt
Ok I want to add a check box on the board size selection screen that, when checked, adds the dud and shuffle card to the board. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Ok I want to add a check box on the board size selection screen that, when checked, adds the dud and shuffle card to the board. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Ok I like the idea of shifting the board. So let’s add 1 card called Shifter. When this card is flipped over the other cards still on the board will reveal themselves, change to random positions and then flip back over. The shifter card will then disappear. To keep the pairs even, add a non-shifter card. When this card is revealed it just disappears. It doesn’t need a pair and doesn’t give points. We need to make sure the flip logic takes into account that for both cards there won’t be a second card to flip. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The back button on the board size picking page doesn’t seem to work. Also, make the dialog box 10% taller on both screens.
User prompt
Ok can you make the size of the asset be dynamic so that i stretches to cover all the text on both screens. Also, please change the text color to black.
User prompt
Ok I want to put small dialog box on both the leaderboard screen and the board size selection screen. Create an asset for it please and the code.
User prompt
please resize the logo as well.
User prompt
ok i have added images to the buttons but they look very squished in the game. Please resize the buttons in the game to match the size of the assets.
User prompt
change the memory match text to a logo sized asset.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
useSpecialCards: false
});
/****
* Classes
****/
var Card = Container.expand(function (pairId) {
var self = Container.call(this);
self.pairId = pairId;
self.isFlipped = false;
self.isMatched = false;
self.back = self.attachAsset('card_back', {
anchorX: 0.5,
anchorY: 0.5
});
var faceAssetId;
if (pairId === -1) {
// Dud Card
faceAssetId = 'dud_card';
} else if (pairId === -2) {
// Shifter Card
faceAssetId = 'shifter_card';
} else {
// Normal Card
faceAssetId = 'card_face_' + pairId;
}
self.face = self.attachAsset(faceAssetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.face.visible = false;
// Public methods must be defined before they are called.
self.flipUp = function (onComplete) {
if (self.isFlipped) return;
self.isFlipped = true;
LK.getSound('flip').play();
tween(self, {
scaleX: 0
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
self.back.visible = false;
self.face.visible = true;
tween(self, {
scaleX: 1
}, {
duration: 150,
easing: tween.easeOut,
onFinish: onComplete
});
}
});
};
self.flipDown = function (onComplete) {
if (!self.isFlipped) return;
self.isFlipped = false;
tween(self, {
scaleX: 0
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
self.face.visible = false;
self.back.visible = true;
tween(self, {
scaleX: 1
}, {
duration: 150,
easing: tween.easeOut,
onFinish: onComplete
});
}
});
};
self.matchFound = function (onComplete) {
self.isMatched = true;
tween(self, {
alpha: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 400,
easing: tween.easeIn,
onFinish: onComplete
});
};
self.down = function () {
handleCardFlip(self);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50 // Dark slate blue background
});
/****
* Game Code
****/
//LK Engine will automatically create assets based on usage.
var menuBackground = game.addChild(LK.getAsset('menu_background', {
x: 1024,
y: 1366,
anchorX: 0.5,
anchorY: 0.5
}));
var boardBackground = game.addChild(LK.getAsset('board_background', {
x: 1024,
y: 1366,
anchorX: 0.5,
anchorY: 0.5
}));
//Defining 8 pairs of cards + 1 card back.
// Red
// Blue
// Green
// Yellow
// Magenta
// Cyan
// Orange
// Purple
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
LK.setScore(0); // Initialize score
// --- Game Constants ---
var COLS = 4;
var ROWS = 4;
var TOTAL_PAIRS = (COLS * ROWS - 2) / 2; // Subtract 2 for the Shifter and Dud cards
var TOTAL_CARD_FACES = 15;
var CARD_WIDTH = 350;
var CARD_HEIGHT = 350;
var MARGIN = 60;
var gridWidth = COLS * (CARD_WIDTH + MARGIN) - MARGIN;
var gridHeight = ROWS * (CARD_HEIGHT + MARGIN) - MARGIN;
var startX = (2048 - gridWidth) / 2 + CARD_WIDTH / 2;
var startY = (2732 - gridHeight) / 2 + CARD_HEIGHT / 2;
// --- Global UI and Game State Variables ---
var startScreenContainer, boardSizeContainer, leaderboardContainer, gameContainer, victoryScreenContainer;
var specialCardsCheckbox;
var cards = [];
var flippedCards = [];
var matchedPairs = 0;
var canPlay = true;
var streakCount = 0;
var maxStreak = 0;
// --- Screen Management ---
function showStartScreen() {
if (boardSizeContainer) boardSizeContainer.visible = false;
if (leaderboardContainer) leaderboardContainer.visible = false;
if (gameContainer) gameContainer.visible = false;
if (victoryScreenContainer) victoryScreenContainer.visible = false;
menuBackground.visible = true;
boardBackground.visible = false;
if (!startScreenContainer) {
startScreenContainer = game.addChild(new Container());
var title = LK.getAsset('logo', {
anchorX: 0.5,
anchorY: 0.5,
width: 1200,
height: 300
});
title.x = 2048 / 2;
title.y = 2732 / 2 - 400;
startScreenContainer.addChild(title);
var playButton = LK.getAsset('play_button', {
anchorX: 0.5,
anchorY: 0.5,
width: 600,
height: 200
});
playButton.x = 2048 / 2;
playButton.y = 2732 / 2;
playButton.down = function () {
showBoardSizeSelection();
};
startScreenContainer.addChild(playButton);
var leaderboardButton = LK.getAsset('leaderboard_button', {
anchorX: 0.5,
anchorY: 0.5,
width: 600,
height: 200
});
leaderboardButton.x = 2048 / 2;
leaderboardButton.y = 2732 / 2 + 250;
leaderboardButton.down = function () {
showLeaderboard();
};
startScreenContainer.addChild(leaderboardButton);
}
startScreenContainer.visible = true;
scoreTxt.visible = false;
}
function updateSpecialCardsButtonAppearance() {
if (storage.useSpecialCards) {
// Add white sheen when enabled (tint to a lighter color)
tween(specialCardsCheckbox, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
} else {
// Remove sheen when disabled (tint to normal, e.g. light gray or no tint)
tween(specialCardsCheckbox, {
tint: 0xCCCCCC
}, {
duration: 200,
easing: tween.easeOut
});
}
}
function showBoardSizeSelection() {
if (startScreenContainer) startScreenContainer.visible = false;
if (leaderboardContainer) leaderboardContainer.visible = false;
if (gameContainer) gameContainer.visible = false;
if (victoryScreenContainer) victoryScreenContainer.visible = false;
menuBackground.visible = true;
boardBackground.visible = false;
if (!boardSizeContainer) {
boardSizeContainer = game.addChild(new Container());
var dialogBox = LK.getAsset('dialog_box', {
x: 2048 / 2,
y: 2732 / 2,
anchorX: 0.5,
anchorY: 0.5
});
boardSizeContainer.addChild(dialogBox);
var content = [];
var title = new Text2('Select Board Size', {
size: 120,
fill: 0x000000,
fontWeight: 'bold'
});
title.anchor.set(0.5, 0.5);
title.x = 2048 / 2;
title.y = 2732 / 2 - 400;
boardSizeContainer.addChild(title);
content.push(title);
var size4x4Button = new Text2('4x4', {
size: 100,
fill: 0x000000,
fontWeight: 'bold'
});
size4x4Button.anchor.set(0.5, 0.5);
size4x4Button.x = 2048 / 2;
size4x4Button.y = 2732 / 2 - 100;
size4x4Button.down = function () {
setBoardSize(4, 4);
startGame();
};
boardSizeContainer.addChild(size4x4Button);
content.push(size4x4Button);
var size4x5Button = new Text2('4x5', {
size: 100,
fill: 0x000000,
fontWeight: 'bold'
});
size4x5Button.anchor.set(0.5, 0.5);
size4x5Button.x = 2048 / 2;
size4x5Button.y = 2732 / 2 + 50;
size4x5Button.down = function () {
setBoardSize(4, 5);
startGame();
};
boardSizeContainer.addChild(size4x5Button);
content.push(size4x5Button);
var size4x6Button = new Text2('4x6', {
size: 100,
fill: 0x000000,
fontWeight: 'bold'
});
size4x6Button.anchor.set(0.5, 0.5);
size4x6Button.x = 2048 / 2;
size4x6Button.y = 2732 / 2 + 200;
size4x6Button.down = function () {
setBoardSize(4, 6);
startGame();
};
boardSizeContainer.addChild(size4x6Button);
content.push(size4x6Button);
specialCardsCheckbox = LK.getAsset('jumble_tile', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 300
});
specialCardsCheckbox.down = function () {
storage.useSpecialCards = !storage.useSpecialCards;
updateSpecialCardsButtonAppearance();
};
boardSizeContainer.addChild(specialCardsCheckbox);
content.push(specialCardsCheckbox);
// Set initial tint to match state before animating
if (storage.useSpecialCards) {
specialCardsCheckbox.tint = 0xFFFFFF;
} else {
specialCardsCheckbox.tint = 0xCCCCCC;
}
// Initialize button appearance based on current setting
updateSpecialCardsButtonAppearance();
// Add help button for special cards
var helpButton = new Text2('?', {
size: 80,
fill: 0x000000,
fontWeight: 'bold'
});
helpButton.anchor.set(0.0, 0.5);
// Position the help button at the end of the jumble tile button
helpButton.x = specialCardsCheckbox.x + specialCardsCheckbox.width / 2 + 30;
helpButton.y = specialCardsCheckbox.y;
helpButton.down = function () {
// Show a simple popup with instructions
if (boardSizeContainer.helpPopup) {
boardSizeContainer.helpPopup.visible = true;
return;
}
var popup = new Container();
var popupBg = LK.getAsset('dialog_box', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 1200,
height: 600
});
popup.addChild(popupBg);
var helpText = new Text2("Special Cards:\n- The Shifter card reveals and shuffles all remaining cards before disappearing.\n- The Dud card disappears when flipped and does not give points or require a match.", {
size: 60,
fill: 0x000000,
wordWrap: true,
wordWrapWidth: 1000
});
helpText.anchor.set(0.5, 0.5);
helpText.x = 2048 / 2;
helpText.y = 2732 / 2 - 60;
popup.addChild(helpText);
var closeBtn = new Text2('Close', {
size: 80,
fill: 0x000000,
fontWeight: 'bold'
});
closeBtn.anchor.set(0.5, 0.5);
closeBtn.x = 2048 / 2;
closeBtn.y = 2732 / 2 + 180;
closeBtn.down = function () {
popup.visible = false;
};
popup.addChild(closeBtn);
boardSizeContainer.addChild(popup);
boardSizeContainer.helpPopup = popup;
};
boardSizeContainer.addChild(helpButton);
content.push(helpButton);
var backButton = new Text2('Back', {
size: 80,
fill: 0x000000,
fontWeight: 'bold'
});
backButton.anchor.set(0.5, 0.5);
backButton.x = 2048 / 2;
backButton.y = 2732 / 2 + 450;
backButton.down = function () {
showStartScreen();
};
boardSizeContainer.addChild(backButton);
content.push(backButton);
var minY = Infinity;
var maxY = -Infinity;
var maxWidth = 0;
for (var i = 0; i < content.length; i++) {
var text = content[i];
var top = text.y - text.height * text.anchor.y;
var bottom = text.y + text.height * (1 - text.anchor.y);
if (top < minY) minY = top;
if (bottom > maxY) maxY = bottom;
if (text.width > maxWidth) maxWidth = text.width;
}
var PADDING_Y = 100;
var PADDING_X = 150;
dialogBox.height = (maxY - minY + PADDING_Y * 2) * 1.1;
dialogBox.width = maxWidth + PADDING_X * 2;
dialogBox.y = minY + (maxY - minY) / 2;
}
// Special cards checkbox is now an image button - no text to update
boardSizeContainer.visible = true;
scoreTxt.visible = false;
}
function setBoardSize(cols, rows) {
COLS = cols;
ROWS = rows;
if (storage.useSpecialCards === true) {
TOTAL_PAIRS = (COLS * ROWS - 2) / 2;
} else {
TOTAL_PAIRS = COLS * ROWS / 2;
}
gridWidth = COLS * (CARD_WIDTH + MARGIN) - MARGIN;
gridHeight = ROWS * (CARD_HEIGHT + MARGIN) - MARGIN;
startX = (2048 - gridWidth) / 2 + CARD_WIDTH / 2;
startY = (2732 - gridHeight) / 2 + CARD_HEIGHT / 2;
}
function showLeaderboard() {
if (startScreenContainer) startScreenContainer.visible = false;
if (boardSizeContainer) boardSizeContainer.visible = false;
menuBackground.visible = true;
boardBackground.visible = false;
if (!leaderboardContainer) {
leaderboardContainer = game.addChild(new Container());
var dialogBox = LK.getAsset('dialog_box', {
x: 2048 / 2,
y: 2732 / 2,
anchorX: 0.5,
anchorY: 0.5
});
leaderboardContainer.addChild(dialogBox);
var content = [];
var title = new Text2('Leaderboard', {
size: 150,
fill: 0x000000,
fontWeight: 'bold'
});
title.anchor.set(0.5, 0.5);
title.x = 2048 / 2;
title.y = 2732 / 2 - 600;
leaderboardContainer.addChild(title);
content.push(title);
var header = new Text2('RANK USER SCORE STREAK', {
size: 70,
fill: 0x000000
});
header.anchor.set(0.5, 0.5);
header.x = 2048 / 2;
header.y = 2732 / 2 - 300;
leaderboardContainer.addChild(header);
content.push(header);
var highScore = storage.highScore || 0;
var highScoreStreak = storage.highScoreStreak || 0;
var userLine = new Text2('1 You ' + highScore + ' ' + highScoreStreak, {
size: 90,
fill: 0x000000,
fontWeight: 'bold'
});
userLine.anchor.set(0.5, 0.5);
userLine.x = 2048 / 2;
userLine.y = 2732 / 2 - 150;
leaderboardContainer.addChild(userLine);
leaderboardContainer.userLine = userLine; // Store reference
content.push(userLine);
var backButton = new Text2('Back', {
size: 100,
fill: 0x000000,
fontWeight: 'bold'
});
backButton.anchor.set(0.5, 0.5);
backButton.x = 2048 / 2;
backButton.y = 2732 / 2 + 300;
backButton.down = function () {
showStartScreen();
};
leaderboardContainer.addChild(backButton);
content.push(backButton);
var minY = Infinity;
var maxY = -Infinity;
var maxWidth = 0;
for (var i = 0; i < content.length; i++) {
var text = content[i];
var top = text.y - text.height * text.anchor.y;
var bottom = text.y + text.height * (1 - text.anchor.y);
if (top < minY) minY = top;
if (bottom > maxY) maxY = bottom;
if (text.width > maxWidth) maxWidth = text.width;
}
var PADDING_Y = 100;
var PADDING_X = 150;
dialogBox.height = (maxY - minY + PADDING_Y * 2) * 1.1;
dialogBox.width = maxWidth + PADDING_X * 2;
dialogBox.y = minY + (maxY - minY) / 2;
} else {
var highScore = storage.highScore || 0;
var highScoreStreak = storage.highScoreStreak || 0;
leaderboardContainer.userLine.setText('1 You ' + highScore + ' ' + highScoreStreak);
}
leaderboardContainer.visible = true;
scoreTxt.visible = false;
}
function showVictoryScreen() {
if (gameContainer) gameContainer.visible = false;
if (boardSizeContainer) boardSizeContainer.visible = false;
scoreTxt.visible = false;
menuBackground.visible = true;
boardBackground.visible = false;
if (!victoryScreenContainer) {
victoryScreenContainer = game.addChild(new Container());
var title = new Text2('You Win!', {
size: 150,
fill: 0xFFD700
});
title.anchor.set(0.5, 0.5);
title.x = 2048 / 2;
title.y = 2732 / 2 - 400;
victoryScreenContainer.addChild(title);
var finalScoreText = new Text2('Final Score: ' + LK.getScore(), {
size: 100,
fill: 0xFFFFFF,
fontWeight: 'bold',
stroke: 0x000000,
strokeThickness: 8
});
finalScoreText.anchor.set(0.5, 0.5);
finalScoreText.x = 2048 / 2;
finalScoreText.y = 2732 / 2 - 200;
victoryScreenContainer.addChild(finalScoreText);
victoryScreenContainer.finalScoreText = finalScoreText; // To update it later
var playAgainButton = new Text2('Play Again', {
size: 100,
fill: 0xFFFFFF,
fontWeight: 'bold',
stroke: 0x000000,
strokeThickness: 8
});
playAgainButton.anchor.set(0.5, 0.5);
playAgainButton.x = 2048 / 2;
playAgainButton.y = 2732 / 2;
playAgainButton.down = function () {
startGame();
};
victoryScreenContainer.addChild(playAgainButton);
var mainMenuButton = new Text2('Main Menu', {
size: 100,
fill: 0xFFFFFF,
fontWeight: 'bold',
stroke: 0x000000,
strokeThickness: 8
});
mainMenuButton.anchor.set(0.5, 0.5);
mainMenuButton.x = 2048 / 2;
mainMenuButton.y = 2732 / 2 + 200;
mainMenuButton.down = function () {
showStartScreen();
};
victoryScreenContainer.addChild(mainMenuButton);
} else {
victoryScreenContainer.finalScoreText.setText('Final Score: ' + LK.getScore());
}
victoryScreenContainer.visible = true;
}
function startGame() {
if (startScreenContainer) startScreenContainer.visible = false;
if (boardSizeContainer) boardSizeContainer.visible = false;
if (leaderboardContainer) leaderboardContainer.visible = false;
if (victoryScreenContainer) victoryScreenContainer.visible = false;
menuBackground.visible = false;
boardBackground.visible = true;
if (!gameContainer) {
gameContainer = game.addChild(new Container());
}
gameContainer.visible = true;
// Clear old cards
for (var i = 0; i < cards.length; i++) {
cards[i].destroy();
}
// Reset game state
cards = [];
flippedCards = [];
matchedPairs = 0;
canPlay = true;
streakCount = 0;
maxStreak = 0;
LK.setScore(0);
scoreTxt.setText('Score: ' + LK.getScore());
scoreTxt.visible = true;
setupBoard();
}
// --- Game Logic Functions ---
function showStreakAnimation(bonusPoints) {
var bonusContainer = new Container();
bonusContainer.x = 2048 / 2;
bonusContainer.y = 2732 / 2;
var bonusText = new Text2('BONUS!!!', {
size: 120,
fill: 0xFFD700
});
bonusText.anchor.set(0.5, 0.5);
bonusText.y = -70;
bonusContainer.addChild(bonusText);
var pointsText = new Text2('+' + bonusPoints, {
size: 100,
fill: 0xFFFFFF
});
pointsText.anchor.set(0.5, 0.5);
pointsText.y = 70;
bonusContainer.addChild(pointsText);
gameContainer.addChild(bonusContainer);
// Animate upward movement
tween(bonusContainer, {
y: bonusContainer.y - 200
}, {
duration: 1000,
easing: tween.easeOut
});
// After 0.5s, start fading out
LK.setTimeout(function () {
if (bonusContainer.parent) {
tween(bonusContainer, {
alpha: 0
}, {
duration: 500,
// Fades over the last 0.5s
easing: tween.easeOut,
onFinish: function onFinish() {
// Self-destruct after animation. Check parent to avoid errors
// if the game state was cleared during the animation.
if (bonusContainer.parent) {
bonusContainer.destroy();
}
}
});
}
}, 500);
}
function checkWinCondition() {
var remainingCards = 0;
for (var i = 0; i < cards.length; i++) {
if (!cards[i].isMatched) {
remainingCards++;
}
}
if (remainingCards === 0) {
var highScore = storage.highScore || 0;
var highScoreStreak = storage.highScoreStreak || 0;
if (LK.getScore() > highScore) {
storage.highScore = LK.getScore();
storage.highScoreStreak = maxStreak;
}
LK.getSound('win').play();
LK.setTimeout(function () {
showVictoryScreen();
}, 200);
}
}
function handleDudCard(card) {
card.isMatched = true; // Mark as handled
// Match the flip down delay of the other card (1000ms)
LK.setTimeout(function () {
tween(card, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
checkWinCondition();
canPlay = true;
}
});
}, 1000);
}
function flipAllDownAndEndTurn(cardsToFlip) {
var flipCount = 0;
if (cardsToFlip.length === 0) {
checkWinCondition();
canPlay = true;
return;
}
cardsToFlip.forEach(function (c) {
c.flipDown(function () {
flipCount++;
if (flipCount === cardsToFlip.length) {
checkWinCondition();
canPlay = true;
}
});
});
}
function startShuffleAnimation(shifterCard, otherCards, originalPositions) {
var newPositions = shuffle(originalPositions);
tween(shifterCard, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
// Card is visually gone and marked as matched.
}
});
var moveCount = 0;
if (otherCards.length === 0) {
flipAllDownAndEndTurn([]);
return;
}
otherCards.forEach(function (c, i) {
tween(c, {
x: newPositions[i].x,
y: newPositions[i].y
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
moveCount++;
if (moveCount === otherCards.length) {
// All cards moved, now flip them back down
flipAllDownAndEndTurn(otherCards);
}
}
});
});
}
function handleShifterCard(card) {
card.isMatched = true; // Mark as handled
var otherCards = cards.filter(function (c) {
return c !== card && !c.isMatched;
});
if (otherCards.length === 0) {
handleDudCard(card); // Behaves like a dud card if no other cards are on board
return;
}
var originalPositions = [];
otherCards.forEach(function (c) {
originalPositions.push({
x: c.x,
y: c.y
});
});
var revealCount = 0;
otherCards.forEach(function (c) {
c.flipUp(function () {
revealCount++;
if (revealCount === otherCards.length) {
LK.setTimeout(function () {
startShuffleAnimation(card, otherCards, originalPositions);
}, 800); // Pause to let player see cards
}
});
});
}
function handleCardFlip(card) {
if (!canPlay || card.isFlipped || card.isMatched) {
return;
}
// Handle special cards immediately
if (card.pairId < 0) {
canPlay = false;
// If a normal card is already flipped, flip it back down before handling the special card
if (flippedCards.length === 1) {
var otherCard = flippedCards[0];
otherCard.flipDown(function () {
flippedCards = [];
card.flipUp(function () {
if (card.pairId === -1) {
handleDudCard(card);
} else if (card.pairId === -2) {
handleShifterCard(card);
}
});
});
} else {
flippedCards = []; // Clear any single-flipped normal card
card.flipUp(function () {
if (card.pairId === -1) {
handleDudCard(card);
} else if (card.pairId === -2) {
handleShifterCard(card);
}
});
}
return;
}
// Prevent flipping a third card
if (flippedCards.length >= 2) {
return;
}
flippedCards.push(card);
card.flipUp(function () {
if (flippedCards.length === 2) {
canPlay = false;
checkMatch();
}
});
}
function checkMatch() {
var card1 = flippedCards[0];
var card2 = flippedCards[1];
if (card1.pairId === card2.pairId) {
matchedPairs++;
streakCount++;
if (streakCount > maxStreak) {
maxStreak = streakCount;
}
// Calculate points based on streak
var points = 10;
var bonusPoints = 0;
if (streakCount === 2) {
points = 20;
bonusPoints = 10;
} else if (streakCount >= 3) {
points = 30;
bonusPoints = 20;
}
if (bonusPoints > 0) {
showStreakAnimation(bonusPoints);
}
LK.setScore(LK.getScore() + points);
scoreTxt.setText('Score: ' + LK.getScore());
LK.setTimeout(function () {
LK.getSound('match').play();
card1.matchFound();
card2.matchFound(function () {
resetTurn();
checkWinCondition();
});
}, 750);
} else {
// Reset streak on miss
streakCount = 0;
LK.setTimeout(function () {
card1.flipDown();
card2.flipDown(function () {
resetTurn();
});
}, 1000);
}
}
function resetTurn() {
flippedCards = [];
canPlay = true;
}
function shuffle(array) {
var currentIndex = array.length,
randomIndex;
while (currentIndex !== 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
var _ref = [array[randomIndex], array[currentIndex]];
array[currentIndex] = _ref[0];
array[randomIndex] = _ref[1];
}
return array;
}
function isLayoutValid(grid) {
for (var row = 0; row < ROWS; row++) {
for (var col = 0; col < COLS; col++) {
var currentPairId = grid[row][col];
// Check all 8 neighbors
for (var dr = -1; dr <= 1; dr++) {
for (var dc = -1; dc <= 1; dc++) {
if (dr === 0 && dc === 0) continue; // Don't check self
var neighborRow = row + dr;
var neighborCol = col + dc;
if (neighborRow >= 0 && neighborRow < ROWS && neighborCol >= 0 && neighborCol < COLS) {
if (grid[neighborRow][neighborCol] === currentPairId) {
return false; // Found an adjacent match
}
}
}
}
}
}
return true; // No adjacent matches found
}
// --- Board Setup ---
function setupBoard() {
var pairIds = [];
// Create a list of all available card face IDs (0 to TOTAL_CARD_FACES-1)
var allFaceIndices = [];
for (var i = 0; i < TOTAL_CARD_FACES; i++) {
allFaceIndices.push(i);
}
// Shuffle the available faces and select enough for the board
shuffle(allFaceIndices);
var gameFaceIndices = allFaceIndices.slice(0, TOTAL_PAIRS);
// Create pairs from the selected faces
for (var i = 0; i < TOTAL_PAIRS; i++) {
pairIds.push(gameFaceIndices[i], gameFaceIndices[i]);
}
// Add the special cards if enabled
if (storage.useSpecialCards === true) {
pairIds.push(-1); // Dud Card
pairIds.push(-2); // Shifter Card
}
var grid = [];
var attempts = 0;
var maxAttempts = 100; // Safeguard to prevent infinite loop
do {
shuffle(pairIds);
// Create a 2D grid from the shuffled IDs
for (var r = 0; r < ROWS; r++) {
grid[r] = [];
for (var c = 0; c < COLS; c++) {
grid[r][c] = pairIds[r * COLS + c];
}
}
attempts++;
} while (!isLayoutValid(grid) && attempts < maxAttempts);
// Create cards from the final grid layout
for (var row = 0; row < ROWS; row++) {
for (var col = 0; col < COLS; col++) {
var pairId = grid[row][col];
var card = new Card(pairId);
card.x = startX + col * (CARD_WIDTH + MARGIN);
card.y = startY + row * (CARD_HEIGHT + MARGIN);
cards.push(card);
gameContainer.addChild(card);
}
}
}
// --- Initial Call ---
showStartScreen(); ===================================================================
--- original.js
+++ change.js
@@ -2,9 +2,9 @@
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
- useSpecialCards: true
+ useSpecialCards: false
});
/****
* Classes
a cartoon style 3d image of a snowman in a field with pine trees in the background. no people.. In-Game asset. 2d. High contrast. No shadows
a cartoon style 3d image of a cozy christmas living room with a cozy fire in a fireplace.. In-Game asset. 2d. High contrast. No shadows
a cartoon style 3d image of a memory match board game with some cards face up and some cards face down.. In-Game asset. 2d. High contrast. No shadows
a cartoon style 3d button that says Play.. In-Game asset. 2d. High contrast. No shadows
a cartoon style 3d button with the word Leader Board on it.. In-Game asset. 2d. High contrast. No shadows
A cartoon style 3d button with the words Match Maker all on 1 line. In-Game asset. 2d. High contrast. No shadows
a cartoon style 3d image of a green meadow with trees on the edges and a clearing in the middle.. In-Game asset. 2d. High contrast. No shadows
A tan dialog box background with a dark brown border.. In-Game asset. 2d. High contrast. No shadows. Cartoon style. 3D image
A table with the game Memory on it that got jostled so the card are flying in the air.. In-Game asset. 2d. High contrast. No shadows. Cartoon style. 3D image
Big TNT firecracker that is a dud with smoke wafting out of the fuse hole. In-Game asset. 2d. High contrast. No shadows. Cartoon style. 3D image
A small button that says Jumble. No shadow.