User prompt
Do background music according to the game
User prompt
Do harder when we complete waves one by one do hard
User prompt
Zombie was little bit powerful from shadowCreature.
User prompt
Add zombie
User prompt
Increase range to attack
User prompt
Add one more peashooterPod to buy . Base on add extra damge and health
User prompt
Add buy button for peashooterPod.
User prompt
Do give more peashooterPod. And opinion to buy to add in ground
User prompt
Enemy bar tell that how much enemy left
User prompt
When enemy damge all manasprout then then the game defeat
User prompt
Change the defeat system. When the all Tower down then the payer were defeat
User prompt
Fix the image
User prompt
Add background image according to the game and music
User prompt
When three defence Tower were dead then game over
User prompt
Make the hero to move with were on place
User prompt
The hero cannot move and attack to enemy with gun
Code edit (1 edits merged)
Please save this source code
User prompt
Mana Bloom: Guardian's Ascent
Initial prompt
let's make it a longer game idea that still holds onto the "no-lag" principle by focusing on clever content reuse and modular design. We'll expand the core concept, progression, and variety without adding excessive real-time processing demands. Mana Bloom: Guardian's Ascent (Extended No-Lag Edition) Concept: You are the last Mana Weaver, tasked with restoring the fragmented Great Mana Bloom across a series of corrupted garden realms. This is a 2D hybrid action-strategy game where you control a hero in small, fixed-screen arenas, planting simple, effective plant guardians to defend a vital "Mana Sprout" against waves of shadow creatures. The emphasis is on strategic decision-making, clever progression, and efficient visual design to ensure a smooth, lag-free experience across many hours of gameplay. Core Gameplay Loop: A Seamless Blend * Arena Combat (Action-Strategy): Each level is a self-contained, fixed-screen arena. Your hero character (e.g., "Seedling Scout," "Bloom Warden") moves freely, attacking incoming waves of shadow creatures with basic attacks. You collect "Sunlight Essences" dropped by defeated enemies, which are the primary resource for planting and upgrading your plant guardians. * Strategic Guardian Placement: From a limited hotbar, you tap to place different types of plant guardians (e.g., "Peashooter Pod" for single-target damage, "Sticky Vine" for slow, "Bursting Berry" for area damage). Guardians attack automatically. You'll need to learn enemy types and paths to optimize your defense. * Wave Management: Enemies arrive in distinct, timed waves. Between waves, there's a short breather to re-position your hero, collect any missed essences, and plan your next guardian placements or upgrades. Surviving all waves completes the arena. * Progression & Realm Exploration: Completing an arena unlocks the next, guiding you through a linear progression of increasingly challenging corrupted garden realms. Each realm introduces new enemy types, environmental hazards, and unique "Mana Sprout" challenges. Deep (Yet Optimized) Progression System * Hero Advancement: * Leveling & Core Stats: Your hero gains XP from defeating enemies and completing levels, increasing base stats like Health, Attack Damage, and Movement Speed. These are simple numerical increments, not complex calculations. * "Weaver Skills" (Passive Unlocks): Instead of an active skill tree, you unlock passive "Weaver Skills" at certain hero levels. These could be: * Essence Magnetism: Automatically collect nearby Sunlight Essences. * Rooted Resilience: Briefly gain defense when planting a guardian. * Sprout Vigor: Mana Sprout passively regenerates a small amount of health. * Efficient Planter: Reduces Sunlight cost for specific guardian types. * Artifacts (Equippable Boosts): Rarely dropped or earned, these are simple stat-boosting items (e.g., "Glimmering Dewdrop" for +5% Essence gain, "Tough Bark Vest" for +10 Health). Only 1-2 can be equipped at a time. * Guardian Evolution: * Unlocking New Types: As you progress through realms, you'll discover "Seed Pods" for new guardian types. Each new guardian offers a distinct strategic advantage. * Tier Upgrades: Each guardian type has 2-3 fixed tiers of upgrades (e.g., Peashooter Pod -> Spitting Pod -> Rapid-Fire Pod). Upgrading a guardian costs Sunlight Essences and boosts its damage, range, or adds a simple effect (e.g., a chance to pierce). These are pre-calculated values, not dynamic modifiers. * "Bloom Resonance" (Global Boosts): Completing certain challenges or realms grants "Bloom Resonance points." These points can be spent on global, passive buffs for all guardians (e.g., +2% overall guardian damage, +1% guardian attack speed). These are persistent and very small numerical boosts, easy for the engine to manage. Content Variety (Designed for No Lag) * Diverse Arenas (Fixed Screens): While each arena is fixed-screen, their layout changes significantly. Some might have winding paths, choke points, multiple Mana Sprouts, or environmental elements (e.g., "Slime Pits" that slow enemies, "Thorn Bushes" that damage them, "Fertile Patches" that boost guardian stats when planted there). These elements are static background layers, not active physics objects. * Unique Enemy Types: Each realm introduces a new set of shadow creatures. These have distinct appearances (simple sprites), movement patterns (pre-set paths), and attack types (melee, simple projectile). Examples: * "Skitterlings": Fast, low HP, rush the Mana Sprout. * "Gloom Beetles": Slow, high HP, require sustained fire. * "Shadow Wisps": Fly over ground units, only targetable by specific guardians or hero attacks. * "Corrupted Blight-Lord" (Bosses): Larger sprites, predictable attack patterns, higher health. These act as "gatekeepers" for new realms. * Thematic Realms: Each realm has a distinct visual theme using a simple palette swap and unique static background elements (e.g., "Sunken Grotto," "Whispering Woods," "Volcanic Fissure"). This creates variety without complex new assets per level. * Challenges & Objectives: Beyond just surviving waves, levels might have secondary objectives: * "Protect all 3 Mana Sprouts." * "Defeat X special enemies." * "Survive with no guardians planted." (Hero-only challenge) No-Lag Design Principles in Action * Minimal Asset Loading: Reuses guardian and enemy base sprites with simple color changes or minor additions for upgrades/variants. Environmental elements are static background layers. * No Physics Engine: All movement and collisions are handled via simple coordinate checks and predetermined paths. * Limited Particle Effects: Visuals for attacks are simple "hit sprites" or quick, small, non-persisting shapes, not complex particle systems. * Optimized Rendering: Uses a single render layer for most gameplay elements, reducing draw calls. * Efficient AI: Enemies follow pre-baked paths. Guardians target the nearest valid enemy. No complex decision-making processes. * Capped Entity Count: The game engine is designed to ensure a maximum, controlled number of enemies and projectiles are active on screen at any given time. * Low-Overhead Audio: Uses short, looping background music and compressed sound effects that are carefully managed to avoid overlapping too much. By focusing on these deliberate design choices, "Mana Bloom: Guardian's Ascent (Extended No-Lag Edition)" provides a rich, engaging, and long-lasting 2D experience that runs incredibly smoothly, proving that depth and longevity don't have to come at the cost of performance.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Hero = Container.expand(function () { var self = Container.call(this); self.hp = 100; self.maxHp = 100; self.speed = 4; self.attackDamage = 25; self.attackCooldown = 0; self.attackRate = 30; // frames between attacks self.targetX = 0; self.targetY = 0; self.isMoving = false; var heroGraphics = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.takeDamage = function (damage) { self.hp -= damage; if (self.hp <= 0) { self.hp = 0; LK.showGameOver(); } LK.effects.flashObject(self, 0xff0000, 300); }; self.update = function () { if (self.attackCooldown > 0) { self.attackCooldown--; } // Handle movement to target position if (self.isMoving) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { // Move towards target self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { // Reached target self.isMoving = false; } } // Gun attack - shoot projectiles at enemies if (self.attackCooldown <= 0) { var closestEnemy = null; var closestDistance = 300; // Gun range for (var i = 0; i < shadowCreatures.length; i++) { var enemy = shadowCreatures[i]; var distance = Math.sqrt(Math.pow(self.x - enemy.x, 2) + Math.pow(self.y - enemy.y, 2)); if (distance < closestDistance) { closestDistance = distance; closestEnemy = enemy; } } if (closestEnemy) { // Shoot projectile at enemy var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; projectile.targetX = closestEnemy.x; projectile.targetY = closestEnemy.y; projectile.damage = self.attackDamage; game.addChild(projectile); projectiles.push(projectile); self.attackCooldown = self.attackRate; LK.getSound('shoot').play(); } } }; return self; }); var ManaSprout = Container.expand(function () { var self = Container.call(this); self.hp = 50; self.maxHp = 50; var sproutGraphics = self.attachAsset('manaSprout', { anchorX: 0.5, anchorY: 0.5 }); self.takeDamage = function (damage) { self.hp -= damage; if (self.hp <= 0) { self.hp = 0; LK.showGameOver(); } LK.effects.flashObject(self, 0xff0000, 500); }; return self; }); var PeashooterPod = Container.expand(function () { var self = Container.call(this); self.attackDamage = 20; self.attackCooldown = 0; self.attackRate = 45; self.range = 200; self.hp = 60; self.maxHp = 60; var podGraphics = self.attachAsset('peashooterPod', { anchorX: 0.5, anchorY: 0.5 }); self.takeDamage = function (damage) { self.hp -= damage; LK.effects.flashObject(self, 0xff0000, 300); if (self.hp <= 0) { self.hp = 0; towersDestroyed++; return true; // tower died } return false; }; self.update = function () { if (self.attackCooldown > 0) { self.attackCooldown--; } // Find enemy in range if (self.attackCooldown <= 0) { for (var i = 0; i < shadowCreatures.length; i++) { var enemy = shadowCreatures[i]; var distance = Math.sqrt(Math.pow(self.x - enemy.x, 2) + Math.pow(self.y - enemy.y, 2)); if (distance <= self.range) { // Shoot projectile var projectile = new Projectile(); projectile.x = self.x; projectile.y = self.y; projectile.targetX = enemy.x; projectile.targetY = enemy.y; projectile.damage = self.attackDamage; game.addChild(projectile); projectiles.push(projectile); self.attackCooldown = self.attackRate; LK.getSound('shoot').play(); break; } } } }; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); self.speed = 8; self.damage = 20; self.targetX = 0; self.targetY = 0; self.directionX = 0; self.directionY = 0; var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); // Calculate direction on creation self.setTarget = function (targetX, targetY) { var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.directionX = dx / distance; self.directionY = dy / distance; } }; self.update = function () { // Move towards target if (self.directionX === 0 && self.directionY === 0) { self.setTarget(self.targetX, self.targetY); } self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; // Check collision with enemies for (var i = 0; i < shadowCreatures.length; i++) { var enemy = shadowCreatures[i]; if (self.intersects(enemy)) { if (enemy.takeDamage(self.damage)) { // Enemy died, remove it enemy.destroy(); shadowCreatures.splice(i, 1); } return true; // Projectile should be destroyed } } // Remove if off screen if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) { return true; // Projectile should be destroyed } return false; }; return self; }); var ShadowCreature = Container.expand(function () { var self = Container.call(this); self.hp = 30; self.maxHp = 30; self.speed = 1; self.attackDamage = 10; self.attackCooldown = 0; self.attackRate = 60; self.target = null; self.lastX = 0; self.lastY = 0; var creatureGraphics = self.attachAsset('shadowCreature', { anchorX: 0.5, anchorY: 0.5 }); self.takeDamage = function (damage) { self.hp -= damage; LK.effects.flashObject(self, 0xffffff, 200); if (self.hp <= 0) { var essence = new SunlightEssence(); essence.x = self.x; essence.y = self.y; game.addChild(essence); sunlightEssences.push(essence); LK.getSound('enemyHit').play(); return true; // enemy died } return false; }; self.update = function () { self.lastX = self.x; self.lastY = self.y; if (self.attackCooldown > 0) { self.attackCooldown--; } // Find closest target var closestDistance = Infinity; self.target = null; // Check mana sprouts for (var i = 0; i < manaSprouts.length; i++) { var sprout = manaSprouts[i]; var distance = Math.sqrt(Math.pow(self.x - sprout.x, 2) + Math.pow(self.y - sprout.y, 2)); if (distance < closestDistance) { closestDistance = distance; self.target = sprout; } } // Check peashooter pods for (var i = 0; i < peashooterPods.length; i++) { var pod = peashooterPods[i]; var distance = Math.sqrt(Math.pow(self.x - pod.x, 2) + Math.pow(self.y - pod.y, 2)); if (distance < closestDistance) { closestDistance = distance; self.target = pod; } } // Check hero if (hero) { var heroDistance = Math.sqrt(Math.pow(self.x - hero.x, 2) + Math.pow(self.y - hero.y, 2)); if (heroDistance < closestDistance) { closestDistance = heroDistance; self.target = hero; } } // Move towards target if (self.target) { var dx = self.target.x - self.x; var dy = self.target.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 40) { // Move towards target self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { // Attack target if (self.attackCooldown <= 0) { self.target.takeDamage(self.attackDamage); self.attackCooldown = self.attackRate; } } } }; return self; }); var SunlightEssence = Container.expand(function () { var self = Container.call(this); self.value = 10; var essenceGraphics = self.attachAsset('sunlightEssence', { anchorX: 0.5, anchorY: 0.5 }); // Add a gentle floating animation tween(self, { y: self.y - 10 }, { duration: 1000, easing: tween.easeInOut }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2d5016 }); /**** * Game Code ****/ // Game state variables var hero; var manaSprouts = []; var shadowCreatures = []; var peashooterPods = []; var projectiles = []; var sunlightEssences = []; var currentEssences = 50; // Starting essences var waveNumber = 1; var enemiesRemaining = 0; var waveActive = false; var timeBetweenWaves = 300; // frames var waveTimer = 0; var selectedPlantType = 'peashooter'; var plantCost = 25; var towersDestroyed = 0; // UI Elements var essenceText = new Text2('Essences: 50', { size: 60, fill: 0xFFFFFF }); essenceText.anchor.set(0, 0); essenceText.x = 120; essenceText.y = 50; LK.gui.topLeft.addChild(essenceText); var waveText = new Text2('Wave: 1', { size: 60, fill: 0xFFFFFF }); waveText.anchor.set(1, 0); waveText.x = -50; waveText.y = 50; LK.gui.topRight.addChild(waveText); var statusText = new Text2('Prepare for battle!', { size: 80, fill: 0xFFFF00 }); statusText.anchor.set(0.5, 0); statusText.x = 0; statusText.y = 120; LK.gui.top.addChild(statusText); // Add background image var backgroundImage = game.addChild(LK.getAsset('gardenBackground', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); // Initialize hero hero = game.addChild(new Hero()); hero.x = 1024; hero.y = 1366; // Start background music LK.playMusic('gardenTheme'); // Initialize mana sprouts var sprout1 = game.addChild(new ManaSprout()); sprout1.x = 512; sprout1.y = 400; manaSprouts.push(sprout1); var sprout2 = game.addChild(new ManaSprout()); sprout2.x = 1536; sprout2.y = 400; manaSprouts.push(sprout2); var sprout3 = game.addChild(new ManaSprout()); sprout3.x = 1024; sprout3.y = 600; manaSprouts.push(sprout3); // Game state functions function startWave() { waveActive = true; enemiesRemaining = waveNumber * 3 + 2; statusText.setText('Wave ' + waveNumber + ' - Enemies: ' + enemiesRemaining); // Spawn enemies gradually var enemySpawnTimer = LK.setInterval(function () { if (enemiesRemaining > 0) { spawnEnemy(); enemiesRemaining--; statusText.setText('Wave ' + waveNumber + ' - Enemies: ' + enemiesRemaining); } }, 60); LK.setTimeout(function () { LK.clearInterval(enemySpawnTimer); }, enemiesRemaining * 60); } function spawnEnemy() { var enemy = new ShadowCreature(); // Spawn from random edge var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top enemy.x = Math.random() * 2048; enemy.y = -50; break; case 1: // Right enemy.x = 2098; enemy.y = Math.random() * 2732; break; case 2: // Bottom enemy.x = Math.random() * 2048; enemy.y = 2782; break; case 3: // Left enemy.x = -50; enemy.y = Math.random() * 2732; break; } game.addChild(enemy); shadowCreatures.push(enemy); } function endWave() { waveActive = false; waveNumber++; waveTimer = timeBetweenWaves; waveText.setText('Wave: ' + waveNumber); statusText.setText('Wave Complete! Next wave in ' + Math.ceil(waveTimer / 60) + 's'); // Bonus essences for completing wave currentEssences += 20; updateEssenceDisplay(); } function updateEssenceDisplay() { essenceText.setText('Essences: ' + currentEssences); } function collectEssence(essence) { currentEssences += essence.value; updateEssenceDisplay(); LK.getSound('collect').play(); } // Input handling var dragNode = null; var plantingMode = false; function handleMove(x, y, obj) { if (dragNode) { dragNode.x = x; dragNode.y = y; } } game.move = handleMove; game.down = function (x, y, obj) { // Set hero target position for movement hero.targetX = x; hero.targetY = y; hero.isMoving = true; // Check if clicking to plant if (currentEssences >= plantCost && !waveActive) { // Check if position is valid (not too close to existing plants or sprouts) var validPosition = true; for (var i = 0; i < peashooterPods.length; i++) { var pod = peashooterPods[i]; var distance = Math.sqrt(Math.pow(x - pod.x, 2) + Math.pow(y - pod.y, 2)); if (distance < 80) { validPosition = false; break; } } for (var i = 0; i < manaSprouts.length; i++) { var sprout = manaSprouts[i]; var distance = Math.sqrt(Math.pow(x - sprout.x, 2) + Math.pow(y - sprout.y, 2)); if (distance < 80) { validPosition = false; break; } } if (validPosition) { var newPod = new PeashooterPod(); newPod.x = x; newPod.y = y; game.addChild(newPod); peashooterPods.push(newPod); currentEssences -= plantCost; updateEssenceDisplay(); LK.getSound('plant').play(); } } }; game.up = function (x, y, obj) { dragNode = null; }; // Start first wave after delay waveTimer = 180; // 3 seconds game.update = function () { // Handle wave timing if (!waveActive) { if (waveTimer > 0) { waveTimer--; if (waveTimer % 60 === 0) { statusText.setText('Next wave in ' + Math.ceil(waveTimer / 60) + 's'); } } else { startWave(); } } else { // Check if wave is complete if (enemiesRemaining <= 0 && shadowCreatures.length === 0) { endWave(); } } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var projectile = projectiles[i]; var shouldDestroy = projectile.update(); if (shouldDestroy) { projectile.destroy(); projectiles.splice(i, 1); } } // Check for destroyed towers for (var i = peashooterPods.length - 1; i >= 0; i--) { var pod = peashooterPods[i]; if (pod.hp <= 0) { pod.destroy(); peashooterPods.splice(i, 1); } } // Check game over condition - 3 towers destroyed if (towersDestroyed >= 3) { LK.showGameOver(); } // Check essence collection for (var i = sunlightEssences.length - 1; i >= 0; i--) { var essence = sunlightEssences[i]; var distance = Math.sqrt(Math.pow(hero.x - essence.x, 2) + Math.pow(hero.y - essence.y, 2)); if (distance < 40) { collectEssence(essence); essence.destroy(); sunlightEssences.splice(i, 1); } } // Hero attack now handled in Hero class update method // Check win condition if (waveNumber > 5 && !waveActive && shadowCreatures.length === 0) { LK.showYouWin(); } };
===================================================================
--- original.js
+++ change.js
@@ -345,12 +345,21 @@
statusText.anchor.set(0.5, 0);
statusText.x = 0;
statusText.y = 120;
LK.gui.top.addChild(statusText);
+// Add background image
+var backgroundImage = game.addChild(LK.getAsset('gardenBackground', {
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 0
+}));
// Initialize hero
hero = game.addChild(new Hero());
hero.x = 1024;
hero.y = 1366;
+// Start background music
+LK.playMusic('gardenTheme');
// Initialize mana sprouts
var sprout1 = game.addChild(new ManaSprout());
sprout1.x = 512;
sprout1.y = 400;
Hero. In-Game asset. 2d. High contrast. No shadows
manaSprout. In-Game asset. 2d. High contrast. No shadows
sunlightEssence. In-Game asset. 2d. High contrast. No shadows
projectile. In-Game asset. 2d. High contrast. No shadows
peashooterPod. In-Game asset. 2d. High contrast. No shadows
shadowCreature. In-Game asset. 2d. High contrast. No shadows
Makeup green colour background in the background and grass. In-Game asset. 2d. High contrast. No shadows
zombie. In-Game asset. 2d. High contrast. No shadows