/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); self.originalTint = getRandomFluorescentColor(); self.tint = self.originalTint; self.rotation = Math.PI * 2 * Math.random(); particleGraphics.blendMode = 1; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 //Init game with black background }); /**** * Game Code ****/ var scoreDisplay; var currentDirection = null; var swipeStartX = null; var swipeStartY = null; var isCorrectSwipe = false; var canSwipe = true; // Array to store score particles var scoreParticles = []; // Timer variables var timerParticles = []; var timerDuration = 5000; // 5 seconds per round in milliseconds var roundStartTime = 0; var timerRadius = 150; // Radius of the timer ring around score // Function to generate bright fluorescent colors function getRandomFluorescentColor() { var fluorColors = [0xFF00FF, // Magenta 0x00FFFF, // Cyan 0xFFFF00, // Yellow 0x00FF00, // Lime 0xFF0080, // Hot Pink 0x80FF00, // Chartreuse 0xFF8000, // Orange 0x00FF80, // Spring Green 0x8000FF, // Purple 0xFF0040, // Rose 0x40FF00, // Green Yellow 0x00FFBF // Turquoise ]; return fluorColors[Math.floor(Math.random() * fluorColors.length)]; } // Digit patterns for particles (5x7 grid for each digit) var digitPatterns = { '0': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]], '1': [[0, 0, 1, 0, 0], [0, 1, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [1, 1, 1, 1, 1]], '2': [[1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1]], '3': [[1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1]], '4': [[1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1]], '5': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1]], '6': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]], '7': [[1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 1, 0], [0, 0, 1, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]], '8': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]], '9': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1]] }; function updateScoreDisplay(score) { // Clear existing score particles scoreParticles.forEach(function (particle) { particle.destroy(); }); scoreParticles = []; var scoreString = score.toString(); var digitSpacing = 80; // Space between digits var particleSize = 12; // Size of each particle in the digit var startX = -(scoreString.length - 1) * digitSpacing / 2; // Create particles for each digit for (var digitIndex = 0; digitIndex < scoreString.length; digitIndex++) { var digit = scoreString[digitIndex]; var pattern = digitPatterns[digit]; var digitX = startX + digitIndex * digitSpacing; // Create particles based on pattern for (var row = 0; row < pattern.length; row++) { for (var col = 0; col < pattern[row].length; col++) { if (pattern[row][col] === 1) { var particle = scoreContainer.addChild(new Particle()); particle.x = digitX + (col - 2) * particleSize; particle.y = (row - 3) * particleSize; particle.scale.set(0.3, 0.3); particle.tint = 0xFFFFFF; // White color for score scoreParticles.push(particle); } } } } } // Initialize score display container var scoreContainer = new Container(); scoreContainer.x = 1024; // Center horizontally scoreContainer.y = 250; // Position lower to accommodate timer ring game.addChild(scoreContainer); // Function to create timer ring function createTimerRing() { // Clear existing timer particles timerParticles.forEach(function (particle) { particle.destroy(); }); timerParticles = []; // Create particles in a circle var particleCount = 60; // Number of particles in the ring for (var i = 0; i < particleCount; i++) { // Start from top (-PI/2) and go clockwise var angle = -Math.PI / 2 + i / particleCount * Math.PI * 2; var particle = scoreContainer.addChild(new Particle()); // Position in circle around score particle.x = Math.cos(angle) * timerRadius; particle.y = Math.sin(angle) * timerRadius; particle.scale.set(0.2, 0.2); particle.tint = 0x00FF00; // Start with green particle.timerIndex = i; particle.baseAngle = angle; timerParticles.push(particle); } } // Initialize score display updateScoreDisplay(0); // Initialize timer ring createTimerRing(); for (var i = 0; i < 500; i++) { var particle = game.addChild(new Particle()); var angle = Math.random() * Math.PI * 2; var radius = Math.random() * 300; particle.x = 1024 + Math.cos(angle) * radius; particle.y = 1366 + Math.sin(angle) * radius; particle.scale.set(4, 4); // Initialize cloud movement parameters particle.cloudAngle = angle; particle.cloudRadius = radius; particle.cloudSpeed = 0.01 + Math.random() * 0.02; particle.driftSpeed = 0.5 + Math.random() * 1; } // Create letter positions for directional words - centered on screen var letterPositions = { UP: [ // U { x: 724, y: 1200 }, { x: 724, y: 1300 }, { x: 724, y: 1400 }, { x: 724, y: 1500 }, { x: 824, y: 1500 }, { x: 924, y: 1500 }, { x: 1024, y: 1200 }, { x: 1024, y: 1300 }, { x: 1024, y: 1400 }, { x: 1024, y: 1500 }, // P { x: 1224, y: 1200 }, { x: 1224, y: 1300 }, { x: 1224, y: 1400 }, { x: 1224, y: 1500 }, { x: 1324, y: 1200 }, { x: 1424, y: 1200 }, { x: 1424, y: 1300 }, { x: 1324, y: 1350 }, { x: 1424, y: 1350 }], DOWN: [ // D { x: 324, y: 1200 }, { x: 324, y: 1300 }, { x: 324, y: 1400 }, { x: 324, y: 1500 }, { x: 424, y: 1200 }, { x: 524, y: 1250 }, { x: 524, y: 1450 }, { x: 424, y: 1500 }, // O { x: 724, y: 1250 }, { x: 724, y: 1450 }, { x: 774, y: 1200 }, { x: 874, y: 1200 }, { x: 924, y: 1250 }, { x: 924, y: 1450 }, { x: 774, y: 1500 }, { x: 874, y: 1500 }, // W { x: 1124, y: 1200 }, { x: 1144, y: 1300 }, { x: 1164, y: 1400 }, { x: 1184, y: 1500 }, { x: 1274, y: 1400 }, { x: 1364, y: 1400 }, { x: 1384, y: 1500 }, { x: 1404, y: 1400 }, { x: 1424, y: 1300 }, { x: 1444, y: 1200 }, // N { x: 1574, y: 1200 }, { x: 1574, y: 1300 }, { x: 1574, y: 1400 }, { x: 1574, y: 1500 }, { x: 1644, y: 1280 }, { x: 1714, y: 1360 }, { x: 1784, y: 1440 }, { x: 1854, y: 1200 }, { x: 1854, y: 1300 }, { x: 1854, y: 1400 }, { x: 1854, y: 1500 }], LEFT: [ // L { x: 424, y: 1200 }, { x: 424, y: 1300 }, { x: 424, y: 1400 }, { x: 424, y: 1500 }, { x: 524, y: 1500 }, { x: 624, y: 1500 }, // E { x: 824, y: 1200 }, { x: 824, y: 1300 }, { x: 824, y: 1400 }, { x: 824, y: 1500 }, { x: 924, y: 1200 }, { x: 1024, y: 1200 }, { x: 924, y: 1350 }, { x: 924, y: 1500 }, { x: 1024, y: 1500 }, // F { x: 1224, y: 1200 }, { x: 1224, y: 1300 }, { x: 1224, y: 1400 }, { x: 1224, y: 1500 }, { x: 1324, y: 1200 }, { x: 1424, y: 1200 }, { x: 1324, y: 1350 }, // T { x: 1624, y: 1200 }, { x: 1724, y: 1200 }, { x: 1824, y: 1200 }, { x: 1724, y: 1300 }, { x: 1724, y: 1400 }, { x: 1724, y: 1500 }], RIGHT: [ // Shifted left by 225px to fit on screen // R { x: 49, // 274 - 225 y: 1200 }, { x: 49, // 274 - 225 y: 1300 }, { x: 49, // 274 - 225 y: 1400 }, { x: 49, // 274 - 225 y: 1500 }, { x: 149, // 374 - 225 y: 1200 }, { x: 249, // 474 - 225 y: 1200 }, { x: 249, // 474 - 225 y: 1300 }, { x: 149, // 374 - 225 y: 1350 }, { x: 249, // 474 - 225 y: 1400 }, { x: 349, // 574 - 225 y: 1500 }, // I { x: 549, // 774 - 225 y: 1200 }, { x: 649, // 874 - 225 y: 1200 }, { x: 749, // 974 - 225 y: 1200 }, { x: 649, // 874 - 225 y: 1300 }, { x: 649, // 874 - 225 y: 1400 }, { x: 549, // 774 - 225 y: 1500 }, { x: 649, // 874 - 225 y: 1500 }, { x: 749, // 974 - 225 y: 1500 }, // G { x: 949, // 1174 - 225 y: 1250 }, { x: 999, // 1224 - 225 y: 1200 }, { x: 1099, // 1324 - 225 y: 1200 }, { x: 1149, // 1374 - 225 y: 1200 }, { x: 949, // 1174 - 225 y: 1350 }, { x: 949, // 1174 - 225 y: 1450 }, { x: 999, // 1224 - 225 y: 1500 }, { x: 1099, // 1324 - 225 y: 1500 }, { x: 1149, // 1374 - 225 y: 1450 }, { x: 1149, // 1374 - 225 y: 1400 }, { x: 1099, // 1324 - 225 y: 1400 }, // H { x: 1349, // 1574 - 225 y: 1200 }, { x: 1349, // 1574 - 225 y: 1300 }, { x: 1349, // 1574 - 225 y: 1400 }, { x: 1349, // 1574 - 225 y: 1500 }, { x: 1449, // 1674 - 225 y: 1350 }, { x: 1549, // 1774 - 225 y: 1350 }, { x: 1649, // 1874 - 225 y: 1200 }, { x: 1649, // 1874 - 225 y: 1300 }, { x: 1649, // 1874 - 225 y: 1400 }, { x: 1649, // 1874 - 225 y: 1500 }, // T { x: 1799, // 2024 - 225 y: 1200 }, { x: 1899, // 2124 - 225 y: 1200 }, { x: 1999, // 2224 - 225 y: 1200 }, { x: 1899, // 2124 - 225 y: 1300 }, { x: 1899, // 2124 - 225 y: 1400 }, { x: 1899, // 2124 - 225 y: 1500 }] }; // NOT letter positions (reusable) var notLetterPositions = { // N 0: { x: 574, y: 1100 }, 1: { x: 574, y: 1200 }, 2: { x: 574, y: 1300 }, 3: { x: 574, y: 1400 }, 4: { x: 644, y: 1180 }, 5: { x: 714, y: 1260 }, 6: { x: 784, y: 1340 }, 7: { x: 854, y: 1100 }, 8: { x: 854, y: 1200 }, 9: { x: 854, y: 1300 }, 10: { x: 854, y: 1400 }, // O 11: { x: 1024, y: 1150 }, 12: { x: 1024, y: 1350 }, 13: { x: 1074, y: 1100 }, 14: { x: 1174, y: 1100 }, 15: { x: 1224, y: 1150 }, 16: { x: 1224, y: 1350 }, 17: { x: 1074, y: 1400 }, 18: { x: 1174, y: 1400 }, // T 19: { x: 1324, y: 1100 }, 20: { x: 1424, y: 1100 }, 21: { x: 1524, y: 1100 }, 22: { x: 1424, y: 1200 }, 23: { x: 1424, y: 1300 }, 24: { x: 1424, y: 1400 } }; // Function to generate NOT direction positions function getNotDirectionPositions(direction) { var positions = []; // Add NOT letters for (var i = 0; i < 25; i++) { positions.push(notLetterPositions[i]); } // Add direction letters with y offset var basePositions = letterPositions[direction]; var yOffset = 300; // Move direction word down for (var j = 0; j < basePositions.length; j++) { positions.push({ x: basePositions[j].x, y: basePositions[j].y + yOffset }); } return positions; } game.move = function (x, y) { // Not used for swipe detection, but required by engine }; game.up = function (x, y) { if (!canSwipe || swipeStartX === null || swipeStartY === null) return; var swipeDeltaX = x - swipeStartX; var swipeDeltaY = y - swipeStartY; var swipeThreshold = 100; var detectedDirection = null; if (Math.abs(swipeDeltaX) > Math.abs(swipeDeltaY)) { if (swipeDeltaX > swipeThreshold) { detectedDirection = 'RIGHT'; } else if (swipeDeltaX < -swipeThreshold) { detectedDirection = 'LEFT'; } } else { if (swipeDeltaY > swipeThreshold) { detectedDirection = 'DOWN'; } else if (swipeDeltaY < -swipeThreshold) { detectedDirection = 'UP'; } } var isCorrect = false; if (currentDirection.indexOf('NOT ') === 0) { // For NOT directions, any swipe except the forbidden one is correct var forbiddenDirection = currentDirection.substring(4); // Remove 'NOT ' prefix if (detectedDirection !== null && detectedDirection !== forbiddenDirection) { isCorrect = true; } } else { // For regular directions, must match exactly isCorrect = detectedDirection === currentDirection; } if (isCorrect) { // Correct swipe! isCorrectSwipe = true; LK.setScore(LK.getScore() + 1); updateScoreDisplay(LK.getScore()); // Flash green for correct LK.effects.flashScreen(0x00FF00, 300); // Check win condition if (LK.getScore() >= 20) { LK.showYouWin(); return; } // Start next round canSwipe = false; showNextDirection(); } else if (detectedDirection !== null) { // Wrong swipe - game over LK.effects.flashScreen(0xFF0000, 300); LK.showGameOver(); } swipeStartX = null; swipeStartY = null; }; function showNextDirection() { // Reset timer for new round roundStartTime = Date.now(); // Reset timer particles to full visibility timerParticles.forEach(function (particle) { particle.alpha = 1; particle.scale.set(0.2, 0.2); particle.tint = 0x00FF00; // Reset to green }); // Choose random direction - include NOT directions var directions = ['UP', 'DOWN', 'LEFT', 'RIGHT', 'NOT UP', 'NOT DOWN', 'NOT LEFT', 'NOT RIGHT']; currentDirection = directions[Math.floor(Math.random() * directions.length)]; var directionColors = { UP: 0xFFFF00, // Bright Yellow DOWN: 0x00FFFF, // Bright Cyan LEFT: 0x00FF00, // Bright Green RIGHT: 0xFF00FF, // Bright Magenta 'NOT UP': 0xFF4500, // Orange Red 'NOT DOWN': 0x00CED1, // Dark Turquoise 'NOT LEFT': 0x32CD32, // Lime Green 'NOT RIGHT': 0xFF1493 // Deep Pink }; // Get particles var particles = []; for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof Particle) { particles.push(game.children[i]); } } // Animate particles to scatter first var scatterDuration = 500; particles.forEach(function (particle, index) { var angle = Math.random() * Math.PI * 2; var radius = 400 + Math.random() * 800; tween(particle, { x: 1024 + Math.cos(angle) * radius, y: 1366 + Math.sin(angle) * radius, scaleX: 0.5, scaleY: 0.5, rotation: Math.random() * Math.PI * 2, tint: particle.originalTint }, { duration: scatterDuration, easing: tween.easeOut }); }); // After scatter, form the word LK.setTimeout(function () { // Get letter positions for the current direction var positions; if (currentDirection.indexOf('NOT ') === 0) { // For NOT directions, generate combined positions var baseDirection = currentDirection.substring(4); // Remove 'NOT ' prefix positions = getNotDirectionPositions(baseDirection); } else { // For regular directions, use existing positions positions = letterPositions[currentDirection].slice(); } // Clone and shuffle the positions var shuffledPositions = positions.slice(); for (var i = shuffledPositions.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = shuffledPositions[i]; shuffledPositions[i] = shuffledPositions[j]; shuffledPositions[j] = temp; } var tweenFunctions = [tween.easeIn, tween.easeOut, tween.elasticOut, tween.bounceOut, tween.easeInOut]; var randomTweenFunction = tweenFunctions[Math.floor(Math.random() * tweenFunctions.length)]; // Use direction color for the word var wordColor = directionColors[currentDirection]; particles.forEach(function (particle, index) { if (index < shuffledPositions.length) { // Form letter // Clear cloud parameters so particle is identified as word particle delete particle.cloudAngle; delete particle.cloudRadius; delete particle.cloudSpeed; delete particle.driftSpeed; tween(particle, { x: shuffledPositions[index].x, y: shuffledPositions[index].y, scaleX: 1.2, // Increased scale for better readability scaleY: 1.2, // Increased scale for better readability rotation: 0, tint: wordColor // Same color for all particles in the word }, { duration: 800, easing: randomTweenFunction, delay: index * 10 }); } else { // Extra particles float around in cloud-like motion var angle = Math.random() * Math.PI * 2; var radius = 300 + Math.random() * 400; var targetX = 1024 + Math.cos(angle) * radius; var targetY = 1366 + Math.sin(angle) * radius; // Store cloud movement parameters on particle particle.cloudAngle = angle; particle.cloudRadius = radius; particle.cloudSpeed = 0.01 + Math.random() * 0.02; particle.driftSpeed = 0.5 + Math.random() * 1; tween(particle, { x: targetX, y: targetY, scaleX: 0.2, scaleY: 0.2, rotation: Math.random() * Math.PI * 2, tint: particle.originalTint }, { duration: 1000, easing: tween.linear }); } }); // Enable swiping after animation LK.setTimeout(function () { canSwipe = true; }, 900); }, scatterDuration + 100); } // Add continuous movement for background particles game.update = function () { // Move particles that are in cloud formation for (var i = 0; i < game.children.length; i++) { var particle = game.children[i]; if (particle instanceof Particle) { // Check if particle is part of the word (not in cloud formation) if (particle.cloudAngle === undefined) { // Add small wiggle to word particles var wiggleX = Math.sin(Date.now() * 0.003 + i) * 0.5; var wiggleY = Math.cos(Date.now() * 0.003 + i) * 0.5; particle.x = particle.x + wiggleX; particle.y = particle.y + wiggleY; } else { // Original cloud movement for background particles // Update cloud angle for circular drift particle.cloudAngle += particle.cloudSpeed; // Calculate new position within cloud shape var centerX = 1024; var centerY = 1366; var cloudX = centerX + Math.cos(particle.cloudAngle) * particle.cloudRadius; var cloudY = centerY + Math.sin(particle.cloudAngle) * particle.cloudRadius; // Add some drift movement var driftX = Math.sin(Date.now() * 0.001 * particle.driftSpeed) * 20; var driftY = Math.cos(Date.now() * 0.001 * particle.driftSpeed) * 15; // Apply movement particle.x = cloudX + driftX; particle.y = cloudY + driftY; // Gentle rotation particle.rotation += 0.01; } } } // Add wiggle effect to score particles scoreParticles.forEach(function (particle, index) { var wiggleX = Math.sin(Date.now() * 0.002 + index * 0.1) * 0.3; var wiggleY = Math.cos(Date.now() * 0.002 + index * 0.1) * 0.3; particle.x = particle.x + wiggleX; particle.y = particle.y + wiggleY; }); // Update timer ring if (canSwipe && roundStartTime > 0) { var elapsedTime = Date.now() - roundStartTime; var timeRemaining = Math.max(0, timerDuration - elapsedTime); var progress = timeRemaining / timerDuration; // Update timer particles timerParticles.forEach(function (particle, index) { // Calculate threshold for this particle (inverted so it depletes clockwise from top) var threshold = 1 - index / timerParticles.length; if (threshold > progress) { particle.alpha = 0.1; // Fade out depleted particles particle.scale.set(0.1, 0.1); } else { particle.alpha = 1; particle.scale.set(0.2, 0.2); // Change color based on time remaining if (progress < 0.2) { particle.tint = 0xFF0000; // Red when low on time } else if (progress < 0.5) { particle.tint = 0xFFFF00; // Yellow when half time } else { particle.tint = 0x00FF00; // Green when plenty of time } // Add pulsing effect when time is low if (progress < 0.2) { var pulse = Math.sin(Date.now() * 0.01) * 0.1 + 0.2; particle.scale.set(pulse, pulse); } } // Add gentle orbital movement var orbitOffset = Math.sin(Date.now() * 0.001 + index * 0.1) * 5; particle.x = Math.cos(particle.baseAngle) * (timerRadius + orbitOffset); particle.y = Math.sin(particle.baseAngle) * (timerRadius + orbitOffset); }); // Check if time ran out if (timeRemaining === 0 && canSwipe) { // Time's up - game over canSwipe = false; LK.effects.flashScreen(0xFF0000, 500); LK.showGameOver(); } } }; // Start the first round showNextDirection(); game.down = function (x, y) { if (!canSwipe) return; swipeStartX = x; swipeStartY = y; isCorrectSwipe = false; };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.originalTint = getRandomFluorescentColor();
self.tint = self.originalTint;
self.rotation = Math.PI * 2 * Math.random();
particleGraphics.blendMode = 1;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 //Init game with black background
});
/****
* Game Code
****/
var scoreDisplay;
var currentDirection = null;
var swipeStartX = null;
var swipeStartY = null;
var isCorrectSwipe = false;
var canSwipe = true;
// Array to store score particles
var scoreParticles = [];
// Timer variables
var timerParticles = [];
var timerDuration = 5000; // 5 seconds per round in milliseconds
var roundStartTime = 0;
var timerRadius = 150; // Radius of the timer ring around score
// Function to generate bright fluorescent colors
function getRandomFluorescentColor() {
var fluorColors = [0xFF00FF,
// Magenta
0x00FFFF,
// Cyan
0xFFFF00,
// Yellow
0x00FF00,
// Lime
0xFF0080,
// Hot Pink
0x80FF00,
// Chartreuse
0xFF8000,
// Orange
0x00FF80,
// Spring Green
0x8000FF,
// Purple
0xFF0040,
// Rose
0x40FF00,
// Green Yellow
0x00FFBF // Turquoise
];
return fluorColors[Math.floor(Math.random() * fluorColors.length)];
}
// Digit patterns for particles (5x7 grid for each digit)
var digitPatterns = {
'0': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]],
'1': [[0, 0, 1, 0, 0], [0, 1, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [1, 1, 1, 1, 1]],
'2': [[1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1]],
'3': [[1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1]],
'4': [[1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1]],
'5': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1]],
'6': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]],
'7': [[1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 1, 0], [0, 0, 1, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0], [0, 1, 0, 0, 0]],
'8': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]],
'9': [[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [1, 1, 1, 1, 1]]
};
function updateScoreDisplay(score) {
// Clear existing score particles
scoreParticles.forEach(function (particle) {
particle.destroy();
});
scoreParticles = [];
var scoreString = score.toString();
var digitSpacing = 80; // Space between digits
var particleSize = 12; // Size of each particle in the digit
var startX = -(scoreString.length - 1) * digitSpacing / 2;
// Create particles for each digit
for (var digitIndex = 0; digitIndex < scoreString.length; digitIndex++) {
var digit = scoreString[digitIndex];
var pattern = digitPatterns[digit];
var digitX = startX + digitIndex * digitSpacing;
// Create particles based on pattern
for (var row = 0; row < pattern.length; row++) {
for (var col = 0; col < pattern[row].length; col++) {
if (pattern[row][col] === 1) {
var particle = scoreContainer.addChild(new Particle());
particle.x = digitX + (col - 2) * particleSize;
particle.y = (row - 3) * particleSize;
particle.scale.set(0.3, 0.3);
particle.tint = 0xFFFFFF; // White color for score
scoreParticles.push(particle);
}
}
}
}
}
// Initialize score display container
var scoreContainer = new Container();
scoreContainer.x = 1024; // Center horizontally
scoreContainer.y = 250; // Position lower to accommodate timer ring
game.addChild(scoreContainer);
// Function to create timer ring
function createTimerRing() {
// Clear existing timer particles
timerParticles.forEach(function (particle) {
particle.destroy();
});
timerParticles = [];
// Create particles in a circle
var particleCount = 60; // Number of particles in the ring
for (var i = 0; i < particleCount; i++) {
// Start from top (-PI/2) and go clockwise
var angle = -Math.PI / 2 + i / particleCount * Math.PI * 2;
var particle = scoreContainer.addChild(new Particle());
// Position in circle around score
particle.x = Math.cos(angle) * timerRadius;
particle.y = Math.sin(angle) * timerRadius;
particle.scale.set(0.2, 0.2);
particle.tint = 0x00FF00; // Start with green
particle.timerIndex = i;
particle.baseAngle = angle;
timerParticles.push(particle);
}
}
// Initialize score display
updateScoreDisplay(0);
// Initialize timer ring
createTimerRing();
for (var i = 0; i < 500; i++) {
var particle = game.addChild(new Particle());
var angle = Math.random() * Math.PI * 2;
var radius = Math.random() * 300;
particle.x = 1024 + Math.cos(angle) * radius;
particle.y = 1366 + Math.sin(angle) * radius;
particle.scale.set(4, 4);
// Initialize cloud movement parameters
particle.cloudAngle = angle;
particle.cloudRadius = radius;
particle.cloudSpeed = 0.01 + Math.random() * 0.02;
particle.driftSpeed = 0.5 + Math.random() * 1;
}
// Create letter positions for directional words - centered on screen
var letterPositions = {
UP: [
// U
{
x: 724,
y: 1200
}, {
x: 724,
y: 1300
}, {
x: 724,
y: 1400
}, {
x: 724,
y: 1500
}, {
x: 824,
y: 1500
}, {
x: 924,
y: 1500
}, {
x: 1024,
y: 1200
}, {
x: 1024,
y: 1300
}, {
x: 1024,
y: 1400
}, {
x: 1024,
y: 1500
},
// P
{
x: 1224,
y: 1200
}, {
x: 1224,
y: 1300
}, {
x: 1224,
y: 1400
}, {
x: 1224,
y: 1500
}, {
x: 1324,
y: 1200
}, {
x: 1424,
y: 1200
}, {
x: 1424,
y: 1300
}, {
x: 1324,
y: 1350
}, {
x: 1424,
y: 1350
}],
DOWN: [
// D
{
x: 324,
y: 1200
}, {
x: 324,
y: 1300
}, {
x: 324,
y: 1400
}, {
x: 324,
y: 1500
}, {
x: 424,
y: 1200
}, {
x: 524,
y: 1250
}, {
x: 524,
y: 1450
}, {
x: 424,
y: 1500
},
// O
{
x: 724,
y: 1250
}, {
x: 724,
y: 1450
}, {
x: 774,
y: 1200
}, {
x: 874,
y: 1200
}, {
x: 924,
y: 1250
}, {
x: 924,
y: 1450
}, {
x: 774,
y: 1500
}, {
x: 874,
y: 1500
},
// W
{
x: 1124,
y: 1200
}, {
x: 1144,
y: 1300
}, {
x: 1164,
y: 1400
}, {
x: 1184,
y: 1500
}, {
x: 1274,
y: 1400
}, {
x: 1364,
y: 1400
}, {
x: 1384,
y: 1500
}, {
x: 1404,
y: 1400
}, {
x: 1424,
y: 1300
}, {
x: 1444,
y: 1200
},
// N
{
x: 1574,
y: 1200
}, {
x: 1574,
y: 1300
}, {
x: 1574,
y: 1400
}, {
x: 1574,
y: 1500
}, {
x: 1644,
y: 1280
}, {
x: 1714,
y: 1360
}, {
x: 1784,
y: 1440
}, {
x: 1854,
y: 1200
}, {
x: 1854,
y: 1300
}, {
x: 1854,
y: 1400
}, {
x: 1854,
y: 1500
}],
LEFT: [
// L
{
x: 424,
y: 1200
}, {
x: 424,
y: 1300
}, {
x: 424,
y: 1400
}, {
x: 424,
y: 1500
}, {
x: 524,
y: 1500
}, {
x: 624,
y: 1500
},
// E
{
x: 824,
y: 1200
}, {
x: 824,
y: 1300
}, {
x: 824,
y: 1400
}, {
x: 824,
y: 1500
}, {
x: 924,
y: 1200
}, {
x: 1024,
y: 1200
}, {
x: 924,
y: 1350
}, {
x: 924,
y: 1500
}, {
x: 1024,
y: 1500
},
// F
{
x: 1224,
y: 1200
}, {
x: 1224,
y: 1300
}, {
x: 1224,
y: 1400
}, {
x: 1224,
y: 1500
}, {
x: 1324,
y: 1200
}, {
x: 1424,
y: 1200
}, {
x: 1324,
y: 1350
},
// T
{
x: 1624,
y: 1200
}, {
x: 1724,
y: 1200
}, {
x: 1824,
y: 1200
}, {
x: 1724,
y: 1300
}, {
x: 1724,
y: 1400
}, {
x: 1724,
y: 1500
}],
RIGHT: [
// Shifted left by 225px to fit on screen
// R
{
x: 49,
// 274 - 225
y: 1200
}, {
x: 49,
// 274 - 225
y: 1300
}, {
x: 49,
// 274 - 225
y: 1400
}, {
x: 49,
// 274 - 225
y: 1500
}, {
x: 149,
// 374 - 225
y: 1200
}, {
x: 249,
// 474 - 225
y: 1200
}, {
x: 249,
// 474 - 225
y: 1300
}, {
x: 149,
// 374 - 225
y: 1350
}, {
x: 249,
// 474 - 225
y: 1400
}, {
x: 349,
// 574 - 225
y: 1500
},
// I
{
x: 549,
// 774 - 225
y: 1200
}, {
x: 649,
// 874 - 225
y: 1200
}, {
x: 749,
// 974 - 225
y: 1200
}, {
x: 649,
// 874 - 225
y: 1300
}, {
x: 649,
// 874 - 225
y: 1400
}, {
x: 549,
// 774 - 225
y: 1500
}, {
x: 649,
// 874 - 225
y: 1500
}, {
x: 749,
// 974 - 225
y: 1500
},
// G
{
x: 949,
// 1174 - 225
y: 1250
}, {
x: 999,
// 1224 - 225
y: 1200
}, {
x: 1099,
// 1324 - 225
y: 1200
}, {
x: 1149,
// 1374 - 225
y: 1200
}, {
x: 949,
// 1174 - 225
y: 1350
}, {
x: 949,
// 1174 - 225
y: 1450
}, {
x: 999,
// 1224 - 225
y: 1500
}, {
x: 1099,
// 1324 - 225
y: 1500
}, {
x: 1149,
// 1374 - 225
y: 1450
}, {
x: 1149,
// 1374 - 225
y: 1400
}, {
x: 1099,
// 1324 - 225
y: 1400
},
// H
{
x: 1349,
// 1574 - 225
y: 1200
}, {
x: 1349,
// 1574 - 225
y: 1300
}, {
x: 1349,
// 1574 - 225
y: 1400
}, {
x: 1349,
// 1574 - 225
y: 1500
}, {
x: 1449,
// 1674 - 225
y: 1350
}, {
x: 1549,
// 1774 - 225
y: 1350
}, {
x: 1649,
// 1874 - 225
y: 1200
}, {
x: 1649,
// 1874 - 225
y: 1300
}, {
x: 1649,
// 1874 - 225
y: 1400
}, {
x: 1649,
// 1874 - 225
y: 1500
},
// T
{
x: 1799,
// 2024 - 225
y: 1200
}, {
x: 1899,
// 2124 - 225
y: 1200
}, {
x: 1999,
// 2224 - 225
y: 1200
}, {
x: 1899,
// 2124 - 225
y: 1300
}, {
x: 1899,
// 2124 - 225
y: 1400
}, {
x: 1899,
// 2124 - 225
y: 1500
}]
};
// NOT letter positions (reusable)
var notLetterPositions = {
// N
0: {
x: 574,
y: 1100
},
1: {
x: 574,
y: 1200
},
2: {
x: 574,
y: 1300
},
3: {
x: 574,
y: 1400
},
4: {
x: 644,
y: 1180
},
5: {
x: 714,
y: 1260
},
6: {
x: 784,
y: 1340
},
7: {
x: 854,
y: 1100
},
8: {
x: 854,
y: 1200
},
9: {
x: 854,
y: 1300
},
10: {
x: 854,
y: 1400
},
// O
11: {
x: 1024,
y: 1150
},
12: {
x: 1024,
y: 1350
},
13: {
x: 1074,
y: 1100
},
14: {
x: 1174,
y: 1100
},
15: {
x: 1224,
y: 1150
},
16: {
x: 1224,
y: 1350
},
17: {
x: 1074,
y: 1400
},
18: {
x: 1174,
y: 1400
},
// T
19: {
x: 1324,
y: 1100
},
20: {
x: 1424,
y: 1100
},
21: {
x: 1524,
y: 1100
},
22: {
x: 1424,
y: 1200
},
23: {
x: 1424,
y: 1300
},
24: {
x: 1424,
y: 1400
}
};
// Function to generate NOT direction positions
function getNotDirectionPositions(direction) {
var positions = [];
// Add NOT letters
for (var i = 0; i < 25; i++) {
positions.push(notLetterPositions[i]);
}
// Add direction letters with y offset
var basePositions = letterPositions[direction];
var yOffset = 300; // Move direction word down
for (var j = 0; j < basePositions.length; j++) {
positions.push({
x: basePositions[j].x,
y: basePositions[j].y + yOffset
});
}
return positions;
}
game.move = function (x, y) {
// Not used for swipe detection, but required by engine
};
game.up = function (x, y) {
if (!canSwipe || swipeStartX === null || swipeStartY === null) return;
var swipeDeltaX = x - swipeStartX;
var swipeDeltaY = y - swipeStartY;
var swipeThreshold = 100;
var detectedDirection = null;
if (Math.abs(swipeDeltaX) > Math.abs(swipeDeltaY)) {
if (swipeDeltaX > swipeThreshold) {
detectedDirection = 'RIGHT';
} else if (swipeDeltaX < -swipeThreshold) {
detectedDirection = 'LEFT';
}
} else {
if (swipeDeltaY > swipeThreshold) {
detectedDirection = 'DOWN';
} else if (swipeDeltaY < -swipeThreshold) {
detectedDirection = 'UP';
}
}
var isCorrect = false;
if (currentDirection.indexOf('NOT ') === 0) {
// For NOT directions, any swipe except the forbidden one is correct
var forbiddenDirection = currentDirection.substring(4); // Remove 'NOT ' prefix
if (detectedDirection !== null && detectedDirection !== forbiddenDirection) {
isCorrect = true;
}
} else {
// For regular directions, must match exactly
isCorrect = detectedDirection === currentDirection;
}
if (isCorrect) {
// Correct swipe!
isCorrectSwipe = true;
LK.setScore(LK.getScore() + 1);
updateScoreDisplay(LK.getScore());
// Flash green for correct
LK.effects.flashScreen(0x00FF00, 300);
// Check win condition
if (LK.getScore() >= 20) {
LK.showYouWin();
return;
}
// Start next round
canSwipe = false;
showNextDirection();
} else if (detectedDirection !== null) {
// Wrong swipe - game over
LK.effects.flashScreen(0xFF0000, 300);
LK.showGameOver();
}
swipeStartX = null;
swipeStartY = null;
};
function showNextDirection() {
// Reset timer for new round
roundStartTime = Date.now();
// Reset timer particles to full visibility
timerParticles.forEach(function (particle) {
particle.alpha = 1;
particle.scale.set(0.2, 0.2);
particle.tint = 0x00FF00; // Reset to green
});
// Choose random direction - include NOT directions
var directions = ['UP', 'DOWN', 'LEFT', 'RIGHT', 'NOT UP', 'NOT DOWN', 'NOT LEFT', 'NOT RIGHT'];
currentDirection = directions[Math.floor(Math.random() * directions.length)];
var directionColors = {
UP: 0xFFFF00,
// Bright Yellow
DOWN: 0x00FFFF,
// Bright Cyan
LEFT: 0x00FF00,
// Bright Green
RIGHT: 0xFF00FF,
// Bright Magenta
'NOT UP': 0xFF4500,
// Orange Red
'NOT DOWN': 0x00CED1,
// Dark Turquoise
'NOT LEFT': 0x32CD32,
// Lime Green
'NOT RIGHT': 0xFF1493 // Deep Pink
};
// Get particles
var particles = [];
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof Particle) {
particles.push(game.children[i]);
}
}
// Animate particles to scatter first
var scatterDuration = 500;
particles.forEach(function (particle, index) {
var angle = Math.random() * Math.PI * 2;
var radius = 400 + Math.random() * 800;
tween(particle, {
x: 1024 + Math.cos(angle) * radius,
y: 1366 + Math.sin(angle) * radius,
scaleX: 0.5,
scaleY: 0.5,
rotation: Math.random() * Math.PI * 2,
tint: particle.originalTint
}, {
duration: scatterDuration,
easing: tween.easeOut
});
});
// After scatter, form the word
LK.setTimeout(function () {
// Get letter positions for the current direction
var positions;
if (currentDirection.indexOf('NOT ') === 0) {
// For NOT directions, generate combined positions
var baseDirection = currentDirection.substring(4); // Remove 'NOT ' prefix
positions = getNotDirectionPositions(baseDirection);
} else {
// For regular directions, use existing positions
positions = letterPositions[currentDirection].slice();
}
// Clone and shuffle the positions
var shuffledPositions = positions.slice();
for (var i = shuffledPositions.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = shuffledPositions[i];
shuffledPositions[i] = shuffledPositions[j];
shuffledPositions[j] = temp;
}
var tweenFunctions = [tween.easeIn, tween.easeOut, tween.elasticOut, tween.bounceOut, tween.easeInOut];
var randomTweenFunction = tweenFunctions[Math.floor(Math.random() * tweenFunctions.length)];
// Use direction color for the word
var wordColor = directionColors[currentDirection];
particles.forEach(function (particle, index) {
if (index < shuffledPositions.length) {
// Form letter
// Clear cloud parameters so particle is identified as word particle
delete particle.cloudAngle;
delete particle.cloudRadius;
delete particle.cloudSpeed;
delete particle.driftSpeed;
tween(particle, {
x: shuffledPositions[index].x,
y: shuffledPositions[index].y,
scaleX: 1.2,
// Increased scale for better readability
scaleY: 1.2,
// Increased scale for better readability
rotation: 0,
tint: wordColor // Same color for all particles in the word
}, {
duration: 800,
easing: randomTweenFunction,
delay: index * 10
});
} else {
// Extra particles float around in cloud-like motion
var angle = Math.random() * Math.PI * 2;
var radius = 300 + Math.random() * 400;
var targetX = 1024 + Math.cos(angle) * radius;
var targetY = 1366 + Math.sin(angle) * radius;
// Store cloud movement parameters on particle
particle.cloudAngle = angle;
particle.cloudRadius = radius;
particle.cloudSpeed = 0.01 + Math.random() * 0.02;
particle.driftSpeed = 0.5 + Math.random() * 1;
tween(particle, {
x: targetX,
y: targetY,
scaleX: 0.2,
scaleY: 0.2,
rotation: Math.random() * Math.PI * 2,
tint: particle.originalTint
}, {
duration: 1000,
easing: tween.linear
});
}
});
// Enable swiping after animation
LK.setTimeout(function () {
canSwipe = true;
}, 900);
}, scatterDuration + 100);
}
// Add continuous movement for background particles
game.update = function () {
// Move particles that are in cloud formation
for (var i = 0; i < game.children.length; i++) {
var particle = game.children[i];
if (particle instanceof Particle) {
// Check if particle is part of the word (not in cloud formation)
if (particle.cloudAngle === undefined) {
// Add small wiggle to word particles
var wiggleX = Math.sin(Date.now() * 0.003 + i) * 0.5;
var wiggleY = Math.cos(Date.now() * 0.003 + i) * 0.5;
particle.x = particle.x + wiggleX;
particle.y = particle.y + wiggleY;
} else {
// Original cloud movement for background particles
// Update cloud angle for circular drift
particle.cloudAngle += particle.cloudSpeed;
// Calculate new position within cloud shape
var centerX = 1024;
var centerY = 1366;
var cloudX = centerX + Math.cos(particle.cloudAngle) * particle.cloudRadius;
var cloudY = centerY + Math.sin(particle.cloudAngle) * particle.cloudRadius;
// Add some drift movement
var driftX = Math.sin(Date.now() * 0.001 * particle.driftSpeed) * 20;
var driftY = Math.cos(Date.now() * 0.001 * particle.driftSpeed) * 15;
// Apply movement
particle.x = cloudX + driftX;
particle.y = cloudY + driftY;
// Gentle rotation
particle.rotation += 0.01;
}
}
}
// Add wiggle effect to score particles
scoreParticles.forEach(function (particle, index) {
var wiggleX = Math.sin(Date.now() * 0.002 + index * 0.1) * 0.3;
var wiggleY = Math.cos(Date.now() * 0.002 + index * 0.1) * 0.3;
particle.x = particle.x + wiggleX;
particle.y = particle.y + wiggleY;
});
// Update timer ring
if (canSwipe && roundStartTime > 0) {
var elapsedTime = Date.now() - roundStartTime;
var timeRemaining = Math.max(0, timerDuration - elapsedTime);
var progress = timeRemaining / timerDuration;
// Update timer particles
timerParticles.forEach(function (particle, index) {
// Calculate threshold for this particle (inverted so it depletes clockwise from top)
var threshold = 1 - index / timerParticles.length;
if (threshold > progress) {
particle.alpha = 0.1; // Fade out depleted particles
particle.scale.set(0.1, 0.1);
} else {
particle.alpha = 1;
particle.scale.set(0.2, 0.2);
// Change color based on time remaining
if (progress < 0.2) {
particle.tint = 0xFF0000; // Red when low on time
} else if (progress < 0.5) {
particle.tint = 0xFFFF00; // Yellow when half time
} else {
particle.tint = 0x00FF00; // Green when plenty of time
}
// Add pulsing effect when time is low
if (progress < 0.2) {
var pulse = Math.sin(Date.now() * 0.01) * 0.1 + 0.2;
particle.scale.set(pulse, pulse);
}
}
// Add gentle orbital movement
var orbitOffset = Math.sin(Date.now() * 0.001 + index * 0.1) * 5;
particle.x = Math.cos(particle.baseAngle) * (timerRadius + orbitOffset);
particle.y = Math.sin(particle.baseAngle) * (timerRadius + orbitOffset);
});
// Check if time ran out
if (timeRemaining === 0 && canSwipe) {
// Time's up - game over
canSwipe = false;
LK.effects.flashScreen(0xFF0000, 500);
LK.showGameOver();
}
}
};
// Start the first round
showNextDirection();
game.down = function (x, y) {
if (!canSwipe) return;
swipeStartX = x;
swipeStartY = y;
isCorrectSwipe = false;
};