User prompt
add a back button on the info page to go bach
User prompt
make the text on the info page more visible
User prompt
add a back button on the info button
User prompt
add another page on the menu that can be accessed by a button
User prompt
give each boss a halthbar
User prompt
polish the game
User prompt
make blizzards vertical attacks more spaced out
User prompt
make blizzard a harder boss
User prompt
make the snowstorm attack more frequent
User prompt
make the snowstorm attack longer and bigger with more
User prompt
add a snowstorm attack to the white boss
User prompt
make the menu music the music asset "music_menu"
User prompt
give the black white and orange boss a variety of differnt attacks
User prompt
after being hit give the player 2 seconds of invincibility
User prompt
make tempests projectiles face wherever they are going
User prompt
give green boss some music
User prompt
add a boss music asset for all bosses that dont have one
User prompt
add some music for the menu screen
User prompt
give each boss their own music
User prompt
when the red boss spins make him always stop facing the right way again
User prompt
Make embers attack spin around
User prompt
Give all bosses different animations for different attacks
User prompt
Make the bosses move in little patterns during gameplay to add effect
User prompt
Peace out the boss rows more for better visibilty
User prompt
Add the new bosses in a new row under the others
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Boss class var Boss = Container.expand(function () { var self = Container.call(this); // Boss type will be set after creation self.bossType = null; self.attackTimer = 0; self.attackInterval = 90; // frames self.difficulty = 1; self.phase = 1; self.timeAlive = 0; self.asset = null; self.init = function (bossType) { self.bossType = bossType; var assetId = bossType.asset; self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.difficulty = bossType.difficulty; self.attackInterval = bossType.baseInterval; self.phase = 1; self.timeAlive = 0; }; self.update = function () { self.timeAlive++; // Increase difficulty over time // For Inferno, slow down ramp-up and minimum interval for more dodgeable attacks if (self.bossType && self.bossType.name === "Inferno") { if (self.timeAlive % 900 === 0 && self.attackInterval > 60) { self.attackInterval -= 10; self.phase++; } } else { if (self.timeAlive % 600 === 0 && self.attackInterval > 30) { self.attackInterval -= 10; self.phase++; } } }; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); var playerGfx = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.radius = playerGfx.width / 2; self.update = function () {}; return self; }); // Projectile class var Projectile = Container.expand(function () { var self = Container.call(this); self.speedX = 0; self.speedY = 0; self.radius = 30; self.asset = null; self.type = null; self.init = function (type, colorAsset) { self.type = type; self.asset = self.attachAsset(colorAsset, { anchorX: 0.5, anchorY: 0.5 }); self.radius = self.asset.width / 2; }; self.update = function () { self.x += self.speedX; self.y += self.speedY; // --- New Boss Effects --- // Abyss: blackhole (gravity to player) if (self._gravityToPlayer) { if (player) { var dx = player.x - self.x; var dy = player.y - self.y; var mag = Math.sqrt(dx * dx + dy * dy) || 1; var grav = 0.18; self.speedX += dx / mag * grav; self.speedY += dy / mag * grav; // Clamp speed var spd = Math.sqrt(self.speedX * self.speedX + self.speedY * self.speedY); var maxSpd = 10; if (spd > maxSpd) { self.speedX *= maxSpd / spd; self.speedY *= maxSpd / spd; } } } // Tempest: twister (S-curve) if (self._twistDir) { self._twistTick++; // Oscillate speedX for S-curve self.speedX = Math.sin(self._twistTick / 18) * 7 * self._twistDir; } // Bounce off arena edges if .bounce is set if (self.bounce) { var minX = ARENA_X + self.radius; var maxX = ARENA_X + ARENA_W - self.radius; var minY = ARENA_Y + self.radius; var maxY = ARENA_Y + ARENA_H - self.radius; if (self.x <= minX && self.speedX < 0 || self.x >= maxX && self.speedX > 0) { self.speedX *= -1; self.x = Math.max(minX, Math.min(maxX, self.x)); } if (self.y <= minY && self.speedY < 0 || self.y >= maxY && self.speedY > 0) { self.speedY *= -1; self.y = Math.max(minY, Math.min(maxY, self.y)); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Prism // Tempest // Abyss // Prism // Tempest // Abyss // Arena settings // Bosses: Each boss will have a unique color and shape for now. // Player: Circle, blue // Bosses // Projectiles // Arena border var ARENA_W = 1800; var ARENA_H = 2400; var ARENA_X = (2048 - ARENA_W) / 2; var ARENA_Y = (2732 - ARENA_H) / 2; // Boss definitions var bossDefs = [{ name: "Inferno", asset: "boss_red", proj: "proj_red", color: 0xe74c3c, difficulty: 2, baseInterval: 140, // was 110 pattern: "spiral" }, { name: "Verdant", asset: "boss_green", proj: "proj_green", color: 0x27ae60, difficulty: 1, baseInterval: 180, // was 140 pattern: "burst" }, { name: "Solaris", asset: "boss_yellow", proj: "proj_yellow", color: 0xf1c40f, difficulty: 3, baseInterval: 80, // was 50 pattern: "aimed" }, { name: "Abyss", asset: "boss_gray", proj: "proj_gray", color: 0x7f8c8d, difficulty: 4, baseInterval: 120, // was 80 pattern: "vortex" }, { name: "Tempest", asset: "boss_blue", proj: "proj_blue", color: 0x2980b9, difficulty: 3, baseInterval: 110, // was 70 pattern: "wind" }, { name: "Prism", asset: "boss_purple", proj: "proj_purple", color: 0x9b59b6, difficulty: 5, baseInterval: 100, // was 60 pattern: "prism" }, { name: "Obsidian", asset: "boss_black", proj: "proj_black", color: 0x111111, difficulty: 4, baseInterval: 120, pattern: "chaos" }, { name: "Blizzard", asset: "boss_white", proj: "proj_white", color: 0xffffff, difficulty: 2, baseInterval: 130, pattern: "ring" }, { name: "Ember", asset: "boss_orange", proj: "proj_orange", color: 0xffa500, difficulty: 3, baseInterval: 100, pattern: "burst" }]; var player = null; var boss = null; var projectiles = []; var survivalTime = 0; var gameStarted = false; var bossChoice = null; var dragNode = null; var lastMoveX = 0, lastMoveY = 0; // Boss animated background container (created once, reused) var bossBgContainer = new Container(); bossBgContainer.visible = false; game.addChild(bossBgContainer); // Arena border var arenaBorder = LK.getAsset('arena_border', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(arenaBorder); // GUI: Survival time var timeTxt = new Text2('0.0s', { size: 110, fill: 0xFFFFFF }); timeTxt.anchor.set(0.5, 0); LK.gui.top.addChild(timeTxt); // GUI: Player lives var playerLives = 3; var livesTxt = new Text2('Lives: 3', { size: 90, fill: 0xFF6666 }); livesTxt.anchor.set(0.5, 0); livesTxt.y = 120; // Place below timeTxt LK.gui.top.addChild(livesTxt); // GUI: Boss name var bossNameTxt = new Text2('', { size: 90, fill: 0xFFECB3 }); bossNameTxt.anchor.set(0.5, 0); LK.gui.top.addChild(bossNameTxt); // --- Menu Background --- var menuBg = LK.getAsset('arena_border', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 1.04, scaleY: 1.04 }); menuBg.alpha = 0.18; game.addChild(menuBg); // GUI: Boss select title var bossSelectTxt = new Text2('Choose Your Boss', { size: 140, fill: 0xFFFFFF, font: "GillSans-Bold,Impact,'Arial Black',Tahoma" }); bossSelectTxt.anchor.set(0.5, 0); bossSelectTxt.y = 20; LK.gui.top.addChild(bossSelectTxt); // GUI: Boss select subtitle var bossSelectSubTxt = new Text2('Tap a boss to begin', { size: 70, fill: 0xCCCCCC }); bossSelectSubTxt.anchor.set(0.5, 0); // Place just under the 'Choose Your Boss' title (title is at y=20, size=140) bossSelectSubTxt.y = bossSelectTxt.y + bossSelectTxt.height + 10; LK.gui.top.addChild(bossSelectSubTxt); // Boss select buttons and labels var bossSelectButtons = []; for (var i = 0; i < bossDefs.length; i++) { var b = bossDefs[i]; // Arrange in three rows of 3: 0,1,2 on top row, 3,4,5 in middle, 6,7,8 in bottom row var row = Math.floor(i / 3); // 0 for top, 1 for middle, 2 for bottom var col = i % 3; // 0,1,2 var x = 2048 / 2 + (col - 1) * 420; // center, -420, 0, +420 var y; var rowSpacing = 440; // Increased spacing for better visibility if (row === 0) { y = 2732 / 2 - rowSpacing; // top row, further above center } else if (row === 1) { y = 2732 / 2 + 0; // middle row, center } else { y = 2732 / 2 + rowSpacing; // bottom row, further below center } // Add a subtle shadow behind each boss button var shadow = LK.getAsset(b.asset, { anchorX: 0.5, anchorY: 0.5, x: x + 0, y: y + 18, scaleX: 1.18, scaleY: 1.18 }); shadow.alpha = 0.13; game.addChild(shadow); var btn = LK.getAsset(b.asset, { anchorX: 0.5, anchorY: 0.5, x: x, y: y, scaleX: 1.13, scaleY: 1.13 }); btn.bossIndex = i; bossSelectButtons.push(btn); game.addChild(btn); // Add boss name label var label = new Text2(b.name, { size: 78, fill: b.color }); label.anchor.set(0.5, 0); label.x = btn.x; // Place label below the button label.y = btn.y + 140; game.addChild(label); btn._label = label; // Add a difficulty indicator (dots) - now even further above the boss button var diffDots = []; for (var d = 0; d < b.difficulty; d++) { var dot = LK.getAsset('boss_' + b.asset.split('_')[1], { anchorX: 0.5, anchorY: 0.5, x: btn.x - 32 * (b.difficulty - 1) / 2 + d * 32, y: btn.y - 180, // moved further above the boss button scaleX: 0.18, scaleY: 0.18 }); dot.alpha = 0.7; game.addChild(dot); diffDots.push(dot); } btn._diffDots = diffDots; } // Hide arena and GUI until boss is chosen arenaBorder.visible = false; timeTxt.visible = false; bossNameTxt.visible = false; // Boss select handler game.down = function (x, y, obj) { if (!gameStarted) { // Check if a boss button was pressed for (var i = 0; i < bossSelectButtons.length; i++) { var btn = bossSelectButtons[i]; var dx = x - btn.x; var dy = y - btn.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 120) { // Boss chosen bossChoice = bossDefs[btn.bossIndex]; startGame(); return; } } } else { // Start drag if inside player var dx = x - player.x; var dy = y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < player.radius) { dragNode = player; lastMoveX = x; lastMoveY = y; } } }; game.up = function (x, y, obj) { dragNode = null; }; function handleMove(x, y, obj) { if (dragNode && gameStarted) { // Clamp to arena var px = x, py = y; var minX = ARENA_X + player.radius; var maxX = ARENA_X + ARENA_W - player.radius; var minY = ARENA_Y + player.radius; var maxY = ARENA_Y + ARENA_H - player.radius; px = Math.max(minX, Math.min(maxX, px)); py = Math.max(minY, Math.min(maxY, py)); dragNode.x = px; dragNode.y = py; lastMoveX = px; lastMoveY = py; } } game.move = handleMove; // Start game after boss selection function startGame() { // Hide boss select UI bossSelectTxt.visible = false; bossSelectSubTxt.visible = false; menuBg.visible = false; for (var i = 0; i < bossSelectButtons.length; i++) { bossSelectButtons[i].visible = false; bossSelectButtons[i]._label.visible = false; if (bossSelectButtons[i]._diffDots) { for (var d = 0; d < bossSelectButtons[i]._diffDots.length; d++) { bossSelectButtons[i]._diffDots[d].visible = false; } } } // Hide all other irrelevant UI during gameplay bossSelectTxt.visible = false; bossSelectSubTxt.visible = false; menuBg.visible = false; for (var i = 0; i < bossSelectButtons.length; i++) { bossSelectButtons[i].visible = false; bossSelectButtons[i]._label.visible = false; if (bossSelectButtons[i]._diffDots) { for (var d = 0; d < bossSelectButtons[i]._diffDots.length; d++) { bossSelectButtons[i]._diffDots[d].visible = false; } } } // Show arena and GUI arenaBorder.visible = true; timeTxt.visible = true; bossNameTxt.visible = true; // --- Boss-specific animated background setup --- bossBgContainer.removeChildren(); bossBgContainer.visible = true; var bgAssetId = null; var bgColor = 0x222222; var bgAlpha = 0.13; var bgAnimType = null; // Pick background asset/color/animation based on boss if (bossChoice.name === "Inferno") { bgAssetId = "boss_red"; bgColor = 0xe74c3c; bgAlpha = 0.10; bgAnimType = "pulse"; } else if (bossChoice.name === "Verdant") { bgAssetId = "boss_green"; bgColor = 0x27ae60; bgAlpha = 0.10; bgAnimType = "wave"; } else if (bossChoice.name === "Solaris") { bgAssetId = "boss_yellow"; bgColor = 0xf1c40f; bgAlpha = 0.10; bgAnimType = "shine"; } else if (bossChoice.name === "Abyss") { bgAssetId = "boss_gray"; bgColor = 0x7f8c8d; bgAlpha = 0.10; bgAnimType = "vortex"; } else if (bossChoice.name === "Tempest") { bgAssetId = "boss_blue"; bgColor = 0x2980b9; bgAlpha = 0.10; bgAnimType = "wind"; } else if (bossChoice.name === "Prism") { bgAssetId = "boss_purple"; bgColor = 0x9b59b6; bgAlpha = 0.10; bgAnimType = "rainbow"; } else { bgAssetId = "arena_border"; bgColor = 0x222222; bgAlpha = 0.10; bgAnimType = null; } // Add a large faded background shape for the boss var bossBgShape = LK.getAsset(bgAssetId, { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 7.5, scaleY: 7.5 }); bossBgShape.alpha = bgAlpha; bossBgContainer.addChild(bossBgShape); // Optionally add a second, smaller animated overlay for some bosses if (bossChoice.name === "Prism") { // Add 6 colored faded ellipses in a circle for rainbow effect for (var c = 0; c < 6; c++) { var colorId = ["boss_red", "boss_yellow", "boss_green", "boss_blue", "boss_purple", "boss_gray"][c]; var angle = Math.PI * 2 * c / 6; var rainbow = LK.getAsset(colorId, { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + Math.cos(angle) * 500, y: 2732 / 2 + Math.sin(angle) * 500, scaleX: 2.7, scaleY: 2.7 }); rainbow.alpha = 0.09; bossBgContainer.addChild(rainbow); } } // Store animation type for update bossBgContainer._animType = bgAnimType; bossBgContainer._animTick = 0; // Create player player = new Player(); player.x = 2048 / 2; player.y = 2732 / 2 + 600; game.addChild(player); // Create boss boss = new Boss(); boss.init(bossChoice); boss.x = 2048 / 2; boss.y = 2732 / 2 - 700; game.addChild(boss); // Set boss name bossNameTxt.setText(bossChoice.name); // Reset state projectiles = []; survivalTime = 0; playerLives = 3; livesTxt.setText('Lives: ' + playerLives); gameStarted = true; } // Boss attack patterns function bossAttack() { if (!boss || !player) return; var bossType = bossChoice; var projAsset = bossType.proj; var cx = boss.x, cy = boss.y; var px = player.x, py = player.y; var phase = boss.phase; var n, angle, i, p, speed, spread, baseAngle, offset, j, delay, targetX, targetY; // Each boss has a set of possible attacks, randomly chosen var attackList = []; if (bossType.name === "Inferno") { attackList = ["spiral", // Rotating spiral "double_spiral", // Two spirals, offset "wall", // Horizontal/vertical wall "cross", // Cross pattern "aimed_burst" // Burst of aimed shots ]; } else if (bossType.name === "Verdant") { attackList = ["burst", // All directions "flower", // Petal/flower pattern "arc", // Arc sweep "ring", // Expanding ring "random_bounce" // Random directions ]; } else if (bossType.name === "Solaris") { attackList = ["aimed", // Aimed shots "triple_aimed", // Three aimed shots "sniper", // Single fast shot "spread", // Wide spread "rain" // Rain from above ]; } else if (bossType.name === "Abyss") { attackList = ["vortex", // swirling projectiles "blackhole", // projectiles curve toward player "void_ring", // slow expanding ring "chaos", // random directions, random speeds "gravity" // projectiles accelerate toward player ]; } else if (bossType.name === "Tempest") { attackList = ["wind", // fast horizontal projectiles "gust", // diagonal waves "cyclone", // spiral from arena edge "twister", // projectiles curve in S-shape "scatter" // random scatter ]; } else if (bossType.name === "Prism") { attackList = ["prism", // rainbow spread "reflect", // bouncing projectiles "laser", // straight fast lines "split", // projectiles split mid-air "mirror" // projectiles reflect off walls ]; } else { attackList = [bossType.pattern]; } // Cycle through attacks in order for predictability if (!boss._attackIndex) boss._attackIndex = 0; var pattern = attackList[boss._attackIndex % attackList.length]; boss._attackIndex++; // --- Abyss Attacks --- if (pattern === "vortex") { // Swirling projectiles inwards toward player n = 7 + Math.floor(phase * 0.7); var swirlBase = boss.timeAlive * 0.04 % (2 * Math.PI); for (i = 0; i < n; i++) { angle = swirlBase + 2 * Math.PI / n * i; p = new Projectile(); p.init("vortex", projAsset); p.x = cx + Math.cos(angle) * 400; p.y = cy + Math.sin(angle) * 400; var toPlayer = Math.atan2(py - p.y, px - p.x); speed = 2.8 + phase * 0.18; p.speedX = Math.cos(toPlayer) * speed; p.speedY = Math.sin(toPlayer) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "blackhole") { // Projectiles curve toward player (simulate gravity) n = 5 + Math.floor(phase / 2); for (i = 0; i < n; i++) { angle = 2 * Math.PI / n * i; p = new Projectile(); p.init("blackhole", projAsset); p.x = cx; p.y = cy; var baseSpeed = 3.2 + phase * 0.13; p.speedX = Math.cos(angle) * baseSpeed; p.speedY = Math.sin(angle) * baseSpeed; // Add gravity effect in update p._gravityToPlayer = true; projectiles.push(p); game.addChild(p); } } else if (pattern === "void_ring") { // Slow expanding ring n = 10 + Math.floor(phase * 0.8); for (i = 0; i < n; i++) { angle = 2 * Math.PI / n * i; p = new Projectile(); p.init("void_ring", projAsset); p.x = cx; p.y = cy; speed = 1.3 + phase * 0.07; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "chaos") { // Random directions, random speeds n = 6 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { angle = Math.random() * 2 * Math.PI; p = new Projectile(); p.init("chaos", projAsset); p.x = cx; p.y = cy; speed = 1.5 + Math.random() * (4.5 + phase * 0.2); p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "gravity") { // Projectiles accelerate toward player after a delay n = 4 + Math.floor(phase / 2); for (i = 0; i < n; i++) { angle = 2 * Math.PI / n * i; p = new Projectile(); p.init("gravity", projAsset); p.x = cx; p.y = cy; speed = 2.5 + phase * 0.13; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; // After 0.7s, home in on player (function (proj) { LK.setTimeout(function () { var dx = player.x - proj.x; var dy = player.y - proj.y; var mag = Math.sqrt(dx * dx + dy * dy) || 1; var newSpeed = 5.5 + phase * 0.2; proj.speedX = dx / mag * newSpeed; proj.speedY = dy / mag * newSpeed; }, 700); })(p); projectiles.push(p); game.addChild(p); } // --- Tempest Attacks --- } else if (pattern === "wind") { // Fast horizontal projectiles from left or right var fromLeft = Math.random() < 0.5; n = 5 + Math.floor(phase / 2); for (i = 0; i < n; i++) { p = new Projectile(); p.init("wind", projAsset); p.x = fromLeft ? ARENA_X + 40 : ARENA_X + ARENA_W - 40; p.y = ARENA_Y + 200 + (ARENA_H - 400) * (i / (n - 1)); p.speedX = (fromLeft ? 1 : -1) * (8.5 + phase * 0.4); p.speedY = 0; projectiles.push(p); game.addChild(p); } } else if (pattern === "gust") { // Diagonal waves n = 4 + Math.floor(phase / 2); for (i = 0; i < n; i++) { p = new Projectile(); p.init("gust", projAsset); p.x = ARENA_X + 100 + (ARENA_W - 200) * (i / (n - 1)); p.y = ARENA_Y + 40; var angle = Math.PI / 4 + (Math.random() - 0.5) * 0.3; p.speedX = Math.cos(angle) * (4.5 + phase * 0.2); p.speedY = Math.sin(angle) * (4.5 + phase * 0.2); projectiles.push(p); game.addChild(p); } } else if (pattern === "cyclone") { // Spiral from arena edge toward center n = 7 + Math.floor(phase * 0.7); var spiralBase = boss.timeAlive * 0.05 % (2 * Math.PI); for (i = 0; i < n; i++) { angle = spiralBase + 2 * Math.PI / n * i; p = new Projectile(); p.init("cyclone", projAsset); p.x = cx + Math.cos(angle) * (ARENA_W / 2 - 100); p.y = cy + Math.sin(angle) * (ARENA_H / 2 - 100); var toCenter = Math.atan2(cy - p.y, cx - p.x); speed = 3.8 + phase * 0.18; p.speedX = Math.cos(toCenter) * speed; p.speedY = Math.sin(toCenter) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "twister") { // Projectiles curve in S-shape (simulate by changing speedY over time) n = 5 + Math.floor(phase / 2); for (i = 0; i < n; i++) { p = new Projectile(); p.init("twister", projAsset); p.x = ARENA_X + 100 + (ARENA_W - 200) * (i / (n - 1)); p.y = ARENA_Y + 40; p.speedX = 0; p.speedY = 5.5 + phase * 0.2; // S-curve: alternate left/right p._twistDir = i % 2 === 0 ? 1 : -1; p._twistTick = 0; projectiles.push(p); game.addChild(p); } } else if (pattern === "scatter") { // Random scatter from boss n = 7 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { angle = Math.random() * 2 * Math.PI; p = new Projectile(); p.init("scatter", projAsset); p.x = cx; p.y = cy; speed = 3.5 + Math.random() * 2.5 + phase * 0.13; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } // --- Prism Attacks --- } else if (pattern === "prism") { // Rainbow spread (simulate with color asset, but all yellow for now) n = 6 + Math.floor(phase * 0.7); var spread = Math.PI * 2 / 3; var baseAngle = -Math.PI / 3; for (i = 0; i < n; i++) { angle = baseAngle + spread * (i / (n - 1)); p = new Projectile(); p.init("prism", projAsset); p.x = cx; p.y = cy; speed = 5.5 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "reflect") { // Bouncing projectiles n = 4 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { angle = Math.PI / 6 + Math.PI * 2 / n * i; p = new Projectile(); p.init("reflect", projAsset); p.x = cx; p.y = cy; speed = 4.5 + phase * 0.18; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; p.bounce = true; projectiles.push(p); game.addChild(p); } } else if (pattern === "laser") { // Straight fast lines n = 2 + Math.floor(phase / 2); for (i = 0; i < n; i++) { angle = Math.PI / 2 + (i - (n - 1) / 2) * 0.12; p = new Projectile(); p.init("laser", projAsset); p.x = cx; p.y = cy; speed = 11 + phase * 0.5; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "split") { // Projectiles split mid-air n = 3 + Math.floor(phase / 2); for (i = 0; i < n; i++) { angle = Math.PI / 2 + (i - (n - 1) / 2) * 0.18; p = new Projectile(); p.init("split", projAsset); p.x = cx; p.y = cy; speed = 5.5 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; // After 0.6s, split into two (function (proj, ang) { LK.setTimeout(function () { for (var s = -1; s <= 1; s += 2) { var child = new Projectile(); child.init("split_child", projAsset); child.x = proj.x; child.y = proj.y; var splitAngle = ang + s * Math.PI / 8; var splitSpeed = 4.5 + phase * 0.18; child.speedX = Math.cos(splitAngle) * splitSpeed; child.speedY = Math.sin(splitAngle) * splitSpeed; projectiles.push(child); game.addChild(child); } }, 600); })(p, angle); projectiles.push(p); game.addChild(p); } } else if (pattern === "mirror") { // Projectiles reflect off walls (simulate with bounce) n = 4 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { angle = Math.PI / 2 + (i - (n - 1) / 2) * 0.22; p = new Projectile(); p.init("mirror", projAsset); p.x = cx; p.y = cy; speed = 5.5 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; p.bounce = true; projectiles.push(p); game.addChild(p); } // --- Inferno Attacks --- } else if (pattern === "spiral") { // Rotating spiral n = 5 + Math.floor(phase * 0.7); baseAngle = boss.timeAlive * 0.07 % (2 * Math.PI); for (i = 0; i < n; i++) { angle = baseAngle + 2 * Math.PI / n * i; p = new Projectile(); p.init("spiral", projAsset); p.x = cx; p.y = cy; speed = 4.5 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "double_spiral") { // Two spirals, offset n = 6 + Math.floor(phase * 0.7); baseAngle = boss.timeAlive * 0.09 % (2 * Math.PI); for (j = 0; j < 2; j++) { offset = j * Math.PI / n; for (i = 0; i < n; i++) { angle = baseAngle + 2 * Math.PI / n * i + offset; p = new Projectile(); p.init("double_spiral", projAsset); p.x = cx; p.y = cy; speed = 3.8 + phase * 0.18; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } } else if (pattern === "wall") { // Shoots a wall of projectiles horizontally or vertically var vertical = Math.random() < 0.5; // Reduce number of projectiles for vertical (downward) wall for more spacing if (vertical) { n = 4 + Math.floor(phase / 3); // was 10 + Math.floor(phase / 2) } else { n = 6 + Math.floor(phase / 2); } for (i = 0; i < n; i++) { p = new Projectile(); p.init("wall", projAsset); if (vertical) { p.x = ARENA_X + ARENA_W / (n + 1) * (i + 1); p.y = cy; p.speedX = 0; p.speedY = 4.5 + phase * 0.22; } else { p.x = cx; p.y = ARENA_Y + ARENA_H / (n + 1) * (i + 1); p.speedX = 4.5 + phase * 0.22; p.speedY = 0; } projectiles.push(p); game.addChild(p); } } else if (pattern === "cross") { // Shoots in a cross pattern (up, down, left, right) var dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]]; for (i = 0; i < dirs.length; i++) { p = new Projectile(); p.init("cross", projAsset); p.x = cx; p.y = cy; speed = 6.5 + phase * 0.22; p.speedX = dirs[i][0] * speed; p.speedY = dirs[i][1] * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "aimed_burst") { // Burst of aimed shots with spread n = 3 + Math.floor(phase / 2); var toPlayer = Math.atan2(py - cy, px - cx); spread = Math.PI / 6 + Math.PI / 32 * phase; for (i = 0; i < n; i++) { angle = toPlayer + spread * (i - (n - 1) / 2) / n; p = new Projectile(); p.init("aimed_burst", projAsset); p.x = cx; p.y = cy; speed = 5.5 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } // --- Verdant Attacks --- } else if (pattern === "burst") { // All directions // Make burst easier: fewer projectiles, slower speed n = 5 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { angle = 2 * Math.PI / n * i; p = new Projectile(); p.init("burst", projAsset); p.x = cx; p.y = cy; speed = 2.2 + phase * 0.13; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "flower") { // Petal/flower pattern (alternating speeds) // Make flower easier: fewer petals, slower speed n = 4 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { angle = 2 * Math.PI / n * i; p = new Projectile(); p.init("flower", projAsset); p.x = cx; p.y = cy; speed = (i % 2 === 0 ? 2.5 : 1.2) + phase * 0.09; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "arc") { // Arc sweep (quarter circle) // Make arc easier: fewer projectiles, slower speed n = 3 + Math.floor(phase * 0.7); var arcStart = Math.PI / 4; var arcEnd = Math.PI * 3 / 4; for (i = 0; i < n; i++) { angle = arcStart + (arcEnd - arcStart) * (i / (n - 1)); p = new Projectile(); p.init("arc", projAsset); p.x = cx; p.y = cy; speed = 2.5 + phase * 0.13; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "ring") { // Expanding ring (slow projectiles) // Make ring easier: fewer projectiles, slower speed n = 6 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { angle = 2 * Math.PI / n * i; p = new Projectile(); p.init("ring", projAsset); p.x = cx; p.y = cy; speed = 1.2 + phase * 0.07; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "random_bounce") { // Deterministic directions, evenly spaced, for predictability // Make random_bounce easier: fewer projectiles, slower speed n = 2 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { angle = 2 * Math.PI / n * i + boss.timeAlive % 60 * 0.05; // slight rotation over time p = new Projectile(); p.init("random_bounce", projAsset); p.x = cx; p.y = cy; speed = 1.5 + i % 2 + phase * 0.07; // deterministic speed, slower p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; // Mark as bouncing (handled in update) p.bounce = true; projectiles.push(p); game.addChild(p); } // --- Solaris Attacks --- } else if (pattern === "aimed") { // Aimed shots at player, with some spread n = 1 + Math.floor(phase / 2); var toPlayer = Math.atan2(py - cy, px - cx); spread = Math.PI / 8 + Math.PI / 32 * phase; // Show indicator lines for each aimed shot for (i = 0; i < n; i++) { angle = toPlayer + spread * (i - (n - 1) / 2); // Draw indicator var indicator = LK.getAsset('proj_' + bossType.asset.split('_')[1], { anchorX: 0.5, anchorY: 0.5, x: cx, y: cy, scaleX: 0.5, scaleY: 0.15, rotation: angle }); // Stretch indicator to show path indicator.width = 900; indicator.alpha = 0.35; game.addChild(indicator); // Fade out and remove indicator after 0.7s (function (ind, angle) { tween(ind, { alpha: 0 }, { duration: 700, onFinish: function onFinish() { if (ind.parent) ind.parent.removeChild(ind); } }); // Fire projectile after indicator delay (0.7s) LK.setTimeout(function () { var p = new Projectile(); p.init("aimed", projAsset); p.x = cx; p.y = cy; var speed = 6.5 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); }, 700); })(indicator, angle); } } else if (pattern === "triple_aimed") { // Three aimed shots, tight spread n = 2; var toPlayer = Math.atan2(py - cy, px - cx); spread = Math.PI / 16; for (i = 0; i < n; i++) { angle = toPlayer + spread * (i - 1); p = new Projectile(); p.init("triple_aimed", projAsset); p.x = cx; p.y = cy; speed = 7.5 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "sniper") { // Single fast shot at player var toPlayer = Math.atan2(py - cy, px - cx); // Draw indicator var indicator = LK.getAsset('proj_' + bossType.asset.split('_')[1], { anchorX: 0.5, anchorY: 0.5, x: cx, y: cy, scaleX: 0.5, scaleY: 0.15, rotation: toPlayer }); indicator.width = 1200; indicator.alpha = 0.45; game.addChild(indicator); (function (ind, angle) { tween(ind, { alpha: 0 }, { duration: 900, onFinish: function onFinish() { if (ind.parent) ind.parent.removeChild(ind); } }); // Fire projectile after indicator delay (0.9s) LK.setTimeout(function () { var p = new Projectile(); p.init("sniper", projAsset); p.x = cx; p.y = cy; var speed = 10 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); }, 900); })(indicator, toPlayer); } else if (pattern === "spread") { // Wide spread n = 4 + Math.floor(phase / 2); var toPlayer = Math.atan2(py - cy, px - cx); spread = Math.PI / 3; for (i = 0; i < n; i++) { angle = toPlayer - spread / 2 + spread * (i / (n - 1)); p = new Projectile(); p.init("spread", projAsset); p.x = cx; p.y = cy; speed = 5.5 + phase * 0.22; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } else if (pattern === "rain") { // Rain from above (projectiles fall from random x at top) n = 4 + Math.floor(phase * 0.7); for (i = 0; i < n; i++) { p = new Projectile(); p.init("rain", projAsset); p.x = ARENA_X + Math.random() * ARENA_W; p.y = ARENA_Y + 40; p.speedX = 0; p.speedY = 6.5 + phase * 0.22; projectiles.push(p); game.addChild(p); } } else { // Fallback: default to spiral n = 8 + phase; baseAngle = boss.timeAlive * 0.07 % (2 * Math.PI); for (i = 0; i < n; i++) { angle = baseAngle + 2 * Math.PI / n * i; p = new Projectile(); p.init("spiral", projAsset); p.x = cx; p.y = cy; speed = 7 + phase * 0.7; p.speedX = Math.cos(angle) * speed; p.speedY = Math.sin(angle) * speed; projectiles.push(p); game.addChild(p); } } } // Main game update game.update = function () { if (!gameStarted) { // Animate menu background in if (menuBg.alpha < 0.18) menuBg.alpha += 0.02; if (bossSelectSubTxt.alpha < 1) bossSelectSubTxt.alpha += 0.05; return; } else { // Animate menu background out if (menuBg.alpha > 0) menuBg.alpha -= 0.04; if (bossSelectSubTxt.alpha > 0) bossSelectSubTxt.alpha -= 0.08; } // Animate boss-specific background if visible if (bossBgContainer && bossBgContainer.visible) { bossBgContainer._animTick = (bossBgContainer._animTick || 0) + 1; var t = bossBgContainer._animTick; var animType = bossBgContainer._animType; // Animate the first child (main background) if (bossBgContainer.children.length > 0) { var bg = bossBgContainer.children[0]; if (animType === "pulse") { // Inferno: pulsing scale bg.scale.x = bg.scale.y = 7.5 + Math.sin(t / 30) * 0.25; bg.alpha = 0.10 + 0.03 * Math.abs(Math.sin(t / 30)); } else if (animType === "wave") { // Verdant: slow scale wave bg.scale.x = 7.5 + Math.sin(t / 60) * 0.18; bg.scale.y = 7.5 + Math.cos(t / 60) * 0.18; bg.alpha = 0.10 + 0.02 * Math.abs(Math.cos(t / 60)); } else if (animType === "shine") { // Solaris: slow rotation bg.rotation = t / 180 % (2 * Math.PI); bg.alpha = 0.10 + 0.03 * Math.abs(Math.sin(t / 50)); } else if (animType === "vortex") { // Abyss: slow swirl and fade bg.rotation = t / 120 % (2 * Math.PI); bg.alpha = 0.10 + 0.04 * Math.abs(Math.sin(t / 80)); } else if (animType === "wind") { // Tempest: horizontal wave bg.x = 2048 / 2 + Math.sin(t / 40) * 60; bg.alpha = 0.10 + 0.03 * Math.abs(Math.sin(t / 40)); } else if (animType === "rainbow") { // Prism: rotate all children for (var c = 0; c < bossBgContainer.children.length; c++) { var child = bossBgContainer.children[c]; if (c === 0) { child.rotation = t / 180 % (2 * Math.PI); child.alpha = 0.10 + 0.02 * Math.abs(Math.sin(t / 60)); } else { // Rainbow ellipses rotate around center var angle = Math.PI * 2 * (c - 1) / 6 + t / 120; child.x = 2048 / 2 + Math.cos(angle) * 500; child.y = 2732 / 2 + Math.sin(angle) * 500; child.alpha = 0.09 + 0.01 * Math.abs(Math.sin(t / 40 + c)); } } } else { // Default: no animation bg.scale.x = bg.scale.y = 7.5; bg.alpha = 0.10; } } } // Update survival time survivalTime += 1 / 60; timeTxt.setText(survivalTime.toFixed(1) + "s"); // Update boss if (boss) { boss.update(); boss.attackTimer++; if (boss.attackTimer >= boss.attackInterval) { boss.attackTimer = 0; bossAttack(); } } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var p = projectiles[i]; p.update(); // Remove if out of arena if (p.x < ARENA_X - 100 || p.x > ARENA_X + ARENA_W + 100 || p.y < ARENA_Y - 100 || p.y > ARENA_Y + ARENA_H + 100) { p.destroy(); projectiles.splice(i, 1); continue; } // Collision with player if (player._invuln && player._invuln > 0) { player._invuln--; continue; } var dx = p.x - player.x; var dy = p.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < player.radius + p.radius - 10) { // Player hit LK.effects.flashScreen(0xff0000, 800); playerLives--; livesTxt.setText('Lives: ' + playerLives); if (playerLives <= 0) { LK.showGameOver(); return; } else { // Remove all projectiles and respawn player at start position for (var j = 0; j < projectiles.length; j++) { projectiles[j].destroy(); } projectiles = []; player.x = 2048 / 2; player.y = 2732 / 2 + 600; clampPlayerStart(); // Brief invulnerability (skip collision for 60 frames) player._invuln = 60; break; } } } }; // Prevent player from being placed in top left 100x100 function clampPlayerStart() { var minX = ARENA_X + player.radius; var minY = ARENA_Y + player.radius; if (player.x < minX) player.x = minX; if (player.y < minY) player.y = minY; } // On game reset, restore boss select UI LK.on('reset', function () { // Restore all boss select UI elements bossSelectTxt.visible = true; bossSelectSubTxt.visible = true; menuBg.visible = true; for (var i = 0; i < bossSelectButtons.length; i++) { bossSelectButtons[i].visible = true; bossSelectButtons[i]._label.visible = true; if (bossSelectButtons[i]._diffDots) { for (var d = 0; d < bossSelectButtons[i]._diffDots.length; d++) { bossSelectButtons[i]._diffDots[d].visible = true; } } } arenaBorder.visible = false; timeTxt.visible = false; bossNameTxt.visible = false; if (bossBgContainer) bossBgContainer.visible = false; gameStarted = false; bossChoice = null; playerLives = 3; livesTxt.setText('Lives: ' + playerLives); // Remove player, boss, projectiles if (player) { player.destroy(); player = null; } if (boss) { boss.destroy(); boss = null; } for (var i = 0; i < projectiles.length; i++) { projectiles[i].destroy(); } projectiles = []; });
===================================================================
--- original.js
+++ change.js
@@ -130,20 +130,20 @@
/****
* Game Code
****/
-// Arena border
-// Projectiles
-// Bosses
-// Player: Circle, blue
-// Bosses: Each boss will have a unique color and shape for now.
-// Arena settings
-// Abyss
-// Tempest
// Prism
-// Abyss
// Tempest
+// Abyss
// Prism
+// Tempest
+// Abyss
+// Arena settings
+// Bosses: Each boss will have a unique color and shape for now.
+// Player: Circle, blue
+// Bosses
+// Projectiles
+// Arena border
var ARENA_W = 1800;
var ARENA_H = 2400;
var ARENA_X = (2048 - ARENA_W) / 2;
var ARENA_Y = (2732 - ARENA_H) / 2;
@@ -308,14 +308,15 @@
var row = Math.floor(i / 3); // 0 for top, 1 for middle, 2 for bottom
var col = i % 3; // 0,1,2
var x = 2048 / 2 + (col - 1) * 420; // center, -420, 0, +420
var y;
+ var rowSpacing = 440; // Increased spacing for better visibility
if (row === 0) {
- y = 2732 / 2 - 340; // top row, further above center
+ y = 2732 / 2 - rowSpacing; // top row, further above center
} else if (row === 1) {
y = 2732 / 2 + 0; // middle row, center
} else {
- y = 2732 / 2 + 340; // bottom row, further below center
+ y = 2732 / 2 + rowSpacing; // bottom row, further below center
}
// Add a subtle shadow behind each boss button
var shadow = LK.getAsset(b.asset, {
anchorX: 0.5,
make a red firey circle with black eyes that are mad and no mouth. In-Game asset. 2d. High contrast. No shadows
a happy blue circle simple. In-Game asset. 2d. High contrast. No shadows
a green circle that is very smart and has a monocle and has orange eyes. In-Game asset. 2d. High contrast. No shadows
only the ball
make a yellow circle that is like the sun that has sunglasses on. In-Game asset. 2d. High contrast. No shadows
only the sorce of the light
a grey circle with orange wyes and he is a space king. In-Game asset. 2d. High contrast. No shadows
make the beard a bit shorter
a purple circle with purple crystal armour and a sturn look on his face. only the head In-Game asset. 2d. High contrast. No shadows
a purple crystal. In-Game asset. 2d. High contrast. No shadows
a black circle that is dark and evil and has red eyes and an evil smirk. In-Game asset. 2d. High contrast. No shadows
remove the red aura and just have a red outline
a white circle with blue eyes and an icy face. In-Game asset. 2d. High contrast. No shadows
a snowflake. In-Game asset. 2d. High contrast. No shadows
remove the guns
a blue energy ball. In-Game asset. 2d. High contrast. No shadows
music_inferno
Music
music_verdant
Music
music_solaris
Music
music_abyss
Music
music_tempest
Music
music_prism
Music
music_obsidian
Music
music_blizzard
Music
music_ember
Music
music_menu
Music
sig_inferno
Sound effect
sig_verdant
Sound effect
sig_solaris
Sound effect
sig_abyss
Sound effect
sig_tempest
Sound effect
sig_prism
Sound effect
sig_obsidian
Sound effect
sig_blizzard
Sound effect
sig_ember
Sound effect