/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
currentLevel: 1
});
/****
* Classes
****/
var Button = Container.expand(function (text) {
var self = Container.call(this);
self.background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
self.label = new Text2(text || "Button", {
size: 50,
fill: 0xFFFFFF
});
self.label.anchor.set(0.5, 0.5);
self.addChild(self.label);
// Set interactive
self.interactive = true;
return self;
});
// Define prototype methods for Button
var Card = Container.expand(function (cardNumber) {
var self = Container.call(this);
self.cardNumber = cardNumber || 0;
self.revealed = false;
self.matched = false;
self.canFlip = false; // Flag to control when cards can be flipped
// Card back (shown initially)
self.back = self.attachAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5
});
// Card front (shown when flipped)
self.front = self.attachAsset('cardFront', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
});
// Card number text
self.numberText = new Text2(self.cardNumber.toString(), {
size: 100,
fill: 0x000000
});
self.numberText.anchor.set(0.5, 0.5);
self.numberText.visible = false;
self.addChild(self.numberText);
// Make card interactive
self.interactive = true;
// Set size based on the card
self.width = self.back.width;
self.height = self.back.height;
// Flag to indicate if animation is in progress
self.animating = false;
// Flip card to show front with animation
self.showFront = function () {
if (!self.revealed && !self.animating) {
self.animating = true;
// First half of flip: scale horizontally to 0
tween(self, {
scaleX: 0
}, {
duration: 150,
onFinish: function onFinish() {
// Switch cards at the middle of animation
self.back.visible = false;
self.front.visible = true;
self.numberText.visible = true;
// Second half of flip: scale back from 0 to 1
tween(self, {
scaleX: 1
}, {
duration: 150,
onFinish: function onFinish() {
self.revealed = true;
self.animating = false;
LK.getSound('flip').play();
}
});
}
});
}
};
// Flip card to show back with animation
self.showBack = function () {
if (self.revealed && !self.animating) {
self.animating = true;
// First half of flip: scale horizontally to 0
tween(self, {
scaleX: 0
}, {
duration: 150,
onFinish: function onFinish() {
// Switch cards at the middle of animation
self.back.visible = true;
self.front.visible = false;
self.numberText.visible = false;
// Second half of flip: scale back from 0 to 1
tween(self, {
scaleX: 1
}, {
duration: 150,
onFinish: function onFinish() {
self.revealed = false;
self.animating = false;
}
});
}
});
}
};
self.down = function (x, y, obj) {
// Handle card click
if (gameState.gamePhase === "memorize" && self.canFlip && !self.animating) {
// Create star burst effect at click location
var localPos = {
x: x,
y: y
};
// Fix: use the clicked object's position directly since parent.toGlobal is causing an error
var gamePos = {
x: self.x,
y: self.y
};
// Create and track the particles
var particles = createStarBurst(gamePos.x, gamePos.y);
activeParticles.push(particles);
if (!self.revealed) {
self.showFront();
// Start the countdown timer when the first card is flipped
if (!timerStarted) {
timerStarted = true;
countdownTimer.visible = true;
countdownTimer.reset();
countdownTimer.start();
}
} else {
self.showBack();
}
}
};
return self;
});
var CountdownTimer = Container.expand(function (duration) {
var self = Container.call(this);
// Create circle background
self.circle = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4CAF50
});
self.addChild(self.circle);
// Create text for countdown
self.timeText = new Text2("15", {
size: 80,
fill: 0xFFFFFF
});
self.timeText.anchor.set(0.5, 0.5);
self.addChild(self.timeText);
// Timer properties
self.duration = duration || 15; // Default 15 seconds
self.timeRemaining = self.duration;
self.active = false;
self.timerInterval = null;
// Start the countdown
self.start = function () {
if (self.active) return;
self.active = true;
self.timeRemaining = self.duration;
self.updateDisplay();
self.timerInterval = LK.setInterval(function () {
self.timeRemaining--;
self.updateDisplay();
// Update circle scale based on time remaining
var progress = self.timeRemaining / self.duration;
self.circle.scale.set(progress);
// Change color as time runs out
if (self.timeRemaining <= 5) {
self.circle.tint = 0xFF5252; // Red when time is running out
}
if (self.timeRemaining <= 0) {
self.stop();
if (typeof self.onComplete === 'function') {
self.onComplete();
}
}
}, 1000);
};
// Stop the countdown
self.stop = function () {
if (!self.active) return;
self.active = false;
if (self.timerInterval) {
LK.clearInterval(self.timerInterval);
self.timerInterval = null;
}
};
// Reset the countdown
self.reset = function () {
self.stop();
self.timeRemaining = self.duration;
self.updateDisplay();
self.circle.tint = 0x4CAF50; // Reset to green
self.circle.scale.set(1);
};
// Update the display
self.updateDisplay = function () {
self.timeText.setText(Math.max(0, self.timeRemaining).toString());
};
return self;
});
var QuestionDisplay = Container.expand(function () {
var self = Container.call(this);
self.questionText = new Text2("", {
size: 60,
fill: 0xFFFFFF
});
// Set anchor to center for proper horizontal centering
self.questionText.anchor.set(0.5, 0.5);
self.addChild(self.questionText);
self.setQuestion = function (question) {
// Set the text content
self.questionText.setText(question);
// Reset position to ensure it's centered
self.questionText.x = 0;
self.questionText.y = 0;
};
return self;
});
var StarParticle = Container.expand(function () {
var self = Container.call(this);
// Create a star shape
var star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
// Gold color
scaleX: 0.5 + Math.random() * 0.5,
// Random size for variety
scaleY: 0.5 + Math.random() * 0.5
});
self.addChild(star);
// Add rotation to star
star.rotation = Math.random() * Math.PI * 2; // Random initial rotation
// Set random properties for the particle
self.vx = (Math.random() - 0.5) * 12; // Random x velocity - increased for more dramatic effect
self.vy = (Math.random() - 0.5) * 12; // Random y velocity - increased for more dramatic effect
self.lifespan = 30 + Math.random() * 60; // Random lifespan (0.5-1.5 seconds)
self.rotationSpeed = (Math.random() - 0.5) * 0.2; // Random rotation speed
// Update function for particle movement
self.update = function () {
// Move particle
self.x += self.vx;
self.y += self.vy;
// Apply slight gravity
self.vy += 0.1;
// Rotate star
star.rotation += self.rotationSpeed;
// Decrease lifespan
self.lifespan--;
// Fade out as lifespan decreases
self.alpha = self.lifespan / 90;
// Remove when lifespan is over
if (self.lifespan <= 0) {
if (self.parent) {
self.parent.removeChild(self);
self.destroy(); // Properly destroy the particle
}
return true; // Return true to indicate particle should be removed
}
return false; // Particle should continue to exist
};
return self;
});
/****
* Initialize Game
****/
// Define prototype methods for Button
var game = new LK.Game({
backgroundColor: 0x1A1A2E
});
/****
* Game Code
****/
// Game configuration
// Define prototype methods for Button
Button.prototype.over = function () {
tween(this.background, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 100
});
};
Button.prototype.out = function () {
tween(this.background, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
Button.prototype.down = function () {
tween(this.background, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
Button.prototype.up = function () {
tween(this.background, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
var config = {
totalCards: 52,
cardsPerRound: 4,
initialViewTime: 5000,
// 5 seconds to view cards initially
viewTimeDecrement: 500,
// Reduced by 500ms each level
minViewTime: 1000,
// Minimum viewing time of 1 second
questionTypes: ["highestCard", "lowestCard", "sumOfCards", "specificPosition"]
};
// Game state
var gameState = {
level: storage.currentLevel || 1,
score: 0,
highScore: storage.highScore || 0,
currentDeck: [],
selectedCards: [],
currentQuestion: "",
currentAnswer: null,
gamePhase: "ready",
// ready, memorize, question, result
viewTime: config.initialViewTime
};
// Game elements
var cards = [];
var buttons = [];
var questionDisplay;
var overlay;
var scoreText;
var levelText;
var messageText;
var countdownTimer;
var timerStarted = false;
// Initialize the game
function initGame() {
// Create deck
createDeck();
// Create UI elements
createUI();
// Play background music
LK.playMusic('bgmusic');
// Reset timer state
timerStarted = false;
if (countdownTimer) {
countdownTimer.reset();
countdownTimer.visible = false;
}
// Reset question display
if (questionDisplay) {
questionDisplay.visible = false;
}
// Show welcome screen
showWelcomeScreen();
}
// Create the full deck of cards
function createDeck() {
gameState.currentDeck = [];
for (var i = 1; i <= config.totalCards; i++) {
gameState.currentDeck.push(i);
}
}
// Create UI elements
function createUI() {
// Add background image
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5
});
background.x = 2048 / 2;
background.y = 2732 / 2;
game.addChild(background);
// Create overlay for transitions
overlay = LK.getAsset('overlay', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
overlay.x = 2048 / 2;
overlay.y = 2732 / 2;
game.addChild(overlay);
// Score display removed
// Create level display
levelText = new Text2("Level: 1", {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.x = 2048 * 3 / 4;
levelText.y = 50;
LK.gui.addChild(levelText);
// Create message text
messageText = new Text2("", {
size: 70,
fill: 0xFFFFFF
});
// Set anchor to center for proper horizontal centering
messageText.anchor.set(0.5, 0.5);
// Position text in the center horizontally and near the top
messageText.x = 2048 / 2;
messageText.y = 400;
LK.gui.addChild(messageText);
// Create question display
questionDisplay = new QuestionDisplay();
questionDisplay.x = 2048 / 2;
questionDisplay.y = 800;
game.addChild(questionDisplay);
questionDisplay.visible = false;
// Create countdown timer
countdownTimer = new CountdownTimer(10);
countdownTimer.x = 2048 / 2;
countdownTimer.y = 2732 - 200; // Position at bottom of screen
countdownTimer.visible = false;
countdownTimer.onComplete = function () {
hideCards();
generateQuestion();
};
game.addChild(countdownTimer);
}
// Show welcome screen
function showWelcomeScreen() {
// Clear UI elements to prevent text overlap on restart
if (levelText && levelText.parent) LK.gui.removeChild(levelText);
if (messageText && messageText.parent) LK.gui.removeChild(messageText);
// Clear any previous game elements
for (var i = 0; i < cards.length; i++) {
if (cards[i] && cards[i].parent) {
cards[i].parent.removeChild(cards[i]);
}
}
for (var j = 0; j < buttons.length; j++) {
if (buttons[j] && buttons[j].parent) {
buttons[j].parent.removeChild(buttons[j]);
}
}
// Reset arrays
cards = [];
buttons = [];
// Reset game state
gameState.score = 0;
gameState.level = 1; // Reset level to 1 instead of using stored level
storage.currentLevel = 1; // Also reset the stored level
gameState.gamePhase = "ready"; // Reset game phase to avoid carrying over wrong answer messages
// Hide question display if visible
if (questionDisplay) {
questionDisplay.visible = false;
}
// Recreate UI elements
// Score display removed
// Create level display
levelText = new Text2("Level: " + gameState.level, {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.x = 2048 * 3 / 4;
levelText.y = 50;
LK.gui.addChild(levelText);
// Create message text
messageText = new Text2("", {
size: 70,
fill: 0xFFFFFF
});
// Set anchor to center for proper horizontal centering
messageText.anchor.set(0.5, 0.5);
// Position text in the center horizontally and near the top
messageText.x = 2048 / 2;
messageText.y = 400;
LK.gui.addChild(messageText);
// Clear any previous message
messageText.setText("");
// Create title text with proper size and center it
messageText.setText("Mind Deck\nTest your memory!");
// Calculate the position for perfect centering near the top
messageText.y = 300;
// Create start button
var startButton = new Button("Start Game");
startButton.x = 2048 / 2;
startButton.y = 1200;
game.addChild(startButton);
startButton.down = function () {
Button.prototype.down.call(this);
};
startButton.up = function () {
Button.prototype.up.call(this);
game.removeChild(startButton);
startGame();
};
// Update UI
updateUI();
}
// Start a new game
function startGame() {
// Reset game state if needed
resetRound();
// Start the first round
startRound();
}
// Reset the current round
function resetRound() {
// Clear previous cards
for (var i = 0; i < cards.length; i++) {
if (cards[i].parent) {
cards[i].parent.removeChild(cards[i]);
}
}
cards = [];
// Clear previous buttons
for (var j = 0; j < buttons.length; j++) {
if (buttons[j].parent) {
buttons[j].parent.removeChild(buttons[j]);
}
}
buttons = [];
// Reset game phase
gameState.gamePhase = "ready";
// Calculate view time based on level
gameState.viewTime = Math.max(config.initialViewTime - (gameState.level - 1) * config.viewTimeDecrement, config.minViewTime);
// Clear message text
messageText.setText("");
// Hide question display
questionDisplay.visible = false;
// Reset timer state
timerStarted = false;
countdownTimer.reset();
countdownTimer.visible = false;
// Update UI
updateUI();
}
// Start a new round
function startRound() {
// Clear any previous messages
messageText.setText("");
// Set new message
messageText.setText("Get Ready!");
// Reset timer state to ensure it's properly initialized for the new round
timerStarted = false;
countdownTimer.reset();
countdownTimer.visible = false;
// Fade in
tween(overlay, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
// Draw cards for this round
drawCards();
// Show cards after a short delay
LK.setTimeout(function () {
messageText.setText("Memorize the cards!");
showCards();
}, 1000);
}
});
}
// Draw cards for the round
function drawCards() {
// Shuffle the deck
shuffleDeck();
// Select cards for this round
gameState.selectedCards = gameState.currentDeck.slice(0, config.cardsPerRound);
// Create card objects
var cardWidth = 300;
var spacing = 50;
var totalWidth = cardWidth * config.cardsPerRound + spacing * (config.cardsPerRound - 1);
var startX = (2048 - totalWidth) / 2 + cardWidth / 2;
for (var i = 0; i < config.cardsPerRound; i++) {
var card = new Card(gameState.selectedCards[i]);
card.x = startX + i * (cardWidth + spacing);
card.y = 1200;
game.addChild(card);
cards.push(card);
}
}
// Show cards to memorize
function showCards() {
gameState.gamePhase = "memorize";
// Show message to tell player to click cards
messageText.setText("Click on cards to reveal them!\nCards will disappear in 10 seconds");
// Move message to the left to fit on screen
messageText.x = 2048 / 2 - 200;
// Make all cards clickable but don't flip them automatically
for (var i = 0; i < cards.length; i++) {
cards[i].canFlip = true;
}
// Timer for cards to disappear after 15 seconds
LK.setTimeout(function () {
// Only execute this timeout if the timer hasn't been started (no cards flipped)
if (!timerStarted) {
// Remove cards from game
for (var i = 0; i < cards.length; i++) {
// Create fade out animation for each card
tween(cards[i], {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
// After animation is complete, ensure cards are removed from game
for (var j = 0; j < cards.length; j++) {
if (cards[j].parent) {
cards[j].parent.removeChild(cards[j]);
}
}
}
});
}
// Update message to inform player
messageText.setText("Time's up! Answer the question from memory");
// Automatically transition to question screen if no cards were flipped
hideCards();
generateQuestion();
}
}, 15000); // 15 seconds
}
// Hide cards and prepare question
function hideCards() {
// Stop the countdown timer if it's running
if (timerStarted) {
countdownTimer.stop();
countdownTimer.visible = false;
}
// Disable card flipping for all cards
for (var i = 0; i < cards.length; i++) {
cards[i].canFlip = false;
}
// Animate all cards flipping back with a cascade effect
var allAnimationsComplete = 0;
var totalAnimations = 0;
// Count cards that need to be flipped
for (var i = 0; i < cards.length; i++) {
if (cards[i].revealed) {
totalAnimations++;
}
}
// If no cards are revealed, move directly to question
if (totalAnimations === 0) {
LK.getSound('flip').play();
generateQuestion();
return;
}
// Flip all revealed cards with animation
for (var i = 0; i < cards.length; i++) {
// Use a closure to preserve the i value for each card
(function (index) {
// Only animate revealed cards
if (cards[index].revealed && !cards[index].animating) {
// Set a small delay for each card
var delay = index * 100;
LK.setTimeout(function () {
cards[index].animating = true;
// First half of flip
tween(cards[index], {
scaleX: 0
}, {
duration: 150,
onFinish: function onFinish() {
// Switch cards at the middle of animation
cards[index].back.visible = true;
cards[index].front.visible = false;
cards[index].numberText.visible = false;
// Second half of flip
tween(cards[index], {
scaleX: 1
}, {
duration: 150,
onFinish: function onFinish() {
cards[index].revealed = false;
cards[index].animating = false;
// Track animation completion
allAnimationsComplete++;
// Only play sound once for the last card
if (allAnimationsComplete === totalAnimations) {
LK.getSound('flip').play();
// Generate and display question after all animations complete
generateQuestion();
}
}
});
}
});
}, delay);
}
})(i);
}
// If no cards needed animation, ensure we still generate a question
if (totalAnimations === 0) {
generateQuestion();
}
}
// Generate a question about the cards
function generateQuestion() {
gameState.gamePhase = "question";
// Clear the canvas of any previous questions or elements
for (var i = 0; i < buttons.length; i++) {
if (buttons[i] && buttons[i].parent) {
buttons[i].parent.removeChild(buttons[i]);
}
}
buttons = [];
// Clear previous question display
questionDisplay.setQuestion("");
// Make sure question display is visible and reset
questionDisplay.visible = true;
// Choose random question type
var questionType = config.questionTypes[Math.floor(Math.random() * config.questionTypes.length)];
switch (questionType) {
case "highestCard":
gameState.currentQuestion = "What was the highest card?";
gameState.currentAnswer = Math.max.apply(null, gameState.selectedCards);
createAnswerButtons(gameState.currentAnswer);
break;
case "lowestCard":
gameState.currentQuestion = "What was the lowest card?";
gameState.currentAnswer = Math.min.apply(null, gameState.selectedCards);
createAnswerButtons(gameState.currentAnswer);
break;
case "sumOfCards":
gameState.currentQuestion = "What was the sum of all cards?";
var sum = 0;
for (var i = 0; i < gameState.selectedCards.length; i++) {
sum += gameState.selectedCards[i];
}
gameState.currentAnswer = sum;
createAnswerButtons(gameState.currentAnswer);
break;
case "specificPosition":
var position = Math.floor(Math.random() * config.cardsPerRound);
var positionNames = ["first", "second", "third", "fourth"];
gameState.currentQuestion = "What was the " + positionNames[position] + " card?";
gameState.currentAnswer = gameState.selectedCards[position];
createAnswerButtons(gameState.currentAnswer);
break;
}
// Show question
questionDisplay.setQuestion(gameState.currentQuestion);
questionDisplay.visible = true;
messageText.setText("Answer the question:");
}
// Create answer buttons
function createAnswerButtons(correctAnswer) {
// Generate wrong answers
var answers = [correctAnswer];
while (answers.length < 4) {
var wrongAnswer;
// Generate a reasonable wrong answer based on correct answer
if (correctAnswer <= 10) {
wrongAnswer = Math.floor(Math.random() * 20) + 1;
} else if (correctAnswer <= 52) {
wrongAnswer = Math.floor(Math.random() * 52) + 1;
} else {
// For sums or other large numbers
var variance = Math.floor(correctAnswer * 0.3);
wrongAnswer = correctAnswer + Math.floor(Math.random() * variance * 2) - variance;
wrongAnswer = Math.max(1, wrongAnswer);
}
// Make sure we don't add duplicates
if (answers.indexOf(wrongAnswer) === -1) {
answers.push(wrongAnswer);
}
}
// Shuffle answers
shuffleArray(answers);
// Create buttons
var buttonWidth = 400;
var spacing = 50;
var totalWidth = buttonWidth * 2 + spacing;
var startX = (2048 - totalWidth) / 2 + buttonWidth / 2;
for (var i = 0; i < answers.length; i++) {
var button = new Button(answers[i].toString());
// Position buttons in a 2x2 grid
var row = Math.floor(i / 2);
var col = i % 2;
button.x = startX + col * (buttonWidth + spacing);
button.y = 1500 + row * 150;
// Store the answer value
button.answerValue = answers[i];
// Set up button handlers
button.down = function () {
Button.prototype.down.call(this);
};
button.up = function () {
Button.prototype.up.call(this);
checkAnswer(this.answerValue);
};
game.addChild(button);
buttons.push(button);
}
}
// Check if the answer is correct
function checkAnswer(answer) {
gameState.gamePhase = "result";
// Hide question
questionDisplay.visible = false;
// Clear all current elements from the canvas
for (var i = 0; i < cards.length; i++) {
if (cards[i] && cards[i].parent) {
cards[i].parent.removeChild(cards[i]);
}
}
cards = []; // Clear cards array completely
for (var j = 0; j < buttons.length; j++) {
if (buttons[j] && buttons[j].parent) {
buttons[j].parent.removeChild(buttons[j]);
}
}
buttons = []; // Clear buttons array completely
// Reset all active particles
for (var k = activeParticles.length - 1; k >= 0; k--) {
var particles = activeParticles[k];
for (var l = particles.length - 1; l >= 0; l--) {
if (particles[l] && particles[l].parent) {
particles[l].parent.removeChild(particles[l]);
}
}
}
activeParticles = []; // Clear all particles
// Check if correct
if (answer === gameState.currentAnswer) {
// Correct answer!
messageText.setText("Correct!");
// Update score
gameState.score += gameState.level * 10;
// Update UI immediately to reflect score change
updateUI();
// Play correct sound
LK.getSound('correct').play();
// Move to next level after delay
LK.setTimeout(function () {
gameState.level++;
storage.currentLevel = gameState.level;
// Update high score if needed
if (gameState.score > gameState.highScore) {
gameState.highScore = gameState.score;
storage.highScore = gameState.highScore;
}
// Play level up sound
LK.getSound('levelUp').play();
// Ensure all state variables are properly reset
timerStarted = false;
countdownTimer.reset();
countdownTimer.visible = false;
// Clear any previous wrong answer messages
messageText.setText("");
// Update UI again after level change
updateUI();
// Start next round
resetRound();
startRound();
}, 1500);
} else {
// Wrong answer
messageText.setText("Wrong! The correct answer was " + gameState.currentAnswer);
// Play wrong sound
LK.getSound('wrong').play();
// Auto-hide wrong answer message after 1 second
LK.setTimeout(function () {
messageText.setText("");
}, 1000);
// Show game over after delay
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
}
}
// Update UI elements
function updateUI() {
levelText.setText("Level: " + gameState.level);
}
// Shuffle the deck
function shuffleDeck() {
shuffleArray(gameState.currentDeck);
}
// Fisher-Yates shuffle algorithm
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;
}
// Function to create a burst of stars at a specific position
function createStarBurst(x, y) {
var particles = [];
var numParticles = 15 + Math.floor(Math.random() * 10); // 15-25 particles for more impressive effect
var colors = [0xFFD700, 0xFFA500, 0xFF8C00, 0xFFFF00, 0xFAFAD2]; // Gold, orange, dark orange, yellow, light yellow
// Create particles
for (var i = 0; i < numParticles; i++) {
var particle = new StarParticle();
particle.x = x;
particle.y = y;
// Apply random color from our palette
var randomColor = colors[Math.floor(Math.random() * colors.length)];
// Get the star child and tint it
if (particle.children && particle.children[0]) {
particle.children[0].tint = randomColor;
}
game.addChild(particle);
particles.push(particle);
}
return particles;
}
// Array to store active particle systems
var activeParticles = [];
// Game update loop
game.update = function () {
// Update all active particles
for (var i = activeParticles.length - 1; i >= 0; i--) {
var particleSystem = activeParticles[i];
var removeCount = 0;
for (var j = particleSystem.length - 1; j >= 0; j--) {
var particle = particleSystem[j];
if (particle.update()) {
particleSystem.splice(j, 1);
removeCount++;
}
}
// Remove empty particle systems
if (particleSystem.length === 0) {
activeParticles.splice(i, 1);
}
}
};
// Handle drag and drop
game.down = function (x, y, obj) {
// Nothing needed for this game
};
game.up = function (x, y, obj) {
// Nothing needed for this game
};
game.move = function (x, y, obj) {
// Nothing needed for this game
};
// Initialize the game
initGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
currentLevel: 1
});
/****
* Classes
****/
var Button = Container.expand(function (text) {
var self = Container.call(this);
self.background = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
self.label = new Text2(text || "Button", {
size: 50,
fill: 0xFFFFFF
});
self.label.anchor.set(0.5, 0.5);
self.addChild(self.label);
// Set interactive
self.interactive = true;
return self;
});
// Define prototype methods for Button
var Card = Container.expand(function (cardNumber) {
var self = Container.call(this);
self.cardNumber = cardNumber || 0;
self.revealed = false;
self.matched = false;
self.canFlip = false; // Flag to control when cards can be flipped
// Card back (shown initially)
self.back = self.attachAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5
});
// Card front (shown when flipped)
self.front = self.attachAsset('cardFront', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
});
// Card number text
self.numberText = new Text2(self.cardNumber.toString(), {
size: 100,
fill: 0x000000
});
self.numberText.anchor.set(0.5, 0.5);
self.numberText.visible = false;
self.addChild(self.numberText);
// Make card interactive
self.interactive = true;
// Set size based on the card
self.width = self.back.width;
self.height = self.back.height;
// Flag to indicate if animation is in progress
self.animating = false;
// Flip card to show front with animation
self.showFront = function () {
if (!self.revealed && !self.animating) {
self.animating = true;
// First half of flip: scale horizontally to 0
tween(self, {
scaleX: 0
}, {
duration: 150,
onFinish: function onFinish() {
// Switch cards at the middle of animation
self.back.visible = false;
self.front.visible = true;
self.numberText.visible = true;
// Second half of flip: scale back from 0 to 1
tween(self, {
scaleX: 1
}, {
duration: 150,
onFinish: function onFinish() {
self.revealed = true;
self.animating = false;
LK.getSound('flip').play();
}
});
}
});
}
};
// Flip card to show back with animation
self.showBack = function () {
if (self.revealed && !self.animating) {
self.animating = true;
// First half of flip: scale horizontally to 0
tween(self, {
scaleX: 0
}, {
duration: 150,
onFinish: function onFinish() {
// Switch cards at the middle of animation
self.back.visible = true;
self.front.visible = false;
self.numberText.visible = false;
// Second half of flip: scale back from 0 to 1
tween(self, {
scaleX: 1
}, {
duration: 150,
onFinish: function onFinish() {
self.revealed = false;
self.animating = false;
}
});
}
});
}
};
self.down = function (x, y, obj) {
// Handle card click
if (gameState.gamePhase === "memorize" && self.canFlip && !self.animating) {
// Create star burst effect at click location
var localPos = {
x: x,
y: y
};
// Fix: use the clicked object's position directly since parent.toGlobal is causing an error
var gamePos = {
x: self.x,
y: self.y
};
// Create and track the particles
var particles = createStarBurst(gamePos.x, gamePos.y);
activeParticles.push(particles);
if (!self.revealed) {
self.showFront();
// Start the countdown timer when the first card is flipped
if (!timerStarted) {
timerStarted = true;
countdownTimer.visible = true;
countdownTimer.reset();
countdownTimer.start();
}
} else {
self.showBack();
}
}
};
return self;
});
var CountdownTimer = Container.expand(function (duration) {
var self = Container.call(this);
// Create circle background
self.circle = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4CAF50
});
self.addChild(self.circle);
// Create text for countdown
self.timeText = new Text2("15", {
size: 80,
fill: 0xFFFFFF
});
self.timeText.anchor.set(0.5, 0.5);
self.addChild(self.timeText);
// Timer properties
self.duration = duration || 15; // Default 15 seconds
self.timeRemaining = self.duration;
self.active = false;
self.timerInterval = null;
// Start the countdown
self.start = function () {
if (self.active) return;
self.active = true;
self.timeRemaining = self.duration;
self.updateDisplay();
self.timerInterval = LK.setInterval(function () {
self.timeRemaining--;
self.updateDisplay();
// Update circle scale based on time remaining
var progress = self.timeRemaining / self.duration;
self.circle.scale.set(progress);
// Change color as time runs out
if (self.timeRemaining <= 5) {
self.circle.tint = 0xFF5252; // Red when time is running out
}
if (self.timeRemaining <= 0) {
self.stop();
if (typeof self.onComplete === 'function') {
self.onComplete();
}
}
}, 1000);
};
// Stop the countdown
self.stop = function () {
if (!self.active) return;
self.active = false;
if (self.timerInterval) {
LK.clearInterval(self.timerInterval);
self.timerInterval = null;
}
};
// Reset the countdown
self.reset = function () {
self.stop();
self.timeRemaining = self.duration;
self.updateDisplay();
self.circle.tint = 0x4CAF50; // Reset to green
self.circle.scale.set(1);
};
// Update the display
self.updateDisplay = function () {
self.timeText.setText(Math.max(0, self.timeRemaining).toString());
};
return self;
});
var QuestionDisplay = Container.expand(function () {
var self = Container.call(this);
self.questionText = new Text2("", {
size: 60,
fill: 0xFFFFFF
});
// Set anchor to center for proper horizontal centering
self.questionText.anchor.set(0.5, 0.5);
self.addChild(self.questionText);
self.setQuestion = function (question) {
// Set the text content
self.questionText.setText(question);
// Reset position to ensure it's centered
self.questionText.x = 0;
self.questionText.y = 0;
};
return self;
});
var StarParticle = Container.expand(function () {
var self = Container.call(this);
// Create a star shape
var star = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700,
// Gold color
scaleX: 0.5 + Math.random() * 0.5,
// Random size for variety
scaleY: 0.5 + Math.random() * 0.5
});
self.addChild(star);
// Add rotation to star
star.rotation = Math.random() * Math.PI * 2; // Random initial rotation
// Set random properties for the particle
self.vx = (Math.random() - 0.5) * 12; // Random x velocity - increased for more dramatic effect
self.vy = (Math.random() - 0.5) * 12; // Random y velocity - increased for more dramatic effect
self.lifespan = 30 + Math.random() * 60; // Random lifespan (0.5-1.5 seconds)
self.rotationSpeed = (Math.random() - 0.5) * 0.2; // Random rotation speed
// Update function for particle movement
self.update = function () {
// Move particle
self.x += self.vx;
self.y += self.vy;
// Apply slight gravity
self.vy += 0.1;
// Rotate star
star.rotation += self.rotationSpeed;
// Decrease lifespan
self.lifespan--;
// Fade out as lifespan decreases
self.alpha = self.lifespan / 90;
// Remove when lifespan is over
if (self.lifespan <= 0) {
if (self.parent) {
self.parent.removeChild(self);
self.destroy(); // Properly destroy the particle
}
return true; // Return true to indicate particle should be removed
}
return false; // Particle should continue to exist
};
return self;
});
/****
* Initialize Game
****/
// Define prototype methods for Button
var game = new LK.Game({
backgroundColor: 0x1A1A2E
});
/****
* Game Code
****/
// Game configuration
// Define prototype methods for Button
Button.prototype.over = function () {
tween(this.background, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 100
});
};
Button.prototype.out = function () {
tween(this.background, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
Button.prototype.down = function () {
tween(this.background, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
Button.prototype.up = function () {
tween(this.background, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
var config = {
totalCards: 52,
cardsPerRound: 4,
initialViewTime: 5000,
// 5 seconds to view cards initially
viewTimeDecrement: 500,
// Reduced by 500ms each level
minViewTime: 1000,
// Minimum viewing time of 1 second
questionTypes: ["highestCard", "lowestCard", "sumOfCards", "specificPosition"]
};
// Game state
var gameState = {
level: storage.currentLevel || 1,
score: 0,
highScore: storage.highScore || 0,
currentDeck: [],
selectedCards: [],
currentQuestion: "",
currentAnswer: null,
gamePhase: "ready",
// ready, memorize, question, result
viewTime: config.initialViewTime
};
// Game elements
var cards = [];
var buttons = [];
var questionDisplay;
var overlay;
var scoreText;
var levelText;
var messageText;
var countdownTimer;
var timerStarted = false;
// Initialize the game
function initGame() {
// Create deck
createDeck();
// Create UI elements
createUI();
// Play background music
LK.playMusic('bgmusic');
// Reset timer state
timerStarted = false;
if (countdownTimer) {
countdownTimer.reset();
countdownTimer.visible = false;
}
// Reset question display
if (questionDisplay) {
questionDisplay.visible = false;
}
// Show welcome screen
showWelcomeScreen();
}
// Create the full deck of cards
function createDeck() {
gameState.currentDeck = [];
for (var i = 1; i <= config.totalCards; i++) {
gameState.currentDeck.push(i);
}
}
// Create UI elements
function createUI() {
// Add background image
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5
});
background.x = 2048 / 2;
background.y = 2732 / 2;
game.addChild(background);
// Create overlay for transitions
overlay = LK.getAsset('overlay', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
overlay.x = 2048 / 2;
overlay.y = 2732 / 2;
game.addChild(overlay);
// Score display removed
// Create level display
levelText = new Text2("Level: 1", {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.x = 2048 * 3 / 4;
levelText.y = 50;
LK.gui.addChild(levelText);
// Create message text
messageText = new Text2("", {
size: 70,
fill: 0xFFFFFF
});
// Set anchor to center for proper horizontal centering
messageText.anchor.set(0.5, 0.5);
// Position text in the center horizontally and near the top
messageText.x = 2048 / 2;
messageText.y = 400;
LK.gui.addChild(messageText);
// Create question display
questionDisplay = new QuestionDisplay();
questionDisplay.x = 2048 / 2;
questionDisplay.y = 800;
game.addChild(questionDisplay);
questionDisplay.visible = false;
// Create countdown timer
countdownTimer = new CountdownTimer(10);
countdownTimer.x = 2048 / 2;
countdownTimer.y = 2732 - 200; // Position at bottom of screen
countdownTimer.visible = false;
countdownTimer.onComplete = function () {
hideCards();
generateQuestion();
};
game.addChild(countdownTimer);
}
// Show welcome screen
function showWelcomeScreen() {
// Clear UI elements to prevent text overlap on restart
if (levelText && levelText.parent) LK.gui.removeChild(levelText);
if (messageText && messageText.parent) LK.gui.removeChild(messageText);
// Clear any previous game elements
for (var i = 0; i < cards.length; i++) {
if (cards[i] && cards[i].parent) {
cards[i].parent.removeChild(cards[i]);
}
}
for (var j = 0; j < buttons.length; j++) {
if (buttons[j] && buttons[j].parent) {
buttons[j].parent.removeChild(buttons[j]);
}
}
// Reset arrays
cards = [];
buttons = [];
// Reset game state
gameState.score = 0;
gameState.level = 1; // Reset level to 1 instead of using stored level
storage.currentLevel = 1; // Also reset the stored level
gameState.gamePhase = "ready"; // Reset game phase to avoid carrying over wrong answer messages
// Hide question display if visible
if (questionDisplay) {
questionDisplay.visible = false;
}
// Recreate UI elements
// Score display removed
// Create level display
levelText = new Text2("Level: " + gameState.level, {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.x = 2048 * 3 / 4;
levelText.y = 50;
LK.gui.addChild(levelText);
// Create message text
messageText = new Text2("", {
size: 70,
fill: 0xFFFFFF
});
// Set anchor to center for proper horizontal centering
messageText.anchor.set(0.5, 0.5);
// Position text in the center horizontally and near the top
messageText.x = 2048 / 2;
messageText.y = 400;
LK.gui.addChild(messageText);
// Clear any previous message
messageText.setText("");
// Create title text with proper size and center it
messageText.setText("Mind Deck\nTest your memory!");
// Calculate the position for perfect centering near the top
messageText.y = 300;
// Create start button
var startButton = new Button("Start Game");
startButton.x = 2048 / 2;
startButton.y = 1200;
game.addChild(startButton);
startButton.down = function () {
Button.prototype.down.call(this);
};
startButton.up = function () {
Button.prototype.up.call(this);
game.removeChild(startButton);
startGame();
};
// Update UI
updateUI();
}
// Start a new game
function startGame() {
// Reset game state if needed
resetRound();
// Start the first round
startRound();
}
// Reset the current round
function resetRound() {
// Clear previous cards
for (var i = 0; i < cards.length; i++) {
if (cards[i].parent) {
cards[i].parent.removeChild(cards[i]);
}
}
cards = [];
// Clear previous buttons
for (var j = 0; j < buttons.length; j++) {
if (buttons[j].parent) {
buttons[j].parent.removeChild(buttons[j]);
}
}
buttons = [];
// Reset game phase
gameState.gamePhase = "ready";
// Calculate view time based on level
gameState.viewTime = Math.max(config.initialViewTime - (gameState.level - 1) * config.viewTimeDecrement, config.minViewTime);
// Clear message text
messageText.setText("");
// Hide question display
questionDisplay.visible = false;
// Reset timer state
timerStarted = false;
countdownTimer.reset();
countdownTimer.visible = false;
// Update UI
updateUI();
}
// Start a new round
function startRound() {
// Clear any previous messages
messageText.setText("");
// Set new message
messageText.setText("Get Ready!");
// Reset timer state to ensure it's properly initialized for the new round
timerStarted = false;
countdownTimer.reset();
countdownTimer.visible = false;
// Fade in
tween(overlay, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
// Draw cards for this round
drawCards();
// Show cards after a short delay
LK.setTimeout(function () {
messageText.setText("Memorize the cards!");
showCards();
}, 1000);
}
});
}
// Draw cards for the round
function drawCards() {
// Shuffle the deck
shuffleDeck();
// Select cards for this round
gameState.selectedCards = gameState.currentDeck.slice(0, config.cardsPerRound);
// Create card objects
var cardWidth = 300;
var spacing = 50;
var totalWidth = cardWidth * config.cardsPerRound + spacing * (config.cardsPerRound - 1);
var startX = (2048 - totalWidth) / 2 + cardWidth / 2;
for (var i = 0; i < config.cardsPerRound; i++) {
var card = new Card(gameState.selectedCards[i]);
card.x = startX + i * (cardWidth + spacing);
card.y = 1200;
game.addChild(card);
cards.push(card);
}
}
// Show cards to memorize
function showCards() {
gameState.gamePhase = "memorize";
// Show message to tell player to click cards
messageText.setText("Click on cards to reveal them!\nCards will disappear in 10 seconds");
// Move message to the left to fit on screen
messageText.x = 2048 / 2 - 200;
// Make all cards clickable but don't flip them automatically
for (var i = 0; i < cards.length; i++) {
cards[i].canFlip = true;
}
// Timer for cards to disappear after 15 seconds
LK.setTimeout(function () {
// Only execute this timeout if the timer hasn't been started (no cards flipped)
if (!timerStarted) {
// Remove cards from game
for (var i = 0; i < cards.length; i++) {
// Create fade out animation for each card
tween(cards[i], {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
// After animation is complete, ensure cards are removed from game
for (var j = 0; j < cards.length; j++) {
if (cards[j].parent) {
cards[j].parent.removeChild(cards[j]);
}
}
}
});
}
// Update message to inform player
messageText.setText("Time's up! Answer the question from memory");
// Automatically transition to question screen if no cards were flipped
hideCards();
generateQuestion();
}
}, 15000); // 15 seconds
}
// Hide cards and prepare question
function hideCards() {
// Stop the countdown timer if it's running
if (timerStarted) {
countdownTimer.stop();
countdownTimer.visible = false;
}
// Disable card flipping for all cards
for (var i = 0; i < cards.length; i++) {
cards[i].canFlip = false;
}
// Animate all cards flipping back with a cascade effect
var allAnimationsComplete = 0;
var totalAnimations = 0;
// Count cards that need to be flipped
for (var i = 0; i < cards.length; i++) {
if (cards[i].revealed) {
totalAnimations++;
}
}
// If no cards are revealed, move directly to question
if (totalAnimations === 0) {
LK.getSound('flip').play();
generateQuestion();
return;
}
// Flip all revealed cards with animation
for (var i = 0; i < cards.length; i++) {
// Use a closure to preserve the i value for each card
(function (index) {
// Only animate revealed cards
if (cards[index].revealed && !cards[index].animating) {
// Set a small delay for each card
var delay = index * 100;
LK.setTimeout(function () {
cards[index].animating = true;
// First half of flip
tween(cards[index], {
scaleX: 0
}, {
duration: 150,
onFinish: function onFinish() {
// Switch cards at the middle of animation
cards[index].back.visible = true;
cards[index].front.visible = false;
cards[index].numberText.visible = false;
// Second half of flip
tween(cards[index], {
scaleX: 1
}, {
duration: 150,
onFinish: function onFinish() {
cards[index].revealed = false;
cards[index].animating = false;
// Track animation completion
allAnimationsComplete++;
// Only play sound once for the last card
if (allAnimationsComplete === totalAnimations) {
LK.getSound('flip').play();
// Generate and display question after all animations complete
generateQuestion();
}
}
});
}
});
}, delay);
}
})(i);
}
// If no cards needed animation, ensure we still generate a question
if (totalAnimations === 0) {
generateQuestion();
}
}
// Generate a question about the cards
function generateQuestion() {
gameState.gamePhase = "question";
// Clear the canvas of any previous questions or elements
for (var i = 0; i < buttons.length; i++) {
if (buttons[i] && buttons[i].parent) {
buttons[i].parent.removeChild(buttons[i]);
}
}
buttons = [];
// Clear previous question display
questionDisplay.setQuestion("");
// Make sure question display is visible and reset
questionDisplay.visible = true;
// Choose random question type
var questionType = config.questionTypes[Math.floor(Math.random() * config.questionTypes.length)];
switch (questionType) {
case "highestCard":
gameState.currentQuestion = "What was the highest card?";
gameState.currentAnswer = Math.max.apply(null, gameState.selectedCards);
createAnswerButtons(gameState.currentAnswer);
break;
case "lowestCard":
gameState.currentQuestion = "What was the lowest card?";
gameState.currentAnswer = Math.min.apply(null, gameState.selectedCards);
createAnswerButtons(gameState.currentAnswer);
break;
case "sumOfCards":
gameState.currentQuestion = "What was the sum of all cards?";
var sum = 0;
for (var i = 0; i < gameState.selectedCards.length; i++) {
sum += gameState.selectedCards[i];
}
gameState.currentAnswer = sum;
createAnswerButtons(gameState.currentAnswer);
break;
case "specificPosition":
var position = Math.floor(Math.random() * config.cardsPerRound);
var positionNames = ["first", "second", "third", "fourth"];
gameState.currentQuestion = "What was the " + positionNames[position] + " card?";
gameState.currentAnswer = gameState.selectedCards[position];
createAnswerButtons(gameState.currentAnswer);
break;
}
// Show question
questionDisplay.setQuestion(gameState.currentQuestion);
questionDisplay.visible = true;
messageText.setText("Answer the question:");
}
// Create answer buttons
function createAnswerButtons(correctAnswer) {
// Generate wrong answers
var answers = [correctAnswer];
while (answers.length < 4) {
var wrongAnswer;
// Generate a reasonable wrong answer based on correct answer
if (correctAnswer <= 10) {
wrongAnswer = Math.floor(Math.random() * 20) + 1;
} else if (correctAnswer <= 52) {
wrongAnswer = Math.floor(Math.random() * 52) + 1;
} else {
// For sums or other large numbers
var variance = Math.floor(correctAnswer * 0.3);
wrongAnswer = correctAnswer + Math.floor(Math.random() * variance * 2) - variance;
wrongAnswer = Math.max(1, wrongAnswer);
}
// Make sure we don't add duplicates
if (answers.indexOf(wrongAnswer) === -1) {
answers.push(wrongAnswer);
}
}
// Shuffle answers
shuffleArray(answers);
// Create buttons
var buttonWidth = 400;
var spacing = 50;
var totalWidth = buttonWidth * 2 + spacing;
var startX = (2048 - totalWidth) / 2 + buttonWidth / 2;
for (var i = 0; i < answers.length; i++) {
var button = new Button(answers[i].toString());
// Position buttons in a 2x2 grid
var row = Math.floor(i / 2);
var col = i % 2;
button.x = startX + col * (buttonWidth + spacing);
button.y = 1500 + row * 150;
// Store the answer value
button.answerValue = answers[i];
// Set up button handlers
button.down = function () {
Button.prototype.down.call(this);
};
button.up = function () {
Button.prototype.up.call(this);
checkAnswer(this.answerValue);
};
game.addChild(button);
buttons.push(button);
}
}
// Check if the answer is correct
function checkAnswer(answer) {
gameState.gamePhase = "result";
// Hide question
questionDisplay.visible = false;
// Clear all current elements from the canvas
for (var i = 0; i < cards.length; i++) {
if (cards[i] && cards[i].parent) {
cards[i].parent.removeChild(cards[i]);
}
}
cards = []; // Clear cards array completely
for (var j = 0; j < buttons.length; j++) {
if (buttons[j] && buttons[j].parent) {
buttons[j].parent.removeChild(buttons[j]);
}
}
buttons = []; // Clear buttons array completely
// Reset all active particles
for (var k = activeParticles.length - 1; k >= 0; k--) {
var particles = activeParticles[k];
for (var l = particles.length - 1; l >= 0; l--) {
if (particles[l] && particles[l].parent) {
particles[l].parent.removeChild(particles[l]);
}
}
}
activeParticles = []; // Clear all particles
// Check if correct
if (answer === gameState.currentAnswer) {
// Correct answer!
messageText.setText("Correct!");
// Update score
gameState.score += gameState.level * 10;
// Update UI immediately to reflect score change
updateUI();
// Play correct sound
LK.getSound('correct').play();
// Move to next level after delay
LK.setTimeout(function () {
gameState.level++;
storage.currentLevel = gameState.level;
// Update high score if needed
if (gameState.score > gameState.highScore) {
gameState.highScore = gameState.score;
storage.highScore = gameState.highScore;
}
// Play level up sound
LK.getSound('levelUp').play();
// Ensure all state variables are properly reset
timerStarted = false;
countdownTimer.reset();
countdownTimer.visible = false;
// Clear any previous wrong answer messages
messageText.setText("");
// Update UI again after level change
updateUI();
// Start next round
resetRound();
startRound();
}, 1500);
} else {
// Wrong answer
messageText.setText("Wrong! The correct answer was " + gameState.currentAnswer);
// Play wrong sound
LK.getSound('wrong').play();
// Auto-hide wrong answer message after 1 second
LK.setTimeout(function () {
messageText.setText("");
}, 1000);
// Show game over after delay
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
}
}
// Update UI elements
function updateUI() {
levelText.setText("Level: " + gameState.level);
}
// Shuffle the deck
function shuffleDeck() {
shuffleArray(gameState.currentDeck);
}
// Fisher-Yates shuffle algorithm
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;
}
// Function to create a burst of stars at a specific position
function createStarBurst(x, y) {
var particles = [];
var numParticles = 15 + Math.floor(Math.random() * 10); // 15-25 particles for more impressive effect
var colors = [0xFFD700, 0xFFA500, 0xFF8C00, 0xFFFF00, 0xFAFAD2]; // Gold, orange, dark orange, yellow, light yellow
// Create particles
for (var i = 0; i < numParticles; i++) {
var particle = new StarParticle();
particle.x = x;
particle.y = y;
// Apply random color from our palette
var randomColor = colors[Math.floor(Math.random() * colors.length)];
// Get the star child and tint it
if (particle.children && particle.children[0]) {
particle.children[0].tint = randomColor;
}
game.addChild(particle);
particles.push(particle);
}
return particles;
}
// Array to store active particle systems
var activeParticles = [];
// Game update loop
game.update = function () {
// Update all active particles
for (var i = activeParticles.length - 1; i >= 0; i--) {
var particleSystem = activeParticles[i];
var removeCount = 0;
for (var j = particleSystem.length - 1; j >= 0; j--) {
var particle = particleSystem[j];
if (particle.update()) {
particleSystem.splice(j, 1);
removeCount++;
}
}
// Remove empty particle systems
if (particleSystem.length === 0) {
activeParticles.splice(i, 1);
}
}
};
// Handle drag and drop
game.down = function (x, y, obj) {
// Nothing needed for this game
};
game.up = function (x, y, obj) {
// Nothing needed for this game
};
game.move = function (x, y, obj) {
// Nothing needed for this game
};
// Initialize the game
initGame();