User prompt
Now place healthbar to the left bottom
User prompt
Can you make health bar from the 6 squares in healthbar asset
User prompt
Place it middle of the screen
User prompt
Make it more seenable
User prompt
Add it visually
User prompt
Add a little leveled bar to the right bottom corner that shows how many health is left
User prompt
Don't start spawn other enemies again until enemyx killed
User prompt
After enemyx killed once, drop 3 health potions
User prompt
When score has passed 250 spawn enemyx before spawning other enemies again
User prompt
In boss mode enemyx drops items a bit less frequently
User prompt
Enemyx shoots a bit less frequently
User prompt
Make enemyx health 250 only in normal mode
User prompt
Health potion, shield and beam items randomly drops from enemyx in boss mode
User prompt
Enemyx's beam is a bit more rare and hits only when active
User prompt
Add a boss mode button in menu that only spawns enemyx in game
User prompt
The laser cannon is not effective on enemyx
User prompt
After the boss is dead, it drops 3 health potions and normal enemies start to come again slowly
User prompt
Make boss music not play at 250 score but when enemyx spawns
User prompt
Make boss music normal again but play at 250 once, not after every score gain
User prompt
The boss music plays so loud. Fix that
User prompt
Remove the delay.
User prompt
Enemyx waits 3 seconds before spawning
User prompt
Count the score of enemies killed by ulti too
User prompt
When 250 score is passed stop the playing music and play boss
User prompt
Make enemyx bigger
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Beam item class var BeamItem = Container.expand(function () { var self = Container.call(this); var beamSprite = self.attachAsset('beamItem', { anchorX: 0.5, anchorY: 0.5 }); beamSprite.width = 90; beamSprite.height = 90; beamSprite.alpha = 0.95; self.update = function () { self.y += 12; }; return self; }); // Enemy type 1: moves straight down var Enemy1 = Container.expand(function () { var self = Container.call(this); var enemySprite = self.attachAsset('enemy1', { anchorX: 0.5, anchorY: 0.5 }); enemySprite.width = 200; enemySprite.height = 200; self.speed = 8 + Math.random() * 4; self.update = function () { self.y += self.speed; }; return self; }); // Enemy type 2: moves in sine wave var Enemy2 = Container.expand(function () { var self = Container.call(this); var enemySprite = self.attachAsset('enemy2', { anchorX: 0.5, anchorY: 0.5 }); enemySprite.width = 160; enemySprite.height = 160; self.speed = 7 + Math.random() * 3; self.waveAmplitude = 120 + Math.random() * 80; self.waveSpeed = 0.02 + Math.random() * 0.01; self.baseX = 0; self.t = 0; self.update = function () { self.y += self.speed; self.t += self.waveSpeed; self.x = self.baseX + Math.sin(self.t * 6.28) * self.waveAmplitude; }; return self; }); // Strong Enemy3: needs 5 hits to die, moves straight down, larger and purple var Enemy3 = Container.expand(function () { var self = Container.call(this); var enemySprite = self.attachAsset('enemy3', { anchorX: 0.5, anchorY: 0.5 }); enemySprite.width = 260; enemySprite.height = 260; self.speed = 6 + Math.random() * 2; self.hp = 5; self.update = function () { self.y += self.speed; }; return self; }); // Enemy bullet class var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = 0; self.speedY = 16; self.update = function () { self.x += self.speedX; self.y += self.speedY; }; return self; }); // Extraordinary EnemyX: spawns only once after 250 score, unique appearance and behavior var EnemyX = Container.expand(function () { var self = Container.call(this); // Use dedicated enemyX asset var enemySprite = self.attachAsset('enemyX', { anchorX: 0.5, anchorY: 0.5 }); enemySprite.width = 600; enemySprite.height = 600; enemySprite.alpha = 0.98; self.speed = 4 + Math.random() * 2; self.hp = 500; // much higher HP (500 hits required) // --- EnemyX shooting logic --- self.shootTick = 0; self.beamCooldown = 0; self.update = function () { // Only allow EnemyX to wander in the upper part of the screen (y between 0 and 500) if (typeof self.t === "undefined") self.t = Math.random() * 2; self.t += 0.012; // Sway left/right slowly self.x += Math.sin(self.t * 2.5) * 6; // Restrict vertical movement: only allow y to increase up to a certain limit, then bounce back up if (typeof self.directionY === "undefined") self.directionY = 1; // Set upper and lower bounds for wandering var upperY = 60 + enemySprite.height / 2; var lowerY = 420 + enemySprite.height / 2; // Move down or up depending on direction self.y += self.speed * self.directionY * 0.5; // much slower vertical movement // If reached lower bound, go up; if reached upper bound, go down if (self.y >= lowerY) { self.y = lowerY; self.directionY = -1; } else if (self.y <= upperY) { self.y = upperY; self.directionY = 1; } // --- Shooting more frequently --- self.shootTick = (self.shootTick || 0) + 1; self.beamCooldown = (self.beamCooldown || 0) - 1; // Shoot a bullet every 30-50 ticks (randomized, much more frequent) if (self.shootTick >= 30 + Math.floor(Math.random() * 20)) { if (typeof game !== "undefined" && typeof hero !== "undefined") { // Shoot 3-way spread for (var i = -1; i <= 1; i++) { var bullet = new EnemyBullet(); bullet.x = self.x + i * 60; bullet.y = self.y + 120; // Aim at hero, but with spread var dx = hero.x - bullet.x + i * 80; var dy = hero.y - bullet.y; var len = Math.sqrt(dx * dx + dy * dy); if (len > 0) { bullet.speedX = dx / len * 20; bullet.speedY = dy / len * 20; } enemyBullets.push(bullet); game.addChild(bullet); LK.getSound('enemyShoot').play(); } } self.shootTick = 0; } // Sometimes shoot a beam down (every 180-300 ticks, random, but not too often) if (self.beamCooldown <= 0 && Math.random() < 0.04) { if (typeof game !== "undefined") { // Visual: big vertical beam var beam = LK.getAsset('beamItem', { anchorX: 0.5, anchorY: 0, x: self.x, y: self.y + enemySprite.height / 2 }); beam.width = 120; beam.height = 2732 - (self.y + enemySprite.height / 2); beam.alpha = 0.38 + Math.random() * 0.12; game.addChild(beam); // Beam effect: damage hero if in column for 60 frames beam.life = 60; beam.update = function () { this.life--; // Flicker effect this.alpha = 0.32 + Math.random() * 0.18; // Check collision with hero if (typeof hero !== "undefined" && hero.y > this.y && hero.y < this.y + this.height) { if (Math.abs(hero.x - this.x) < this.width / 2 + hero.width / 2) { if (!godMode && !shieldActive && this.life === 59) { LK.getSound('heroHit').play(); LK.effects.flashScreen(0xff0000, 800); heroHealth--; updateHealthBar(); if (heroHealth <= 0) { LK.showGameOver(); return; } } else if (!godMode && shieldActive && this.life === 59) { LK.effects.flashObject(hero, 0x00ffff, 200); } } } if (this.life <= 0) { this.destroy(); } }; // Add to enemyBullets for update/removal enemyBullets.push(beam); // Play laser sound LK.getSound('laser').play(); // Set cooldown for next beam self.beamCooldown = 180 + Math.floor(Math.random() * 120); } } }; return self; }); // Health potion class (separate asset) var HealthPotion = Container.expand(function () { var self = Container.call(this); var potionSprite = self.attachAsset('healthPotion', { anchorX: 0.5, anchorY: 0.5 }); potionSprite.width = 90; potionSprite.height = 90; potionSprite.alpha = 0.95; self.update = function () { self.y += 16; }; return self; }); // Hero class var Hero = Container.expand(function () { var self = Container.call(this); var heroSprite = self.attachAsset('hero', { anchorX: 0.5, anchorY: 0.5 }); self.radius = heroSprite.width / 2; self.shootCooldown = 0; self.update = function () { if (self.shootCooldown > 0) self.shootCooldown--; }; return self; }); // Hero bullet class var HeroBullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('heroBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -32; self.update = function () { self.y += self.speed; }; return self; }); // Shield item class var ShieldItem = Container.expand(function () { var self = Container.call(this); var shieldSprite = self.attachAsset('shieldItem', { anchorX: 0.5, anchorY: 0.5 }); shieldSprite.width = 90; shieldSprite.height = 90; shieldSprite.alpha = 0.95; // Make it much brighter/less transparent self.update = function () { self.y += 12; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Add background asset to game scene // --- MENU OVERLAY --- // Play menu music and stop background music when menu is shown // separate asset for health potion var backgroundSprite = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); // Scale background to fill the screen (2048x2732) var bgOriginalWidth = backgroundSprite.width; var bgOriginalHeight = backgroundSprite.height; var scaleX = 2048 / bgOriginalWidth; var scaleY = 2732 / bgOriginalHeight; var scale = Math.max(scaleX, scaleY); // cover entire area backgroundSprite.width = bgOriginalWidth * scale; backgroundSprite.height = bgOriginalHeight * scale; // Center if needed (in case aspect ratio doesn't match) backgroundSprite.x = (2048 - backgroundSprite.width) / 2; backgroundSprite.y = (2732 - backgroundSprite.height) / 2; game.addChild(backgroundSprite); LK.stopMusic(); LK.playMusic('Menu'); var menuOverlay = new Container(); menuOverlay.zIndex = 10000; // ensure on top // Title text var titleTxt = new Text2("GALAXY DODGE SHOOTER", { size: 160, fill: "#fff", fontWeight: "bold" }); titleTxt.anchor.set(0.5, 0); titleTxt.x = 2048 / 2; titleTxt.y = 220; menuOverlay.addChild(titleTxt); // Play button background var playBtnBg = LK.getAsset('enemy2', { anchorX: 0.5, anchorY: 0.5, tint: 0x00eaff }); playBtnBg.width = 600; playBtnBg.height = 220; playBtnBg.alpha = 0.25; playBtnBg.x = 2048 / 2; playBtnBg.y = 700; menuOverlay.addChild(playBtnBg); // Play button text var playBtn = new Text2("PLAY", { size: 140, fill: 0x00EAFF, fontWeight: "bold" }); playBtn.anchor.set(0.5, 0.5); playBtn.x = 2048 / 2; playBtn.y = 700; menuOverlay.addChild(playBtn); // Add music toggle button to menu var musicOn = true; var musicBtnBg = LK.getAsset('enemy2', { anchorX: 0.5, anchorY: 0.5, tint: 0x00eaff }); musicBtnBg.width = 340; musicBtnBg.height = 140; musicBtnBg.alpha = 0.25; musicBtnBg.x = 2048 / 2; musicBtnBg.y = 1050; menuOverlay.addChild(musicBtnBg); var musicBtn = new Text2("MUSIC: ON", { size: 80, fill: 0x00EAFF, fontWeight: "bold" }); musicBtn.anchor.set(0.5, 0.5); musicBtn.x = 2048 / 2; musicBtn.y = 1050; menuOverlay.addChild(musicBtn); // Add god mode play button to menu, positioned under the music button var godMode = false; var godPlayBtnBg = LK.getAsset('enemy2', { anchorX: 0.5, anchorY: 0.5, tint: 0xffd700 }); godPlayBtnBg.width = 600; godPlayBtnBg.height = 220; godPlayBtnBg.alpha = 0.25; // Place god mode button below the music button (with margin) godPlayBtnBg.x = 2048 / 2; godPlayBtnBg.y = 1050 + musicBtnBg.height / 2 + 60 + godPlayBtnBg.height / 2; menuOverlay.addChild(godPlayBtnBg); var godPlayBtn = new Text2("PLAY (GOD MODE)", { size: 100, fill: 0xffd700, fontWeight: "bold" }); godPlayBtn.anchor.set(0.5, 0.5); godPlayBtn.x = 2048 / 2; godPlayBtn.y = godPlayBtnBg.y; menuOverlay.addChild(godPlayBtn); // Add menu overlay to game game.addChild(menuOverlay); // Menu state var menuActive = true; // Play button interaction menuOverlay.down = function (x, y, obj) { // Check if play button was pressed (normal mode) var dx = x - playBtn.x; var dy = y - playBtn.y; if (Math.abs(dx) <= playBtnBg.width / 2 && Math.abs(dy) <= playBtnBg.height / 2) { // Hide menu, start game in normal mode menuOverlay.visible = false; menuActive = false; godMode = false; LK.stopMusic(); if (musicOn) { LK.playMusic('bgmusic'); } return; } // Check if god mode play button was pressed var gdx = x - godPlayBtn.x; var gdy = y - godPlayBtn.y; if (Math.abs(gdx) <= godPlayBtnBg.width / 2 && Math.abs(gdy) <= godPlayBtnBg.height / 2) { // Hide menu, start game in god mode menuOverlay.visible = false; menuActive = false; godMode = true; LK.stopMusic(); if (musicOn) { LK.playMusic('Godmode'); // godmode music while playing in godmode } return; } // Check if music button was pressed var mdx = x - musicBtn.x; var mdy = y - musicBtn.y; if (Math.abs(mdx) <= musicBtnBg.width / 2 && Math.abs(mdy) <= musicBtnBg.height / 2) { musicOn = !musicOn; if (musicOn) { musicBtn.setText("MUSIC: ON"); LK.playMusic('Menu'); } else { musicBtn.setText("MUSIC: OFF"); LK.stopMusic(); } return; } }; menuOverlay.move = function (x, y, obj) {}; menuOverlay.up = function (x, y, obj) {}; // Score display var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Health bar UI var maxHealth = 6; var heroHealth = maxHealth; var healthBarBg = LK.getAsset('enemy2', { anchorX: 0, // left edge anchorY: 1, // bottom edge tint: 0x222222 }); healthBarBg.width = 420; healthBarBg.height = 60; healthBarBg.alpha = 0.45; // Place at left bottom, with margin (60px from left, 60px from bottom) healthBarBg.x = 60; healthBarBg.y = 2732 - 60; LK.gui.bottomLeft.addChild(healthBarBg); var healthBar = LK.getAsset('enemy1', { anchorX: 0, // left edge anchorY: 1, // bottom edge tint: 0xff4444 }); healthBar.width = 420; healthBar.height = 60; healthBar.alpha = 0.85; healthBar.x = 60; healthBar.y = 2732 - 60; LK.gui.bottomLeft.addChild(healthBar); function updateHealthBar() { healthBar.width = 420 * (heroHealth / maxHealth); if (heroHealth <= 2) { healthBar.tint = 0xff2222; } else if (heroHealth <= 4) { healthBar.tint = 0xffbb22; } else { healthBar.tint = 0x44ff44; } } updateHealthBar(); // Game variables var hero = new Hero(); game.addChild(hero); hero.x = 2048 / 2; hero.y = 2732 - 350; // Track if EnemyX has spawned var enemyXSpawned = false; // Ulti button UI and state var ultiReady = true; var ultiCooldown = 0; var ultiCooldownMax = 1800; // 30 seconds at 60fps // Create ulti button var ultiBtn = new Text2("ULTI", { size: 120, fill: 0x00EAFF, fontWeight: "bold" }); ultiBtn.anchor.set(0.5, 0.5); // Place in right corner, leaving margin for touch and not overlapping top menu ultiBtn.x = 2048 - 180; ultiBtn.y = 2732 - 180; ultiBtn.bg = LK.getAsset('enemy2', { anchorX: 0.5, anchorY: 0.5, tint: 0x00eaff }); ultiBtn.bg.width = 340; ultiBtn.bg.height = 220; ultiBtn.bg.alpha = 0.25; ultiBtn.bg.x = ultiBtn.x; ultiBtn.bg.y = ultiBtn.y; game.addChild(ultiBtn.bg); game.addChild(ultiBtn); // Ulti button cooldown overlay var ultiBtnOverlay = LK.getAsset('enemy2', { anchorX: 0.5, anchorY: 0.5, tint: 0x222222 }); ultiBtnOverlay.width = 340; ultiBtnOverlay.height = 220; ultiBtnOverlay.alpha = 0.55; ultiBtnOverlay.x = ultiBtn.x; ultiBtnOverlay.y = ultiBtn.y; ultiBtnOverlay.visible = false; game.addChild(ultiBtnOverlay); // Laser Cannon state (no button UI) var laserReady = true; var laserCooldown = 0; var laserCooldownMax = 720; // 12 seconds at 60fps // Armor visual overlay for shield var heroArmor = LK.getAsset('enemy2', { anchorX: 0.5, anchorY: 0.5, tint: 0x80eaff // light blue }); heroArmor.width = hero.width * 1.35; heroArmor.height = hero.height * 1.35; heroArmor.alpha = 0.55; heroArmor.visible = false; game.addChild(heroArmor); var heroBullets = []; var enemies = []; var enemyBullets = []; var items = []; var dragNode = null; var lastHeroIntersecting = false; var score = 0; var spawnTick = 0; var enemyShootTick = 0; // Powerup state var shieldActive = false; var shieldTimer = 0; var beamActive = false; var beamTimer = 0; // Helper: spawn item function spawnItem() { var itemType = Math.random() < 0.5 ? "shield" : "beam"; var item; if (itemType === "shield") { item = new ShieldItem(); } else { item = new BeamItem(); } item.x = 200 + Math.random() * (2048 - 400); item.y = -80; items.push(item); game.addChild(item); } // Helper: spawn enemy function spawnEnemy() { // Increase chance for Enemy3: 20% Enemy3, 40% Enemy1, 40% Enemy2 var rand = Math.random(); var enemy; if (rand < 0.4) { enemy = new Enemy1(); enemy.x = 200 + Math.random() * (2048 - 400); enemy.y = -80; } else if (rand < 0.8) { enemy = new Enemy2(); enemy.baseX = 200 + Math.random() * (2048 - 400); enemy.x = enemy.baseX; enemy.y = -80; enemy.t = Math.random() * 2; } else { enemy = new Enemy3(); enemy.x = 200 + Math.random() * (2048 - 400); enemy.y = -80; } enemies.push(enemy); game.addChild(enemy); } // Helper: spawn enemy bullet function spawnEnemyBullet(enemy, targetX, targetY) { var bullet = new EnemyBullet(); bullet.x = enemy.x; bullet.y = enemy.y + 60; // Aim at hero var dx = targetX - bullet.x; var dy = targetY - bullet.y; var len = Math.sqrt(dx * dx + dy * dy); if (len > 0) { bullet.speedX = dx / len * 18; bullet.speedY = dy / len * 18; } enemyBullets.push(bullet); game.addChild(bullet); LK.getSound('enemyShoot').play(); } // Move handler for dragging hero function handleMove(x, y, obj) { if (dragNode) { // Clamp hero inside screen var hw = dragNode.width / 2; var hh = dragNode.height / 2; var nx = Math.max(hw, Math.min(2048 - hw, x)); var ny = Math.max(hh + 100, Math.min(2732 - hh, y)); dragNode.x = nx; dragNode.y = ny; } } // Touch down: start dragging hero game.down = function (x, y, obj) { if (typeof menuActive !== "undefined" && menuActive) return; // PC: left mouse click triggers laser cannon if ready and not on menu if (obj && obj.event && obj.event.type === "mousedown" && obj.event.button === 0 && laserReady) { // Only fire if click is inside hero sprite (circle) var dx = x - hero.x; var dy = y - hero.y; if (dx * dx + dy * dy <= hero.radius * hero.radius) { // Activate laser laserReady = false; laserCooldown = laserCooldownMax; // Laser effect: fire a vertical laser column at hero.x var laserX = hero.x; // Visual effect: draw a vertical beam for a short time, and make it follow the hero var laserBeam = LK.getAsset('heroBullet', { anchorX: 0.5, anchorY: 1, x: laserX, y: hero.y - hero.height / 2 }); laserBeam.width = 80; laserBeam.height = hero.y - hero.height / 2; // from hero to top laserBeam.alpha = 0.45; game.addChild(laserBeam); // Store reference to active laser beam and set timer game.activeLaserBeam = laserBeam; game.activeLaserBeamTimer = 90; // 1.5 seconds at 60fps LK.getSound('laser').play(); // Destroy all enemies and enemy bullets in the column for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; if (Math.abs(e.x - laserX) <= 80) { LK.effects.flashObject(e, 0xffffff, 200); for (var pi = 0; pi < 12; pi++) { var part = LK.getAsset(e instanceof Enemy1 ? 'enemy1' : e instanceof Enemy2 ? 'enemy2' : 'enemy3', { anchorX: 0.5, anchorY: 0.5 }); part.x = e.x; part.y = e.y; part.width = 20 + Math.random() * 20; part.height = 20 + Math.random() * 20; part.alpha = 0.7 + Math.random() * 0.3; var angle = Math.PI * 2 * (pi / 12) + Math.random() * 0.2; var speed = 10 + Math.random() * 10; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; part.life = 10 + Math.floor(Math.random() * 10); part.update = function () { this.x += vx; this.y += vy; this.life--; this.alpha *= 0.88 + Math.random() * 0.06; if (this.life <= 0) { this.destroy(); } }; game.addChild(part); } // 35% chance to drop a health potion if Enemy3 if (e instanceof Enemy3 && Math.random() < 0.35) { var healthPotion = new HealthPotion(); healthPotion.x = e.x; healthPotion.y = e.y; items.push(healthPotion); game.addChild(healthPotion); } e.destroy(); enemies.splice(i, 1); } } for (var i = enemyBullets.length - 1; i >= 0; i--) { var b = enemyBullets[i]; if (Math.abs(b.x - laserX) <= 80) { b.destroy(); enemyBullets.splice(i, 1); } } return; } } dragNode = hero; handleMove(x, y, obj); }; // Touch up: stop dragging game.up = function (x, y, obj) { if (typeof menuActive !== "undefined" && menuActive) return; dragNode = null; }; // Touch move: move hero game.move = function (x, y, obj) { if (typeof menuActive !== "undefined" && menuActive) return; handleMove(x, y, obj); // Handle ulti button press (touch/click) if (ultiReady) { // Check if touch is inside ulti button area var dx = x - ultiBtn.x; var dy = y - ultiBtn.y; if (Math.abs(dx) <= ultiBtn.bg.width / 2 && Math.abs(dy) <= ultiBtn.bg.height / 2) { // Activate ulti ultiReady = false; ultiCooldown = ultiCooldownMax; ultiBtnOverlay.visible = true; // Ulti effect: clear all enemies and enemy bullets for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; if (e instanceof EnemyX) { // Ulti does 50 hits to EnemyX e.hp -= 50; LK.effects.flashObject(e, 0xffffff, 400); if (e.hp <= 0) { // Play death animation for EnemyX var enemyToDestroy = e; for (var pi = 0; pi < 48; pi++) { var part = LK.getAsset('enemyX', { anchorX: 0.5, anchorY: 0.5 }); part.x = enemyToDestroy.x; part.y = enemyToDestroy.y; part.width = 48 + Math.random() * 48; part.height = 48 + Math.random() * 48; part.alpha = 0.8 + Math.random() * 0.2; var angle = Math.PI * 2 * (pi / 48) + Math.random() * 0.2; var speed = 24 + Math.random() * 16; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; part.life = 32 + Math.floor(Math.random() * 32); part.update = function () { this.x += vx; this.y += vy; this.life--; this.alpha *= 0.90 + Math.random() * 0.04; if (this.life <= 0) { this.destroy(); } }; game.addChild(part); } // Add score for killing EnemyX with ulti score += 1; scoreTxt.setText(score); enemyToDestroy.destroy(); enemies.splice(i, 1); } } else { // Add score for killing normal enemies with ulti score += 1; scoreTxt.setText(score); enemies[i].destroy(); enemies.splice(i, 1); } } for (var i = enemyBullets.length - 1; i >= 0; i--) { enemyBullets[i].destroy(); enemyBullets.splice(i, 1); } LK.effects.flashScreen(0x00eaff, 600); return; } } // Handle laser cannon activation by clicking on the hero if (laserReady) { var dx = x - hero.x; var dy = y - hero.y; // Check if touch/click is inside hero sprite (circle) if (dx * dx + dy * dy <= hero.radius * hero.radius) { // Activate laser laserReady = false; laserCooldown = laserCooldownMax; // Laser effect: fire a vertical laser column at hero.x var laserX = hero.x; // Visual effect: draw a vertical beam for a short time, and make it follow the hero var laserBeam = LK.getAsset('heroBullet', { anchorX: 0.5, anchorY: 1, //{37} // anchor at bottom x: laserX, y: hero.y - hero.height / 2 }); laserBeam.width = 80; laserBeam.height = hero.y - hero.height / 2; // from hero to top laserBeam.alpha = 0.45; game.addChild(laserBeam); // Store reference to active laser beam and set timer game.activeLaserBeam = laserBeam; game.activeLaserBeamTimer = 90; // 1.5 seconds at 60fps LK.getSound('laser').play(); // Destroy all enemies and enemy bullets in the column for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; if (Math.abs(e.x - laserX) <= 80) { // Play death animation for each LK.effects.flashObject(e, 0xffffff, 200); // Particle effect for each for (var pi = 0; pi < 12; pi++) { var part = LK.getAsset(e instanceof Enemy1 ? 'enemy1' : e instanceof Enemy2 ? 'enemy2' : 'enemy3', { anchorX: 0.5, anchorY: 0.5 }); part.x = e.x; part.y = e.y; part.width = 20 + Math.random() * 20; part.height = 20 + Math.random() * 20; part.alpha = 0.7 + Math.random() * 0.3; var angle = Math.PI * 2 * (pi / 12) + Math.random() * 0.2; var speed = 10 + Math.random() * 10; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; part.life = 10 + Math.floor(Math.random() * 10); part.update = function () { this.x += vx; this.y += vy; this.life--; this.alpha *= 0.88 + Math.random() * 0.06; if (this.life <= 0) { this.destroy(); } }; game.addChild(part); } // 35% chance to drop a health potion if Enemy3 if (e instanceof Enemy3 && Math.random() < 0.35) { var healthPotion = new HealthPotion(); healthPotion.x = e.x; healthPotion.y = e.y; items.push(healthPotion); game.addChild(healthPotion); } e.destroy(); enemies.splice(i, 1); } } for (var i = enemyBullets.length - 1; i >= 0; i--) { var b = enemyBullets[i]; if (Math.abs(b.x - laserX) <= 80) { b.destroy(); enemyBullets.splice(i, 1); } } return; } } }; // Main game update game.update = function () { if (typeof menuActive !== "undefined" && menuActive) { // Block all game logic while menu is active return; } // Update hero hero.update(); // Laser beam follow logic if (game.activeLaserBeam) { // Move the beam to follow the hero's x and y, and always stretch from hero to top game.activeLaserBeam.x = hero.x; game.activeLaserBeam.y = hero.y - hero.height / 2; game.activeLaserBeam.height = hero.y - hero.height / 2; // Laser beam hits enemies it touches for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; // Check if enemy is within the laser beam's column (80px wide, same as beam) if (e.y + (e.height ? e.height / 2 : 60) >= 0 && // enemy is not above top e.y - (e.height ? e.height / 2 : 60) <= hero.y - hero.height / 2 && // enemy is not below beam bottom Math.abs(e.x - game.activeLaserBeam.x) <= game.activeLaserBeam.width / 2) { // Play hit sound and flash LK.getSound('enemyHit').play(); LK.effects.flashObject(e, 0xffffff, 200); // Score and handle Enemy3 HP score += 1; scoreTxt.setText(score); if (e instanceof Enemy3) { e.hp--; if (e.hp <= 0) { // Play death animation before destroying Enemy3 var enemyToDestroy = e; for (var pi = 0; pi < 24; pi++) { var part = LK.getAsset('enemy3', { anchorX: 0.5, anchorY: 0.5 }); part.x = enemyToDestroy.x; part.y = enemyToDestroy.y; part.width = 32 + Math.random() * 32; part.height = 32 + Math.random() * 32; part.alpha = 0.8 + Math.random() * 0.2; var angle = Math.PI * 2 * (pi / 24) + Math.random() * 0.2; var speed = 16 + Math.random() * 12; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; part.life = 16 + Math.floor(Math.random() * 16); part.update = function () { this.x += vx; this.y += vy; this.life--; this.alpha *= 0.90 + Math.random() * 0.04; if (this.life <= 0) { this.destroy(); } }; game.addChild(part); } // 35% chance to drop a health potion when Enemy3 is killed if (Math.random() < 0.35) { var healthPotion = new HealthPotion(); healthPotion.x = enemyToDestroy.x; healthPotion.y = enemyToDestroy.y; items.push(healthPotion); game.addChild(healthPotion); } enemyToDestroy.destroy(); enemies.splice(i, 1); } else { // Flash for hit, but don't destroy LK.effects.flashObject(e, 0x8e24aa, 120); } } else { // Play death animation before destroying normal enemies var enemyToDestroy = e; for (var pi = 0; pi < 16; pi++) { var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : 'enemy2', { anchorX: 0.5, anchorY: 0.5 }); part.x = enemyToDestroy.x; part.y = enemyToDestroy.y; part.width = 20 + Math.random() * 20; part.height = 20 + Math.random() * 20; part.alpha = 0.7 + Math.random() * 0.3; var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2; var speed = 10 + Math.random() * 10; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; part.life = 10 + Math.floor(Math.random() * 10); part.update = function () { this.x += vx; this.y += vy; this.life--; this.alpha *= 0.88 + Math.random() * 0.06; if (this.life <= 0) { this.destroy(); } }; game.addChild(part); } enemyToDestroy.destroy(); enemies.splice(i, 1); } } } // Decrement timer and destroy when done game.activeLaserBeamTimer--; if (game.activeLaserBeamTimer <= 0) { game.activeLaserBeam.destroy(); game.activeLaserBeam = null; } } // Ulti cooldown logic if (godMode) { ultiReady = true; ultiCooldown = 0; ultiBtnOverlay.visible = false; ultiBtn.text = "ULTI"; } else { if (!ultiReady) { ultiCooldown--; if (ultiCooldown <= 0) { ultiReady = true; ultiBtnOverlay.visible = false; } else { // Show overlay and update text to show seconds left ultiBtnOverlay.visible = true; ultiBtn.text = "ULTI\n" + Math.ceil(ultiCooldown / 60) + "s"; } } if (ultiReady) { ultiBtn.text = "ULTI"; ultiBtnOverlay.visible = false; } } // Update armor overlay position and visibility heroArmor.x = hero.x; heroArmor.y = hero.y; heroArmor.visible = shieldActive; // Laser cannon cooldown logic (no button UI) if (!laserReady) { laserCooldown--; if (laserCooldown <= 0) { laserReady = true; } } // Update shield/beam timers if (shieldActive) { shieldTimer--; if (shieldTimer <= 0) { shieldActive = false; } } if (beamActive) { beamTimer--; if (beamTimer <= 0) { beamActive = false; } } // Update items (powerups) for (var i = items.length - 1; i >= 0; i--) { var item = items[i]; item.update(); // Remove if off screen if (item.y > 2732 + 100) { item.destroy(); items.splice(i, 1); continue; } // Pickup by hero if (item.intersects(hero)) { if (item instanceof HealthPotion) { // Health potion always gives 1 health (if not at max) if (heroHealth < maxHealth) { heroHealth = Math.min(maxHealth, heroHealth + 1); updateHealthBar(); LK.effects.flashObject(hero, 0x44ff44, 400); } } else if (item instanceof ShieldItem) { // If already at max health, treat as shield if (heroHealth >= maxHealth) { shieldActive = true; shieldTimer = 360; // 6 seconds at 60fps LK.effects.flashObject(hero, 0x00ffff, 400); } else { // If not at max health, ignore shield pickup (health potions now handled separately) } } else if (item instanceof BeamItem) { beamActive = true; beamTimer = 180; // 3 seconds at 60fps LK.effects.flashObject(hero, 0xff00ff, 400); } item.destroy(); items.splice(i, 1); continue; } } // Hero shooting (auto-fire) if (hero.shootCooldown <= 0) { if (beamActive) { // Beam: fire 3 bullets in spread for (var bdir = -1; bdir <= 1; bdir++) { var bullet = new HeroBullet(); bullet.x = hero.x + bdir * 40; bullet.y = hero.y - hero.height / 2 - 20; bullet.spread = bdir * 0.18; // radians bullet.update = function (origUpdate, spread) { return function () { this.y += this.speed; this.x += Math.sin(spread) * 18; }; }(bullet.update, bullet.spread); heroBullets.push(bullet); game.addChild(bullet); } hero.shootCooldown = 6; LK.getSound('laser').play(); } else { var bullet = new HeroBullet(); bullet.x = hero.x; bullet.y = hero.y - hero.height / 2 - 20; heroBullets.push(bullet); game.addChild(bullet); hero.shootCooldown = 10; LK.getSound('laser').play(); } } // Update hero bullets for (var i = heroBullets.length - 1; i >= 0; i--) { var b = heroBullets[i]; b.update(); // Remove if off screen if (b.y < -60) { b.destroy(); heroBullets.splice(i, 1); continue; } // Check collision with enemies for (var j = enemies.length - 1; j >= 0; j--) { var e = enemies[j]; if (b.intersects(e)) { // Enemy hit LK.getSound('enemyHit').play(); score += 1; scoreTxt.setText(score); // Flash enemy LK.effects.flashObject(e, 0xffffff, 200); // Remove both or handle Enemy3/EnemyX hp if (e instanceof Enemy3 || e instanceof EnemyX) { e.hp--; if (e.hp <= 0) { // Play death animation before destroying Enemy3/EnemyX var enemyToDestroy = e; // Particle animation for Enemy3/EnemyX death (more particles, richer effect) var particleCount = e instanceof EnemyX ? 48 : 24; for (var pi = 0; pi < particleCount; pi++) { var part = LK.getAsset(e instanceof EnemyX ? 'enemyX' : 'enemy3', { anchorX: 0.5, anchorY: 0.5 }); part.x = enemyToDestroy.x; part.y = enemyToDestroy.y; part.width = (e instanceof EnemyX ? 48 : 32) + Math.random() * (e instanceof EnemyX ? 48 : 32); part.height = (e instanceof EnemyX ? 48 : 32) + Math.random() * (e instanceof EnemyX ? 48 : 32); part.alpha = 0.8 + Math.random() * 0.2; var angle = Math.PI * 2 * (pi / particleCount) + Math.random() * 0.2; var speed = (e instanceof EnemyX ? 24 : 16) + Math.random() * (e instanceof EnemyX ? 16 : 12); var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; part.life = (e instanceof EnemyX ? 32 : 16) + Math.floor(Math.random() * (e instanceof EnemyX ? 32 : 16)); part.update = function () { this.x += vx; this.y += vy; this.life--; this.alpha *= 0.90 + Math.random() * 0.04; if (this.life <= 0) { this.destroy(); } }; game.addChild(part); } // 35% chance to drop a health potion when Enemy3 is killed (not for EnemyX) if (e instanceof Enemy3 && Math.random() < 0.35) { var healthPotion = new HealthPotion(); healthPotion.x = enemyToDestroy.x; healthPotion.y = enemyToDestroy.y; items.push(healthPotion); game.addChild(healthPotion); } enemyToDestroy.destroy(); enemies.splice(j, 1); } else { // Flash for hit, but don't destroy LK.effects.flashObject(e, 0x8e24aa, 120); } b.destroy(); heroBullets.splice(i, 1); break; } else { b.destroy(); heroBullets.splice(i, 1); // Play death animation before destroying normal enemies var enemyToDestroy = e; // Particle animation for normal enemy death (more particles, richer effect) for (var pi = 0; pi < 16; pi++) { var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : 'enemy2', { anchorX: 0.5, anchorY: 0.5 }); part.x = enemyToDestroy.x; part.y = enemyToDestroy.y; part.width = 20 + Math.random() * 20; part.height = 20 + Math.random() * 20; part.alpha = 0.7 + Math.random() * 0.3; var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2; var speed = 10 + Math.random() * 10; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; part.life = 10 + Math.floor(Math.random() * 10); part.update = function () { this.x += vx; this.y += vy; this.life--; this.alpha *= 0.88 + Math.random() * 0.06; if (this.life <= 0) { this.destroy(); } }; game.addChild(part); } enemyToDestroy.destroy(); enemies.splice(j, 1); break; } } } } // Update enemies for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; e.update(); // Remove if off screen if (e.y > 2732 + 100) { e.destroy(); enemies.splice(i, 1); continue; } // Enemy shoots randomly if (Math.random() < 0.008) { spawnEnemyBullet(e, hero.x, hero.y); } // Check collision with hero if (e.intersects(hero)) { if (godMode) { // In god mode, ignore all damage and just destroy enemy enemies[i].destroy(); enemies.splice(i, 1); continue; } if (!shieldActive) { // Hero hit LK.getSound('heroHit').play(); LK.effects.flashScreen(0xff0000, 800); heroHealth--; updateHealthBar(); if (heroHealth <= 0) { LK.showGameOver(); return; } enemies[i].destroy(); enemies.splice(i, 1); continue; } else { // Shield absorbs hit, destroy enemy LK.effects.flashObject(hero, 0x00ffff, 200); // Play death animation before destroying enemy killed by shield var enemyToDestroy = e; // Particle animation for shield kill (more particles, richer effect) for (var pi = 0; pi < 16; pi++) { var part = LK.getAsset(enemyToDestroy instanceof Enemy1 ? 'enemy1' : enemyToDestroy instanceof Enemy2 ? 'enemy2' : 'enemy3', { anchorX: 0.5, anchorY: 0.5 }); part.x = enemyToDestroy.x; part.y = enemyToDestroy.y; part.width = 20 + Math.random() * 20; part.height = 20 + Math.random() * 20; part.alpha = 0.7 + Math.random() * 0.3; var angle = Math.PI * 2 * (pi / 16) + Math.random() * 0.2; var speed = 10 + Math.random() * 10; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; part.life = 10 + Math.floor(Math.random() * 10); part.update = function () { this.x += vx; this.y += vy; this.life--; this.alpha *= 0.88 + Math.random() * 0.06; if (this.life <= 0) { this.destroy(); } }; game.addChild(part); } enemyToDestroy.destroy(); enemies.splice(i, 1); continue; } } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var b = enemyBullets[i]; b.update(); // Remove if off screen if (b.y < -60 || b.y > 2732 + 60 || b.x < -60 || b.x > 2048 + 60) { b.destroy(); enemyBullets.splice(i, 1); continue; } // Check collision with hero if (b.intersects(hero)) { if (godMode) { // In god mode, ignore all damage and just destroy bullet b.destroy(); enemyBullets.splice(i, 1); continue; } if (!shieldActive) { LK.getSound('heroHit').play(); LK.effects.flashScreen(0xff0000, 800); heroHealth--; updateHealthBar(); if (heroHealth <= 0) { LK.showGameOver(); return; } b.destroy(); enemyBullets.splice(i, 1); continue; } else { // Shield absorbs bullet LK.effects.flashObject(hero, 0x00ffff, 120); b.destroy(); enemyBullets.splice(i, 1); continue; } } } // --- ENEMY SPAWN RATE BOOST LOGIC --- if (typeof spawnRateBoostActive === "undefined") { var spawnRateBoostActive = false; var spawnRateBoostTimer = 0; var nextBoostScore = 50; var spawnIntervalNormal = 60; var spawnIntervalBoost = 30; } // Check if we reached a new boost score (50, 150, 250, ...) and trigger boost if (score >= nextBoostScore && !spawnRateBoostActive) { spawnRateBoostActive = true; spawnRateBoostTimer = 180; // 3 seconds at 60fps // After 50, next is 150, then 250, 350, ... if (nextBoostScore === 50) { nextBoostScore = 150; } else { nextBoostScore += 100; } } // Handle boost timer if (spawnRateBoostActive) { spawnRateBoostTimer--; if (spawnRateBoostTimer <= 0) { spawnRateBoostActive = false; } } // Spawn enemies spawnTick++; // Use boosted or normal interval // Make spawn rate scale more slowly with score (easier): decrease by 2 per 20 score, not 4 per 10 var spawnInterval = spawnRateBoostActive ? spawnIntervalBoost : Math.max(18, spawnIntervalNormal - Math.floor(score / 20) * 2); // Slower scaling for easier game if (score < 250) { if (spawnTick >= spawnInterval) { // Calculate how many enemies to spawn based on score (1 + 1 per 50 score) var numEnemies = 1 + Math.floor(score / 50); for (var i = 0; i < numEnemies; i++) { spawnEnemy(); } // 1 in 8 chance to spawn an item if (Math.random() < 0.125) { spawnItem(); } spawnTick = 0; } } else if (score >= 250) { // Stop current music and play boss music when score passes 250 if (typeof bossMusicPlayed === "undefined") { var bossMusicPlayed = false; } if (!bossMusicPlayed) { LK.stopMusic(); LK.playMusic('Boss'); bossMusicPlayed = true; } if (spawnTick >= spawnInterval) { // Only spawn extraordinary enemy (EnemyX) at 250+ score, and only once if (!enemyXSpawned) { var enemy = new EnemyX(); enemy.x = 200 + Math.random() * (2048 - 400); enemy.y = -80; enemies.push(enemy); game.addChild(enemy); enemyXSpawned = true; } spawnTick = 0; } } };
===================================================================
--- original.js
+++ change.js
@@ -753,12 +753,18 @@
}
};
game.addChild(part);
}
+ // Add score for killing EnemyX with ulti
+ score += 1;
+ scoreTxt.setText(score);
enemyToDestroy.destroy();
enemies.splice(i, 1);
}
} else {
+ // Add score for killing normal enemies with ulti
+ score += 1;
+ scoreTxt.setText(score);
enemies[i].destroy();
enemies.splice(i, 1);
}
}
A power core with electricity and blue lights. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A blue space ship with laser gun and powerful engines. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A shiny purple crystal. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A red winged alien with exoskeleton. . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A tiny green alien with spikes. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A strong yellow-white alien with horns. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A king yellow alien with black and white stripes and wings. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Neboula background. In-Game asset. 2d. High contrast. No shadows. Cinematic deep
A blue button. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A dark green alien with a gray orb above it. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A dark green alien boss with two gray orbs around it. On top it has a green crown. Has light gray stripes. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A futuristic scoreboard tablet with blue and cyan colors. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat