User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.leaderboard = leaderboard;' Line Number: 119 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'TypeError: storage.set is not a function' in or related to this line: 'storage.set("leaderboard", leaderboard);' Line Number: 119 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var storedUsername = storage.get("username");' Line Number: 415 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
giriş yapan (adını yazan) kullanıcıya tekrar oyun başlayınca kullanıcı adı sorma
User prompt
onay butonunu harflerin altına koy
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.leaderboard = leaderboard;' Line Number: 119
User prompt
rakamlar yerine hafler koy
User prompt
kullanıcı adı bu şekilde girilemiyor. başka bir yol yöntem dene
User prompt
olmaı. şunu çalışır bir şekilde yap lütfen.
User prompt
kullanıcı adı girilemiyor
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of null (setting 'y')' in or related to this line: 'fly.y = y;' Line Number: 510
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of null (reading 'flap')' in or related to this line: 'fly.flap();' Line Number: 500
User prompt
kullanıcı adı girişi ekranında yumurta gösterilmesin, oyun başlamasın, kullanıcı adı girildikten sonra başlasın. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
bunu kaldır ve oyun başlamadan önce ekrana 5cm eninde 4 cm yüksekliğinde, kenarları oval beyaz bir kutu çiz. Kutunun içinde inputbox ve Tamam yazan bir buton olsun. inputbox'a yazılan isimleri oyunun sonundaki lider tablosunda kullan. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
olmadı ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
bu olmuyor, başka bir yöntem dene ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
başka bir yol dene ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
isim girilemiyor ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'storage.get is not a function' in or related to this line: 'var storedUsername = storage.get('username');' Line Number: 134 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
kayıtlı skor tablosu için kullanıcı adının girilmesi gerek, buna göre bir sistem oluştur
User prompt
olmadı
User prompt
yine girilemiyor
User prompt
kullanıcı adı girilemiyor
User prompt
kullanıcı adını girebileceğim beyaz bir kutucuk oluştur
User prompt
kullanıcı adını girmek için kenarları oval beyaz dikdörtgen inputbox oluştur, aynı dikdörtgen kutuvuğun altında (iputbox'ın altında) Tamam butonu yap
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Swatter class var Swatter = Container.expand(function () { var self = Container.call(this); // Swatter types and their point values var swatterTypes = [{ id: 'swatter_red', points: 50 }, { id: 'swatter_yellow', points: 35 }, { id: 'swatter_green', points: 20 }, { id: 'swatter_blue', points: 60 }]; // Randomly select a type var typeIndex = Math.floor(Math.random() * swatterTypes.length); self.type = swatterTypes[typeIndex]; self.points = self.type.points; // Attach asset var swatterAsset = self.attachAsset(self.type.id, { anchorX: 0.5, anchorY: 0.5 }); // Set initial position and speed self.x = 2048 + 120; // Start just off the right edge self.y = 200 + Math.floor(Math.random() * (2732 - 400)); self.speed = (12 + Math.random() * 6) * 0.75; // 25% slower // Allow scaleX to be set after creation for random length self.scaleX = 1; // For collision detection self.update = function () { self.x -= self.speed; }; return self; }); // Yumurta class (formerly Fly) var Yumurta = Container.expand(function () { var self = Container.call(this); var flyAsset = self.attachAsset('fly', { anchorX: 0.5, anchorY: 0.5 }); self.width = flyAsset.width; self.height = flyAsset.height; // Physics self.vy = 0; self.gravity = 1.2; self.lift = -28; // For touch controls self.flap = function () { self.vy = self.lift; }; // Update position self.update = function () { self.vy += self.gravity; self.y += self.vy; // Clamp to screen if (self.y < self.height / 2) { self.y = self.height / 2; self.vy = 0; } if (self.y > 2732 - self.height / 2) { self.y = 2732 - self.height / 2; self.vy = 0; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 // Initial background: black }); /**** * Game Code ****/ // Username and leaderboard // --- Ava: High Score Table & Username Prompt --- // Use storage plugin for persistent data var username = ""; var leaderboard = []; // [{name, score}] // Helper to load leaderboard from storage function loadLeaderboard() { var data = storage.leaderboard; if (data && Array.isArray(data)) { leaderboard = data; } else { leaderboard = []; } } // Helper to save leaderboard to storage function saveLeaderboard() { // Only store 1-level deep array of objects with literal values var safeLeaderboard = []; for (var i = 0; i < leaderboard.length; i++) { var entry = leaderboard[i]; // Only keep name and score as literals safeLeaderboard.push({ name: typeof entry.name === "string" ? entry.name : "", score: typeof entry.score === "number" ? entry.score : 0 }); } storage.leaderboard = safeLeaderboard; } // Helper to show username prompt before game starts function showUsernamePrompt(onDone) { // Remove any old prompt if (typeof usernamePromptBox !== "undefined" && usernamePromptBox.parent) { usernamePromptBox.parent.removeChild(usernamePromptBox); } // Load username from storage if available, fallback to default var storedUsername = storage.username; if (typeof storedUsername === "string" && storedUsername.length > 0) { username = storedUsername.substring(0, 16); } else { username = ""; } // --- Ava: 5cm x 4cm box, white, rounded, centered --- // iPad Pro 12" portrait: 2048x2732, 1cm ≈ 81.92px (2048/25) var cmToPx = 2048 / 25.0; var boxW = Math.round(5 * cmToPx); // 409px var boxH = Math.round(4 * cmToPx); // 327px // Main box container usernamePromptBox = new Container(); // White rounded rectangle var boxBg = LK.getAsset('bg_forest', { width: boxW, height: boxH, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); boxBg.alpha = 1; boxBg.radius = Math.min(boxH, boxW) / 3; // oval corners usernamePromptBox.addChild(boxBg); // Prompt text var promptTxt = new Text2("Kullanıcı adını gir:", { size: 70, fill: 0x222222, align: "center" }); promptTxt.anchor.set(0.5, 0); promptTxt.x = 0; promptTxt.y = -boxH / 2 + 36; usernamePromptBox.addChild(promptTxt); // Input box (simulated as a white rounded rectangle with border) var inputW = boxW - 80; var inputH = 90; var inputBg = LK.getAsset('bg_forest', { width: inputW, height: inputH, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 0, y: -30 }); inputBg.alpha = 1; inputBg.radius = inputH / 2; usernamePromptBox.addChild(inputBg); // Input text var initialUsernameText = username && username.length > 0 ? username : "_"; var inputText = new Text2(initialUsernameText, { size: 70, fill: 0x222222, align: "center" }); inputText.anchor.set(0.5, 0.5); inputText.x = 0; inputText.y = -30; inputText.textValue = username && username.length > 0 ? username : ""; usernamePromptBox.addChild(inputText); // --- Ava: On-screen keypad for username entry (mobile-friendly) --- var btnW = 220, btnH = 80; // Place the "Tamam" button below the keypad var btnBg = LK.getAsset('bg_forest', { width: btnW, height: btnH, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 0, // y: below keypad, calculate based on keypad height y: keyPadStartY + keyRows * keyH + btnH / 2 + 24 }); btnBg.alpha = 1; btnBg.radius = btnH / 2; usernamePromptBox.addChild(btnBg); var btnTxt = new Text2("Tamam", { size: 60, fill: 0x222222, align: "center" }); btnTxt.anchor.set(0.5, 0.5); btnTxt.x = 0; btnTxt.y = keyPadStartY + keyRows * keyH + btnH / 2 + 24; usernamePromptBox.addChild(btnTxt); // Add to game usernamePromptBox.x = 2048 / 2; usernamePromptBox.y = 2732 / 2; game.addChild(usernamePromptBox); // Input logic inputBg.interactive = false; inputText.interactive = false; // Keypad layout (4x7 grid: A-Z, Sil, Temizle, Boşluk) var keypadKeys = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Sil", "Temizle"]; var keypadBtns = []; var keyCols = 7; var keyRows = 4; var keyW = Math.floor((inputW - 20) / keyCols); var keyH = 80; var keyPadStartY = 60; for (var i = 0; i < keyCols * keyRows; i++) { var col = i % keyCols; var row = Math.floor(i / keyCols); var keyLabel = keypadKeys[i]; if (!keyLabel) continue; var keyBtn = LK.getAsset('bg_forest', { width: keyW - 10, height: keyH - 10, color: 0xf0f0f0, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: -((keyCols - 1) * keyW) / 2 + col * keyW, y: keyPadStartY + row * keyH }); keyBtn.radius = 18; keyBtn.interactive = true; (function (keyLabel, keyBtn) { keyBtn.down = function () { if (!inputActive) return; if (keyLabel === "Sil") { inputText.textValue = inputText.textValue.slice(0, -1); } else if (keyLabel === "Temizle") { inputText.textValue = ""; } else if (inputText.textValue.length < 16 && keyLabel.length === 1) { inputText.textValue += keyLabel; } inputText.setText(inputText.textValue.length > 0 ? inputText.textValue : "_"); }; })(keyLabel, keyBtn); usernamePromptBox.addChild(keyBtn); // Key label var keyTxt = new Text2(keyLabel, { size: 48, fill: 0x222222, align: "center" }); keyTxt.anchor.set(0.5, 0.5); keyTxt.x = keyBtn.x; keyTxt.y = keyBtn.y; usernamePromptBox.addChild(keyTxt); keypadBtns.push(keyBtn); } // Input logic var inputActive = true; function finishInput() { if (inputText.textValue.length > 0) { username = inputText.textValue; if (usernamePromptBox.parent) usernamePromptBox.parent.removeChild(usernamePromptBox); // Store username in persistent storage for leaderboard storage.set("username", username); inputActive = false; // Remove keypad interactivity after done for (var i = 0; i < keypadBtns.length; i++) { keypadBtns[i].interactive = false; keypadBtns[i].down = null; } if (onDone) onDone(); } } // "Tamam" button interactivity btnBg.interactive = true; btnBg.down = function (x, y, obj) { if (!inputActive) return; finishInput(); }; btnTxt.interactive = true; btnTxt.down = function (x, y, obj) { if (!inputActive) return; finishInput(); }; // Remove all keyboard and prompt logic (mobile only, no keyboard or prompt) } // Helper to show leaderboard after game over function showLeaderboard() { loadLeaderboard(); // Add current score if not already in var score = LK.getScore(); if (username && score > 0) { leaderboard.push({ name: username, score: score }); // Sort descending leaderboard.sort(function (a, b) { return b.score - a.score; }); // Keep top 10 leaderboard = leaderboard.slice(0, 10); saveLeaderboard(); } // Remove old leaderboard if any if (typeof leaderboardTxt !== "undefined" && leaderboardTxt.parent) { leaderboardTxt.parent.removeChild(leaderboardTxt); } // Build leaderboard text var text = "En Yüksek Skorlar\n"; for (var i = 0; i < leaderboard.length; i++) { var entry = leaderboard[i]; text += i + 1 + ". " + entry.name + " - " + entry.score + "\n"; } leaderboardTxt = new Text2(text, { size: 70, fill: 0xffffff, align: "center" }); leaderboardTxt.anchor.set(0.5, 0.5); leaderboardTxt.x = 2048 / 2; leaderboardTxt.y = 2732 / 2; game.addChild(leaderboardTxt); // Remove after 4 seconds LK.setTimeout(function () { if (leaderboardTxt.parent) leaderboardTxt.parent.removeChild(leaderboardTxt); }, 4000); } // --- Ava: End High Score Table & Username Prompt --- // Level config // Backgrounds: always black var levelCount = 100; var currentLevel = 1; var swatterInterval = 90; // ticks between swatters, stays constant var swatterSpeedBonus = 0; // stays constant // Score var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Level text var levelTxt = new Text2('Seviye 1', { size: 70, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); levelTxt.y = 120; // Background node var bgNode = LK.getAsset('bg_forest', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); bgNode.tint = 0x000000; game.addChild(bgNode); // Yumurta var fly = null; // Will be created after username is entered // Swatters array var swatters = []; // For touch controls var isTouching = false; // --- Ava: Fly stays in air for 5 seconds, then falls if not touched --- // Instruction message before game starts var instructionTxt = new Text2("Yumurta ilk 5 saniye havada kalır\nOnu düşürmemek için mouse ile tıklayın", { size: 90, fill: 0xffffff, align: "center" }); instructionTxt.anchor.set(0.5, 0.5); instructionTxt.x = 2048 / 2; instructionTxt.y = 2732 / 2; instructionTxt.alpha = 1; // Block game logic until instruction is gone or username entered var gameBlocked = true; // Show username prompt first, then show instruction, then fade out instruction var storedUsername = storage.username; if (typeof storedUsername === "string" && storedUsername.length > 0) { username = storedUsername.substring(0, 16); // Username already set, skip prompt if (!fly) { fly = new Yumurta(); game.addChild(fly); fly.x = 400; fly.y = 2732 / 2; } if (!instructionTxt.parent) game.addChild(instructionTxt); instructionTxt.alpha = 1; instructionTxt.x = 2048 / 2; instructionTxt.y = 2732 / 2; LK.setTimeout(function () { tween(instructionTxt, { alpha: 0 }, { duration: 700, easing: tween.easeOut, onFinish: function onFinish() { if (instructionTxt.parent) instructionTxt.parent.removeChild(instructionTxt); gameBlocked = false; flyStartTime = Date.now(); // Start fly grace period after message } }); }, 2000); } else { showUsernamePrompt(function () { // After username entered, create and show the egg (fly) if (!fly) { fly = new Yumurta(); game.addChild(fly); fly.x = 400; fly.y = 2732 / 2; } // After username entered, show instruction if (!instructionTxt.parent) game.addChild(instructionTxt); instructionTxt.alpha = 1; instructionTxt.x = 2048 / 2; instructionTxt.y = 2732 / 2; LK.setTimeout(function () { tween(instructionTxt, { alpha: 0 }, { duration: 700, easing: tween.easeOut, onFinish: function onFinish() { if (instructionTxt.parent) instructionTxt.parent.removeChild(instructionTxt); gameBlocked = false; flyStartTime = Date.now(); // Start fly grace period after message } }); }, 2000); }); } var flyStartTime = Date.now(); var flyGracePeriod = 5000; // ms var flyActive = false; // becomes true after first touch or after grace period var flyFell = false; // if fly has fallen var swatterRows = 6; // number of swatter rows per spawn var swatterRowYs = []; for (var r = 0; r < swatterRows; r++) { // Evenly space rows, avoid top/bottom 100px var minY = 100 + 60; var maxY = 2732 - 100 - 60; var rowY = minY + r * ((maxY - minY) / (swatterRows - 1)); swatterRowYs.push(rowY); } // For level progression var nextLevelScore = 100; var levelScoreStep = 110; // %10 daha yavaş seviye atlama // Set background for level function setBackgroundForLevel(level) { // Always keep background black, do not change or add any colored backgrounds // Remove old background if any if (bgNode && bgNode.parent) { bgNode.parent.removeChild(bgNode); } // Create a black background node bgNode = LK.getAsset('bg_forest', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); bgNode.tint = 0x000000; game.addChildAt(bgNode, 0); } // Level up function levelUp() { currentLevel++; if (currentLevel > levelCount) { LK.showYouWin(); return; } setBackgroundForLevel(currentLevel); levelTxt.setText('Seviye ' + currentLevel); // Difficulty stays constant except for speed scaling after level 10 swatterInterval = 90; // After level 10, increase swatterSpeedBonus by 1% every 10 levels if (currentLevel > 10) { var speedupSteps = Math.floor((currentLevel - 1) / 10); swatterSpeedBonus = 0 * 0.75 + speedupSteps * 0.01; } else { swatterSpeedBonus = 0 * 0.75; } nextLevelScore += levelScoreStep; // Flash background for level up LK.effects.flashScreen(0xffff00, 600); } // Touch/drag controls game.down = function (x, y, obj) { isTouching = true; if (!flyActive) { flyActive = true; } if (fly && typeof fly.flap === "function") { fly.flap(); } }; game.up = function (x, y, obj) { isTouching = false; }; game.move = function (x, y, obj) { // Optional: allow dragging fly up/down if (isTouching && fly) { fly.y = y; } }; // Main update loop game.update = function () { // --- Ava: Block all game logic until instruction message is gone --- if (gameBlocked) { return; } // --- Ava: Fly grace period and falling logic --- if (!flyActive && !flyFell) { // During grace period, keep fly in air if (Date.now() - flyStartTime < flyGracePeriod) { fly.vy = 0; // Keep fly at initial y fly.y = 2732 / 2; } else { // Grace period over, fly falls unless touched flyActive = true; isTouching = false; } } if (flyActive && !isTouching && !flyFell) { // If not touching after grace, let fly fall fly.update(); if (fly.y >= 2732 - fly.height / 2 - 1) { // Fly hit the ground flyFell = true; LK.effects.flashScreen(0x222222, 800); // Show game over popup (score will be shown by LK engine) // Oyun bittiğinde seviye ve skor gösterimi LK.showGameOver ile yapılır LK.showGameOver(); showLeaderboard(); return; } } else if (!flyActive) { // During grace, don't update physics } else if (isTouching && !flyFell) { fly.update(); } else if (!flyFell) { fly.update(); } // --- Ava: Swatters spawn in every row --- if (LK.ticks % swatterInterval === 0) { // --- Ava: Randomize swatter spawn order each wave --- // Create a shuffled copy of swatterRowYs var shuffledRows = []; for (var i = 0; i < swatterRowYs.length; i++) { shuffledRows[i] = swatterRowYs[i]; } // Fisher-Yates shuffle for (var i = shuffledRows.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = shuffledRows[i]; shuffledRows[i] = shuffledRows[j]; shuffledRows[j] = temp; } // --- Ava: For each row, spawn swatter with random delay and random length --- for (var r = 0; r < swatterRows; r++) { (function (rowIdx, rowY) { // Random delay for this row (0-40 ticks, up to ~0.66s) var delayTicks = Math.floor(Math.random() * 40); LK.setTimeout(function () { var swatter = new Swatter(); swatter.speed += swatterSpeedBonus * 0.75; swatter.y = rowY; // Randomize swatter length (scaleX 1.0 to 2.0) var scale = 1 + Math.random(); swatter.scaleX = scale; // Adjust anchor so left edge stays at same place if (swatter.children && swatter.children.length > 0) { // Set anchorX to 0.5 (center) for scaling, already set in Swatter class } swatters.push(swatter); game.addChild(swatter); }, delayTicks * 1000 / 60); // convert ticks to ms })(r, shuffledRows[r]); } } // Update swatters for (var i = swatters.length - 1; i >= 0; i--) { var sw = swatters[i]; sw.update(); // Collision if (fly.intersects(sw)) { LK.effects.flashScreen(0xff0000, 1000); // Show game over popup (score will be shown by LK engine) // Oyun bittiğinde seviye ve skor gösterimi LK.showGameOver ile yapılır LK.showGameOver(); showLeaderboard(); return; } // Off screen if (sw.x < -200) { // Award points for successful dodge LK.setScore(LK.getScore() + sw.points); scoreTxt.setText(LK.getScore()); // Level up if needed if (LK.getScore() >= nextLevelScore) { levelUp(); } sw.destroy(); swatters.splice(i, 1); } } }; // Reset game state on restart LK.on('gameStart', function () { // Reset variables currentLevel = 1; swatterInterval = 90; swatterSpeedBonus = 0 * 0.75; // Reset speed scaling on restart nextLevelScore = 100; levelScoreStep = 110; // %10 daha yavaş seviye atlama (reset) setBackgroundForLevel(currentLevel); levelTxt.setText('Seviye 1'); LK.setScore(0); scoreTxt.setText('0'); // Remove all swatters for (var i = 0; i < swatters.length; i++) { swatters[i].destroy(); } swatters = []; // Reset fly if (fly && fly.parent) { fly.parent.removeChild(fly); fly = null; } flyActive = false; flyFell = false; // Do not reset username, so user is not prompted again // username = ""; // Show instruction message again and block game gameBlocked = true; instructionTxt.setText("Yumurta ilk 5 saniye havada kalır\nOnu düşürmemek için mouse ile tıklayın"); instructionTxt.alpha = 1; instructionTxt.x = 2048 / 2; instructionTxt.y = 2732 / 2; // Show username prompt first, then show instruction, then fade out instruction var storedUsername = storage.username; if (typeof storedUsername === "string" && storedUsername.length > 0) { username = storedUsername.substring(0, 16); // Username already set, skip prompt if (!fly) { fly = new Yumurta(); game.addChild(fly); fly.x = 400; fly.y = 2732 / 2; } if (!instructionTxt.parent) game.addChild(instructionTxt); instructionTxt.alpha = 1; instructionTxt.x = 2048 / 2; instructionTxt.y = 2732 / 2; LK.setTimeout(function () { tween(instructionTxt, { alpha: 0 }, { duration: 700, easing: tween.easeOut, onFinish: function onFinish() { if (instructionTxt.parent) instructionTxt.parent.removeChild(instructionTxt); gameBlocked = false; flyStartTime = Date.now(); } }); }, 2000); } else { showUsernamePrompt(function () { // After username entered, create and show the egg (fly) if (!fly) { fly = new Yumurta(); game.addChild(fly); fly.x = 400; fly.y = 2732 / 2; } if (!instructionTxt.parent) game.addChild(instructionTxt); instructionTxt.alpha = 1; instructionTxt.x = 2048 / 2; instructionTxt.y = 2732 / 2; LK.setTimeout(function () { tween(instructionTxt, { alpha: 0 }, { duration: 700, easing: tween.easeOut, onFinish: function onFinish() { if (instructionTxt.parent) instructionTxt.parent.removeChild(instructionTxt); gameBlocked = false; flyStartTime = Date.now(); } }); }, 2000); }); } }); /* End of MVP */
===================================================================
--- original.js
+++ change.js
@@ -104,9 +104,19 @@
}
}
// Helper to save leaderboard to storage
function saveLeaderboard() {
- storage.leaderboard = leaderboard;
+ // Only store 1-level deep array of objects with literal values
+ var safeLeaderboard = [];
+ for (var i = 0; i < leaderboard.length; i++) {
+ var entry = leaderboard[i];
+ // Only keep name and score as literals
+ safeLeaderboard.push({
+ name: typeof entry.name === "string" ? entry.name : "",
+ score: typeof entry.score === "number" ? entry.score : 0
+ });
+ }
+ storage.leaderboard = safeLeaderboard;
}
// Helper to show username prompt before game starts
function showUsernamePrompt(onDone) {
// Remove any old prompt