User prompt
The paddle keeps getting bigger fix that ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Fix the error ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Timeout.tick error: Invalid end type for property fill: undefined' in or related to this line: 'tween(scoreTxt, {' Line Number: 1828 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add better animations ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add animations to everything ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add volume sliders rather than presets ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
now add an extra page of settings for sounds in game and have it on another page and to get to the sound settings you click a down arrow in the settings that pulls up the sound settings and does a little page flip animation ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add an animation when you enter and exit the settings ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the settings better to make every part of the game customizable like visualy ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
center the 'new high score' text
User prompt
animate the lava ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
put the select game mode text just a bit higher
User prompt
make the box corners in the select game mode screen rounded
User prompt
add some different game modes that the player can play
User prompt
add a back button so you can go to the start screen
User prompt
when ever the ball hits the paddle or a wall add particles
User prompt
make the radius of where the particles go smaller
User prompt
make them smaller
User prompt
make them smaller
User prompt
make the particles a bit smaller
User prompt
add particles when the cursor is clicked make them big ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add a click sound when ever the cursor is clicked
User prompt
make it so when you go past level 3 the music changes to heavy metal but before that is relaxing music
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphic = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = 0; self.speedY = 0; self.active = true; self.trailCounter = 0; self.gravity = 0.18; // Further reduced gravity for slower falling self.airResistance = 0.995; // Slightly increased air resistance for slower movement self.bounciness = 0.92; // Lower bounciness for less energetic bounces self.spin = 0; // Ball spin (affects horizontal movement) self.lastHitPos = 0; // Last hit position on paddle (for spin calculation) self.reset = function (speedMultiplier) { // Set position to center of screen self.x = 2048 / 2; self.y = 2732 / 2; // Generate a random angle between 0 and 2π (full 360 degrees) var randomAngle = Math.random() * Math.PI * 2; // Set initial speed magnitude var speedMagnitude = 15 * speedMultiplier; // Calculate velocity components based on random angle self.speedX = Math.cos(randomAngle) * speedMagnitude; self.speedY = Math.sin(randomAngle) * speedMagnitude; self.active = true; self.spin = 0; // Reset spin self.lastHitPos = 0; // Reset last hit position }; self.update = function () { if (!self.active) { return; } // Store last positions for collision detection var lastX = self.x; var lastY = self.y; // Apply gravity - increases vertical speed over time self.speedY += self.gravity; // Apply air resistance self.speedX *= self.airResistance; self.speedY *= self.airResistance; // Apply spin effect to horizontal movement self.speedX += self.spin * 0.1; // Gradually reduce spin over time self.spin *= 0.98; // Apply velocity self.x += self.speedX; self.y += self.speedY; // Add trail effect based on speed self.trailCounter++; // Adjust trail frequency based on speed - faster speed = more frequent trails var trailFrequency = Math.max(1, 5 - Math.floor((Math.abs(self.speedX) + Math.abs(self.speedY)) / 10)); // Create more trails at higher speeds if (self.trailCounter > trailFrequency) { self.trailCounter = 0; var trail = LK.getAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: lastX, y: lastY }); // Only create trail if trails are enabled if (!visualSettings.trailsEnabled) { self.trailCounter = 0; return; } // Adjust trail size based on ball speed and settings var speedFactor = Math.min(1, (Math.abs(self.speedX) + Math.abs(self.speedY)) / 40); var trailSize = (0.7 - speedFactor * 0.2) * visualSettings.ballSize * visualSettings.trailIntensity; trail.scale.set(self.scale.x * trailSize, self.scale.y * trailSize); trail.tint = visualSettings.ballColor; // Higher alpha for faster speeds, adjusted by trail intensity trail.alpha = (0.5 + speedFactor * 0.3) * visualSettings.trailIntensity; game.addChildAt(trail, game.getChildIndex(self)); // Fade out and remove trail - faster trails disappear quicker, adjusted by animation speed var trailDuration = (300 - speedFactor * 150) / visualSettings.animationSpeed; tween(trail, { alpha: 0, scaleX: trail.scale.x * 0.5, scaleY: trail.scale.y * 0.5 }, { duration: trailDuration, onFinish: function onFinish() { trail.destroy(); } }); } // Rotate the ball based on horizontal speed to show rolling effect ballGraphic.rotation += self.speedX * 0.05; // Bounce off sides with more random physics if (self.x < 20 || self.x > 2028) { // Create particles at wall collision point createCollisionParticles(self.x, self.y); // Flip the horizontal direction self.speedX = -self.speedX * self.bounciness * 1.2; // Add significant random variation to both speed components self.speedX += Math.random() * 6 - 3; // Major randomness on x-axis self.speedY += Math.random() * 4 - 2; // Add randomness to y-axis on wall bounce too // Chance for a very wild bounce (20% chance) if (Math.random() < 0.2) { self.speedX *= 0.5 + Math.random(); self.speedY *= 0.5 + Math.random(); } // Keep the ball within the game boundaries self.x = Math.max(20, Math.min(2028, self.x)); // Play bounce sound if soundEnabled is true if (soundEnabled) { LK.getSound('bounce').play(); } } // Check if ball hits the top of the screen with more random bounces if (self.y < 20) { // Create particles at ceiling collision point createCollisionParticles(self.x, self.y); // Flip the vertical direction self.speedY = -self.speedY * self.bounciness * 1.25; // Add significant random variation to both speed components self.speedX += Math.random() * 5 - 2.5; // Add randomness to x-axis on ceiling bounce self.speedY += Math.random() * 5 - 2.5; // Major randomness on y-axis // Chance for a very wild bounce (20% chance) if (Math.random() < 0.2) { // Completely random direction after ceiling hit var randomAngle = Math.random() * Math.PI + Math.PI; // Angle in bottom half var currentSpeed = Math.sqrt(self.speedX * self.speedX + self.speedY * self.speedY); self.speedX = Math.cos(randomAngle) * currentSpeed; self.speedY = Math.sin(randomAngle) * currentSpeed; } self.y = 20; // Play bounce sound if soundEnabled is true if (soundEnabled) { LK.getSound('bounce').play(); } } }; return self; }); var DiagonalStripe = Container.expand(function () { var self = Container.call(this); // Create a shape for the diagonal stripe var stripeGraphic = self.attachAsset('background', { anchorX: 0, anchorY: 0 }); // Configure the stripe appearance stripeGraphic.width = 3000; // Increased width to extend past screen edges stripeGraphic.height = 100; stripeGraphic.tint = 0xffffff; // White // Initial position and rotation stripeGraphic.rotation = Math.PI / 4; // 45 degrees in radians // Position it to extend past screen edges stripeGraphic.x = -500; // Start before the left edge // Empty update method (stripe will be still) self.update = function () { // No animation - stripe remains still }; return self; }); var Paddle = Container.expand(function () { var self = Container.call(this); // Create the main paddle base - middle rectangle section var paddleGraphic = self.attachAsset('paddle', { anchorX: 0.5, anchorY: 0.5 }); paddleGraphic.tint = 0xFFB612; // Set paddle color to #FFB612 // Create the left rounded end (circle shape) var leftEnd = LK.getAsset('ball', { // Using the ball asset as it's a circle anchorX: 0.5, anchorY: 0.5, width: paddleGraphic.height, height: paddleGraphic.height, tint: 0xFFB612 }); leftEnd.x = -paddleGraphic.width / 2 + leftEnd.width / 2; self.addChild(leftEnd); // Create the right rounded end (circle shape) var rightEnd = LK.getAsset('ball', { // Using the ball asset as it's a circle anchorX: 0.5, anchorY: 0.5, width: paddleGraphic.height, height: paddleGraphic.height, tint: 0xFFB612 }); rightEnd.x = paddleGraphic.width / 2 - rightEnd.width / 2; // Make sure the right end is the correct color rightEnd.tint = 0xFFB612; self.addChild(rightEnd); // Trim the main paddle to accommodate rounded ends paddleGraphic.width = paddleGraphic.width - paddleGraphic.height; self.width = paddleGraphic.width + paddleGraphic.height; // Total width includes the circles self.height = paddleGraphic.height; self.update = function () { // Keep paddle within screen bounds self.x = Math.max(self.width / 2, Math.min(2048 - self.width / 2, self.x)); }; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphic = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); // Initial size scale based on settings var particleScale = 0.5 * visualSettings.particleSize * visualSettings.particleIntensity; self.scale.set(particleScale, particleScale); // Particle colors from settings particleGraphic.tint = visualSettings.particleColors[Math.floor(Math.random() * visualSettings.particleColors.length)]; // Random speed and direction var angle = Math.random() * Math.PI * 2; var speed = 2 + Math.random() * 8; self.vx = Math.cos(angle) * speed; self.vy = Math.sin(angle) * speed; // Random rotation self.rotationSpeed = (Math.random() - 0.5) * 0.2; // Particle lifespan tracking self.lifetime = 0; self.maxLifetime = 30 + Math.random() * 30; // Update function self.update = function () { // Update position with reduced movement (smaller radius) self.x += self.vx * 0.5; // Reduce horizontal movement by 50% self.vy += 0.1; // Gravity effect self.y += self.vy * 0.5; // Reduce vertical movement by 50% // Rotate particle particleGraphic.rotation += self.rotationSpeed; // Update lifetime self.lifetime++; // Fade out based on lifetime if (self.lifetime > self.maxLifetime * 0.7) { self.alpha = 1 - (self.lifetime - self.maxLifetime * 0.7) / (self.maxLifetime * 0.3); } // Remove when lifetime is over if (self.lifetime >= self.maxLifetime) { self.active = false; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xffffff // Light sky blue for a calmer atmosphere }); /**** * Game Code ****/ // Game state management 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); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var GAME_STATE = { MENU: 0, PLAYING: 1, SETTINGS: 2, MODE_SELECT: 3 }; var currentState = GAME_STATE.MENU; // Game modes var GAME_MODES = { CLASSIC: 0, SPEED_DEMON: 1, MULTI_BALL: 2, SURVIVAL: 3 }; var currentGameMode = GAME_MODES.CLASSIC; // Game mode configurations var gameModeConfigs = _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, GAME_MODES.CLASSIC, { name: "Classic Mode", description: "The original Lava Bounce experience.\nBounce balls and level up gradually.", initialSpeed: 1.5, speedIncrease: 0.4, maxBalls: 1, hitsPerLevel: 25 }), GAME_MODES.SPEED_DEMON, { name: "Speed Demon", description: "Fast-paced action from the start!\nHigh speed, quick reflexes required.", initialSpeed: 3.0, speedIncrease: 0.8, maxBalls: 1, hitsPerLevel: 15 }), GAME_MODES.MULTI_BALL, { name: "Multi-Ball Madness", description: "Multiple balls create chaos!\nManage several balls at once.", initialSpeed: 1.2, speedIncrease: 0.3, maxBalls: 3, hitsPerLevel: 35 }), GAME_MODES.SURVIVAL, { name: "Survival Mode", description: "How long can you last?\nIncreasing difficulty, one life only.", initialSpeed: 1.0, speedIncrease: 0.6, maxBalls: 1, hitsPerLevel: 20 }); // Visual customization settings with defaults var visualSettings = { // Colors paddleColor: storage.paddleColor || 0xFFB612, ballColor: storage.ballColor || 0xFFB612, lavaColor: storage.lavaColor || 0xC60C30, backgroundColor: storage.backgroundColor || 0xFFFFFF, textColor: storage.textColor || 0x101820, uiColor: storage.uiColor || 0xFFFFFF, particleColors: storage.particleColors || [0xFFB612, 0xC60C30, 0x003087, 0xFFFFFF], // Effects trailsEnabled: storage.trailsEnabled !== undefined ? storage.trailsEnabled : true, particlesEnabled: storage.particlesEnabled !== undefined ? storage.particlesEnabled : true, screenShakeEnabled: storage.screenShakeEnabled !== undefined ? storage.screenShakeEnabled : true, lavaAnimationEnabled: storage.lavaAnimationEnabled !== undefined ? storage.lavaAnimationEnabled : true, // Sizes ballSize: storage.ballSize || 1.0, paddleSize: storage.paddleSize || 1.0, textSize: storage.textSize || 1.0, particleSize: storage.particleSize || 1.0, // Visual intensity trailIntensity: storage.trailIntensity || 1.0, particleIntensity: storage.particleIntensity || 1.0, animationSpeed: storage.animationSpeed || 1.0 }; // Default colors for game elements - using customizable settings var gameColors = { paddle: visualSettings.paddleColor, ball: visualSettings.ballColor, lava: visualSettings.lavaColor }; // Function to save visual settings function saveVisualSettings() { storage.paddleColor = visualSettings.paddleColor; storage.ballColor = visualSettings.ballColor; storage.lavaColor = visualSettings.lavaColor; storage.backgroundColor = visualSettings.backgroundColor; storage.textColor = visualSettings.textColor; storage.uiColor = visualSettings.uiColor; storage.particleColors = visualSettings.particleColors; storage.trailsEnabled = visualSettings.trailsEnabled; storage.particlesEnabled = visualSettings.particlesEnabled; storage.screenShakeEnabled = visualSettings.screenShakeEnabled; storage.lavaAnimationEnabled = visualSettings.lavaAnimationEnabled; storage.ballSize = visualSettings.ballSize; storage.paddleSize = visualSettings.paddleSize; storage.textSize = visualSettings.textSize; storage.particleSize = visualSettings.particleSize; storage.trailIntensity = visualSettings.trailIntensity; storage.particleIntensity = visualSettings.particleIntensity; storage.animationSpeed = visualSettings.animationSpeed; } // Function to apply visual settings to game elements function applyVisualSettings() { // Update game colors gameColors.paddle = visualSettings.paddleColor; gameColors.ball = visualSettings.ballColor; gameColors.lava = visualSettings.lavaColor; // Update background color if (game) { game.setBackgroundColor(visualSettings.backgroundColor); } if (background) { background.tint = visualSettings.backgroundColor; } if (menuBackground) { menuBackground.getChildAt(1).tint = visualSettings.backgroundColor; } } // Make game accessible to other functions var gameInstance = game; // Game variables var background; var paddle; var lava; var balls = []; var particles = []; // Array to track active particles var score = 0; var highScore = storage.highScore || 0; var level = 1; var combo = 0; var lastBallHit = 0; var gameActive = false; var speedMultiplier = 1.0; var maxBalls = 1; var ballsInPlay = 0; var spawnInterval; var hitsToNextLevel = 25; var currentHits = 0; var hitCounterText; // UI elements var scoreTxt; var levelTxt; var comboTxt; var highScoreTxt; var speedTxt; var backButton; // Default sound settings var soundEnabled = storage.soundEnabled !== undefined ? storage.soundEnabled : true; var musicEnabled = storage.musicEnabled !== undefined ? storage.musicEnabled : true; // Initialize game elements (called when starting game) function initializeGameElements() { if (!background) { // Create background background = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(background); // Initialize lava lava = LK.getAsset('lava', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: 2732 - 200 }); lava.tint = visualSettings.lavaColor; game.addChild(lava); // Start lava animation animateLava(); // Initialize paddle paddle = new Paddle(); paddle.x = 2048 / 2; paddle.y = 2732 - 250; paddle.getChildAt(0).tint = visualSettings.paddleColor; // Apply paddle size scaling paddle.scale.set(visualSettings.paddleSize, visualSettings.paddleSize); game.addChild(paddle); // Diagonal stripe removed from here and placed in menu // Create hit counter text scoreTxt = new Text2('0', { size: 180, fill: 0x101820 }); scoreTxt.anchor.set(0.5, 0.5); // Position score text precisely in the center of the screen scoreTxt.x = 2048 / 2; // True center horizontally scoreTxt.y = 2732 / 2; // True center vertically game.addChild(scoreTxt); // Create level text levelTxt = new Text2('Level: 1', { size: 70, fill: 0xFFFFFF }); levelTxt.anchor.set(1, 0); levelTxt.x = 2000; levelTxt.y = 50; LK.gui.addChild(levelTxt); // Create combo text comboTxt = new Text2('', { size: 60, fill: 0xFFFFFF }); comboTxt.anchor.set(0.5, 0); comboTxt.x = 1024; comboTxt.y = 50; comboTxt.alpha = 0; LK.gui.addChild(comboTxt); // Create high score text highScoreTxt = new Text2('High Score: ' + highScore, { size: 60, fill: 0xffb612 }); highScoreTxt.anchor.set(1, 0); highScoreTxt.x = 2000; highScoreTxt.y = 130; // Position below hit counter game.addChild(highScoreTxt); // Add directly to game to ensure visibility // Create speed indicator text speedTxt = new Text2('Speed: x' + speedMultiplier.toFixed(1), { size: 60, fill: 0xffb612 }); speedTxt.anchor.set(0, 0); speedTxt.x = 48; speedTxt.y = 50; game.addChild(speedTxt); // Create game mode indicator var modeIndicator = new Text2(gameModeConfigs[currentGameMode].name, { size: 50, fill: 0x003087 }); modeIndicator.anchor.set(0, 0); modeIndicator.x = 48; modeIndicator.y = 130; game.addChild(modeIndicator); // Create hit counter text hitCounterText = new Text2(currentHits + '/25', { size: 70, fill: 0x003087 }); hitCounterText.anchor.set(0.5, 0); hitCounterText.x = 1024; hitCounterText.y = 150; // More visible position at top of screen game.addChild(hitCounterText); // Add directly to game to ensure visibility // Create back button backButton = new Text2('← Menu', { size: 50, fill: 0xFFB612 }); backButton.anchor.set(0, 0); backButton.x = 120; // Position to avoid platform menu icon backButton.y = 120; backButton.interactive = true; backButton.down = function () { if (soundEnabled) { LK.getSound('click').play(); } // Stop current game gameActive = false; // Clear balls for (var i = 0; i < balls.length; i++) { balls[i].destroy(); } balls = []; ballsInPlay = 0; // Hide game elements hideGameElements(); // Show menu showMenu(); }; game.addChild(backButton); } // Show game elements background.visible = true; lava.visible = true; paddle.visible = true; scoreTxt.visible = true; levelTxt.visible = true; comboTxt.visible = true; highScoreTxt.visible = true; hitCounterText.visible = true; backButton.visible = true; } // Create menu elements var titleText; var startButton; var settingsButton; var settingsPanel; var menuBackground; // Initialize menu initializeMenu(); function initializeMenu() { // Play menu music if enabled if (musicEnabled) { LK.playMusic('menuMusic', { fade: { start: 0, end: 0.6, duration: 1500 } }); } // Create menu background menuBackground = new Container(); var menuBg = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, tint: 0xFFFFFF // White color for menu background }); // Create a border by adding a slightly larger background behind it var menuBorder = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, tint: 0xA5ACAF // Border color set to #A5ACAF }); menuBorder.width = 2048 + 10 * 2; // Adding 10px on each side menuBorder.height = 2732 + 10 * 2; // Adding 10px on each side menuBorder.x = -10; // Position it 10px to the left menuBorder.y = -10; // Position it 10px to the top menuBackground.addChild(menuBorder); menuBackground.addChild(menuBg); game.addChild(menuBackground); // Diagonal stripe removed from menu // Create game title titleText = new Text2('Lava Bounce', { size: 150, fill: 0x101820 }); titleText.anchor.set(0.5, 0); titleText.x = 1024; titleText.y = 200; game.addChild(titleText); // Animate the title to rotate back and forth function animateTitleRotation() { // Rotate to one side tween(titleText, { rotation: 0.1 // Slight rotation to the right (in radians) }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { // Rotate to the other side tween(titleText, { rotation: -0.1 // Slight rotation to the left (in radians) }, { duration: 1000, easing: tween.easeInOut, onFinish: animateTitleRotation // Loop the animation }); } }); } // Start the title rotation animation animateTitleRotation(); // Create the "2" as a separate, larger text element var titleNumber = new Text2('2', { size: 200, // Bigger than the main title text fill: 0xFFB612 // Gold color }); titleNumber.anchor.set(0.5, 0); titleNumber.x = 1024; // Centered horizontally titleNumber.y = 350; // Positioned below the main title game.addChild(titleNumber); // Animate the "2" with a continuous bounce effect function animateTitle2() { // Bounce up animation tween(titleNumber, { y: 320, // Move up slightly scaleX: 1.1, scaleY: 1.1 }, { duration: 700, onFinish: function onFinish() { // Bounce down animation tween(titleNumber, { y: 350, // Back to original position scaleX: 1, scaleY: 1 }, { duration: 700, onFinish: animateTitle2 // Loop the animation }); } }); } // Start the animation animateTitle2(); // Create start button startButton = new Text2('Start Game', { size: 90, fill: 0xFFB612 }); startButton.anchor.set(0.5, 0.5); startButton.x = 1024; startButton.y = 1200; startButton.interactive = true; startButton.isHovered = false; // Track hover state startButton.move = function (x, y, obj) { // Check if cursor is over the button if (x >= startButton.x - startButton.width / 2 && x <= startButton.x + startButton.width / 2 && y >= startButton.y - startButton.height / 2 && y <= startButton.y + startButton.height / 2) { // Start animation only if not already hovering if (!startButton.isHovered) { startButton.isHovered = true; // Apply a slight scale increase when hovered tween(startButton, { scaleX: 1.05, scaleY: 1.05 }, { duration: 200, easing: tween.easeOut }); animateStartButton(); } } else { // Stop animation when cursor moves away if (startButton.isHovered) { startButton.isHovered = false; tween.stop(startButton, { rotation: true }); tween(startButton, { rotation: 0, scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } } }; // Function to animate the start button function animateStartButton() { if (!startButton.isHovered) { return; } // Rotate to one side tween(startButton, { rotation: 0.08 // Slight rotation (in radians) }, { duration: 50, // Very quick rotation for more responsive feel easing: tween.easeInOut, onFinish: function onFinish() { if (!startButton.isHovered) { startButton.rotation = 0; return; } // Rotate to the other side tween(startButton, { rotation: -0.08 // Slight rotation in opposite direction }, { duration: 50, // Very quick rotation for more responsive feel easing: tween.easeInOut, onFinish: animateStartButton // Continue the animation }); } }); } game.addChild(startButton); // Create settings button settingsButton = new Text2('Settings', { size: 90, fill: 0x101820 }); settingsButton.anchor.set(0.5, 0.5); settingsButton.x = 1024; settingsButton.y = 1400; settingsButton.interactive = true; game.addChild(settingsButton); // Set up event handlers for menu startButton.down = function () { if (soundEnabled) { LK.getSound('click').play(); } hideMenu(); showModeSelect(); }; settingsButton.down = function () { if (soundEnabled) { LK.getSound('click').play(); } hideMenu(); showSettings(); }; } function hideMenu() { if (menuBackground) { menuBackground.visible = false; } if (titleText) { titleText.visible = false; } if (startButton) { startButton.visible = false; } if (settingsButton) { settingsButton.visible = false; } // Make sure high score is visible in game if (highScoreTxt) { highScoreTxt.visible = true; } } function hideGameElements() { if (background) { background.visible = false; } if (lava) { lava.visible = false; } if (paddle) { paddle.visible = false; } if (scoreTxt) { scoreTxt.visible = false; } if (levelTxt) { levelTxt.visible = false; } if (comboTxt) { comboTxt.visible = false; } if (highScoreTxt) { highScoreTxt.visible = false; } if (hitCounterText) { hitCounterText.visible = false; } if (speedTxt) { speedTxt.visible = false; } if (backButton) { backButton.visible = false; } } function showMenu() { currentState = GAME_STATE.MENU; if (menuBackground) { menuBackground.visible = true; } if (titleText) { titleText.visible = true; } if (startButton) { startButton.visible = true; } if (settingsButton) { settingsButton.visible = true; } if (settingsPanel) { settingsPanel.visible = false; } // Play menu music when returning to menu from game over if (musicEnabled && currentState === GAME_STATE.MENU) { LK.playMusic('menuMusic', { fade: { start: 0, end: 0.6, duration: 1000 } }); } } // Mode selection screen var modeSelectPanel; var modeButtons = []; function showModeSelect() { currentState = GAME_STATE.MODE_SELECT; // Create mode select panel if it doesn't exist if (!modeSelectPanel) { modeSelectPanel = new Container(); game.addChild(modeSelectPanel); // Mode select background var modeBg = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, tint: 0xFFFFFF }); modeSelectPanel.addChild(modeBg); // Mode select title var modeTitle = new Text2('Select Game Mode', { size: 120, fill: 0x101820 }); modeTitle.anchor.set(0.5, 0); modeTitle.x = 1024; modeTitle.y = 100; modeSelectPanel.addChild(modeTitle); // Create mode buttons var modeKeys = Object.keys(GAME_MODES); for (var i = 0; i < modeKeys.length; i++) { var modeKey = modeKeys[i]; var modeId = GAME_MODES[modeKey]; var config = gameModeConfigs[modeId]; var yPos = 400 + i * 320; // Mode button container var modeContainer = new Container(); modeContainer.x = 1024; modeContainer.y = yPos; modeSelectPanel.addChild(modeContainer); // Mode button background with rounded corners var buttonBg = new Container(); // Main rectangle body var mainRect = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); mainRect.width = 1700; // Slightly smaller for rounded ends mainRect.height = 280; mainRect.tint = 0x101820; buttonBg.addChild(mainRect); // Left rounded corner (circle) var leftCorner = LK.getAsset('ball', { anchorX: 0.5, anchorY: 0.5, width: 280, height: 280, tint: 0x101820 }); leftCorner.x = -850; // Position at left edge leftCorner.y = 0; buttonBg.addChild(leftCorner); // Right rounded corner (circle) var rightCorner = LK.getAsset('ball', { anchorX: 0.5, anchorY: 0.5, width: 280, height: 280, tint: 0x101820 }); rightCorner.x = 850; // Position at right edge rightCorner.y = 0; buttonBg.addChild(rightCorner); modeContainer.addChild(buttonBg); // Mode name var modeName = new Text2(config.name, { size: 80, fill: 0xFFB612 }); modeName.anchor.set(0.5, 0); modeName.x = 0; modeName.y = -80; modeContainer.addChild(modeName); // Mode description var modeDesc = new Text2(config.description, { size: 50, fill: 0xFFFFFF }); modeDesc.anchor.set(0.5, 0); modeDesc.x = 0; modeDesc.y = -20; modeContainer.addChild(modeDesc); // Make button interactive modeContainer.interactive = true; modeContainer.modeId = modeId; modeContainer.down = function () { if (soundEnabled) { LK.getSound('click').play(); } currentGameMode = this.modeId; hideModeSelect(); // Stop menu music with fade out if (musicEnabled) { LK.playMusic('menuMusic', { fade: { start: 0.6, end: 0, duration: 500 } }); } initializeGameElements(); startGame(); }; modeButtons.push(modeContainer); } // Back to menu button var backToMenuBtn = new Text2('← Back to Menu', { size: 70, fill: 0x101820 }); backToMenuBtn.anchor.set(0.5, 0.5); backToMenuBtn.x = 1024; backToMenuBtn.y = 2500; backToMenuBtn.interactive = true; backToMenuBtn.down = function () { if (soundEnabled) { LK.getSound('click').play(); } hideModeSelect(); showMenu(); }; modeSelectPanel.addChild(backToMenuBtn); } else { modeSelectPanel.visible = true; } } function hideModeSelect() { if (modeSelectPanel) { modeSelectPanel.visible = false; } } function showSettings() { currentState = GAME_STATE.SETTINGS; // Create settings panel if it doesn't exist if (!settingsPanel) { settingsPanel = new Container(); game.addChild(settingsPanel); // Settings panel background var panelBg = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); panelBg.width = 2048; panelBg.height = 2732; panelBg.tint = 0x101820; settingsPanel.addChild(panelBg); // Settings title var settingsTitle = new Text2('Visual Settings', { size: 100 * visualSettings.textSize, fill: visualSettings.uiColor }); settingsTitle.anchor.set(0.5, 0); settingsTitle.x = 1024; settingsTitle.y = 100; settingsPanel.addChild(settingsTitle); // Create scrollable settings content var settingsContent = new Container(); settingsContent.y = 0; settingsPanel.addChild(settingsContent); var currentY = 250; var spacing = 120; // Color settings section var colorTitle = new Text2('Colors', { size: 80 * visualSettings.textSize, fill: 0xFFB612 }); colorTitle.anchor.set(0, 0); colorTitle.x = 100; colorTitle.y = currentY; settingsContent.addChild(colorTitle); currentY += spacing; // Color presets var colorPresets = [{ name: 'Classic Gold', paddle: 0xFFB612, ball: 0xFFB612, lava: 0xC60C30, bg: 0xFFFFFF, text: 0x101820, ui: 0xFFFFFF }, { name: 'Ocean Blue', paddle: 0x3498DB, ball: 0x2980B9, lava: 0xE74C3C, bg: 0xECF0F1, text: 0x2C3E50, ui: 0xFFFFFF }, { name: 'Forest Green', paddle: 0x27AE60, ball: 0x2ECC71, lava: 0xE67E22, bg: 0xF8F9FA, text: 0x1E3A8A, ui: 0xFFFFFF }, { name: 'Purple Power', paddle: 0x8E44AD, ball: 0x9B59B6, lava: 0xE74C3C, bg: 0xF4F3FF, text: 0x4C1D95, ui: 0xFFFFFF }, { name: 'Sunset', paddle: 0xFF6B35, ball: 0xFF8C42, lava: 0xC70025, bg: 0xFFF8DC, text: 0x8B0000, ui: 0xFFFFFF }]; for (var i = 0; i < colorPresets.length; i++) { var preset = colorPresets[i]; var presetButton = new Text2(preset.name, { size: 60 * visualSettings.textSize, fill: preset.paddle }); presetButton.anchor.set(0, 0); presetButton.x = 150; presetButton.y = currentY; presetButton.interactive = true; presetButton.preset = preset; presetButton.down = function () { if (soundEnabled) LK.getSound('click').play(); // Apply preset colors visualSettings.paddleColor = this.preset.paddle; visualSettings.ballColor = this.preset.ball; visualSettings.lavaColor = this.preset.lava; visualSettings.backgroundColor = this.preset.bg; visualSettings.textColor = this.preset.text; visualSettings.uiColor = this.preset.ui; saveVisualSettings(); applyVisualSettings(); // Refresh settings panel settingsPanel.destroy(); settingsPanel = null; showSettings(); }; settingsContent.addChild(presetButton); currentY += 80; } currentY += 40; // Effects section var effectsTitle = new Text2('Effects', { size: 80 * visualSettings.textSize, fill: 0xFFB612 }); effectsTitle.anchor.set(0, 0); effectsTitle.x = 100; effectsTitle.y = currentY; settingsContent.addChild(effectsTitle); currentY += spacing; // Effects toggles var effectsSettings = [{ key: 'trailsEnabled', name: 'Ball Trails' }, { key: 'particlesEnabled', name: 'Particles' }, { key: 'screenShakeEnabled', name: 'Screen Shake' }, { key: 'lavaAnimationEnabled', name: 'Lava Animation' }]; for (var i = 0; i < effectsSettings.length; i++) { var setting = effectsSettings[i]; var toggleText = new Text2(setting.name + ': ' + (visualSettings[setting.key] ? 'ON' : 'OFF'), { size: 60 * visualSettings.textSize, fill: visualSettings[setting.key] ? 0x00FF00 : 0xFF0000 }); toggleText.anchor.set(0, 0); toggleText.x = 150; toggleText.y = currentY; toggleText.interactive = true; toggleText.settingKey = setting.key; toggleText.settingName = setting.name; toggleText.down = function () { if (soundEnabled) LK.getSound('click').play(); visualSettings[this.settingKey] = !visualSettings[this.settingKey]; saveVisualSettings(); this.setText(this.settingName + ': ' + (visualSettings[this.settingKey] ? 'ON' : 'OFF')); this.fill = visualSettings[this.settingKey] ? 0x00FF00 : 0xFF0000; }; settingsContent.addChild(toggleText); currentY += 80; } currentY += 40; // Size settings section var sizeTitle = new Text2('Sizes', { size: 80 * visualSettings.textSize, fill: 0xFFB612 }); sizeTitle.anchor.set(0, 0); sizeTitle.x = 100; sizeTitle.y = currentY; settingsContent.addChild(sizeTitle); currentY += spacing; // Size presets var sizePresets = [{ name: 'Small', ball: 0.8, paddle: 0.8, text: 0.8, particle: 0.8 }, { name: 'Normal', ball: 1.0, paddle: 1.0, text: 1.0, particle: 1.0 }, { name: 'Large', ball: 1.3, paddle: 1.2, text: 1.2, particle: 1.2 }, { name: 'Extra Large', ball: 1.6, paddle: 1.4, text: 1.4, particle: 1.4 }]; for (var i = 0; i < sizePresets.length; i++) { var preset = sizePresets[i]; var sizeButton = new Text2(preset.name, { size: 60 * visualSettings.textSize, fill: 0xFFFFFF }); sizeButton.anchor.set(0, 0); sizeButton.x = 150; sizeButton.y = currentY; sizeButton.interactive = true; sizeButton.preset = preset; sizeButton.down = function () { if (soundEnabled) LK.getSound('click').play(); // Apply size preset visualSettings.ballSize = this.preset.ball; visualSettings.paddleSize = this.preset.paddle; visualSettings.textSize = this.preset.text; visualSettings.particleSize = this.preset.particle; saveVisualSettings(); // Refresh settings panel settingsPanel.destroy(); settingsPanel = null; showSettings(); }; settingsContent.addChild(sizeButton); currentY += 80; } currentY += 40; // Reset all settings button var resetAllButton = new Text2('Reset All Settings', { size: 70 * visualSettings.textSize, fill: 0xFF6B6B }); resetAllButton.anchor.set(0.5, 0.5); resetAllButton.x = 1024; resetAllButton.y = currentY; resetAllButton.interactive = true; resetAllButton.down = function () { if (soundEnabled) LK.getSound('click').play(); // Reset to defaults visualSettings.paddleColor = 0xFFB612; visualSettings.ballColor = 0xFFB612; visualSettings.lavaColor = 0xC60C30; visualSettings.backgroundColor = 0xFFFFFF; visualSettings.textColor = 0x101820; visualSettings.uiColor = 0xFFFFFF; visualSettings.trailsEnabled = true; visualSettings.particlesEnabled = true; visualSettings.screenShakeEnabled = true; visualSettings.lavaAnimationEnabled = true; visualSettings.ballSize = 1.0; visualSettings.paddleSize = 1.0; visualSettings.textSize = 1.0; visualSettings.particleSize = 1.0; visualSettings.trailIntensity = 1.0; visualSettings.particleIntensity = 1.0; visualSettings.animationSpeed = 1.0; saveVisualSettings(); applyVisualSettings(); // Refresh settings panel settingsPanel.destroy(); settingsPanel = null; showSettings(); }; settingsContent.addChild(resetAllButton); currentY += 120; // High score display var highScoreDisplay = new Text2('High Score: ' + highScore, { size: 60 * visualSettings.textSize, fill: visualSettings.uiColor }); highScoreDisplay.anchor.set(0.5, 0.5); highScoreDisplay.x = 1024; highScoreDisplay.y = currentY; settingsContent.addChild(highScoreDisplay); currentY += 100; // Reset high score button var resetScoreButton = new Text2('Reset High Score', { size: 60 * visualSettings.textSize, fill: 0xFF6B6B }); resetScoreButton.anchor.set(0.5, 0.5); resetScoreButton.x = 1024; resetScoreButton.y = currentY; resetScoreButton.interactive = true; resetScoreButton.down = function () { if (soundEnabled) LK.getSound('click').play(); showResetConfirmation(); }; settingsContent.addChild(resetScoreButton); currentY += 100; // Back to menu button var backButton = new Text2('← Back to Menu', { size: 70 * visualSettings.textSize, fill: visualSettings.uiColor }); backButton.anchor.set(0.5, 0.5); backButton.x = 1024; backButton.y = currentY; backButton.interactive = true; backButton.down = function () { if (soundEnabled) LK.getSound('click').play(); settingsPanel.visible = false; showMenu(); if (musicEnabled) { LK.playMusic('menuMusic', { fade: { start: 0, end: 0.6, duration: 1000 } }); } }; settingsContent.addChild(backButton); // Make settings panel scrollable settingsPanel.interactive = true; settingsPanel.scrollY = 0; settingsPanel.move = function (x, y, obj) { // Simple scroll implementation if (obj && obj.event && obj.event.movementY) { settingsContent.y += obj.event.movementY * 2; settingsContent.y = Math.max(Math.min(0, settingsContent.y), -(currentY - 2732 + 200)); } }; } else { settingsPanel.visible = true; } } // Function to create particles at click location function createClickParticles(x, y) { // Only create particles if enabled if (!visualSettings.particlesEnabled) { return; } // Create 15-20 particles for a visually impressive effect, adjusted by intensity var baseCount = 15 + Math.floor(Math.random() * 6); var particleCount = Math.floor(baseCount * visualSettings.particleIntensity); for (var i = 0; i < particleCount; i++) { var particle = new Particle(); particle.x = x; particle.y = y; particle.active = true; // Add to particles array and game display particles.push(particle); game.addChild(particle); } } // Function to create particles at collision location function createCollisionParticles(x, y) { // Only create particles if enabled if (!visualSettings.particlesEnabled) { return; } // Create 8-12 particles for collision effect - fewer than click particles, adjusted by intensity var baseCount = 8 + Math.floor(Math.random() * 5); var particleCount = Math.floor(baseCount * visualSettings.particleIntensity); for (var i = 0; i < particleCount; i++) { var particle = new Particle(); particle.x = x; particle.y = y; particle.active = true; var collisionScale = 0.3 * visualSettings.particleSize * visualSettings.particleIntensity; particle.scale.set(collisionScale, collisionScale); // Smaller particles for collisions // Add to particles array and game display particles.push(particle); game.addChild(particle); } } // Initialize balls array function createBall() { if (ballsInPlay >= maxBalls || !gameActive) { return; } var ball = new Ball(); ball.reset(speedMultiplier); ball.getChildAt(0).tint = visualSettings.ballColor; // Visual indicator of speed - make ball slightly smaller as it gets faster, adjusted by ball size setting var scale = Math.max(0.6, 1 - (speedMultiplier - 1) * 0.15) * visualSettings.ballSize; ball.scale.set(scale, scale); balls.push(ball); game.addChild(ball); ballsInPlay++; } // Handle input events based on current state game.down = function (x, y, obj) { // Play click sound whenever cursor is clicked if (soundEnabled) { LK.getSound('click').play(); } // Create particles at click location createClickParticles(x, y); if (currentState === GAME_STATE.PLAYING) { paddle.x = x; } // Check if we hit any interactive elements if (obj && obj.event && obj.event.target && obj.event.target.down) { obj.event.target.down(x, y, obj); } }; game.move = function (x, y, obj) { if (currentState === GAME_STATE.PLAYING) { paddle.x = x; } }; // Update function game.update = function () { // Update any diagonal stripes in the game (always update even when not playing) for (var i = 0; i < game.children.length; i++) { if (game.children[i] instanceof DiagonalStripe) { game.children[i].update(); } } // Update all particles for (var i = particles.length - 1; i >= 0; i--) { var particle = particles[i]; if (particle.active === false) { particle.destroy(); particles.splice(i, 1); continue; } particle.update(); } // Check if in playing state if (currentState !== GAME_STATE.PLAYING) { return; } // Game play state if (!gameActive) { return; } // Update speed indicator if it exists if (speedTxt) { speedTxt.setText('Speed: x' + speedMultiplier.toFixed(1)); } // Create balls based on game mode if (currentGameMode === GAME_MODES.MULTI_BALL) { // Multi-ball mode: maintain multiple balls while (ballsInPlay < maxBalls) { createBall(); } } else { // Other modes: only create a ball if none exists if (ballsInPlay === 0) { createBall(); } } // Update paddle and track position for physics calculations game.lastPaddleX = paddle.x; // Store current position for next frame paddle.update(); // Update all balls for (var i = balls.length - 1; i >= 0; i--) { var ball = balls[i]; if (!ball.active) { continue; } ball.update(); // Check if ball hits paddle with improved collision detection if (ball.speedY > 0 && ball.y + 20 >= paddle.y - paddle.height / 2 && ball.y - 20 <= paddle.y + paddle.height / 2 && ball.x + 20 >= paddle.x - paddle.width / 2 && ball.x - 20 <= paddle.x + paddle.width / 2) { // Create particles at collision point createCollisionParticles(ball.x, ball.y); // Calculate hit position from -1 (left edge) to 1 (right edge) var hitPos = (ball.x - paddle.x) / (paddle.width / 2); // Calculate spin based on the difference between current and last hit position // This simulates the effect of a moving paddle hitting the ball var paddleMovementEffect = 0; if (game.lastPaddleX !== undefined) { paddleMovementEffect = (paddle.x - game.lastPaddleX) * 0.1; } // Apply reduced spin based on hit position and paddle movement ball.spin = hitPos * 0.3 + paddleMovementEffect * 0.6; // Reduced spin effect ball.lastHitPos = hitPos; // Calculate angle based on where the ball hits the paddle with more randomness // Wider angle range - full 180 degrees (0 to 180) instead of 120 degrees var angle = Math.PI * Math.random() + Math.PI / 2; // Random angle in upper half (90 to 270 degrees) // Add influence from hit position angle = angle * 0.7 + (Math.PI / 3 * hitPos + Math.PI / 2) * 0.3; // Calculate current speed with an adjustment var currentSpeed = Math.sqrt(ball.speedX * ball.speedX + ball.speedY * ball.speedY); var speed = Math.max(currentSpeed * 1.25, 12 * speedMultiplier); // Adjust ball direction with more random bounce physics ball.speedX = Math.cos(angle) * speed + paddleMovementEffect * 1.5; ball.speedY = -Math.sin(angle) * speed * 1.4; // Increased vertical multiplier for higher bounce // Add larger random variations for more unpredictable bouncing ball.speedX += (Math.random() * 4 - 2) * speedMultiplier; // Increased randomness ball.speedY += (Math.random() * 4 - 2) * speedMultiplier; // Increased randomness // Create a bounce effect with the paddle - make it visually respond to the hit tween(paddle, { scaleY: 0.85, y: paddle.y + 5 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(paddle, { scaleY: 1.0, y: paddle.y - 5 }, { duration: 100, easing: tween.elasticOut }); } }); // Move ball above paddle to prevent multiple collisions ball.y = paddle.y - paddle.height / 2 - 20; // Add a visual impact effect var impactEffect = LK.getAsset('ball', { anchorX: 0.5, anchorY: 0.5, x: ball.x, y: ball.y + 10, tint: 0xFFFFFF }); impactEffect.scale.set(1.5, 0.5); impactEffect.alpha = 0.7; game.addChild(impactEffect); // Animate and remove the impact effect tween(impactEffect, { alpha: 0, scaleX: 2.5, scaleY: 0.2 }, { duration: 200, onFinish: function onFinish() { impactEffect.destroy(); } }); // Simple scoring - always add 1 point score += 1; // Hide combo text comboTxt.alpha = 0; // Update hit counter scoreTxt.setText('' + score); // Center the score text scoreTxt.x = 2048 / 2; // True center horizontally scoreTxt.y = 2732 / 2; // True center vertically // Make it fade and gently grow when updated tween(scoreTxt, { scaleX: 1.1, // Smaller scale change scaleY: 1.1, // Smaller scale change alpha: 0.8 // Slight fade out }, { duration: 300, // Longer duration for smoother animation easing: tween.easeInOut, // Smoother easing onFinish: function onFinish() { tween(scoreTxt, { scaleX: 1, scaleY: 1, alpha: 1 // Back to full opacity }, { duration: 300, // Longer duration easing: tween.easeInOut // Smoother easing }); } }); LK.setScore(score); // Play bounce sound if enabled if (soundEnabled) { LK.getSound('bounce').play(); } // Update hit counter for level system currentHits++; hitCounterText.setText(currentHits + '/' + hitsToNextLevel); // Level up based on hits if (currentHits >= hitsToNextLevel) { currentHits = 0; levelUp(); hitCounterText.setText('Hits to Next Level: ' + hitsToNextLevel); // Animate hit counter text tween(hitCounterText, { scaleX: 1.2, scaleY: 1.2, alpha: 0.8 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { tween(hitCounterText, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 300, easing: tween.easeInOut }); } }); } } // Check if ball falls into lava if (ball.y > lava.y) { // Play lava sound if enabled if (soundEnabled) { LK.getSound('lava').play(); } // Flash the lava tween(lava, { tint: 0xffffff }, { duration: 200, onFinish: function onFinish() { tween(lava, { tint: 0xe74c3c }, { duration: 200 }); } }); // Remove ball ball.active = false; ball.destroy(); balls.splice(i, 1); ballsInPlay--; // Check game over if (balls.length === 0 && ballsInPlay === 0) { gameOver(); } } } }; // Reset confirmation popup function showResetConfirmation() { // Create popup container var popup = new Container(); game.addChild(popup); // Popup background var popupBg = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); popupBg.width = 1200; popupBg.height = 700; popupBg.tint = 0x101820; popup.addChild(popupBg); // Border for popup var popupBorder = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); popupBorder.width = 1210; popupBorder.height = 710; popupBorder.tint = 0xFFB612; popup.addChildAt(popupBorder, 0); // Confirmation text var confirmText = new Text2('Reset High Score?', { size: 70, fill: 0xFFFFFF }); confirmText.anchor.set(0.5, 0); confirmText.x = 1024; confirmText.y = 1200; popup.addChild(confirmText); // Yes button var yesButton = new Text2('Yes', { size: 60, fill: 0xFF6B6B }); yesButton.anchor.set(0.5, 0.5); yesButton.x = 824; yesButton.y = 1450; yesButton.interactive = true; yesButton.down = function () { if (soundEnabled) { LK.getSound('click').play(); } // Reset high score highScore = 0; storage.highScore = 0; // Update high score display if (highScoreTxt) { highScoreTxt.setText('High Score: 0'); } // Update settings display settingsPanel.children.forEach(function (child) { if (child instanceof Text2 && child.text && child.text.startsWith('High Score:')) { child.setText('High Score: 0'); } }); // Remove popup with animation tween(popup, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 300, onFinish: function onFinish() { popup.destroy(); } }); }; popup.addChild(yesButton); // No button var noButton = new Text2('No', { size: 60, fill: 0xFFFFFF }); noButton.anchor.set(0.5, 0.5); noButton.x = 1224; noButton.y = 1450; noButton.interactive = true; noButton.down = function () { if (soundEnabled) { LK.getSound('click').play(); } // Remove popup with animation tween(popup, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 300, onFinish: function onFinish() { popup.destroy(); } }); }; popup.addChild(noButton); // Animate popup appearing popup.scale.set(0.8, 0.8); popup.alpha = 0; tween(popup, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); } function levelUp() { level++; levelTxt.setText('Level: ' + level); // Show level up message with speed information var levelUpTxt = new Text2('LEVEL UP!\nSpeed x' + speedMultiplier.toFixed(1), { size: 80, fill: 0xFFFFFF }); levelUpTxt.anchor.set(0.5, 0.5); levelUpTxt.x = 1024; levelUpTxt.y = 1366; LK.gui.addChild(levelUpTxt); // Animate level up message tween(levelUpTxt, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 1000, onFinish: function onFinish() { levelUpTxt.destroy(); } }); // Change music to heavy metal if level is 4 or above if (level === 4 && musicEnabled) { // Transition to heavy metal music with fade effects LK.playMusic('heavyMetalMusic', { fade: { start: 0, end: 0.7, duration: 1500 } }); } // Get current mode configuration var modeConfig = gameModeConfigs[currentGameMode]; // Increase difficulty based on game mode speedMultiplier += modeConfig.speedIncrease + level * 0.08; maxBalls = modeConfig.maxBalls; // Reset hit counter for next level currentHits = 0; // Set hits required for next level based on mode hitsToNextLevel = modeConfig.hitsPerLevel + (level - 1) * 5; hitCounterText.setText('0/' + hitsToNextLevel); } function gameOver() { gameActive = false; // Check if we have a new high score if (score > highScore) { highScore = score; storage.highScore = highScore; // Show new high score message var newHighScoreTxt = new Text2('NEW HIGH SCORE!', { size: 80, fill: 0xFFB612 }); newHighScoreTxt.anchor.set(0.5, 0.5); newHighScoreTxt.x = 2048 / 2; // True center horizontally newHighScoreTxt.y = 1000; LK.gui.addChild(newHighScoreTxt); // Animate high score message tween(newHighScoreTxt, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 1500, onFinish: function onFinish() { newHighScoreTxt.destroy(); } }); // Update high score display if (highScoreTxt) { highScoreTxt.setText('High Score: ' + highScore); } } // Flash the screen red to indicate death LK.effects.flashScreen(0xff0000, 500); // If music enabled and player was at level 4 or above, prepare to reset music var shouldResetMusic = level >= 4 && musicEnabled; // Restart the game after a short delay instead of showing menu LK.setTimeout(function () { // Keep the game elements visible, just restart game logic // Clear any remaining balls for (var i = 0; i < balls.length; i++) { balls[i].destroy(); } balls = []; ballsInPlay = 0; // Restart the game immediately startGame(); // Ensure we're in playing state currentState = GAME_STATE.PLAYING; }, 500); } // Start the game function startGame() { // Get current mode configuration var modeConfig = gameModeConfigs[currentGameMode]; // Reset variables score = 0; level = 1; combo = 0; lastBallHit = 0; gameActive = true; speedMultiplier = modeConfig.initialSpeed; maxBalls = modeConfig.maxBalls; ballsInPlay = 0; currentHits = 0; hitsToNextLevel = modeConfig.hitsPerLevel; // Update UI scoreTxt.setText('0'); scoreTxt.scale.set(1, 1); // Reset any scaling from animations scoreTxt.x = 2048 / 2; // True center horizontally scoreTxt.y = 2732 / 2; // True center vertically levelTxt.setText('Level: 1'); comboTxt.setText(''); comboTxt.alpha = 0; hitCounterText.setText('0/' + hitsToNextLevel); // Update high score display if (highScoreTxt) { highScoreTxt.setText('High Score: ' + highScore); } // Clear any existing balls for (var i = 0; i < balls.length; i++) { balls[i].destroy(); } balls = []; // Start with one ball createBall(); // Play relaxing game music at start (level 1-3) if (musicEnabled) { LK.playMusic('gameMusic', { fade: { start: 0, end: 0.4, // Lower volume duration: 2000 // Longer fade in } }); } // Ensure the current state is set to playing currentState = GAME_STATE.PLAYING; } // Apply visual settings on initialization applyVisualSettings(); // Game will start when player presses the Play button in the menu // Function to animate the lava with multiple effects function animateLava() { if (!visualSettings.lavaAnimationEnabled) { // Just apply the static lava color if animations are disabled if (lava) { lava.tint = visualSettings.lavaColor; } return; } // Pulsing scale animation function pulseLava() { if (!visualSettings.lavaAnimationEnabled) return; tween(lava, { scaleY: 1.05, scaleX: 1.02 }, { duration: (800 + Math.random() * 400) / visualSettings.animationSpeed, easing: tween.easeInOut, onFinish: function onFinish() { if (!visualSettings.lavaAnimationEnabled) return; tween(lava, { scaleY: 0.98, scaleX: 1.01 }, { duration: (600 + Math.random() * 400) / visualSettings.animationSpeed, easing: tween.easeInOut, onFinish: pulseLava }); } }); } // Color shifting animation - based on the selected lava color function shiftLavaColor() { if (!visualSettings.lavaAnimationEnabled) return; // Create variations of the selected lava color var baseLava = visualSettings.lavaColor; var colors = [baseLava, baseLava + 0x111111, baseLava - 0x111111, baseLava + 0x220000, baseLava - 0x110011]; var randomColor = colors[Math.floor(Math.random() * colors.length)]; tween(lava, { tint: randomColor }, { duration: (1500 + Math.random() * 1000) / visualSettings.animationSpeed, easing: tween.easeInOut, onFinish: shiftLavaColor }); } // Subtle vertical movement to simulate bubbling function bubbleLava() { if (!visualSettings.lavaAnimationEnabled) return; var originalY = lava.y; tween(lava, { y: originalY - 5 - Math.random() * 8 }, { duration: (400 + Math.random() * 300) / visualSettings.animationSpeed, easing: tween.easeInOut, onFinish: function onFinish() { if (!visualSettings.lavaAnimationEnabled) return; tween(lava, { y: originalY + 3 + Math.random() * 4 }, { duration: (500 + Math.random() * 200) / visualSettings.animationSpeed, easing: tween.easeInOut, onFinish: function onFinish() { if (!visualSettings.lavaAnimationEnabled) return; tween(lava, { y: originalY }, { duration: (300 + Math.random() * 200) / visualSettings.animationSpeed, easing: tween.easeOut, onFinish: function onFinish() { // Wait a bit before next bubble cycle LK.setTimeout(bubbleLava, (500 + Math.random() * 1500) / visualSettings.animationSpeed); } }); } }); } }); } // Start all animations pulseLava(); shiftLavaColor(); LK.setTimeout(bubbleLava, Math.random() * 1000 / visualSettings.animationSpeed); // Start bubbling with random delay }
===================================================================
--- original.js
+++ change.js
@@ -70,17 +70,23 @@
anchorY: 0.5,
x: lastX,
y: lastY
});
- // Adjust trail size based on ball speed
+ // Only create trail if trails are enabled
+ if (!visualSettings.trailsEnabled) {
+ self.trailCounter = 0;
+ return;
+ }
+ // Adjust trail size based on ball speed and settings
var speedFactor = Math.min(1, (Math.abs(self.speedX) + Math.abs(self.speedY)) / 40);
- trail.scale.set(self.scale.x * (0.7 - speedFactor * 0.2), self.scale.y * (0.7 - speedFactor * 0.2));
- trail.tint = gameColors.ball;
- // Higher alpha for faster speeds
- trail.alpha = 0.5 + speedFactor * 0.3;
+ var trailSize = (0.7 - speedFactor * 0.2) * visualSettings.ballSize * visualSettings.trailIntensity;
+ trail.scale.set(self.scale.x * trailSize, self.scale.y * trailSize);
+ trail.tint = visualSettings.ballColor;
+ // Higher alpha for faster speeds, adjusted by trail intensity
+ trail.alpha = (0.5 + speedFactor * 0.3) * visualSettings.trailIntensity;
game.addChildAt(trail, game.getChildIndex(self));
- // Fade out and remove trail - faster trails disappear quicker
- var trailDuration = 300 - speedFactor * 150;
+ // Fade out and remove trail - faster trails disappear quicker, adjusted by animation speed
+ var trailDuration = (300 - speedFactor * 150) / visualSettings.animationSpeed;
tween(trail, {
alpha: 0,
scaleX: trail.scale.x * 0.5,
scaleY: trail.scale.y * 0.5
@@ -208,13 +214,13 @@
var particleGraphic = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
- // Initial size scale
- self.scale.set(0.5, 0.5); // Start with smaller particles
- // Particle colors
- var colors = [0xFFB612, 0xC60C30, 0x003087, 0xFFFFFF];
- particleGraphic.tint = colors[Math.floor(Math.random() * colors.length)];
+ // Initial size scale based on settings
+ var particleScale = 0.5 * visualSettings.particleSize * visualSettings.particleIntensity;
+ self.scale.set(particleScale, particleScale);
+ // Particle colors from settings
+ particleGraphic.tint = visualSettings.particleColors[Math.floor(Math.random() * visualSettings.particleColors.length)];
// Random speed and direction
var angle = Math.random() * Math.PI * 2;
var speed = 2 + Math.random() * 8;
self.vx = Math.cos(angle) * speed;
@@ -331,17 +337,77 @@
speedIncrease: 0.6,
maxBalls: 1,
hitsPerLevel: 20
});
-// Default colors for game elements - softer, more calming colors
+// Visual customization settings with defaults
+var visualSettings = {
+ // Colors
+ paddleColor: storage.paddleColor || 0xFFB612,
+ ballColor: storage.ballColor || 0xFFB612,
+ lavaColor: storage.lavaColor || 0xC60C30,
+ backgroundColor: storage.backgroundColor || 0xFFFFFF,
+ textColor: storage.textColor || 0x101820,
+ uiColor: storage.uiColor || 0xFFFFFF,
+ particleColors: storage.particleColors || [0xFFB612, 0xC60C30, 0x003087, 0xFFFFFF],
+ // Effects
+ trailsEnabled: storage.trailsEnabled !== undefined ? storage.trailsEnabled : true,
+ particlesEnabled: storage.particlesEnabled !== undefined ? storage.particlesEnabled : true,
+ screenShakeEnabled: storage.screenShakeEnabled !== undefined ? storage.screenShakeEnabled : true,
+ lavaAnimationEnabled: storage.lavaAnimationEnabled !== undefined ? storage.lavaAnimationEnabled : true,
+ // Sizes
+ ballSize: storage.ballSize || 1.0,
+ paddleSize: storage.paddleSize || 1.0,
+ textSize: storage.textSize || 1.0,
+ particleSize: storage.particleSize || 1.0,
+ // Visual intensity
+ trailIntensity: storage.trailIntensity || 1.0,
+ particleIntensity: storage.particleIntensity || 1.0,
+ animationSpeed: storage.animationSpeed || 1.0
+};
+// Default colors for game elements - using customizable settings
var gameColors = {
- paddle: 0xffb612,
- // Changed to requested color #ffb612
- ball: 0xFFB612,
- // Changed to requested color #FFB612
- lava: 0xC60C30 // Changed to requested color #C60C30
+ paddle: visualSettings.paddleColor,
+ ball: visualSettings.ballColor,
+ lava: visualSettings.lavaColor
};
-// Color saving/loading disabled
+// Function to save visual settings
+function saveVisualSettings() {
+ storage.paddleColor = visualSettings.paddleColor;
+ storage.ballColor = visualSettings.ballColor;
+ storage.lavaColor = visualSettings.lavaColor;
+ storage.backgroundColor = visualSettings.backgroundColor;
+ storage.textColor = visualSettings.textColor;
+ storage.uiColor = visualSettings.uiColor;
+ storage.particleColors = visualSettings.particleColors;
+ storage.trailsEnabled = visualSettings.trailsEnabled;
+ storage.particlesEnabled = visualSettings.particlesEnabled;
+ storage.screenShakeEnabled = visualSettings.screenShakeEnabled;
+ storage.lavaAnimationEnabled = visualSettings.lavaAnimationEnabled;
+ storage.ballSize = visualSettings.ballSize;
+ storage.paddleSize = visualSettings.paddleSize;
+ storage.textSize = visualSettings.textSize;
+ storage.particleSize = visualSettings.particleSize;
+ storage.trailIntensity = visualSettings.trailIntensity;
+ storage.particleIntensity = visualSettings.particleIntensity;
+ storage.animationSpeed = visualSettings.animationSpeed;
+}
+// Function to apply visual settings to game elements
+function applyVisualSettings() {
+ // Update game colors
+ gameColors.paddle = visualSettings.paddleColor;
+ gameColors.ball = visualSettings.ballColor;
+ gameColors.lava = visualSettings.lavaColor;
+ // Update background color
+ if (game) {
+ game.setBackgroundColor(visualSettings.backgroundColor);
+ }
+ if (background) {
+ background.tint = visualSettings.backgroundColor;
+ }
+ if (menuBackground) {
+ menuBackground.getChildAt(1).tint = visualSettings.backgroundColor;
+ }
+}
// Make game accessible to other functions
var gameInstance = game;
// Game variables
var background;
@@ -369,15 +435,10 @@
var highScoreTxt;
var speedTxt;
var backButton;
// Default sound settings
-var soundEnabled = true;
-var musicEnabled = true;
-// Load stored sound settings
-var soundSetting = storage.soundEnabled;
-if (soundSetting !== undefined) {
- soundEnabled = soundSetting;
-}
+var soundEnabled = storage.soundEnabled !== undefined ? storage.soundEnabled : true;
+var musicEnabled = storage.musicEnabled !== undefined ? storage.musicEnabled : true;
// Initialize game elements (called when starting game)
function initializeGameElements() {
if (!background) {
// Create background
@@ -394,17 +455,19 @@
anchorY: 0,
x: 2048 / 2,
y: 2732 - 200
});
- lava.tint = gameColors.lava;
+ lava.tint = visualSettings.lavaColor;
game.addChild(lava);
// Start lava animation
animateLava();
// Initialize paddle
paddle = new Paddle();
paddle.x = 2048 / 2;
paddle.y = 2732 - 250;
- paddle.getChildAt(0).tint = 0xffb612;
+ paddle.getChildAt(0).tint = visualSettings.paddleColor;
+ // Apply paddle size scaling
+ paddle.scale.set(visualSettings.paddleSize, visualSettings.paddleSize);
game.addChild(paddle);
// Diagonal stripe removed from here and placed in menu
// Create hit counter text
scoreTxt = new Text2('0', {
@@ -946,128 +1009,338 @@
// Create settings panel if it doesn't exist
if (!settingsPanel) {
settingsPanel = new Container();
game.addChild(settingsPanel);
- // Settings panel background without border
- var panelContainer = new Container();
- panelContainer.x = 1024;
- panelContainer.y = 1366;
- // Set initial scale to zero for animation
- panelContainer.scale.x = 0;
- panelContainer.scale.y = 0;
- // Inner panel background (without blue border)
+ // Settings panel background
var panelBg = LK.getAsset('background', {
- anchorX: 0.5,
- anchorY: 0.5,
+ anchorX: 0,
+ anchorY: 0,
x: 0,
y: 0
});
- panelBg.width = 1600;
- panelBg.height = 1000;
- panelBg.tint = 0x101820; // Dark blue/black color for settings panel
- panelContainer.addChild(panelBg);
- settingsPanel.addChild(panelContainer);
+ panelBg.width = 2048;
+ panelBg.height = 2732;
+ panelBg.tint = 0x101820;
+ settingsPanel.addChild(panelBg);
// Settings title
- var settingsTitle = new Text2('Settings', {
- size: 80,
- fill: 0xFFFFFF
+ var settingsTitle = new Text2('Visual Settings', {
+ size: 100 * visualSettings.textSize,
+ fill: visualSettings.uiColor
});
settingsTitle.anchor.set(0.5, 0);
settingsTitle.x = 1024;
- settingsTitle.y = 500;
+ settingsTitle.y = 100;
settingsPanel.addChild(settingsTitle);
- // Color selectors have been removed
- // Game description text
- var gameDescription = new Text2('Lava Bounce 2: A frantic paddle game where you\ncontrol a golden paddle to bounce balls away from\ndeadly red lava. Score points with each bounce,\nlevel up for increased speed and challenge.\nCan you set a new high score record?', {
- size: 50,
+ // Create scrollable settings content
+ var settingsContent = new Container();
+ settingsContent.y = 0;
+ settingsPanel.addChild(settingsContent);
+ var currentY = 250;
+ var spacing = 120;
+ // Color settings section
+ var colorTitle = new Text2('Colors', {
+ size: 80 * visualSettings.textSize,
fill: 0xFFB612
});
- gameDescription.anchor.set(0.5, 0.5);
- gameDescription.x = 1024; // True center horizontally
- gameDescription.y = 700;
- settingsPanel.addChild(gameDescription);
- // High score display in settings
+ colorTitle.anchor.set(0, 0);
+ colorTitle.x = 100;
+ colorTitle.y = currentY;
+ settingsContent.addChild(colorTitle);
+ currentY += spacing;
+ // Color presets
+ var colorPresets = [{
+ name: 'Classic Gold',
+ paddle: 0xFFB612,
+ ball: 0xFFB612,
+ lava: 0xC60C30,
+ bg: 0xFFFFFF,
+ text: 0x101820,
+ ui: 0xFFFFFF
+ }, {
+ name: 'Ocean Blue',
+ paddle: 0x3498DB,
+ ball: 0x2980B9,
+ lava: 0xE74C3C,
+ bg: 0xECF0F1,
+ text: 0x2C3E50,
+ ui: 0xFFFFFF
+ }, {
+ name: 'Forest Green',
+ paddle: 0x27AE60,
+ ball: 0x2ECC71,
+ lava: 0xE67E22,
+ bg: 0xF8F9FA,
+ text: 0x1E3A8A,
+ ui: 0xFFFFFF
+ }, {
+ name: 'Purple Power',
+ paddle: 0x8E44AD,
+ ball: 0x9B59B6,
+ lava: 0xE74C3C,
+ bg: 0xF4F3FF,
+ text: 0x4C1D95,
+ ui: 0xFFFFFF
+ }, {
+ name: 'Sunset',
+ paddle: 0xFF6B35,
+ ball: 0xFF8C42,
+ lava: 0xC70025,
+ bg: 0xFFF8DC,
+ text: 0x8B0000,
+ ui: 0xFFFFFF
+ }];
+ for (var i = 0; i < colorPresets.length; i++) {
+ var preset = colorPresets[i];
+ var presetButton = new Text2(preset.name, {
+ size: 60 * visualSettings.textSize,
+ fill: preset.paddle
+ });
+ presetButton.anchor.set(0, 0);
+ presetButton.x = 150;
+ presetButton.y = currentY;
+ presetButton.interactive = true;
+ presetButton.preset = preset;
+ presetButton.down = function () {
+ if (soundEnabled) LK.getSound('click').play();
+ // Apply preset colors
+ visualSettings.paddleColor = this.preset.paddle;
+ visualSettings.ballColor = this.preset.ball;
+ visualSettings.lavaColor = this.preset.lava;
+ visualSettings.backgroundColor = this.preset.bg;
+ visualSettings.textColor = this.preset.text;
+ visualSettings.uiColor = this.preset.ui;
+ saveVisualSettings();
+ applyVisualSettings();
+ // Refresh settings panel
+ settingsPanel.destroy();
+ settingsPanel = null;
+ showSettings();
+ };
+ settingsContent.addChild(presetButton);
+ currentY += 80;
+ }
+ currentY += 40;
+ // Effects section
+ var effectsTitle = new Text2('Effects', {
+ size: 80 * visualSettings.textSize,
+ fill: 0xFFB612
+ });
+ effectsTitle.anchor.set(0, 0);
+ effectsTitle.x = 100;
+ effectsTitle.y = currentY;
+ settingsContent.addChild(effectsTitle);
+ currentY += spacing;
+ // Effects toggles
+ var effectsSettings = [{
+ key: 'trailsEnabled',
+ name: 'Ball Trails'
+ }, {
+ key: 'particlesEnabled',
+ name: 'Particles'
+ }, {
+ key: 'screenShakeEnabled',
+ name: 'Screen Shake'
+ }, {
+ key: 'lavaAnimationEnabled',
+ name: 'Lava Animation'
+ }];
+ for (var i = 0; i < effectsSettings.length; i++) {
+ var setting = effectsSettings[i];
+ var toggleText = new Text2(setting.name + ': ' + (visualSettings[setting.key] ? 'ON' : 'OFF'), {
+ size: 60 * visualSettings.textSize,
+ fill: visualSettings[setting.key] ? 0x00FF00 : 0xFF0000
+ });
+ toggleText.anchor.set(0, 0);
+ toggleText.x = 150;
+ toggleText.y = currentY;
+ toggleText.interactive = true;
+ toggleText.settingKey = setting.key;
+ toggleText.settingName = setting.name;
+ toggleText.down = function () {
+ if (soundEnabled) LK.getSound('click').play();
+ visualSettings[this.settingKey] = !visualSettings[this.settingKey];
+ saveVisualSettings();
+ this.setText(this.settingName + ': ' + (visualSettings[this.settingKey] ? 'ON' : 'OFF'));
+ this.fill = visualSettings[this.settingKey] ? 0x00FF00 : 0xFF0000;
+ };
+ settingsContent.addChild(toggleText);
+ currentY += 80;
+ }
+ currentY += 40;
+ // Size settings section
+ var sizeTitle = new Text2('Sizes', {
+ size: 80 * visualSettings.textSize,
+ fill: 0xFFB612
+ });
+ sizeTitle.anchor.set(0, 0);
+ sizeTitle.x = 100;
+ sizeTitle.y = currentY;
+ settingsContent.addChild(sizeTitle);
+ currentY += spacing;
+ // Size presets
+ var sizePresets = [{
+ name: 'Small',
+ ball: 0.8,
+ paddle: 0.8,
+ text: 0.8,
+ particle: 0.8
+ }, {
+ name: 'Normal',
+ ball: 1.0,
+ paddle: 1.0,
+ text: 1.0,
+ particle: 1.0
+ }, {
+ name: 'Large',
+ ball: 1.3,
+ paddle: 1.2,
+ text: 1.2,
+ particle: 1.2
+ }, {
+ name: 'Extra Large',
+ ball: 1.6,
+ paddle: 1.4,
+ text: 1.4,
+ particle: 1.4
+ }];
+ for (var i = 0; i < sizePresets.length; i++) {
+ var preset = sizePresets[i];
+ var sizeButton = new Text2(preset.name, {
+ size: 60 * visualSettings.textSize,
+ fill: 0xFFFFFF
+ });
+ sizeButton.anchor.set(0, 0);
+ sizeButton.x = 150;
+ sizeButton.y = currentY;
+ sizeButton.interactive = true;
+ sizeButton.preset = preset;
+ sizeButton.down = function () {
+ if (soundEnabled) LK.getSound('click').play();
+ // Apply size preset
+ visualSettings.ballSize = this.preset.ball;
+ visualSettings.paddleSize = this.preset.paddle;
+ visualSettings.textSize = this.preset.text;
+ visualSettings.particleSize = this.preset.particle;
+ saveVisualSettings();
+ // Refresh settings panel
+ settingsPanel.destroy();
+ settingsPanel = null;
+ showSettings();
+ };
+ settingsContent.addChild(sizeButton);
+ currentY += 80;
+ }
+ currentY += 40;
+ // Reset all settings button
+ var resetAllButton = new Text2('Reset All Settings', {
+ size: 70 * visualSettings.textSize,
+ fill: 0xFF6B6B
+ });
+ resetAllButton.anchor.set(0.5, 0.5);
+ resetAllButton.x = 1024;
+ resetAllButton.y = currentY;
+ resetAllButton.interactive = true;
+ resetAllButton.down = function () {
+ if (soundEnabled) LK.getSound('click').play();
+ // Reset to defaults
+ visualSettings.paddleColor = 0xFFB612;
+ visualSettings.ballColor = 0xFFB612;
+ visualSettings.lavaColor = 0xC60C30;
+ visualSettings.backgroundColor = 0xFFFFFF;
+ visualSettings.textColor = 0x101820;
+ visualSettings.uiColor = 0xFFFFFF;
+ visualSettings.trailsEnabled = true;
+ visualSettings.particlesEnabled = true;
+ visualSettings.screenShakeEnabled = true;
+ visualSettings.lavaAnimationEnabled = true;
+ visualSettings.ballSize = 1.0;
+ visualSettings.paddleSize = 1.0;
+ visualSettings.textSize = 1.0;
+ visualSettings.particleSize = 1.0;
+ visualSettings.trailIntensity = 1.0;
+ visualSettings.particleIntensity = 1.0;
+ visualSettings.animationSpeed = 1.0;
+ saveVisualSettings();
+ applyVisualSettings();
+ // Refresh settings panel
+ settingsPanel.destroy();
+ settingsPanel = null;
+ showSettings();
+ };
+ settingsContent.addChild(resetAllButton);
+ currentY += 120;
+ // High score display
var highScoreDisplay = new Text2('High Score: ' + highScore, {
- size: 60,
- fill: 0xFFFFFF
+ size: 60 * visualSettings.textSize,
+ fill: visualSettings.uiColor
});
- highScoreDisplay.anchor.set(0, 0.5);
- highScoreDisplay.x = 400;
- highScoreDisplay.y = 970; // Moved down a bit
- settingsPanel.addChild(highScoreDisplay);
+ highScoreDisplay.anchor.set(0.5, 0.5);
+ highScoreDisplay.x = 1024;
+ highScoreDisplay.y = currentY;
+ settingsContent.addChild(highScoreDisplay);
+ currentY += 100;
// Reset high score button
- var resetButton = new Text2('Reset High Score', {
- size: 60,
+ var resetScoreButton = new Text2('Reset High Score', {
+ size: 60 * visualSettings.textSize,
fill: 0xFF6B6B
});
- resetButton.anchor.set(0.5, 0.5);
- resetButton.x = 1024; // True center horizontally
- resetButton.y = 1366; // True center vertically
- resetButton.interactive = true;
- resetButton.down = function () {
- if (soundEnabled) {
- LK.getSound('click').play();
- }
+ resetScoreButton.anchor.set(0.5, 0.5);
+ resetScoreButton.x = 1024;
+ resetScoreButton.y = currentY;
+ resetScoreButton.interactive = true;
+ resetScoreButton.down = function () {
+ if (soundEnabled) LK.getSound('click').play();
showResetConfirmation();
};
- settingsPanel.addChild(resetButton);
+ settingsContent.addChild(resetScoreButton);
+ currentY += 100;
// Back to menu button
- var backButton = new Text2('Back to Menu', {
- size: 60,
- fill: 0xFFFFFF
+ var backButton = new Text2('← Back to Menu', {
+ size: 70 * visualSettings.textSize,
+ fill: visualSettings.uiColor
});
backButton.anchor.set(0.5, 0.5);
backButton.x = 1024;
- backButton.y = 1100;
+ backButton.y = currentY;
backButton.interactive = true;
backButton.down = function () {
- if (soundEnabled) {
- LK.getSound('click').play();
- }
- // Animate settings panel closing
- tween(settingsPanel.getChildAt(0), {
- scaleX: 0,
- scaleY: 0
- }, {
- duration: 300,
- easing: tween.easeIn,
- onFinish: function onFinish() {
- settingsPanel.visible = false;
- showMenu();
- // Play menu music when returning to menu
- if (musicEnabled) {
- LK.playMusic('menuMusic', {
- fade: {
- start: 0,
- end: 0.6,
- duration: 1000
- }
- });
+ if (soundEnabled) LK.getSound('click').play();
+ settingsPanel.visible = false;
+ showMenu();
+ if (musicEnabled) {
+ LK.playMusic('menuMusic', {
+ fade: {
+ start: 0,
+ end: 0.6,
+ duration: 1000
}
- }
- });
+ });
+ }
};
- settingsPanel.addChild(backButton);
+ settingsContent.addChild(backButton);
+ // Make settings panel scrollable
+ settingsPanel.interactive = true;
+ settingsPanel.scrollY = 0;
+ settingsPanel.move = function (x, y, obj) {
+ // Simple scroll implementation
+ if (obj && obj.event && obj.event.movementY) {
+ settingsContent.y += obj.event.movementY * 2;
+ settingsContent.y = Math.max(Math.min(0, settingsContent.y), -(currentY - 2732 + 200));
+ }
+ };
} else {
settingsPanel.visible = true;
- // Reset scale for animation if panel already exists
- settingsPanel.getChildAt(0).scale.x = 0;
- settingsPanel.getChildAt(0).scale.y = 0;
}
- // Animate the settings panel opening with bounce effect
- tween(settingsPanel.getChildAt(0), {
- scaleX: 1,
- scaleY: 1
- }, {
- duration: 600,
- easing: tween.elasticOut
- });
- // Color buttons function has been removed
}
// Function to create particles at click location
function createClickParticles(x, y) {
- // Create 15-20 particles for a visually impressive effect
- var particleCount = 15 + Math.floor(Math.random() * 6);
+ // Only create particles if enabled
+ if (!visualSettings.particlesEnabled) {
+ return;
+ }
+ // Create 15-20 particles for a visually impressive effect, adjusted by intensity
+ var baseCount = 15 + Math.floor(Math.random() * 6);
+ var particleCount = Math.floor(baseCount * visualSettings.particleIntensity);
for (var i = 0; i < particleCount; i++) {
var particle = new Particle();
particle.x = x;
particle.y = y;
@@ -1078,16 +1351,22 @@
}
}
// Function to create particles at collision location
function createCollisionParticles(x, y) {
- // Create 8-12 particles for collision effect - fewer than click particles
- var particleCount = 8 + Math.floor(Math.random() * 5);
+ // Only create particles if enabled
+ if (!visualSettings.particlesEnabled) {
+ return;
+ }
+ // Create 8-12 particles for collision effect - fewer than click particles, adjusted by intensity
+ var baseCount = 8 + Math.floor(Math.random() * 5);
+ var particleCount = Math.floor(baseCount * visualSettings.particleIntensity);
for (var i = 0; i < particleCount; i++) {
var particle = new Particle();
particle.x = x;
particle.y = y;
particle.active = true;
- particle.scale.set(0.3, 0.3); // Smaller particles for collisions
+ var collisionScale = 0.3 * visualSettings.particleSize * visualSettings.particleIntensity;
+ particle.scale.set(collisionScale, collisionScale); // Smaller particles for collisions
// Add to particles array and game display
particles.push(particle);
game.addChild(particle);
}
@@ -1098,11 +1377,11 @@
return;
}
var ball = new Ball();
ball.reset(speedMultiplier);
- ball.getChildAt(0).tint = gameColors.ball;
- // Visual indicator of speed - make ball slightly smaller as it gets faster
- var scale = Math.max(0.6, 1 - (speedMultiplier - 1) * 0.15);
+ ball.getChildAt(0).tint = visualSettings.ballColor;
+ // Visual indicator of speed - make ball slightly smaller as it gets faster, adjusted by ball size setting
+ var scale = Math.max(0.6, 1 - (speedMultiplier - 1) * 0.15) * visualSettings.ballSize;
ball.scale.set(scale, scale);
balls.push(ball);
game.addChild(ball);
ballsInPlay++;
@@ -1604,66 +1883,83 @@
}
// Ensure the current state is set to playing
currentState = GAME_STATE.PLAYING;
}
+// Apply visual settings on initialization
+applyVisualSettings();
// Game will start when player presses the Play button in the menu
// Function to animate the lava with multiple effects
function animateLava() {
+ if (!visualSettings.lavaAnimationEnabled) {
+ // Just apply the static lava color if animations are disabled
+ if (lava) {
+ lava.tint = visualSettings.lavaColor;
+ }
+ return;
+ }
// Pulsing scale animation
function pulseLava() {
+ if (!visualSettings.lavaAnimationEnabled) return;
tween(lava, {
scaleY: 1.05,
scaleX: 1.02
}, {
- duration: 800 + Math.random() * 400,
+ duration: (800 + Math.random() * 400) / visualSettings.animationSpeed,
easing: tween.easeInOut,
onFinish: function onFinish() {
+ if (!visualSettings.lavaAnimationEnabled) return;
tween(lava, {
scaleY: 0.98,
scaleX: 1.01
}, {
- duration: 600 + Math.random() * 400,
+ duration: (600 + Math.random() * 400) / visualSettings.animationSpeed,
easing: tween.easeInOut,
onFinish: pulseLava
});
}
});
}
- // Color shifting animation - between different shades of red/orange
+ // Color shifting animation - based on the selected lava color
function shiftLavaColor() {
- var colors = [0xC60C30, 0xFF4444, 0xE74C3C, 0xD32F2F, 0xFF5722];
+ if (!visualSettings.lavaAnimationEnabled) return;
+ // Create variations of the selected lava color
+ var baseLava = visualSettings.lavaColor;
+ var colors = [baseLava, baseLava + 0x111111, baseLava - 0x111111, baseLava + 0x220000, baseLava - 0x110011];
var randomColor = colors[Math.floor(Math.random() * colors.length)];
tween(lava, {
tint: randomColor
}, {
- duration: 1500 + Math.random() * 1000,
+ duration: (1500 + Math.random() * 1000) / visualSettings.animationSpeed,
easing: tween.easeInOut,
onFinish: shiftLavaColor
});
}
// Subtle vertical movement to simulate bubbling
function bubbleLava() {
+ if (!visualSettings.lavaAnimationEnabled) return;
var originalY = lava.y;
tween(lava, {
y: originalY - 5 - Math.random() * 8
}, {
- duration: 400 + Math.random() * 300,
+ duration: (400 + Math.random() * 300) / visualSettings.animationSpeed,
easing: tween.easeInOut,
onFinish: function onFinish() {
+ if (!visualSettings.lavaAnimationEnabled) return;
tween(lava, {
y: originalY + 3 + Math.random() * 4
}, {
- duration: 500 + Math.random() * 200,
+ duration: (500 + Math.random() * 200) / visualSettings.animationSpeed,
easing: tween.easeInOut,
onFinish: function onFinish() {
+ if (!visualSettings.lavaAnimationEnabled) return;
tween(lava, {
y: originalY
}, {
- duration: 300 + Math.random() * 200,
+ duration: (300 + Math.random() * 200) / visualSettings.animationSpeed,
easing: tween.easeOut,
onFinish: function onFinish() {
// Wait a bit before next bubble cycle
- LK.setTimeout(bubbleLava, 500 + Math.random() * 1500);
+ LK.setTimeout(bubbleLava, (500 + Math.random() * 1500) / visualSettings.animationSpeed);
}
});
}
});
@@ -1672,6 +1968,6 @@
}
// Start all animations
pulseLava();
shiftLavaColor();
- LK.setTimeout(bubbleLava, Math.random() * 1000); // Start bubbling with random delay
+ LK.setTimeout(bubbleLava, Math.random() * 1000 / visualSettings.animationSpeed); // Start bubbling with random delay
}
\ No newline at end of file