User prompt
Remove ai
User prompt
Make ai cant caught the obstacle's
User prompt
Make ai mind master and give fast boost
User prompt
Give ai player and do smart
User prompt
Remove auto DODGE
User prompt
Make player auto DODGE
User prompt
Play song kachow for player but when player DODGE
User prompt
Remove all volume setting
User prompt
Volume button hit box gonna big
User prompt
Remove the start word top start button
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'mainMenuOverlay.addChild(startBtnLabel);' Line Number: 231
User prompt
Make a player Regular
User prompt
Make a small
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'height')' in or related to this line: 'startBtnLabel.y = 1250 - startBtn.height / 2 - 30;' Line Number: 228
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'addChild')' in or related to this line: 'mainMenuOverlay.addChild(startBtnLabel);' Line Number: 234
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'height')' in or related to this line: 'startBtnLabel.y = 1250 - startBtn.height / 2 - 30;' Line Number: 228
User prompt
Add start worlds to start button top
User prompt
Do İnteract volume button
User prompt
Remove start word top the start button
User prompt
Make visible volume button
User prompt
Make volume setting button move
User prompt
Do İnteract to volume setting
User prompt
Put down volume setting
User prompt
Make volume setting visible and under the start
User prompt
Mute all sound ond dead screen
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Obstacle class: moves in a straight or curved unpredictable path, fast var Obstacle = Container.expand(function () { var self = Container.call(this); // Randomly pick a shape and color var type = Math.floor(Math.random() * 4); var assetId = 'obstacleBox'; if (type === 1) assetId = 'obstacleEllipse'; if (type === 2) assetId = 'obstacleBox2'; if (type === 3) assetId = 'obstacleEllipse2'; var obstacleGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); obstacleGraphics.assetId = assetId; // Tint obstacles to a backrooms yellow obstacleGraphics.tint = 0xffe066; // Randomize size a bit for more chaos var scale = 0.8 + Math.random() * 0.7; obstacleGraphics.scaleX = scale; obstacleGraphics.scaleY = scale; // Movement: always target the player's current position at spawn // Start position: randomly from one of the four edges var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left var startX = 0, startY = 0, endX = 0, endY = 0; var w = 2048, h = 2732; // For curved movement, we use a simple parametric curve (sin/cos offset) self.curve = Math.random() < 0.5; // 50% chance to curve self.curvePhase = Math.random() * Math.PI * 2; self.curveAmp = 80 + Math.random() * 120; // Speed: fast, but random self.speed = 22 + Math.random() * 18; // px per frame // Set start position based on edge if (edge === 0) { // top startX = 100 + Math.random() * (w - 200); startY = -100; } else if (edge === 1) { // right startX = w + 100; startY = 100 + Math.random() * (h - 200); } else if (edge === 2) { // bottom startX = 100 + Math.random() * (w - 200); startY = h + 100; } else { // left startX = -100; startY = 100 + Math.random() * (h - 200); } // Target the player's current position at spawn if (typeof player !== "undefined" && player) { endX = player.x; endY = player.y; } else { // fallback to center if player not defined yet endX = w / 2; endY = h / 2; } self.x = startX; self.y = startY; self.startX = startX; self.startY = startY; self.endX = endX; self.endY = endY; // For movement progress self.progress = 0; // 0 to 1 // For collision detection self.lastIntersecting = false; // Update method: move along the path self.update = function () { // Move progress var dx = self.endX - self.startX; var dy = self.endY - self.startY; var dist = Math.sqrt(dx * dx + dy * dy); var totalFrames = dist / self.speed; self.progress += 1 / totalFrames; // Obstacles never stop: let them continue past the player and offscreen // Remove the progress clamp so they keep moving // (no if (self.progress > 1.1) ...) // Linear movement var px = self.startX + dx * self.progress; var py = self.startY + dy * self.progress; // Add curve if needed if (self.curve) { // Perpendicular direction var perpAngle = Math.atan2(dy, dx) + Math.PI / 2; var curveOffset = Math.sin(self.progress * Math.PI + self.curvePhase) * self.curveAmp; px += Math.cos(perpAngle) * curveOffset; py += Math.sin(perpAngle) * curveOffset; } self.x = px; self.y = py; }; return self; }); // Player class: draggable circle var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Tint player to a faded yellow for backrooms vibe playerGraphics.tint = 0xfff7b2; // --- Smaller hitbox for collision detection --- self.hitboxScale = 0.62; // 62% of visual size (smaller hitbox) self.getHitboxRect = function () { var w = playerGraphics.width * self.hitboxScale; var h = playerGraphics.height * self.hitboxScale; return { x: self.x - w / 2, y: self.y - h / 2, width: w, height: h }; }; // Override intersects to use smaller hitbox self.intersects = function (other) { var a = self.getHitboxRect(); var b; if (typeof other.getHitboxRect === "function") { b = other.getHitboxRect(); } else { // fallback to bounding box b = { x: other.x - other.width / 2, y: other.y - other.height / 2, width: other.width, height: other.height }; } return !(a.x + a.width < b.x || a.x > b.x + b.width || a.y + a.height < b.y || a.y > b.y + b.height); }; // --- Raster/grid overlay effect --- var gridRows = 6; var gridCols = 6; var gridW = playerGraphics.width; var gridH = playerGraphics.height; var cellW = gridW / gridCols; var cellH = gridH / gridRows; for (var gx = 0; gx < gridCols; gx++) { for (var gy = 0; gy < gridRows; gy++) { // Use a small rectangle asset for the raster cell var cell = self.attachAsset('obstacleBox2', { anchorX: 0.5, anchorY: 0.5, scaleX: cellW / 20 * 0.85, scaleY: cellH / 30 * 0.85, x: (gx - (gridCols - 1) / 2) * cellW, y: (gy - (gridRows - 1) / 2) * cellH, tint: 0xffffff }); cell.alpha = 0.18 + 0.08 * ((gx + gy) % 2); // subtle grid } } // For touch feedback self.flash = function () { tween(playerGraphics, { tint: 0xff0000 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { tween(playerGraphics, { tint: 0xffffff }, { duration: 200, easing: tween.linear }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xffe066 // Backrooms yellow }); /**** * Game Code ****/ // LK.init.sound('dodge', {volume: 0.5}); // Sound for dodge (optional, not used as per guidelines) // Player: small, bright circle // Obstacles: fast-moving, unpredictable shapes (boxes and ellipses, different colors/sizes) // Game variables // Toplist icon as a top tier image asset function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var player = new Player(); var obstacles = []; var dragNode = null; var lastGameOver = false; var timeSurvived = 0; // in ms var timerText = null; var spawnInterval = 36; // frames between spawns, will decrease var minSpawnInterval = 12; var spawnTick = 0; var gameOver = false; // --- Main Menu Overlay --- // Remove old overlay if present (defensive) if (typeof mainMenuOverlay !== "undefined" && mainMenuOverlay && mainMenuOverlay.parent) { mainMenuOverlay.parent.removeChild(mainMenuOverlay); } var mainMenuOverlay = new Container(); mainMenuOverlay.zIndex = 10000; // ensure on top // Animated, layered background var menuBg = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 32, scaleY: 44, x: 2048 / 2, y: 2732 / 2 }); menuBg.alpha = 0.96; menuBg.tint = 0x181818; mainMenuOverlay.addChild(menuBg); // Add a subtle, animated "glow" behind the title var glow = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 2.2, x: 2048 / 2, y: 600 }); glow.alpha = 0.22; glow.tint = 0xffe066; mainMenuOverlay.addChild(glow); // Title with shadow effect var titleText = new Text2('DODGE THE CHAOS', { size: 200, fill: 0xFFE066 }); titleText.anchor.set(0.5, 0); titleText.x = 2048 / 2; titleText.y = 420; // Add shadow first so it's behind the title var titleShadow = new Text2('DODGE THE CHAOS', { size: 200, fill: "#000" }); titleShadow.anchor.set(0.5, 0); titleShadow.x = 2048 / 2 + 8; titleShadow.y = 420 + 10; titleShadow.alpha = 0.18; mainMenuOverlay.addChild(titleShadow); mainMenuOverlay.addChild(titleText); // Subtitle with more punch var subtitleText = new Text2('Survive as long as you can\nby dodging unpredictable obstacles!', { size: 90, fill: "#fff" }); subtitleText.anchor.set(0.5, 0); subtitleText.x = 2048 / 2; subtitleText.y = 670; mainMenuOverlay.addChild(subtitleText); // Start Button (now using a new image asset for the button) var startBtn = LK.getAsset('startBtnImage', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, x: 2048 / 2, y: 1250 }); mainMenuOverlay.addChild(startBtn); // Optional: add a subtle glow behind the image button for effect var startBtnGlow = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.2, scaleY: 0.7, x: 2048 / 2, y: 1250 }); startBtnGlow.tint = 0x83de44; startBtnGlow.alpha = 0.18; mainMenuOverlay.addChild(startBtnGlow); // Optional: add text overlay for accessibility/clarity var startBtnText = new Text2('START', { size: 130, fill: "#222" }); startBtnText.anchor.set(0.5, 0.5); startBtnText.x = 2048 / 2; startBtnText.y = 1250; mainMenuOverlay.addChild(startBtnText); // Add a "How to Play" quick tip var tipText = new Text2('Drag the player to dodge!\nTouch START to begin.', { size: 70, fill: 0xFFE066 }); tipText.anchor.set(0.5, 0); tipText.x = 2048 / 2; tipText.y = 1450; mainMenuOverlay.addChild(tipText); // Show overlay game.addChild(mainMenuOverlay); // --- Volume Slider UI --- // Retrieve saved volume or default to 1 var currentVolume = 1; if (typeof storage.getItem === "function") { var savedVol = storage.getItem("volume"); if (typeof savedVol === "number" && savedVol >= 0 && savedVol <= 1) { currentVolume = savedVol; } } // Draw slider bar var sliderBar = LK.getAsset('obstacleBox2', { anchorX: 0, anchorY: 0.5, scaleX: 12, scaleY: 0.7, x: 2048 / 2 - 300, y: 1100, //{1E} // moved up above start button tint: 0xcccccc }); sliderBar.alpha = 0.32; mainMenuOverlay.addChild(sliderBar); // Draw slider knob var sliderKnob = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, x: 2048 / 2 - 300 + 600 * currentVolume, y: 1100, //{1K} // moved up above start button tint: 0x4e9ae7 }); sliderKnob.alpha = 0.9; mainMenuOverlay.addChild(sliderKnob); // Volume label var sliderLabel = new Text2('VOLUME', { size: 70, fill: "#fff" }); sliderLabel.anchor.set(1, 0.5); sliderLabel.x = 2048 / 2 - 340; sliderLabel.y = 1100; // moved up above start button mainMenuOverlay.addChild(sliderLabel); // Volume percent text var sliderValueText = new Text2(Math.round(currentVolume * 100) + "%", { size: 70, fill: "#fff" }); sliderValueText.anchor.set(0, 0.5); sliderValueText.x = 2048 / 2 + 340; sliderValueText.y = 1100; // moved up above start button mainMenuOverlay.addChild(sliderValueText); // Helper for updating volume function setVolume(vol) { if (vol < 0) vol = 0; if (vol > 1) vol = 1; currentVolume = vol; sliderKnob.x = 2048 / 2 - 300 + 600 * currentVolume; sliderValueText.setText(Math.round(currentVolume * 100) + "%"); if (typeof LK.setMasterVolume === "function") { LK.setMasterVolume(currentVolume); } if (typeof storage.setItem === "function") { storage.setItem("volume", currentVolume); } } // Set initial volume setVolume(currentVolume); // Slider drag logic var sliderDragging = false; mainMenuOverlay.move = function (x, y, obj) { if (!sliderDragging) return; // Clamp x to slider bar var sx = x - (2048 / 2 - 300); var vol = sx / 600; setVolume(vol); }; mainMenuOverlay.down = function (origDown) { return function (x, y, obj) { // Check if touch is on slider knob or bar var knobDx = x - sliderKnob.x; var knobDy = y - sliderKnob.y; if (knobDx * knobDx + knobDy * knobDy < sliderKnob.width / 2 * (sliderKnob.width / 2)) { sliderDragging = true; mainMenuOverlay.move(x, y, obj); return; } // Check if touch is on slider bar var barRect = { x: sliderBar.x, y: sliderBar.y - sliderBar.height / 2, width: sliderBar.width, height: sliderBar.height }; if (x >= barRect.x && x <= barRect.x + barRect.width && y >= barRect.y && y <= barRect.y + barRect.height) { sliderDragging = true; mainMenuOverlay.move(x, y, obj); return; } // Otherwise, call original down (start button) if (typeof origDown === "function") origDown(x, y, obj); }; }(mainMenuOverlay.down); mainMenuOverlay.up = function (x, y, obj) { sliderDragging = false; }; game.up = function (origUp) { return function (x, y, obj) { if (typeof mainMenuOverlay.up === "function") mainMenuOverlay.up(x, y, obj); if (typeof origUp === "function") origUp(x, y, obj); }; }(game.up); // Block game logic until started var menuActive = true; // Animate menu elements for polish tween(glow, { scaleX: 10, scaleY: 2.7, alpha: 0.32 }, { duration: 1200, yoyo: true, repeat: Infinity, easing: tween.sineInOut }); // Start button interaction mainMenuOverlay.down = function (x, y, obj) { // Only start if touch/click is on the button var dx = x - startBtn.x; var dy = y - startBtn.y; var w = startBtn.width / 2, h = startBtn.height / 2; if (dx >= -w && dx <= w && dy >= -h && dy <= h) { // Unmute all sounds when starting game if (typeof LK.unmuteAllSounds === "function") { LK.unmuteAllSounds(); } // Animate out tween(mainMenuOverlay, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { mainMenuOverlay.visible = false; menuActive = false; player.visible = true; // Show player when game starts } }); } }; mainMenuOverlay.interactive = true; // Place player at center (do not add to mainMenuOverlay, only to game scene) player.x = 2048 / 2; player.y = 2732 / 2; player.visible = false; // Hide player in main menu game.addChild(player); // (Meme corner logic removed) // Timer text (top center) timerText = new Text2('0.00', { size: 120, fill: "#fff" }); timerText.anchor.set(0.5, 0); LK.gui.top.addChild(timerText); // Prevent player from being placed in top left 100x100 function clampPlayerPosition(x, y) { var px = x, py = y; var r = player.width / 2; if (px < r + 10) px = r + 10; if (px > 2048 - r - 10) px = 2048 - r - 10; if (py < r + 10) py = r + 10; if (py > 2732 - r - 10) py = 2732 - r - 10; // Avoid top left menu if (px - r < 100 && py - r < 100) { if (px > py) px = 100 + r + 10;else py = 100 + r + 10; } return { x: px, y: py }; } // Dragging logic function handleMove(x, y, obj) { if (menuActive || gameOver) return; if (dragNode) { var pos = clampPlayerPosition(x, y); dragNode.x = pos.x; dragNode.y = pos.y; } } game.move = handleMove; game.down = function (x, y, obj) { if (menuActive) return; // Only allow drag if touch is on player var dx = x - player.x; var dy = y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < player.width / 2 + 10) { dragNode = player; handleMove(x, y, obj); } }; game.up = function (x, y, obj) { if (menuActive) return; dragNode = null; }; // --- Leaderboard Overlay --- // Remade leaderboard overlay with a new visual style and layout var leaderboardOverlay = new Container(); leaderboardOverlay.zIndex = 9999; leaderboardOverlay.visible = false; // New background: larger, more vibrant, with a subtle border var lbBg = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 24, x: 2048 / 2, y: 2732 / 2 }); lbBg.alpha = 0.97; lbBg.tint = 0x181818; leaderboardOverlay.addChild(lbBg); // Add a glowing border effect var lbGlow = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 21.5, scaleY: 25.5, x: 2048 / 2, y: 2732 / 2 }); lbGlow.alpha = 0.13; lbGlow.tint = 0xffe066; leaderboardOverlay.addChild(lbGlow); // Top tier icon, larger and with a glow var lbIcon = LK.getAsset('topTierIcon', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 340, scaleX: 1.6, scaleY: 1.6 }); leaderboardOverlay.addChild(lbIcon); var lbIconGlow = LK.getAsset('topTierIcon', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 340, scaleX: 2.2, scaleY: 2.2 }); lbIconGlow.alpha = 0.18; lbIconGlow.tint = 0xffe066; leaderboardOverlay.addChild(lbIconGlow); // Title with shadow and highlight var lbTitleShadow = new Text2('TOP PLAYERS', { size: 140, fill: "#000" }); lbTitleShadow.anchor.set(0.5, 0); lbTitleShadow.x = 2048 / 2 + 8; lbTitleShadow.y = 440 + 10; lbTitleShadow.alpha = 0.18; leaderboardOverlay.addChild(lbTitleShadow); var lbTitle = new Text2('TOP PLAYERS', { size: 140, fill: 0xFFE066 }); lbTitle.anchor.set(0.5, 0); lbTitle.x = 2048 / 2; lbTitle.y = 440; leaderboardOverlay.addChild(lbTitle); // Subtitle var lbSubtitle = new Text2('Survive the chaos. Can you make the list?', { size: 70, fill: "#fff" }); lbSubtitle.anchor.set(0.5, 0); lbSubtitle.x = 2048 / 2; lbSubtitle.y = 600; leaderboardOverlay.addChild(lbSubtitle); // List of top players, larger and more spaced var lbListText = new Text2('', { size: 100, fill: "#fff" }); lbListText.anchor.set(0.5, 0); lbListText.x = 2048 / 2; lbListText.y = 740; leaderboardOverlay.addChild(lbListText); // Close button: new style, round and more visible var lbCloseBtn = LK.getAsset('topTierIcon', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, x: 2048 / 2, y: 2200 }); lbCloseBtn.tint = 0xd83318; leaderboardOverlay.addChild(lbCloseBtn); var lbCloseBtnGlow = LK.getAsset('topTierIcon', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.1, scaleY: 2.1, x: 2048 / 2, y: 2200 }); lbCloseBtnGlow.tint = 0xd83318; lbCloseBtnGlow.alpha = 0.13; leaderboardOverlay.addChild(lbCloseBtnGlow); var lbCloseText = new Text2('CLOSE', { size: 90, fill: "#fff" }); lbCloseText.anchor.set(0.5, 0.5); lbCloseText.x = 2048 / 2; lbCloseText.y = 2200; leaderboardOverlay.addChild(lbCloseText); // Show leaderboard overlay function showLeaderboard() { // Get top 5 scores from storage (convert 1-level deep object to array) var scoresObj = storage.topScores || {}; var scores = []; for (var k in scoresObj) { if (scoresObj.hasOwnProperty(k)) scores.push(scoresObj[k]); } // Sort descending scores.sort(function (a, b) { return b.score - a.score; }); // Format for display var lines = []; for (var i = 0; i < Math.min(5, scores.length); i++) { var entry = scores[i]; // Add a trophy emoji for top 1, 2, 3 var trophy = ""; if (i === 0) trophy = "🥇 ";else if (i === 1) trophy = "🥈 ";else if (i === 2) trophy = "🥉 "; lines.push(trophy + (i + 1) + ". " + (entry.name && entry.name.length > 0 ? entry.name : "Player") + " - " + entry.score.toFixed(2) + "s"); } if (lines.length === 0) lines.push("No scores yet!"); lbListText.setText(lines.join("\n\n")); // Unmute all sounds when showing leaderboard if (typeof LK.unmuteAllSounds === "function") { LK.unmuteAllSounds(); } leaderboardOverlay.visible = true; leaderboardOverlay.alpha = 1; } lbCloseBtn.interactive = true; leaderboardOverlay.down = function (x, y, obj) { // Only close if touch/click is on the button var dx = x - lbCloseBtn.x; var dy = y - lbCloseBtn.y; var w = lbCloseBtn.width / 2, h = lbCloseBtn.height / 2; if (dx >= -w && dx <= w && dy >= -h && dy <= h) { leaderboardOverlay.visible = false; } }; game.addChild(leaderboardOverlay); // (Leaderboard button removed from main menu overlay) // Main update loop game.update = function () { if (menuActive || gameOver) { // Ensure volume is set when menu is active (in case of reload) if (typeof LK.setMasterVolume === "function" && typeof currentVolume !== "undefined") { LK.setMasterVolume(currentVolume); } return; } // Update timer timeSurvived += 1000 / 60; var t = Math.floor(timeSurvived) / 1000; timerText.setText(t.toFixed(2)); // Increase difficulty over time if (timeSurvived > 8000 && spawnInterval > minSpawnInterval) { spawnInterval = 24; } if (timeSurvived > 18000 && spawnInterval > minSpawnInterval) { spawnInterval = 16; } if (timeSurvived > 30000 && spawnInterval > minSpawnInterval) { spawnInterval = minSpawnInterval; } // Spawn new obstacles spawnTick++; if (spawnTick >= spawnInterval) { spawnTick = 0; var obs = new Obstacle(); obstacles.push(obs); game.addChild(obs); // Play Panda sound if obstacle is of type obstacleEllipse2 if (obs && obs.children && obs.children[0] && obs.children[0].assetId === 'obstacleEllipse2') { LK.getSound('Panda').play(); } // Play Papa sound if obstacle is of type obstacleEllipse if (obs && obs.children && obs.children[0] && obs.children[0].assetId === 'obstacleEllipse') { LK.getSound('Papa').play(); } // Play Kanye sound if obstacle is of type obstacleBox2 if (obs && obs.children && obs.children[0] && obs.children[0].assetId === 'obstacleBox2') { LK.getSound('Kanye').play(); } // Play Godzilla sound if obstacle is of type obstacleBox if (obs && obs.children && obs.children[0] && obs.children[0].assetId === 'obstacleBox') { LK.getSound('Godzilla').play(); } } // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.update(); // Remove if far offscreen (let them go well past the screen) if (obs.x < -400 || obs.x > 2048 + 400 || obs.y < -400 || obs.y > 2732 + 400) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision detection var intersecting = obs.intersects && player.intersects ? player.intersects(obs) : obs.intersects(player); if (!obs.lastIntersecting && intersecting) { // Game over: flash, then show dead screen overlay player.flash(); LK.effects.flashScreen(0xff0000, 800); gameOver = true; // Mute all sounds when dead screen is shown if (typeof LK.muteAllSounds === "function") { LK.muteAllSounds(); } // Show dead screen overlay if (typeof deadScreenOverlay !== "undefined" && deadScreenOverlay && deadScreenOverlay.parent) { deadScreenOverlay.parent.removeChild(deadScreenOverlay); } var deadScreenOverlay = new Container(); deadScreenOverlay.zIndex = 10001; // Background var deadBg = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 24, x: 2048 / 2, y: 2732 / 2 }); deadBg.alpha = 0.97; deadBg.tint = 0x181818; deadScreenOverlay.addChild(deadBg); // Glow var deadGlow = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 21.5, scaleY: 25.5, x: 2048 / 2, y: 2732 / 2 }); deadGlow.alpha = 0.13; deadGlow.tint = 0xff0000; deadScreenOverlay.addChild(deadGlow); // Title var deadTitleShadow = new Text2('YOU DIED', { size: 180, fill: "#000" }); deadTitleShadow.anchor.set(0.5, 0); deadTitleShadow.x = 2048 / 2 + 8; deadTitleShadow.y = 700 + 10; deadTitleShadow.alpha = 0.18; deadScreenOverlay.addChild(deadTitleShadow); var deadTitle = new Text2('YOU DIED', { size: 180, fill: 0xff0000 }); deadTitle.anchor.set(0.5, 0); deadTitle.x = 2048 / 2; deadTitle.y = 700; deadScreenOverlay.addChild(deadTitle); // Subtitle var deadSubtitle = new Text2('Survived: ' + (Math.floor(timeSurvived) / 1000).toFixed(2) + 's', { size: 90, fill: "#fff" }); deadSubtitle.anchor.set(0.5, 0); deadSubtitle.x = 2048 / 2; deadSubtitle.y = 900; deadScreenOverlay.addChild(deadSubtitle); // Restart Button (replaces Main Menu) var restartBtn = LK.getAsset('startBtnImage', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 1.0, x: 2048 / 2, y: 1400 }); deadScreenOverlay.addChild(restartBtn); var restartBtnGlow = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.2, scaleY: 0.7, x: 2048 / 2, y: 1400 }); restartBtnGlow.tint = 0x83de44; restartBtnGlow.alpha = 0.18; deadScreenOverlay.addChild(restartBtnGlow); var restartBtnText = new Text2('RESTART', { size: 130, fill: "#222" }); restartBtnText.anchor.set(0.5, 0.5); restartBtnText.x = 2048 / 2; restartBtnText.y = 1400; deadScreenOverlay.addChild(restartBtnText); // Optionally, add a "Leaderboard" button var mainMenuBtn = LK.getAsset('topTierIcon', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, x: 2048 / 2, y: 1700 }); mainMenuBtn.tint = 0x4e9ae7; deadScreenOverlay.addChild(mainMenuBtn); var mainMenuBtnText = new Text2('MAIN MENU', { size: 90, fill: "#fff" }); mainMenuBtnText.anchor.set(0.5, 0.5); mainMenuBtnText.x = 2048 / 2; mainMenuBtnText.y = 1700; deadScreenOverlay.addChild(mainMenuBtnText); // Interactivity deadScreenOverlay.interactive = true; deadScreenOverlay.down = function (x, y, obj) { // Restart button var dx = x - restartBtn.x; var dy = y - restartBtn.y; var w = restartBtn.width / 2, h = restartBtn.height / 2; if (dx >= -w && dx <= w && dy >= -h && dy <= h) { deadScreenOverlay.visible = false; // Mute all sounds on restart if (typeof LK.muteAllSounds === "function") { LK.muteAllSounds(); } // Instantly restart the game: hide overlays, reset state, and start game mainMenuOverlay.visible = false; menuActive = false; player.visible = true; gameOver = false; timeSurvived = 0; spawnInterval = 36; spawnTick = 0; timerText.setText('0.00'); // Remove all obstacles for (var i = 0; i < obstacles.length; i++) { obstacles[i].destroy(); } obstacles = []; // Reset player position player.x = 2048 / 2; player.y = 2732 / 2; dragNode = null; return; } // Main Menu button var dx2 = x - mainMenuBtn.x; var dy2 = y - mainMenuBtn.y; var w2 = mainMenuBtn.width / 2, h2 = mainMenuBtn.height / 2; if (dx2 >= -w2 && dx2 <= w2 && dy2 >= -h2 && dy2 <= h2) { deadScreenOverlay.visible = false; // Mute all sounds when returning to main menu if (typeof LK.muteAllSounds === "function") { LK.muteAllSounds(); } // Unmute all sounds when returning to main menu if (typeof LK.unmuteAllSounds === "function") { LK.unmuteAllSounds(); } mainMenuOverlay.visible = true; mainMenuOverlay.alpha = 1; menuActive = true; player.visible = false; return; } }; game.addChild(deadScreenOverlay); break; } obs.lastIntersecting = intersecting; } }; // Reset logic (when game restarts) game.on('reset', function () { // Remove all obstacles for (var i = 0; i < obstacles.length; i++) { obstacles[i].destroy(); } obstacles = []; // Reset player position player.x = 2048 / 2; player.y = 2732 / 2; dragNode = null; timeSurvived = 0; spawnInterval = 36; spawnTick = 0; gameOver = false; timerText.setText('0.00'); // Hide dead screen overlay if present if (typeof deadScreenOverlay !== "undefined" && deadScreenOverlay) { deadScreenOverlay.visible = false; } // Show main menu again mainMenuOverlay.visible = true; mainMenuOverlay.alpha = 1; menuActive = true; player.visible = false; // Hide player in main menu after reset // Mute all sounds on reset when showing main menu if (typeof LK.muteAllSounds === "function") { LK.muteAllSounds(); } // Restore volume setting on reset if (typeof LK.setMasterVolume === "function" && typeof currentVolume !== "undefined") { LK.setMasterVolume(currentVolume); } });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Obstacle class: moves in a straight or curved unpredictable path, fast
var Obstacle = Container.expand(function () {
var self = Container.call(this);
// Randomly pick a shape and color
var type = Math.floor(Math.random() * 4);
var assetId = 'obstacleBox';
if (type === 1) assetId = 'obstacleEllipse';
if (type === 2) assetId = 'obstacleBox2';
if (type === 3) assetId = 'obstacleEllipse2';
var obstacleGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
obstacleGraphics.assetId = assetId;
// Tint obstacles to a backrooms yellow
obstacleGraphics.tint = 0xffe066;
// Randomize size a bit for more chaos
var scale = 0.8 + Math.random() * 0.7;
obstacleGraphics.scaleX = scale;
obstacleGraphics.scaleY = scale;
// Movement: always target the player's current position at spawn
// Start position: randomly from one of the four edges
var edge = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
var startX = 0,
startY = 0,
endX = 0,
endY = 0;
var w = 2048,
h = 2732;
// For curved movement, we use a simple parametric curve (sin/cos offset)
self.curve = Math.random() < 0.5; // 50% chance to curve
self.curvePhase = Math.random() * Math.PI * 2;
self.curveAmp = 80 + Math.random() * 120;
// Speed: fast, but random
self.speed = 22 + Math.random() * 18; // px per frame
// Set start position based on edge
if (edge === 0) {
// top
startX = 100 + Math.random() * (w - 200);
startY = -100;
} else if (edge === 1) {
// right
startX = w + 100;
startY = 100 + Math.random() * (h - 200);
} else if (edge === 2) {
// bottom
startX = 100 + Math.random() * (w - 200);
startY = h + 100;
} else {
// left
startX = -100;
startY = 100 + Math.random() * (h - 200);
}
// Target the player's current position at spawn
if (typeof player !== "undefined" && player) {
endX = player.x;
endY = player.y;
} else {
// fallback to center if player not defined yet
endX = w / 2;
endY = h / 2;
}
self.x = startX;
self.y = startY;
self.startX = startX;
self.startY = startY;
self.endX = endX;
self.endY = endY;
// For movement progress
self.progress = 0; // 0 to 1
// For collision detection
self.lastIntersecting = false;
// Update method: move along the path
self.update = function () {
// Move progress
var dx = self.endX - self.startX;
var dy = self.endY - self.startY;
var dist = Math.sqrt(dx * dx + dy * dy);
var totalFrames = dist / self.speed;
self.progress += 1 / totalFrames;
// Obstacles never stop: let them continue past the player and offscreen
// Remove the progress clamp so they keep moving
// (no if (self.progress > 1.1) ...)
// Linear movement
var px = self.startX + dx * self.progress;
var py = self.startY + dy * self.progress;
// Add curve if needed
if (self.curve) {
// Perpendicular direction
var perpAngle = Math.atan2(dy, dx) + Math.PI / 2;
var curveOffset = Math.sin(self.progress * Math.PI + self.curvePhase) * self.curveAmp;
px += Math.cos(perpAngle) * curveOffset;
py += Math.sin(perpAngle) * curveOffset;
}
self.x = px;
self.y = py;
};
return self;
});
// Player class: draggable circle
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint player to a faded yellow for backrooms vibe
playerGraphics.tint = 0xfff7b2;
// --- Smaller hitbox for collision detection ---
self.hitboxScale = 0.62; // 62% of visual size (smaller hitbox)
self.getHitboxRect = function () {
var w = playerGraphics.width * self.hitboxScale;
var h = playerGraphics.height * self.hitboxScale;
return {
x: self.x - w / 2,
y: self.y - h / 2,
width: w,
height: h
};
};
// Override intersects to use smaller hitbox
self.intersects = function (other) {
var a = self.getHitboxRect();
var b;
if (typeof other.getHitboxRect === "function") {
b = other.getHitboxRect();
} else {
// fallback to bounding box
b = {
x: other.x - other.width / 2,
y: other.y - other.height / 2,
width: other.width,
height: other.height
};
}
return !(a.x + a.width < b.x || a.x > b.x + b.width || a.y + a.height < b.y || a.y > b.y + b.height);
};
// --- Raster/grid overlay effect ---
var gridRows = 6;
var gridCols = 6;
var gridW = playerGraphics.width;
var gridH = playerGraphics.height;
var cellW = gridW / gridCols;
var cellH = gridH / gridRows;
for (var gx = 0; gx < gridCols; gx++) {
for (var gy = 0; gy < gridRows; gy++) {
// Use a small rectangle asset for the raster cell
var cell = self.attachAsset('obstacleBox2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: cellW / 20 * 0.85,
scaleY: cellH / 30 * 0.85,
x: (gx - (gridCols - 1) / 2) * cellW,
y: (gy - (gridRows - 1) / 2) * cellH,
tint: 0xffffff
});
cell.alpha = 0.18 + 0.08 * ((gx + gy) % 2); // subtle grid
}
}
// For touch feedback
self.flash = function () {
tween(playerGraphics, {
tint: 0xff0000
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
tween(playerGraphics, {
tint: 0xffffff
}, {
duration: 200,
easing: tween.linear
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xffe066 // Backrooms yellow
});
/****
* Game Code
****/
// LK.init.sound('dodge', {volume: 0.5});
// Sound for dodge (optional, not used as per guidelines)
// Player: small, bright circle
// Obstacles: fast-moving, unpredictable shapes (boxes and ellipses, different colors/sizes)
// Game variables
// Toplist icon as a top tier image asset
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var player = new Player();
var obstacles = [];
var dragNode = null;
var lastGameOver = false;
var timeSurvived = 0; // in ms
var timerText = null;
var spawnInterval = 36; // frames between spawns, will decrease
var minSpawnInterval = 12;
var spawnTick = 0;
var gameOver = false;
// --- Main Menu Overlay ---
// Remove old overlay if present (defensive)
if (typeof mainMenuOverlay !== "undefined" && mainMenuOverlay && mainMenuOverlay.parent) {
mainMenuOverlay.parent.removeChild(mainMenuOverlay);
}
var mainMenuOverlay = new Container();
mainMenuOverlay.zIndex = 10000; // ensure on top
// Animated, layered background
var menuBg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 32,
scaleY: 44,
x: 2048 / 2,
y: 2732 / 2
});
menuBg.alpha = 0.96;
menuBg.tint = 0x181818;
mainMenuOverlay.addChild(menuBg);
// Add a subtle, animated "glow" behind the title
var glow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 2.2,
x: 2048 / 2,
y: 600
});
glow.alpha = 0.22;
glow.tint = 0xffe066;
mainMenuOverlay.addChild(glow);
// Title with shadow effect
var titleText = new Text2('DODGE THE CHAOS', {
size: 200,
fill: 0xFFE066
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 420;
// Add shadow first so it's behind the title
var titleShadow = new Text2('DODGE THE CHAOS', {
size: 200,
fill: "#000"
});
titleShadow.anchor.set(0.5, 0);
titleShadow.x = 2048 / 2 + 8;
titleShadow.y = 420 + 10;
titleShadow.alpha = 0.18;
mainMenuOverlay.addChild(titleShadow);
mainMenuOverlay.addChild(titleText);
// Subtitle with more punch
var subtitleText = new Text2('Survive as long as you can\nby dodging unpredictable obstacles!', {
size: 90,
fill: "#fff"
});
subtitleText.anchor.set(0.5, 0);
subtitleText.x = 2048 / 2;
subtitleText.y = 670;
mainMenuOverlay.addChild(subtitleText);
// Start Button (now using a new image asset for the button)
var startBtn = LK.getAsset('startBtnImage', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
x: 2048 / 2,
y: 1250
});
mainMenuOverlay.addChild(startBtn);
// Optional: add a subtle glow behind the image button for effect
var startBtnGlow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 0.7,
x: 2048 / 2,
y: 1250
});
startBtnGlow.tint = 0x83de44;
startBtnGlow.alpha = 0.18;
mainMenuOverlay.addChild(startBtnGlow);
// Optional: add text overlay for accessibility/clarity
var startBtnText = new Text2('START', {
size: 130,
fill: "#222"
});
startBtnText.anchor.set(0.5, 0.5);
startBtnText.x = 2048 / 2;
startBtnText.y = 1250;
mainMenuOverlay.addChild(startBtnText);
// Add a "How to Play" quick tip
var tipText = new Text2('Drag the player to dodge!\nTouch START to begin.', {
size: 70,
fill: 0xFFE066
});
tipText.anchor.set(0.5, 0);
tipText.x = 2048 / 2;
tipText.y = 1450;
mainMenuOverlay.addChild(tipText);
// Show overlay
game.addChild(mainMenuOverlay);
// --- Volume Slider UI ---
// Retrieve saved volume or default to 1
var currentVolume = 1;
if (typeof storage.getItem === "function") {
var savedVol = storage.getItem("volume");
if (typeof savedVol === "number" && savedVol >= 0 && savedVol <= 1) {
currentVolume = savedVol;
}
}
// Draw slider bar
var sliderBar = LK.getAsset('obstacleBox2', {
anchorX: 0,
anchorY: 0.5,
scaleX: 12,
scaleY: 0.7,
x: 2048 / 2 - 300,
y: 1100,
//{1E} // moved up above start button
tint: 0xcccccc
});
sliderBar.alpha = 0.32;
mainMenuOverlay.addChild(sliderBar);
// Draw slider knob
var sliderKnob = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
x: 2048 / 2 - 300 + 600 * currentVolume,
y: 1100,
//{1K} // moved up above start button
tint: 0x4e9ae7
});
sliderKnob.alpha = 0.9;
mainMenuOverlay.addChild(sliderKnob);
// Volume label
var sliderLabel = new Text2('VOLUME', {
size: 70,
fill: "#fff"
});
sliderLabel.anchor.set(1, 0.5);
sliderLabel.x = 2048 / 2 - 340;
sliderLabel.y = 1100; // moved up above start button
mainMenuOverlay.addChild(sliderLabel);
// Volume percent text
var sliderValueText = new Text2(Math.round(currentVolume * 100) + "%", {
size: 70,
fill: "#fff"
});
sliderValueText.anchor.set(0, 0.5);
sliderValueText.x = 2048 / 2 + 340;
sliderValueText.y = 1100; // moved up above start button
mainMenuOverlay.addChild(sliderValueText);
// Helper for updating volume
function setVolume(vol) {
if (vol < 0) vol = 0;
if (vol > 1) vol = 1;
currentVolume = vol;
sliderKnob.x = 2048 / 2 - 300 + 600 * currentVolume;
sliderValueText.setText(Math.round(currentVolume * 100) + "%");
if (typeof LK.setMasterVolume === "function") {
LK.setMasterVolume(currentVolume);
}
if (typeof storage.setItem === "function") {
storage.setItem("volume", currentVolume);
}
}
// Set initial volume
setVolume(currentVolume);
// Slider drag logic
var sliderDragging = false;
mainMenuOverlay.move = function (x, y, obj) {
if (!sliderDragging) return;
// Clamp x to slider bar
var sx = x - (2048 / 2 - 300);
var vol = sx / 600;
setVolume(vol);
};
mainMenuOverlay.down = function (origDown) {
return function (x, y, obj) {
// Check if touch is on slider knob or bar
var knobDx = x - sliderKnob.x;
var knobDy = y - sliderKnob.y;
if (knobDx * knobDx + knobDy * knobDy < sliderKnob.width / 2 * (sliderKnob.width / 2)) {
sliderDragging = true;
mainMenuOverlay.move(x, y, obj);
return;
}
// Check if touch is on slider bar
var barRect = {
x: sliderBar.x,
y: sliderBar.y - sliderBar.height / 2,
width: sliderBar.width,
height: sliderBar.height
};
if (x >= barRect.x && x <= barRect.x + barRect.width && y >= barRect.y && y <= barRect.y + barRect.height) {
sliderDragging = true;
mainMenuOverlay.move(x, y, obj);
return;
}
// Otherwise, call original down (start button)
if (typeof origDown === "function") origDown(x, y, obj);
};
}(mainMenuOverlay.down);
mainMenuOverlay.up = function (x, y, obj) {
sliderDragging = false;
};
game.up = function (origUp) {
return function (x, y, obj) {
if (typeof mainMenuOverlay.up === "function") mainMenuOverlay.up(x, y, obj);
if (typeof origUp === "function") origUp(x, y, obj);
};
}(game.up);
// Block game logic until started
var menuActive = true;
// Animate menu elements for polish
tween(glow, {
scaleX: 10,
scaleY: 2.7,
alpha: 0.32
}, {
duration: 1200,
yoyo: true,
repeat: Infinity,
easing: tween.sineInOut
});
// Start button interaction
mainMenuOverlay.down = function (x, y, obj) {
// Only start if touch/click is on the button
var dx = x - startBtn.x;
var dy = y - startBtn.y;
var w = startBtn.width / 2,
h = startBtn.height / 2;
if (dx >= -w && dx <= w && dy >= -h && dy <= h) {
// Unmute all sounds when starting game
if (typeof LK.unmuteAllSounds === "function") {
LK.unmuteAllSounds();
}
// Animate out
tween(mainMenuOverlay, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
mainMenuOverlay.visible = false;
menuActive = false;
player.visible = true; // Show player when game starts
}
});
}
};
mainMenuOverlay.interactive = true;
// Place player at center (do not add to mainMenuOverlay, only to game scene)
player.x = 2048 / 2;
player.y = 2732 / 2;
player.visible = false; // Hide player in main menu
game.addChild(player);
// (Meme corner logic removed)
// Timer text (top center)
timerText = new Text2('0.00', {
size: 120,
fill: "#fff"
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
// Prevent player from being placed in top left 100x100
function clampPlayerPosition(x, y) {
var px = x,
py = y;
var r = player.width / 2;
if (px < r + 10) px = r + 10;
if (px > 2048 - r - 10) px = 2048 - r - 10;
if (py < r + 10) py = r + 10;
if (py > 2732 - r - 10) py = 2732 - r - 10;
// Avoid top left menu
if (px - r < 100 && py - r < 100) {
if (px > py) px = 100 + r + 10;else py = 100 + r + 10;
}
return {
x: px,
y: py
};
}
// Dragging logic
function handleMove(x, y, obj) {
if (menuActive || gameOver) return;
if (dragNode) {
var pos = clampPlayerPosition(x, y);
dragNode.x = pos.x;
dragNode.y = pos.y;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (menuActive) return;
// Only allow drag if touch is on player
var dx = x - player.x;
var dy = y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < player.width / 2 + 10) {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
if (menuActive) return;
dragNode = null;
};
// --- Leaderboard Overlay ---
// Remade leaderboard overlay with a new visual style and layout
var leaderboardOverlay = new Container();
leaderboardOverlay.zIndex = 9999;
leaderboardOverlay.visible = false;
// New background: larger, more vibrant, with a subtle border
var lbBg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 24,
x: 2048 / 2,
y: 2732 / 2
});
lbBg.alpha = 0.97;
lbBg.tint = 0x181818;
leaderboardOverlay.addChild(lbBg);
// Add a glowing border effect
var lbGlow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 21.5,
scaleY: 25.5,
x: 2048 / 2,
y: 2732 / 2
});
lbGlow.alpha = 0.13;
lbGlow.tint = 0xffe066;
leaderboardOverlay.addChild(lbGlow);
// Top tier icon, larger and with a glow
var lbIcon = LK.getAsset('topTierIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 340,
scaleX: 1.6,
scaleY: 1.6
});
leaderboardOverlay.addChild(lbIcon);
var lbIconGlow = LK.getAsset('topTierIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 340,
scaleX: 2.2,
scaleY: 2.2
});
lbIconGlow.alpha = 0.18;
lbIconGlow.tint = 0xffe066;
leaderboardOverlay.addChild(lbIconGlow);
// Title with shadow and highlight
var lbTitleShadow = new Text2('TOP PLAYERS', {
size: 140,
fill: "#000"
});
lbTitleShadow.anchor.set(0.5, 0);
lbTitleShadow.x = 2048 / 2 + 8;
lbTitleShadow.y = 440 + 10;
lbTitleShadow.alpha = 0.18;
leaderboardOverlay.addChild(lbTitleShadow);
var lbTitle = new Text2('TOP PLAYERS', {
size: 140,
fill: 0xFFE066
});
lbTitle.anchor.set(0.5, 0);
lbTitle.x = 2048 / 2;
lbTitle.y = 440;
leaderboardOverlay.addChild(lbTitle);
// Subtitle
var lbSubtitle = new Text2('Survive the chaos. Can you make the list?', {
size: 70,
fill: "#fff"
});
lbSubtitle.anchor.set(0.5, 0);
lbSubtitle.x = 2048 / 2;
lbSubtitle.y = 600;
leaderboardOverlay.addChild(lbSubtitle);
// List of top players, larger and more spaced
var lbListText = new Text2('', {
size: 100,
fill: "#fff"
});
lbListText.anchor.set(0.5, 0);
lbListText.x = 2048 / 2;
lbListText.y = 740;
leaderboardOverlay.addChild(lbListText);
// Close button: new style, round and more visible
var lbCloseBtn = LK.getAsset('topTierIcon', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
x: 2048 / 2,
y: 2200
});
lbCloseBtn.tint = 0xd83318;
leaderboardOverlay.addChild(lbCloseBtn);
var lbCloseBtnGlow = LK.getAsset('topTierIcon', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.1,
scaleY: 2.1,
x: 2048 / 2,
y: 2200
});
lbCloseBtnGlow.tint = 0xd83318;
lbCloseBtnGlow.alpha = 0.13;
leaderboardOverlay.addChild(lbCloseBtnGlow);
var lbCloseText = new Text2('CLOSE', {
size: 90,
fill: "#fff"
});
lbCloseText.anchor.set(0.5, 0.5);
lbCloseText.x = 2048 / 2;
lbCloseText.y = 2200;
leaderboardOverlay.addChild(lbCloseText);
// Show leaderboard overlay
function showLeaderboard() {
// Get top 5 scores from storage (convert 1-level deep object to array)
var scoresObj = storage.topScores || {};
var scores = [];
for (var k in scoresObj) {
if (scoresObj.hasOwnProperty(k)) scores.push(scoresObj[k]);
}
// Sort descending
scores.sort(function (a, b) {
return b.score - a.score;
});
// Format for display
var lines = [];
for (var i = 0; i < Math.min(5, scores.length); i++) {
var entry = scores[i];
// Add a trophy emoji for top 1, 2, 3
var trophy = "";
if (i === 0) trophy = "🥇 ";else if (i === 1) trophy = "🥈 ";else if (i === 2) trophy = "🥉 ";
lines.push(trophy + (i + 1) + ". " + (entry.name && entry.name.length > 0 ? entry.name : "Player") + " - " + entry.score.toFixed(2) + "s");
}
if (lines.length === 0) lines.push("No scores yet!");
lbListText.setText(lines.join("\n\n"));
// Unmute all sounds when showing leaderboard
if (typeof LK.unmuteAllSounds === "function") {
LK.unmuteAllSounds();
}
leaderboardOverlay.visible = true;
leaderboardOverlay.alpha = 1;
}
lbCloseBtn.interactive = true;
leaderboardOverlay.down = function (x, y, obj) {
// Only close if touch/click is on the button
var dx = x - lbCloseBtn.x;
var dy = y - lbCloseBtn.y;
var w = lbCloseBtn.width / 2,
h = lbCloseBtn.height / 2;
if (dx >= -w && dx <= w && dy >= -h && dy <= h) {
leaderboardOverlay.visible = false;
}
};
game.addChild(leaderboardOverlay);
// (Leaderboard button removed from main menu overlay)
// Main update loop
game.update = function () {
if (menuActive || gameOver) {
// Ensure volume is set when menu is active (in case of reload)
if (typeof LK.setMasterVolume === "function" && typeof currentVolume !== "undefined") {
LK.setMasterVolume(currentVolume);
}
return;
}
// Update timer
timeSurvived += 1000 / 60;
var t = Math.floor(timeSurvived) / 1000;
timerText.setText(t.toFixed(2));
// Increase difficulty over time
if (timeSurvived > 8000 && spawnInterval > minSpawnInterval) {
spawnInterval = 24;
}
if (timeSurvived > 18000 && spawnInterval > minSpawnInterval) {
spawnInterval = 16;
}
if (timeSurvived > 30000 && spawnInterval > minSpawnInterval) {
spawnInterval = minSpawnInterval;
}
// Spawn new obstacles
spawnTick++;
if (spawnTick >= spawnInterval) {
spawnTick = 0;
var obs = new Obstacle();
obstacles.push(obs);
game.addChild(obs);
// Play Panda sound if obstacle is of type obstacleEllipse2
if (obs && obs.children && obs.children[0] && obs.children[0].assetId === 'obstacleEllipse2') {
LK.getSound('Panda').play();
}
// Play Papa sound if obstacle is of type obstacleEllipse
if (obs && obs.children && obs.children[0] && obs.children[0].assetId === 'obstacleEllipse') {
LK.getSound('Papa').play();
}
// Play Kanye sound if obstacle is of type obstacleBox2
if (obs && obs.children && obs.children[0] && obs.children[0].assetId === 'obstacleBox2') {
LK.getSound('Kanye').play();
}
// Play Godzilla sound if obstacle is of type obstacleBox
if (obs && obs.children && obs.children[0] && obs.children[0].assetId === 'obstacleBox') {
LK.getSound('Godzilla').play();
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.update();
// Remove if far offscreen (let them go well past the screen)
if (obs.x < -400 || obs.x > 2048 + 400 || obs.y < -400 || obs.y > 2732 + 400) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision detection
var intersecting = obs.intersects && player.intersects ? player.intersects(obs) : obs.intersects(player);
if (!obs.lastIntersecting && intersecting) {
// Game over: flash, then show dead screen overlay
player.flash();
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
// Mute all sounds when dead screen is shown
if (typeof LK.muteAllSounds === "function") {
LK.muteAllSounds();
}
// Show dead screen overlay
if (typeof deadScreenOverlay !== "undefined" && deadScreenOverlay && deadScreenOverlay.parent) {
deadScreenOverlay.parent.removeChild(deadScreenOverlay);
}
var deadScreenOverlay = new Container();
deadScreenOverlay.zIndex = 10001;
// Background
var deadBg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 24,
x: 2048 / 2,
y: 2732 / 2
});
deadBg.alpha = 0.97;
deadBg.tint = 0x181818;
deadScreenOverlay.addChild(deadBg);
// Glow
var deadGlow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 21.5,
scaleY: 25.5,
x: 2048 / 2,
y: 2732 / 2
});
deadGlow.alpha = 0.13;
deadGlow.tint = 0xff0000;
deadScreenOverlay.addChild(deadGlow);
// Title
var deadTitleShadow = new Text2('YOU DIED', {
size: 180,
fill: "#000"
});
deadTitleShadow.anchor.set(0.5, 0);
deadTitleShadow.x = 2048 / 2 + 8;
deadTitleShadow.y = 700 + 10;
deadTitleShadow.alpha = 0.18;
deadScreenOverlay.addChild(deadTitleShadow);
var deadTitle = new Text2('YOU DIED', {
size: 180,
fill: 0xff0000
});
deadTitle.anchor.set(0.5, 0);
deadTitle.x = 2048 / 2;
deadTitle.y = 700;
deadScreenOverlay.addChild(deadTitle);
// Subtitle
var deadSubtitle = new Text2('Survived: ' + (Math.floor(timeSurvived) / 1000).toFixed(2) + 's', {
size: 90,
fill: "#fff"
});
deadSubtitle.anchor.set(0.5, 0);
deadSubtitle.x = 2048 / 2;
deadSubtitle.y = 900;
deadScreenOverlay.addChild(deadSubtitle);
// Restart Button (replaces Main Menu)
var restartBtn = LK.getAsset('startBtnImage', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 1.0,
x: 2048 / 2,
y: 1400
});
deadScreenOverlay.addChild(restartBtn);
var restartBtnGlow = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 0.7,
x: 2048 / 2,
y: 1400
});
restartBtnGlow.tint = 0x83de44;
restartBtnGlow.alpha = 0.18;
deadScreenOverlay.addChild(restartBtnGlow);
var restartBtnText = new Text2('RESTART', {
size: 130,
fill: "#222"
});
restartBtnText.anchor.set(0.5, 0.5);
restartBtnText.x = 2048 / 2;
restartBtnText.y = 1400;
deadScreenOverlay.addChild(restartBtnText);
// Optionally, add a "Leaderboard" button
var mainMenuBtn = LK.getAsset('topTierIcon', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
x: 2048 / 2,
y: 1700
});
mainMenuBtn.tint = 0x4e9ae7;
deadScreenOverlay.addChild(mainMenuBtn);
var mainMenuBtnText = new Text2('MAIN MENU', {
size: 90,
fill: "#fff"
});
mainMenuBtnText.anchor.set(0.5, 0.5);
mainMenuBtnText.x = 2048 / 2;
mainMenuBtnText.y = 1700;
deadScreenOverlay.addChild(mainMenuBtnText);
// Interactivity
deadScreenOverlay.interactive = true;
deadScreenOverlay.down = function (x, y, obj) {
// Restart button
var dx = x - restartBtn.x;
var dy = y - restartBtn.y;
var w = restartBtn.width / 2,
h = restartBtn.height / 2;
if (dx >= -w && dx <= w && dy >= -h && dy <= h) {
deadScreenOverlay.visible = false;
// Mute all sounds on restart
if (typeof LK.muteAllSounds === "function") {
LK.muteAllSounds();
}
// Instantly restart the game: hide overlays, reset state, and start game
mainMenuOverlay.visible = false;
menuActive = false;
player.visible = true;
gameOver = false;
timeSurvived = 0;
spawnInterval = 36;
spawnTick = 0;
timerText.setText('0.00');
// Remove all obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Reset player position
player.x = 2048 / 2;
player.y = 2732 / 2;
dragNode = null;
return;
}
// Main Menu button
var dx2 = x - mainMenuBtn.x;
var dy2 = y - mainMenuBtn.y;
var w2 = mainMenuBtn.width / 2,
h2 = mainMenuBtn.height / 2;
if (dx2 >= -w2 && dx2 <= w2 && dy2 >= -h2 && dy2 <= h2) {
deadScreenOverlay.visible = false;
// Mute all sounds when returning to main menu
if (typeof LK.muteAllSounds === "function") {
LK.muteAllSounds();
}
// Unmute all sounds when returning to main menu
if (typeof LK.unmuteAllSounds === "function") {
LK.unmuteAllSounds();
}
mainMenuOverlay.visible = true;
mainMenuOverlay.alpha = 1;
menuActive = true;
player.visible = false;
return;
}
};
game.addChild(deadScreenOverlay);
break;
}
obs.lastIntersecting = intersecting;
}
};
// Reset logic (when game restarts)
game.on('reset', function () {
// Remove all obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
// Reset player position
player.x = 2048 / 2;
player.y = 2732 / 2;
dragNode = null;
timeSurvived = 0;
spawnInterval = 36;
spawnTick = 0;
gameOver = false;
timerText.setText('0.00');
// Hide dead screen overlay if present
if (typeof deadScreenOverlay !== "undefined" && deadScreenOverlay) {
deadScreenOverlay.visible = false;
}
// Show main menu again
mainMenuOverlay.visible = true;
mainMenuOverlay.alpha = 1;
menuActive = true;
player.visible = false; // Hide player in main menu after reset
// Mute all sounds on reset when showing main menu
if (typeof LK.muteAllSounds === "function") {
LK.muteAllSounds();
}
// Restore volume setting on reset
if (typeof LK.setMasterVolume === "function" && typeof currentVolume !== "undefined") {
LK.setMasterVolume(currentVolume);
}
});