User prompt
kendin oluşturduğun karakteri kaldır,
User prompt
Please fix the bug: 'Uncaught ReferenceError: beatboxer is not defined' in or related to this line: 'if (characterList[characterStyle] === beatboxer && typeof beatboxer.beat === "function") {' Line Number: 458
User prompt
karakter değilere placeholder koy, o play holderları ben sonra assetlerle değiştircem
User prompt
Update tap handler to loop through 3 character styles and animate if Beatboxer
User prompt
tap butona basıldığında , karakter değişsin
User prompt
daha da aşaya olsun
User prompt
karakter çok yukarda oldu ona, kırmızı butona yakın olsun
User prompt
beatbox karakter yerine, mavı bir kare koy, ben onu değitirmek istiyorum assetle çizgi animasyon bir karakter yapacağım
User prompt
beatbox yapan karakter sil, ben oraya asset kulanacağım
Code edit (1 edits merged)
Please save this source code
User prompt
Beatbox Tap Star
Initial prompt
Merkezde: Sevimli, çizgi film tarzı bir beatbox karakter Kafasında büyük kulaklık Geniş hoodie, renkli spor ayakkabılar Ağzı açık, yanakları şişmiş: beatbox yapıyor görünmeli Alt ortada: Kırmızı büyük bir buton (oyuncunun bastığı) Sağda: Dikey bir nefes göstergesi (yeşil bir alan içeriyor, hareketli çerçeve içinde) Arka plan: Neon sahne, müzik notaları, ses dalgaları, renkli beat parçacıkları Renkler: Parlak mavi, mor, pembe, elektrik yeşili Yazı: Yukarıda "Tap to Beatbox!" veya "Bas ve Beatbox Yap!" şeklinde neon fontlu slogan UI detayları: Köşede küçük bir skor ve nickname kutusu görünmeli Genel hissiyat: Eğlenceli, ritmik, enerjik, çocuklara ve casual oyunculara hitap eden atmosfer
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Beat Particle var BeatParticle = Container.expand(function () { var self = Container.call(this); var p = self.attachAsset('beatParticle', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 0; self.vy = 0; self.alpha = 1; self.scale = 1; self.update = function () { self.x += self.vx; self.y += self.vy; self.scale += 0.02; self.alpha -= 0.018; p.scaleX = p.scaleY = self.scale; if (self.alpha <= 0) { self.destroyed = true; } }; return self; }); // BreathBar: Visual breath meter with fill, danger, and update logic var BreathBar = Container.expand(function () { var self = Container.call(this); // Background var bg = self.attachAsset('breathBarBg', { anchorX: 0.5, anchorY: 0, x: 0, y: 0 }); // Danger zone (red, bottom) var danger = self.attachAsset('breathBarDanger', { anchorX: 0.5, anchorY: 0, x: 0, y: 20 }); // Fill (cyan, dynamic) var fill = self.attachAsset('breathBarFill', { anchorX: 0.5, anchorY: 0, x: 0, y: 20 }); // Bar state self.maxValue = 100; self.value = 100; self.drainPerTick = 0.18; // ~10s to empty self.minValue = 0; // Set fill height based on value self.setValue = function (v) { self.value = Math.max(self.minValue, Math.min(self.maxValue, v)); // Fill height: 0-660px, y=20 var fillHeight = Math.round(660 * (self.value / self.maxValue)); fill.height = fillHeight; fill.y = 20 + (660 - fillHeight); // Danger always at y=20, height=660 // Optionally, fade fill if low if (self.value < 20) { fill.alpha = 0.5 + 0.5 * (self.value / 20); } else { fill.alpha = 1; } }; // Drain bar per tick self.update = function () { self.setValue(self.value - self.drainPerTick); }; // Refill by 5% (e.g. on tap) self.refill = function () { var increase = self.maxValue * 0.05; self.setValue(self.value + increase); }; // Is bar empty? self.isEmpty = function () { return self.value <= self.minValue + 0.01; }; // Init self.setValue(self.value); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0a0a1a }); /**** * Game Code ****/ // Music // Sound // Soundwave // Slogan Neon Bar // Beat Particle // Music Note // --- Breath Meter // Red Tap Button // Character: Big, cartoon beatboxer with headphones, hoodie, sneakers // --- Neon Slogan at Top --- function _typeof5(o) { "@babel/helpers - typeof"; return _typeof5 = "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; }, _typeof5(o); } function _typeof4(o) { "@babel/helpers - typeof"; return _typeof4 = "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; }, _typeof4(o); } function _typeof3(o) { "@babel/helpers - typeof"; return _typeof3 = "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; }, _typeof3(o); } function _typeof2(o) { "@babel/helpers - typeof"; return _typeof2 = "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; }, _typeof2(o); } 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); } // --- Static Background (behind all elements) --- // Make sure the background fully covers the screen (2048x2732) var beatboxBg = LK.getAsset('beatbox_bg', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, width: 2048, height: 2732 }); game.addChild(beatboxBg); var sloganText = new Text2('BEATBOX TAP STAR', { size: 140, fill: 0x00FFFF, font: "Impact, 'Arial Black', Tahoma" }); sloganText.anchor.set(0.5, 0.5); sloganText.x = 2048 / 2; sloganText.y = 130; game.addChild(sloganText); // --- Score Text (top right) --- var scoreText = new Text2('0', { size: 110, fill: 0xffffff, font: "Impact, 'Arial Black', Tahoma" }); scoreText.anchor.set(1, 0); // right-top scoreText.x = -10; // 10px from right edge scoreText.y = 30; // 30px from top (no breathbar) // Do not add to LK.gui.right here; will be added to game after breathBar is created // --- Best Score Text (bottom left corner) --- var bestScore = storage.bestScore || 0; var bestScoreText = new Text2('BEST: ' + bestScore, { size: 80, fill: 0xffe066, font: "Impact, 'Arial Black', Tahoma" }); bestScoreText.anchor.set(0, 1); // left-bottom bestScoreText.x = 40; // 40px from left edge bestScoreText.y = 2732 - 40; // 40px from bottom edge game.addChild(bestScoreText); // --- Beatboxer Character (center stage) --- // Character switching logic // Character style 0: Blue square placeholder var characterPlaceholder0 = LK.getAsset('characterPlaceholder', { anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 2350 }); // Character style 1: Pink ellipse placeholder var characterPlaceholder1 = LK.getAsset('beatboxerHead', { anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 2350, color: 0xff66cc }); characterPlaceholder1.visible = false; // Character style 2: Green box placeholder var characterPlaceholder2 = LK.getAsset('beatParticle', { anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 2350, color: 0x00ffcc }); characterPlaceholder2.visible = false; // Character style 3: Blue square placeholder (new) var characterPlaceholder3 = LK.getAsset('characterPlaceholderSquare', { anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 2350 }); characterPlaceholder3.visible = false; game.addChild(characterPlaceholder0); game.addChild(characterPlaceholder1); game.addChild(characterPlaceholder2); game.addChild(characterPlaceholder3); // Track which character is currently shown (0, 1, 2, 3) var characterStyle = 0; var characterList = [characterPlaceholder0, characterPlaceholder1, characterPlaceholder2, characterPlaceholder3]; // --- Beatboxer character instance removed as per instructions --- // --- Tap Button (bottom center) --- var tapButton = LK.getAsset('tapButton', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2350 //{1U} // moved up by 150px }); game.addChild(tapButton); // --- Animated Background Particles --- var beatParticles = []; // --- Game State --- var score = 0; var isGameOver = false; var canTap = true; var lastTapTick = 0; // Remove tap count and speedup logic; breathBar is always fast // --- Nickname and Leaderboard --- var nickname = storage.nickname || null; var leaderboard = storage.leaderboard || []; var leaderboardText = null; // --- Nickname Display (under sloganText, small font) --- var nicknameDisplayText = null; function updateNicknameDisplay() { if (!nicknameDisplayText) { nicknameDisplayText = new Text2('', { size: 90, fill: 0xcccccc, font: "Impact, 'Arial Black', Tahoma", align: 'center' }); nicknameDisplayText.anchor.set(0.5, 0); nicknameDisplayText.x = 2048 / 2; nicknameDisplayText.y = sloganText.y + sloganText.height / 2 + 10; game.addChild(nicknameDisplayText); } nicknameDisplayText.setText(nickname ? nickname : ''); nicknameDisplayText.visible = !!nickname; } // --- Nickname Overlay (semi-transparent black) --- var nicknameOverlay = null; // --- Nickname Animation --- var nicknameAnimText = null; var nicknameAnimTimer = null; var nicknameAnimTicks = 0; var nicknameAnimBase = "BeatBoxer"; var nicknameAnimCurrent = ""; var nicknameAnimDone = false; // Assign a random nickname and animate it function assignRandomNicknameAndShow() { // If already set, skip if (nickname) return; nicknameAnimTicks = 0; nicknameAnimDone = false; // Create overlay (if not present) if (!nicknameOverlay) { nicknameOverlay = LK.getAsset('breathBarBg', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, color: 0x000000 }); nicknameOverlay.alpha = 0.7; nicknameOverlay.interactive = false; game.addChild(nicknameOverlay); } else { nicknameOverlay.visible = true; } // Create animated nickname text if (nicknameAnimText) { nicknameAnimText.destroy(); nicknameAnimText = null; } nicknameAnimText = new Text2("YOUR NICKNAME IS ...", { size: 160, fill: 0xffffff, font: "Impact, 'Arial Black', Tahoma", align: 'center' }); nicknameAnimText.anchor.set(0.5, 0.5); nicknameAnimText.x = 2048 / 2; nicknameAnimText.y = 700; game.addChild(nicknameAnimText); // Animate the number rolling for 1.2 seconds, then pick a random number nicknameAnimTimer = LK.setInterval(function () { nicknameAnimTicks++; // Animate number from 01 to 99 var num = Math.floor(Math.random() * 99) + 1; var numStr = (num < 10 ? "0" : "") + num; nicknameAnimCurrent = nicknameAnimBase + numStr; nicknameAnimText.setText("YOUR NICKNAME IS\n" + nicknameAnimCurrent); // After 1.2 seconds (about 18 frames), finalize nickname if (nicknameAnimTicks > 18) { LK.clearInterval(nicknameAnimTimer); nicknameAnimTimer = null; // Final random number var finalNum = Math.floor(Math.random() * 99) + 1; var finalNumStr = (finalNum < 10 ? "0" : "") + finalNum; nickname = nicknameAnimBase + finalNumStr; storage.nickname = nickname; nicknameAnimText.setText("YOUR NICKNAME IS\n" + nickname); nicknameAnimDone = true; // Remove after 1.2s LK.setTimeout(function () { if (nicknameAnimText) { nicknameAnimText.destroy(); nicknameAnimText = null; } updateNicknameDisplay(); gamePausedForNickname = false; }, 1200); } }, 65); // Pause game logic until nickname is set gamePausedForNickname = true; } // On first load, always clear storage and assign new nickname, then show Ready button function resetAndAssignNickname() { // Clear storage for nickname and leaderboard storage.nickname = null; storage.leaderboard = []; nickname = null; leaderboard = []; // Remove any previous nickname text if (nicknameAnimText) { nicknameAnimText.destroy(); nicknameAnimText = null; } // Remove nickname display if present if (nicknameDisplayText) { nicknameDisplayText.destroy(); nicknameDisplayText = null; } // Assign new nickname with animation assignRandomNicknameAndShow(); // After nickname animation is done, show Ready button function showReadyButtonWhenDone() { if (nicknameAnimDone) { // Show Ready button if (window.readyBtn) { window.readyBtn.destroy(); window.readyBtn = null; } var readyBtn = new Text2("READY", { size: 140, fill: 0x00ffcc, font: "Impact, 'Arial Black', Tahoma", align: 'center' }); readyBtn.anchor.set(0.5, 0.5); readyBtn.x = 2048 / 2; readyBtn.y = 1100; game.addChild(readyBtn); window.readyBtn = readyBtn; readyBtn.interactive = true; readyBtn.buttonMode = true; readyBtn.down = function (x, y, obj) { // Remove button, unpause game if (window.readyBtn) { window.readyBtn.destroy(); window.readyBtn = null; } // Hide overlay when Ready is pressed if (nicknameOverlay) { nicknameOverlay.visible = false; } gamePausedForNickname = false; // Start background music when Ready is pressed // (Moved to first tap on red button) // Create and show breathBar (if not already) if (!breathBar) { breathBar = new BreathBar(); // Set fast drain from the start breathBar.drainPerTick = 0.36; // double the original speed // Place at right edge, below top margin (avoid top right 100x100) // breathBar.width is 80, so anchorX:0.5 means center is at x // Place 80px from right, 160px from top breathBar.x = 2048 - 80; breathBar.y = 160; game.addChild(breathBar); // Move scoreText below breathBar // scoreText is already created above, just move it scoreText.anchor.set(0.5, 0); // center-top scoreText.x = 2048 - 80; // align with breathBar.x scoreText.y = breathBar.y + 700 + 30; // breathBar height (700) + 30px margin // Remove from LK.gui.right if present, add to game if (scoreText.parent && scoreText.parent.removeChild) { scoreText.parent.removeChild(scoreText); } game.addChild(scoreText); } }; } else { LK.setTimeout(showReadyButtonWhenDone, 100); } } showReadyButtonWhenDone(); // Pause game logic until nickname is set and Ready pressed gamePausedForNickname = true; } resetAndAssignNickname(); function showLeaderboard() { if (leaderboardText) { leaderboardText.destroy(); leaderboardText = null; } var sorted = leaderboard.slice().sort(function (a, b) { return b.score - a.score; }).slice(0, 10); var lines = ['🏆 TOP SCORES 🏆']; for (var i = 0; i < sorted.length; i++) { lines.push(i + 1 + '. ' + sorted[i].nickname + ' - ' + sorted[i].score); } leaderboardText = new Text2(lines.join('\n'), { size: 80, fill: 0xffff00, font: "Impact, 'Arial Black', Tahoma", align: 'center' }); leaderboardText.anchor.set(0.5, 0.5); leaderboardText.x = 2048 / 2; leaderboardText.y = 2732 / 2; game.addChild(leaderboardText); // Remove leaderboard after 3 seconds LK.setTimeout(function () { if (leaderboardText) { leaderboardText.destroy(); leaderboardText = null; } }, 3000); } // On first load, ask for nickname if not set var gamePausedForNickname = false; // --- BreathBar instance (created after Ready) --- var breathBar = null; // --- Helper: Animate Tap Button Glow --- function animateTapButtonGlow() { // Button press animation: scale down then up tween(tapButton, { scaleX: 0.92, scaleY: 0.92 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { tween(tapButton, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.cubicIn }); } }); } // --- Helper: Add Beat Particle --- function spawnBeatParticle() { var p = new BeatParticle(); p.x = 2048 / 2; p.y = 1200 - 220; p.vx = (Math.random() - 0.5) * 1.5; p.vy = -1.5 - Math.random() * 1.5; p.alpha = 0.8 + Math.random() * 0.2; beatParticles.push(p); game.addChild(p); } // --- Tap Button Handler --- function handleTap(x, y, obj) { if (isGameOver || !canTap) { return; } // Only register tap if inside button var dx = x - tapButton.x; var dy = y - tapButton.y; var r = tapButton.width / 2; if (dx * dx + dy * dy > r * r) { return; } // Tap registered! canTap = false; lastTapTick = LK.ticks; // Animate animateTapButtonGlow(); spawnBeatParticle(); // Sound effects removed; only background music remains // Refill breathBar on tap if (breathBar) { breathBar.refill(); } // Update score and UI score++; scoreText.setText(score); // --- Motivational Text Animation --- if (score === 20 || score === 50 || score === 80) { var msg = ""; if (score === 20) msg = "SUPER!"; if (score === 50) msg = "EXCELLENT!"; if (score === 80) msg = "FANTASTIC!"; var motivText = new Text2(msg, { size: 200, fill: 0xffff00, font: "Impact, 'Arial Black', Tahoma", align: 'center' }); motivText.anchor.set(0.5, 0.5); motivText.x = 2048 / 2; motivText.y = 900; motivText.alpha = 0.0; game.addChild(motivText); // Animate: fade in, scale up, then fade out motivText.scaleX = motivText.scaleY = 0.7; tween(motivText, { alpha: 1, scaleX: 1.1, scaleY: 1.1 }, { duration: 220, easing: tween.cubicOut, onFinish: function onFinish() { tween(motivText, { alpha: 0, scaleX: 1.25, scaleY: 1.25 }, { duration: 600, easing: tween.cubicIn, onFinish: function onFinish() { motivText.destroy(); } }); } }); } // No game over at 20, 50, or 80 taps; game continues // Switch character: loop through 3 styles // Hide all, show next characterList[characterStyle].visible = false; characterStyle = (characterStyle + 1) % characterList.length; characterList[characterStyle].visible = true; // Animate if Beatboxer // (No Beatboxer instance present, so no animation triggered here) // Win condition removed for endless play } // --- Tap Button Down/Up/Move --- var musicStarted = false; // Track if music has started game.down = function (x, y, obj) { if (gamePausedForNickname) return; // Block all background taps if Ready button is visible if (window.readyBtn) return; // Start background music on first tap of red button if (!musicStarted) { LK.playMusic('neonbeat', { fade: { start: 0, end: 1, duration: 1200 } }); musicStarted = true; } handleTap(x, y, obj); }; game.move = function (x, y, obj) { if (gamePausedForNickname) return; // Block all background move events if Ready button is visible if (window.readyBtn) return; // No drag needed, but allow repeated tap if (!canTap && LK.ticks - lastTapTick > 7) { canTap = true; } }; game.up = function (x, y, obj) { if (gamePausedForNickname) return; // Block all background up events if Ready button is visible if (window.readyBtn) return; // Allow next tap canTap = true; }; // --- Main Game Update --- game.update = function () { if (isGameOver || gamePausedForNickname) { // Still allow sloganText and background particles to animate // Animate sloganText neon pulse sloganText.alpha = 0.85 + 0.15 * Math.sin(LK.ticks * 0.08); sloganText.scaleX = sloganText.scaleY = 1 + 0.03 * Math.sin(LK.ticks * 0.07); // Animate background: spawn beat particles if (LK.ticks % 30 === 0) { spawnBeatParticle(); } // Update and cleanup beat particles for (var i = beatParticles.length - 1; i >= 0; i--) { var p = beatParticles[i]; p.update(); if (p.destroyed) { p.destroy(); beatParticles.splice(i, 1); } } // Prevent breathbar from draining or updating while waiting for Ready return; } // --- BreathBar logic (drain, refill, game over) --- if (breathBar) { breathBar.update(); if (breathBar.isEmpty() && !isGameOver) { isGameOver = true; // Stop background music when breathBar is empty LK.stopMusic(); // Update best score if needed if (score > bestScore) { bestScore = score; storage.bestScore = bestScore; if (bestScoreText) bestScoreText.setText('BEST: ' + bestScore); } // Show overlay background behind score var scoreOverlay = LK.getAsset('breathBarBg', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, color: 0x000000 }); scoreOverlay.alpha = 0.7; scoreOverlay.interactive = false; game.addChild(scoreOverlay); // Show "Your Score Is" and the score in the center, but a bit higher var bigScoreText = new Text2("Your Score Is\n" + score, { size: 220, fill: 0xffff00, font: "Impact, 'Arial Black', Tahoma", align: 'center' }); bigScoreText.anchor.set(0.5, 0.5); bigScoreText.x = 2048 / 2; // Move further up (higher on the screen) bigScoreText.y = 800; game.addChild(bigScoreText); // Animate: fade in, scale up, then stay visible (do not fade out or destroy) bigScoreText.alpha = 0.0; bigScoreText.scaleX = bigScoreText.scaleY = 0.7; tween(bigScoreText, { alpha: 1, scaleX: 1.1, scaleY: 1.1 }, { duration: 420, easing: tween.cubicOut, onFinish: function onFinish() { // Do not fade out or destroy, keep on screen // Remove overlay and show game over after a short delay, but keep bigScoreText LK.setTimeout(function () { if (scoreOverlay) scoreOverlay.destroy(); LK.showGameOver(); }, 1500); } }); // Optionally, flash bar red tween(breathBar, { alpha: 0.2 }, { duration: 200, yoyo: true, repeat: 2, onFinish: function onFinish() { breathBar.alpha = 1; } }); } } // Animate sloganText neon pulse sloganText.alpha = 0.85 + 0.15 * Math.sin(LK.ticks * 0.08); sloganText.scaleX = sloganText.scaleY = 1 + 0.03 * Math.sin(LK.ticks * 0.07); // Animate background: spawn beat particles if (LK.ticks % 30 === 0) { spawnBeatParticle(); } // Update and cleanup beat particles for (var i = beatParticles.length - 1; i >= 0; i--) { var p = beatParticles[i]; p.update(); if (p.destroyed) { p.destroy(); beatParticles.splice(i, 1); } } }; // --- Play Music --- // (Music now starts after Ready is pressed, see readyBtn.down handler)
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Beat Particle
var BeatParticle = Container.expand(function () {
var self = Container.call(this);
var p = self.attachAsset('beatParticle', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = 0;
self.vy = 0;
self.alpha = 1;
self.scale = 1;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.scale += 0.02;
self.alpha -= 0.018;
p.scaleX = p.scaleY = self.scale;
if (self.alpha <= 0) {
self.destroyed = true;
}
};
return self;
});
// BreathBar: Visual breath meter with fill, danger, and update logic
var BreathBar = Container.expand(function () {
var self = Container.call(this);
// Background
var bg = self.attachAsset('breathBarBg', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 0
});
// Danger zone (red, bottom)
var danger = self.attachAsset('breathBarDanger', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 20
});
// Fill (cyan, dynamic)
var fill = self.attachAsset('breathBarFill', {
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 20
});
// Bar state
self.maxValue = 100;
self.value = 100;
self.drainPerTick = 0.18; // ~10s to empty
self.minValue = 0;
// Set fill height based on value
self.setValue = function (v) {
self.value = Math.max(self.minValue, Math.min(self.maxValue, v));
// Fill height: 0-660px, y=20
var fillHeight = Math.round(660 * (self.value / self.maxValue));
fill.height = fillHeight;
fill.y = 20 + (660 - fillHeight);
// Danger always at y=20, height=660
// Optionally, fade fill if low
if (self.value < 20) {
fill.alpha = 0.5 + 0.5 * (self.value / 20);
} else {
fill.alpha = 1;
}
};
// Drain bar per tick
self.update = function () {
self.setValue(self.value - self.drainPerTick);
};
// Refill by 5% (e.g. on tap)
self.refill = function () {
var increase = self.maxValue * 0.05;
self.setValue(self.value + increase);
};
// Is bar empty?
self.isEmpty = function () {
return self.value <= self.minValue + 0.01;
};
// Init
self.setValue(self.value);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0a1a
});
/****
* Game Code
****/
// Music
// Sound
// Soundwave
// Slogan Neon Bar
// Beat Particle
// Music Note
// --- Breath Meter
// Red Tap Button
// Character: Big, cartoon beatboxer with headphones, hoodie, sneakers
// --- Neon Slogan at Top ---
function _typeof5(o) {
"@babel/helpers - typeof";
return _typeof5 = "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;
}, _typeof5(o);
}
function _typeof4(o) {
"@babel/helpers - typeof";
return _typeof4 = "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;
}, _typeof4(o);
}
function _typeof3(o) {
"@babel/helpers - typeof";
return _typeof3 = "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;
}, _typeof3(o);
}
function _typeof2(o) {
"@babel/helpers - typeof";
return _typeof2 = "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;
}, _typeof2(o);
}
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);
}
// --- Static Background (behind all elements) ---
// Make sure the background fully covers the screen (2048x2732)
var beatboxBg = LK.getAsset('beatbox_bg', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 2048,
height: 2732
});
game.addChild(beatboxBg);
var sloganText = new Text2('BEATBOX TAP STAR', {
size: 140,
fill: 0x00FFFF,
font: "Impact, 'Arial Black', Tahoma"
});
sloganText.anchor.set(0.5, 0.5);
sloganText.x = 2048 / 2;
sloganText.y = 130;
game.addChild(sloganText);
// --- Score Text (top right) ---
var scoreText = new Text2('0', {
size: 110,
fill: 0xffffff,
font: "Impact, 'Arial Black', Tahoma"
});
scoreText.anchor.set(1, 0); // right-top
scoreText.x = -10; // 10px from right edge
scoreText.y = 30; // 30px from top (no breathbar)
// Do not add to LK.gui.right here; will be added to game after breathBar is created
// --- Best Score Text (bottom left corner) ---
var bestScore = storage.bestScore || 0;
var bestScoreText = new Text2('BEST: ' + bestScore, {
size: 80,
fill: 0xffe066,
font: "Impact, 'Arial Black', Tahoma"
});
bestScoreText.anchor.set(0, 1); // left-bottom
bestScoreText.x = 40; // 40px from left edge
bestScoreText.y = 2732 - 40; // 40px from bottom edge
game.addChild(bestScoreText);
// --- Beatboxer Character (center stage) ---
// Character switching logic
// Character style 0: Blue square placeholder
var characterPlaceholder0 = LK.getAsset('characterPlaceholder', {
anchorX: 0.5,
anchorY: 1,
x: 2048 / 2,
y: 2350
});
// Character style 1: Pink ellipse placeholder
var characterPlaceholder1 = LK.getAsset('beatboxerHead', {
anchorX: 0.5,
anchorY: 1,
x: 2048 / 2,
y: 2350,
color: 0xff66cc
});
characterPlaceholder1.visible = false;
// Character style 2: Green box placeholder
var characterPlaceholder2 = LK.getAsset('beatParticle', {
anchorX: 0.5,
anchorY: 1,
x: 2048 / 2,
y: 2350,
color: 0x00ffcc
});
characterPlaceholder2.visible = false;
// Character style 3: Blue square placeholder (new)
var characterPlaceholder3 = LK.getAsset('characterPlaceholderSquare', {
anchorX: 0.5,
anchorY: 1,
x: 2048 / 2,
y: 2350
});
characterPlaceholder3.visible = false;
game.addChild(characterPlaceholder0);
game.addChild(characterPlaceholder1);
game.addChild(characterPlaceholder2);
game.addChild(characterPlaceholder3);
// Track which character is currently shown (0, 1, 2, 3)
var characterStyle = 0;
var characterList = [characterPlaceholder0, characterPlaceholder1, characterPlaceholder2, characterPlaceholder3];
// --- Beatboxer character instance removed as per instructions ---
// --- Tap Button (bottom center) ---
var tapButton = LK.getAsset('tapButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2350 //{1U} // moved up by 150px
});
game.addChild(tapButton);
// --- Animated Background Particles ---
var beatParticles = [];
// --- Game State ---
var score = 0;
var isGameOver = false;
var canTap = true;
var lastTapTick = 0;
// Remove tap count and speedup logic; breathBar is always fast
// --- Nickname and Leaderboard ---
var nickname = storage.nickname || null;
var leaderboard = storage.leaderboard || [];
var leaderboardText = null;
// --- Nickname Display (under sloganText, small font) ---
var nicknameDisplayText = null;
function updateNicknameDisplay() {
if (!nicknameDisplayText) {
nicknameDisplayText = new Text2('', {
size: 90,
fill: 0xcccccc,
font: "Impact, 'Arial Black', Tahoma",
align: 'center'
});
nicknameDisplayText.anchor.set(0.5, 0);
nicknameDisplayText.x = 2048 / 2;
nicknameDisplayText.y = sloganText.y + sloganText.height / 2 + 10;
game.addChild(nicknameDisplayText);
}
nicknameDisplayText.setText(nickname ? nickname : '');
nicknameDisplayText.visible = !!nickname;
}
// --- Nickname Overlay (semi-transparent black) ---
var nicknameOverlay = null;
// --- Nickname Animation ---
var nicknameAnimText = null;
var nicknameAnimTimer = null;
var nicknameAnimTicks = 0;
var nicknameAnimBase = "BeatBoxer";
var nicknameAnimCurrent = "";
var nicknameAnimDone = false;
// Assign a random nickname and animate it
function assignRandomNicknameAndShow() {
// If already set, skip
if (nickname) return;
nicknameAnimTicks = 0;
nicknameAnimDone = false;
// Create overlay (if not present)
if (!nicknameOverlay) {
nicknameOverlay = LK.getAsset('breathBarBg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
color: 0x000000
});
nicknameOverlay.alpha = 0.7;
nicknameOverlay.interactive = false;
game.addChild(nicknameOverlay);
} else {
nicknameOverlay.visible = true;
}
// Create animated nickname text
if (nicknameAnimText) {
nicknameAnimText.destroy();
nicknameAnimText = null;
}
nicknameAnimText = new Text2("YOUR NICKNAME IS ...", {
size: 160,
fill: 0xffffff,
font: "Impact, 'Arial Black', Tahoma",
align: 'center'
});
nicknameAnimText.anchor.set(0.5, 0.5);
nicknameAnimText.x = 2048 / 2;
nicknameAnimText.y = 700;
game.addChild(nicknameAnimText);
// Animate the number rolling for 1.2 seconds, then pick a random number
nicknameAnimTimer = LK.setInterval(function () {
nicknameAnimTicks++;
// Animate number from 01 to 99
var num = Math.floor(Math.random() * 99) + 1;
var numStr = (num < 10 ? "0" : "") + num;
nicknameAnimCurrent = nicknameAnimBase + numStr;
nicknameAnimText.setText("YOUR NICKNAME IS\n" + nicknameAnimCurrent);
// After 1.2 seconds (about 18 frames), finalize nickname
if (nicknameAnimTicks > 18) {
LK.clearInterval(nicknameAnimTimer);
nicknameAnimTimer = null;
// Final random number
var finalNum = Math.floor(Math.random() * 99) + 1;
var finalNumStr = (finalNum < 10 ? "0" : "") + finalNum;
nickname = nicknameAnimBase + finalNumStr;
storage.nickname = nickname;
nicknameAnimText.setText("YOUR NICKNAME IS\n" + nickname);
nicknameAnimDone = true;
// Remove after 1.2s
LK.setTimeout(function () {
if (nicknameAnimText) {
nicknameAnimText.destroy();
nicknameAnimText = null;
}
updateNicknameDisplay();
gamePausedForNickname = false;
}, 1200);
}
}, 65);
// Pause game logic until nickname is set
gamePausedForNickname = true;
}
// On first load, always clear storage and assign new nickname, then show Ready button
function resetAndAssignNickname() {
// Clear storage for nickname and leaderboard
storage.nickname = null;
storage.leaderboard = [];
nickname = null;
leaderboard = [];
// Remove any previous nickname text
if (nicknameAnimText) {
nicknameAnimText.destroy();
nicknameAnimText = null;
}
// Remove nickname display if present
if (nicknameDisplayText) {
nicknameDisplayText.destroy();
nicknameDisplayText = null;
}
// Assign new nickname with animation
assignRandomNicknameAndShow();
// After nickname animation is done, show Ready button
function showReadyButtonWhenDone() {
if (nicknameAnimDone) {
// Show Ready button
if (window.readyBtn) {
window.readyBtn.destroy();
window.readyBtn = null;
}
var readyBtn = new Text2("READY", {
size: 140,
fill: 0x00ffcc,
font: "Impact, 'Arial Black', Tahoma",
align: 'center'
});
readyBtn.anchor.set(0.5, 0.5);
readyBtn.x = 2048 / 2;
readyBtn.y = 1100;
game.addChild(readyBtn);
window.readyBtn = readyBtn;
readyBtn.interactive = true;
readyBtn.buttonMode = true;
readyBtn.down = function (x, y, obj) {
// Remove button, unpause game
if (window.readyBtn) {
window.readyBtn.destroy();
window.readyBtn = null;
}
// Hide overlay when Ready is pressed
if (nicknameOverlay) {
nicknameOverlay.visible = false;
}
gamePausedForNickname = false;
// Start background music when Ready is pressed
// (Moved to first tap on red button)
// Create and show breathBar (if not already)
if (!breathBar) {
breathBar = new BreathBar();
// Set fast drain from the start
breathBar.drainPerTick = 0.36; // double the original speed
// Place at right edge, below top margin (avoid top right 100x100)
// breathBar.width is 80, so anchorX:0.5 means center is at x
// Place 80px from right, 160px from top
breathBar.x = 2048 - 80;
breathBar.y = 160;
game.addChild(breathBar);
// Move scoreText below breathBar
// scoreText is already created above, just move it
scoreText.anchor.set(0.5, 0); // center-top
scoreText.x = 2048 - 80; // align with breathBar.x
scoreText.y = breathBar.y + 700 + 30; // breathBar height (700) + 30px margin
// Remove from LK.gui.right if present, add to game
if (scoreText.parent && scoreText.parent.removeChild) {
scoreText.parent.removeChild(scoreText);
}
game.addChild(scoreText);
}
};
} else {
LK.setTimeout(showReadyButtonWhenDone, 100);
}
}
showReadyButtonWhenDone();
// Pause game logic until nickname is set and Ready pressed
gamePausedForNickname = true;
}
resetAndAssignNickname();
function showLeaderboard() {
if (leaderboardText) {
leaderboardText.destroy();
leaderboardText = null;
}
var sorted = leaderboard.slice().sort(function (a, b) {
return b.score - a.score;
}).slice(0, 10);
var lines = ['🏆 TOP SCORES 🏆'];
for (var i = 0; i < sorted.length; i++) {
lines.push(i + 1 + '. ' + sorted[i].nickname + ' - ' + sorted[i].score);
}
leaderboardText = new Text2(lines.join('\n'), {
size: 80,
fill: 0xffff00,
font: "Impact, 'Arial Black', Tahoma",
align: 'center'
});
leaderboardText.anchor.set(0.5, 0.5);
leaderboardText.x = 2048 / 2;
leaderboardText.y = 2732 / 2;
game.addChild(leaderboardText);
// Remove leaderboard after 3 seconds
LK.setTimeout(function () {
if (leaderboardText) {
leaderboardText.destroy();
leaderboardText = null;
}
}, 3000);
}
// On first load, ask for nickname if not set
var gamePausedForNickname = false;
// --- BreathBar instance (created after Ready) ---
var breathBar = null;
// --- Helper: Animate Tap Button Glow ---
function animateTapButtonGlow() {
// Button press animation: scale down then up
tween(tapButton, {
scaleX: 0.92,
scaleY: 0.92
}, {
duration: 80,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(tapButton, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.cubicIn
});
}
});
}
// --- Helper: Add Beat Particle ---
function spawnBeatParticle() {
var p = new BeatParticle();
p.x = 2048 / 2;
p.y = 1200 - 220;
p.vx = (Math.random() - 0.5) * 1.5;
p.vy = -1.5 - Math.random() * 1.5;
p.alpha = 0.8 + Math.random() * 0.2;
beatParticles.push(p);
game.addChild(p);
}
// --- Tap Button Handler ---
function handleTap(x, y, obj) {
if (isGameOver || !canTap) {
return;
}
// Only register tap if inside button
var dx = x - tapButton.x;
var dy = y - tapButton.y;
var r = tapButton.width / 2;
if (dx * dx + dy * dy > r * r) {
return;
}
// Tap registered!
canTap = false;
lastTapTick = LK.ticks;
// Animate
animateTapButtonGlow();
spawnBeatParticle();
// Sound effects removed; only background music remains
// Refill breathBar on tap
if (breathBar) {
breathBar.refill();
}
// Update score and UI
score++;
scoreText.setText(score);
// --- Motivational Text Animation ---
if (score === 20 || score === 50 || score === 80) {
var msg = "";
if (score === 20) msg = "SUPER!";
if (score === 50) msg = "EXCELLENT!";
if (score === 80) msg = "FANTASTIC!";
var motivText = new Text2(msg, {
size: 200,
fill: 0xffff00,
font: "Impact, 'Arial Black', Tahoma",
align: 'center'
});
motivText.anchor.set(0.5, 0.5);
motivText.x = 2048 / 2;
motivText.y = 900;
motivText.alpha = 0.0;
game.addChild(motivText);
// Animate: fade in, scale up, then fade out
motivText.scaleX = motivText.scaleY = 0.7;
tween(motivText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 220,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(motivText, {
alpha: 0,
scaleX: 1.25,
scaleY: 1.25
}, {
duration: 600,
easing: tween.cubicIn,
onFinish: function onFinish() {
motivText.destroy();
}
});
}
});
}
// No game over at 20, 50, or 80 taps; game continues
// Switch character: loop through 3 styles
// Hide all, show next
characterList[characterStyle].visible = false;
characterStyle = (characterStyle + 1) % characterList.length;
characterList[characterStyle].visible = true;
// Animate if Beatboxer
// (No Beatboxer instance present, so no animation triggered here)
// Win condition removed for endless play
}
// --- Tap Button Down/Up/Move ---
var musicStarted = false; // Track if music has started
game.down = function (x, y, obj) {
if (gamePausedForNickname) return;
// Block all background taps if Ready button is visible
if (window.readyBtn) return;
// Start background music on first tap of red button
if (!musicStarted) {
LK.playMusic('neonbeat', {
fade: {
start: 0,
end: 1,
duration: 1200
}
});
musicStarted = true;
}
handleTap(x, y, obj);
};
game.move = function (x, y, obj) {
if (gamePausedForNickname) return;
// Block all background move events if Ready button is visible
if (window.readyBtn) return;
// No drag needed, but allow repeated tap
if (!canTap && LK.ticks - lastTapTick > 7) {
canTap = true;
}
};
game.up = function (x, y, obj) {
if (gamePausedForNickname) return;
// Block all background up events if Ready button is visible
if (window.readyBtn) return;
// Allow next tap
canTap = true;
};
// --- Main Game Update ---
game.update = function () {
if (isGameOver || gamePausedForNickname) {
// Still allow sloganText and background particles to animate
// Animate sloganText neon pulse
sloganText.alpha = 0.85 + 0.15 * Math.sin(LK.ticks * 0.08);
sloganText.scaleX = sloganText.scaleY = 1 + 0.03 * Math.sin(LK.ticks * 0.07);
// Animate background: spawn beat particles
if (LK.ticks % 30 === 0) {
spawnBeatParticle();
}
// Update and cleanup beat particles
for (var i = beatParticles.length - 1; i >= 0; i--) {
var p = beatParticles[i];
p.update();
if (p.destroyed) {
p.destroy();
beatParticles.splice(i, 1);
}
}
// Prevent breathbar from draining or updating while waiting for Ready
return;
}
// --- BreathBar logic (drain, refill, game over) ---
if (breathBar) {
breathBar.update();
if (breathBar.isEmpty() && !isGameOver) {
isGameOver = true;
// Stop background music when breathBar is empty
LK.stopMusic();
// Update best score if needed
if (score > bestScore) {
bestScore = score;
storage.bestScore = bestScore;
if (bestScoreText) bestScoreText.setText('BEST: ' + bestScore);
}
// Show overlay background behind score
var scoreOverlay = LK.getAsset('breathBarBg', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
color: 0x000000
});
scoreOverlay.alpha = 0.7;
scoreOverlay.interactive = false;
game.addChild(scoreOverlay);
// Show "Your Score Is" and the score in the center, but a bit higher
var bigScoreText = new Text2("Your Score Is\n" + score, {
size: 220,
fill: 0xffff00,
font: "Impact, 'Arial Black', Tahoma",
align: 'center'
});
bigScoreText.anchor.set(0.5, 0.5);
bigScoreText.x = 2048 / 2;
// Move further up (higher on the screen)
bigScoreText.y = 800;
game.addChild(bigScoreText);
// Animate: fade in, scale up, then stay visible (do not fade out or destroy)
bigScoreText.alpha = 0.0;
bigScoreText.scaleX = bigScoreText.scaleY = 0.7;
tween(bigScoreText, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 420,
easing: tween.cubicOut,
onFinish: function onFinish() {
// Do not fade out or destroy, keep on screen
// Remove overlay and show game over after a short delay, but keep bigScoreText
LK.setTimeout(function () {
if (scoreOverlay) scoreOverlay.destroy();
LK.showGameOver();
}, 1500);
}
});
// Optionally, flash bar red
tween(breathBar, {
alpha: 0.2
}, {
duration: 200,
yoyo: true,
repeat: 2,
onFinish: function onFinish() {
breathBar.alpha = 1;
}
});
}
}
// Animate sloganText neon pulse
sloganText.alpha = 0.85 + 0.15 * Math.sin(LK.ticks * 0.08);
sloganText.scaleX = sloganText.scaleY = 1 + 0.03 * Math.sin(LK.ticks * 0.07);
// Animate background: spawn beat particles
if (LK.ticks % 30 === 0) {
spawnBeatParticle();
}
// Update and cleanup beat particles
for (var i = beatParticles.length - 1; i >= 0; i--) {
var p = beatParticles[i];
p.update();
if (p.destroyed) {
p.destroy();
beatParticles.splice(i, 1);
}
}
};
// --- Play Music ---
// (Music now starts after Ready is pressed, see readyBtn.down handler)