User prompt
Make enemies that try to come near you
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'tween.to(self, {' Line Number: 237 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
More code
Code edit (1 edits merged)
Please save this source code
User prompt
Air Weaver
Initial prompt
A person who controls air and with their hands
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var AirCurrent = Container.expand(function () { var self = Container.call(this); var circle = self.attachAsset('airCircle', { anchorX: 0.5, anchorY: 0.5, alpha: 0.4 }); self.force = 5; self.radius = 50; self.active = true; self.update = function () { if (!self.active) return; // Pulse effect if (!self.pulseDirection) self.pulseDirection = 1; circle.alpha += 0.01 * self.pulseDirection; if (circle.alpha >= 0.6) self.pulseDirection = -1; if (circle.alpha <= 0.2) self.pulseDirection = 1; }; self.applyForce = function (obj) { if (!self.active) return false; var dx = obj.x - self.x; var dy = obj.y - self.y; var distSq = dx * dx + dy * dy; var radiusSq = self.radius * self.radius; if (distSq <= radiusSq) { var dist = Math.sqrt(distSq); if (dist === 0) dist = 0.01; var forceFactor = (1 - dist / self.radius) * self.force; // Direction from air current to object var dirX = dx / dist; var dirY = dy / dist; obj.vx += dirX * forceFactor; obj.vy += dirY * forceFactor; return true; } return false; }; return self; }); var AirParticle = Container.expand(function () { var self = Container.call(this); var particle = self.attachAsset('airParticle', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); self.speed = { x: 0, y: 0 }; self.lifespan = 2000; // milliseconds self.born = Date.now(); self.fadeSpeed = 0.01; self.update = function () { self.x += self.speed.x; self.y += self.speed.y; // Apply fade as particle ages var age = Date.now() - self.born; if (age > self.lifespan * 0.7) { particle.alpha -= self.fadeSpeed; if (particle.alpha <= 0) { self.destroy = true; } } // Apply slight random movement self.speed.x += (Math.random() - 0.5) * 0.1; self.speed.y += (Math.random() - 0.5) * 0.1; // Slow down over time self.speed.x *= 0.99; self.speed.y *= 0.99; }; return self; }); var Cloud = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('cloud', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 0; self.vy = 0; self.friction = 0.98; self.interactable = true; self.update = function () { if (self.interactable) { self.x += self.vx; self.y += self.vy; // Apply friction self.vx *= self.friction; self.vy *= self.friction; // Keep within bounds if (self.x < 0) { self.x = 0; self.vx *= -0.5; } else if (self.x > 2048) { self.x = 2048; self.vx *= -0.5; } if (self.y < 0) { self.y = 0; self.vy *= -0.5; } else if (self.y > 2732) { self.y = 2732; self.vy *= -0.5; } } }; return self; }); var Flower = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('flower', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); self.bloomed = false; self.bloom = function () { if (self.bloomed) return; self.bloomed = true; LK.getSound('flowerBloom').play(); // Expand and brighten tween(graphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 1000, easing: tween.elasticOut }); // Increase score LK.setScore(LK.getScore() + 10); }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 0; self.vy = 0; self.friction = 0.95; self.health = 3; self.interactable = true; self.update = function () { if (self.interactable) { self.x += self.vx; self.y += self.vy; // Apply friction self.vx *= self.friction; self.vy *= self.friction; // Keep within bounds if (self.x < 0) { self.x = 0; self.vx *= -0.2; } else if (self.x > 2048) { self.x = 2048; self.vx *= -0.2; } if (self.y < 0) { self.y = 0; self.vy *= -0.2; } else if (self.y > 2732) { self.y = 2732; self.vy *= -0.2; } } }; self.damage = function () { if (!self.interactable) return; self.health--; // Flash effect LK.effects.flashObject(self, 0xff0000, 300); if (self.health <= 0) { self.interactable = false; LK.getSound('obstacleBreak').play(); // Shrink and fade out tween(graphics, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { self.destroy = true; } }); } }; return self; }); var Whirlwind = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('whirlwind', { anchorX: 0.5, anchorY: 0.5, alpha: 0.6 }); self.force = 8; self.radius = 100; self.active = true; self.rotationSpeed = 0.03; self.update = function () { if (!self.active) return; // Rotate continuously graphics.rotation += self.rotationSpeed; // Pulse effect if (!self.pulseDirection) self.pulseDirection = 1; graphics.alpha += 0.01 * self.pulseDirection; if (graphics.alpha >= 0.7) self.pulseDirection = -1; if (graphics.alpha <= 0.4) self.pulseDirection = 1; }; self.applyForce = function (obj) { if (!self.active) return false; var dx = obj.x - self.x; var dy = obj.y - self.y; var distSq = dx * dx + dy * dy; var radiusSq = self.radius * self.radius; if (distSq <= radiusSq) { var dist = Math.sqrt(distSq); if (dist === 0) dist = 0.01; var angle = Math.atan2(dy, dx); var forceFactor = (1 - dist / self.radius) * self.force; // Orbital motion around the whirlwind center obj.vx += -Math.sin(angle) * forceFactor; obj.vy += Math.cos(angle) * forceFactor; return true; } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Define game parameters var airCurrents = []; var whirlwinds = []; var clouds = []; var obstacles = []; var flowers = []; var particles = []; var activeTouches = {}; var gestureTrails = {}; var level = 1; var maxLevels = 3; var windSound = null; // Create UI elements var scoreTxt = new Text2(LK.getScore().toString(), { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var levelTxt = new Text2("Level " + level, { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); levelTxt.x = 150; levelTxt.y = 20; LK.gui.topRight.addChild(levelTxt); var helpTxt = new Text2("Draw circles for whirlwinds\nSwipe for air currents", { size: 40, fill: 0xFFFFFF }); helpTxt.anchor.set(0.5, 0); helpTxt.y = 150; LK.gui.top.addChild(helpTxt); // Hide help text after 5 seconds LK.setTimeout(function () { tween(helpTxt, { alpha: 0 }, { duration: 1000, easing: tween.easeOut }); }, 5000); // Setup game function setupLevel(levelNum) { // Clear previous level objects clearLevel(); // Update level text levelTxt.setText("Level " + levelNum); // Common setup for all levels var cloudCount, obstacleCount, flowerCount; switch (levelNum) { case 1: cloudCount = 3; obstacleCount = 2; flowerCount = 3; break; case 2: cloudCount = 5; obstacleCount = 4; flowerCount = 5; break; case 3: cloudCount = 7; obstacleCount = 6; flowerCount = 8; break; default: cloudCount = 3; obstacleCount = 2; flowerCount = 3; } // Create clouds for (var i = 0; i < cloudCount; i++) { var cloud = new Cloud(); cloud.x = Math.random() * 1848 + 100; cloud.y = Math.random() * 1000 + 300; clouds.push(cloud); game.addChild(cloud); } // Create obstacles for (var i = 0; i < obstacleCount; i++) { var obstacle = new Obstacle(); obstacle.x = Math.random() * 1848 + 100; obstacle.y = Math.random() * 1500 + 600; obstacles.push(obstacle); game.addChild(obstacle); } // Create flowers that need to bloom for (var i = 0; i < flowerCount; i++) { var flower = new Flower(); flower.x = Math.random() * 1848 + 100; flower.y = Math.random() * 2000 + 500; flowers.push(flower); game.addChild(flower); } // Play background music LK.playMusic('ambientMusic'); } function clearLevel() { // Remove all game elements for (var i = 0; i < airCurrents.length; i++) { if (airCurrents[i].parent) { airCurrents[i].parent.removeChild(airCurrents[i]); } } airCurrents = []; for (var i = 0; i < whirlwinds.length; i++) { if (whirlwinds[i].parent) { whirlwinds[i].parent.removeChild(whirlwinds[i]); } } whirlwinds = []; for (var i = 0; i < clouds.length; i++) { if (clouds[i].parent) { clouds[i].parent.removeChild(clouds[i]); } } clouds = []; for (var i = 0; i < obstacles.length; i++) { if (obstacles[i].parent) { obstacles[i].parent.removeChild(obstacles[i]); } } obstacles = []; for (var i = 0; i < flowers.length; i++) { if (flowers[i].parent) { flowers[i].parent.removeChild(flowers[i]); } } flowers = []; for (var i = 0; i < particles.length; i++) { if (particles[i].parent) { particles[i].parent.removeChild(particles[i]); } } particles = []; } // Check if level is complete function checkLevelComplete() { var allBloomed = true; for (var i = 0; i < flowers.length; i++) { if (!flowers[i].bloomed) { allBloomed = false; break; } } if (allBloomed && flowers.length > 0) { // Level complete! level++; if (level > maxLevels) { // Game complete! LK.showYouWin(); } else { // Flash screen and move to next level LK.effects.flashScreen(0xffffff, 500); // Show level complete message var completeTxt = new Text2("Level Complete!", { size: 120, fill: 0xFFFFFF }); completeTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(completeTxt); // Remove message and start next level after delay LK.setTimeout(function () { LK.gui.center.removeChild(completeTxt); setupLevel(level); }, 2000); } } } // Input handling function detectGesture(id) { var trail = gestureTrails[id]; if (!trail || trail.length < 10) return null; // Check if it's a circle gesture var isCircle = detectCircleGesture(trail); if (isCircle) { return "circle"; } // Check if it's a swipe gesture var isSwipe = detectSwipeGesture(trail); if (isSwipe) { return "swipe"; } return null; } function detectCircleGesture(trail) { if (trail.length < 10) return false; // Calculate center of points var centerX = 0, centerY = 0; for (var i = 0; i < trail.length; i++) { centerX += trail[i].x; centerY += trail[i].y; } centerX /= trail.length; centerY /= trail.length; // Calculate average distance from center var avgDist = 0; for (var i = 0; i < trail.length; i++) { var dx = trail[i].x - centerX; var dy = trail[i].y - centerY; avgDist += Math.sqrt(dx * dx + dy * dy); } avgDist /= trail.length; // Check if points form a rough circle var isCircular = true; var threshold = 0.3; // Allow 30% deviation for (var i = 0; i < trail.length; i++) { var dx = trail[i].x - centerX; var dy = trail[i].y - centerY; var dist = Math.sqrt(dx * dx + dy * dy); if (Math.abs(dist - avgDist) / avgDist > threshold) { isCircular = false; break; } } // Check if first and last points are close enough var firstPoint = trail[0]; var lastPoint = trail[trail.length - 1]; var dx = firstPoint.x - lastPoint.x; var dy = firstPoint.y - lastPoint.y; var startEndDist = Math.sqrt(dx * dx + dy * dy); return isCircular && startEndDist < avgDist * 0.5; } function detectSwipeGesture(trail) { if (trail.length < 5) return false; var firstPoint = trail[0]; var lastPoint = trail[trail.length - 1]; var dx = lastPoint.x - firstPoint.x; var dy = lastPoint.y - firstPoint.y; var distance = Math.sqrt(dx * dx + dy * dy); // Check if the distance is significant enough to be a swipe return distance > 200; } function createWhirlwind(x, y) { var whirlwind = new Whirlwind(); whirlwind.x = x; whirlwind.y = y; whirlwinds.push(whirlwind); game.addChild(whirlwind); // Play sound LK.getSound('whirlwindSound').play(); // Automatically remove after some time LK.setTimeout(function () { tween(whirlwind, { alpha: 0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { if (whirlwind.parent) { whirlwind.parent.removeChild(whirlwind); } var index = whirlwinds.indexOf(whirlwind); if (index > -1) { whirlwinds.splice(index, 1); } } }); }, 5000); } function createAirCurrent(fromX, fromY, toX, toY) { var dx = toX - fromX; var dy = toY - fromY; var length = Math.sqrt(dx * dx + dy * dy); var steps = Math.max(1, Math.floor(length / 100)); for (var i = 0; i < steps; i++) { var t = i / steps; var x = fromX + dx * t; var y = fromY + dy * t; var airCurrent = new AirCurrent(); airCurrent.x = x; airCurrent.y = y; airCurrents.push(airCurrent); game.addChild(airCurrent); // Create visual particles createAirParticles(x, y, dx / length, dy / length); } // Play sound if (!windSound) { windSound = LK.getSound('windSound'); windSound.play(); } // Automatically remove after some time LK.setTimeout(function () { for (var i = 0; i < airCurrents.length; i++) { var airCurrent = airCurrents[i]; tween(airCurrent, { alpha: 0 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { if (airCurrent.parent) { airCurrent.parent.removeChild(airCurrent); } } }); } airCurrents = []; if (windSound) { windSound = null; } }, 2000); } function createAirParticles(x, y, dirX, dirY) { for (var i = 0; i < 3; i++) { var particle = new AirParticle(); particle.x = x + (Math.random() - 0.5) * 40; particle.y = y + (Math.random() - 0.5) * 40; particle.speed.x = dirX * (2 + Math.random() * 3); particle.speed.y = dirY * (2 + Math.random() * 3); particles.push(particle); game.addChild(particle); } } // Touch event handlers game.down = function (x, y, obj) { var touchId = Date.now().toString(); activeTouches[touchId] = { x: x, y: y }; gestureTrails[touchId] = [{ x: x, y: y }]; }; game.move = function (x, y, obj) { // Update active touches for (var id in activeTouches) { activeTouches[id] = { x: x, y: y }; // Add point to gesture trail if (gestureTrails[id]) { gestureTrails[id].push({ x: x, y: y }); } } }; game.up = function (x, y, obj) { for (var id in activeTouches) { // Detect gesture var gesture = detectGesture(id); if (gesture === "circle") { // Create a whirlwind at the center of the gesture var trail = gestureTrails[id]; var centerX = 0, centerY = 0; for (var i = 0; i < trail.length; i++) { centerX += trail[i].x; centerY += trail[i].y; } centerX /= trail.length; centerY /= trail.length; createWhirlwind(centerX, centerY); } else if (gesture === "swipe") { // Create air current along the swipe var trail = gestureTrails[id]; var firstPoint = trail[0]; var lastPoint = trail[trail.length - 1]; createAirCurrent(firstPoint.x, firstPoint.y, lastPoint.x, lastPoint.y); } // Clear this touch delete activeTouches[id]; delete gestureTrails[id]; } }; // Game update function game.update = function () { // Update score display scoreTxt.setText(LK.getScore().toString()); // Update all game objects // Update air currents for (var i = 0; i < airCurrents.length; i++) { airCurrents[i].update(); } // Update whirlwinds for (var i = 0; i < whirlwinds.length; i++) { whirlwinds[i].update(); } // Update clouds for (var i = 0; i < clouds.length; i++) { // Apply forces from air elements for (var j = 0; j < airCurrents.length; j++) { airCurrents[j].applyForce(clouds[i]); } for (var j = 0; j < whirlwinds.length; j++) { whirlwinds[j].applyForce(clouds[i]); } clouds[i].update(); } // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; // Apply forces from air elements var forcesApplied = 0; for (var j = 0; j < airCurrents.length; j++) { if (airCurrents[j].applyForce(obstacle)) { forcesApplied++; } } for (var j = 0; j < whirlwinds.length; j++) { if (whirlwinds[j].applyForce(obstacle)) { forcesApplied++; } } // If multiple forces are applied, damage the obstacle if (forcesApplied >= 2 && LK.ticks % 30 === 0) { obstacle.damage(); } obstacle.update(); // Remove destroyed obstacles if (obstacle.destroy) { game.removeChild(obstacle); obstacles.splice(i, 1); } } // Update flowers for (var i = flowers.length - 1; i >= 0; i--) { var flower = flowers[i]; // Check if a cloud is over the flower for (var j = 0; j < clouds.length; j++) { if (clouds[j].intersects(flower)) { flower.bloom(); break; } } } // Update particles for (var i = particles.length - 1; i >= 0; i--) { particles[i].update(); if (particles[i].destroy) { game.removeChild(particles[i]); particles.splice(i, 1); } } // Check if level is complete checkLevelComplete(); }; // Start the game setupLevel(level);
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,703 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var AirCurrent = Container.expand(function () {
+ var self = Container.call(this);
+ var circle = self.attachAsset('airCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.4
+ });
+ self.force = 5;
+ self.radius = 50;
+ self.active = true;
+ self.update = function () {
+ if (!self.active) return;
+ // Pulse effect
+ if (!self.pulseDirection) self.pulseDirection = 1;
+ circle.alpha += 0.01 * self.pulseDirection;
+ if (circle.alpha >= 0.6) self.pulseDirection = -1;
+ if (circle.alpha <= 0.2) self.pulseDirection = 1;
+ };
+ self.applyForce = function (obj) {
+ if (!self.active) return false;
+ var dx = obj.x - self.x;
+ var dy = obj.y - self.y;
+ var distSq = dx * dx + dy * dy;
+ var radiusSq = self.radius * self.radius;
+ if (distSq <= radiusSq) {
+ var dist = Math.sqrt(distSq);
+ if (dist === 0) dist = 0.01;
+ var forceFactor = (1 - dist / self.radius) * self.force;
+ // Direction from air current to object
+ var dirX = dx / dist;
+ var dirY = dy / dist;
+ obj.vx += dirX * forceFactor;
+ obj.vy += dirY * forceFactor;
+ return true;
+ }
+ return false;
+ };
+ return self;
+});
+var AirParticle = Container.expand(function () {
+ var self = Container.call(this);
+ var particle = self.attachAsset('airParticle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.7
+ });
+ self.speed = {
+ x: 0,
+ y: 0
+ };
+ self.lifespan = 2000; // milliseconds
+ self.born = Date.now();
+ self.fadeSpeed = 0.01;
+ self.update = function () {
+ self.x += self.speed.x;
+ self.y += self.speed.y;
+ // Apply fade as particle ages
+ var age = Date.now() - self.born;
+ if (age > self.lifespan * 0.7) {
+ particle.alpha -= self.fadeSpeed;
+ if (particle.alpha <= 0) {
+ self.destroy = true;
+ }
+ }
+ // Apply slight random movement
+ self.speed.x += (Math.random() - 0.5) * 0.1;
+ self.speed.y += (Math.random() - 0.5) * 0.1;
+ // Slow down over time
+ self.speed.x *= 0.99;
+ self.speed.y *= 0.99;
+ };
+ return self;
+});
+var Cloud = Container.expand(function () {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('cloud', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.friction = 0.98;
+ self.interactable = true;
+ self.update = function () {
+ if (self.interactable) {
+ self.x += self.vx;
+ self.y += self.vy;
+ // Apply friction
+ self.vx *= self.friction;
+ self.vy *= self.friction;
+ // Keep within bounds
+ if (self.x < 0) {
+ self.x = 0;
+ self.vx *= -0.5;
+ } else if (self.x > 2048) {
+ self.x = 2048;
+ self.vx *= -0.5;
+ }
+ if (self.y < 0) {
+ self.y = 0;
+ self.vy *= -0.5;
+ } else if (self.y > 2732) {
+ self.y = 2732;
+ self.vy *= -0.5;
+ }
+ }
+ };
+ return self;
+});
+var Flower = Container.expand(function () {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('flower', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.5,
+ scaleY: 0.5
+ });
+ self.bloomed = false;
+ self.bloom = function () {
+ if (self.bloomed) return;
+ self.bloomed = true;
+ LK.getSound('flowerBloom').play();
+ // Expand and brighten
+ tween(graphics, {
+ scaleX: 1.0,
+ scaleY: 1.0
+ }, {
+ duration: 1000,
+ easing: tween.elasticOut
+ });
+ // Increase score
+ LK.setScore(LK.getScore() + 10);
+ };
+ return self;
+});
+var Obstacle = Container.expand(function () {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('obstacle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.friction = 0.95;
+ self.health = 3;
+ self.interactable = true;
+ self.update = function () {
+ if (self.interactable) {
+ self.x += self.vx;
+ self.y += self.vy;
+ // Apply friction
+ self.vx *= self.friction;
+ self.vy *= self.friction;
+ // Keep within bounds
+ if (self.x < 0) {
+ self.x = 0;
+ self.vx *= -0.2;
+ } else if (self.x > 2048) {
+ self.x = 2048;
+ self.vx *= -0.2;
+ }
+ if (self.y < 0) {
+ self.y = 0;
+ self.vy *= -0.2;
+ } else if (self.y > 2732) {
+ self.y = 2732;
+ self.vy *= -0.2;
+ }
+ }
+ };
+ self.damage = function () {
+ if (!self.interactable) return;
+ self.health--;
+ // Flash effect
+ LK.effects.flashObject(self, 0xff0000, 300);
+ if (self.health <= 0) {
+ self.interactable = false;
+ LK.getSound('obstacleBreak').play();
+ // Shrink and fade out
+ tween(graphics, {
+ alpha: 0,
+ scaleX: 0.1,
+ scaleY: 0.1
+ }, {
+ duration: 800,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ self.destroy = true;
+ }
+ });
+ }
+ };
+ return self;
+});
+var Whirlwind = Container.expand(function () {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('whirlwind', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.6
+ });
+ self.force = 8;
+ self.radius = 100;
+ self.active = true;
+ self.rotationSpeed = 0.03;
+ self.update = function () {
+ if (!self.active) return;
+ // Rotate continuously
+ graphics.rotation += self.rotationSpeed;
+ // Pulse effect
+ if (!self.pulseDirection) self.pulseDirection = 1;
+ graphics.alpha += 0.01 * self.pulseDirection;
+ if (graphics.alpha >= 0.7) self.pulseDirection = -1;
+ if (graphics.alpha <= 0.4) self.pulseDirection = 1;
+ };
+ self.applyForce = function (obj) {
+ if (!self.active) return false;
+ var dx = obj.x - self.x;
+ var dy = obj.y - self.y;
+ var distSq = dx * dx + dy * dy;
+ var radiusSq = self.radius * self.radius;
+ if (distSq <= radiusSq) {
+ var dist = Math.sqrt(distSq);
+ if (dist === 0) dist = 0.01;
+ var angle = Math.atan2(dy, dx);
+ var forceFactor = (1 - dist / self.radius) * self.force;
+ // Orbital motion around the whirlwind center
+ obj.vx += -Math.sin(angle) * forceFactor;
+ obj.vy += Math.cos(angle) * forceFactor;
+ return true;
+ }
+ return false;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87CEEB
+});
+
+/****
+* Game Code
+****/
+// Define game parameters
+var airCurrents = [];
+var whirlwinds = [];
+var clouds = [];
+var obstacles = [];
+var flowers = [];
+var particles = [];
+var activeTouches = {};
+var gestureTrails = {};
+var level = 1;
+var maxLevels = 3;
+var windSound = null;
+// Create UI elements
+var scoreTxt = new Text2(LK.getScore().toString(), {
+ size: 80,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+var levelTxt = new Text2("Level " + level, {
+ size: 60,
+ fill: 0xFFFFFF
+});
+levelTxt.anchor.set(0, 0);
+levelTxt.x = 150;
+levelTxt.y = 20;
+LK.gui.topRight.addChild(levelTxt);
+var helpTxt = new Text2("Draw circles for whirlwinds\nSwipe for air currents", {
+ size: 40,
+ fill: 0xFFFFFF
+});
+helpTxt.anchor.set(0.5, 0);
+helpTxt.y = 150;
+LK.gui.top.addChild(helpTxt);
+// Hide help text after 5 seconds
+LK.setTimeout(function () {
+ tween(helpTxt, {
+ alpha: 0
+ }, {
+ duration: 1000,
+ easing: tween.easeOut
+ });
+}, 5000);
+// Setup game
+function setupLevel(levelNum) {
+ // Clear previous level objects
+ clearLevel();
+ // Update level text
+ levelTxt.setText("Level " + levelNum);
+ // Common setup for all levels
+ var cloudCount, obstacleCount, flowerCount;
+ switch (levelNum) {
+ case 1:
+ cloudCount = 3;
+ obstacleCount = 2;
+ flowerCount = 3;
+ break;
+ case 2:
+ cloudCount = 5;
+ obstacleCount = 4;
+ flowerCount = 5;
+ break;
+ case 3:
+ cloudCount = 7;
+ obstacleCount = 6;
+ flowerCount = 8;
+ break;
+ default:
+ cloudCount = 3;
+ obstacleCount = 2;
+ flowerCount = 3;
+ }
+ // Create clouds
+ for (var i = 0; i < cloudCount; i++) {
+ var cloud = new Cloud();
+ cloud.x = Math.random() * 1848 + 100;
+ cloud.y = Math.random() * 1000 + 300;
+ clouds.push(cloud);
+ game.addChild(cloud);
+ }
+ // Create obstacles
+ for (var i = 0; i < obstacleCount; i++) {
+ var obstacle = new Obstacle();
+ obstacle.x = Math.random() * 1848 + 100;
+ obstacle.y = Math.random() * 1500 + 600;
+ obstacles.push(obstacle);
+ game.addChild(obstacle);
+ }
+ // Create flowers that need to bloom
+ for (var i = 0; i < flowerCount; i++) {
+ var flower = new Flower();
+ flower.x = Math.random() * 1848 + 100;
+ flower.y = Math.random() * 2000 + 500;
+ flowers.push(flower);
+ game.addChild(flower);
+ }
+ // Play background music
+ LK.playMusic('ambientMusic');
+}
+function clearLevel() {
+ // Remove all game elements
+ for (var i = 0; i < airCurrents.length; i++) {
+ if (airCurrents[i].parent) {
+ airCurrents[i].parent.removeChild(airCurrents[i]);
+ }
+ }
+ airCurrents = [];
+ for (var i = 0; i < whirlwinds.length; i++) {
+ if (whirlwinds[i].parent) {
+ whirlwinds[i].parent.removeChild(whirlwinds[i]);
+ }
+ }
+ whirlwinds = [];
+ for (var i = 0; i < clouds.length; i++) {
+ if (clouds[i].parent) {
+ clouds[i].parent.removeChild(clouds[i]);
+ }
+ }
+ clouds = [];
+ for (var i = 0; i < obstacles.length; i++) {
+ if (obstacles[i].parent) {
+ obstacles[i].parent.removeChild(obstacles[i]);
+ }
+ }
+ obstacles = [];
+ for (var i = 0; i < flowers.length; i++) {
+ if (flowers[i].parent) {
+ flowers[i].parent.removeChild(flowers[i]);
+ }
+ }
+ flowers = [];
+ for (var i = 0; i < particles.length; i++) {
+ if (particles[i].parent) {
+ particles[i].parent.removeChild(particles[i]);
+ }
+ }
+ particles = [];
+}
+// Check if level is complete
+function checkLevelComplete() {
+ var allBloomed = true;
+ for (var i = 0; i < flowers.length; i++) {
+ if (!flowers[i].bloomed) {
+ allBloomed = false;
+ break;
+ }
+ }
+ if (allBloomed && flowers.length > 0) {
+ // Level complete!
+ level++;
+ if (level > maxLevels) {
+ // Game complete!
+ LK.showYouWin();
+ } else {
+ // Flash screen and move to next level
+ LK.effects.flashScreen(0xffffff, 500);
+ // Show level complete message
+ var completeTxt = new Text2("Level Complete!", {
+ size: 120,
+ fill: 0xFFFFFF
+ });
+ completeTxt.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(completeTxt);
+ // Remove message and start next level after delay
+ LK.setTimeout(function () {
+ LK.gui.center.removeChild(completeTxt);
+ setupLevel(level);
+ }, 2000);
+ }
+ }
+}
+// Input handling
+function detectGesture(id) {
+ var trail = gestureTrails[id];
+ if (!trail || trail.length < 10) return null;
+ // Check if it's a circle gesture
+ var isCircle = detectCircleGesture(trail);
+ if (isCircle) {
+ return "circle";
+ }
+ // Check if it's a swipe gesture
+ var isSwipe = detectSwipeGesture(trail);
+ if (isSwipe) {
+ return "swipe";
+ }
+ return null;
+}
+function detectCircleGesture(trail) {
+ if (trail.length < 10) return false;
+ // Calculate center of points
+ var centerX = 0,
+ centerY = 0;
+ for (var i = 0; i < trail.length; i++) {
+ centerX += trail[i].x;
+ centerY += trail[i].y;
+ }
+ centerX /= trail.length;
+ centerY /= trail.length;
+ // Calculate average distance from center
+ var avgDist = 0;
+ for (var i = 0; i < trail.length; i++) {
+ var dx = trail[i].x - centerX;
+ var dy = trail[i].y - centerY;
+ avgDist += Math.sqrt(dx * dx + dy * dy);
+ }
+ avgDist /= trail.length;
+ // Check if points form a rough circle
+ var isCircular = true;
+ var threshold = 0.3; // Allow 30% deviation
+ for (var i = 0; i < trail.length; i++) {
+ var dx = trail[i].x - centerX;
+ var dy = trail[i].y - centerY;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (Math.abs(dist - avgDist) / avgDist > threshold) {
+ isCircular = false;
+ break;
+ }
+ }
+ // Check if first and last points are close enough
+ var firstPoint = trail[0];
+ var lastPoint = trail[trail.length - 1];
+ var dx = firstPoint.x - lastPoint.x;
+ var dy = firstPoint.y - lastPoint.y;
+ var startEndDist = Math.sqrt(dx * dx + dy * dy);
+ return isCircular && startEndDist < avgDist * 0.5;
+}
+function detectSwipeGesture(trail) {
+ if (trail.length < 5) return false;
+ var firstPoint = trail[0];
+ var lastPoint = trail[trail.length - 1];
+ var dx = lastPoint.x - firstPoint.x;
+ var dy = lastPoint.y - firstPoint.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ // Check if the distance is significant enough to be a swipe
+ return distance > 200;
+}
+function createWhirlwind(x, y) {
+ var whirlwind = new Whirlwind();
+ whirlwind.x = x;
+ whirlwind.y = y;
+ whirlwinds.push(whirlwind);
+ game.addChild(whirlwind);
+ // Play sound
+ LK.getSound('whirlwindSound').play();
+ // Automatically remove after some time
+ LK.setTimeout(function () {
+ tween(whirlwind, {
+ alpha: 0
+ }, {
+ duration: 1000,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ if (whirlwind.parent) {
+ whirlwind.parent.removeChild(whirlwind);
+ }
+ var index = whirlwinds.indexOf(whirlwind);
+ if (index > -1) {
+ whirlwinds.splice(index, 1);
+ }
+ }
+ });
+ }, 5000);
+}
+function createAirCurrent(fromX, fromY, toX, toY) {
+ var dx = toX - fromX;
+ var dy = toY - fromY;
+ var length = Math.sqrt(dx * dx + dy * dy);
+ var steps = Math.max(1, Math.floor(length / 100));
+ for (var i = 0; i < steps; i++) {
+ var t = i / steps;
+ var x = fromX + dx * t;
+ var y = fromY + dy * t;
+ var airCurrent = new AirCurrent();
+ airCurrent.x = x;
+ airCurrent.y = y;
+ airCurrents.push(airCurrent);
+ game.addChild(airCurrent);
+ // Create visual particles
+ createAirParticles(x, y, dx / length, dy / length);
+ }
+ // Play sound
+ if (!windSound) {
+ windSound = LK.getSound('windSound');
+ windSound.play();
+ }
+ // Automatically remove after some time
+ LK.setTimeout(function () {
+ for (var i = 0; i < airCurrents.length; i++) {
+ var airCurrent = airCurrents[i];
+ tween(airCurrent, {
+ alpha: 0
+ }, {
+ duration: 800,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ if (airCurrent.parent) {
+ airCurrent.parent.removeChild(airCurrent);
+ }
+ }
+ });
+ }
+ airCurrents = [];
+ if (windSound) {
+ windSound = null;
+ }
+ }, 2000);
+}
+function createAirParticles(x, y, dirX, dirY) {
+ for (var i = 0; i < 3; i++) {
+ var particle = new AirParticle();
+ particle.x = x + (Math.random() - 0.5) * 40;
+ particle.y = y + (Math.random() - 0.5) * 40;
+ particle.speed.x = dirX * (2 + Math.random() * 3);
+ particle.speed.y = dirY * (2 + Math.random() * 3);
+ particles.push(particle);
+ game.addChild(particle);
+ }
+}
+// Touch event handlers
+game.down = function (x, y, obj) {
+ var touchId = Date.now().toString();
+ activeTouches[touchId] = {
+ x: x,
+ y: y
+ };
+ gestureTrails[touchId] = [{
+ x: x,
+ y: y
+ }];
+};
+game.move = function (x, y, obj) {
+ // Update active touches
+ for (var id in activeTouches) {
+ activeTouches[id] = {
+ x: x,
+ y: y
+ };
+ // Add point to gesture trail
+ if (gestureTrails[id]) {
+ gestureTrails[id].push({
+ x: x,
+ y: y
+ });
+ }
+ }
+};
+game.up = function (x, y, obj) {
+ for (var id in activeTouches) {
+ // Detect gesture
+ var gesture = detectGesture(id);
+ if (gesture === "circle") {
+ // Create a whirlwind at the center of the gesture
+ var trail = gestureTrails[id];
+ var centerX = 0,
+ centerY = 0;
+ for (var i = 0; i < trail.length; i++) {
+ centerX += trail[i].x;
+ centerY += trail[i].y;
+ }
+ centerX /= trail.length;
+ centerY /= trail.length;
+ createWhirlwind(centerX, centerY);
+ } else if (gesture === "swipe") {
+ // Create air current along the swipe
+ var trail = gestureTrails[id];
+ var firstPoint = trail[0];
+ var lastPoint = trail[trail.length - 1];
+ createAirCurrent(firstPoint.x, firstPoint.y, lastPoint.x, lastPoint.y);
+ }
+ // Clear this touch
+ delete activeTouches[id];
+ delete gestureTrails[id];
+ }
+};
+// Game update function
+game.update = function () {
+ // Update score display
+ scoreTxt.setText(LK.getScore().toString());
+ // Update all game objects
+ // Update air currents
+ for (var i = 0; i < airCurrents.length; i++) {
+ airCurrents[i].update();
+ }
+ // Update whirlwinds
+ for (var i = 0; i < whirlwinds.length; i++) {
+ whirlwinds[i].update();
+ }
+ // Update clouds
+ for (var i = 0; i < clouds.length; i++) {
+ // Apply forces from air elements
+ for (var j = 0; j < airCurrents.length; j++) {
+ airCurrents[j].applyForce(clouds[i]);
+ }
+ for (var j = 0; j < whirlwinds.length; j++) {
+ whirlwinds[j].applyForce(clouds[i]);
+ }
+ clouds[i].update();
+ }
+ // Update obstacles
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ var obstacle = obstacles[i];
+ // Apply forces from air elements
+ var forcesApplied = 0;
+ for (var j = 0; j < airCurrents.length; j++) {
+ if (airCurrents[j].applyForce(obstacle)) {
+ forcesApplied++;
+ }
+ }
+ for (var j = 0; j < whirlwinds.length; j++) {
+ if (whirlwinds[j].applyForce(obstacle)) {
+ forcesApplied++;
+ }
+ }
+ // If multiple forces are applied, damage the obstacle
+ if (forcesApplied >= 2 && LK.ticks % 30 === 0) {
+ obstacle.damage();
+ }
+ obstacle.update();
+ // Remove destroyed obstacles
+ if (obstacle.destroy) {
+ game.removeChild(obstacle);
+ obstacles.splice(i, 1);
+ }
+ }
+ // Update flowers
+ for (var i = flowers.length - 1; i >= 0; i--) {
+ var flower = flowers[i];
+ // Check if a cloud is over the flower
+ for (var j = 0; j < clouds.length; j++) {
+ if (clouds[j].intersects(flower)) {
+ flower.bloom();
+ break;
+ }
+ }
+ }
+ // Update particles
+ for (var i = particles.length - 1; i >= 0; i--) {
+ particles[i].update();
+ if (particles[i].destroy) {
+ game.removeChild(particles[i]);
+ particles.splice(i, 1);
+ }
+ }
+ // Check if level is complete
+ checkLevelComplete();
+};
+// Start the game
+setupLevel(level);
\ No newline at end of file
Modern App Store icon, high definition, square with rounded corners, for a game titled "Air Weaver" and with the description "A mystical adventure where you control the element of air through touch gestures. Harness wind currents, create tornadoes, and manipulate your environment by moving your hands across the screen. Master your air powers to overcome obstacles and restore balance to a world disrupted by chaotic weather patterns.". No text on icon!
A boy controlling wind. In-Game asset. 2d. High contrast. No shadows