User prompt
Create a special space where we can fill our souls
User prompt
Create a beautiful background.
User prompt
Enemies only come from above
User prompt
Please fix the bug: 'TypeError: taskTexts[i].setColor is not a function' in or related to this line: 'taskTexts[i].setColor(color);' Line Number: 334
User prompt
Put the character's health bar under
User prompt
give us some tasks and show these tasks on top
User prompt
Reduces enemies' health and range
Code edit (1 edits merged)
Please save this source code
User prompt
Top Cop: Police Pursuit
Initial prompt
make a gun game and um top top camera and then uh and then and then uh sound effects and uh police and uh and
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Background = Container.expand(function () { var self = Container.call(this); // Create sky gradient var skyGradient = new Container(); // Create several bands of sky color var skyColors = [0x1a3c80, 0x3a5c9f, 0x5a7cbf, 0x7a9cdf, 0x9abcff]; var bandHeight = 2732 / skyColors.length; for (var i = 0; i < skyColors.length; i++) { var skyBand = LK.getAsset('skyBand' + i, { width: 2048, height: bandHeight, color: skyColors[i], shape: 'box', y: i * bandHeight }); skyGradient.addChild(skyBand); } self.addChild(skyGradient); // Create buildings var buildings = new Container(); self.addChild(buildings); // Far buildings (darker) var buildingColors = [0x222a40, 0x323a50, 0x424a60]; var buildingCount = 15; for (var i = 0; i < buildingCount; i++) { var buildingWidth = 100 + Math.random() * 150; var buildingHeight = 300 + Math.random() * 400; var building = LK.getAsset('building_far_' + i, { width: buildingWidth, height: buildingHeight, color: buildingColors[Math.floor(Math.random() * buildingColors.length)], shape: 'box', x: i * (2048 / buildingCount), y: 2732 - buildingHeight, anchorY: 0 }); buildings.addChild(building); } // Near buildings (slightly lighter) var nearBuildingColors = [0x303a50, 0x404a60, 0x505a70]; var nearBuildingCount = 10; for (var i = 0; i < nearBuildingCount; i++) { var buildingWidth = 180 + Math.random() * 150; var buildingHeight = 500 + Math.random() * 600; var building = LK.getAsset('building_near_' + i, { width: buildingWidth, height: buildingHeight, color: nearBuildingColors[Math.floor(Math.random() * nearBuildingColors.length)], shape: 'box', x: i * (2048 / nearBuildingCount), y: 2732 - buildingHeight, anchorY: 0 }); buildings.addChild(building); } // Add some windows to buildings (as small yellow rectangles) for (var b = 0; b < buildings.children.length; b++) { var building = buildings.children[b]; var windowCount = Math.floor(building.width / 30) * Math.floor(building.height / 40); // Limit window count for performance windowCount = Math.min(windowCount, 20); for (var w = 0; w < windowCount; w++) { var windowSize = 10 + Math.random() * 10; var windowX = Math.random() * (building.width - windowSize); var windowY = Math.random() * (building.height - windowSize); // Only add some windows (randomized lighting effect) if (Math.random() > 0.4) { var windowLight = LK.getAsset('window_' + b + '_' + w, { width: windowSize, height: windowSize, color: Math.random() > 0.7 ? 0xffcc66 : 0x888888, // Some windows lit, some not shape: 'box', x: building.x + windowX, y: building.y + windowY }); self.addChild(windowLight); } } } // Add clouds var clouds = new Container(); self.clouds = clouds; self.addChild(clouds); var cloudCount = 6; for (var i = 0; i < cloudCount; i++) { var cloudWidth = 200 + Math.random() * 300; var cloudHeight = 100 + Math.random() * 100; var cloud = LK.getAsset('cloud_' + i, { width: cloudWidth, height: cloudHeight, color: 0xddddff, shape: 'ellipse', x: Math.random() * 2048, y: 200 + Math.random() * 400, alpha: 0.7 }); // Add some variation to clouds with slight scaling cloud.scaleX = 0.8 + Math.random() * 0.4; cloud.scaleY = 0.8 + Math.random() * 0.4; // Store cloud speed for animation cloud.speedX = 0.2 + Math.random() * 0.3; clouds.addChild(cloud); } // Update function to animate clouds self.update = function () { // Move clouds horizontally for (var i = 0; i < clouds.children.length; i++) { var cloud = clouds.children[i]; cloud.x += cloud.speedX; // Loop clouds when they move off screen if (cloud.x > 2048 + cloud.width) { cloud.x = -cloud.width; cloud.y = 200 + Math.random() * 400; } } }; return self; }); var BreathingCircle = Container.expand(function () { var self = Container.call(this); // Create the breathing circle var innerCircle = self.attachAsset('centerCircle', { width: 200, height: 200, color: 0x3a5c9f, anchorX: 0.5, anchorY: 0.5, alpha: 0.4 }); var outerCircle = LK.getAsset('centerCircle', { width: 240, height: 240, color: 0x5a7cbf, anchorX: 0.5, anchorY: 0.5, alpha: 0.2 }); self.addChild(outerCircle); // Breathing animation state self.breathPhase = 0; // 0: inhale growing, 1: hold, 2: exhale shrinking, 3: hold self.breathTimer = 0; self.inhaleDuration = 240; // 4 seconds self.holdDuration = 120; // 2 seconds self.exhaleDuration = 240; // 4 seconds self.restDuration = 60; // 1 second // Text guide for breathing self.breathText = new Text2("Breathe In", { size: 40, fill: 0xffffff }); self.breathText.anchor.set(0.5, 0.5); self.breathText.y = -160; self.addChild(self.breathText); // Update method to animate the breathing circle self.update = function () { self.breathTimer++; // Determine current phase based on timer if (self.breathPhase === 0) { // Inhale var progress = self.breathTimer / self.inhaleDuration; var scale = 1 + progress * 0.5; innerCircle.scale.x = innerCircle.scale.y = scale; outerCircle.scale.x = outerCircle.scale.y = 0.9 + progress * 0.5; self.breathText.setText("Breathe In"); if (self.breathTimer >= self.inhaleDuration) { self.breathPhase = 1; self.breathTimer = 0; } } else if (self.breathPhase === 1) { // Hold after inhale self.breathText.setText("Hold"); if (self.breathTimer >= self.holdDuration) { self.breathPhase = 2; self.breathTimer = 0; } } else if (self.breathPhase === 2) { // Exhale var progress = self.breathTimer / self.exhaleDuration; var scale = 1.5 - progress * 0.5; innerCircle.scale.x = innerCircle.scale.y = scale; outerCircle.scale.x = outerCircle.scale.y = 1.4 - progress * 0.5; self.breathText.setText("Breathe Out"); if (self.breathTimer >= self.exhaleDuration) { self.breathPhase = 3; self.breathTimer = 0; } } else { // Hold after exhale self.breathText.setText("Rest"); if (self.breathTimer >= self.restDuration) { self.breathPhase = 0; self.breathTimer = 0; } } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 12; self.direction = { x: 0, y: -1 }; // Default upward self.lifespan = 120; // 2 seconds at 60fps self.age = 0; self.damage = 1; self.update = function () { self.x += self.direction.x * self.speed; self.y += self.direction.y * self.speed; self.age++; if (self.age > self.lifespan) { self.markForDeletion = true; } }; return self; }); var Criminal = Container.expand(function () { var self = Container.call(this); var criminalGraphics = self.attachAsset('criminal', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.health = 2; // Reduced from 3 self.shootCooldown = 0; self.shootDelay = 120; // Frames between shots self.attackRange = 300; // Reduced from 500 self.movePattern = Math.floor(Math.random() * 3); // 0: direct, 1: zigzag, 2: circle self.moveTimer = 0; self.update = function () { // Target the player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Movement based on pattern if (distance > 100) { // Keep some distance var moveX = 0; var moveY = 0; switch (self.movePattern) { case 0: // Direct moveX = dx / distance; moveY = dy / distance; break; case 1: // Zigzag self.moveTimer++; moveX = dx / distance + Math.sin(self.moveTimer * 0.1) * 0.5; moveY = dy / distance; break; case 2: // Circle self.moveTimer++; moveX = dx / distance + Math.sin(self.moveTimer * 0.05) * 0.8; moveY = dy / distance + Math.cos(self.moveTimer * 0.05) * 0.8; break; } self.x += moveX * self.speed; self.y += moveY * self.speed; } // Shooting logic if (distance < self.attackRange) { if (self.shootCooldown <= 0) { // Create enemy bullet var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; // Calculate direction toward player var dirX = dx / distance; var dirY = dy / distance; bullet.direction = { x: dirX, y: dirY }; // Mark as enemy bullet bullet.isEnemyBullet = true; // Add to game's bullets array bullets.push(bullet); game.addChild(bullet); // Reset cooldown with some randomness self.shootCooldown = self.shootDelay + Math.random() * 60; } } if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.takeDamage = function () { self.health--; LK.effects.flashObject(self, 0xFF0000, 300); if (self.health <= 0) { LK.getSound('criminal_down').play(); LK.setScore(LK.getScore() + 1); self.markForDeletion = true; // Track criminal elimination task var eliminateTask = tasks.find(function (task) { return task.id === 'eliminate'; }); if (eliminateTask && !eliminateTask.completed) { eliminateTask.count++; if (eliminateTask.count >= eliminateTask.target) { eliminateTask.completed = true; LK.effects.flashObject(taskTexts[1], 0x00FF00, 1000); } updateTaskDisplay(); } } }; return self; }); var EmergencyCall = Container.expand(function () { var self = Container.call(this); var callGraphics = self.attachAsset('emergencyCall', { anchorX: 0.5, anchorY: 0.5 }); self.lifetime = 600; // 10 seconds at 60fps self.age = 0; self.flashInterval = 30; self.update = function () { self.age++; // Flash effect if (self.age % self.flashInterval === 0) { if (callGraphics.alpha === 1) { tween(callGraphics, { alpha: 0.3 }, { duration: 500 }); } else { tween(callGraphics, { alpha: 1 }, { duration: 500 }); } } // Expire after lifetime if (self.age > self.lifetime) { self.markForDeletion = true; } }; self.down = function () { // Responding to call LK.getSound('radiochatter').play(); // Spawn criminals from top of screen, using emergency call's X position spawnCriminals(self.x, 0, 2 + Math.floor(Math.random() * 3)); self.markForDeletion = true; // Increase score for responding LK.setScore(LK.getScore() + 2); // Track emergency call response task var respondTask = tasks.find(function (task) { return task.id === 'respond'; }); if (respondTask && !respondTask.completed) { respondTask.count++; if (respondTask.count >= respondTask.target) { respondTask.completed = true; LK.effects.flashObject(taskTexts[0], 0x00FF00, 1000); } updateTaskDisplay(); } }; return self; }); var MeditationGuide = Container.expand(function () { var self = Container.call(this); // Create a text display for meditation prompts self.promptText = new Text2("Breathe deeply...", { size: 60, fill: 0xffffff, align: 'center' }); self.promptText.anchor.set(0.5, 0.5); self.addChild(self.promptText); // List of meditation prompts self.prompts = ["Breathe deeply...", "Focus on your breath...", "Let go of your thoughts...", "Feel the peace within...", "You are present...", "Allow yourself to be...", "Feel the energy flow...", "Find your center..."]; self.currentPrompt = 0; self.promptTimer = 0; self.promptDuration = 300; // 5 seconds per prompt // Update method to cycle through prompts self.update = function () { self.promptTimer++; // Change prompt periodically if (self.promptTimer >= self.promptDuration) { self.currentPrompt = (self.currentPrompt + 1) % self.prompts.length; self.promptText.setText(self.prompts[self.currentPrompt]); self.promptTimer = 0; // Animate text appearance self.promptText.alpha = 0; tween(self.promptText, { alpha: 1 }, { duration: 1000 }); } // Subtle pulse animation var scale = 1 + 0.05 * Math.sin(self.promptTimer * 0.01); self.promptText.scale.x = scale; self.promptText.scale.y = scale; }; return self; }); var MeditationSpace = Container.expand(function () { var self = Container.call(this); // Create a peaceful gradient background var background = new Container(); self.addChild(background); // Create calming gradient colors for the background var skyColors = [0x081832, 0x112a4e, 0x1a3c6a, 0x234e86, 0x2c60a2]; var bandHeight = 2732 / skyColors.length; for (var i = 0; i < skyColors.length; i++) { var skyBand = LK.getAsset('skyBand' + i, { width: 2048, height: bandHeight, color: skyColors[i], y: i * bandHeight }); background.addChild(skyBand); } // Create stars var stars = new Container(); self.stars = stars; self.addChild(stars); // Add stars to the night sky var starCount = 100; for (var i = 0; i < starCount; i++) { var starSize = 2 + Math.random() * 4; var star = LK.getAsset('star_' + i, { width: starSize, height: starSize, color: 0xffffff, shape: 'ellipse', x: Math.random() * 2048, y: Math.random() * 1200, alpha: 0.5 + Math.random() * 0.5 }); star.pulseSpeed = 0.01 + Math.random() * 0.02; star.pulsePhase = Math.random() * Math.PI * 2; stars.addChild(star); } // Add floating lotus flowers var lotusFlowers = new Container(); self.lotusFlowers = lotusFlowers; self.addChild(lotusFlowers); var lotusCount = 5; for (var i = 0; i < lotusCount; i++) { var lotusSize = 80 + Math.random() * 40; var lotus = LK.getAsset('lotus_' + i, { width: lotusSize, height: lotusSize, color: 0xffb6c1, shape: 'ellipse', x: 400 + Math.random() * 1200, y: 1500 + Math.random() * 800 }); lotus.floatSpeed = 0.2 + Math.random() * 0.3; lotus.floatPhase = Math.random() * Math.PI * 2; lotusFlowers.addChild(lotus); } // Add water ripples var ripples = new Container(); self.ripples = ripples; self.addChild(ripples); self.rippleTimer = 0; // Update function to animate elements self.update = function () { // Animate stars (pulsing effect) for (var i = 0; i < stars.children.length; i++) { var star = stars.children[i]; star.pulsePhase += star.pulseSpeed; star.alpha = 0.5 + 0.5 * Math.sin(star.pulsePhase); } // Animate lotus flowers (gentle floating) for (var i = 0; i < lotusFlowers.children.length; i++) { var lotus = lotusFlowers.children[i]; lotus.floatPhase += 0.01; lotus.y += Math.sin(lotus.floatPhase) * lotus.floatSpeed; } // Create new ripples periodically self.rippleTimer++; if (self.rippleTimer > 120) { // Every 2 seconds self.createRipple(400 + Math.random() * 1200, 1500 + Math.random() * 800); self.rippleTimer = 0; } // Update existing ripples for (var i = ripples.children.length - 1; i >= 0; i--) { var ripple = ripples.children[i]; ripple.age++; // Expand ripple ripple.scale.x += 0.01; ripple.scale.y += 0.01; // Fade out ripple ripple.alpha = 1 - ripple.age / ripple.lifespan; // Remove old ripples if (ripple.age >= ripple.lifespan) { ripple.destroy(); ripples.removeChild(ripple); } } }; // Method to create a new water ripple self.createRipple = function (x, y) { var ripple = LK.getAsset('ripple', { width: 50, height: 50, color: 0xffffff, shape: 'ellipse', x: x, y: y, anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); ripple.age = 0; ripple.lifespan = 120; // 2 seconds ripples.addChild(ripple); }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.health = 100; self.maxHealth = 100; self.shootCooldown = 0; self.shootDelay = 15; // Frames between shots self.canMove = true; // Health bar setup var healthBarBg = self.attachAsset('healthBarBackground', { anchorX: 0.5, anchorY: 0, y: 120 }); var healthBarFill = self.attachAsset('healthBar', { anchorX: 0.5, anchorY: 0, y: 122 }); self.updateHealthBar = function () { var healthPercentage = self.health / self.maxHealth; healthBarFill.scale.x = healthPercentage; // Center the health bar healthBarFill.x = -100 * (1 - healthPercentage); }; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { self.health = 0; LK.effects.flashScreen(0xFF0000, 1000); LK.showGameOver(); } self.updateHealthBar(); }; self.shoot = function () { if (self.shootCooldown <= 0) { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y - 40; // Add to game's bullets array bullets.push(bullet); game.addChild(bullet); // Play gun sound LK.getSound('gunshot').play(); // Reset cooldown self.shootCooldown = self.shootDelay; } }; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.down = function (x, y, obj) { self.shoot(); }; // Initialize health bar self.updateHealthBar(); return self; }); var SoulOrb = Container.expand(function () { var self = Container.call(this); // Create the soul orb with a glowing effect var orbCore = self.attachAsset('centerCircle', { width: 60, height: 60, color: 0x83de44, anchorX: 0.5, anchorY: 0.5 }); // Create outer glow var orbGlow = LK.getAsset('centerCircle', { width: 100, height: 100, color: 0xb8ffb0, anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); self.addChild(orbGlow); // Add pulsating animation to the glow self.glowPhase = 0; self.energy = 0; // Energy level (0-100) self.maxEnergy = 100; self.pulseSpeed = 0.05; // Update method to animate the orb self.update = function () { self.glowPhase += self.pulseSpeed; orbGlow.scale.x = 1 + 0.2 * Math.sin(self.glowPhase); orbGlow.scale.y = 1 + 0.2 * Math.sin(self.glowPhase); // Adjust color based on energy level var energyRatio = self.energy / self.maxEnergy; var r = Math.floor(131 + (255 - 131) * energyRatio); var g = Math.floor(222 + (255 - 222) * energyRatio); var b = Math.floor(68 + (255 - 68) * energyRatio); // Convert RGB to hex var color = r << 16 | g << 8 | b; orbCore.tint = color; }; // Method to add energy to the orb self.addEnergy = function (amount) { self.energy = Math.min(self.maxEnergy, self.energy + amount); // Flash with increasing brightness as energy increases LK.effects.flashObject(self, 0xffffff, 300); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x081832 }); /**** * Game Code ****/ // Game variables var meditationSpace; var soulOrb; var breathingCircle; var meditationGuide; var gameActive = true; var dragOffset = { x: 0, y: 0 }; var meditationLevel = 1; var meditationTime = 0; var soulEnergy = 0; var maxSoulEnergy = 100; var breathingTimer = 0; // Meditation practices var practices = [{ id: 'breathe', text: 'Complete 5 breathing cycles', count: 0, target: 5, completed: false }, { id: 'focus', text: 'Maintain focus for 60 seconds', count: 0, target: 60, completed: false }, { id: 'energy', text: 'Fill your soul with energy', count: 0, target: 100, completed: false }]; // Setup practice UI var practiceContainer = new Container(); practiceContainer.x = 40; practiceContainer.y = 180; LK.gui.left.addChild(practiceContainer); var practiceTitle = new Text2('PRACTICES:', { size: 50, fill: 0xFFFFFF }); practiceContainer.addChild(practiceTitle); // Create text for each practice var practiceTexts = []; for (var i = 0; i < practices.length; i++) { var practiceText = new Text2('• ' + practices[i].text + ' (0/' + practices[i].target + ')', { size: 40, fill: 0xCCCCCC }); practiceText.y = 60 + i * 50; practiceContainer.addChild(practiceText); practiceTexts.push(practiceText); } // Function to update practice UI function updatePracticeDisplay() { for (var i = 0; i < practices.length; i++) { var practice = practices[i]; var color = practice.completed ? 0x83de44 : 0xCCCCCC; practiceTexts[i].setText('• ' + practice.text + ' (' + practice.count + '/' + practice.target + ')'); practiceTexts[i].fill = color; } } // Setup UI var energyTxt = new Text2('Soul Energy: 0%', { size: 60, fill: 0xFFFFFF }); energyTxt.anchor.set(0.5, 0); LK.gui.top.addChild(energyTxt); var levelTxt = new Text2('Meditation Level: 1', { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); levelTxt.y = 70; LK.gui.top.addChild(levelTxt); // Create and add meditation space meditationSpace = new MeditationSpace(); game.addChild(meditationSpace); // Initialize soul orb soulOrb = new SoulOrb(); soulOrb.x = 2048 / 2; soulOrb.y = 2732 / 3; game.addChild(soulOrb); // Initialize breathing circle breathingCircle = new BreathingCircle(); breathingCircle.x = 2048 / 2; breathingCircle.y = 2732 / 2 + 200; game.addChild(breathingCircle); // Initialize meditation guide meditationGuide = new MeditationGuide(); meditationGuide.x = 2048 / 2; meditationGuide.y = 2732 / 5; game.addChild(meditationGuide); // Play meditation music LK.playMusic('background_music'); // Create a ripple at a position (utility function) function createRipple(x, y) { meditationSpace.createRipple(x, y); } // Add soul energy function addSoulEnergy(amount) { soulOrb.addEnergy(amount); // Update energy practice var energyPractice = practices.find(function (practice) { return practice.id === 'energy'; }); if (energyPractice && !energyPractice.completed) { energyPractice.count = Math.floor(soulOrb.energy); if (energyPractice.count >= energyPractice.target) { energyPractice.completed = true; LK.effects.flashObject(practiceTexts[2], 0x83de44, 1000); } updatePracticeDisplay(); } } // Check if meditation level should increase function checkMeditationProgress() { // Check if practices are completed to progress meditation level var completedPractices = practices.filter(function (practice) { return practice.completed; }).length; var newLevel = 1 + Math.floor(completedPractices / 2); if (newLevel > meditationLevel) { meditationLevel = newLevel; levelTxt.setText('Meditation Level: ' + meditationLevel); // Bonus for reaching new level addSoulEnergy(10 * meditationLevel); // Visual feedback LK.effects.flashScreen(0x83de44, 500); } } // Meditation interaction handling game.down = function (x, y, obj) { // Calculate distances to interactive elements var distToOrb = Math.sqrt(Math.pow(x - soulOrb.x, 2) + Math.pow(y - soulOrb.y, 2)); // If touching the soul orb if (distToOrb < 100) { // Add energy to the soul soulOrb.addEnergy(5); // Emit a ripple effect from the interaction point meditationSpace.createRipple(x, y); // Create visual feedback LK.effects.flashObject(soulOrb, 0xFFFFFF, 500); } else { // Create ripple at touch point meditationSpace.createRipple(x, y); } // Set drag offset for moving the orb dragOffset.x = soulOrb.x - x; dragOffset.y = soulOrb.y - y; }; game.move = function (x, y, obj) { // Move soul orb with drag soulOrb.x = x + dragOffset.x; soulOrb.y = y + dragOffset.y; // Keep soul orb in bounds soulOrb.x = Math.max(100, Math.min(2048 - 100, soulOrb.x)); soulOrb.y = Math.max(100, Math.min(2732 - 100, soulOrb.y)); // Create subtle ripple effects during movement if (Math.random() < 0.1) { meditationSpace.createRipple(soulOrb.x + (Math.random() * 100 - 50), soulOrb.y + (Math.random() * 100 - 50)); } }; game.up = function () { // Create final ripple at release point meditationSpace.createRipple(soulOrb.x, soulOrb.y); }; // Game update loop game.update = function () { if (!gameActive) return; // Update meditation space meditationSpace.update(); // Update soul orb, breathing circle, and guide soulOrb.update(); breathingCircle.update(); meditationGuide.update(); // Update energy display energyTxt.setText('Soul Energy: ' + Math.floor(soulOrb.energy / maxSoulEnergy * 100) + '%'); // Track breathing cycles for breathe practice if (breathingCircle.breathPhase === 3 && breathingCircle.breathTimer === 0) { // Just completed a full breathing cycle var breathePractice = practices.find(function (practice) { return practice.id === 'breathe'; }); if (breathePractice && !breathePractice.completed) { breathePractice.count++; if (breathePractice.count >= breathePractice.target) { breathePractice.completed = true; LK.effects.flashObject(practiceTexts[0], 0x83de44, 1000); // Add soul energy when completing breathing practice soulOrb.addEnergy(20); } updatePracticeDisplay(); } } // Track focus time for focus practice meditationTime++; if (meditationTime % 60 === 0) { // Every second var focusPractice = practices.find(function (practice) { return practice.id === 'focus'; }); if (focusPractice && !focusPractice.completed) { focusPractice.count++; if (focusPractice.count >= focusPractice.target) { focusPractice.completed = true; LK.effects.flashObject(practiceTexts[1], 0x83de44, 1000); // Add soul energy when completing focus practice soulOrb.addEnergy(30); } updatePracticeDisplay(); } } // Add soul energy over time with active meditation if (meditationTime % 180 === 0) { // Every 3 seconds soulOrb.addEnergy(1); // Track soul energy for energy practice var energyPractice = practices.find(function (practice) { return practice.id === 'energy'; }); if (energyPractice && !energyPractice.completed) { energyPractice.count = Math.floor(soulOrb.energy); if (energyPractice.count >= energyPractice.target) { energyPractice.completed = true; LK.effects.flashObject(practiceTexts[2], 0x83de44, 1000); } updatePracticeDisplay(); } } // Check for meditation level up if (meditationTime % 600 === 0) { // Every 10 seconds meditationLevel++; levelTxt.setText('Meditation Level: ' + meditationLevel); // Visual feedback for level up LK.effects.flashScreen(0x83de44, 500); } // Check if all practices are completed var allPracticesCompleted = practices.every(function (practice) { return practice.completed; }); if (allPracticesCompleted && gameActive) { // Show enlightenment message var enlightenmentMessage = new Text2('ENLIGHTENMENT ACHIEVED!', { size: 100, fill: 0xFFFFFF }); enlightenmentMessage.anchor.set(0.5, 0.5); enlightenmentMessage.x = 2048 / 2; enlightenmentMessage.y = 2732 / 2; game.addChild(enlightenmentMessage); // Visual effects for enlightenment LK.effects.flashScreen(0xFFFFFF, 2000); // Create new practices with higher requirements practices = [{ id: 'breathe', text: 'Complete 10 breathing cycles', count: 0, target: 10, completed: false }, { id: 'focus', text: 'Maintain focus for 120 seconds', count: 0, target: 120, completed: false }, { id: 'energy', text: 'Achieve deeper enlightenment', count: 0, target: 200, completed: false }]; // Update practice display for (var i = 0; i < practices.length; i++) { practiceTexts[i].setText('• ' + practices[i].text + ' (0/' + practices[i].target + ')'); practiceTexts[i].fill = 0xCCCCCC; } // Increase soul orb capacity maxSoulEnergy = 200; // Remove the enlightenment message after 3 seconds LK.setTimeout(function () { enlightenmentMessage.destroy(); updatePracticeDisplay(); }, 3000); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Background = Container.expand(function () {
var self = Container.call(this);
// Create sky gradient
var skyGradient = new Container();
// Create several bands of sky color
var skyColors = [0x1a3c80, 0x3a5c9f, 0x5a7cbf, 0x7a9cdf, 0x9abcff];
var bandHeight = 2732 / skyColors.length;
for (var i = 0; i < skyColors.length; i++) {
var skyBand = LK.getAsset('skyBand' + i, {
width: 2048,
height: bandHeight,
color: skyColors[i],
shape: 'box',
y: i * bandHeight
});
skyGradient.addChild(skyBand);
}
self.addChild(skyGradient);
// Create buildings
var buildings = new Container();
self.addChild(buildings);
// Far buildings (darker)
var buildingColors = [0x222a40, 0x323a50, 0x424a60];
var buildingCount = 15;
for (var i = 0; i < buildingCount; i++) {
var buildingWidth = 100 + Math.random() * 150;
var buildingHeight = 300 + Math.random() * 400;
var building = LK.getAsset('building_far_' + i, {
width: buildingWidth,
height: buildingHeight,
color: buildingColors[Math.floor(Math.random() * buildingColors.length)],
shape: 'box',
x: i * (2048 / buildingCount),
y: 2732 - buildingHeight,
anchorY: 0
});
buildings.addChild(building);
}
// Near buildings (slightly lighter)
var nearBuildingColors = [0x303a50, 0x404a60, 0x505a70];
var nearBuildingCount = 10;
for (var i = 0; i < nearBuildingCount; i++) {
var buildingWidth = 180 + Math.random() * 150;
var buildingHeight = 500 + Math.random() * 600;
var building = LK.getAsset('building_near_' + i, {
width: buildingWidth,
height: buildingHeight,
color: nearBuildingColors[Math.floor(Math.random() * nearBuildingColors.length)],
shape: 'box',
x: i * (2048 / nearBuildingCount),
y: 2732 - buildingHeight,
anchorY: 0
});
buildings.addChild(building);
}
// Add some windows to buildings (as small yellow rectangles)
for (var b = 0; b < buildings.children.length; b++) {
var building = buildings.children[b];
var windowCount = Math.floor(building.width / 30) * Math.floor(building.height / 40);
// Limit window count for performance
windowCount = Math.min(windowCount, 20);
for (var w = 0; w < windowCount; w++) {
var windowSize = 10 + Math.random() * 10;
var windowX = Math.random() * (building.width - windowSize);
var windowY = Math.random() * (building.height - windowSize);
// Only add some windows (randomized lighting effect)
if (Math.random() > 0.4) {
var windowLight = LK.getAsset('window_' + b + '_' + w, {
width: windowSize,
height: windowSize,
color: Math.random() > 0.7 ? 0xffcc66 : 0x888888,
// Some windows lit, some not
shape: 'box',
x: building.x + windowX,
y: building.y + windowY
});
self.addChild(windowLight);
}
}
}
// Add clouds
var clouds = new Container();
self.clouds = clouds;
self.addChild(clouds);
var cloudCount = 6;
for (var i = 0; i < cloudCount; i++) {
var cloudWidth = 200 + Math.random() * 300;
var cloudHeight = 100 + Math.random() * 100;
var cloud = LK.getAsset('cloud_' + i, {
width: cloudWidth,
height: cloudHeight,
color: 0xddddff,
shape: 'ellipse',
x: Math.random() * 2048,
y: 200 + Math.random() * 400,
alpha: 0.7
});
// Add some variation to clouds with slight scaling
cloud.scaleX = 0.8 + Math.random() * 0.4;
cloud.scaleY = 0.8 + Math.random() * 0.4;
// Store cloud speed for animation
cloud.speedX = 0.2 + Math.random() * 0.3;
clouds.addChild(cloud);
}
// Update function to animate clouds
self.update = function () {
// Move clouds horizontally
for (var i = 0; i < clouds.children.length; i++) {
var cloud = clouds.children[i];
cloud.x += cloud.speedX;
// Loop clouds when they move off screen
if (cloud.x > 2048 + cloud.width) {
cloud.x = -cloud.width;
cloud.y = 200 + Math.random() * 400;
}
}
};
return self;
});
var BreathingCircle = Container.expand(function () {
var self = Container.call(this);
// Create the breathing circle
var innerCircle = self.attachAsset('centerCircle', {
width: 200,
height: 200,
color: 0x3a5c9f,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.4
});
var outerCircle = LK.getAsset('centerCircle', {
width: 240,
height: 240,
color: 0x5a7cbf,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.2
});
self.addChild(outerCircle);
// Breathing animation state
self.breathPhase = 0; // 0: inhale growing, 1: hold, 2: exhale shrinking, 3: hold
self.breathTimer = 0;
self.inhaleDuration = 240; // 4 seconds
self.holdDuration = 120; // 2 seconds
self.exhaleDuration = 240; // 4 seconds
self.restDuration = 60; // 1 second
// Text guide for breathing
self.breathText = new Text2("Breathe In", {
size: 40,
fill: 0xffffff
});
self.breathText.anchor.set(0.5, 0.5);
self.breathText.y = -160;
self.addChild(self.breathText);
// Update method to animate the breathing circle
self.update = function () {
self.breathTimer++;
// Determine current phase based on timer
if (self.breathPhase === 0) {
// Inhale
var progress = self.breathTimer / self.inhaleDuration;
var scale = 1 + progress * 0.5;
innerCircle.scale.x = innerCircle.scale.y = scale;
outerCircle.scale.x = outerCircle.scale.y = 0.9 + progress * 0.5;
self.breathText.setText("Breathe In");
if (self.breathTimer >= self.inhaleDuration) {
self.breathPhase = 1;
self.breathTimer = 0;
}
} else if (self.breathPhase === 1) {
// Hold after inhale
self.breathText.setText("Hold");
if (self.breathTimer >= self.holdDuration) {
self.breathPhase = 2;
self.breathTimer = 0;
}
} else if (self.breathPhase === 2) {
// Exhale
var progress = self.breathTimer / self.exhaleDuration;
var scale = 1.5 - progress * 0.5;
innerCircle.scale.x = innerCircle.scale.y = scale;
outerCircle.scale.x = outerCircle.scale.y = 1.4 - progress * 0.5;
self.breathText.setText("Breathe Out");
if (self.breathTimer >= self.exhaleDuration) {
self.breathPhase = 3;
self.breathTimer = 0;
}
} else {
// Hold after exhale
self.breathText.setText("Rest");
if (self.breathTimer >= self.restDuration) {
self.breathPhase = 0;
self.breathTimer = 0;
}
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.direction = {
x: 0,
y: -1
}; // Default upward
self.lifespan = 120; // 2 seconds at 60fps
self.age = 0;
self.damage = 1;
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
self.age++;
if (self.age > self.lifespan) {
self.markForDeletion = true;
}
};
return self;
});
var Criminal = Container.expand(function () {
var self = Container.call(this);
var criminalGraphics = self.attachAsset('criminal', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.health = 2; // Reduced from 3
self.shootCooldown = 0;
self.shootDelay = 120; // Frames between shots
self.attackRange = 300; // Reduced from 500
self.movePattern = Math.floor(Math.random() * 3); // 0: direct, 1: zigzag, 2: circle
self.moveTimer = 0;
self.update = function () {
// Target the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Movement based on pattern
if (distance > 100) {
// Keep some distance
var moveX = 0;
var moveY = 0;
switch (self.movePattern) {
case 0:
// Direct
moveX = dx / distance;
moveY = dy / distance;
break;
case 1:
// Zigzag
self.moveTimer++;
moveX = dx / distance + Math.sin(self.moveTimer * 0.1) * 0.5;
moveY = dy / distance;
break;
case 2:
// Circle
self.moveTimer++;
moveX = dx / distance + Math.sin(self.moveTimer * 0.05) * 0.8;
moveY = dy / distance + Math.cos(self.moveTimer * 0.05) * 0.8;
break;
}
self.x += moveX * self.speed;
self.y += moveY * self.speed;
}
// Shooting logic
if (distance < self.attackRange) {
if (self.shootCooldown <= 0) {
// Create enemy bullet
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
// Calculate direction toward player
var dirX = dx / distance;
var dirY = dy / distance;
bullet.direction = {
x: dirX,
y: dirY
};
// Mark as enemy bullet
bullet.isEnemyBullet = true;
// Add to game's bullets array
bullets.push(bullet);
game.addChild(bullet);
// Reset cooldown with some randomness
self.shootCooldown = self.shootDelay + Math.random() * 60;
}
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.takeDamage = function () {
self.health--;
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
LK.getSound('criminal_down').play();
LK.setScore(LK.getScore() + 1);
self.markForDeletion = true;
// Track criminal elimination task
var eliminateTask = tasks.find(function (task) {
return task.id === 'eliminate';
});
if (eliminateTask && !eliminateTask.completed) {
eliminateTask.count++;
if (eliminateTask.count >= eliminateTask.target) {
eliminateTask.completed = true;
LK.effects.flashObject(taskTexts[1], 0x00FF00, 1000);
}
updateTaskDisplay();
}
}
};
return self;
});
var EmergencyCall = Container.expand(function () {
var self = Container.call(this);
var callGraphics = self.attachAsset('emergencyCall', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 600; // 10 seconds at 60fps
self.age = 0;
self.flashInterval = 30;
self.update = function () {
self.age++;
// Flash effect
if (self.age % self.flashInterval === 0) {
if (callGraphics.alpha === 1) {
tween(callGraphics, {
alpha: 0.3
}, {
duration: 500
});
} else {
tween(callGraphics, {
alpha: 1
}, {
duration: 500
});
}
}
// Expire after lifetime
if (self.age > self.lifetime) {
self.markForDeletion = true;
}
};
self.down = function () {
// Responding to call
LK.getSound('radiochatter').play();
// Spawn criminals from top of screen, using emergency call's X position
spawnCriminals(self.x, 0, 2 + Math.floor(Math.random() * 3));
self.markForDeletion = true;
// Increase score for responding
LK.setScore(LK.getScore() + 2);
// Track emergency call response task
var respondTask = tasks.find(function (task) {
return task.id === 'respond';
});
if (respondTask && !respondTask.completed) {
respondTask.count++;
if (respondTask.count >= respondTask.target) {
respondTask.completed = true;
LK.effects.flashObject(taskTexts[0], 0x00FF00, 1000);
}
updateTaskDisplay();
}
};
return self;
});
var MeditationGuide = Container.expand(function () {
var self = Container.call(this);
// Create a text display for meditation prompts
self.promptText = new Text2("Breathe deeply...", {
size: 60,
fill: 0xffffff,
align: 'center'
});
self.promptText.anchor.set(0.5, 0.5);
self.addChild(self.promptText);
// List of meditation prompts
self.prompts = ["Breathe deeply...", "Focus on your breath...", "Let go of your thoughts...", "Feel the peace within...", "You are present...", "Allow yourself to be...", "Feel the energy flow...", "Find your center..."];
self.currentPrompt = 0;
self.promptTimer = 0;
self.promptDuration = 300; // 5 seconds per prompt
// Update method to cycle through prompts
self.update = function () {
self.promptTimer++;
// Change prompt periodically
if (self.promptTimer >= self.promptDuration) {
self.currentPrompt = (self.currentPrompt + 1) % self.prompts.length;
self.promptText.setText(self.prompts[self.currentPrompt]);
self.promptTimer = 0;
// Animate text appearance
self.promptText.alpha = 0;
tween(self.promptText, {
alpha: 1
}, {
duration: 1000
});
}
// Subtle pulse animation
var scale = 1 + 0.05 * Math.sin(self.promptTimer * 0.01);
self.promptText.scale.x = scale;
self.promptText.scale.y = scale;
};
return self;
});
var MeditationSpace = Container.expand(function () {
var self = Container.call(this);
// Create a peaceful gradient background
var background = new Container();
self.addChild(background);
// Create calming gradient colors for the background
var skyColors = [0x081832, 0x112a4e, 0x1a3c6a, 0x234e86, 0x2c60a2];
var bandHeight = 2732 / skyColors.length;
for (var i = 0; i < skyColors.length; i++) {
var skyBand = LK.getAsset('skyBand' + i, {
width: 2048,
height: bandHeight,
color: skyColors[i],
y: i * bandHeight
});
background.addChild(skyBand);
}
// Create stars
var stars = new Container();
self.stars = stars;
self.addChild(stars);
// Add stars to the night sky
var starCount = 100;
for (var i = 0; i < starCount; i++) {
var starSize = 2 + Math.random() * 4;
var star = LK.getAsset('star_' + i, {
width: starSize,
height: starSize,
color: 0xffffff,
shape: 'ellipse',
x: Math.random() * 2048,
y: Math.random() * 1200,
alpha: 0.5 + Math.random() * 0.5
});
star.pulseSpeed = 0.01 + Math.random() * 0.02;
star.pulsePhase = Math.random() * Math.PI * 2;
stars.addChild(star);
}
// Add floating lotus flowers
var lotusFlowers = new Container();
self.lotusFlowers = lotusFlowers;
self.addChild(lotusFlowers);
var lotusCount = 5;
for (var i = 0; i < lotusCount; i++) {
var lotusSize = 80 + Math.random() * 40;
var lotus = LK.getAsset('lotus_' + i, {
width: lotusSize,
height: lotusSize,
color: 0xffb6c1,
shape: 'ellipse',
x: 400 + Math.random() * 1200,
y: 1500 + Math.random() * 800
});
lotus.floatSpeed = 0.2 + Math.random() * 0.3;
lotus.floatPhase = Math.random() * Math.PI * 2;
lotusFlowers.addChild(lotus);
}
// Add water ripples
var ripples = new Container();
self.ripples = ripples;
self.addChild(ripples);
self.rippleTimer = 0;
// Update function to animate elements
self.update = function () {
// Animate stars (pulsing effect)
for (var i = 0; i < stars.children.length; i++) {
var star = stars.children[i];
star.pulsePhase += star.pulseSpeed;
star.alpha = 0.5 + 0.5 * Math.sin(star.pulsePhase);
}
// Animate lotus flowers (gentle floating)
for (var i = 0; i < lotusFlowers.children.length; i++) {
var lotus = lotusFlowers.children[i];
lotus.floatPhase += 0.01;
lotus.y += Math.sin(lotus.floatPhase) * lotus.floatSpeed;
}
// Create new ripples periodically
self.rippleTimer++;
if (self.rippleTimer > 120) {
// Every 2 seconds
self.createRipple(400 + Math.random() * 1200, 1500 + Math.random() * 800);
self.rippleTimer = 0;
}
// Update existing ripples
for (var i = ripples.children.length - 1; i >= 0; i--) {
var ripple = ripples.children[i];
ripple.age++;
// Expand ripple
ripple.scale.x += 0.01;
ripple.scale.y += 0.01;
// Fade out ripple
ripple.alpha = 1 - ripple.age / ripple.lifespan;
// Remove old ripples
if (ripple.age >= ripple.lifespan) {
ripple.destroy();
ripples.removeChild(ripple);
}
}
};
// Method to create a new water ripple
self.createRipple = function (x, y) {
var ripple = LK.getAsset('ripple', {
width: 50,
height: 50,
color: 0xffffff,
shape: 'ellipse',
x: x,
y: y,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
ripple.age = 0;
ripple.lifespan = 120; // 2 seconds
ripples.addChild(ripple);
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.health = 100;
self.maxHealth = 100;
self.shootCooldown = 0;
self.shootDelay = 15; // Frames between shots
self.canMove = true;
// Health bar setup
var healthBarBg = self.attachAsset('healthBarBackground', {
anchorX: 0.5,
anchorY: 0,
y: 120
});
var healthBarFill = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0,
y: 122
});
self.updateHealthBar = function () {
var healthPercentage = self.health / self.maxHealth;
healthBarFill.scale.x = healthPercentage;
// Center the health bar
healthBarFill.x = -100 * (1 - healthPercentage);
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
self.health = 0;
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
self.updateHealthBar();
};
self.shoot = function () {
if (self.shootCooldown <= 0) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y - 40;
// Add to game's bullets array
bullets.push(bullet);
game.addChild(bullet);
// Play gun sound
LK.getSound('gunshot').play();
// Reset cooldown
self.shootCooldown = self.shootDelay;
}
};
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.down = function (x, y, obj) {
self.shoot();
};
// Initialize health bar
self.updateHealthBar();
return self;
});
var SoulOrb = Container.expand(function () {
var self = Container.call(this);
// Create the soul orb with a glowing effect
var orbCore = self.attachAsset('centerCircle', {
width: 60,
height: 60,
color: 0x83de44,
anchorX: 0.5,
anchorY: 0.5
});
// Create outer glow
var orbGlow = LK.getAsset('centerCircle', {
width: 100,
height: 100,
color: 0xb8ffb0,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
self.addChild(orbGlow);
// Add pulsating animation to the glow
self.glowPhase = 0;
self.energy = 0; // Energy level (0-100)
self.maxEnergy = 100;
self.pulseSpeed = 0.05;
// Update method to animate the orb
self.update = function () {
self.glowPhase += self.pulseSpeed;
orbGlow.scale.x = 1 + 0.2 * Math.sin(self.glowPhase);
orbGlow.scale.y = 1 + 0.2 * Math.sin(self.glowPhase);
// Adjust color based on energy level
var energyRatio = self.energy / self.maxEnergy;
var r = Math.floor(131 + (255 - 131) * energyRatio);
var g = Math.floor(222 + (255 - 222) * energyRatio);
var b = Math.floor(68 + (255 - 68) * energyRatio);
// Convert RGB to hex
var color = r << 16 | g << 8 | b;
orbCore.tint = color;
};
// Method to add energy to the orb
self.addEnergy = function (amount) {
self.energy = Math.min(self.maxEnergy, self.energy + amount);
// Flash with increasing brightness as energy increases
LK.effects.flashObject(self, 0xffffff, 300);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x081832
});
/****
* Game Code
****/
// Game variables
var meditationSpace;
var soulOrb;
var breathingCircle;
var meditationGuide;
var gameActive = true;
var dragOffset = {
x: 0,
y: 0
};
var meditationLevel = 1;
var meditationTime = 0;
var soulEnergy = 0;
var maxSoulEnergy = 100;
var breathingTimer = 0;
// Meditation practices
var practices = [{
id: 'breathe',
text: 'Complete 5 breathing cycles',
count: 0,
target: 5,
completed: false
}, {
id: 'focus',
text: 'Maintain focus for 60 seconds',
count: 0,
target: 60,
completed: false
}, {
id: 'energy',
text: 'Fill your soul with energy',
count: 0,
target: 100,
completed: false
}];
// Setup practice UI
var practiceContainer = new Container();
practiceContainer.x = 40;
practiceContainer.y = 180;
LK.gui.left.addChild(practiceContainer);
var practiceTitle = new Text2('PRACTICES:', {
size: 50,
fill: 0xFFFFFF
});
practiceContainer.addChild(practiceTitle);
// Create text for each practice
var practiceTexts = [];
for (var i = 0; i < practices.length; i++) {
var practiceText = new Text2('• ' + practices[i].text + ' (0/' + practices[i].target + ')', {
size: 40,
fill: 0xCCCCCC
});
practiceText.y = 60 + i * 50;
practiceContainer.addChild(practiceText);
practiceTexts.push(practiceText);
}
// Function to update practice UI
function updatePracticeDisplay() {
for (var i = 0; i < practices.length; i++) {
var practice = practices[i];
var color = practice.completed ? 0x83de44 : 0xCCCCCC;
practiceTexts[i].setText('• ' + practice.text + ' (' + practice.count + '/' + practice.target + ')');
practiceTexts[i].fill = color;
}
}
// Setup UI
var energyTxt = new Text2('Soul Energy: 0%', {
size: 60,
fill: 0xFFFFFF
});
energyTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(energyTxt);
var levelTxt = new Text2('Meditation Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
levelTxt.y = 70;
LK.gui.top.addChild(levelTxt);
// Create and add meditation space
meditationSpace = new MeditationSpace();
game.addChild(meditationSpace);
// Initialize soul orb
soulOrb = new SoulOrb();
soulOrb.x = 2048 / 2;
soulOrb.y = 2732 / 3;
game.addChild(soulOrb);
// Initialize breathing circle
breathingCircle = new BreathingCircle();
breathingCircle.x = 2048 / 2;
breathingCircle.y = 2732 / 2 + 200;
game.addChild(breathingCircle);
// Initialize meditation guide
meditationGuide = new MeditationGuide();
meditationGuide.x = 2048 / 2;
meditationGuide.y = 2732 / 5;
game.addChild(meditationGuide);
// Play meditation music
LK.playMusic('background_music');
// Create a ripple at a position (utility function)
function createRipple(x, y) {
meditationSpace.createRipple(x, y);
}
// Add soul energy
function addSoulEnergy(amount) {
soulOrb.addEnergy(amount);
// Update energy practice
var energyPractice = practices.find(function (practice) {
return practice.id === 'energy';
});
if (energyPractice && !energyPractice.completed) {
energyPractice.count = Math.floor(soulOrb.energy);
if (energyPractice.count >= energyPractice.target) {
energyPractice.completed = true;
LK.effects.flashObject(practiceTexts[2], 0x83de44, 1000);
}
updatePracticeDisplay();
}
}
// Check if meditation level should increase
function checkMeditationProgress() {
// Check if practices are completed to progress meditation level
var completedPractices = practices.filter(function (practice) {
return practice.completed;
}).length;
var newLevel = 1 + Math.floor(completedPractices / 2);
if (newLevel > meditationLevel) {
meditationLevel = newLevel;
levelTxt.setText('Meditation Level: ' + meditationLevel);
// Bonus for reaching new level
addSoulEnergy(10 * meditationLevel);
// Visual feedback
LK.effects.flashScreen(0x83de44, 500);
}
}
// Meditation interaction handling
game.down = function (x, y, obj) {
// Calculate distances to interactive elements
var distToOrb = Math.sqrt(Math.pow(x - soulOrb.x, 2) + Math.pow(y - soulOrb.y, 2));
// If touching the soul orb
if (distToOrb < 100) {
// Add energy to the soul
soulOrb.addEnergy(5);
// Emit a ripple effect from the interaction point
meditationSpace.createRipple(x, y);
// Create visual feedback
LK.effects.flashObject(soulOrb, 0xFFFFFF, 500);
} else {
// Create ripple at touch point
meditationSpace.createRipple(x, y);
}
// Set drag offset for moving the orb
dragOffset.x = soulOrb.x - x;
dragOffset.y = soulOrb.y - y;
};
game.move = function (x, y, obj) {
// Move soul orb with drag
soulOrb.x = x + dragOffset.x;
soulOrb.y = y + dragOffset.y;
// Keep soul orb in bounds
soulOrb.x = Math.max(100, Math.min(2048 - 100, soulOrb.x));
soulOrb.y = Math.max(100, Math.min(2732 - 100, soulOrb.y));
// Create subtle ripple effects during movement
if (Math.random() < 0.1) {
meditationSpace.createRipple(soulOrb.x + (Math.random() * 100 - 50), soulOrb.y + (Math.random() * 100 - 50));
}
};
game.up = function () {
// Create final ripple at release point
meditationSpace.createRipple(soulOrb.x, soulOrb.y);
};
// Game update loop
game.update = function () {
if (!gameActive) return;
// Update meditation space
meditationSpace.update();
// Update soul orb, breathing circle, and guide
soulOrb.update();
breathingCircle.update();
meditationGuide.update();
// Update energy display
energyTxt.setText('Soul Energy: ' + Math.floor(soulOrb.energy / maxSoulEnergy * 100) + '%');
// Track breathing cycles for breathe practice
if (breathingCircle.breathPhase === 3 && breathingCircle.breathTimer === 0) {
// Just completed a full breathing cycle
var breathePractice = practices.find(function (practice) {
return practice.id === 'breathe';
});
if (breathePractice && !breathePractice.completed) {
breathePractice.count++;
if (breathePractice.count >= breathePractice.target) {
breathePractice.completed = true;
LK.effects.flashObject(practiceTexts[0], 0x83de44, 1000);
// Add soul energy when completing breathing practice
soulOrb.addEnergy(20);
}
updatePracticeDisplay();
}
}
// Track focus time for focus practice
meditationTime++;
if (meditationTime % 60 === 0) {
// Every second
var focusPractice = practices.find(function (practice) {
return practice.id === 'focus';
});
if (focusPractice && !focusPractice.completed) {
focusPractice.count++;
if (focusPractice.count >= focusPractice.target) {
focusPractice.completed = true;
LK.effects.flashObject(practiceTexts[1], 0x83de44, 1000);
// Add soul energy when completing focus practice
soulOrb.addEnergy(30);
}
updatePracticeDisplay();
}
}
// Add soul energy over time with active meditation
if (meditationTime % 180 === 0) {
// Every 3 seconds
soulOrb.addEnergy(1);
// Track soul energy for energy practice
var energyPractice = practices.find(function (practice) {
return practice.id === 'energy';
});
if (energyPractice && !energyPractice.completed) {
energyPractice.count = Math.floor(soulOrb.energy);
if (energyPractice.count >= energyPractice.target) {
energyPractice.completed = true;
LK.effects.flashObject(practiceTexts[2], 0x83de44, 1000);
}
updatePracticeDisplay();
}
}
// Check for meditation level up
if (meditationTime % 600 === 0) {
// Every 10 seconds
meditationLevel++;
levelTxt.setText('Meditation Level: ' + meditationLevel);
// Visual feedback for level up
LK.effects.flashScreen(0x83de44, 500);
}
// Check if all practices are completed
var allPracticesCompleted = practices.every(function (practice) {
return practice.completed;
});
if (allPracticesCompleted && gameActive) {
// Show enlightenment message
var enlightenmentMessage = new Text2('ENLIGHTENMENT ACHIEVED!', {
size: 100,
fill: 0xFFFFFF
});
enlightenmentMessage.anchor.set(0.5, 0.5);
enlightenmentMessage.x = 2048 / 2;
enlightenmentMessage.y = 2732 / 2;
game.addChild(enlightenmentMessage);
// Visual effects for enlightenment
LK.effects.flashScreen(0xFFFFFF, 2000);
// Create new practices with higher requirements
practices = [{
id: 'breathe',
text: 'Complete 10 breathing cycles',
count: 0,
target: 10,
completed: false
}, {
id: 'focus',
text: 'Maintain focus for 120 seconds',
count: 0,
target: 120,
completed: false
}, {
id: 'energy',
text: 'Achieve deeper enlightenment',
count: 0,
target: 200,
completed: false
}];
// Update practice display
for (var i = 0; i < practices.length; i++) {
practiceTexts[i].setText('• ' + practices[i].text + ' (0/' + practices[i].target + ')');
practiceTexts[i].fill = 0xCCCCCC;
}
// Increase soul orb capacity
maxSoulEnergy = 200;
// Remove the enlightenment message after 3 seconds
LK.setTimeout(function () {
enlightenmentMessage.destroy();
updatePracticeDisplay();
}, 3000);
}
};