/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var Animal = Container.expand(function () { var self = Container.call(this); self.animalGraphic = self.attachAsset('animal', { anchorX: 0.5, anchorY: 0.5 }); self.direction = Math.random() > 0.5 ? 1 : -1; self.speed = Math.random() * 2 + 1; self.health = 100; self.hunger = 0; self.thirsty = 0; self.state = 'wandering'; // wandering, eating, drinking self.targetX = null; self.targetY = null; self.targetPlant = null; self.wanderTimer = 0; if (self.direction === -1) { self.animalGraphic.scaleX = -1; } self.update = function () { // Natural state changes self.hunger += 0.1; self.thirsty += 0.15; // Cap values if (self.hunger > 100) { self.hunger = 100; } if (self.thirsty > 100) { self.thirsty = 100; } // Health decreases if hungry or thirsty if (self.hunger > 80 || self.thirsty > 80) { self.health -= 0.2; } else { // Recover health when not hungry or thirsty self.health += 0.05; if (self.health > 100) { self.health = 100; } } // Decision making if (self.state === 'wandering') { // Find food or water if needed if (self.thirsty > 70 && waterPools.length > 0) { self.state = 'drinking'; // Find nearest water var closestDist = Infinity; var closestWater = null; for (var i = 0; i < waterPools.length; i++) { var water = waterPools[i]; var dist = Math.sqrt(Math.pow(self.x - water.x, 2) + Math.pow(self.y - water.y, 2)); if (dist < closestDist) { closestDist = dist; closestWater = water; } } if (closestWater) { self.targetX = closestWater.x + Math.random() * 100 - 50; self.targetY = closestWater.y - 30; } } else if (self.hunger > 60 && plants.length > 0) { self.state = 'eating'; // Find nearest plant that's mature enough var closestDist = Infinity; var closestPlant = null; for (var j = 0; j < plants.length; j++) { var plant = plants[j]; if (plant.growthStage > 2) { // Only eat mature plants var dist = Math.sqrt(Math.pow(self.x - plant.x, 2) + Math.pow(self.y - plant.y, 2)); if (dist < closestDist) { closestDist = dist; closestPlant = plant; } } } if (closestPlant) { self.targetPlant = closestPlant; self.targetX = closestPlant.x; self.targetY = closestPlant.y; } else { // No suitable plants, continue wandering self.wanderTimer++; if (self.wanderTimer > 120) { self.wanderTimer = 0; self.targetX = Math.random() * 1800 + 100; } } } else { // Regular wandering self.wanderTimer++; if (self.wanderTimer > 180 || self.targetX === null) { self.wanderTimer = 0; self.targetX = Math.random() * 1800 + 100; } } // Move towards target if there is one if (self.targetX !== null) { var dx = self.targetX - self.x; if (Math.abs(dx) < 5) { // Reached target self.targetX = null; } else { // Move towards target self.direction = dx > 0 ? 1 : -1; self.animalGraphic.scaleX = self.direction; self.x += self.direction * self.speed; } } } else if (self.state === 'drinking') { // Move towards water if (self.targetX !== null) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 20) { // Reached water, drink self.thirsty -= 1; // Make drinking animation if (Math.random() < 0.1) { var splash = new Particle(); splash.x = self.x; splash.y = self.y + 20; splash.vx = Math.random() * 2 - 1; splash.vy = -Math.random() * 2 - 1; splash.lifespan = 20; game.addChild(splash); particles.push(splash); } // Done drinking if (self.thirsty <= 10) { self.state = 'wandering'; self.targetX = null; LK.getSound('animalSound').play(); } } else { // Move towards water self.direction = dx > 0 ? 1 : -1; self.animalGraphic.scaleX = self.direction; self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } else { self.state = 'wandering'; } } else if (self.state === 'eating') { // Move towards plant if (self.targetPlant && self.targetPlant.parent) { var dx = self.targetPlant.x - self.x; var dy = self.targetPlant.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 30) { // Reached plant, eat self.hunger -= 0.5; self.targetPlant.growthStage -= 0.01; // Done eating if (self.hunger <= 10 || self.targetPlant.growthStage <= 1) { self.state = 'wandering'; self.targetPlant = null; self.targetX = null; LK.getSound('animalSound').play(); } } else { // Move towards plant self.direction = dx > 0 ? 1 : -1; self.animalGraphic.scaleX = self.direction; self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; } } else { self.state = 'wandering'; self.targetPlant = null; } } // Health visual indicator if (self.health < 50) { self.animalGraphic.alpha = 0.5 + self.health / 100 * 0.5; } else { self.animalGraphic.alpha = 1.0; } // Die if health reaches 0 if (self.health <= 0 && self.parent) { tween(self, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { self.destroy(); } }); } }; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphic = self.attachAsset('particleSmall', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); self.vx = 0; self.vy = 0; self.lifespan = 100; self.age = 0; self.update = function () { self.x += self.vx; self.y += self.vy; self.age++; if (self.age > self.lifespan) { if (self.parent) { self.destroy(); } return; } particleGraphic.alpha = 1 - self.age / self.lifespan; }; return self; }); var Plant = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'grass'; self.growthStage = 0; self.maxGrowth = 5; self.growthSpeed = 0; self.health = 100; self.waterLevel = 50; self.sunLevel = 50; self.buildGraphics = function () { self.removeChildren(); if (self.type === 'grass') { var scale = 0.4 + self.growthStage / self.maxGrowth * 0.6; self.mainGraphic = self.attachAsset('grass', { anchorX: 0.5, anchorY: 1.0, scaleX: scale, scaleY: scale }); } else if (self.type === 'tree') { var scale = 0.3 + self.growthStage / self.maxGrowth * 0.7; // Tree trunk self.trunkGraphic = self.attachAsset('tree', { anchorX: 0.5, anchorY: 1.0, scaleX: scale, scaleY: scale }); // Tree top self.topGraphic = self.attachAsset('treeTop', { anchorX: 0.5, anchorY: 1.0, y: -self.trunkGraphic.height * scale, scaleX: scale * 1.2, scaleY: scale * 1.2 }); } else if (self.type === 'flower') { var scale = 0.3 + self.growthStage / self.maxGrowth * 0.7; // Stem self.stemGraphic = self.attachAsset('grass', { anchorX: 0.5, anchorY: 1.0, scaleX: scale * 0.5, scaleY: scale }); // Flower self.flowerGraphic = self.attachAsset('flower', { anchorX: 0.5, anchorY: 0.5, y: -self.stemGraphic.height * scale, scaleX: scale, scaleY: scale }); } }; // Set initial graphics self.buildGraphics(); self.grow = function () { if (self.growthStage < self.maxGrowth) { self.growthStage += 0.1; self.buildGraphics(); } }; self.updateHealth = function () { // Ideal conditions: water 50-70, sun 50-80 if (self.waterLevel < 20 || self.waterLevel > 90) { self.health -= 0.5; } else if (self.waterLevel > 40 && self.waterLevel < 80) { self.health += 0.2; } if (self.sunLevel < 30 || self.sunLevel > 90) { self.health -= 0.5; } else if (self.sunLevel > 40 && self.sunLevel < 80) { self.health += 0.2; } // Cap health if (self.health > 100) { self.health = 100; } if (self.health < 0) { self.health = 0; } // Update visual health var healthColor = 0x33D17A; // Healthy green if (self.health < 70) { healthColor = 0xF6D32D; } // Yellow-ish if (self.health < 40) { healthColor = 0xE01B24; } // Red-ish // Change tint based on health if (self.type === 'grass') { self.mainGraphic.tint = healthColor; } else if (self.type === 'tree') { self.topGraphic.tint = healthColor; } else if (self.type === 'flower') { self.flowerGraphic.tint = healthColor; } // If plant is dead, make it wither if (self.health <= 0 && self.parent) { tween(self, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { self.destroy(); } }); } }; self.update = function () { // Natural water loss self.waterLevel -= 0.1; // Natural sun effects based on weather if (currentWeather === 'sunny') { self.sunLevel += 0.2; self.waterLevel -= 0.05; // Extra evaporation when sunny } else if (currentWeather === 'rainy') { self.sunLevel -= 0.1; self.waterLevel += 0.3; } else if (currentWeather === 'windy') { self.waterLevel -= 0.15; // Wind causes more evaporation } else if (currentWeather === 'stormy') { self.sunLevel -= 0.2; self.waterLevel += 0.5; } // Cap water and sun levels if (self.waterLevel > 100) { self.waterLevel = 100; } if (self.waterLevel < 0) { self.waterLevel = 0; } if (self.sunLevel > 100) { self.sunLevel = 100; } if (self.sunLevel < 0) { self.sunLevel = 0; } // Update health based on conditions self.updateHealth(); // Calculate growth speed self.growthSpeed = 0; // Perfect conditions for growth if (self.waterLevel > 40 && self.waterLevel < 80 && self.sunLevel > 40 && self.sunLevel < 80) { self.growthSpeed = 0.01; } // Apply growth if (self.growthSpeed > 0) { self.grow(); } }; return self; }); var Raindrop = Container.expand(function () { var self = Container.call(this); var dropGraphic = self.attachAsset('rain', { anchorX: 0.5, anchorY: 0.5 }); self.speed = Math.random() * 5 + 10; self.alpha = Math.random() * 0.5 + 0.5; dropGraphic.alpha = self.alpha; self.update = function () { self.y += self.speed; // If raindrop is below ground level if (self.y > groundLevel) { // Create splash effect for (var i = 0; i < 3; i++) { var splash = new Particle(); splash.x = self.x; splash.y = groundLevel; splash.vx = Math.random() * 4 - 2; splash.vy = -Math.random() * 3 - 2; splash.lifespan = 20; game.addChild(splash); particles.push(splash); } if (self.parent) { self.destroy(); } } }; return self; }); var StormCloud = Container.expand(function () { var self = Container.call(this); var cloudBase = self.attachAsset('storm', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 2, alpha: 0.7 }); // Add some smaller clouds around it for texture for (var i = 0; i < 5; i++) { var cloudPuff = self.attachAsset('storm', { anchorX: 0.5, anchorY: 0.5, x: Math.random() * 160 - 80, y: Math.random() * 60 - 30, scaleX: Math.random() * 1.5 + 0.5, scaleY: Math.random() * 1.5 + 0.5, alpha: 0.8 }); } self.vx = Math.random() * 2 - 1; self.vy = Math.random() * 0.5 - 0.25; self.thunderTimer = 0; self.thunderFrequency = Math.floor(Math.random() * 120) + 180; // 3-5 seconds between thunder self.lifespan = 600; // 10 seconds life self.age = 0; self.update = function () { self.x += self.vx; self.y += self.vy; self.age++; // Wrap around edges if (self.x < -100) { self.x = 2148; } if (self.x > 2148) { self.x = -100; } self.thunderTimer++; if (self.thunderTimer >= self.thunderFrequency) { self.thunderTimer = 0; // Flash the storm cloud tween(self, { alpha: 0.9 }, { duration: 100, onFinish: function onFinish() { tween(self, { alpha: 0.7 }, { duration: 300 }); } }); // Play thunder sound LK.getSound('stormSound').play(); // Create rain from the storm for (var i = 0; i < 8; i++) { var drop = new Raindrop(); drop.x = self.x + Math.random() * 160 - 80; drop.y = self.y + 40; game.addChild(drop); rain.push(drop); } } if (self.age > self.lifespan) { if (self.parent) { tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); } } }; return self; }); var Sun = Container.expand(function () { var self = Container.call(this); var sunGraphic = self.attachAsset('sun', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.intensity = 0; self.targetIntensity = 0; self.update = function () { // Smooth transition to target intensity if (self.intensity < self.targetIntensity) { self.intensity += 0.01; } else if (self.intensity > self.targetIntensity) { self.intensity -= 0.01; } // Visual representation of intensity sunGraphic.alpha = self.intensity; // Sun rays effect if (self.intensity > 0.5 && Math.random() < 0.1) { var ray = new Particle(); ray.x = self.x; ray.y = self.y; var angle = Math.random() * Math.PI * 2; var distance = sunGraphic.width * 0.7; ray.vx = Math.cos(angle) * 2; ray.vy = Math.sin(angle) * 2; ray.x += Math.cos(angle) * distance; ray.y += Math.sin(angle) * distance; ray.lifespan = 30; game.addChild(ray); particles.push(ray); } }; return self; }); var WaterPool = Container.expand(function () { var self = Container.call(this); self.width = 400; self.height = 200; var waterGraphic = self.attachAsset('water', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); self.level = 100; // Water level percentage self.update = function () { // Water level changes based on weather if (currentWeather === 'sunny') { self.level -= 0.1; } else if (currentWeather === 'rainy') { self.level += 0.2; } else if (currentWeather === 'windy') { self.level -= 0.05; } else if (currentWeather === 'stormy') { self.level += 0.3; } // Cap water level if (self.level > 100) { self.level = 100; } if (self.level < 0) { self.level = 0; } // Visual representation of water level waterGraphic.scaleY = self.level / 100; // Create ripples occasionally if (Math.random() < 0.05 && self.level > 10) { var ripple = new Particle(); ripple.x = self.x + Math.random() * self.width - self.width / 2; ripple.y = self.y + Math.random() * self.height / 2 - self.height / 4; ripple.vx = Math.random() * 0.5 - 0.25; ripple.vy = Math.random() * 0.5 - 0.25; ripple.lifespan = 30; game.addChild(ripple); particles.push(ripple); } }; return self; }); var WindGust = Container.expand(function () { var self = Container.call(this); var gustGraphic = self.attachAsset('wind', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); self.speed = Math.random() * 8 + 5; self.lifespan = 120; self.age = 0; self.update = function () { self.x += self.speed; self.age++; if (self.age > self.lifespan || self.x > 2048 + gustGraphic.width) { if (self.parent) { self.destroy(); } return; } gustGraphic.alpha = 0.3 * (1 - self.age / self.lifespan); // Create particles along the wind path if (self.age % 5 === 0) { var particle = new Particle(); particle.x = self.x; particle.y = self.y + (Math.random() * gustGraphic.height - gustGraphic.height / 2); particle.vx = self.speed * 0.8; particle.vy = Math.random() * 2 - 1; particle.lifespan = 40; game.addChild(particle); particles.push(particle); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue background }); /**** * Game Code ****/ // Global variables var groundLevel = 2200; var currentWeather = 'neutral'; // neutral, sunny, rainy, windy, stormy var weatherIntensity = 0; var weatherChangeTimer = 0; var faceDetected = false; var lastExpression = 'neutral'; // Arrays to keep track of game objects var plants = []; var animals = []; var rain = []; var wind = []; var storms = []; var particles = []; var waterPools = []; // Create ground var ground = game.addChild(LK.getAsset('ground', { anchorX: 0.5, anchorY: 0.0, x: 2048 / 2, y: groundLevel })); // Create sun var sun = new Sun(); sun.x = 200; sun.y = 200; game.addChild(sun); // Create water pool var pool = new WaterPool(); pool.x = 1700; pool.y = groundLevel - 60; game.addChild(pool); waterPools.push(pool); // UI Elements var ecosystemTxt = new Text2('Emotion Ecosystem', { size: 70, fill: 0xFFFFFF }); ecosystemTxt.anchor.set(0.5, 0); LK.gui.top.addChild(ecosystemTxt); var detectionTxt = new Text2('Looking for your face...', { size: 40, fill: 0xFFFFFF }); detectionTxt.anchor.set(0.5, 0); detectionTxt.y = 100; LK.gui.top.addChild(detectionTxt); var weatherTxt = new Text2('Weather: Neutral', { size: 40, fill: 0xFFFFFF }); weatherTxt.anchor.set(0.5, 0); weatherTxt.y = 150; LK.gui.top.addChild(weatherTxt); var instructionsTxt = new Text2('Smile = Sun\n' + 'Frown = Rain\n' + 'Surprised = Wind\n' + 'Angry = Storm', { size: 30, fill: 0xFFFFFF }); instructionsTxt.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionsTxt); // Helper functions function generatePlant(type, x) { var plant = new Plant(type); plant.x = x || Math.random() * 1800 + 100; plant.y = groundLevel; game.addChild(plant); plants.push(plant); return plant; } function generateAnimal(x) { var animal = new Animal(); animal.x = x || Math.random() * 1800 + 100; animal.y = groundLevel - 20; game.addChild(animal); animals.push(animal); return animal; } function createRain() { var drop = new Raindrop(); drop.x = Math.random() * 2048; drop.y = -50; game.addChild(drop); rain.push(drop); // Play rain sound occasionally if (Math.random() < 0.05) { LK.getSound('rainSound').play(); } } function createWind() { var gust = new WindGust(); gust.x = -100; gust.y = Math.random() * 1500; game.addChild(gust); wind.push(gust); // Play wind sound occasionally if (Math.random() < 0.1) { LK.getSound('windSound').play(); } } function createStorm() { var storm = new StormCloud(); storm.x = Math.random() * 2048; storm.y = Math.random() * 300 + 100; game.addChild(storm); storms.push(storm); } function detectFacialExpression() { // Check if face is detected if (facekit.mouthCenter.x > 0 || facekit.mouthCenter.y > 0) { faceDetected = true; // Check facial expressions if (facekit.mouthOpen) { // Calculate how open the mouth is based on distance between upper and lower lip var mouthOpenness = Math.abs(facekit.upperLip.y - facekit.lowerLip.y) / 100; if (mouthOpenness > 0.5) { // Very open mouth - surprised expression return 'surprised'; } } // Check smile (happy expression) // A smile is detected by curvature of the mouth // This is a simple approximation - in a real implementation we'd use more robust detection var mouthWidth = Math.abs(facekit.upperLip.x - facekit.lowerLip.x); var mouthHeight = Math.abs(facekit.upperLip.y - facekit.lowerLip.y); if (mouthWidth > 30 && mouthHeight < 20) { return 'happy'; } // Check frown (sad expression) // Simple approximation - in real implementation we'd use more robust detection if (mouthWidth < 20 && facekit.upperLip.y > facekit.lowerLip.y) { return 'sad'; } // Check angry expression // Simple approximation using eyebrows and mouth // For this demo, we'll use volume as a proxy for anger if (facekit.volume > 0.7) { return 'angry'; } return 'neutral'; } else { faceDetected = false; return 'not detected'; } } function updateWeather() { // Blend from current weather to target weather based on expression if (lastExpression === 'happy') { currentWeather = 'sunny'; sun.targetIntensity = 1.0; } else if (lastExpression === 'sad') { currentWeather = 'rainy'; sun.targetIntensity = 0.3; } else if (lastExpression === 'surprised') { currentWeather = 'windy'; sun.targetIntensity = 0.6; } else if (lastExpression === 'angry') { currentWeather = 'stormy'; sun.targetIntensity = 0.2; } else { currentWeather = 'neutral'; sun.targetIntensity = 0.5; } // Update weather text weatherTxt.setText('Weather: ' + currentWeather.charAt(0).toUpperCase() + currentWeather.slice(1)); // Spawn weather effects based on current weather if (currentWeather === 'rainy' && Math.random() < 0.2) { createRain(); } else if (currentWeather === 'windy' && Math.random() < 0.1) { createWind(); } else if (currentWeather === 'stormy') { if (Math.random() < 0.02 && storms.length < 3) { createStorm(); } if (Math.random() < 0.1) { createRain(); } } } // Setup initial ecosystem function setupInitialEcosystem() { // Create initial plants for (var i = 0; i < 5; i++) { generatePlant('grass', 200 + i * 300); } for (var i = 0; i < 3; i++) { generatePlant('tree', 400 + i * 400); } for (var i = 0; i < 4; i++) { generatePlant('flower', 350 + i * 350); } // Create initial animals for (var i = 0; i < 3; i++) { generateAnimal(300 + i * 500); } // Start background music LK.playMusic('bgMusic'); } // Call setup setupInitialEcosystem(); // Main game loop game.update = function () { // Update face detection status var expression = detectFacialExpression(); if (expression !== 'not detected') { detectionTxt.setText('Expression: ' + expression.charAt(0).toUpperCase() + expression.slice(1)); lastExpression = expression; } else { detectionTxt.setText('Looking for your face...'); } // Update weather based on expression updateWeather(); // Update weather timer weatherChangeTimer++; if (weatherChangeTimer > 300) { // Every 5 seconds weatherChangeTimer = 0; // Occasionally spawn new plants or animals if (plants.length < 20 && Math.random() < 0.3) { var types = ['grass', 'tree', 'flower']; generatePlant(types[Math.floor(Math.random() * types.length)]); } if (animals.length < 8 && Math.random() < 0.2) { generateAnimal(); } } // Update all game objects sun.update(); // Update plants for (var i = plants.length - 1; i >= 0; i--) { if (plants[i].parent) { plants[i].update(); } else { plants.splice(i, 1); } } // Update animals for (var i = animals.length - 1; i >= 0; i--) { if (animals[i].parent) { animals[i].update(); } else { animals.splice(i, 1); } } // Update rain for (var i = rain.length - 1; i >= 0; i--) { if (rain[i].parent) { rain[i].update(); } else { rain.splice(i, 1); } } // Update wind for (var i = wind.length - 1; i >= 0; i--) { if (wind[i].parent) { wind[i].update(); } else { wind.splice(i, 1); } } // Update storms for (var i = storms.length - 1; i >= 0; i--) { if (storms[i].parent) { storms[i].update(); } else { storms.splice(i, 1); } } // Update particles for (var i = particles.length - 1; i >= 0; i--) { if (particles[i].parent) { particles[i].update(); } else { particles.splice(i, 1); } } // Update water pools for (var i = waterPools.length - 1; i >= 0; i--) { if (waterPools[i].parent) { waterPools[i].update(); } else { waterPools.splice(i, 1); } } // Game over condition - all plants and animals died if (plants.length === 0 && animals.length === 0) { LK.showGameOver(); } // Win condition - flourishing ecosystem (many plants and animals) if (plants.length > 15 && animals.length > 5) { // Update score based on ecosystem health LK.setScore(plants.length + animals.length * 2); // Check if score is high enough to win if (LK.getScore() > 30) { LK.showYouWin(); } } };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,917 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+var facekit = LK.import("@upit/facekit.v1");
+
+/****
+* Classes
+****/
+var Animal = Container.expand(function () {
+ var self = Container.call(this);
+ self.animalGraphic = self.attachAsset('animal', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.direction = Math.random() > 0.5 ? 1 : -1;
+ self.speed = Math.random() * 2 + 1;
+ self.health = 100;
+ self.hunger = 0;
+ self.thirsty = 0;
+ self.state = 'wandering'; // wandering, eating, drinking
+ self.targetX = null;
+ self.targetY = null;
+ self.targetPlant = null;
+ self.wanderTimer = 0;
+ if (self.direction === -1) {
+ self.animalGraphic.scaleX = -1;
+ }
+ self.update = function () {
+ // Natural state changes
+ self.hunger += 0.1;
+ self.thirsty += 0.15;
+ // Cap values
+ if (self.hunger > 100) {
+ self.hunger = 100;
+ }
+ if (self.thirsty > 100) {
+ self.thirsty = 100;
+ }
+ // Health decreases if hungry or thirsty
+ if (self.hunger > 80 || self.thirsty > 80) {
+ self.health -= 0.2;
+ } else {
+ // Recover health when not hungry or thirsty
+ self.health += 0.05;
+ if (self.health > 100) {
+ self.health = 100;
+ }
+ }
+ // Decision making
+ if (self.state === 'wandering') {
+ // Find food or water if needed
+ if (self.thirsty > 70 && waterPools.length > 0) {
+ self.state = 'drinking';
+ // Find nearest water
+ var closestDist = Infinity;
+ var closestWater = null;
+ for (var i = 0; i < waterPools.length; i++) {
+ var water = waterPools[i];
+ var dist = Math.sqrt(Math.pow(self.x - water.x, 2) + Math.pow(self.y - water.y, 2));
+ if (dist < closestDist) {
+ closestDist = dist;
+ closestWater = water;
+ }
+ }
+ if (closestWater) {
+ self.targetX = closestWater.x + Math.random() * 100 - 50;
+ self.targetY = closestWater.y - 30;
+ }
+ } else if (self.hunger > 60 && plants.length > 0) {
+ self.state = 'eating';
+ // Find nearest plant that's mature enough
+ var closestDist = Infinity;
+ var closestPlant = null;
+ for (var j = 0; j < plants.length; j++) {
+ var plant = plants[j];
+ if (plant.growthStage > 2) {
+ // Only eat mature plants
+ var dist = Math.sqrt(Math.pow(self.x - plant.x, 2) + Math.pow(self.y - plant.y, 2));
+ if (dist < closestDist) {
+ closestDist = dist;
+ closestPlant = plant;
+ }
+ }
+ }
+ if (closestPlant) {
+ self.targetPlant = closestPlant;
+ self.targetX = closestPlant.x;
+ self.targetY = closestPlant.y;
+ } else {
+ // No suitable plants, continue wandering
+ self.wanderTimer++;
+ if (self.wanderTimer > 120) {
+ self.wanderTimer = 0;
+ self.targetX = Math.random() * 1800 + 100;
+ }
+ }
+ } else {
+ // Regular wandering
+ self.wanderTimer++;
+ if (self.wanderTimer > 180 || self.targetX === null) {
+ self.wanderTimer = 0;
+ self.targetX = Math.random() * 1800 + 100;
+ }
+ }
+ // Move towards target if there is one
+ if (self.targetX !== null) {
+ var dx = self.targetX - self.x;
+ if (Math.abs(dx) < 5) {
+ // Reached target
+ self.targetX = null;
+ } else {
+ // Move towards target
+ self.direction = dx > 0 ? 1 : -1;
+ self.animalGraphic.scaleX = self.direction;
+ self.x += self.direction * self.speed;
+ }
+ }
+ } else if (self.state === 'drinking') {
+ // Move towards water
+ if (self.targetX !== null) {
+ var dx = self.targetX - self.x;
+ var dy = self.targetY - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < 20) {
+ // Reached water, drink
+ self.thirsty -= 1;
+ // Make drinking animation
+ if (Math.random() < 0.1) {
+ var splash = new Particle();
+ splash.x = self.x;
+ splash.y = self.y + 20;
+ splash.vx = Math.random() * 2 - 1;
+ splash.vy = -Math.random() * 2 - 1;
+ splash.lifespan = 20;
+ game.addChild(splash);
+ particles.push(splash);
+ }
+ // Done drinking
+ if (self.thirsty <= 10) {
+ self.state = 'wandering';
+ self.targetX = null;
+ LK.getSound('animalSound').play();
+ }
+ } else {
+ // Move towards water
+ self.direction = dx > 0 ? 1 : -1;
+ self.animalGraphic.scaleX = self.direction;
+ self.x += dx / dist * self.speed;
+ self.y += dy / dist * self.speed;
+ }
+ } else {
+ self.state = 'wandering';
+ }
+ } else if (self.state === 'eating') {
+ // Move towards plant
+ if (self.targetPlant && self.targetPlant.parent) {
+ var dx = self.targetPlant.x - self.x;
+ var dy = self.targetPlant.y - self.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < 30) {
+ // Reached plant, eat
+ self.hunger -= 0.5;
+ self.targetPlant.growthStage -= 0.01;
+ // Done eating
+ if (self.hunger <= 10 || self.targetPlant.growthStage <= 1) {
+ self.state = 'wandering';
+ self.targetPlant = null;
+ self.targetX = null;
+ LK.getSound('animalSound').play();
+ }
+ } else {
+ // Move towards plant
+ self.direction = dx > 0 ? 1 : -1;
+ self.animalGraphic.scaleX = self.direction;
+ self.x += dx / dist * self.speed;
+ self.y += dy / dist * self.speed;
+ }
+ } else {
+ self.state = 'wandering';
+ self.targetPlant = null;
+ }
+ }
+ // Health visual indicator
+ if (self.health < 50) {
+ self.animalGraphic.alpha = 0.5 + self.health / 100 * 0.5;
+ } else {
+ self.animalGraphic.alpha = 1.0;
+ }
+ // Die if health reaches 0
+ if (self.health <= 0 && self.parent) {
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 1000,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ }
+ };
+ return self;
+});
+var Particle = Container.expand(function () {
+ var self = Container.call(this);
+ var particleGraphic = self.attachAsset('particleSmall', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.8
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.lifespan = 100;
+ self.age = 0;
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ self.age++;
+ if (self.age > self.lifespan) {
+ if (self.parent) {
+ self.destroy();
+ }
+ return;
+ }
+ particleGraphic.alpha = 1 - self.age / self.lifespan;
+ };
+ return self;
+});
+var Plant = Container.expand(function (type) {
+ var self = Container.call(this);
+ self.type = type || 'grass';
+ self.growthStage = 0;
+ self.maxGrowth = 5;
+ self.growthSpeed = 0;
+ self.health = 100;
+ self.waterLevel = 50;
+ self.sunLevel = 50;
+ self.buildGraphics = function () {
+ self.removeChildren();
+ if (self.type === 'grass') {
+ var scale = 0.4 + self.growthStage / self.maxGrowth * 0.6;
+ self.mainGraphic = self.attachAsset('grass', {
+ anchorX: 0.5,
+ anchorY: 1.0,
+ scaleX: scale,
+ scaleY: scale
+ });
+ } else if (self.type === 'tree') {
+ var scale = 0.3 + self.growthStage / self.maxGrowth * 0.7;
+ // Tree trunk
+ self.trunkGraphic = self.attachAsset('tree', {
+ anchorX: 0.5,
+ anchorY: 1.0,
+ scaleX: scale,
+ scaleY: scale
+ });
+ // Tree top
+ self.topGraphic = self.attachAsset('treeTop', {
+ anchorX: 0.5,
+ anchorY: 1.0,
+ y: -self.trunkGraphic.height * scale,
+ scaleX: scale * 1.2,
+ scaleY: scale * 1.2
+ });
+ } else if (self.type === 'flower') {
+ var scale = 0.3 + self.growthStage / self.maxGrowth * 0.7;
+ // Stem
+ self.stemGraphic = self.attachAsset('grass', {
+ anchorX: 0.5,
+ anchorY: 1.0,
+ scaleX: scale * 0.5,
+ scaleY: scale
+ });
+ // Flower
+ self.flowerGraphic = self.attachAsset('flower', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -self.stemGraphic.height * scale,
+ scaleX: scale,
+ scaleY: scale
+ });
+ }
+ };
+ // Set initial graphics
+ self.buildGraphics();
+ self.grow = function () {
+ if (self.growthStage < self.maxGrowth) {
+ self.growthStage += 0.1;
+ self.buildGraphics();
+ }
+ };
+ self.updateHealth = function () {
+ // Ideal conditions: water 50-70, sun 50-80
+ if (self.waterLevel < 20 || self.waterLevel > 90) {
+ self.health -= 0.5;
+ } else if (self.waterLevel > 40 && self.waterLevel < 80) {
+ self.health += 0.2;
+ }
+ if (self.sunLevel < 30 || self.sunLevel > 90) {
+ self.health -= 0.5;
+ } else if (self.sunLevel > 40 && self.sunLevel < 80) {
+ self.health += 0.2;
+ }
+ // Cap health
+ if (self.health > 100) {
+ self.health = 100;
+ }
+ if (self.health < 0) {
+ self.health = 0;
+ }
+ // Update visual health
+ var healthColor = 0x33D17A; // Healthy green
+ if (self.health < 70) {
+ healthColor = 0xF6D32D;
+ } // Yellow-ish
+ if (self.health < 40) {
+ healthColor = 0xE01B24;
+ } // Red-ish
+ // Change tint based on health
+ if (self.type === 'grass') {
+ self.mainGraphic.tint = healthColor;
+ } else if (self.type === 'tree') {
+ self.topGraphic.tint = healthColor;
+ } else if (self.type === 'flower') {
+ self.flowerGraphic.tint = healthColor;
+ }
+ // If plant is dead, make it wither
+ if (self.health <= 0 && self.parent) {
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 2000,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ }
+ };
+ self.update = function () {
+ // Natural water loss
+ self.waterLevel -= 0.1;
+ // Natural sun effects based on weather
+ if (currentWeather === 'sunny') {
+ self.sunLevel += 0.2;
+ self.waterLevel -= 0.05; // Extra evaporation when sunny
+ } else if (currentWeather === 'rainy') {
+ self.sunLevel -= 0.1;
+ self.waterLevel += 0.3;
+ } else if (currentWeather === 'windy') {
+ self.waterLevel -= 0.15; // Wind causes more evaporation
+ } else if (currentWeather === 'stormy') {
+ self.sunLevel -= 0.2;
+ self.waterLevel += 0.5;
+ }
+ // Cap water and sun levels
+ if (self.waterLevel > 100) {
+ self.waterLevel = 100;
+ }
+ if (self.waterLevel < 0) {
+ self.waterLevel = 0;
+ }
+ if (self.sunLevel > 100) {
+ self.sunLevel = 100;
+ }
+ if (self.sunLevel < 0) {
+ self.sunLevel = 0;
+ }
+ // Update health based on conditions
+ self.updateHealth();
+ // Calculate growth speed
+ self.growthSpeed = 0;
+ // Perfect conditions for growth
+ if (self.waterLevel > 40 && self.waterLevel < 80 && self.sunLevel > 40 && self.sunLevel < 80) {
+ self.growthSpeed = 0.01;
+ }
+ // Apply growth
+ if (self.growthSpeed > 0) {
+ self.grow();
+ }
+ };
+ return self;
+});
+var Raindrop = Container.expand(function () {
+ var self = Container.call(this);
+ var dropGraphic = self.attachAsset('rain', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = Math.random() * 5 + 10;
+ self.alpha = Math.random() * 0.5 + 0.5;
+ dropGraphic.alpha = self.alpha;
+ self.update = function () {
+ self.y += self.speed;
+ // If raindrop is below ground level
+ if (self.y > groundLevel) {
+ // Create splash effect
+ for (var i = 0; i < 3; i++) {
+ var splash = new Particle();
+ splash.x = self.x;
+ splash.y = groundLevel;
+ splash.vx = Math.random() * 4 - 2;
+ splash.vy = -Math.random() * 3 - 2;
+ splash.lifespan = 20;
+ game.addChild(splash);
+ particles.push(splash);
+ }
+ if (self.parent) {
+ self.destroy();
+ }
+ }
+ };
+ return self;
+});
+var StormCloud = Container.expand(function () {
+ var self = Container.call(this);
+ var cloudBase = self.attachAsset('storm', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 3,
+ scaleY: 2,
+ alpha: 0.7
+ });
+ // Add some smaller clouds around it for texture
+ for (var i = 0; i < 5; i++) {
+ var cloudPuff = self.attachAsset('storm', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: Math.random() * 160 - 80,
+ y: Math.random() * 60 - 30,
+ scaleX: Math.random() * 1.5 + 0.5,
+ scaleY: Math.random() * 1.5 + 0.5,
+ alpha: 0.8
+ });
+ }
+ self.vx = Math.random() * 2 - 1;
+ self.vy = Math.random() * 0.5 - 0.25;
+ self.thunderTimer = 0;
+ self.thunderFrequency = Math.floor(Math.random() * 120) + 180; // 3-5 seconds between thunder
+ self.lifespan = 600; // 10 seconds life
+ self.age = 0;
+ self.update = function () {
+ self.x += self.vx;
+ self.y += self.vy;
+ self.age++;
+ // Wrap around edges
+ if (self.x < -100) {
+ self.x = 2148;
+ }
+ if (self.x > 2148) {
+ self.x = -100;
+ }
+ self.thunderTimer++;
+ if (self.thunderTimer >= self.thunderFrequency) {
+ self.thunderTimer = 0;
+ // Flash the storm cloud
+ tween(self, {
+ alpha: 0.9
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ tween(self, {
+ alpha: 0.7
+ }, {
+ duration: 300
+ });
+ }
+ });
+ // Play thunder sound
+ LK.getSound('stormSound').play();
+ // Create rain from the storm
+ for (var i = 0; i < 8; i++) {
+ var drop = new Raindrop();
+ drop.x = self.x + Math.random() * 160 - 80;
+ drop.y = self.y + 40;
+ game.addChild(drop);
+ rain.push(drop);
+ }
+ }
+ if (self.age > self.lifespan) {
+ if (self.parent) {
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ }
+ }
+ };
+ return self;
+});
+var Sun = Container.expand(function () {
+ var self = Container.call(this);
+ var sunGraphic = self.attachAsset('sun', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 1.5,
+ scaleY: 1.5
+ });
+ self.intensity = 0;
+ self.targetIntensity = 0;
+ self.update = function () {
+ // Smooth transition to target intensity
+ if (self.intensity < self.targetIntensity) {
+ self.intensity += 0.01;
+ } else if (self.intensity > self.targetIntensity) {
+ self.intensity -= 0.01;
+ }
+ // Visual representation of intensity
+ sunGraphic.alpha = self.intensity;
+ // Sun rays effect
+ if (self.intensity > 0.5 && Math.random() < 0.1) {
+ var ray = new Particle();
+ ray.x = self.x;
+ ray.y = self.y;
+ var angle = Math.random() * Math.PI * 2;
+ var distance = sunGraphic.width * 0.7;
+ ray.vx = Math.cos(angle) * 2;
+ ray.vy = Math.sin(angle) * 2;
+ ray.x += Math.cos(angle) * distance;
+ ray.y += Math.sin(angle) * distance;
+ ray.lifespan = 30;
+ game.addChild(ray);
+ particles.push(ray);
+ }
+ };
+ return self;
+});
+var WaterPool = Container.expand(function () {
+ var self = Container.call(this);
+ self.width = 400;
+ self.height = 200;
+ var waterGraphic = self.attachAsset('water', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.7
+ });
+ self.level = 100; // Water level percentage
+ self.update = function () {
+ // Water level changes based on weather
+ if (currentWeather === 'sunny') {
+ self.level -= 0.1;
+ } else if (currentWeather === 'rainy') {
+ self.level += 0.2;
+ } else if (currentWeather === 'windy') {
+ self.level -= 0.05;
+ } else if (currentWeather === 'stormy') {
+ self.level += 0.3;
+ }
+ // Cap water level
+ if (self.level > 100) {
+ self.level = 100;
+ }
+ if (self.level < 0) {
+ self.level = 0;
+ }
+ // Visual representation of water level
+ waterGraphic.scaleY = self.level / 100;
+ // Create ripples occasionally
+ if (Math.random() < 0.05 && self.level > 10) {
+ var ripple = new Particle();
+ ripple.x = self.x + Math.random() * self.width - self.width / 2;
+ ripple.y = self.y + Math.random() * self.height / 2 - self.height / 4;
+ ripple.vx = Math.random() * 0.5 - 0.25;
+ ripple.vy = Math.random() * 0.5 - 0.25;
+ ripple.lifespan = 30;
+ game.addChild(ripple);
+ particles.push(ripple);
+ }
+ };
+ return self;
+});
+var WindGust = Container.expand(function () {
+ var self = Container.call(this);
+ var gustGraphic = self.attachAsset('wind', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.3
+ });
+ self.speed = Math.random() * 8 + 5;
+ self.lifespan = 120;
+ self.age = 0;
+ self.update = function () {
+ self.x += self.speed;
+ self.age++;
+ if (self.age > self.lifespan || self.x > 2048 + gustGraphic.width) {
+ if (self.parent) {
+ self.destroy();
+ }
+ return;
+ }
+ gustGraphic.alpha = 0.3 * (1 - self.age / self.lifespan);
+ // Create particles along the wind path
+ if (self.age % 5 === 0) {
+ var particle = new Particle();
+ particle.x = self.x;
+ particle.y = self.y + (Math.random() * gustGraphic.height - gustGraphic.height / 2);
+ particle.vx = self.speed * 0.8;
+ particle.vy = Math.random() * 2 - 1;
+ particle.lifespan = 40;
+ game.addChild(particle);
+ particles.push(particle);
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87CEEB // Sky blue background
+});
+
+/****
+* Game Code
+****/
+// Global variables
+var groundLevel = 2200;
+var currentWeather = 'neutral'; // neutral, sunny, rainy, windy, stormy
+var weatherIntensity = 0;
+var weatherChangeTimer = 0;
+var faceDetected = false;
+var lastExpression = 'neutral';
+// Arrays to keep track of game objects
+var plants = [];
+var animals = [];
+var rain = [];
+var wind = [];
+var storms = [];
+var particles = [];
+var waterPools = [];
+// Create ground
+var ground = game.addChild(LK.getAsset('ground', {
+ anchorX: 0.5,
+ anchorY: 0.0,
+ x: 2048 / 2,
+ y: groundLevel
+}));
+// Create sun
+var sun = new Sun();
+sun.x = 200;
+sun.y = 200;
+game.addChild(sun);
+// Create water pool
+var pool = new WaterPool();
+pool.x = 1700;
+pool.y = groundLevel - 60;
+game.addChild(pool);
+waterPools.push(pool);
+// UI Elements
+var ecosystemTxt = new Text2('Emotion Ecosystem', {
+ size: 70,
+ fill: 0xFFFFFF
+});
+ecosystemTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(ecosystemTxt);
+var detectionTxt = new Text2('Looking for your face...', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+detectionTxt.anchor.set(0.5, 0);
+detectionTxt.y = 100;
+LK.gui.top.addChild(detectionTxt);
+var weatherTxt = new Text2('Weather: Neutral', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+weatherTxt.anchor.set(0.5, 0);
+weatherTxt.y = 150;
+LK.gui.top.addChild(weatherTxt);
+var instructionsTxt = new Text2('Smile = Sun\n' + 'Frown = Rain\n' + 'Surprised = Wind\n' + 'Angry = Storm', {
+ size: 30,
+ fill: 0xFFFFFF
+});
+instructionsTxt.anchor.set(0.5, 1);
+LK.gui.bottom.addChild(instructionsTxt);
+// Helper functions
+function generatePlant(type, x) {
+ var plant = new Plant(type);
+ plant.x = x || Math.random() * 1800 + 100;
+ plant.y = groundLevel;
+ game.addChild(plant);
+ plants.push(plant);
+ return plant;
+}
+function generateAnimal(x) {
+ var animal = new Animal();
+ animal.x = x || Math.random() * 1800 + 100;
+ animal.y = groundLevel - 20;
+ game.addChild(animal);
+ animals.push(animal);
+ return animal;
+}
+function createRain() {
+ var drop = new Raindrop();
+ drop.x = Math.random() * 2048;
+ drop.y = -50;
+ game.addChild(drop);
+ rain.push(drop);
+ // Play rain sound occasionally
+ if (Math.random() < 0.05) {
+ LK.getSound('rainSound').play();
+ }
+}
+function createWind() {
+ var gust = new WindGust();
+ gust.x = -100;
+ gust.y = Math.random() * 1500;
+ game.addChild(gust);
+ wind.push(gust);
+ // Play wind sound occasionally
+ if (Math.random() < 0.1) {
+ LK.getSound('windSound').play();
+ }
+}
+function createStorm() {
+ var storm = new StormCloud();
+ storm.x = Math.random() * 2048;
+ storm.y = Math.random() * 300 + 100;
+ game.addChild(storm);
+ storms.push(storm);
+}
+function detectFacialExpression() {
+ // Check if face is detected
+ if (facekit.mouthCenter.x > 0 || facekit.mouthCenter.y > 0) {
+ faceDetected = true;
+ // Check facial expressions
+ if (facekit.mouthOpen) {
+ // Calculate how open the mouth is based on distance between upper and lower lip
+ var mouthOpenness = Math.abs(facekit.upperLip.y - facekit.lowerLip.y) / 100;
+ if (mouthOpenness > 0.5) {
+ // Very open mouth - surprised expression
+ return 'surprised';
+ }
+ }
+ // Check smile (happy expression)
+ // A smile is detected by curvature of the mouth
+ // This is a simple approximation - in a real implementation we'd use more robust detection
+ var mouthWidth = Math.abs(facekit.upperLip.x - facekit.lowerLip.x);
+ var mouthHeight = Math.abs(facekit.upperLip.y - facekit.lowerLip.y);
+ if (mouthWidth > 30 && mouthHeight < 20) {
+ return 'happy';
+ }
+ // Check frown (sad expression)
+ // Simple approximation - in real implementation we'd use more robust detection
+ if (mouthWidth < 20 && facekit.upperLip.y > facekit.lowerLip.y) {
+ return 'sad';
+ }
+ // Check angry expression
+ // Simple approximation using eyebrows and mouth
+ // For this demo, we'll use volume as a proxy for anger
+ if (facekit.volume > 0.7) {
+ return 'angry';
+ }
+ return 'neutral';
+ } else {
+ faceDetected = false;
+ return 'not detected';
+ }
+}
+function updateWeather() {
+ // Blend from current weather to target weather based on expression
+ if (lastExpression === 'happy') {
+ currentWeather = 'sunny';
+ sun.targetIntensity = 1.0;
+ } else if (lastExpression === 'sad') {
+ currentWeather = 'rainy';
+ sun.targetIntensity = 0.3;
+ } else if (lastExpression === 'surprised') {
+ currentWeather = 'windy';
+ sun.targetIntensity = 0.6;
+ } else if (lastExpression === 'angry') {
+ currentWeather = 'stormy';
+ sun.targetIntensity = 0.2;
+ } else {
+ currentWeather = 'neutral';
+ sun.targetIntensity = 0.5;
+ }
+ // Update weather text
+ weatherTxt.setText('Weather: ' + currentWeather.charAt(0).toUpperCase() + currentWeather.slice(1));
+ // Spawn weather effects based on current weather
+ if (currentWeather === 'rainy' && Math.random() < 0.2) {
+ createRain();
+ } else if (currentWeather === 'windy' && Math.random() < 0.1) {
+ createWind();
+ } else if (currentWeather === 'stormy') {
+ if (Math.random() < 0.02 && storms.length < 3) {
+ createStorm();
+ }
+ if (Math.random() < 0.1) {
+ createRain();
+ }
+ }
+}
+// Setup initial ecosystem
+function setupInitialEcosystem() {
+ // Create initial plants
+ for (var i = 0; i < 5; i++) {
+ generatePlant('grass', 200 + i * 300);
+ }
+ for (var i = 0; i < 3; i++) {
+ generatePlant('tree', 400 + i * 400);
+ }
+ for (var i = 0; i < 4; i++) {
+ generatePlant('flower', 350 + i * 350);
+ }
+ // Create initial animals
+ for (var i = 0; i < 3; i++) {
+ generateAnimal(300 + i * 500);
+ }
+ // Start background music
+ LK.playMusic('bgMusic');
+}
+// Call setup
+setupInitialEcosystem();
+// Main game loop
+game.update = function () {
+ // Update face detection status
+ var expression = detectFacialExpression();
+ if (expression !== 'not detected') {
+ detectionTxt.setText('Expression: ' + expression.charAt(0).toUpperCase() + expression.slice(1));
+ lastExpression = expression;
+ } else {
+ detectionTxt.setText('Looking for your face...');
+ }
+ // Update weather based on expression
+ updateWeather();
+ // Update weather timer
+ weatherChangeTimer++;
+ if (weatherChangeTimer > 300) {
+ // Every 5 seconds
+ weatherChangeTimer = 0;
+ // Occasionally spawn new plants or animals
+ if (plants.length < 20 && Math.random() < 0.3) {
+ var types = ['grass', 'tree', 'flower'];
+ generatePlant(types[Math.floor(Math.random() * types.length)]);
+ }
+ if (animals.length < 8 && Math.random() < 0.2) {
+ generateAnimal();
+ }
+ }
+ // Update all game objects
+ sun.update();
+ // Update plants
+ for (var i = plants.length - 1; i >= 0; i--) {
+ if (plants[i].parent) {
+ plants[i].update();
+ } else {
+ plants.splice(i, 1);
+ }
+ }
+ // Update animals
+ for (var i = animals.length - 1; i >= 0; i--) {
+ if (animals[i].parent) {
+ animals[i].update();
+ } else {
+ animals.splice(i, 1);
+ }
+ }
+ // Update rain
+ for (var i = rain.length - 1; i >= 0; i--) {
+ if (rain[i].parent) {
+ rain[i].update();
+ } else {
+ rain.splice(i, 1);
+ }
+ }
+ // Update wind
+ for (var i = wind.length - 1; i >= 0; i--) {
+ if (wind[i].parent) {
+ wind[i].update();
+ } else {
+ wind.splice(i, 1);
+ }
+ }
+ // Update storms
+ for (var i = storms.length - 1; i >= 0; i--) {
+ if (storms[i].parent) {
+ storms[i].update();
+ } else {
+ storms.splice(i, 1);
+ }
+ }
+ // Update particles
+ for (var i = particles.length - 1; i >= 0; i--) {
+ if (particles[i].parent) {
+ particles[i].update();
+ } else {
+ particles.splice(i, 1);
+ }
+ }
+ // Update water pools
+ for (var i = waterPools.length - 1; i >= 0; i--) {
+ if (waterPools[i].parent) {
+ waterPools[i].update();
+ } else {
+ waterPools.splice(i, 1);
+ }
+ }
+ // Game over condition - all plants and animals died
+ if (plants.length === 0 && animals.length === 0) {
+ LK.showGameOver();
+ }
+ // Win condition - flourishing ecosystem (many plants and animals)
+ if (plants.length > 15 && animals.length > 5) {
+ // Update score based on ecosystem health
+ LK.setScore(plants.length + animals.length * 2);
+ // Check if score is high enough to win
+ if (LK.getScore() > 30) {
+ LK.showYouWin();
+ }
+ }
+};
\ No newline at end of file