User prompt
Use POWERUP as powerup drops
User prompt
Make a go back to level 1 button under settings
User prompt
Too big asset... i said not too big
User prompt
Make player bullet asset a lot bigger but not too big and make minibosses easier
User prompt
Make controls default to left
User prompt
Remove skip tutorial and play tutorial no matter what
User prompt
Put settings in top right and just do tutorial without skip stuff
User prompt
I meant the skip tutorial button not settings put it back and move skip tutorial button (also it skipped tutorial and I didn't even press it)
User prompt
Put it in top left for that button
User prompt
Instead of skip tutorial in settings what about a button for it during tutorial
User prompt
Make a left hand or right hand selector in a settings tab that pauses game for left or right hand placing for move buttons and other settings. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Make up/down/left/right buttons bigger
User prompt
Make arrow buttons to move instead of dragging
Code edit (1 edits merged)
Please save this source code
User prompt
Boss Blitz: Escalating Challenge
User prompt
Make bosses after 2 mini-bosses for first 2 levels and then the other ones are bosses. Make bosses and mini-bosswes get harder every time
Initial prompt
Space shooter game
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { currentLevel: 1, maxLevelReached: 1, playerPowerups: {}, controlsOnRight: true }); /**** * Classes ****/ var Boss = Container.expand(function (type, level) { var self = Container.call(this); self.type = type || 'miniBoss1'; self.level = level || 1; var bossGraphics = self.attachAsset(self.type, { anchorX: 0.5, anchorY: 0.5 }); // Boss stats scale with level self.health = 100 * self.level; self.maxHealth = self.health; self.speed = 3 + self.level * 0.5; self.shootCooldown = 0; self.shootDelay = Math.max(30 - self.level * 5, 10); // Faster shooting at higher levels self.attackPattern = 0; self.phaseCounter = 0; self.phases = ['entry', 'attack1', 'movement', 'attack2', 'rage']; self.currentPhase = 'entry'; self.phaseTimer = 180; // 3 seconds per phase self.moveDirection = 1; self.targetX = 2048 / 2; self.targetY = 300; // Define movement patterns based on boss type self.patterns = { miniBoss1: { entry: function entry() { if (self.y < self.targetY) { self.y += self.speed; } else { self.changePhase('attack1'); } }, attack1: function attack1() { // Simple straight shots if (self.shootCooldown <= 0) { self.shootBullets(); self.shootCooldown = self.shootDelay; } // Move side to side self.x += self.speed * self.moveDirection; if (self.x > 1800 || self.x < 248) { self.moveDirection *= -1; } }, movement: function movement() { // Circle pattern self.x = self.targetX + Math.cos(self.phaseCounter / 30) * 300; self.y = self.targetY + Math.sin(self.phaseCounter / 30) * 100; }, attack2: function attack2() { // Spread shots if (self.shootCooldown <= 0) { self.shootSpread(5, 0.2); self.shootCooldown = self.shootDelay * 2; } }, rage: function rage() { // Fast movements and frequent attacks self.x += self.speed * 1.5 * self.moveDirection; if (self.x > 1800 || self.x < 248) { self.moveDirection *= -1; } if (self.shootCooldown <= 0) { self.shootSpread(3, 0.3); self.shootCooldown = self.shootDelay / 2; } } }, miniBoss2: { entry: function entry() { if (self.y < self.targetY) { self.y += self.speed; } else { self.changePhase('attack1'); } }, attack1: function attack1() { // Laser attacks if (self.shootCooldown <= 0) { self.shootLaser(); self.shootCooldown = self.shootDelay * 3; } // Slow tracking if (player && self.phaseCounter % 30 === 0) { self.targetX = player.x; } self.x += (self.targetX - self.x) * 0.02; }, movement: function movement() { // Quick dash to one side then the other if (self.phaseCounter < self.phaseTimer / 2) { self.x += self.speed * 2; } else { self.x -= self.speed * 2; } // Keep in bounds self.x = Math.max(200, Math.min(1848, self.x)); }, attack2: function attack2() { // Circular bullet pattern if (self.shootCooldown <= 0) { self.shootCircle(8); self.shootCooldown = self.shootDelay * 2; } }, rage: function rage() { // Erratic movement and mixed attacks self.x = self.targetX + Math.sin(self.phaseCounter / 10) * 300; if (self.shootCooldown <= 0) { if (self.phaseCounter % 120 < 60) { self.shootSpread(7, 0.15); } else { self.shootLaser(); } self.shootCooldown = self.shootDelay; } } }, boss1: { // More complex patterns for main bosses entry: function entry() { if (self.y < self.targetY) { self.y += self.speed; } else { self.changePhase('attack1'); } }, attack1: function attack1() { // Wave pattern with bursts of bullets self.x = self.targetX + Math.sin(self.phaseCounter / 20) * 400; if (self.shootCooldown <= 0) { if (self.phaseCounter % 60 < 30) { self.shootBullets(); } else { self.shootSpread(3, 0.2); } self.shootCooldown = self.shootDelay; } }, movement: function movement() { // Quick charge toward player if (player && self.phaseCounter % 60 === 0) { self.targetX = player.x; self.targetY = player.y - 300; } self.x += (self.targetX - self.x) * 0.05; self.y += (self.targetY - self.y) * 0.05; // Don't get too close to player self.y = Math.min(self.y, 500); }, attack2: function attack2() { // Laser attacks with bullet spray if (self.shootCooldown <= 0) { if (self.phaseCounter % 120 < 60) { self.shootLaser(); } else { self.shootCircle(12); } self.shootCooldown = self.shootDelay * 1.5; } // Slow side-to-side movement self.x += Math.sin(self.phaseCounter / 30) * 5; }, rage: function rage() { // Fast erratic movement with constant attacks self.x = self.targetX + Math.sin(self.phaseCounter / 10) * 300 + Math.cos(self.phaseCounter / 15) * 200; self.y = self.targetY + Math.sin(self.phaseCounter / 12) * 100; if (self.shootCooldown <= 0) { // Alternate between different attack patterns switch (Math.floor(self.phaseCounter / 40) % 3) { case 0: self.shootSpread(5, 0.15); break; case 1: self.shootLaser(); break; case 2: self.shootCircle(8); break; } self.shootCooldown = self.shootDelay * 0.7; } } }, boss2: { // Similar structure, different patterns entry: function entry() { if (self.y < self.targetY) { self.y += self.speed; } else { self.changePhase('attack1'); } }, attack1: function attack1() { // Spiral bullet pattern if (self.shootCooldown <= 0) { self.shootSpiral(self.phaseCounter / 10); self.shootCooldown = Math.max(5, self.shootDelay / 2); } // Slow rotation around center self.x = self.targetX + Math.cos(self.phaseCounter / 60) * 200; self.y = self.targetY + Math.sin(self.phaseCounter / 60) * 100; }, movement: function movement() { // Quick teleport movements if (self.phaseCounter % 60 === 0) { // Flash effect for teleport LK.effects.flashObject(self, 0xFFFFFF, 200); // Choose random position in top third of screen self.targetX = 300 + Math.random() * (2048 - 600); self.targetY = 150 + Math.random() * 250; } // Quick movement to target self.x += (self.targetX - self.x) * 0.1; self.y += (self.targetY - self.y) * 0.1; }, attack2: function attack2() { // Multiple lasers if (self.shootCooldown <= 0) { for (var i = 0; i < 3; i++) { var offset = (i - 1) * 200; self.shootLaser(offset); } self.shootCooldown = self.shootDelay * 2; } // Small jittery movements self.x += (Math.random() - 0.5) * 10; self.y += (Math.random() - 0.5) * 5; // Keep in bounds self.x = Math.max(200, Math.min(1848, self.x)); self.y = Math.max(100, Math.min(500, self.y)); }, rage: function rage() { // Screen-filling attacks and fast movement if (self.shootCooldown <= 0) { // Alternate between massive spreads and laser curtains if (self.phaseCounter % 180 < 90) { self.shootSpread(15, 0.1); } else { for (var i = 0; i < 5; i++) { var offset = (i - 2) * 150; self.shootLaser(offset); } } self.shootCooldown = self.shootDelay * 0.6; } // Aggressive tracking of player if (player) { self.targetX = player.x; self.x += (self.targetX - self.x) * 0.03; } // Vertical bobbing self.y = self.targetY + Math.sin(self.phaseCounter / 20) * 100; } }, boss3: { // More extreme patterns entry: function entry() { if (self.y < self.targetY) { self.y += self.speed; } else { self.changePhase('attack1'); } }, attack1: function attack1() { // 360-degree bullet hell if (self.shootCooldown <= 0) { self.shootCircle(16); self.shootCooldown = self.shootDelay; } // Slow pulsing movement self.x = self.targetX + Math.sin(self.phaseCounter / 30) * 300; self.y = self.targetY + Math.cos(self.phaseCounter / 30) * 100; }, movement: function movement() { // Aggressive dash toward player position then retreat if (self.phaseCounter % 90 < 45 && player) { // Dash toward player self.targetX = player.x; self.targetY = player.y - 150; self.x += (self.targetX - self.x) * 0.08; self.y += (self.targetY - self.y) * 0.08; } else { // Retreat to top self.targetY = 250; self.y += (self.targetY - self.y) * 0.05; } }, attack2: function attack2() { // Multiple attack types simultaneously if (self.shootCooldown <= 0) { // Lasers + bullets combo self.shootLaser(0); self.shootSpread(9, 0.15); self.shootCooldown = self.shootDelay * 1.2; } // Side-to-side sweep self.x += self.speed * 2 * self.moveDirection; if (self.x > 1800 || self.x < 248) { self.moveDirection *= -1; } }, rage: function rage() { // Total bullet hell mode if (self.shootCooldown <= 0) { // Spiral + lasers + directed shots self.shootSpiral(self.phaseCounter / 5); if (self.phaseCounter % 60 === 0) { // Multiple lasers in fan pattern for (var i = -2; i <= 2; i++) { self.shootLaser(i * 120); } } // Direct shots at player if (player && self.phaseCounter % 30 === 0) { self.shootAtPlayer(); } self.shootCooldown = Math.max(3, self.shootDelay / 3); } // Chaotic movement self.x = self.targetX + Math.sin(self.phaseCounter / 10) * 400 + Math.cos(self.phaseCounter / 7) * 200; self.y = self.targetY + Math.sin(self.phaseCounter / 8) * 150; } } }; // Shooting methods self.shootBullets = function () { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + 50; bullet.angle = Math.PI / 2; // Straight down bullets.push(bullet); game.addChild(bullet); }; self.shootSpread = function (count, spreadAngle) { var startAngle = Math.PI / 2 - spreadAngle * (count - 1) / 2; for (var i = 0; i < count; i++) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + 50; bullet.angle = startAngle + spreadAngle * i; bullets.push(bullet); game.addChild(bullet); } }; self.shootCircle = function (count) { var angleStep = Math.PI * 2 / count; for (var i = 0; i < count; i++) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; bullet.angle = angleStep * i; bullets.push(bullet); game.addChild(bullet); } }; self.shootSpiral = function (baseAngle) { var count = 8; var angleStep = Math.PI * 2 / count; for (var i = 0; i < count; i++) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; bullet.angle = baseAngle + angleStep * i; bullets.push(bullet); game.addChild(bullet); } }; self.shootLaser = function (xOffset) { xOffset = xOffset || 0; var laser = new EnemyLaser(); laser.x = self.x + xOffset; laser.y = self.y; lasers.push(laser); game.addChild(laser); }; self.shootAtPlayer = function () { if (!player) return; var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + 50; // Calculate angle to player var dx = player.x - self.x; var dy = player.y - self.y; bullet.angle = Math.atan2(dy, dx); bullets.push(bullet); game.addChild(bullet); }; self.changePhase = function (newPhase) { self.currentPhase = newPhase; self.phaseCounter = 0; // Adjust phase timer based on phase if (newPhase === 'rage') { self.phaseTimer = 360; // Longer rage phase } else { self.phaseTimer = 180; // Normal phases } }; self.takeDamage = function (damage) { self.health -= damage; // Flash boss when hit LK.effects.flashObject(bossGraphics, 0xFFFFFF, 200); LK.getSound('bossHit').play(); // Check for phase change based on health percentage var healthPercent = self.health / self.maxHealth; if (healthPercent <= 0.25 && self.currentPhase !== 'rage') { self.changePhase('rage'); } else if (healthPercent <= 0.5 && self.currentPhase !== 'rage' && self.currentPhase !== 'attack2') { self.changePhase('attack2'); } else if (healthPercent <= 0.75 && self.currentPhase !== 'rage' && self.currentPhase !== 'attack2' && self.currentPhase !== 'movement') { self.changePhase('movement'); } return self.health <= 0; }; self.update = function () { // Update based on current phase if (self.patterns[self.type] && self.patterns[self.type][self.currentPhase]) { self.patterns[self.type][self.currentPhase](); } // Update counters self.phaseCounter++; if (self.shootCooldown > 0) { self.shootCooldown--; } // Check for phase timeout if (self.phaseCounter >= self.phaseTimer && self.currentPhase !== 'rage' && self.health > self.maxHealth * 0.25) { // Cycle to next phase var currentPhaseIndex = self.phases.indexOf(self.currentPhase); var nextPhaseIndex = (currentPhaseIndex + 1) % (self.phases.length - 1); // Skip rage phase self.changePhase(self.phases[nextPhaseIndex]); } }; return self; }); var ControlButton = Container.expand(function (direction) { var self = Container.call(this); // Different color for each direction button var color; switch (direction) { case 'up': color = 0x4285F4; break; // Blue case 'down': color = 0xEA4335; break; // Red case 'left': color = 0xFBBC05; break; // Yellow case 'right': color = 0x34A853; break; // Green default: color = 0xFFFFFF; // White } // Create button shape var buttonGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); // Set button color buttonGraphics.tint = color; // Arrow display (using text as a simple way to show direction) var arrowSymbol; switch (direction) { case 'up': arrowSymbol = '▲'; break; case 'down': arrowSymbol = '▼'; break; case 'left': arrowSymbol = '◀'; break; case 'right': arrowSymbol = '▶'; break; default: arrowSymbol = '•'; } var arrow = new Text2(arrowSymbol, { size: 60, fill: 0xFFFFFF }); arrow.anchor.set(0.5, 0.5); self.addChild(arrow); // Store direction for later use self.direction = direction; // Handle button press self.down = function (x, y, obj) { // Visual feedback - shrink slightly when pressed buttonGraphics.scale.set(1.1); // Start moving in this direction if (player && gameState === 'playing') { movePlayer(self.direction, true); } }; // Handle button release self.up = function (x, y, obj) { // Visual feedback - return to normal size buttonGraphics.scale.set(1.2); // Stop moving in this direction if (player && gameState === 'playing') { movePlayer(self.direction, false); } }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 1; self.angle = 0; // Direction in radians self.update = function () { self.x += Math.cos(self.angle) * self.speed; self.y += Math.sin(self.angle) * self.speed; // Remove if off screen if (self.y > 2732 + 50 || self.y < -50 || self.x > 2048 + 50 || self.x < -50) { self.shouldRemove = true; } }; return self; }); var EnemyLaser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('enemyLaser', { anchorX: 0.5, anchorY: 0 }); self.damage = 2; self.duration = 120; // 2 seconds at 60fps self.counter = 0; self.warningCounter = 60; // 1 second warning // Start with low alpha for warning laserGraphics.alpha = 0.3; self.update = function () { self.counter++; if (self.counter < self.warningCounter) { // Warning phase if (self.counter % 10 < 5) { laserGraphics.alpha = 0.5; } else { laserGraphics.alpha = 0.3; } } else if (self.counter === self.warningCounter) { // Activate laser laserGraphics.alpha = 0.8; // Expand width tween(laserGraphics, { width: 80 }, { duration: 100 }); } else if (self.counter >= self.duration) { // Remove laser self.shouldRemove = true; } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.shootCooldown = 0; self.shootDelay = 15; // 4 shots per second self.health = 100; self.maxHealth = 100; self.invincible = false; self.invincibleTimer = 0; self.shield = null; self.powerups = {}; // Track movement directions self.moving = { up: false, down: false, left: false, right: false }; // Initialize shield (hidden at first) self.createShield = function () { if (self.shield) return; self.shield = self.attachAsset('playerShield', { anchorX: 0.5, anchorY: 0.5 }); self.shield.alpha = 0; }; self.activateShield = function (duration) { if (!self.shield) self.createShield(); self.shield.alpha = 0.7; self.invincible = true; // Fade out shield over duration tween(self.shield, { alpha: 0 }, { duration: duration, onFinish: function onFinish() { self.invincible = false; } }); }; self.takeDamage = function (damage) { if (self.invincible) return false; self.health -= damage; if (self.health <= 0) { self.health = 0; return true; // Player died } // Flash player and make invincible briefly LK.effects.flashObject(playerGraphics, 0xFF0000, 500); self.invincible = true; self.invincibleTimer = 60; // 1 second invincibility LK.getSound('playerHit').play(); return false; // Player alive }; self.shoot = function () { if (self.shootCooldown > 0) return null; var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - 40; // Apply powerups if (self.powerups.doubleDamage) { bullet.damage *= 2; bullet.tint = 0xFFFF00; // Yellow for double damage } // Triple shot powerup if (self.powerups.tripleShot) { // Create two additional bullets var bulletLeft = new PlayerBullet(); bulletLeft.x = self.x - 30; bulletLeft.y = self.y - 20; var bulletRight = new PlayerBullet(); bulletRight.x = self.x + 30; bulletRight.y = self.y - 20; self.shootCooldown = self.shootDelay; LK.getSound('playerShoot').play(); return [bullet, bulletLeft, bulletRight]; } self.shootCooldown = self.shootDelay; LK.getSound('playerShoot').play(); return [bullet]; }; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } if (self.invincible && self.invincibleTimer > 0) { self.invincibleTimer--; if (self.invincibleTimer <= 0) { self.invincible = false; } } // Handle movement based on pressed direction buttons if (gameState === 'playing') { if (self.moving.up) { self.y -= self.speed; } if (self.moving.down) { self.y += self.speed; } if (self.moving.left) { self.x -= self.speed; } if (self.moving.right) { self.x += self.speed; } // Keep player within screen bounds self.x = Math.max(50, Math.min(2048 - 50, self.x)); self.y = Math.max(100, Math.min(2732 - 100, self.y)); } }; self.down = function (x, y, obj) { // This is handled in the game's touch handler }; self.up = function (x, y, obj) { // This is handled in the game's touch handler }; self.createShield(); return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.damage = 1; self.update = function () { self.y -= self.speed; // Remove if off screen if (self.y < -50) { self.shouldRemove = true; } }; return self; }); var PowerUp = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'shield'; var color; switch (self.type) { case 'shield': color = 0x00FFFF; break; case 'doubleDamage': color = 0xFFFF00; break; case 'tripleShot': color = 0xFF00FF; break; default: color = 0xFFFFFF; } var powerupGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); // Set color based on powerup type powerupGraphics.tint = color; self.speed = 3; self.duration = type === 'shield' ? 300 : 600; // Shield lasts 5 seconds, others 10 self.update = function () { self.y += self.speed; // Remove if off screen if (self.y > 2732 + 50) { self.shouldRemove = true; } }; self.applyEffect = function (player) { LK.getSound('powerUp').play(); switch (self.type) { case 'shield': player.activateShield(5000); // 5 seconds break; case 'doubleDamage': player.powerups.doubleDamage = true; // Clear previous timeout if exists if (player.powerups.doubleDamageTimer) { LK.clearTimeout(player.powerups.doubleDamageTimer); } // Set timeout to clear powerup player.powerups.doubleDamageTimer = LK.setTimeout(function () { player.powerups.doubleDamage = false; }, 10000); // 10 seconds break; case 'tripleShot': player.powerups.tripleShot = true; // Clear previous timeout if exists if (player.powerups.tripleShotTimer) { LK.clearTimeout(player.powerups.tripleShotTimer); } // Set timeout to clear powerup player.powerups.tripleShotTimer = LK.setTimeout(function () { player.powerups.tripleShot = false; }, 10000); // 10 seconds break; } self.shouldRemove = true; }; return self; }); var SettingsPanel = Container.expand(function () { var self = Container.call(this); // Semi-transparent black background var background = LK.getAsset('bossHealthBarBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 10, scaleY: 20 }); background.tint = 0x000000; background.alpha = 0.8; self.addChild(background); // Title var titleText = new Text2('SETTINGS', { size: 100, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.y = -900; self.addChild(titleText); // Control layout option var controlsText = new Text2('CONTROLS LAYOUT:', { size: 70, fill: 0xFFFFFF }); controlsText.anchor.set(0.5, 0.5); controlsText.y = -700; self.addChild(controlsText); // Left hand option var leftHandButton = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1.5 }); leftHandButton.tint = storage.controlsOnRight ? 0x666666 : 0x4285F4; leftHandButton.x = -250; leftHandButton.y = -550; self.addChild(leftHandButton); var leftHandText = new Text2('LEFT HAND', { size: 50, fill: 0xFFFFFF }); leftHandText.anchor.set(0.5, 0.5); leftHandText.x = -250; leftHandText.y = -550; self.addChild(leftHandText); // Right hand option var rightHandButton = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1.5 }); rightHandButton.tint = storage.controlsOnRight ? 0x4285F4 : 0x666666; rightHandButton.x = 250; rightHandButton.y = -550; self.addChild(rightHandButton); var rightHandText = new Text2('RIGHT HAND', { size: 50, fill: 0xFFFFFF }); rightHandText.anchor.set(0.5, 0.5); rightHandText.x = 250; rightHandText.y = -550; self.addChild(rightHandText); // No skip tutorial option - removed // Close button var closeButton = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1.5 }); closeButton.tint = 0xEA4335; closeButton.y = 200; self.addChild(closeButton); var closeText = new Text2('CLOSE', { size: 50, fill: 0xFFFFFF }); closeText.anchor.set(0.5, 0.5); closeText.y = 200; self.addChild(closeText); // Button interaction handlers leftHandButton.interactive = true; leftHandButton.down = function () { if (storage.controlsOnRight) { storage.controlsOnRight = false; leftHandButton.tint = 0x4285F4; rightHandButton.tint = 0x666666; if (typeof repositionControlButtons === 'function') { repositionControlButtons(); } } }; rightHandButton.interactive = true; rightHandButton.down = function () { if (!storage.controlsOnRight) { storage.controlsOnRight = true; rightHandButton.tint = 0x4285F4; leftHandButton.tint = 0x666666; if (typeof repositionControlButtons === 'function') { repositionControlButtons(); } } }; // No skip tutorial button handler - removed closeButton.interactive = true; closeButton.down = function () { if (self.parent) { self.parent.removeChild(self); if (gameState === 'paused') { resumeGame(); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Background music // Sound effects // Health bars and UI // Boss projectiles // Main bosses // Mini bosses // Player, bosses, projectiles, UI elements, and effects // Core game variables var player; var currentBoss; var bullets = []; var lasers = []; var playerBullets = []; var powerups = []; var currentLevel = storage.currentLevel || 1; var gameState = 'tutorial'; // tutorial, playing, bossDead, gameOver var tutorialStep = 0; var lastShootTime = 0; var controlButtons = []; // UI Elements var scoreText; var levelText; var playerHealthBar; var playerHealthBarBg; var bossHealthBar; var bossHealthBarBg; var tutorialText; // Initialize game function initGame() { // Background game.setBackgroundColor(0x111133); // Create player player = new Player(); player.x = 2048 / 2; player.y = 2732 - 200; game.addChild(player); // Initialize UI createUI(); // Always start with tutorial if first level if (currentLevel === 1) { showTutorial(); } else { startLevel(); } // Play background music LK.playMusic('battleMusic'); } function createUI() { // Score and level display scoreText = new Text2('SCORE: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.top.addChild(scoreText); scoreText.x = 150; scoreText.y = 30; levelText = new Text2('LEVEL ' + currentLevel, { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(1, 0); LK.gui.topRight.addChild(levelText); levelText.x = -50; levelText.y = 30; // Add settings button in top right corner var settingsButton = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); settingsButton.tint = 0x999999; settingsButton.x = 2048 - 100; // Position in top right settingsButton.y = 100; // Position in top right game.addChild(settingsButton); var settingsText = new Text2('⚙️', { size: 60, fill: 0xFFFFFF }); settingsText.anchor.set(0.5, 0.5); settingsText.x = 2048 - 100; // Match the button position settingsText.y = 100; // Match the button position game.addChild(settingsText); // Make settings button interactive settingsButton.interactive = true; settingsButton.down = function () { if (gameState !== 'paused') { pauseGame(); showSettings(); } }; // Create directional control buttons createControlButtons(); // Player health bar playerHealthBarBg = LK.getAsset('healthBarBackground', { anchorX: 0, anchorY: 0.5 }); playerHealthBar = LK.getAsset('healthBar', { anchorX: 0, anchorY: 0.5 }); playerHealthBarBg.x = 50; playerHealthBarBg.y = 100; playerHealthBar.x = 50; playerHealthBar.y = 100; game.addChild(playerHealthBarBg); game.addChild(playerHealthBar); // Boss health bar (hidden initially) bossHealthBarBg = LK.getAsset('bossHealthBarBackground', { anchorX: 0.5, anchorY: 0.5 }); bossHealthBar = LK.getAsset('bossHealthBar', { anchorX: 0, anchorY: 0.5 }); bossHealthBarBg.x = 2048 / 2; bossHealthBarBg.y = 50; bossHealthBar.x = 2048 / 2 - bossHealthBarBg.width / 2; bossHealthBar.y = 50; bossHealthBarBg.visible = false; bossHealthBar.visible = false; game.addChild(bossHealthBarBg); game.addChild(bossHealthBar); // Tutorial text (hidden initially) tutorialText = new Text2('', { size: 70, fill: 0xFFFFFF }); tutorialText.anchor.set(0.5, 0.5); tutorialText.x = 2048 / 2; tutorialText.y = 2732 / 2; tutorialText.visible = false; game.addChild(tutorialText); } function showTutorial() { gameState = 'tutorial'; tutorialText.visible = true; var tutorialMessages = ["Welcome to Boss Blitz!\n\nUse the arrow buttons to move your ship.", "Tap anywhere to shoot.\n\nDestroy the bosses to progress.", "Collect power-ups dropped by bosses\nto gain special abilities.", "Survive long enough to defeat\nall boss levels.", "Good luck!\n\nTap to begin..."]; tutorialText.setText(tutorialMessages[tutorialStep]); // Make tutorial text pulsate tween(tutorialText, { alpha: 0.7 }, { duration: 1000, easing: tween.sinceOut, onFinish: function onFinish() { tween(tutorialText, { alpha: 1 }, { duration: 1000, easing: tween.sinceIn }); } }); } function advanceTutorial() { tutorialStep++; if (tutorialStep >= 5) { // End tutorial tutorialText.visible = false; // Remove skip tutorial button if it exists if (game.skipTutorialButton) { game.removeChild(game.skipTutorialButton); game.removeChild(game.skipTutorialText); game.skipTutorialButton = null; game.skipTutorialText = null; } startLevel(); } else { showTutorial(); } } function startLevel() { gameState = 'playing'; // Reset player position player.x = 2048 / 2; player.y = 2732 - 200; // Clear any existing projectiles clearProjectiles(); // Create boss based on current level var bossType; if (currentLevel === 1) { bossType = 'miniBoss1'; } else if (currentLevel === 2) { bossType = 'miniBoss2'; } else if (currentLevel === 3) { bossType = 'boss1'; } else if (currentLevel === 4) { bossType = 'boss2'; } else { bossType = 'boss3'; } currentBoss = new Boss(bossType, currentLevel); currentBoss.x = 2048 / 2; currentBoss.y = -200; // Start above screen game.addChild(currentBoss); // Show boss health bar bossHealthBarBg.visible = true; bossHealthBar.visible = true; // Update UI updateScore(); levelText.setText('LEVEL ' + currentLevel); } function updateScore() { scoreText.setText('SCORE: ' + LK.getScore()); } function clearProjectiles() { // Remove all bullets, lasers, and powerups bullets.forEach(function (bullet) { bullet.parent.removeChild(bullet); }); bullets = []; lasers.forEach(function (laser) { laser.parent.removeChild(laser); }); lasers = []; playerBullets.forEach(function (bullet) { bullet.parent.removeChild(bullet); }); playerBullets = []; powerups.forEach(function (powerup) { powerup.parent.removeChild(powerup); }); powerups = []; } function checkCollisions() { // Player bullets hitting boss for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; if (bullet.intersects(currentBoss)) { // Boss hit var bossDead = currentBoss.takeDamage(bullet.damage); // Remove bullet bullet.parent.removeChild(bullet); playerBullets.splice(i, 1); // Update boss health bar updateBossHealthBar(); // Check if boss defeated if (bossDead) { handleBossDefeat(); } } } // Enemy bullets hitting player for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.intersects(player)) { // Player hit var playerDied = player.takeDamage(bullet.damage); // Remove bullet bullet.parent.removeChild(bullet); bullets.splice(i, 1); // Update health bar updatePlayerHealthBar(); // Check if player died if (playerDied) { handlePlayerDefeat(); } } } // Lasers hitting player for (var i = lasers.length - 1; i >= 0; i--) { var laser = lasers[i]; // Only check active lasers (not in warning phase) if (laser.counter >= laser.warningCounter && laser.intersects(player)) { // Player hit var playerDied = player.takeDamage(laser.damage); // Update health bar updatePlayerHealthBar(); // Check if player died if (playerDied) { handlePlayerDefeat(); } // Don't remove laser on hit, it persists } } // Power-ups being collected by player for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; if (powerup.intersects(player)) { // Apply powerup effect powerup.applyEffect(player); // Remove powerup powerup.parent.removeChild(powerup); powerups.splice(i, 1); } } } function updatePlayerHealthBar() { // Update width of health bar based on player health percentage var healthPercent = player.health / player.maxHealth; playerHealthBar.width = playerHealthBarBg.width * healthPercent; // Change color based on health remaining if (healthPercent > 0.6) { playerHealthBar.tint = 0x34A853; // Green } else if (healthPercent > 0.3) { playerHealthBar.tint = 0xFBBC05; // Yellow } else { playerHealthBar.tint = 0xEA4335; // Red } } function updateBossHealthBar() { // Update width of health bar based on boss health percentage var healthPercent = currentBoss.health / currentBoss.maxHealth; bossHealthBar.width = bossHealthBarBg.width * healthPercent; // Change color based on health remaining if (healthPercent > 0.6) { bossHealthBar.tint = 0xEA4335; // Red } else if (healthPercent > 0.3) { bossHealthBar.tint = 0xFF5733; // Orange } else { bossHealthBar.tint = 0xC70039; // Dark red } } function handleBossDefeat() { gameState = 'bossDead'; // Play defeat sound LK.getSound('bossDefeat').play(); // Flash screen LK.effects.flashScreen(0xFFFFFF, 500); // Create explosion effect at boss position LK.effects.flashObject(currentBoss, 0xFFFFFF, 1000); LK.getSound('explosion').play(); // Remove boss LK.setTimeout(function () { game.removeChild(currentBoss); currentBoss = null; // Hide boss health bar bossHealthBarBg.visible = false; bossHealthBar.visible = false; // Spawn powerups spawnPowerups(); // Award score based on level var scoreIncrease = currentLevel * 1000; LK.setScore(LK.getScore() + scoreIncrease); updateScore(); // Show level complete message tutorialText.setText("LEVEL " + currentLevel + " COMPLETE!\n\nTap to continue..."); tutorialText.visible = true; // Make text appear with effect tutorialText.alpha = 0; tween(tutorialText, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); }, 1000); } function spawnPowerups() { // Spawn 1-3 random powerups var count = Math.floor(Math.random() * 3) + 1; var types = ['shield', 'doubleDamage', 'tripleShot']; for (var i = 0; i < count; i++) { var type = types[Math.floor(Math.random() * types.length)]; var powerup = new PowerUp(type); // Position near where boss was defeated powerup.x = 2048 / 2 + (Math.random() * 400 - 200); powerup.y = 300 + (Math.random() * 200 - 100); game.addChild(powerup); powerups.push(powerup); } } function advanceToNextLevel() { currentLevel++; storage.currentLevel = currentLevel; // Update max level reached if (currentLevel > storage.maxLevelReached) { storage.maxLevelReached = currentLevel; } // Hide tutorial text tutorialText.visible = false; // Start new level startLevel(); } function handlePlayerDefeat() { gameState = 'gameOver'; // Play explosion LK.getSound('explosion').play(); // Flash screen red LK.effects.flashScreen(0xFF0000, 1000); // Show game over message LK.setTimeout(function () { LK.showGameOver(); }, 1500); } function playerShoot() { if (gameState !== 'playing') return; var bullets = player.shoot(); if (bullets) { bullets.forEach(function (bullet) { game.addChild(bullet); playerBullets.push(bullet); }); } } // Event handlers function handleDown(x, y, obj) { // Handle tutorial advancement if (gameState === 'tutorial') { advanceTutorial(); return; } // Handle level advancement after boss defeat if (gameState === 'bossDead' && tutorialText.visible) { advanceToNextLevel(); return; } // In playing state, any tap triggers shooting if (gameState === 'playing') { // Check if the tap is on any of the control buttons var isOnControlButton = false; for (var i = 0; i < controlButtons.length; i++) { if (obj === controlButtons[i]) { isOnControlButton = true; break; } } // Only shoot if not tapping a control button if (!isOnControlButton) { playerShoot(); } } } function handleMove(x, y, obj) { // No longer need to handle dragging movement } function handleUp(x, y, obj) { // No longer need to handle dragging release } game.down = handleDown; game.move = handleMove; game.up = handleUp; // Main game loop game.update = function () { // Skip updates for non-playing states if (gameState === 'tutorial' || gameState === 'gameOver' || gameState === 'paused') { return; } // Auto-shoot for player if (gameState === 'playing' && LK.ticks % 30 === 0) { playerShoot(); } // Update player player.update(); // Update boss if (currentBoss && gameState === 'playing') { currentBoss.update(); } // Update projectiles for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; bullet.update(); if (bullet.shouldRemove) { bullet.parent.removeChild(bullet); playerBullets.splice(i, 1); } } for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; bullet.update(); if (bullet.shouldRemove) { bullet.parent.removeChild(bullet); bullets.splice(i, 1); } } for (var i = lasers.length - 1; i >= 0; i--) { var laser = lasers[i]; laser.update(); if (laser.shouldRemove) { laser.parent.removeChild(laser); lasers.splice(i, 1); } } for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; powerup.update(); if (powerup.shouldRemove) { powerup.parent.removeChild(powerup); powerups.splice(i, 1); } } // Check for collisions if (gameState === 'playing') { checkCollisions(); } // Update UI elements updatePlayerHealthBar(); if (currentBoss) { updateBossHealthBar(); } }; // Initialize game initGame(); function createControlButtons() { // Create the direction buttons var btnSize = 150; // Increased from 120 to 150 var spacing = 25; // Slightly increased spacing // Create buttons for each direction var upButton = new ControlButton('up'); var downButton = new ControlButton('down'); var leftButton = new ControlButton('left'); var rightButton = new ControlButton('right'); // Position buttons based on user preference var baseX = storage.controlsOnRight ? 2048 * 3 / 4 : 2048 / 4; // Position the buttons in a D-pad layout upButton.x = baseX; upButton.y = 2732 - 3 * btnSize - 2 * spacing; downButton.x = baseX; downButton.y = 2732 - btnSize - spacing; leftButton.x = baseX - btnSize - spacing; leftButton.y = 2732 - 2 * btnSize - 1.5 * spacing; rightButton.x = baseX + btnSize + spacing; rightButton.y = 2732 - 2 * btnSize - 1.5 * spacing; // Add buttons to the game game.addChild(upButton); game.addChild(downButton); game.addChild(leftButton); game.addChild(rightButton); // Store buttons for reference controlButtons = [upButton, downButton, leftButton, rightButton]; } // Function to reposition control buttons when settings change function repositionControlButtons() { if (!controlButtons || controlButtons.length < 4) return; var btnSize = 150; var spacing = 25; var baseX = storage.controlsOnRight ? 2048 * 3 / 4 : 2048 / 4; // Update positions controlButtons[0].x = baseX; // up controlButtons[1].x = baseX; // down controlButtons[2].x = baseX - btnSize - spacing; // left controlButtons[3].x = baseX + btnSize + spacing; // right } // Function to handle player movement based on button presses function movePlayer(direction, isPressed) { if (!player || gameState !== 'playing') return; // Update the movement state for the player player.moving[direction] = isPressed; } // Pause the game and save previous state function pauseGame() { if (gameState !== 'playing') return; // Store previous state var previousState = gameState; gameState = 'paused'; // Store this for when we resume gameState.previousState = previousState; } // Resume the game function resumeGame() { if (gameState !== 'paused') return; // Restore previous state gameState = gameState.previousState || 'playing'; delete gameState.previousState; } // Show settings panel function showSettings() { var settingsPanel = new SettingsPanel(); settingsPanel.x = 2048 / 2; settingsPanel.y = 2732 / 2; game.addChild(settingsPanel); } // Skip tutorial button removed ;
===================================================================
--- original.js
+++ change.js
@@ -5,10 +5,9 @@
var storage = LK.import("@upit/storage.v1", {
currentLevel: 1,
maxLevelReached: 1,
playerPowerups: {},
- controlsOnRight: true,
- skipTutorial: false
+ controlsOnRight: true
});
/****
* Classes
@@ -856,33 +855,9 @@
rightHandText.anchor.set(0.5, 0.5);
rightHandText.x = 250;
rightHandText.y = -550;
self.addChild(rightHandText);
- // Skip tutorial option
- var skipTutorialText = new Text2('SKIP TUTORIAL:', {
- size: 70,
- fill: 0xFFFFFF
- });
- skipTutorialText.anchor.set(0.5, 0.5);
- skipTutorialText.y = -350;
- self.addChild(skipTutorialText);
- // Toggle button for skip tutorial
- var skipTutorialButton = LK.getAsset('bullet', {
- anchorX: 0.5,
- anchorY: 0.5,
- scaleX: 2,
- scaleY: 1.5
- });
- skipTutorialButton.tint = storage.skipTutorial ? 0x4285F4 : 0x666666;
- skipTutorialButton.y = -200;
- self.addChild(skipTutorialButton);
- var skipTutorialBtnText = new Text2(storage.skipTutorial ? 'ON' : 'OFF', {
- size: 50,
- fill: 0xFFFFFF
- });
- skipTutorialBtnText.anchor.set(0.5, 0.5);
- skipTutorialBtnText.y = -200;
- self.addChild(skipTutorialBtnText);
+ // No skip tutorial option - removed
// Close button
var closeButton = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
@@ -921,14 +896,9 @@
repositionControlButtons();
}
}
};
- skipTutorialButton.interactive = true;
- skipTutorialButton.down = function () {
- storage.skipTutorial = !storage.skipTutorial;
- skipTutorialButton.tint = storage.skipTutorial ? 0x4285F4 : 0x666666;
- skipTutorialBtnText.setText(storage.skipTutorial ? 'ON' : 'OFF');
- };
+ // No skip tutorial button handler - removed
closeButton.interactive = true;
closeButton.down = function () {
if (self.parent) {
self.parent.removeChild(self);
@@ -987,10 +957,10 @@
player.y = 2732 - 200;
game.addChild(player);
// Initialize UI
createUI();
- // Start with tutorial if first level
- if (currentLevel === 1 && !storage.skipTutorial) {
+ // Always start with tutorial if first level
+ if (currentLevel === 1) {
showTutorial();
} else {
startLevel();
}
@@ -1106,12 +1076,8 @@
easing: tween.sinceIn
});
}
});
- // Add skip tutorial button during tutorial
- if (!game.skipTutorialButton) {
- createSkipTutorialButton();
- }
}
function advanceTutorial() {
tutorialStep++;
if (tutorialStep >= 5) {
@@ -1354,25 +1320,13 @@
}
}
// Event handlers
function handleDown(x, y, obj) {
- // Check if click is on the skip tutorial button
- if (gameState === 'tutorial' && game.skipTutorialButton && obj === game.skipTutorialButton) {
- // Let the skip button's handler handle it
- return;
- }
- // Handle tutorial advancement only when not clicking skip button
+ // Handle tutorial advancement
if (gameState === 'tutorial') {
advanceTutorial();
return;
}
- // Remove skip tutorial button if it exists when not in tutorial mode
- if (gameState !== 'tutorial' && game.skipTutorialButton) {
- game.removeChild(game.skipTutorialButton);
- game.removeChild(game.skipTutorialText);
- game.skipTutorialButton = null;
- game.skipTutorialText = null;
- }
// Handle level advancement after boss defeat
if (gameState === 'bossDead' && tutorialText.visible) {
advanceToNextLevel();
return;
@@ -1531,44 +1485,6 @@
settingsPanel.x = 2048 / 2;
settingsPanel.y = 2732 / 2;
game.addChild(settingsPanel);
}
-// Create a skip tutorial button
-function createSkipTutorialButton() {
- // Create button
- var skipButton = LK.getAsset('bullet', {
- anchorX: 0.5,
- anchorY: 0.5,
- scaleX: 2.5,
- scaleY: 1.5
- });
- skipButton.tint = 0x4285F4; // Blue
- skipButton.x = 120; // Position to right of the 100x100px platform menu area
- skipButton.y = 200; // Position below the 100x100px platform menu area and settings button
- game.addChild(skipButton);
- // Add text to button
- var skipText = new Text2("SKIP TUTORIAL", {
- size: 50,
- fill: 0xFFFFFF
- });
- skipText.anchor.set(0.5, 0.5);
- skipText.x = 120; // Match the button position
- skipText.y = 200; // Match the button position
- game.addChild(skipText);
- // Make button interactive
- skipButton.interactive = true;
- skipButton.down = function () {
- // Skip tutorial and start the game
- tutorialText.visible = false;
- // Remove the skip button
- game.removeChild(skipButton);
- game.removeChild(skipText);
- game.skipTutorialButton = null;
- game.skipTutorialText = null;
- // Start the level
- startLevel();
- };
- // Store reference to skip button to avoid creating multiple instances
- game.skipTutorialButton = skipButton;
- game.skipTutorialText = skipText;
-}
+// Skip tutorial button removed
;
\ No newline at end of file