/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var Card = Container.expand(function () { var self = Container.call(this); self.isFlipped = false; self.isActive = false; self.cardIndex = 0; self.init = function (index) { self.cardIndex = index; // Create card back self.cardBack = self.attachAsset('cardBack', { anchorX: 0.5, anchorY: 0.5 }); // Create card front (hidden initially) var frontAssetName = 'cardFront' + (index + 1); self.cardFront = self.attachAsset(frontAssetName, { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Create character on front var characterAssetName = 'character' + (index + 1); self.character = self.attachAsset(characterAssetName, { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Add question mark text on card back self.questionMark = new Text2('?', { size: 120, fill: 0xFFFFFF }); self.questionMark.anchor.set(0.5, 0.5); self.addChild(self.questionMark); }; self.flipCard = function () { if (self.isFlipped) return; self.isFlipped = true; // Play flip sound LK.getSound('cardFlip').play(); // Flip animation tween(self.cardBack, { scaleX: 0 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { self.cardBack.alpha = 0; self.questionMark.alpha = 0; self.cardFront.alpha = 1; self.character.alpha = 1; tween(self.cardFront, { scaleX: 1 }, { duration: 300, easing: tween.easeInOut }); tween(self.character, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.bounceOut }); // Flash effect LK.effects.flashObject(self, 0xFFFFFF, 500); } }); tween(self.questionMark, { scaleX: 0 }, { duration: 300, easing: tween.easeInOut }); }; self.down = function (x, y, obj) { if (self.isActive && !self.isFlipped && waitingForInput) { handleCardOpen(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2C3E50 }); /**** * Game Code ****/ var cards = []; var currentCardIndex = 0; var gameState = 'waiting'; // 'waiting', 'countdown', 'input', 'flipping', 'completed' var countdownTimer = null; var inputTimer = null; var waitingForInput = false; var countdownCount = 3; // UI Elements var instructionText = new Text2('Ready to open a card?', { size: 80, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); LK.gui.top.addChild(instructionText); instructionText.y = 150; var countdownText = new Text2('', { size: 120, fill: 0xFFD700 }); countdownText.anchor.set(0.5, 0.5); LK.gui.center.addChild(countdownText); var promptText = new Text2('', { size: 60, fill: 0x00FF00 }); promptText.anchor.set(0.5, 0.5); LK.gui.bottom.addChild(promptText); promptText.y = -200; // Create and position cards function initializeCards() { var cardSpacing = 350; var startX = (2048 - 4 * cardSpacing) / 2; var topRowY = 1366 - 300; var bottomRowY = 1366 + 100; for (var i = 0; i < 5; i++) { var card = new Card(); card.init(i); if (i < 3) { // Top row card.x = startX + i * cardSpacing; card.y = topRowY; } else { // Bottom row card.x = startX + (i - 3) * cardSpacing + cardSpacing / 2; card.y = bottomRowY; } cards.push(card); game.addChild(card); } // Make first card active cards[0].isActive = true; tween(cards[0], { scaleX: 1.1, scaleY: 1.1 }, { duration: 500, easing: tween.easeInOut }); } function startCountdown() { gameState = 'countdown'; countdownCount = 3; instructionText.setText('Get ready...'); function doCountdown() { if (countdownCount > 0) { countdownText.setText(countdownCount.toString()); LK.getSound('countdown').play(); countdownCount--; countdownTimer = LK.setTimeout(doCountdown, 1000); } else { countdownText.setText(''); startInputPhase(); } } doCountdown(); } function startInputPhase() { gameState = 'input'; waitingForInput = true; instructionText.setText('Say "Open the card!" or tap the card!'); promptText.setText('NOW!'); // Give player 3 seconds to respond inputTimer = LK.setTimeout(function () { if (waitingForInput) { waitingForInput = false; promptText.setText('Too slow! Try again...'); LK.setTimeout(function () { if (gameState !== 'completed') { resetForNextAttempt(); } }, 2000); } }, 3000); } function handleCardOpen() { if (!waitingForInput) return; waitingForInput = false; gameState = 'flipping'; if (inputTimer) { LK.clearTimeout(inputTimer); inputTimer = null; } instructionText.setText('Great job!'); promptText.setText(''); countdownText.setText(''); // Play success sound LK.getSound('success').play(); // Flip the current card cards[currentCardIndex].flipCard(); // Move to next card after delay LK.setTimeout(function () { currentCardIndex++; if (currentCardIndex >= cards.length) { // All cards opened gameState = 'completed'; instructionText.setText('Amazing! All cards opened!'); // Celebrate with screen flash LK.effects.flashScreen(0xFFD700, 2000); // Scale all cards for celebration for (var i = 0; i < cards.length; i++) { tween(cards[i], { scaleX: 1.2, scaleY: 1.2 }, { duration: 1000, easing: tween.bounceOut }); } } else { // Activate next card cards[currentCardIndex].isActive = true; tween(cards[currentCardIndex], { scaleX: 1.1, scaleY: 1.1 }, { duration: 500, easing: tween.easeInOut }); // Reset for next card LK.setTimeout(resetForNextAttempt, 1500); } }, 2000); } function resetForNextAttempt() { if (gameState === 'completed') return; gameState = 'waiting'; instructionText.setText('Ready for the next card?'); promptText.setText(''); countdownText.setText(''); LK.setTimeout(function () { if (gameState === 'waiting') { startCountdown(); } }, 2000); } // Voice detection var lastVoiceCheck = false; game.update = function () { // Check for voice input during input phase if (waitingForInput && facekit.volume > 0.3) { if (!lastVoiceCheck) { // Voice just started handleCardOpen(); } } lastVoiceCheck = facekit.volume > 0.3; }; // Touch input for starting the game game.down = function (x, y, obj) { if (gameState === 'waiting' && currentCardIndex === 0 && !cards[0].isFlipped) { startCountdown(); } }; // Initialize the game initializeCards();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Card = Container.expand(function () {
var self = Container.call(this);
self.isFlipped = false;
self.isActive = false;
self.cardIndex = 0;
self.init = function (index) {
self.cardIndex = index;
// Create card back
self.cardBack = self.attachAsset('cardBack', {
anchorX: 0.5,
anchorY: 0.5
});
// Create card front (hidden initially)
var frontAssetName = 'cardFront' + (index + 1);
self.cardFront = self.attachAsset(frontAssetName, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Create character on front
var characterAssetName = 'character' + (index + 1);
self.character = self.attachAsset(characterAssetName, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Add question mark text on card back
self.questionMark = new Text2('?', {
size: 120,
fill: 0xFFFFFF
});
self.questionMark.anchor.set(0.5, 0.5);
self.addChild(self.questionMark);
};
self.flipCard = function () {
if (self.isFlipped) return;
self.isFlipped = true;
// Play flip sound
LK.getSound('cardFlip').play();
// Flip animation
tween(self.cardBack, {
scaleX: 0
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.cardBack.alpha = 0;
self.questionMark.alpha = 0;
self.cardFront.alpha = 1;
self.character.alpha = 1;
tween(self.cardFront, {
scaleX: 1
}, {
duration: 300,
easing: tween.easeInOut
});
tween(self.character, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.bounceOut
});
// Flash effect
LK.effects.flashObject(self, 0xFFFFFF, 500);
}
});
tween(self.questionMark, {
scaleX: 0
}, {
duration: 300,
easing: tween.easeInOut
});
};
self.down = function (x, y, obj) {
if (self.isActive && !self.isFlipped && waitingForInput) {
handleCardOpen();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2C3E50
});
/****
* Game Code
****/
var cards = [];
var currentCardIndex = 0;
var gameState = 'waiting'; // 'waiting', 'countdown', 'input', 'flipping', 'completed'
var countdownTimer = null;
var inputTimer = null;
var waitingForInput = false;
var countdownCount = 3;
// UI Elements
var instructionText = new Text2('Ready to open a card?', {
size: 80,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
LK.gui.top.addChild(instructionText);
instructionText.y = 150;
var countdownText = new Text2('', {
size: 120,
fill: 0xFFD700
});
countdownText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(countdownText);
var promptText = new Text2('', {
size: 60,
fill: 0x00FF00
});
promptText.anchor.set(0.5, 0.5);
LK.gui.bottom.addChild(promptText);
promptText.y = -200;
// Create and position cards
function initializeCards() {
var cardSpacing = 350;
var startX = (2048 - 4 * cardSpacing) / 2;
var topRowY = 1366 - 300;
var bottomRowY = 1366 + 100;
for (var i = 0; i < 5; i++) {
var card = new Card();
card.init(i);
if (i < 3) {
// Top row
card.x = startX + i * cardSpacing;
card.y = topRowY;
} else {
// Bottom row
card.x = startX + (i - 3) * cardSpacing + cardSpacing / 2;
card.y = bottomRowY;
}
cards.push(card);
game.addChild(card);
}
// Make first card active
cards[0].isActive = true;
tween(cards[0], {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 500,
easing: tween.easeInOut
});
}
function startCountdown() {
gameState = 'countdown';
countdownCount = 3;
instructionText.setText('Get ready...');
function doCountdown() {
if (countdownCount > 0) {
countdownText.setText(countdownCount.toString());
LK.getSound('countdown').play();
countdownCount--;
countdownTimer = LK.setTimeout(doCountdown, 1000);
} else {
countdownText.setText('');
startInputPhase();
}
}
doCountdown();
}
function startInputPhase() {
gameState = 'input';
waitingForInput = true;
instructionText.setText('Say "Open the card!" or tap the card!');
promptText.setText('NOW!');
// Give player 3 seconds to respond
inputTimer = LK.setTimeout(function () {
if (waitingForInput) {
waitingForInput = false;
promptText.setText('Too slow! Try again...');
LK.setTimeout(function () {
if (gameState !== 'completed') {
resetForNextAttempt();
}
}, 2000);
}
}, 3000);
}
function handleCardOpen() {
if (!waitingForInput) return;
waitingForInput = false;
gameState = 'flipping';
if (inputTimer) {
LK.clearTimeout(inputTimer);
inputTimer = null;
}
instructionText.setText('Great job!');
promptText.setText('');
countdownText.setText('');
// Play success sound
LK.getSound('success').play();
// Flip the current card
cards[currentCardIndex].flipCard();
// Move to next card after delay
LK.setTimeout(function () {
currentCardIndex++;
if (currentCardIndex >= cards.length) {
// All cards opened
gameState = 'completed';
instructionText.setText('Amazing! All cards opened!');
// Celebrate with screen flash
LK.effects.flashScreen(0xFFD700, 2000);
// Scale all cards for celebration
for (var i = 0; i < cards.length; i++) {
tween(cards[i], {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 1000,
easing: tween.bounceOut
});
}
} else {
// Activate next card
cards[currentCardIndex].isActive = true;
tween(cards[currentCardIndex], {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 500,
easing: tween.easeInOut
});
// Reset for next card
LK.setTimeout(resetForNextAttempt, 1500);
}
}, 2000);
}
function resetForNextAttempt() {
if (gameState === 'completed') return;
gameState = 'waiting';
instructionText.setText('Ready for the next card?');
promptText.setText('');
countdownText.setText('');
LK.setTimeout(function () {
if (gameState === 'waiting') {
startCountdown();
}
}, 2000);
}
// Voice detection
var lastVoiceCheck = false;
game.update = function () {
// Check for voice input during input phase
if (waitingForInput && facekit.volume > 0.3) {
if (!lastVoiceCheck) {
// Voice just started
handleCardOpen();
}
}
lastVoiceCheck = facekit.volume > 0.3;
};
// Touch input for starting the game
game.down = function (x, y, obj) {
if (gameState === 'waiting' && currentCardIndex === 0 && !cards[0].isFlipped) {
startCountdown();
}
};
// Initialize the game
initializeCards();