User prompt
Make meidum balls bounce back when hitting the ground
User prompt
add background to the game
User prompt
Drop the red ball first, yellow ball second, and orange ball third from the top
User prompt
drop the red ball first and, yellow ball second and ,orange ball third from upside
User prompt
release the red ball first , and the yellow ball second and the orange ball third
User prompt
make the large ball change of color every time the new ball releases
User prompt
Make only large balls bounce back when hitting the ground not medium ball or small ball
User prompt
make the large ball bounce back
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'multiplierTxt.style.fill = "#ffcc00"; // Default yellow' Line Number: 304
Code edit (1 edits merged)
Please save this source code
User prompt
Cannon Bounce Blast
Initial prompt
Title: Cannon Bounce Blast Game Description: Control a powerful cannon that automatically shoots bullets to destroy bouncing balls. The balls fall from the top, bounce off the ground, and split into smaller pieces when hit. If a ball touches your cannon, the game is over! Core Mechanics: Cannon Movement: The player moves the cannon left and right using arrow keys or touch controls. Automatic Shooting: The cannon fires bullets continuously to destroy or split balls. Ball Physics: Balls fall from the top and bounce off the ground instead of disappearing. When hit, large balls split into smaller ones until they disappear. Game Over Condition: If a ball touches the cannon, the game ends. Scoring System: Earn points by destroying balls. Bonus points for clearing multiple balls quickly. Additional Features: Power-ups (Rapid Fire, Bigger Bullets, Shield). Upgrades (Faster shooting, Stronger bullets). Different Ball Types (Harder balls, Explosive balls). Smooth Animations and Juicy Effects. Controls: Arrow Keys / Touch Swipe: Move the cannon left & right. Automatic Shooting: No need to press a button! Winning & Losing Conditions: ✅ Win by clearing as many balls as possible for a high score. ❌ Lose if a ball touches the cannon.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Ball = Container.expand(function (size, speedX, speedY) { var self = Container.call(this); self.size = size || 'large'; self.speedX = speedX || Math.random() * 10 - 5; self.speedY = speedY || Math.random() * 5 + 2; var assetName = self.size + 'Ball'; var ballGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.radius = ballGraphics.width / 2; self.update = function () { // Move the ball self.x += self.speedX; self.y += self.speedY; // Bounce off walls if (self.x < self.radius || self.x > 2048 - self.radius) { self.speedX *= -1; // Adjust position to prevent sticking to walls if (self.x < self.radius) { self.x = self.radius; } if (self.x > 2048 - self.radius) { self.x = 2048 - self.radius; } } // Bounce off top if (self.y < self.radius) { self.speedY *= -1; self.y = self.radius; } // Ball falls off bottom of screen if (self.y > 2732 + self.radius) { self.markForRemoval = true; } // Apply gravity self.speedY += 0.2; }; self.split = function () { // Create two smaller balls when hit var nextSize; if (self.size === 'large') { nextSize = 'medium'; score += 100; } else if (self.size === 'medium') { nextSize = 'small'; score += 200; } else { // Small balls just disappear score += 300; return []; } var newBalls = []; // Create two smaller balls with slightly altered velocities for (var i = 0; i < 2; i++) { var speedMultiplier = i === 0 ? 1 : -1; var newBall = new Ball(nextSize, self.speedX * 1.2 * speedMultiplier, self.speedY * 0.8); newBall.x = self.x; newBall.y = self.y; newBalls.push(newBall); } return newBalls; }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -15; self.update = function () { self.y += self.speed; // Remove bullet if it goes off-screen if (self.y < -50) { self.markForRemoval = true; } }; return self; }); var Cannon = Container.expand(function () { var self = Container.call(this); // Base of the cannon var base = self.attachAsset('cannonBase', { anchorX: 0.5, anchorY: 0.5, y: 20 }); // The cannon barrel var barrel = self.attachAsset('cannon', { anchorX: 0.5, anchorY: 1.0, y: 0 }); // Fire rate control self.lastFired = 0; self.fireRate = 500; // ms between shots // Cannon shoots automatically self.tryToFire = function () { var currentTime = Date.now(); if (currentTime - self.lastFired > self.fireRate) { self.fire(); self.lastFired = currentTime; } }; self.fire = function () { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y - barrel.height; game.addChild(bullet); bullets.push(bullet); LK.getSound('shoot').play(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x202060 }); /**** * Game Code ****/ // Game variables var balls = []; var bullets = []; var score = 0; var isGameOver = false; var lastBallSpawnTime = 0; var ballSpawnInterval = 3000; // ms between ball spawns var timeSinceLastHit = 0; var comboMultiplier = 1; var comboTimeout = 1000; // ms to maintain combo // Create cannon var cannon = new Cannon(); cannon.x = 2048 / 2; cannon.y = 2732 - 100; game.addChild(cannon); // Create score display var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -scoreTxt.width - 20; scoreTxt.y = 20; // Create multiplier display var multiplierTxt = new Text2('x1', { size: 60, fill: 0xFFCC00 }); multiplierTxt.anchor.set(0, 0); LK.gui.topRight.addChild(multiplierTxt); multiplierTxt.x = -multiplierTxt.width - 20; multiplierTxt.y = scoreTxt.height + 30; // Handle ball spawning function spawnBall() { var ball = new Ball('large'); ball.x = Math.random() * (2048 - 200) + 100; // Avoid spawning too close to edges ball.y = -100; game.addChild(ball); balls.push(ball); } // Cannon movement var isDragging = false; game.down = function (x, y, obj) { isDragging = true; moveCannonTo(x); }; game.move = function (x, y, obj) { if (isDragging) { moveCannonTo(x); } }; game.up = function (x, y, obj) { isDragging = false; }; function moveCannonTo(x) { // Constrain cannon position to screen boundaries var minX = 100; var maxX = 2048 - 100; cannon.x = Math.max(minX, Math.min(maxX, x)); } // Update game state game.update = function () { if (isGameOver) { return; } // Update combo multiplier timeSinceLastHit += 16.67; // Approximate ms per frame at 60fps if (timeSinceLastHit > comboTimeout && comboMultiplier > 1) { comboMultiplier = 1; updateMultiplierDisplay(); } // Spawn new balls periodically var currentTime = Date.now(); if (currentTime - lastBallSpawnTime > ballSpawnInterval) { spawnBall(); lastBallSpawnTime = currentTime; // Gradually decrease spawn interval to increase difficulty ballSpawnInterval = Math.max(1000, ballSpawnInterval - 50); } // Automatically fire cannon cannon.tryToFire(); // Update all bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; // Check for collisions with balls for (var j = balls.length - 1; j >= 0; j--) { var ball = balls[j]; // Simple distance-based collision detection var dx = bullet.x - ball.x; var dy = bullet.y - ball.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ball.radius) { // Hit detected LK.getSound('hit').play(); // Update combo system timeSinceLastHit = 0; comboMultiplier = Math.min(10, comboMultiplier + 1); updateMultiplierDisplay(); // Create new smaller balls var newBalls = ball.split(); for (var k = 0; k < newBalls.length; k++) { game.addChild(newBalls[k]); balls.push(newBalls[k]); } // Remove the current ball and bullet game.removeChild(ball); balls.splice(j, 1); game.removeChild(bullet); bullets.splice(i, 1); // Update score updateScore(); // Break out of inner loop since bullet is gone break; } } // Remove bullets marked for removal if (bullet.markForRemoval) { game.removeChild(bullet); bullets.splice(i, 1); } } // Update all balls for (var i = balls.length - 1; i >= 0; i--) { var ball = balls[i]; // Check collision with cannon var dx = ball.x - cannon.x; var dy = ball.y - cannon.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ball.radius + 75) { // Approximate cannon collision radius gameOver(); break; } // Remove balls marked for removal if (ball.markForRemoval) { game.removeChild(ball); balls.splice(i, 1); } } }; function updateScore() { // Apply the multiplier to score updates score += 50 * comboMultiplier; scoreTxt.setText('Score: ' + score); // Update the internal LK score for leaderboards LK.setScore(score); } function updateMultiplierDisplay() { multiplierTxt.setText('x' + comboMultiplier); // Change color based on multiplier level if (comboMultiplier > 5) { multiplierTxt.style.fill = "#ff3333"; // Red for high multiplier } else if (comboMultiplier > 2) { multiplierTxt.style.fill = "#ffaa00"; // Orange for medium multiplier } else { multiplierTxt.style.fill = "#ffcc00"; // Default yellow } } function gameOver() { if (isGameOver) { return; } isGameOver = true; LK.effects.flashScreen(0xff0000, 500); LK.showGameOver(); } // Start background music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.7, duration: 1000 } });
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,311 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var Ball = Container.expand(function (size, speedX, speedY) {
+ var self = Container.call(this);
+ self.size = size || 'large';
+ self.speedX = speedX || Math.random() * 10 - 5;
+ self.speedY = speedY || Math.random() * 5 + 2;
+ var assetName = self.size + 'Ball';
+ var ballGraphics = self.attachAsset(assetName, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = ballGraphics.width / 2;
+ self.update = function () {
+ // Move the ball
+ self.x += self.speedX;
+ self.y += self.speedY;
+ // Bounce off walls
+ if (self.x < self.radius || self.x > 2048 - self.radius) {
+ self.speedX *= -1;
+ // Adjust position to prevent sticking to walls
+ if (self.x < self.radius) {
+ self.x = self.radius;
+ }
+ if (self.x > 2048 - self.radius) {
+ self.x = 2048 - self.radius;
+ }
+ }
+ // Bounce off top
+ if (self.y < self.radius) {
+ self.speedY *= -1;
+ self.y = self.radius;
+ }
+ // Ball falls off bottom of screen
+ if (self.y > 2732 + self.radius) {
+ self.markForRemoval = true;
+ }
+ // Apply gravity
+ self.speedY += 0.2;
+ };
+ self.split = function () {
+ // Create two smaller balls when hit
+ var nextSize;
+ if (self.size === 'large') {
+ nextSize = 'medium';
+ score += 100;
+ } else if (self.size === 'medium') {
+ nextSize = 'small';
+ score += 200;
+ } else {
+ // Small balls just disappear
+ score += 300;
+ return [];
+ }
+ var newBalls = [];
+ // Create two smaller balls with slightly altered velocities
+ for (var i = 0; i < 2; i++) {
+ var speedMultiplier = i === 0 ? 1 : -1;
+ var newBall = new Ball(nextSize, self.speedX * 1.2 * speedMultiplier, self.speedY * 0.8);
+ newBall.x = self.x;
+ newBall.y = self.y;
+ newBalls.push(newBall);
+ }
+ return newBalls;
+ };
+ return self;
+});
+var Bullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletGraphics = self.attachAsset('bullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = -15;
+ self.update = function () {
+ self.y += self.speed;
+ // Remove bullet if it goes off-screen
+ if (self.y < -50) {
+ self.markForRemoval = true;
+ }
+ };
+ return self;
+});
+var Cannon = Container.expand(function () {
+ var self = Container.call(this);
+ // Base of the cannon
+ var base = self.attachAsset('cannonBase', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: 20
+ });
+ // The cannon barrel
+ var barrel = self.attachAsset('cannon', {
+ anchorX: 0.5,
+ anchorY: 1.0,
+ y: 0
+ });
+ // Fire rate control
+ self.lastFired = 0;
+ self.fireRate = 500; // ms between shots
+ // Cannon shoots automatically
+ self.tryToFire = function () {
+ var currentTime = Date.now();
+ if (currentTime - self.lastFired > self.fireRate) {
+ self.fire();
+ self.lastFired = currentTime;
+ }
+ };
+ self.fire = function () {
+ var bullet = new Bullet();
+ bullet.x = self.x;
+ bullet.y = self.y - barrel.height;
+ game.addChild(bullet);
+ bullets.push(bullet);
+ LK.getSound('shoot').play();
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x202060
+});
+
+/****
+* Game Code
+****/
+// Game variables
+var balls = [];
+var bullets = [];
+var score = 0;
+var isGameOver = false;
+var lastBallSpawnTime = 0;
+var ballSpawnInterval = 3000; // ms between ball spawns
+var timeSinceLastHit = 0;
+var comboMultiplier = 1;
+var comboTimeout = 1000; // ms to maintain combo
+// Create cannon
+var cannon = new Cannon();
+cannon.x = 2048 / 2;
+cannon.y = 2732 - 100;
+game.addChild(cannon);
+// Create score display
+var scoreTxt = new Text2('Score: 0', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0, 0);
+LK.gui.topRight.addChild(scoreTxt);
+scoreTxt.x = -scoreTxt.width - 20;
+scoreTxt.y = 20;
+// Create multiplier display
+var multiplierTxt = new Text2('x1', {
+ size: 60,
+ fill: 0xFFCC00
+});
+multiplierTxt.anchor.set(0, 0);
+LK.gui.topRight.addChild(multiplierTxt);
+multiplierTxt.x = -multiplierTxt.width - 20;
+multiplierTxt.y = scoreTxt.height + 30;
+// Handle ball spawning
+function spawnBall() {
+ var ball = new Ball('large');
+ ball.x = Math.random() * (2048 - 200) + 100; // Avoid spawning too close to edges
+ ball.y = -100;
+ game.addChild(ball);
+ balls.push(ball);
+}
+// Cannon movement
+var isDragging = false;
+game.down = function (x, y, obj) {
+ isDragging = true;
+ moveCannonTo(x);
+};
+game.move = function (x, y, obj) {
+ if (isDragging) {
+ moveCannonTo(x);
+ }
+};
+game.up = function (x, y, obj) {
+ isDragging = false;
+};
+function moveCannonTo(x) {
+ // Constrain cannon position to screen boundaries
+ var minX = 100;
+ var maxX = 2048 - 100;
+ cannon.x = Math.max(minX, Math.min(maxX, x));
+}
+// Update game state
+game.update = function () {
+ if (isGameOver) {
+ return;
+ }
+ // Update combo multiplier
+ timeSinceLastHit += 16.67; // Approximate ms per frame at 60fps
+ if (timeSinceLastHit > comboTimeout && comboMultiplier > 1) {
+ comboMultiplier = 1;
+ updateMultiplierDisplay();
+ }
+ // Spawn new balls periodically
+ var currentTime = Date.now();
+ if (currentTime - lastBallSpawnTime > ballSpawnInterval) {
+ spawnBall();
+ lastBallSpawnTime = currentTime;
+ // Gradually decrease spawn interval to increase difficulty
+ ballSpawnInterval = Math.max(1000, ballSpawnInterval - 50);
+ }
+ // Automatically fire cannon
+ cannon.tryToFire();
+ // Update all bullets
+ for (var i = bullets.length - 1; i >= 0; i--) {
+ var bullet = bullets[i];
+ // Check for collisions with balls
+ for (var j = balls.length - 1; j >= 0; j--) {
+ var ball = balls[j];
+ // Simple distance-based collision detection
+ var dx = bullet.x - ball.x;
+ var dy = bullet.y - ball.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < ball.radius) {
+ // Hit detected
+ LK.getSound('hit').play();
+ // Update combo system
+ timeSinceLastHit = 0;
+ comboMultiplier = Math.min(10, comboMultiplier + 1);
+ updateMultiplierDisplay();
+ // Create new smaller balls
+ var newBalls = ball.split();
+ for (var k = 0; k < newBalls.length; k++) {
+ game.addChild(newBalls[k]);
+ balls.push(newBalls[k]);
+ }
+ // Remove the current ball and bullet
+ game.removeChild(ball);
+ balls.splice(j, 1);
+ game.removeChild(bullet);
+ bullets.splice(i, 1);
+ // Update score
+ updateScore();
+ // Break out of inner loop since bullet is gone
+ break;
+ }
+ }
+ // Remove bullets marked for removal
+ if (bullet.markForRemoval) {
+ game.removeChild(bullet);
+ bullets.splice(i, 1);
+ }
+ }
+ // Update all balls
+ for (var i = balls.length - 1; i >= 0; i--) {
+ var ball = balls[i];
+ // Check collision with cannon
+ var dx = ball.x - cannon.x;
+ var dy = ball.y - cannon.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < ball.radius + 75) {
+ // Approximate cannon collision radius
+ gameOver();
+ break;
+ }
+ // Remove balls marked for removal
+ if (ball.markForRemoval) {
+ game.removeChild(ball);
+ balls.splice(i, 1);
+ }
+ }
+};
+function updateScore() {
+ // Apply the multiplier to score updates
+ score += 50 * comboMultiplier;
+ scoreTxt.setText('Score: ' + score);
+ // Update the internal LK score for leaderboards
+ LK.setScore(score);
+}
+function updateMultiplierDisplay() {
+ multiplierTxt.setText('x' + comboMultiplier);
+ // Change color based on multiplier level
+ if (comboMultiplier > 5) {
+ multiplierTxt.style.fill = "#ff3333"; // Red for high multiplier
+ } else if (comboMultiplier > 2) {
+ multiplierTxt.style.fill = "#ffaa00"; // Orange for medium multiplier
+ } else {
+ multiplierTxt.style.fill = "#ffcc00"; // Default yellow
+ }
+}
+function gameOver() {
+ if (isGameOver) {
+ return;
+ }
+ isGameOver = true;
+ LK.effects.flashScreen(0xff0000, 500);
+ LK.showGameOver();
+}
+// Start background music
+LK.playMusic('gameMusic', {
+ fade: {
+ start: 0,
+ end: 0.7,
+ duration: 1000
+ }
});
\ No newline at end of file