User prompt
add some power ups ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add more assets
User prompt
fix the lag
User prompt
make it smooth @upit/tween.v1 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make it smooth ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add more level
User prompt
add more time
User prompt
make the assets more big ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make it harder
User prompt
make the map bigger
User prompt
make the assets across around the map ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the time 20 second
User prompt
make the map more fancy ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the assets more smooth ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make it harder
User prompt
not working
User prompt
dimension not working
User prompt
game not working
Code edit (1 edits merged)
Please save this source code
User prompt
Quantum Paradox
Initial prompt
impres me
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BackgroundStar = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); self.twinkleSpeed = 0.02 + Math.random() * 0.03; self.twinkleOffset = Math.random() * Math.PI * 2; self.baseAlpha = 0.3 + Math.random() * 0.7; self.update = function () { // Direct property updates instead of creating tweens every frame var twinkle = Math.sin(LK.ticks * self.twinkleSpeed + self.twinkleOffset) * 0.3 + 0.7; self.alpha = self.baseAlpha * twinkle; // Direct position updates for smooth movement self.x += Math.sin(LK.ticks * 0.01 + self.twinkleOffset) * 0.02; self.y += Math.cos(LK.ticks * 0.008 + self.twinkleOffset) * 0.015; }; return self; }); var InterferenceField = Container.expand(function () { var self = Container.call(this); var fieldGraphics = self.attachAsset('interferenceField', { anchorX: 0.5, anchorY: 0.5, tint: 0xff4444 }); self.dimension = 0; self.pulseDirection = 1; self.setDimension = function (dim) { self.dimension = dim; self.alpha = 0.8; }; self.update = function () { // Direct rotation update fieldGraphics.rotation += 0.015; // Direct alpha updates instead of creating tweens every frame if (self.dimension === currentDimension) { self.alpha = 0.9 + Math.sin(LK.ticks * 0.05) * 0.3; // Add bright glow effect with color cycling var glowIntensity = Math.sin(LK.ticks * 0.08) * 0.5 + 0.5; fieldGraphics.tint = 0xff0000 + Math.floor(glowIntensity * 0x4444); } else { self.alpha = 0.4; fieldGraphics.tint = 0xff4444; } // Direct position updates for moving fields - reduced speeds for easier gameplay if (self.moveDirection !== undefined) { var moveSpeed = 2.5; // Reduced from 4 to 2.5 // Increase speed for level 8+ if (level >= 8) { moveSpeed = 3.5; // Reduced from 6 to 3.5 } // Ultra-fast speed for level 16+ if (level >= 16) { moveSpeed = 5; // Reduced from 9 to 5 } // Extreme speed for level 11+ if (level >= 11) { moveSpeed = 4; // Reduced from 7 to 4 } self.x += self.moveDirection * moveSpeed; if (self.x <= self.minX || self.x >= self.maxX) { self.moveDirection *= -1; } } }; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); self.dimension = 0; self.originalPosition = { x: 0, y: 0 }; self.isBeingDragged = false; self.isCollected = false; self.entangledWith = null; self.setDimension = function (dim) { self.dimension = dim; self.alpha = 1.0; }; self.startDrag = function () { self.isBeingDragged = true; tween(particleGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200 }); }; self.stopDrag = function () { self.isBeingDragged = false; tween(particleGraphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); }; self.collect = function () { self.isCollected = true; // Enhanced collection animation with bounce effect tween(self, { scaleX: 1.5, scaleY: 1.5 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { self.visible = false; } }); } }); // Tutorial step progression for particle collection if (isTutorial) { if (tutorialStep === 1 || tutorialStep === 2) { tutorialStep = 3; // Move to "great job" step LK.setTimeout(function () { updateTutorialStep(); }, 800); } else if (tutorialStep === 5) { tutorialStep = 6; LK.setTimeout(function () { updateTutorialStep(); }, 800); } } }; self.update = function () { if (self.isCollected) return; // Initialize collision tracking if (self.lastCoreIntersecting === undefined) { self.lastCoreIntersecting = false; } // Check collision with quantum core - only trigger on first contact var currentCoreIntersecting = false; if (self.dimension === currentDimension && quantumCore) { // Use actual asset dimensions for accurate collision detection var particleHalfWidth = particleGraphics.width / 2; // Use actual particle asset width var particleHalfHeight = particleGraphics.height / 2; // Use actual particle asset height var coreHalfWidth = quantumCore.width / 2; // Use actual quantum core asset width var coreHalfHeight = quantumCore.height / 2; // Use actual quantum core asset height currentCoreIntersecting = Math.abs(self.x - quantumCore.x) < particleHalfWidth + coreHalfWidth && Math.abs(self.y - quantumCore.y) < particleHalfHeight + coreHalfHeight; } if (!self.lastCoreIntersecting && currentCoreIntersecting) { self.collect(); LK.getSound('collectSound').play(); particlesCollected++; checkWinCondition(); } self.lastCoreIntersecting = currentCoreIntersecting; // Check collision with interference fields for (var i = 0; i < interferenceFields.length; i++) { var field = interferenceFields[i]; if (field.dimension === self.dimension) { // Use actual asset dimensions for accurate collision detection var particleHalfWidth = particleGraphics.width / 2; // Use actual particle asset width var particleHalfHeight = particleGraphics.height / 2; // Use actual particle asset height var fieldHalfWidth = field.children[0].width / 2; // Use actual interference field asset width var fieldHalfHeight = field.children[0].height / 2; // Use actual interference field asset height var isColliding = Math.abs(self.x - field.x) < particleHalfWidth + fieldHalfWidth && Math.abs(self.y - field.y) < particleHalfHeight + fieldHalfHeight; if (isColliding) { if (isTutorial) { // In tutorial, just show educational message instead of resetting if (tutorialStep >= 7) { tutorialText.setText('You touched an interference field!\nIn real levels, this would reset the level.'); LK.effects.flashObject(self, 0xff0000, 500); } } else { resetLevel(); return; } } } } // Handle entanglement if (self.entangledWith && !self.isBeingDragged && self.entangledWith.isBeingDragged) { self.x = self.entangledWith.x + 150; self.y = self.entangledWith.y; // Maintain proper alpha based on current dimension var targetAlpha = self.dimension === currentDimension ? 1.0 : 0.15; self.alpha = targetAlpha; } }; self.down = function (x, y, obj) { // Drag handling is now managed by game.down event handler }; return self; }); var Portal = Container.expand(function () { var self = Container.call(this); var portalGraphics = self.attachAsset('portal', { anchorX: 0.5, anchorY: 0.5 }); self.dimension = 0; self.targetDimension = 1; self.setDimension = function (dim) { self.dimension = dim; self.alpha = 1.0; }; self.update = function () { // Direct rotation update portalGraphics.rotation += 0.02; // Check if particles are transported through portal for (var i = 0; i < particles.length; i++) { var particle = particles[i]; if (particle.dimension === self.dimension && !particle.isBeingDragged) { // Use actual asset dimensions for accurate collision detection var portalHalfWidth = portalGraphics.width / 2; // Use actual portal asset width var portalHalfHeight = portalGraphics.height / 2; // Use actual portal asset height var particleHalfWidth = particle.children[0].width / 2; // Use actual particle asset width var particleHalfHeight = particle.children[0].height / 2; // Use actual particle asset height var isColliding = Math.abs(self.x - particle.x) < portalHalfWidth + particleHalfWidth && Math.abs(self.y - particle.y) < portalHalfHeight + particleHalfHeight; if (isColliding) { particle.setDimension(self.targetDimension); LK.getSound('portalSound').play(); LK.effects.flashObject(self, 0xffffff, 300); } } } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); self.type = 'timeBoost'; // Default type self.dimension = 0; self.isCollected = false; self.powerUpGraphics = null; self.floatOffset = Math.random() * Math.PI * 2; self.floatSpeed = 0.02 + Math.random() * 0.01; self.glowDirection = 1; self.glowIntensity = 1.0; self.setType = function (type) { self.type = type; if (self.powerUpGraphics) { self.powerUpGraphics.destroy(); } var assetName = type === 'timeBoost' ? 'timeBoost' : type === 'shield' ? 'shieldPower' : 'slowMotion'; self.powerUpGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); }; self.setDimension = function (dim) { self.dimension = dim; self.alpha = 1.0; }; self.collect = function () { self.isCollected = true; LK.getSound('powerUpSound').play(); // Collect animation with burst effect tween(self, { scaleX: 2.0, scaleY: 2.0, alpha: 0 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { self.visible = false; } }); // Apply power-up effect self.applyEffect(); }; self.applyEffect = function () { if (self.type === 'timeBoost') { timeRemaining += 15000; // Add 15 seconds (increased from 10) LK.effects.flashScreen(0x00ff00, 300); showPowerUpSpec('TIME BOOST', '+15 seconds', 0x00ff00); } else if (self.type === 'shield') { shieldActive = true; shieldTimeRemaining = 12000; // 12 seconds of shield (increased from 8) LK.effects.flashScreen(0x0088ff, 300); showPowerUpSpec('SHIELD', '12 seconds protection', 0x0088ff); } else if (self.type === 'slowMotion') { slowMotionActive = true; slowMotionTimeRemaining = 10000; // 10 seconds of slow motion (increased from 6) LK.effects.flashScreen(0xff8800, 300); showPowerUpSpec('SLOW MOTION', '10 seconds effect', 0xff8800); } }; self.update = function () { if (self.isCollected) return; // Initialize collision tracking if (self.lastPlayerIntersecting === undefined) { self.lastPlayerIntersecting = false; } // Floating animation self.y += Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 0.5; // Glow effect self.glowIntensity += self.glowDirection * 0.02; if (self.glowIntensity > 1.3) { self.glowIntensity = 1.3; self.glowDirection = -1; } else if (self.glowIntensity < 0.7) { self.glowIntensity = 0.7; self.glowDirection = 1; } self.scaleX = self.glowIntensity; self.scaleY = self.glowIntensity; // Rotation for visual appeal if (self.powerUpGraphics) { self.powerUpGraphics.rotation += 0.03; } // Update visibility based on current dimension var targetAlpha = self.dimension === currentDimension ? self.glowIntensity : 0.15; if (Math.abs(self.alpha - targetAlpha) > 0.05) { self.alpha = targetAlpha; } // Check collision with all particles in current dimension var currentPlayerIntersecting = false; for (var p = 0; p < particles.length; p++) { var particle = particles[p]; if (particle.dimension === self.dimension && particle.dimension === currentDimension && !particle.isCollected) { // Use actual asset dimensions for accurate collision detection var powerUpHalfWidth = self.powerUpGraphics.width / 2; // Use actual power-up asset width var powerUpHalfHeight = self.powerUpGraphics.height / 2; // Use actual power-up asset height var particleHalfWidth = particle.children[0].width / 2; // Use actual particle asset width var particleHalfHeight = particle.children[0].height / 2; // Use actual particle asset height var isColliding = Math.abs(self.x - particle.x) < powerUpHalfWidth + particleHalfWidth && Math.abs(self.y - particle.y) < powerUpHalfHeight + particleHalfHeight; if (isColliding) { currentPlayerIntersecting = true; break; } } } if (!self.lastPlayerIntersecting && currentPlayerIntersecting) { self.collect(); } self.lastPlayerIntersecting = currentPlayerIntersecting; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000033 }); /**** * Game Code ****/ var currentDimension = 0; var totalDimensions = 2; var particles = []; var portals = []; var interferenceFields = []; var quantumCore; var draggedParticle = null; var dragOffset = { x: 0, y: 0 }; var particlesCollected = 0; var totalParticles = 0; var level = 0; // Start with tutorial level (level 0) var timeLimit = 25000; // 25 seconds in milliseconds var timeRemaining = timeLimit; var timerActive = false; var dimensionSwitches = 0; var maxDimensionSwitches = 5; var backgroundStars = []; var powerUps = []; var shieldActive = false; var shieldTimeRemaining = 0; var slowMotionActive = false; var slowMotionTimeRemaining = 0; var powerUpSpawnTimer = 0; var powerUpSpawnInterval = 8000; // Spawn power-up every 8 seconds var isTutorial = true; var tutorialStep = 0; var tutorialComplete = false; var tutorialText = null; // UI Elements var dimensionText = new Text2('Dimension: 0', { size: 60, fill: 0xFFFFFF }); dimensionText.anchor.set(0.5, 0); LK.gui.top.addChild(dimensionText); var levelText = new Text2('Level: 1', { size: 50, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); levelText.y = 100; LK.gui.top.addChild(levelText); var instructionText = new Text2('Tap to switch dimensions', { size: 40, fill: 0xCCCCCC }); instructionText.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionText); var timerText = new Text2('Time: 25s', { size: 50, fill: 0xFFFFFF }); timerText.anchor.set(0.5, 0); timerText.y = 160; LK.gui.top.addChild(timerText); var shieldText = new Text2('SHIELD ACTIVE', { size: 45, fill: 0x0088ff }); shieldText.anchor.set(0.5, 0); shieldText.y = 220; shieldText.visible = false; LK.gui.top.addChild(shieldText); var slowMotionText = new Text2('SLOW MOTION', { size: 45, fill: 0xff8800 }); slowMotionText.anchor.set(0.5, 0); slowMotionText.y = 280; slowMotionText.visible = false; LK.gui.top.addChild(slowMotionText); // Tutorial text - larger and more visible tutorialText = new Text2('Welcome to Quantum Dimensions!', { size: 55, fill: 0x00ff88 }); tutorialText.anchor.set(0.5, 0.5); tutorialText.x = 1024; tutorialText.y = 500; // Better positioning tutorialText.visible = false; game.addChild(tutorialText); // Create dimension indicators var dimensionIndicators = []; for (var d = 0; d < totalDimensions; d++) { var indicator = LK.getAsset('dimensionIndicator', { anchorX: 0.5, anchorY: 0.5, x: 1024 + d * 60, y: 150 }); dimensionIndicators.push(indicator); LK.gui.addChild(indicator); } function initializeLevel() { // Clear existing elements for (var i = 0; i < particles.length; i++) { particles[i].destroy(); } for (var i = 0; i < portals.length; i++) { portals[i].destroy(); } for (var i = 0; i < interferenceFields.length; i++) { interferenceFields[i].destroy(); } for (var i = 0; i < backgroundStars.length; i++) { backgroundStars[i].destroy(); } for (var i = 0; i < powerUps.length; i++) { powerUps[i].destroy(); } backgroundStars = []; particles = []; portals = []; interferenceFields = []; powerUps = []; particlesCollected = 0; currentDimension = 0; // Reset and start timer - reduced time penalty for easier gameplay var timeReduction = (level - 1) * 800; // Reduced from 1500 to 800 // Extra time reduction for extreme levels - less harsh if (level >= 11) { timeReduction += (level - 10) * 200; // Reduced from 500 to 200 } if (level >= 16) { timeReduction += (level - 15) * 100; // Reduced from 300 to 100 } timeRemaining = Math.max(12000, timeLimit - timeReduction); // Increased minimum from 6 to 12 seconds timerActive = true; dimensionSwitches = 0; maxDimensionSwitches = Math.max(12, 18 - Math.min(level, 4)); // More switches allowed, minimum 12 (increased from 8) // Reset power-up system shieldActive = false; shieldTimeRemaining = 0; slowMotionActive = false; slowMotionTimeRemaining = 0; powerUpSpawnTimer = 0; shieldText.visible = false; slowMotionText.visible = false; // Create quantum core if (quantumCore) { quantumCore.destroy(); } quantumCore = game.addChild(LK.getAsset('quantumCore', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 800 })); // Create background star field var numStars = 80 + level * 15; for (var i = 0; i < numStars; i++) { var star = game.addChild(new BackgroundStar()); star.x = Math.random() * 2048; star.y = Math.random() * 2732; star.scaleX = 0.5 + Math.random() * 1.5; star.scaleY = star.scaleX; backgroundStars.push(star); } // Create orbital particles around quantum core for (var i = 0; i < 8; i++) { var orbitalStar = game.addChild(new BackgroundStar()); var angle = i / 8 * Math.PI * 2; var radius = 200 + Math.random() * 100; orbitalStar.x = quantumCore.x + Math.cos(angle) * radius; orbitalStar.y = quantumCore.y + Math.sin(angle) * radius; orbitalStar.scaleX = 1.5; orbitalStar.scaleY = 1.5; orbitalStar.orbitalAngle = angle; orbitalStar.orbitalRadius = radius; orbitalStar.orbitalSpeed = 0.01 + Math.random() * 0.02; backgroundStars.push(orbitalStar); } // Tutorial level setup (Level 0) if (level === 0) { isTutorial = true; tutorialStep = 0; tutorialComplete = false; timerActive = false; // No timer pressure in tutorial maxDimensionSwitches = 999; // Unlimited switches for tutorial tutorialText.visible = true; tutorialText.setText('Welcome to Quantum Dimensions!'); // Single particle in dimension 0 for simple drag tutorial var tutorialParticle = game.addChild(new Particle()); tutorialParticle.x = 300; tutorialParticle.y = 1800; tutorialParticle.setDimension(0); tutorialParticle.lastCoreIntersecting = false; tutorialParticle.isBeingDragged = false; tutorialParticle.isCollected = false; tutorialParticle.dimension = 0; // Ensure dimension is properly set particles.push(tutorialParticle); // Add a second particle in dimension 1 to demonstrate dimension switching var tutorialParticle2 = game.addChild(new Particle()); tutorialParticle2.x = 1700; tutorialParticle2.y = 1800; tutorialParticle2.setDimension(1); tutorialParticle2.lastCoreIntersecting = false; tutorialParticle2.isBeingDragged = false; tutorialParticle2.isCollected = false; tutorialParticle2.dimension = 1; // Ensure dimension is properly set particles.push(tutorialParticle2); // Add a safe interference field for demonstration (not dangerous in tutorial) var demoField = game.addChild(new InterferenceField()); demoField.x = 1024; demoField.y = 2200; demoField.setDimension(0); demoField.alpha = 0.3; // Make it less threatening interferenceFields.push(demoField); // Add a portal for demonstration var demoPortal = game.addChild(new Portal()); demoPortal.x = 1024; demoPortal.y = 1400; demoPortal.dimension = 0; demoPortal.targetDimension = 1; demoPortal.setDimension(0); demoPortal.alpha = 0.5; // Make it visible but not distracting portals.push(demoPortal); totalParticles = 2; // Count both particles for tutorial completion // Show tutorial instructions immediately LK.setTimeout(function () { updateTutorialStep(); }, 500); } else if (level === 1) { // Reset tutorial flags for actual gameplay isTutorial = false; tutorialText.visible = false; timerActive = true; // Simple particles in different dimensions var particle1 = game.addChild(new Particle()); particle1.x = 300; particle1.y = 1600; particle1.setDimension(0); particle1.lastCoreIntersecting = false; particle1.isBeingDragged = false; particle1.isCollected = false; particles.push(particle1); var particle2 = game.addChild(new Particle()); particle2.x = 1700; particle2.y = 1600; particle2.setDimension(1); particle2.lastCoreIntersecting = false; particle2.isBeingDragged = false; particle2.isCollected = false; particles.push(particle2); // Portal to connect dimensions var portal1 = game.addChild(new Portal()); portal1.x = 1024; portal1.y = 1600; portal1.dimension = 0; portal1.targetDimension = 1; portal1.setDimension(0); portals.push(portal1); totalParticles = 2; } else { // Progressive levels with more complexity - reduced interference fields var numParticles = Math.min(level + 1, 4); var numFields = Math.min(Math.max(0, level - 1), 4); // Fewer interference fields, starting from level 2 for (var i = 0; i < numParticles; i++) { var particle = game.addChild(new Particle()); particle.x = 200 + i * 400; particle.y = 1800 + i % 2 * 400; particle.setDimension(i % totalDimensions); particle.lastCoreIntersecting = false; particle.isBeingDragged = false; particle.isCollected = false; particles.push(particle); } // Create entangled pairs for higher levels if (level >= 3 && particles.length >= 2) { particles[0].entangledWith = particles[1]; particles[1].entangledWith = particles[0]; } // Create portals for (var i = 0; i < 2; i++) { var portal = game.addChild(new Portal()); portal.x = 400 + i * 1200; portal.y = 1200; portal.dimension = i; portal.targetDimension = (i + 1) % totalDimensions; portal.setDimension(i); portals.push(portal); } // Create interference fields for (var i = 0; i < numFields; i++) { var field = game.addChild(new InterferenceField()); field.x = 300 + i * 600; field.y = 1000 + i % 2 * 400; field.setDimension(i % totalDimensions); // Add movement to interference fields for higher levels if (level >= 2) { field.moveDirection = i % 2 === 0 ? 1 : -1; field.minX = 100; field.maxX = 1948; } interferenceFields.push(field); } // Add additional moving barriers for higher levels if (level >= 2) { var movingField = game.addChild(new InterferenceField()); movingField.x = 1024; movingField.y = 1400; movingField.setDimension(0); movingField.moveDirection = 1; movingField.minX = 200; movingField.maxX = 1848; interferenceFields.push(movingField); } // Add second moving barrier for level 3+ if (level >= 3) { var movingField2 = game.addChild(new InterferenceField()); movingField2.x = 500; movingField2.y = 2000; movingField2.setDimension(1); movingField2.moveDirection = -1; movingField2.minX = 100; movingField2.maxX = 1948; interferenceFields.push(movingField2); } // Add third moving barrier for level 4+ if (level >= 4) { var movingField3 = game.addChild(new InterferenceField()); movingField3.x = 1500; movingField3.y = 1600; movingField3.setDimension(0); movingField3.moveDirection = 1; movingField3.minX = 300; movingField3.maxX = 1700; interferenceFields.push(movingField3); } // Add fourth moving barrier for level 5+ if (level >= 5) { var movingField4 = game.addChild(new InterferenceField()); movingField4.x = 800; movingField4.y = 1800; movingField4.setDimension(1); movingField4.moveDirection = -1; movingField4.minX = 200; movingField4.maxX = 1800; interferenceFields.push(movingField4); } // Advanced levels 6-10 with additional challenges if (level >= 6) { // Add more particles for higher levels var extraParticles = Math.min(level - 5, 3); for (var j = 0; j < extraParticles; j++) { var extraParticle = game.addChild(new Particle()); extraParticle.x = 400 + j * 300; extraParticle.y = 2200 + j % 2 * 200; extraParticle.setDimension(j % totalDimensions); extraParticle.lastCoreIntersecting = false; extraParticle.isBeingDragged = false; extraParticle.isCollected = false; particles.push(extraParticle); } totalParticles += extraParticles; // Add additional moving barriers var numExtraFields = Math.min(level - 5, 4); for (var k = 0; k < numExtraFields; k++) { var extraField = game.addChild(new InterferenceField()); extraField.x = 200 + k * 400; extraField.y = 1300 + k % 2 * 300; extraField.setDimension(k % totalDimensions); extraField.moveDirection = k % 2 === 0 ? 1 : -1; extraField.minX = 100; extraField.maxX = 1948; interferenceFields.push(extraField); } } // Level 8+ speed increase is now handled in the InterferenceField update method // Level 10 gets entangled triplets if (level >= 10 && particles.length >= 3) { particles[0].entangledWith = particles[1]; particles[1].entangledWith = particles[2]; particles[2].entangledWith = particles[0]; } // Advanced levels 11-15 with extreme challenges if (level >= 11) { // Add even more particles for extreme levels var extremeParticles = Math.min(level - 10, 5); for (var m = 0; m < extremeParticles; m++) { var extremeParticle = game.addChild(new Particle()); extremeParticle.x = 150 + m * 250; extremeParticle.y = 2400 + m % 2 * 150; extremeParticle.setDimension(m % totalDimensions); extremeParticle.lastCoreIntersecting = false; extremeParticle.isBeingDragged = false; extremeParticle.isCollected = false; particles.push(extremeParticle); } totalParticles += extremeParticles; // Add maze-like interference field patterns var mazeFields = Math.min(level - 10, 6); for (var n = 0; n < mazeFields; n++) { var mazeField = game.addChild(new InterferenceField()); mazeField.x = 300 + n * 200; mazeField.y = 1100 + n % 3 * 200; mazeField.setDimension(n % totalDimensions); mazeField.moveDirection = n % 2 === 0 ? 1 : -1; mazeField.minX = 50; mazeField.maxX = 1998; interferenceFields.push(mazeField); } } // Master levels 16-20 with ultimate difficulty if (level >= 16) { // Add master-level particles var masterParticles = Math.min(level - 15, 4); for (var p = 0; p < masterParticles; p++) { var masterParticle = game.addChild(new Particle()); masterParticle.x = 200 + p * 400; masterParticle.y = 2500 + p % 2 * 100; masterParticle.setDimension(p % totalDimensions); masterParticle.lastCoreIntersecting = false; masterParticle.isBeingDragged = false; masterParticle.isCollected = false; particles.push(masterParticle); } totalParticles += masterParticles; // Create complex entanglement networks if (particles.length >= 4) { for (var q = 0; q < Math.min(particles.length - 1, 6); q++) { if (q + 1 < particles.length) { particles[q].entangledWith = particles[q + 1]; } } } // Add ultra-fast moving barriers var ultraFields = Math.min(level - 15, 8); for (var r = 0; r < ultraFields; r++) { var ultraField = game.addChild(new InterferenceField()); ultraField.x = 100 + r * 180; ultraField.y = 1200 + r % 4 * 150; ultraField.setDimension(r % totalDimensions); ultraField.moveDirection = r % 2 === 0 ? 1 : -1; ultraField.minX = 50; ultraField.maxX = 1998; interferenceFields.push(ultraField); } } // Calculate total particles correctly for all levels totalParticles = particles.length; } updateDimensionDisplay(); if (level === 0) { levelText.setText('Tutorial'); } else { levelText.setText('Level: ' + level); } } function updateDimensionDisplay() { dimensionText.setText('Dimension: ' + currentDimension); instructionText.setText('Switches: ' + dimensionSwitches + '/' + maxDimensionSwitches + ' - Tap to switch'); for (var i = 0; i < dimensionIndicators.length; i++) { var indicator = dimensionIndicators[i]; tween(indicator, { alpha: i === currentDimension ? 1.0 : 0.3, scaleX: i === currentDimension ? 1.5 : 1.0, scaleY: i === currentDimension ? 1.5 : 1.0 }, { duration: 300, easing: tween.easeOut }); } // Update all objects for dimension visibility for (var i = 0; i < particles.length; i++) { var targetAlpha = particles[i].dimension === currentDimension ? 1.0 : 0.15; tween(particles[i], { alpha: targetAlpha }, { duration: 200, easing: tween.easeInOut }); } for (var i = 0; i < portals.length; i++) { var targetAlpha = portals[i].dimension === currentDimension ? 1.0 : 0.1; tween(portals[i], { alpha: targetAlpha }, { duration: 200, easing: tween.easeInOut }); } for (var i = 0; i < interferenceFields.length; i++) { var targetAlpha = interferenceFields[i].dimension === currentDimension ? 0.8 : 0.1; tween(interferenceFields[i], { alpha: targetAlpha }, { duration: 200, easing: tween.easeInOut }); } for (var i = 0; i < powerUps.length; i++) { var targetAlpha = powerUps[i].dimension === currentDimension ? 1.0 : 0.15; tween(powerUps[i], { alpha: targetAlpha }, { duration: 200, easing: tween.easeInOut }); } } function switchDimension() { if (dimensionSwitches >= maxDimensionSwitches && !isTutorial) { LK.effects.flashScreen(0xFF0000, 200); return; // No more switches allowed (except in tutorial) } dimensionSwitches++; // Remove time penalty to make dimension switching more accessible currentDimension = (currentDimension + 1) % totalDimensions; updateDimensionDisplay(); LK.getSound('dimensionShift').play(); LK.effects.flashScreen(0x440088, 200); // Tutorial progress tracking if (isTutorial) { if (tutorialStep === 3) { tutorialStep = 4; // Add celebratory flash for successful dimension switch LK.effects.flashScreen(0x00ff88, 300); LK.setTimeout(function () { updateTutorialStep(); }, 800); } else if (tutorialStep === 4 && currentDimension === 1) { // Player successfully switched to dimension 1 tutorialStep = 5; LK.setTimeout(function () { updateTutorialStep(); }, 1200); } } } function checkWinCondition() { if (particlesCollected >= totalParticles) { timerActive = false; // Stop timer when level complete if (isTutorial) { if (particlesCollected === 1 && tutorialStep <= 3) { // First particle collected, advance tutorial tutorialStep = 3; updateTutorialStep(); return; } else if (particlesCollected >= 2) { // All particles collected in tutorial, complete it if (tutorialStep < 6) { tutorialStep = 6; updateTutorialStep(); } else if (tutorialComplete || tutorialStep >= 10) { // Tutorial is complete, move to level 1 level = 1; isTutorial = false; tutorialText.visible = false; initializeLevel(); } return; } } level++; LK.setTimeout(function () { if (level > 20) { LK.showYouWin(); } else { initializeLevel(); } }, 1000); } } function resetLevel() { // Check if shield is active to prevent death if (shieldActive) { shieldActive = false; shieldTimeRemaining = 0; shieldText.visible = false; LK.effects.flashScreen(0x0088ff, 300); return; // Shield absorbed the hit } LK.effects.flashScreen(0xff0000, 500); LK.setTimeout(function () { initializeLevel(); }, 600); } function spawnPowerUp() { if (powerUps.length >= 2) return; // Maximum 2 power-ups on screen var powerUp = game.addChild(new PowerUp()); // Ensure power-ups spawn in safe areas away from interference fields var safePosition = false; var attempts = 0; var spawnX, spawnY; while (!safePosition && attempts < 10) { spawnX = 300 + Math.random() * 1448; spawnY = 600 + Math.random() * 800; // Check distance from interference fields safePosition = true; for (var f = 0; f < interferenceFields.length; f++) { var field = interferenceFields[f]; var distance = Math.sqrt((spawnX - field.x) * (spawnX - field.x) + (spawnY - field.y) * (spawnY - field.y)); if (distance < 200) { safePosition = false; break; } } attempts++; } powerUp.x = spawnX || 300 + Math.random() * 1448; powerUp.y = spawnY || 600 + Math.random() * 800; powerUp.setDimension(currentDimension); // Always spawn in current dimension for better accessibility // Random power-up type var types = ['timeBoost', 'shield', 'slowMotion']; var randomType = types[Math.floor(Math.random() * types.length)]; powerUp.setType(randomType); powerUp.lastPlayerIntersecting = false; powerUps.push(powerUp); } // Event handlers game.down = function (x, y, obj) { var hitParticle = false; for (var i = 0; i < particles.length; i++) { var particle = particles[i]; if (particle.dimension === currentDimension && !particle.isCollected && particle.alpha > 0.5) { // Use actual asset dimensions for accurate touch detection var halfWidth = particle.children[0].width / 2; // Use actual particle asset width var halfHeight = particle.children[0].height / 2; // Use actual particle asset height // Check if touch point is within particle bounds if (x >= particle.x - halfWidth && x <= particle.x + halfWidth && y >= particle.y - halfHeight && y <= particle.y + halfHeight) { draggedParticle = particle; particle.startDrag(); dragOffset.x = x - particle.x; dragOffset.y = y - particle.y; hitParticle = true; break; } } } if (!hitParticle) { switchDimension(); } }; game.move = function (x, y, obj) { if (draggedParticle && !draggedParticle.isCollected) { var targetX = x - dragOffset.x; var targetY = y - dragOffset.y; // Keep particle within bounds targetX = Math.max(80, Math.min(1968, targetX)); targetY = Math.max(80, Math.min(2652, targetY)); // Direct position update for responsive dragging draggedParticle.x = targetX; draggedParticle.y = targetY; // Reduce trail effect frequency to improve performance if (LK.ticks % 10 === 0) { var trailStar = game.addChild(new BackgroundStar()); trailStar.x = draggedParticle.x + (Math.random() - 0.5) * 20; trailStar.y = draggedParticle.y + (Math.random() - 0.5) * 20; trailStar.scaleX = 0.8; trailStar.scaleY = 0.8; trailStar.alpha = 0.8; // Fade out trail particle tween(trailStar, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { trailStar.destroy(); } }); } // Handle entangled particle movement with direct updates if (draggedParticle.entangledWith) { // Only move entangled particles when BOTH the dragged particle AND the entangled particle are in the current dimension // This prevents cross-dimensional interference where particles in other dimensions move unexpectedly if (draggedParticle.dimension === currentDimension && draggedParticle.entangledWith.dimension === currentDimension) { draggedParticle.entangledWith.x = targetX + 150; draggedParticle.entangledWith.y = targetY; } // Ensure entangled particles maintain proper alpha based on current dimension var entangledTargetAlpha = draggedParticle.entangledWith.dimension === currentDimension ? 1.0 : 0.15; draggedParticle.entangledWith.alpha = entangledTargetAlpha; } } }; game.up = function (x, y, obj) { if (draggedParticle) { draggedParticle.stopDrag(); draggedParticle = null; } }; game.update = function () { // Handle timer countdown if (timerActive) { var timeDecrement = slowMotionActive ? 8.33 : 16.67; // Slow motion halves time consumption timeRemaining -= timeDecrement; if (timeRemaining <= 0) { resetLevel(); return; } var seconds = Math.ceil(timeRemaining / 1000); timerText.setText('Time: ' + seconds + 's'); // Smooth color transitions when time is running out if (seconds <= 5) { tween(timerText, { tint: 0xFF0000 }, { duration: 200, easing: tween.easeOut }); } else if (seconds <= 10) { tween(timerText, { tint: 0xFFFF00 }, { duration: 200, easing: tween.easeOut }); } else { tween(timerText, { tint: 0xFFFFFF }, { duration: 200, easing: tween.easeOut }); } } // Animate quantum core with direct property updates if (quantumCore) { // Direct rotation update quantumCore.rotation += 0.02; // Direct pulsing animation var pulse = Math.sin(LK.ticks * 0.08) * 0.15 + 1.0; quantumCore.scaleX = pulse; quantumCore.scaleY = pulse; // Reduced frequency color cycling if (LK.ticks % 60 === 0) { var colorPhase = LK.ticks * 0.015; var r = Math.sin(colorPhase) * 0.4 + 0.6; var g = Math.sin(colorPhase + 2) * 0.4 + 0.6; var b = Math.sin(colorPhase + 4) * 0.4 + 0.6; var color = Math.floor(r * 255) << 16 | Math.floor(g * 255) << 8 | Math.floor(b * 255); quantumCore.tint = color; } } // Update all particles for (var i = 0; i < particles.length; i++) { if (particles[i].update) { particles[i].update(); } } // Update all portals for (var i = 0; i < portals.length; i++) { if (portals[i].update) { portals[i].update(); } } // Update all interference fields for (var i = 0; i < interferenceFields.length; i++) { if (interferenceFields[i].update) { interferenceFields[i].update(); } } // Handle power-up spawning if (timerActive) { powerUpSpawnTimer += 16.67; // Calculate dynamic spawn interval based on level - more frequent power-ups var dynamicSpawnInterval = powerUpSpawnInterval; if (level >= 5) { dynamicSpawnInterval = Math.max(3000, powerUpSpawnInterval - (level - 4) * 300); // Faster spawning for higher levels, minimum 3 seconds (reduced from 4) } if (powerUpSpawnTimer >= dynamicSpawnInterval) { spawnPowerUp(); powerUpSpawnTimer = 0; } } // Handle shield duration if (shieldActive) { shieldTimeRemaining -= 16.67; if (shieldTimeRemaining <= 0) { shieldActive = false; shieldText.visible = false; } else { shieldText.visible = true; shieldText.setText('SHIELD: ' + Math.ceil(shieldTimeRemaining / 1000) + 's'); } } // Handle slow motion duration if (slowMotionActive) { slowMotionTimeRemaining -= 16.67; if (slowMotionTimeRemaining <= 0) { slowMotionActive = false; slowMotionText.visible = false; } else { slowMotionText.visible = true; slowMotionText.setText('SLOW MOTION: ' + Math.ceil(slowMotionTimeRemaining / 1000) + 's'); } } // Update power-ups for (var i = powerUps.length - 1; i >= 0; i--) { if (powerUps[i].update) { powerUps[i].update(); } // Remove collected power-ups if (powerUps[i].isCollected && !powerUps[i].visible) { powerUps[i].destroy(); powerUps.splice(i, 1); } } // Update background stars for (var i = 0; i < backgroundStars.length; i++) { var star = backgroundStars[i]; if (star.update) { star.update(); } // Handle orbital motion for core particles if (star.orbitalAngle !== undefined && quantumCore) { star.orbitalAngle += star.orbitalSpeed; star.x = quantumCore.x + Math.cos(star.orbitalAngle) * star.orbitalRadius; star.y = quantumCore.y + Math.sin(star.orbitalAngle) * star.orbitalRadius; } } }; function updateTutorialStep() { if (!isTutorial) return; // Ensure tutorial text is visible and properly positioned tutorialText.visible = true; tutorialText.alpha = 1.0; // Position tutorial text in center area for better visibility tutorialText.x = 1024; tutorialText.y = 500; // Better positioning for readability // Ensure text is on top and visible game.removeChild(tutorialText); game.addChild(tutorialText); switch (tutorialStep) { case 0: tutorialText.setText('Welcome to Quantum Dimensions!\nMove particles to the center core to collect them.'); LK.setTimeout(function () { tutorialStep = 1; updateTutorialStep(); }, 2500); break; case 1: tutorialText.setText('STEP 1: DRAG A PARTICLE\nTouch and drag the glowing particle below.'); // Add visual hint by pulsing the particle if (particles.length > 0 && particles[0].dimension === currentDimension) { LK.effects.flashObject(particles[0], 0x00ff00, 1500); // Keep flashing until moved LK.setInterval(function () { if (tutorialStep === 1 && !particles[0].isBeingDragged) { LK.effects.flashObject(particles[0], 0x00ff00, 800); } }, 1000); } break; case 2: tutorialText.setText('STEP 2: MOVE TO CENTER\nDrag the particle to the quantum core (glowing center).'); // Add visual hint by flashing the quantum core if (quantumCore) { LK.effects.flashObject(quantumCore, 0x00ffff, 2000); // Keep flashing until collected LK.setInterval(function () { if (tutorialStep === 2 && quantumCore) { LK.effects.flashObject(quantumCore, 0x00ffff, 1000); } }, 1500); } break; case 3: tutorialText.setText('GREAT! Particle collected!\nNow tap empty space to switch dimensions.'); break; case 4: tutorialText.setText('STEP 3: DIMENSION SWITCHING\nYou switched to Dimension 1! See the other particle?'); if (particles.length > 1 && particles[1].dimension === currentDimension) { LK.effects.flashObject(particles[1], 0x00ff00, 1500); } LK.setTimeout(function () { tutorialStep = 5; updateTutorialStep(); }, 2500); break; case 5: tutorialText.setText('STEP 4: COLLECT SECOND PARTICLE\nDrag this particle to the center too.'); if (particles.length > 1 && particles[1].dimension === currentDimension) { LK.effects.flashObject(particles[1], 0x00ff00, 1500); // Keep flashing until collected LK.setInterval(function () { if (tutorialStep === 5 && particles.length > 1 && !particles[1].isCollected) { LK.effects.flashObject(particles[1], 0x00ff00, 800); } }, 1200); } break; case 6: tutorialText.setText('PERFECT! You mastered the basics!\nRemember: Limited dimension switches in real levels.'); LK.setTimeout(function () { tutorialStep = 7; updateTutorialStep(); }, 2500); break; case 7: tutorialText.setText('WARNING: RED FIELDS = DANGER\nAvoid red interference fields - they reset the level!'); // Flash the demo interference field to show danger for (var i = 0; i < interferenceFields.length; i++) { LK.effects.flashObject(interferenceFields[i], 0xff0000, 2000); } LK.setTimeout(function () { tutorialStep = 8; updateTutorialStep(); }, 3000); break; case 8: tutorialText.setText('BLUE PORTALS = TRANSPORT\nPortals move particles between dimensions.'); // Flash the demo portal for (var i = 0; i < portals.length; i++) { LK.effects.flashObject(portals[i], 0x0088ff, 2000); } LK.setTimeout(function () { tutorialStep = 9; updateTutorialStep(); }, 3000); break; case 9: tutorialText.setText('POWER-UPS HELP YOU:\n🟢 Time Boost 🔵 Shield 🟡 Slow Motion'); LK.setTimeout(function () { tutorialStep = 10; updateTutorialStep(); }, 3500); break; case 10: tutorialText.setText('🎉 TUTORIAL COMPLETE! 🎉\nReady for the real challenge? Starting Level 1...'); LK.setTimeout(function () { tutorialComplete = true; checkWinCondition(); // Use existing function to transition properly }, 3000); break; } } function showPowerUpSpec(title, description, color) { // Create power-up specification display var specContainer = new Container(); // Title text var titleText = new Text2(title, { size: 60, fill: color }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 1300; specContainer.addChild(titleText); // Description text var descText = new Text2(description, { size: 45, fill: 0xFFFFFF }); descText.anchor.set(0.5, 0.5); descText.x = 1024; descText.y = 1380; specContainer.addChild(descText); // Add to game game.addChild(specContainer); // Initial state specContainer.alpha = 0; specContainer.scaleX = 0.3; specContainer.scaleY = 0.3; // Animation: fade in and scale up tween(specContainer, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Hold for a moment then fade out LK.setTimeout(function () { tween(specContainer, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 400, easing: tween.easeIn, onFinish: function onFinish() { specContainer.destroy(); } }); }, 2000); } }); } // Initialize first level initializeLevel();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BackgroundStar = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.twinkleSpeed = 0.02 + Math.random() * 0.03;
self.twinkleOffset = Math.random() * Math.PI * 2;
self.baseAlpha = 0.3 + Math.random() * 0.7;
self.update = function () {
// Direct property updates instead of creating tweens every frame
var twinkle = Math.sin(LK.ticks * self.twinkleSpeed + self.twinkleOffset) * 0.3 + 0.7;
self.alpha = self.baseAlpha * twinkle;
// Direct position updates for smooth movement
self.x += Math.sin(LK.ticks * 0.01 + self.twinkleOffset) * 0.02;
self.y += Math.cos(LK.ticks * 0.008 + self.twinkleOffset) * 0.015;
};
return self;
});
var InterferenceField = Container.expand(function () {
var self = Container.call(this);
var fieldGraphics = self.attachAsset('interferenceField', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xff4444
});
self.dimension = 0;
self.pulseDirection = 1;
self.setDimension = function (dim) {
self.dimension = dim;
self.alpha = 0.8;
};
self.update = function () {
// Direct rotation update
fieldGraphics.rotation += 0.015;
// Direct alpha updates instead of creating tweens every frame
if (self.dimension === currentDimension) {
self.alpha = 0.9 + Math.sin(LK.ticks * 0.05) * 0.3;
// Add bright glow effect with color cycling
var glowIntensity = Math.sin(LK.ticks * 0.08) * 0.5 + 0.5;
fieldGraphics.tint = 0xff0000 + Math.floor(glowIntensity * 0x4444);
} else {
self.alpha = 0.4;
fieldGraphics.tint = 0xff4444;
}
// Direct position updates for moving fields - reduced speeds for easier gameplay
if (self.moveDirection !== undefined) {
var moveSpeed = 2.5; // Reduced from 4 to 2.5
// Increase speed for level 8+
if (level >= 8) {
moveSpeed = 3.5; // Reduced from 6 to 3.5
}
// Ultra-fast speed for level 16+
if (level >= 16) {
moveSpeed = 5; // Reduced from 9 to 5
}
// Extreme speed for level 11+
if (level >= 11) {
moveSpeed = 4; // Reduced from 7 to 4
}
self.x += self.moveDirection * moveSpeed;
if (self.x <= self.minX || self.x >= self.maxX) {
self.moveDirection *= -1;
}
}
};
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.dimension = 0;
self.originalPosition = {
x: 0,
y: 0
};
self.isBeingDragged = false;
self.isCollected = false;
self.entangledWith = null;
self.setDimension = function (dim) {
self.dimension = dim;
self.alpha = 1.0;
};
self.startDrag = function () {
self.isBeingDragged = true;
tween(particleGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200
});
};
self.stopDrag = function () {
self.isBeingDragged = false;
tween(particleGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
};
self.collect = function () {
self.isCollected = true;
// Enhanced collection animation with bounce effect
tween(self, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
self.visible = false;
}
});
}
});
// Tutorial step progression for particle collection
if (isTutorial) {
if (tutorialStep === 1 || tutorialStep === 2) {
tutorialStep = 3; // Move to "great job" step
LK.setTimeout(function () {
updateTutorialStep();
}, 800);
} else if (tutorialStep === 5) {
tutorialStep = 6;
LK.setTimeout(function () {
updateTutorialStep();
}, 800);
}
}
};
self.update = function () {
if (self.isCollected) return;
// Initialize collision tracking
if (self.lastCoreIntersecting === undefined) {
self.lastCoreIntersecting = false;
}
// Check collision with quantum core - only trigger on first contact
var currentCoreIntersecting = false;
if (self.dimension === currentDimension && quantumCore) {
// Use actual asset dimensions for accurate collision detection
var particleHalfWidth = particleGraphics.width / 2; // Use actual particle asset width
var particleHalfHeight = particleGraphics.height / 2; // Use actual particle asset height
var coreHalfWidth = quantumCore.width / 2; // Use actual quantum core asset width
var coreHalfHeight = quantumCore.height / 2; // Use actual quantum core asset height
currentCoreIntersecting = Math.abs(self.x - quantumCore.x) < particleHalfWidth + coreHalfWidth && Math.abs(self.y - quantumCore.y) < particleHalfHeight + coreHalfHeight;
}
if (!self.lastCoreIntersecting && currentCoreIntersecting) {
self.collect();
LK.getSound('collectSound').play();
particlesCollected++;
checkWinCondition();
}
self.lastCoreIntersecting = currentCoreIntersecting;
// Check collision with interference fields
for (var i = 0; i < interferenceFields.length; i++) {
var field = interferenceFields[i];
if (field.dimension === self.dimension) {
// Use actual asset dimensions for accurate collision detection
var particleHalfWidth = particleGraphics.width / 2; // Use actual particle asset width
var particleHalfHeight = particleGraphics.height / 2; // Use actual particle asset height
var fieldHalfWidth = field.children[0].width / 2; // Use actual interference field asset width
var fieldHalfHeight = field.children[0].height / 2; // Use actual interference field asset height
var isColliding = Math.abs(self.x - field.x) < particleHalfWidth + fieldHalfWidth && Math.abs(self.y - field.y) < particleHalfHeight + fieldHalfHeight;
if (isColliding) {
if (isTutorial) {
// In tutorial, just show educational message instead of resetting
if (tutorialStep >= 7) {
tutorialText.setText('You touched an interference field!\nIn real levels, this would reset the level.');
LK.effects.flashObject(self, 0xff0000, 500);
}
} else {
resetLevel();
return;
}
}
}
}
// Handle entanglement
if (self.entangledWith && !self.isBeingDragged && self.entangledWith.isBeingDragged) {
self.x = self.entangledWith.x + 150;
self.y = self.entangledWith.y;
// Maintain proper alpha based on current dimension
var targetAlpha = self.dimension === currentDimension ? 1.0 : 0.15;
self.alpha = targetAlpha;
}
};
self.down = function (x, y, obj) {
// Drag handling is now managed by game.down event handler
};
return self;
});
var Portal = Container.expand(function () {
var self = Container.call(this);
var portalGraphics = self.attachAsset('portal', {
anchorX: 0.5,
anchorY: 0.5
});
self.dimension = 0;
self.targetDimension = 1;
self.setDimension = function (dim) {
self.dimension = dim;
self.alpha = 1.0;
};
self.update = function () {
// Direct rotation update
portalGraphics.rotation += 0.02;
// Check if particles are transported through portal
for (var i = 0; i < particles.length; i++) {
var particle = particles[i];
if (particle.dimension === self.dimension && !particle.isBeingDragged) {
// Use actual asset dimensions for accurate collision detection
var portalHalfWidth = portalGraphics.width / 2; // Use actual portal asset width
var portalHalfHeight = portalGraphics.height / 2; // Use actual portal asset height
var particleHalfWidth = particle.children[0].width / 2; // Use actual particle asset width
var particleHalfHeight = particle.children[0].height / 2; // Use actual particle asset height
var isColliding = Math.abs(self.x - particle.x) < portalHalfWidth + particleHalfWidth && Math.abs(self.y - particle.y) < portalHalfHeight + particleHalfHeight;
if (isColliding) {
particle.setDimension(self.targetDimension);
LK.getSound('portalSound').play();
LK.effects.flashObject(self, 0xffffff, 300);
}
}
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.type = 'timeBoost'; // Default type
self.dimension = 0;
self.isCollected = false;
self.powerUpGraphics = null;
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.02 + Math.random() * 0.01;
self.glowDirection = 1;
self.glowIntensity = 1.0;
self.setType = function (type) {
self.type = type;
if (self.powerUpGraphics) {
self.powerUpGraphics.destroy();
}
var assetName = type === 'timeBoost' ? 'timeBoost' : type === 'shield' ? 'shieldPower' : 'slowMotion';
self.powerUpGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
};
self.setDimension = function (dim) {
self.dimension = dim;
self.alpha = 1.0;
};
self.collect = function () {
self.isCollected = true;
LK.getSound('powerUpSound').play();
// Collect animation with burst effect
tween(self, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
self.visible = false;
}
});
// Apply power-up effect
self.applyEffect();
};
self.applyEffect = function () {
if (self.type === 'timeBoost') {
timeRemaining += 15000; // Add 15 seconds (increased from 10)
LK.effects.flashScreen(0x00ff00, 300);
showPowerUpSpec('TIME BOOST', '+15 seconds', 0x00ff00);
} else if (self.type === 'shield') {
shieldActive = true;
shieldTimeRemaining = 12000; // 12 seconds of shield (increased from 8)
LK.effects.flashScreen(0x0088ff, 300);
showPowerUpSpec('SHIELD', '12 seconds protection', 0x0088ff);
} else if (self.type === 'slowMotion') {
slowMotionActive = true;
slowMotionTimeRemaining = 10000; // 10 seconds of slow motion (increased from 6)
LK.effects.flashScreen(0xff8800, 300);
showPowerUpSpec('SLOW MOTION', '10 seconds effect', 0xff8800);
}
};
self.update = function () {
if (self.isCollected) return;
// Initialize collision tracking
if (self.lastPlayerIntersecting === undefined) {
self.lastPlayerIntersecting = false;
}
// Floating animation
self.y += Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 0.5;
// Glow effect
self.glowIntensity += self.glowDirection * 0.02;
if (self.glowIntensity > 1.3) {
self.glowIntensity = 1.3;
self.glowDirection = -1;
} else if (self.glowIntensity < 0.7) {
self.glowIntensity = 0.7;
self.glowDirection = 1;
}
self.scaleX = self.glowIntensity;
self.scaleY = self.glowIntensity;
// Rotation for visual appeal
if (self.powerUpGraphics) {
self.powerUpGraphics.rotation += 0.03;
}
// Update visibility based on current dimension
var targetAlpha = self.dimension === currentDimension ? self.glowIntensity : 0.15;
if (Math.abs(self.alpha - targetAlpha) > 0.05) {
self.alpha = targetAlpha;
}
// Check collision with all particles in current dimension
var currentPlayerIntersecting = false;
for (var p = 0; p < particles.length; p++) {
var particle = particles[p];
if (particle.dimension === self.dimension && particle.dimension === currentDimension && !particle.isCollected) {
// Use actual asset dimensions for accurate collision detection
var powerUpHalfWidth = self.powerUpGraphics.width / 2; // Use actual power-up asset width
var powerUpHalfHeight = self.powerUpGraphics.height / 2; // Use actual power-up asset height
var particleHalfWidth = particle.children[0].width / 2; // Use actual particle asset width
var particleHalfHeight = particle.children[0].height / 2; // Use actual particle asset height
var isColliding = Math.abs(self.x - particle.x) < powerUpHalfWidth + particleHalfWidth && Math.abs(self.y - particle.y) < powerUpHalfHeight + particleHalfHeight;
if (isColliding) {
currentPlayerIntersecting = true;
break;
}
}
}
if (!self.lastPlayerIntersecting && currentPlayerIntersecting) {
self.collect();
}
self.lastPlayerIntersecting = currentPlayerIntersecting;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
var currentDimension = 0;
var totalDimensions = 2;
var particles = [];
var portals = [];
var interferenceFields = [];
var quantumCore;
var draggedParticle = null;
var dragOffset = {
x: 0,
y: 0
};
var particlesCollected = 0;
var totalParticles = 0;
var level = 0; // Start with tutorial level (level 0)
var timeLimit = 25000; // 25 seconds in milliseconds
var timeRemaining = timeLimit;
var timerActive = false;
var dimensionSwitches = 0;
var maxDimensionSwitches = 5;
var backgroundStars = [];
var powerUps = [];
var shieldActive = false;
var shieldTimeRemaining = 0;
var slowMotionActive = false;
var slowMotionTimeRemaining = 0;
var powerUpSpawnTimer = 0;
var powerUpSpawnInterval = 8000; // Spawn power-up every 8 seconds
var isTutorial = true;
var tutorialStep = 0;
var tutorialComplete = false;
var tutorialText = null;
// UI Elements
var dimensionText = new Text2('Dimension: 0', {
size: 60,
fill: 0xFFFFFF
});
dimensionText.anchor.set(0.5, 0);
LK.gui.top.addChild(dimensionText);
var levelText = new Text2('Level: 1', {
size: 50,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
levelText.y = 100;
LK.gui.top.addChild(levelText);
var instructionText = new Text2('Tap to switch dimensions', {
size: 40,
fill: 0xCCCCCC
});
instructionText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionText);
var timerText = new Text2('Time: 25s', {
size: 50,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
timerText.y = 160;
LK.gui.top.addChild(timerText);
var shieldText = new Text2('SHIELD ACTIVE', {
size: 45,
fill: 0x0088ff
});
shieldText.anchor.set(0.5, 0);
shieldText.y = 220;
shieldText.visible = false;
LK.gui.top.addChild(shieldText);
var slowMotionText = new Text2('SLOW MOTION', {
size: 45,
fill: 0xff8800
});
slowMotionText.anchor.set(0.5, 0);
slowMotionText.y = 280;
slowMotionText.visible = false;
LK.gui.top.addChild(slowMotionText);
// Tutorial text - larger and more visible
tutorialText = new Text2('Welcome to Quantum Dimensions!', {
size: 55,
fill: 0x00ff88
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.x = 1024;
tutorialText.y = 500; // Better positioning
tutorialText.visible = false;
game.addChild(tutorialText);
// Create dimension indicators
var dimensionIndicators = [];
for (var d = 0; d < totalDimensions; d++) {
var indicator = LK.getAsset('dimensionIndicator', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + d * 60,
y: 150
});
dimensionIndicators.push(indicator);
LK.gui.addChild(indicator);
}
function initializeLevel() {
// Clear existing elements
for (var i = 0; i < particles.length; i++) {
particles[i].destroy();
}
for (var i = 0; i < portals.length; i++) {
portals[i].destroy();
}
for (var i = 0; i < interferenceFields.length; i++) {
interferenceFields[i].destroy();
}
for (var i = 0; i < backgroundStars.length; i++) {
backgroundStars[i].destroy();
}
for (var i = 0; i < powerUps.length; i++) {
powerUps[i].destroy();
}
backgroundStars = [];
particles = [];
portals = [];
interferenceFields = [];
powerUps = [];
particlesCollected = 0;
currentDimension = 0;
// Reset and start timer - reduced time penalty for easier gameplay
var timeReduction = (level - 1) * 800; // Reduced from 1500 to 800
// Extra time reduction for extreme levels - less harsh
if (level >= 11) {
timeReduction += (level - 10) * 200; // Reduced from 500 to 200
}
if (level >= 16) {
timeReduction += (level - 15) * 100; // Reduced from 300 to 100
}
timeRemaining = Math.max(12000, timeLimit - timeReduction); // Increased minimum from 6 to 12 seconds
timerActive = true;
dimensionSwitches = 0;
maxDimensionSwitches = Math.max(12, 18 - Math.min(level, 4)); // More switches allowed, minimum 12 (increased from 8)
// Reset power-up system
shieldActive = false;
shieldTimeRemaining = 0;
slowMotionActive = false;
slowMotionTimeRemaining = 0;
powerUpSpawnTimer = 0;
shieldText.visible = false;
slowMotionText.visible = false;
// Create quantum core
if (quantumCore) {
quantumCore.destroy();
}
quantumCore = game.addChild(LK.getAsset('quantumCore', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 800
}));
// Create background star field
var numStars = 80 + level * 15;
for (var i = 0; i < numStars; i++) {
var star = game.addChild(new BackgroundStar());
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.scaleX = 0.5 + Math.random() * 1.5;
star.scaleY = star.scaleX;
backgroundStars.push(star);
}
// Create orbital particles around quantum core
for (var i = 0; i < 8; i++) {
var orbitalStar = game.addChild(new BackgroundStar());
var angle = i / 8 * Math.PI * 2;
var radius = 200 + Math.random() * 100;
orbitalStar.x = quantumCore.x + Math.cos(angle) * radius;
orbitalStar.y = quantumCore.y + Math.sin(angle) * radius;
orbitalStar.scaleX = 1.5;
orbitalStar.scaleY = 1.5;
orbitalStar.orbitalAngle = angle;
orbitalStar.orbitalRadius = radius;
orbitalStar.orbitalSpeed = 0.01 + Math.random() * 0.02;
backgroundStars.push(orbitalStar);
}
// Tutorial level setup (Level 0)
if (level === 0) {
isTutorial = true;
tutorialStep = 0;
tutorialComplete = false;
timerActive = false; // No timer pressure in tutorial
maxDimensionSwitches = 999; // Unlimited switches for tutorial
tutorialText.visible = true;
tutorialText.setText('Welcome to Quantum Dimensions!');
// Single particle in dimension 0 for simple drag tutorial
var tutorialParticle = game.addChild(new Particle());
tutorialParticle.x = 300;
tutorialParticle.y = 1800;
tutorialParticle.setDimension(0);
tutorialParticle.lastCoreIntersecting = false;
tutorialParticle.isBeingDragged = false;
tutorialParticle.isCollected = false;
tutorialParticle.dimension = 0; // Ensure dimension is properly set
particles.push(tutorialParticle);
// Add a second particle in dimension 1 to demonstrate dimension switching
var tutorialParticle2 = game.addChild(new Particle());
tutorialParticle2.x = 1700;
tutorialParticle2.y = 1800;
tutorialParticle2.setDimension(1);
tutorialParticle2.lastCoreIntersecting = false;
tutorialParticle2.isBeingDragged = false;
tutorialParticle2.isCollected = false;
tutorialParticle2.dimension = 1; // Ensure dimension is properly set
particles.push(tutorialParticle2);
// Add a safe interference field for demonstration (not dangerous in tutorial)
var demoField = game.addChild(new InterferenceField());
demoField.x = 1024;
demoField.y = 2200;
demoField.setDimension(0);
demoField.alpha = 0.3; // Make it less threatening
interferenceFields.push(demoField);
// Add a portal for demonstration
var demoPortal = game.addChild(new Portal());
demoPortal.x = 1024;
demoPortal.y = 1400;
demoPortal.dimension = 0;
demoPortal.targetDimension = 1;
demoPortal.setDimension(0);
demoPortal.alpha = 0.5; // Make it visible but not distracting
portals.push(demoPortal);
totalParticles = 2; // Count both particles for tutorial completion
// Show tutorial instructions immediately
LK.setTimeout(function () {
updateTutorialStep();
}, 500);
} else if (level === 1) {
// Reset tutorial flags for actual gameplay
isTutorial = false;
tutorialText.visible = false;
timerActive = true;
// Simple particles in different dimensions
var particle1 = game.addChild(new Particle());
particle1.x = 300;
particle1.y = 1600;
particle1.setDimension(0);
particle1.lastCoreIntersecting = false;
particle1.isBeingDragged = false;
particle1.isCollected = false;
particles.push(particle1);
var particle2 = game.addChild(new Particle());
particle2.x = 1700;
particle2.y = 1600;
particle2.setDimension(1);
particle2.lastCoreIntersecting = false;
particle2.isBeingDragged = false;
particle2.isCollected = false;
particles.push(particle2);
// Portal to connect dimensions
var portal1 = game.addChild(new Portal());
portal1.x = 1024;
portal1.y = 1600;
portal1.dimension = 0;
portal1.targetDimension = 1;
portal1.setDimension(0);
portals.push(portal1);
totalParticles = 2;
} else {
// Progressive levels with more complexity - reduced interference fields
var numParticles = Math.min(level + 1, 4);
var numFields = Math.min(Math.max(0, level - 1), 4); // Fewer interference fields, starting from level 2
for (var i = 0; i < numParticles; i++) {
var particle = game.addChild(new Particle());
particle.x = 200 + i * 400;
particle.y = 1800 + i % 2 * 400;
particle.setDimension(i % totalDimensions);
particle.lastCoreIntersecting = false;
particle.isBeingDragged = false;
particle.isCollected = false;
particles.push(particle);
}
// Create entangled pairs for higher levels
if (level >= 3 && particles.length >= 2) {
particles[0].entangledWith = particles[1];
particles[1].entangledWith = particles[0];
}
// Create portals
for (var i = 0; i < 2; i++) {
var portal = game.addChild(new Portal());
portal.x = 400 + i * 1200;
portal.y = 1200;
portal.dimension = i;
portal.targetDimension = (i + 1) % totalDimensions;
portal.setDimension(i);
portals.push(portal);
}
// Create interference fields
for (var i = 0; i < numFields; i++) {
var field = game.addChild(new InterferenceField());
field.x = 300 + i * 600;
field.y = 1000 + i % 2 * 400;
field.setDimension(i % totalDimensions);
// Add movement to interference fields for higher levels
if (level >= 2) {
field.moveDirection = i % 2 === 0 ? 1 : -1;
field.minX = 100;
field.maxX = 1948;
}
interferenceFields.push(field);
}
// Add additional moving barriers for higher levels
if (level >= 2) {
var movingField = game.addChild(new InterferenceField());
movingField.x = 1024;
movingField.y = 1400;
movingField.setDimension(0);
movingField.moveDirection = 1;
movingField.minX = 200;
movingField.maxX = 1848;
interferenceFields.push(movingField);
}
// Add second moving barrier for level 3+
if (level >= 3) {
var movingField2 = game.addChild(new InterferenceField());
movingField2.x = 500;
movingField2.y = 2000;
movingField2.setDimension(1);
movingField2.moveDirection = -1;
movingField2.minX = 100;
movingField2.maxX = 1948;
interferenceFields.push(movingField2);
}
// Add third moving barrier for level 4+
if (level >= 4) {
var movingField3 = game.addChild(new InterferenceField());
movingField3.x = 1500;
movingField3.y = 1600;
movingField3.setDimension(0);
movingField3.moveDirection = 1;
movingField3.minX = 300;
movingField3.maxX = 1700;
interferenceFields.push(movingField3);
}
// Add fourth moving barrier for level 5+
if (level >= 5) {
var movingField4 = game.addChild(new InterferenceField());
movingField4.x = 800;
movingField4.y = 1800;
movingField4.setDimension(1);
movingField4.moveDirection = -1;
movingField4.minX = 200;
movingField4.maxX = 1800;
interferenceFields.push(movingField4);
}
// Advanced levels 6-10 with additional challenges
if (level >= 6) {
// Add more particles for higher levels
var extraParticles = Math.min(level - 5, 3);
for (var j = 0; j < extraParticles; j++) {
var extraParticle = game.addChild(new Particle());
extraParticle.x = 400 + j * 300;
extraParticle.y = 2200 + j % 2 * 200;
extraParticle.setDimension(j % totalDimensions);
extraParticle.lastCoreIntersecting = false;
extraParticle.isBeingDragged = false;
extraParticle.isCollected = false;
particles.push(extraParticle);
}
totalParticles += extraParticles;
// Add additional moving barriers
var numExtraFields = Math.min(level - 5, 4);
for (var k = 0; k < numExtraFields; k++) {
var extraField = game.addChild(new InterferenceField());
extraField.x = 200 + k * 400;
extraField.y = 1300 + k % 2 * 300;
extraField.setDimension(k % totalDimensions);
extraField.moveDirection = k % 2 === 0 ? 1 : -1;
extraField.minX = 100;
extraField.maxX = 1948;
interferenceFields.push(extraField);
}
}
// Level 8+ speed increase is now handled in the InterferenceField update method
// Level 10 gets entangled triplets
if (level >= 10 && particles.length >= 3) {
particles[0].entangledWith = particles[1];
particles[1].entangledWith = particles[2];
particles[2].entangledWith = particles[0];
}
// Advanced levels 11-15 with extreme challenges
if (level >= 11) {
// Add even more particles for extreme levels
var extremeParticles = Math.min(level - 10, 5);
for (var m = 0; m < extremeParticles; m++) {
var extremeParticle = game.addChild(new Particle());
extremeParticle.x = 150 + m * 250;
extremeParticle.y = 2400 + m % 2 * 150;
extremeParticle.setDimension(m % totalDimensions);
extremeParticle.lastCoreIntersecting = false;
extremeParticle.isBeingDragged = false;
extremeParticle.isCollected = false;
particles.push(extremeParticle);
}
totalParticles += extremeParticles;
// Add maze-like interference field patterns
var mazeFields = Math.min(level - 10, 6);
for (var n = 0; n < mazeFields; n++) {
var mazeField = game.addChild(new InterferenceField());
mazeField.x = 300 + n * 200;
mazeField.y = 1100 + n % 3 * 200;
mazeField.setDimension(n % totalDimensions);
mazeField.moveDirection = n % 2 === 0 ? 1 : -1;
mazeField.minX = 50;
mazeField.maxX = 1998;
interferenceFields.push(mazeField);
}
}
// Master levels 16-20 with ultimate difficulty
if (level >= 16) {
// Add master-level particles
var masterParticles = Math.min(level - 15, 4);
for (var p = 0; p < masterParticles; p++) {
var masterParticle = game.addChild(new Particle());
masterParticle.x = 200 + p * 400;
masterParticle.y = 2500 + p % 2 * 100;
masterParticle.setDimension(p % totalDimensions);
masterParticle.lastCoreIntersecting = false;
masterParticle.isBeingDragged = false;
masterParticle.isCollected = false;
particles.push(masterParticle);
}
totalParticles += masterParticles;
// Create complex entanglement networks
if (particles.length >= 4) {
for (var q = 0; q < Math.min(particles.length - 1, 6); q++) {
if (q + 1 < particles.length) {
particles[q].entangledWith = particles[q + 1];
}
}
}
// Add ultra-fast moving barriers
var ultraFields = Math.min(level - 15, 8);
for (var r = 0; r < ultraFields; r++) {
var ultraField = game.addChild(new InterferenceField());
ultraField.x = 100 + r * 180;
ultraField.y = 1200 + r % 4 * 150;
ultraField.setDimension(r % totalDimensions);
ultraField.moveDirection = r % 2 === 0 ? 1 : -1;
ultraField.minX = 50;
ultraField.maxX = 1998;
interferenceFields.push(ultraField);
}
}
// Calculate total particles correctly for all levels
totalParticles = particles.length;
}
updateDimensionDisplay();
if (level === 0) {
levelText.setText('Tutorial');
} else {
levelText.setText('Level: ' + level);
}
}
function updateDimensionDisplay() {
dimensionText.setText('Dimension: ' + currentDimension);
instructionText.setText('Switches: ' + dimensionSwitches + '/' + maxDimensionSwitches + ' - Tap to switch');
for (var i = 0; i < dimensionIndicators.length; i++) {
var indicator = dimensionIndicators[i];
tween(indicator, {
alpha: i === currentDimension ? 1.0 : 0.3,
scaleX: i === currentDimension ? 1.5 : 1.0,
scaleY: i === currentDimension ? 1.5 : 1.0
}, {
duration: 300,
easing: tween.easeOut
});
}
// Update all objects for dimension visibility
for (var i = 0; i < particles.length; i++) {
var targetAlpha = particles[i].dimension === currentDimension ? 1.0 : 0.15;
tween(particles[i], {
alpha: targetAlpha
}, {
duration: 200,
easing: tween.easeInOut
});
}
for (var i = 0; i < portals.length; i++) {
var targetAlpha = portals[i].dimension === currentDimension ? 1.0 : 0.1;
tween(portals[i], {
alpha: targetAlpha
}, {
duration: 200,
easing: tween.easeInOut
});
}
for (var i = 0; i < interferenceFields.length; i++) {
var targetAlpha = interferenceFields[i].dimension === currentDimension ? 0.8 : 0.1;
tween(interferenceFields[i], {
alpha: targetAlpha
}, {
duration: 200,
easing: tween.easeInOut
});
}
for (var i = 0; i < powerUps.length; i++) {
var targetAlpha = powerUps[i].dimension === currentDimension ? 1.0 : 0.15;
tween(powerUps[i], {
alpha: targetAlpha
}, {
duration: 200,
easing: tween.easeInOut
});
}
}
function switchDimension() {
if (dimensionSwitches >= maxDimensionSwitches && !isTutorial) {
LK.effects.flashScreen(0xFF0000, 200);
return; // No more switches allowed (except in tutorial)
}
dimensionSwitches++;
// Remove time penalty to make dimension switching more accessible
currentDimension = (currentDimension + 1) % totalDimensions;
updateDimensionDisplay();
LK.getSound('dimensionShift').play();
LK.effects.flashScreen(0x440088, 200);
// Tutorial progress tracking
if (isTutorial) {
if (tutorialStep === 3) {
tutorialStep = 4;
// Add celebratory flash for successful dimension switch
LK.effects.flashScreen(0x00ff88, 300);
LK.setTimeout(function () {
updateTutorialStep();
}, 800);
} else if (tutorialStep === 4 && currentDimension === 1) {
// Player successfully switched to dimension 1
tutorialStep = 5;
LK.setTimeout(function () {
updateTutorialStep();
}, 1200);
}
}
}
function checkWinCondition() {
if (particlesCollected >= totalParticles) {
timerActive = false; // Stop timer when level complete
if (isTutorial) {
if (particlesCollected === 1 && tutorialStep <= 3) {
// First particle collected, advance tutorial
tutorialStep = 3;
updateTutorialStep();
return;
} else if (particlesCollected >= 2) {
// All particles collected in tutorial, complete it
if (tutorialStep < 6) {
tutorialStep = 6;
updateTutorialStep();
} else if (tutorialComplete || tutorialStep >= 10) {
// Tutorial is complete, move to level 1
level = 1;
isTutorial = false;
tutorialText.visible = false;
initializeLevel();
}
return;
}
}
level++;
LK.setTimeout(function () {
if (level > 20) {
LK.showYouWin();
} else {
initializeLevel();
}
}, 1000);
}
}
function resetLevel() {
// Check if shield is active to prevent death
if (shieldActive) {
shieldActive = false;
shieldTimeRemaining = 0;
shieldText.visible = false;
LK.effects.flashScreen(0x0088ff, 300);
return; // Shield absorbed the hit
}
LK.effects.flashScreen(0xff0000, 500);
LK.setTimeout(function () {
initializeLevel();
}, 600);
}
function spawnPowerUp() {
if (powerUps.length >= 2) return; // Maximum 2 power-ups on screen
var powerUp = game.addChild(new PowerUp());
// Ensure power-ups spawn in safe areas away from interference fields
var safePosition = false;
var attempts = 0;
var spawnX, spawnY;
while (!safePosition && attempts < 10) {
spawnX = 300 + Math.random() * 1448;
spawnY = 600 + Math.random() * 800;
// Check distance from interference fields
safePosition = true;
for (var f = 0; f < interferenceFields.length; f++) {
var field = interferenceFields[f];
var distance = Math.sqrt((spawnX - field.x) * (spawnX - field.x) + (spawnY - field.y) * (spawnY - field.y));
if (distance < 200) {
safePosition = false;
break;
}
}
attempts++;
}
powerUp.x = spawnX || 300 + Math.random() * 1448;
powerUp.y = spawnY || 600 + Math.random() * 800;
powerUp.setDimension(currentDimension); // Always spawn in current dimension for better accessibility
// Random power-up type
var types = ['timeBoost', 'shield', 'slowMotion'];
var randomType = types[Math.floor(Math.random() * types.length)];
powerUp.setType(randomType);
powerUp.lastPlayerIntersecting = false;
powerUps.push(powerUp);
}
// Event handlers
game.down = function (x, y, obj) {
var hitParticle = false;
for (var i = 0; i < particles.length; i++) {
var particle = particles[i];
if (particle.dimension === currentDimension && !particle.isCollected && particle.alpha > 0.5) {
// Use actual asset dimensions for accurate touch detection
var halfWidth = particle.children[0].width / 2; // Use actual particle asset width
var halfHeight = particle.children[0].height / 2; // Use actual particle asset height
// Check if touch point is within particle bounds
if (x >= particle.x - halfWidth && x <= particle.x + halfWidth && y >= particle.y - halfHeight && y <= particle.y + halfHeight) {
draggedParticle = particle;
particle.startDrag();
dragOffset.x = x - particle.x;
dragOffset.y = y - particle.y;
hitParticle = true;
break;
}
}
}
if (!hitParticle) {
switchDimension();
}
};
game.move = function (x, y, obj) {
if (draggedParticle && !draggedParticle.isCollected) {
var targetX = x - dragOffset.x;
var targetY = y - dragOffset.y;
// Keep particle within bounds
targetX = Math.max(80, Math.min(1968, targetX));
targetY = Math.max(80, Math.min(2652, targetY));
// Direct position update for responsive dragging
draggedParticle.x = targetX;
draggedParticle.y = targetY;
// Reduce trail effect frequency to improve performance
if (LK.ticks % 10 === 0) {
var trailStar = game.addChild(new BackgroundStar());
trailStar.x = draggedParticle.x + (Math.random() - 0.5) * 20;
trailStar.y = draggedParticle.y + (Math.random() - 0.5) * 20;
trailStar.scaleX = 0.8;
trailStar.scaleY = 0.8;
trailStar.alpha = 0.8;
// Fade out trail particle
tween(trailStar, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
trailStar.destroy();
}
});
}
// Handle entangled particle movement with direct updates
if (draggedParticle.entangledWith) {
// Only move entangled particles when BOTH the dragged particle AND the entangled particle are in the current dimension
// This prevents cross-dimensional interference where particles in other dimensions move unexpectedly
if (draggedParticle.dimension === currentDimension && draggedParticle.entangledWith.dimension === currentDimension) {
draggedParticle.entangledWith.x = targetX + 150;
draggedParticle.entangledWith.y = targetY;
}
// Ensure entangled particles maintain proper alpha based on current dimension
var entangledTargetAlpha = draggedParticle.entangledWith.dimension === currentDimension ? 1.0 : 0.15;
draggedParticle.entangledWith.alpha = entangledTargetAlpha;
}
}
};
game.up = function (x, y, obj) {
if (draggedParticle) {
draggedParticle.stopDrag();
draggedParticle = null;
}
};
game.update = function () {
// Handle timer countdown
if (timerActive) {
var timeDecrement = slowMotionActive ? 8.33 : 16.67; // Slow motion halves time consumption
timeRemaining -= timeDecrement;
if (timeRemaining <= 0) {
resetLevel();
return;
}
var seconds = Math.ceil(timeRemaining / 1000);
timerText.setText('Time: ' + seconds + 's');
// Smooth color transitions when time is running out
if (seconds <= 5) {
tween(timerText, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeOut
});
} else if (seconds <= 10) {
tween(timerText, {
tint: 0xFFFF00
}, {
duration: 200,
easing: tween.easeOut
});
} else {
tween(timerText, {
tint: 0xFFFFFF
}, {
duration: 200,
easing: tween.easeOut
});
}
}
// Animate quantum core with direct property updates
if (quantumCore) {
// Direct rotation update
quantumCore.rotation += 0.02;
// Direct pulsing animation
var pulse = Math.sin(LK.ticks * 0.08) * 0.15 + 1.0;
quantumCore.scaleX = pulse;
quantumCore.scaleY = pulse;
// Reduced frequency color cycling
if (LK.ticks % 60 === 0) {
var colorPhase = LK.ticks * 0.015;
var r = Math.sin(colorPhase) * 0.4 + 0.6;
var g = Math.sin(colorPhase + 2) * 0.4 + 0.6;
var b = Math.sin(colorPhase + 4) * 0.4 + 0.6;
var color = Math.floor(r * 255) << 16 | Math.floor(g * 255) << 8 | Math.floor(b * 255);
quantumCore.tint = color;
}
}
// Update all particles
for (var i = 0; i < particles.length; i++) {
if (particles[i].update) {
particles[i].update();
}
}
// Update all portals
for (var i = 0; i < portals.length; i++) {
if (portals[i].update) {
portals[i].update();
}
}
// Update all interference fields
for (var i = 0; i < interferenceFields.length; i++) {
if (interferenceFields[i].update) {
interferenceFields[i].update();
}
}
// Handle power-up spawning
if (timerActive) {
powerUpSpawnTimer += 16.67;
// Calculate dynamic spawn interval based on level - more frequent power-ups
var dynamicSpawnInterval = powerUpSpawnInterval;
if (level >= 5) {
dynamicSpawnInterval = Math.max(3000, powerUpSpawnInterval - (level - 4) * 300); // Faster spawning for higher levels, minimum 3 seconds (reduced from 4)
}
if (powerUpSpawnTimer >= dynamicSpawnInterval) {
spawnPowerUp();
powerUpSpawnTimer = 0;
}
}
// Handle shield duration
if (shieldActive) {
shieldTimeRemaining -= 16.67;
if (shieldTimeRemaining <= 0) {
shieldActive = false;
shieldText.visible = false;
} else {
shieldText.visible = true;
shieldText.setText('SHIELD: ' + Math.ceil(shieldTimeRemaining / 1000) + 's');
}
}
// Handle slow motion duration
if (slowMotionActive) {
slowMotionTimeRemaining -= 16.67;
if (slowMotionTimeRemaining <= 0) {
slowMotionActive = false;
slowMotionText.visible = false;
} else {
slowMotionText.visible = true;
slowMotionText.setText('SLOW MOTION: ' + Math.ceil(slowMotionTimeRemaining / 1000) + 's');
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
if (powerUps[i].update) {
powerUps[i].update();
}
// Remove collected power-ups
if (powerUps[i].isCollected && !powerUps[i].visible) {
powerUps[i].destroy();
powerUps.splice(i, 1);
}
}
// Update background stars
for (var i = 0; i < backgroundStars.length; i++) {
var star = backgroundStars[i];
if (star.update) {
star.update();
}
// Handle orbital motion for core particles
if (star.orbitalAngle !== undefined && quantumCore) {
star.orbitalAngle += star.orbitalSpeed;
star.x = quantumCore.x + Math.cos(star.orbitalAngle) * star.orbitalRadius;
star.y = quantumCore.y + Math.sin(star.orbitalAngle) * star.orbitalRadius;
}
}
};
function updateTutorialStep() {
if (!isTutorial) return;
// Ensure tutorial text is visible and properly positioned
tutorialText.visible = true;
tutorialText.alpha = 1.0;
// Position tutorial text in center area for better visibility
tutorialText.x = 1024;
tutorialText.y = 500; // Better positioning for readability
// Ensure text is on top and visible
game.removeChild(tutorialText);
game.addChild(tutorialText);
switch (tutorialStep) {
case 0:
tutorialText.setText('Welcome to Quantum Dimensions!\nMove particles to the center core to collect them.');
LK.setTimeout(function () {
tutorialStep = 1;
updateTutorialStep();
}, 2500);
break;
case 1:
tutorialText.setText('STEP 1: DRAG A PARTICLE\nTouch and drag the glowing particle below.');
// Add visual hint by pulsing the particle
if (particles.length > 0 && particles[0].dimension === currentDimension) {
LK.effects.flashObject(particles[0], 0x00ff00, 1500);
// Keep flashing until moved
LK.setInterval(function () {
if (tutorialStep === 1 && !particles[0].isBeingDragged) {
LK.effects.flashObject(particles[0], 0x00ff00, 800);
}
}, 1000);
}
break;
case 2:
tutorialText.setText('STEP 2: MOVE TO CENTER\nDrag the particle to the quantum core (glowing center).');
// Add visual hint by flashing the quantum core
if (quantumCore) {
LK.effects.flashObject(quantumCore, 0x00ffff, 2000);
// Keep flashing until collected
LK.setInterval(function () {
if (tutorialStep === 2 && quantumCore) {
LK.effects.flashObject(quantumCore, 0x00ffff, 1000);
}
}, 1500);
}
break;
case 3:
tutorialText.setText('GREAT! Particle collected!\nNow tap empty space to switch dimensions.');
break;
case 4:
tutorialText.setText('STEP 3: DIMENSION SWITCHING\nYou switched to Dimension 1! See the other particle?');
if (particles.length > 1 && particles[1].dimension === currentDimension) {
LK.effects.flashObject(particles[1], 0x00ff00, 1500);
}
LK.setTimeout(function () {
tutorialStep = 5;
updateTutorialStep();
}, 2500);
break;
case 5:
tutorialText.setText('STEP 4: COLLECT SECOND PARTICLE\nDrag this particle to the center too.');
if (particles.length > 1 && particles[1].dimension === currentDimension) {
LK.effects.flashObject(particles[1], 0x00ff00, 1500);
// Keep flashing until collected
LK.setInterval(function () {
if (tutorialStep === 5 && particles.length > 1 && !particles[1].isCollected) {
LK.effects.flashObject(particles[1], 0x00ff00, 800);
}
}, 1200);
}
break;
case 6:
tutorialText.setText('PERFECT! You mastered the basics!\nRemember: Limited dimension switches in real levels.');
LK.setTimeout(function () {
tutorialStep = 7;
updateTutorialStep();
}, 2500);
break;
case 7:
tutorialText.setText('WARNING: RED FIELDS = DANGER\nAvoid red interference fields - they reset the level!');
// Flash the demo interference field to show danger
for (var i = 0; i < interferenceFields.length; i++) {
LK.effects.flashObject(interferenceFields[i], 0xff0000, 2000);
}
LK.setTimeout(function () {
tutorialStep = 8;
updateTutorialStep();
}, 3000);
break;
case 8:
tutorialText.setText('BLUE PORTALS = TRANSPORT\nPortals move particles between dimensions.');
// Flash the demo portal
for (var i = 0; i < portals.length; i++) {
LK.effects.flashObject(portals[i], 0x0088ff, 2000);
}
LK.setTimeout(function () {
tutorialStep = 9;
updateTutorialStep();
}, 3000);
break;
case 9:
tutorialText.setText('POWER-UPS HELP YOU:\n🟢 Time Boost 🔵 Shield 🟡 Slow Motion');
LK.setTimeout(function () {
tutorialStep = 10;
updateTutorialStep();
}, 3500);
break;
case 10:
tutorialText.setText('🎉 TUTORIAL COMPLETE! 🎉\nReady for the real challenge? Starting Level 1...');
LK.setTimeout(function () {
tutorialComplete = true;
checkWinCondition(); // Use existing function to transition properly
}, 3000);
break;
}
}
function showPowerUpSpec(title, description, color) {
// Create power-up specification display
var specContainer = new Container();
// Title text
var titleText = new Text2(title, {
size: 60,
fill: color
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 1300;
specContainer.addChild(titleText);
// Description text
var descText = new Text2(description, {
size: 45,
fill: 0xFFFFFF
});
descText.anchor.set(0.5, 0.5);
descText.x = 1024;
descText.y = 1380;
specContainer.addChild(descText);
// Add to game
game.addChild(specContainer);
// Initial state
specContainer.alpha = 0;
specContainer.scaleX = 0.3;
specContainer.scaleY = 0.3;
// Animation: fade in and scale up
tween(specContainer, {
alpha: 1.0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Hold for a moment then fade out
LK.setTimeout(function () {
tween(specContainer, {
alpha: 0,
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 400,
easing: tween.easeIn,
onFinish: function onFinish() {
specContainer.destroy();
}
});
}, 2000);
}
});
}
// Initialize first level
initializeLevel();