User prompt
It's a issue when ball comes down then it's not bouncing in air after clicks also
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'detail')' in or related to this line: 'if (obj.event.detail === 2) {' Line Number: 462
User prompt
On double tap ball will bounce on air
Code edit (1 edits merged)
Please save this source code
User prompt
Bouncy Ball Blitz
Initial prompt
Bouncy Ball - A ball that bounces continuously, and players must tap/click to change its direction to avoid obstacles.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); var ballSprite = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.radius = ballSprite.width / 2; self.velocity = { x: 7, y: -15 }; self.gravity = 0.5; self.bounce = 0.8; self.isAlive = true; self.isPoweredUp = false; self.update = function () { if (!self.isAlive) { return; } // Apply gravity self.velocity.y += self.gravity; // Move based on velocity self.x += self.velocity.x; self.y += self.velocity.y; // Bounce off walls if (self.x < self.radius) { self.x = self.radius; self.velocity.x = Math.abs(self.velocity.x); } else if (self.x > 2048 - self.radius) { self.x = 2048 - self.radius; self.velocity.x = -Math.abs(self.velocity.x); } // Bounce off ground if (self.y > 2732 - 100 - self.radius) { self.y = 2732 - 100 - self.radius; self.velocity.y = -Math.abs(self.velocity.y * self.bounce); LK.getSound('bounce').play(); } // Bounce off ceiling if (self.y < self.radius) { self.y = self.radius; self.velocity.y = Math.abs(self.velocity.y * self.bounce); LK.getSound('bounce').play(); } }; self.changeDirection = function () { if (!self.isAlive) { return; } // Reverse horizontal direction on tap self.velocity.x = -self.velocity.x; }; self.activatePowerUp = function (type) { self.isPoweredUp = true; // Different power-up effects if (type === "slow") { var originalVelocityX = self.velocity.x; var originalVelocityY = self.velocity.y; var originalGravity = self.gravity; // Slow down self.velocity.x *= 0.5; self.velocity.y *= 0.5; self.gravity *= 0.5; // Flash the ball to indicate power-up tween(ballSprite, { tint: 0x00FFFF }, { duration: 300, easing: tween.linear }); // Reset after 5 seconds LK.setTimeout(function () { self.velocity.x = originalVelocityX; self.velocity.y = originalVelocityY; self.gravity = originalGravity; self.isPoweredUp = false; tween(ballSprite, { tint: 0xFFFFFF }, { duration: 300, easing: tween.linear }); }, 5000); } else if (type === "small") { var originalRadius = self.radius; // Shrink the ball tween(ballSprite, { scale: 0.5 }, { duration: 300, easing: tween.easeOut }); self.radius *= 0.5; // Flash the ball to indicate power-up tween(ballSprite, { tint: 0xFF00FF }, { duration: 300, easing: tween.linear }); // Reset after 5 seconds LK.setTimeout(function () { tween(ballSprite, { scale: 1 }, { duration: 300, easing: tween.easeOut }); self.radius = originalRadius; self.isPoweredUp = false; tween(ballSprite, { tint: 0xFFFFFF }, { duration: 300, easing: tween.linear }); }, 5000); } }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleSprite = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.width = obstacleSprite.width; self.height = obstacleSprite.height; self.speed = 5; self.update = function () { self.x -= self.speed; // Remove if off screen if (self.x < -self.width) { self.shouldRemove = true; } }; self.setSpeed = function (newSpeed) { self.speed = newSpeed; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupSprite = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.radius = powerupSprite.width / 2; self.speed = 5; self.type = Math.random() < 0.5 ? "slow" : "small"; // Set color based on type if (self.type === "slow") { powerupSprite.tint = 0x00FFFF; // Cyan for slow time } else { powerupSprite.tint = 0xFF00FF; // Magenta for shrink } self.update = function () { self.x -= self.speed; // Spin effect powerupSprite.rotation += 0.05; // Remove if off screen if (self.x < -self.radius * 2) { self.shouldRemove = true; } }; self.setSpeed = function (newSpeed) { self.speed = newSpeed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game variables var obstacles = []; var powerups = []; var obstacleSpawnTimer = null; var powerupSpawnTimer = null; var gameSpeed = 5; var spawnRate = 2000; var score = 0; var difficultyTimer = null; var isGameActive = false; // Create background var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); // Create ground var ground = game.addChild(LK.getAsset('ground', { anchorX: 0, anchorY: 0, x: 0, y: 2732 - 100 })); // Create ball var ball = game.addChild(new Ball()); ball.x = 300; ball.y = 500; // Create score text var scoreTxt = new Text2('Score: 0', { size: 70, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.y = 50; // Create high score text var highScore = storage.highScore || 0; var highScoreTxt = new Text2('Best: ' + highScore, { size: 50, fill: 0xFFFFFF }); highScoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(highScoreTxt); highScoreTxt.y = 130; // Start message var tapToStartTxt = new Text2('Tap to Start', { size: 100, fill: 0xFFFFFF }); tapToStartTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(tapToStartTxt); // Game functions function startGame() { if (isGameActive) { return; } isGameActive = true; score = 0; gameSpeed = 5; scoreTxt.setText('Score: 0'); // Remove start message LK.gui.center.removeChild(tapToStartTxt); // Reset the ball ball.x = 300; ball.y = 500; ball.velocity = { x: 7, y: -15 }; ball.isAlive = true; // Clear existing obstacles and powerups for (var i = obstacles.length - 1; i >= 0; i--) { game.removeChild(obstacles[i]); } obstacles = []; for (var i = powerups.length - 1; i >= 0; i--) { game.removeChild(powerups[i]); } powerups = []; // Start obstacle spawning spawnRate = 2000; obstacleSpawnTimer = LK.setInterval(spawnObstacle, spawnRate); // Start power-up spawning (less frequent) powerupSpawnTimer = LK.setInterval(spawnPowerUp, 7000); // Increase difficulty over time difficultyTimer = LK.setInterval(increaseDifficulty, 10000); // Play background music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.4, duration: 1000 } }); } function gameOver() { isGameActive = false; ball.isAlive = false; // Play crash sound LK.getSound('crash').play(); // Flash screen red LK.effects.flashScreen(0xFF0000, 500); // Stop spawning LK.clearInterval(obstacleSpawnTimer); LK.clearInterval(powerupSpawnTimer); LK.clearInterval(difficultyTimer); // Update high score if needed if (score > highScore) { highScore = score; storage.highScore = highScore; highScoreTxt.setText('Best: ' + highScore); } // Show game over LK.showGameOver(); } function spawnObstacle() { if (!isGameActive) { return; } var obstacle = new Obstacle(); // Random height var height = 200 + Math.random() * 300; obstacle.getChildAt(0).height = height; obstacle.height = height; // Position at right side of screen obstacle.x = 2048 + obstacle.width / 2; // Random vertical position, but ensure gap for player var minY = 150; var maxY = 2732 - 100 - 150 - height; obstacle.y = minY + Math.random() * (maxY - minY); // Set speed obstacle.setSpeed(gameSpeed); // Add to game obstacles.push(obstacle); game.addChild(obstacle); } function spawnPowerUp() { if (!isGameActive) { return; } var powerup = new PowerUp(); // Position at right side of screen powerup.x = 2048 + powerup.radius; // Random vertical position powerup.y = 150 + Math.random() * (2732 - 350); // Set speed powerup.setSpeed(gameSpeed); // Add to game powerups.push(powerup); game.addChild(powerup); } function increaseDifficulty() { if (!isGameActive) { return; } // Increase game speed gameSpeed += 0.5; // Update existing obstacles and powerups for (var i = 0; i < obstacles.length; i++) { obstacles[i].setSpeed(gameSpeed); } for (var i = 0; i < powerups.length; i++) { powerups[i].setSpeed(gameSpeed); } // Decrease spawn rate (but not below 1000ms) spawnRate = Math.max(1000, spawnRate - 100); // Clear and reset obstacle spawn timer with new rate LK.clearInterval(obstacleSpawnTimer); obstacleSpawnTimer = LK.setInterval(spawnObstacle, spawnRate); } function checkCollisions() { if (!ball.isAlive) { return; } // Check obstacle collisions for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; // Simple rectangle collision detection var ballLeft = ball.x - ball.radius; var ballRight = ball.x + ball.radius; var ballTop = ball.y - ball.radius; var ballBottom = ball.y + ball.radius; var obstacleLeft = obstacle.x - obstacle.width / 2; var obstacleRight = obstacle.x + obstacle.width / 2; var obstacleTop = obstacle.y - obstacle.height / 2; var obstacleBottom = obstacle.y + obstacle.height / 2; if (ballRight > obstacleLeft && ballLeft < obstacleRight && ballBottom > obstacleTop && ballTop < obstacleBottom) { // If powered up with "small", do more precise collision detection if (ball.isPoweredUp && ball.radius < 25) { // More precise circle-rectangle collision var closestX = Math.max(obstacleLeft, Math.min(ball.x, obstacleRight)); var closestY = Math.max(obstacleTop, Math.min(ball.y, obstacleBottom)); var distanceX = ball.x - closestX; var distanceY = ball.y - closestY; var distanceSquared = distanceX * distanceX + distanceY * distanceY; if (distanceSquared < ball.radius * ball.radius) { gameOver(); return; } } else { gameOver(); return; } } } // Check powerup collisions for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; // Simple circle collision detection var dx = ball.x - powerup.x; var dy = ball.y - powerup.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ball.radius + powerup.radius) { // Collect powerup LK.getSound('collect').play(); // Apply powerup effect ball.activatePowerUp(powerup.type); // Remove powerup game.removeChild(powerup); powerups.splice(i, 1); // Add score score += 10; scoreTxt.setText('Score: ' + score); } } } function updateGame() { if (!isGameActive) { return; } // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { if (obstacles[i].shouldRemove) { game.removeChild(obstacles[i]); obstacles.splice(i, 1); // Increment score when passing an obstacle score += 1; scoreTxt.setText('Score: ' + score); continue; } } // Update powerups for (var i = powerups.length - 1; i >= 0; i--) { if (powerups[i].shouldRemove) { game.removeChild(powerups[i]); powerups.splice(i, 1); } } // Check for collisions checkCollisions(); } // Event handlers game.down = function (x, y, obj) { if (!isGameActive) { startGame(); } else { if (obj.event && obj.event.detail && obj.event.detail === 2) { // Check for double tap ball.velocity.y = -Math.abs(ball.velocity.y * ball.bounce); // Bounce in the air LK.getSound('bounce').play(); } else { ball.changeDirection(); } } }; // Main update function game.update = function () { updateGame(); };
===================================================================
--- original.js
+++ change.js
@@ -445,9 +445,9 @@
game.down = function (x, y, obj) {
if (!isGameActive) {
startGame();
} else {
- if (obj.event && obj.event.detail === 2) {
+ if (obj.event && obj.event.detail && obj.event.detail === 2) {
// Check for double tap
ball.velocity.y = -Math.abs(ball.velocity.y * ball.bounce); // Bounce in the air
LK.getSound('bounce').play();
} else {