User prompt
Don't make the screen yellow when laser cannon is shot
User prompt
Make the column laser move with the hero
User prompt
Remove the laser button and shoot the laser cannon by clicking on the hero
User prompt
Fix the bug in a diffrent way
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(laserBeam).to({' Line Number: 581
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(laserBeam).to({' Line Number: 580
User prompt
Fix bug: ensure tween is defined and used correctly for laser beam fade
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(laserBeam).to({' Line Number: 578
User prompt
Please fix the bug: 'Uncaught TypeError: tween.to is not a function' in or related to this line: 'tween.to(laserBeam, {' Line Number: 578
User prompt
Add a laser cannon button that shoots in a full column
User prompt
Seperate it as the asset
User prompt
Sperate the health potion asset
User prompt
Enemy3 drops potion to the bottom
User prompt
Health potion gives 1 health
User prompt
Enemy3 drops a health potion per %35 change when killed.
User prompt
Make the health bar visible at left bottom corner
User prompt
Make the health bar visible at right bottom corner
User prompt
Add an health bar and give me 6 health, so i can die with 6 hits.
User prompt
Add a button for closing and opening the music in menu
User prompt
Then make the ticks go down not so faster so the game would be a little bit more easy
User prompt
Make it first 50 score then 150, 250, 350, onwards
User prompt
Make it 30 ticks and 3 seconds
User prompt
After hitting 50 score, when 4 second is passed reduce the enemy spawn rate to normal again do this for every 50 score
Code edit (1 edits merged)
Please save this source code
User prompt
In every 50 score more enemies will come after 5 seconds it will be normal again
/**** * 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 }); 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 }); 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 }); 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; }); // 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 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 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 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 menuOverlay.visible = false; menuActive = false; LK.stopMusic(); LK.playMusic('bgmusic'); } }; 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); // Game variables var hero = new Hero(); game.addChild(hero); hero.x = 2048 / 2; hero.y = 2732 - 350; // 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); // 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; 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--) { 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); } } }; // Main game update game.update = function () { if (typeof menuActive !== "undefined" && menuActive) { // Block all game logic while menu is active return; } // Update hero hero.update(); // Ulti cooldown logic 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; // 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 ShieldItem) { shieldActive = true; shieldTimer = 360; // 6 seconds at 60fps LK.effects.flashObject(hero, 0x00ffff, 400); } 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 hp if (e instanceof Enemy3) { e.hp--; if (e.hp <= 0) { // Play death animation before destroying Enemy3 var enemyToDestroy = e; // Particle animation for Enemy3 death (more particles, richer effect) 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); } 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 (!shieldActive) { // Hero hit LK.getSound('heroHit').play(); LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } 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 (!shieldActive) { LK.getSound('heroHit').play(); LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } else { // Shield absorbs bullet LK.effects.flashObject(hero, 0x00ffff, 120); b.destroy(); enemyBullets.splice(i, 1); continue; } } } // --- More enemies every 50 score for 5 seconds logic --- if (typeof moreEnemiesActive === "undefined") { moreEnemiesActive = false; } if (typeof moreEnemiesTimer === "undefined") { moreEnemiesTimer = 0; } if (typeof lastScore50 === "undefined") { lastScore50 = 0; } // Check if we just crossed a new 50-multiple score (but not at 0) if (score > 0 && score % 50 === 0 && lastScore50 !== score) { moreEnemiesActive = true; moreEnemiesTimer = 300; // 5 seconds at 60fps lastScore50 = score; } if (moreEnemiesActive) { moreEnemiesTimer--; if (moreEnemiesTimer <= 0) { moreEnemiesActive = false; } } // Spawn enemies spawnTick++; var spawnInterval = Math.max(18, 60 - Math.floor(score / 10) * 4); // Faster as score increases // Boss logic if (typeof bossSpawned === "undefined") { bossSpawned = false; } if (score >= 250 && !bossSpawned) { // Spawn boss here (replace with actual Boss class if available) // Example: var boss = new Boss(); boss.x = 2048/2; boss.y = -200; game.addChild(boss); bossSpawned = true; // No enemies or items spawn when boss is present } if (!bossSpawned || 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); if (moreEnemiesActive) { numEnemies += 2; // Add 2 more enemies during the 5 seconds } for (var i = 0; i < numEnemies; i++) { spawnEnemy(); } // 1 in 8 chance to spawn an item if (Math.random() < 0.125) { spawnItem(); } spawnTick = 0; } } };
/****
* 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
});
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
});
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
});
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;
});
// 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
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 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
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
menuOverlay.visible = false;
menuActive = false;
LK.stopMusic();
LK.playMusic('bgmusic');
}
};
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);
// Game variables
var hero = new Hero();
game.addChild(hero);
hero.x = 2048 / 2;
hero.y = 2732 - 350;
// 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);
// 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;
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--) {
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);
}
}
};
// Main game update
game.update = function () {
if (typeof menuActive !== "undefined" && menuActive) {
// Block all game logic while menu is active
return;
}
// Update hero
hero.update();
// Ulti cooldown logic
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;
// 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 ShieldItem) {
shieldActive = true;
shieldTimer = 360; // 6 seconds at 60fps
LK.effects.flashObject(hero, 0x00ffff, 400);
} 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 hp
if (e instanceof Enemy3) {
e.hp--;
if (e.hp <= 0) {
// Play death animation before destroying Enemy3
var enemyToDestroy = e;
// Particle animation for Enemy3 death (more particles, richer effect)
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);
}
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 (!shieldActive) {
// Hero hit
LK.getSound('heroHit').play();
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
} 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 (!shieldActive) {
LK.getSound('heroHit').play();
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
} else {
// Shield absorbs bullet
LK.effects.flashObject(hero, 0x00ffff, 120);
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
}
}
// --- More enemies every 50 score for 5 seconds logic ---
if (typeof moreEnemiesActive === "undefined") {
moreEnemiesActive = false;
}
if (typeof moreEnemiesTimer === "undefined") {
moreEnemiesTimer = 0;
}
if (typeof lastScore50 === "undefined") {
lastScore50 = 0;
}
// Check if we just crossed a new 50-multiple score (but not at 0)
if (score > 0 && score % 50 === 0 && lastScore50 !== score) {
moreEnemiesActive = true;
moreEnemiesTimer = 300; // 5 seconds at 60fps
lastScore50 = score;
}
if (moreEnemiesActive) {
moreEnemiesTimer--;
if (moreEnemiesTimer <= 0) {
moreEnemiesActive = false;
}
}
// Spawn enemies
spawnTick++;
var spawnInterval = Math.max(18, 60 - Math.floor(score / 10) * 4); // Faster as score increases
// Boss logic
if (typeof bossSpawned === "undefined") {
bossSpawned = false;
}
if (score >= 250 && !bossSpawned) {
// Spawn boss here (replace with actual Boss class if available)
// Example: var boss = new Boss(); boss.x = 2048/2; boss.y = -200; game.addChild(boss);
bossSpawned = true;
// No enemies or items spawn when boss is present
}
if (!bossSpawned || 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);
if (moreEnemiesActive) {
numEnemies += 2; // Add 2 more enemies during the 5 seconds
}
for (var i = 0; i < numEnemies; i++) {
spawnEnemy();
}
// 1 in 8 chance to spawn an item
if (Math.random() < 0.125) {
spawnItem();
}
spawnTick = 0;
}
}
};
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