User prompt
"Boom!" is not showed when destroying the tiniest bubbles
Code edit (3 edits merged)
Please save this source code
User prompt
There is something wrong in the ball split logic when hitting the player: a split is created but the parent bubble from which the split was created is not destroyed.
User prompt
When the bubbles hit the player, they should not be destroyed, but split.
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'difficultyIndicator.style.fill = textColor;' Line Number: 470
User prompt
The trail collision with small bubbles (0.25) works, but the bubbles don't seem to be destroyed. Please destroy them on collisions with the train. Don't change anything else. I've got many of these: Bubble hit detection SUCCESS: size=0.25, x=411.20283351168956, y=2452.2476231932624, harpoon.x=503.71250000000003, harpoon.y=912, hitType=trail
User prompt
Nope. Trailstill does not pop the tiniest balls.
User prompt
I get lots of Small bubble hit by trail: size=0.25, x=677.4786181111297, harpoon.x=580.5500000000001. However, the bubble does not seem to get destroyed
User prompt
For some reason the last bubbles, the super small ones, don't get destroyed when intersecting with the trail.
User prompt
Make sure the harpoon trail / line attached to it also pops bubbles. Do only necessary changes.
User prompt
Please remove the showDifficultyAnnouncement
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'difficultyIndicator.style.fill = '#' + textColor.toString(16).padStart(6, '0');' Line Number: 439
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'difficultyIndicator.style.fill = '#' + textColor.toString(16).padStart(6, '0');' Line Number: 439
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'difficultyIndicator.style.fill = textColor.toString(16).padStart(6, '0');' Line Number: 439
User prompt
"Getting started" has just made my game stuck. There is something nasty there. Please fix.
User prompt
"Getting started" has just made my game stuck. There is something nasty there. Please fix.
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'difficultyIndicator.style.fill = textColor;' Line Number: 436
User prompt
Make that the balls pop also when the train/line intersects with them, not only the harpoon. Don't change anything else.
Code edit (1 edits merged)
Please save this source code
User prompt
It's still too difficult: create bubbles much less frequently
User prompt
Bubbles are created too frequently. Reduce it at start and only increase how frequently bubbles are created depending maybe on the "balloons popped" score? The higher the more frequently. But keep it easy at start.
User prompt
Then the player blinks because of being hit, it should blink three times and be tinted to red during that time.
User prompt
Start with much less bubbles, like half.
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'for (var k = 0; k < boxes.length; k++) {' Line Number: 526
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'for (var k = 0; k < boxes.length; k++) {' Line Number: 526
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Box class var Box = Container.expand(function () { var self = Container.call(this); var boxGraphics = self.attachAsset('box', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, // Increase the scale to enlarge the bounding box scaleY: 1.2 }); self.speed = 5; self.update = function () { self.y += self.speed; if (self.y > 2732) { self.destroy(); } }; }); // Box1 class var Box1 = Container.expand(function () { var self = Container.call(this); var boxGraphics = self.attachAsset('box1', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, // Increase the scale to enlarge the bounding box scaleY: 1.2 }); self.speed = 5; self.update = function () { self.y += self.speed; if (self.y > 2732) { self.destroy(); } }; }); // Box2 class var Box2 = Container.expand(function () { var self = Container.call(this); var boxGraphics = self.attachAsset('box2', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, // Increase the scale to enlarge the bounding box scaleY: 1.2 }); self.speed = 7; self.update = function () { self.y += self.speed; if (self.y > 2732) { self.destroy(); } }; }); // Box3 class var Box3 = Container.expand(function () { var self = Container.call(this); var boxGraphics = self.attachAsset('box3', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, // Increase the scale to enlarge the bounding box scaleY: 1.2 }); self.speed = 9; self.update = function () { self.y += self.speed; if (self.y > 2732) { self.destroy(); } }; }); // The assets will be automatically created and loaded by the LK engine. // Bubble class var Bubble = Container.expand(function () { var self = Container.call(this); var bubbleGraphics = self.attachAsset('bubble', { anchorX: 0.5, anchorY: 0.5, alpha: 1 // Start fully visible instead of transparent }); // Allow for different bubble sizes (original size = 1.0) self.size = 1.0; // Update bubble size based on the size property bubbleGraphics.scale.set(self.size); // Physics constants for more consistent behavior self.gravity = 0.2; // Gravity constant self.bounceFactor = 0.7; // Energy loss on bounce (30% loss) self.friction = 0.98; // Air/ground friction self.speed = 3; // Vertical speed (significantly reduced initial speed) // Track last position for collision detection self.lastY = 0; self.lastIntersecting = false; // Method to split the bubble into two smaller ones self.split = function () { // Only split if bubble is not too small if (self.size <= 0.3) { return false; } // Create two new smaller bubbles var halfSize = self.size * 0.5; // Create left bubble var leftBubble = new Bubble(); leftBubble.x = self.x; leftBubble.y = self.y; leftBubble.size = halfSize; leftBubble.speedX = -Math.abs(self.speedX) * 1.2; // Move left, slightly faster leftBubble.speed = -5 - Math.random() * 3; // Jump up leftBubble.lastY = leftBubble.y; leftBubble.lastIntersecting = false; if (leftBubble.children && leftBubble.children.length > 0) { leftBubble.children[0].scale.set(halfSize); } // Create right bubble var rightBubble = new Bubble(); rightBubble.x = self.x; rightBubble.y = self.y; rightBubble.size = halfSize; rightBubble.speedX = Math.abs(self.speedX) * 1.2; // Move right, slightly faster rightBubble.speed = -5 - Math.random() * 3; // Jump up rightBubble.lastY = rightBubble.y; rightBubble.lastIntersecting = false; if (rightBubble.children && rightBubble.children.length > 0) { rightBubble.children[0].scale.set(halfSize); } // Add both bubbles to the game game.addChild(leftBubble); game.addChild(rightBubble); return true; }; self.update = function () { // Track last position before moving self.lastY = self.y; self.lastIntersecting = self.intersects(player); self.speed += 0.2; // Further reduced gravity acceleration from 0.3 to 0.2 self.y += self.speed; self.x += self.speedX; // Update horizontal position based on speedX // Bounce off the left and right margins with a small boost to ensure movement if (self.x <= 100 && self.speedX < 0 || self.x >= 1948 && self.speedX > 0) { self.speedX *= -1.1; // Reverse horizontal direction with a slight boost to ensure movement } // Bounce off the ground (bottom of the screen) if (self.y >= 2732 - 100) { // Account for bubble size/radius self.y = 2732 - 100; // Reset position to prevent sinking below ground self.speed = -self.speed * 0.7; // Reverse vertical direction with dampening (70% of original speed) // Add a small random horizontal impulse on bounce for more natural movement self.speedX += (Math.random() - 0.5) * 2; } // Removed tint application when reaching a certain Y position // Only destroy bubble when hit by player if (!self.lastIntersecting && self.intersects(player)) { // Make the player blink three times with red tint when hit by a bubble if (player.children && player.children.length > 0) { var playerGraphics = player.children[0]; // Save original tint var originalTint = playerGraphics.tint || 0xFFFFFF; // Tint to red playerGraphics.tint = 0xFF0000; // First blink (1/3) tween(playerGraphics, { alpha: 0 }, { duration: 100, onFinish: function onFinish() { tween(playerGraphics, { alpha: 1 }, { duration: 100, onFinish: function onFinish() { // Second blink (2/3) tween(playerGraphics, { alpha: 0 }, { duration: 100, onFinish: function onFinish() { tween(playerGraphics, { alpha: 1 }, { duration: 100, onFinish: function onFinish() { // Third blink (3/3) tween(playerGraphics, { alpha: 0 }, { duration: 100, onFinish: function onFinish() { tween(playerGraphics, { alpha: 1 }, { duration: 100, onFinish: function onFinish() { // Reset tint to original color playerGraphics.tint = originalTint; } }); } }); } }); } }); } }); } }); } self.destroy(); lives -= 1; // Remove a heart icon when a life is lost if (hearts.length > lives) { var heartToRemove = hearts.pop(); if (heartToRemove) { tween(heartToRemove.scale, { x: 0, y: 0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { heartToRemove.destroy(); } }); } } if (lives < 0) { LK.showGameOver(); } } }; }); // Explosion class var Explosion = Container.expand(function () { var self = Container.call(this); var explosionGraphics = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5 }); tween(explosionGraphics, { scaleX: explosionGraphics.scaleX + 1, scaleY: explosionGraphics.scaleY + 1 }, { duration: 1000, easing: tween.bounceOut, onFinish: function onFinish() { self.destroy(); } }); self.update = function () { // The explosion will disappear after a while if (self.alpha > 0) { self.alpha -= 0.02; } else { self.destroy(); } }; }); // Harpoon class var Harpoon = Container.expand(function () { var self = Container.call(this); var harpoonGraphics = self.attachAsset('harpoon', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -20; self.trail = game.addChild(new Trail()); // Function to check if point is on line (trail) self.isPointOnLine = function (point, bubbleSize) { // The trail is a vertical line from the harpoon down to the player // Check if point is close enough to the line segment // Get bubble size factor (if not provided, default to 1) var sizeFactor = bubbleSize || 1.0; // Adjust tolerance based on bubble size - smaller bubbles need more generous tolerance // For very small bubbles (size <= 0.3), use larger tolerance var baseWidth = 50; // Base tolerance for normal bubbles var tolerance = baseWidth; if (sizeFactor <= 0.3) { tolerance = 100; // Larger tolerance for tiny bubbles } else if (sizeFactor < 1.0) { // Scale tolerance inversely with bubble size tolerance = baseWidth * (2 - sizeFactor); } // Vertical line check (point.x near self.x and point.y between self.y and trail bottom) return Math.abs(point.x - self.x) < tolerance && point.y >= self.y && point.y <= 2732; }; self.update = function () { self.y += self.speed; self.trail.height = 2732 - self.y; self.trail.y = self.y + self.trail.height / 2; if (self.y < 0 || self.y < 2732 * (1 / 3)) { self.destroy(); self.trail.destroy(); } }; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.update = function () { if (self.direction && self.direction === 'left') { self.x -= self.speed; } else if (self.direction === 'right') { self.x += self.speed; } }; self.shoot = function () { var harpoon = new Harpoon(); harpoon.x = player.x; harpoon.y = player.y - 200; harpoon.trail.x = player.x; harpoon.trail.y = player.y - 200; game.addChild(harpoon); LK.getSound('crossbow').play(); }; }); // PowerUpText class var PowerUpText = Container.expand(function () { var self = Container.call(this); var textGraphics = self.attachAsset('PowerUpText', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.y -= 2; if (self.y < 0) { self.destroy(); } }; }); // Trail class var Trail = Container.expand(function () { var self = Container.call(this); var trailGraphics = self.attachAsset('line', { anchorX: 0.5, anchorY: 0.5, width: 18 }); self.update = function () { self.y += 10; if (self.y > 2732) { self.destroy(); } }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xFFFFFFFF // Init game with black background }); /**** * Game Code ****/ var background = game.attachAsset('Landscape', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.setChildIndex(background, 0); var player = new Player(); player.x = 2048 / 2; player.y = 2732 - 180; game.addChild(player); // Add player after trail to ensure correct rendering order game.move = function (x, y, obj) { player.x = x; if (x < 2048 / 2 && player.scaleX > 0 || x >= 2048 / 2 && player.scaleX < 0) { player.scaleX *= -1; // Mirror the player image } }; var score = 0; var lives = 3; var lastDifficultyLevel = 0; // Track the last level for showing difficulty announcements // Create score background var scoreBackground = new Container(); var scoreBgGraphics = scoreBackground.attachAsset('scoreBg', { anchorX: 0.5, anchorY: 0.1, scaleX: 5, scaleY: 5, alpha: 1 }); // Create difficulty indicator var difficultyIndicator = new Text2('Difficulty: Easy', { size: 24, fill: 0x00FF00, font: "'Comic Sans MS', cursive, sans-serif" }); difficultyIndicator.anchor.set(0, 0.5); difficultyIndicator.x = 20; difficultyIndicator.y = 50; LK.gui.topLeft.addChild(difficultyIndicator); // Function to update difficulty indicator based on score function updateDifficultyIndicator() { var level = Math.floor(score / 10); var difficultyText = 'Difficulty: '; var textColor = 0x00FF00; if (level === 0) { difficultyText += 'Very Easy'; textColor = 0x00FF00; } else if (level === 1) { difficultyText += 'Easy'; textColor = 0x66FF00; } else if (level === 2) { difficultyText += 'Medium'; textColor = 0xFFFF00; } else if (level === 3) { difficultyText += 'Challenging'; textColor = 0xFF9900; } else if (level === 4) { difficultyText += 'Hard'; textColor = 0xFF6600; } else { difficultyText += 'Expert'; textColor = 0xFF0000; } difficultyIndicator.setText(difficultyText); difficultyIndicator.style.fill = textColor; } scoreBackground.addChild(scoreBgGraphics); scoreBackground.x = 0; scoreBackground.y = 0; LK.gui.top.addChild(scoreBackground); // Create score text var scoreTxt = new Text2('Balloons popped: 0', { size: 30, fill: 0xFF3659, font: "'Comic Sans MS', cursive, sans-serif" }); scoreTxt.anchor.set(0.5, -0.1); scoreBackground.addChild(scoreTxt); // Function to show difficulty level change announcement function showDifficultyAnnouncement(level) { var difficultyText = ''; var textColor = 0xFFFFFF; switch (level) { case 1: difficultyText = "Warming Up!"; textColor = 0x00FF00; break; case 2: difficultyText = "Getting Started!"; textColor = 0xFFFF00; break; case 3: difficultyText = "Picking Up Pace!"; textColor = 0xFF9900; break; case 4: difficultyText = "More Bubbles!"; textColor = 0xFF6600; break; case 5: difficultyText = "Getting Challenging!"; textColor = 0xFF3300; break; default: if (level > 5) { difficultyText = "Level " + (level - 5) + "!"; textColor = 0xFF0000; } } if (difficultyText) { // Create text for announcement var announcement = new Text2(difficultyText, { size: 100, fill: textColor, font: "'Comic Sans MS', cursive, sans-serif" }); announcement.anchor.set(0.5, 0.5); announcement.x = 2048 / 2; announcement.y = 2732 / 2; announcement.alpha = 0; game.addChild(announcement); // Fade in tween(announcement, { alpha: 1 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Hold for a moment LK.setTimeout(function () { // Fade out tween(announcement, { alpha: 0 }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { announcement.destroy(); } }); }, 1500); } }); // Play a sound for level up LK.getSound('powerup').play(); } } var hearts = []; for (var i = 0; i < lives; i++) { var heart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, x: -1 * (i + 1) * 50, // Position hearts with some spacing y: 50 }); LK.gui.topRight.addChild(heart); hearts.push(heart); } var lastShot = -999; game.down = function (x, y, obj) { if (LK.ticks - lastShot > 30) { player.shoot(); lastShot = LK.ticks; } }; // Start the music 'chinese' upon starting the game LK.playMusic('arcade'); game.update = function () { // Create boxes array before using it var boxes = game.children.filter(function (child) { return child instanceof Box || child instanceof Box1 || child instanceof Box2 || child instanceof Box3; }); // Dynamic bubble spawn rate based on score // Base spawn interval is much slower at start (300 ticks) and only gradually decreases based on score // This makes the start of the game much easier var baseInterval = 300; // Start with very slow spawn rate (5 seconds between bubbles) var minInterval = 60; // Minimum spawn interval is now higher (1 second) var reductionPerPoint = 2; // Slower progression - only reduce by 2 ticks per point var intervalReductionThreshold = 10; // Only start making game harder after scoring 10 points // Calculate spawn interval with much gentler progression var scoreBasedReduction = Math.max(0, score - intervalReductionThreshold) * reductionPerPoint; var spawnInterval = Math.max(minInterval, baseInterval - scoreBasedReduction); // Only spawn a bubble if current tick matches spawn interval if (LK.ticks % spawnInterval === 0) { var newBubble = new Bubble(); newBubble.x = Math.random() * 2048; newBubble.y = 0; // Reduced horizontal speed for more predictable trajectories var minSpeed = 3; // Reduced from 5 var maxSpeed = 6; // Reduced from 8 var randomSpeed = minSpeed + Math.random() * (maxSpeed - minSpeed); newBubble.speedX = Math.random() < 0.5 ? -randomSpeed : randomSpeed; // Give bubbles a smaller initial vertical speed for gentler physics newBubble.speed = 1 + Math.random() * 2; // Reduced from 2 + random * 2 // Set bounce count to track how many times the bubble has bounced newBubble.bounceCount = 0; newBubble.maxBounces = 3 + Math.floor(Math.random() * 3); // Initialize tracking properties for the bubble newBubble.lastY = newBubble.y; newBubble.lastIntersecting = false; game.addChild(newBubble); // Log difficulty progression for debugging if (score > 0 && score % 10 === 0 && LK.ticks % spawnInterval === 0) { console.log("Score: " + score + ", New spawn interval: " + spawnInterval + " ms (" + (spawnInterval / 60).toFixed(1) + " seconds between bubbles)"); } } // Make sure to initialize all arrays at the beginning var bubbles = game.children.filter(function (child) { return child instanceof Bubble; }); // boxes array is now initialized at the beginning of update function // to prevent 'Cannot read properties of undefined' error var harpoons = game.children.filter(function (child) { return child instanceof Harpoon; }); for (var i = 0; i < bubbles.length; i++) { var bubble = bubbles[i]; // Collision handling is now done in the Bubble class update method for (var j = 0; j < harpoons.length; j++) { var harpoon = harpoons[j]; // Check if bubble collides with harpoon OR with harpoon's trail var hitsHarpoon = bubble.intersects(harpoon); var hitsTrail = harpoon.isPointOnLine({ x: bubble.x, y: bubble.y }, bubble.size); if (hitsHarpoon || hitsTrail) { // Log small bubble collisions for debugging if (bubble.size <= 0.3 && hitsTrail) { console.log("Small bubble hit by trail: size=" + bubble.size + ", x=" + bubble.x + ", harpoon.x=" + harpoon.x); } // Store current position and data for explosion var bubbleX = bubble.x; var bubbleY = bubble.y; var bubbleSize = bubble.size || 1.0; var bubbleSpeedX = bubble.speedX; // Try to split the bubble var wasSplit = false; if (bubbleSize > 0.3) { // Call split method to create two smaller bubbles wasSplit = bubble.split(); var boxes = game.children.filter(function (child) { return child instanceof Box || child instanceof Box1 || child instanceof Box2 || child instanceof Box3; }); // Remove the original bubble bubble.destroy(); // Play explosion sound LK.getSound('explosion').play(); // Remove the harpoon harpoon.trail.destroy(); // Destroy the harpoon trail harpoon.destroy(); bubbles.splice(i, 1); // Remove bubble from the array // Update score and UI score += 1; scoreTxt.setText("Balloons popped: " + score.toString()); // Check if we've reached a new difficulty level (every 10 points) var currentDifficultyLevel = Math.floor(score / 10); if (currentDifficultyLevel > lastDifficultyLevel) { lastDifficultyLevel = currentDifficultyLevel; // Show difficulty level announcement showDifficultyAnnouncement(currentDifficultyLevel); // Update the difficulty indicator updateDifficultyIndicator(); } tween(scoreTxt.scale, { x: 2, y: 2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(scoreTxt.scale, { x: 1, y: 1 }, { duration: 500, easing: tween.easeInOut }); } }); harpoons.splice(j, 1); // Remove harpoon from the array // Create an explosion at the intersection point var explosion = new Explosion(); explosion.x = bubbleX; explosion.y = bubbleY; game.addChild(explosion); // Create a box at the intersection point with a 10% probability, but only if bubble wasn't split // and if there are no other boxes in the game if (!wasSplit && !game.children.some(function (child) { return child instanceof Box || child instanceof Box1 || child instanceof Box2 || child instanceof Box3; })) { if (Math.random() < 1) { var boxType = Math.floor(Math.random() * 4); var box; switch (boxType) { case 0: box = new Box(); break; case 1: box = new Box1(); break; case 2: box = new Box2(); break; case 3: box = new Box3(); break; } box.x = bubbleX; box.y = bubbleY; game.addChild(box); } } break; // Break out of the loop since we're deleting the bubble } } } for (var k = 0; k < boxes.length; k++) { var box = boxes[k]; for (var l = 0; l < harpoons.length; l++) { var harpoon = harpoons[l]; // Check if box collides with harpoon OR with harpoon's trail var hitsHarpoon = box.intersects(harpoon); var hitsTrail = harpoon.isPointOnLine({ x: box.x, y: box.y }, 1.0); if (hitsHarpoon || hitsTrail) { box.destroy(); LK.getSound('powerup').play(); harpoon.trail.destroy(); harpoon.destroy(); // Display toast text based on the type of box destroyed var toastText = new Text2('', { size: 250, fill: 0xFFC0CB, font: "'Comic Sans MS', cursive, sans-serif" }); var toastTextBg = new Text2('', { size: 255, fill: 0xFF00AA, font: "'Comic Sans MS', cursive, sans-serif" }); toastText.anchor.set(0.5, 0.5); toastText.x = 2048 / 2; toastText.y = 2732 / 2; toastTextBg.anchor.set(0.5, 0.5); toastTextBg.x = 2048 / 2; toastTextBg.y = 2732 / 2; game.addChild(toastText); game.addChild(toastTextBg); if (box instanceof Box1) { toastText.setText("Smash!"); toastTextBg.setText("Smash!"); } else if (box instanceof Box2) { toastText.setText("Destruction!"); toastTextBg.setText("Destruction!"); } else if (box instanceof Box) { toastText.setText("Less madness!"); toastTextBg.setText("Less madness!"); } else if (box instanceof Box3) { toastText.setText("Life up!"); toastTextBg.setText("Life up!"); } // Tween the toast text to fade out and destroy after 2 seconds tween(toastText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { toastText.destroy(); } }); tween(toastTextBg, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { toastTextBg.destroy(); } }); boxes.splice(k, 1); harpoons.splice(l, 1); // Check if the destroyed box is an instance of Box1 if (box instanceof Box1) { // Create six additional harpoons and trails for (var i = 1; i <= 3; i++) { var leftHarpoon = new Harpoon(); leftHarpoon.x = player.x - i * 150; leftHarpoon.y = player.y; leftHarpoon.trail.x = player.x - i * 150; leftHarpoon.trail.y = player.y; game.addChild(leftHarpoon); var rightHarpoon = new Harpoon(); rightHarpoon.x = player.x + i * 150; rightHarpoon.y = player.y; rightHarpoon.trail.x = player.x + i * 150; rightHarpoon.trail.y = player.y; game.addChild(rightHarpoon); // Set a timeout to remove the additional harpoons after 5 seconds LK.setTimeout(function (lh, rh) { lh.destroy(); lh.trail.destroy(); rh.destroy(); rh.trail.destroy(); }.bind(null, leftHarpoon, rightHarpoon), 5000); } } // Check if the destroyed box is an instance of Box and reduce bubble speed if (box instanceof Box) { var bubbles = game.children.filter(function (child) { return child instanceof Bubble; }); bubbles.forEach(function (bubble) { bubble.speed /= 2; }); LK.setTimeout(function () { bubbles.forEach(function (bubble) { bubble.speed *= 2; }); }, 5000); } // Check if the destroyed box is an instance of Box3 and lives are less than 3 if (box instanceof Box3 && lives < 3) { lives += 1; var heart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5, x: -1 * lives * 50, y: 50 }); LK.gui.topRight.addChild(heart); hearts.push(heart); } // Check if the destroyed box is an instance of Box2 if (box instanceof Box2) { var bubbles = game.children.filter(function (child) { return child instanceof Bubble; }); var bubblesDestroyed = bubbles.length; bubbles.forEach(function (bubble) { bubble.destroy(); }); score += bubblesDestroyed; scoreTxt.setText("Balloons popped: " + score.toString()); tween(scoreTxt.scale, { x: 2, y: 2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(scoreTxt.scale, { x: 1, y: 1 }, { duration: 500, easing: tween.easeInOut }); } }); } break; } } } } };
===================================================================
--- original.js
+++ change.js
@@ -272,12 +272,23 @@
});
self.speed = -20;
self.trail = game.addChild(new Trail());
// Function to check if point is on line (trail)
- self.isPointOnLine = function (point) {
+ self.isPointOnLine = function (point, bubbleSize) {
// The trail is a vertical line from the harpoon down to the player
- // Check if point is close enough to the line segment (tolerance to account for bubble size)
- var tolerance = 50; // Adjust based on bubble and trail visual width
+ // Check if point is close enough to the line segment
+ // Get bubble size factor (if not provided, default to 1)
+ var sizeFactor = bubbleSize || 1.0;
+ // Adjust tolerance based on bubble size - smaller bubbles need more generous tolerance
+ // For very small bubbles (size <= 0.3), use larger tolerance
+ var baseWidth = 50; // Base tolerance for normal bubbles
+ var tolerance = baseWidth;
+ if (sizeFactor <= 0.3) {
+ tolerance = 100; // Larger tolerance for tiny bubbles
+ } else if (sizeFactor < 1.0) {
+ // Scale tolerance inversely with bubble size
+ tolerance = baseWidth * (2 - sizeFactor);
+ }
// Vertical line check (point.x near self.x and point.y between self.y and trail bottom)
return Math.abs(point.x - self.x) < tolerance && point.y >= self.y && point.y <= 2732;
};
self.update = function () {
@@ -580,10 +591,14 @@
var hitsHarpoon = bubble.intersects(harpoon);
var hitsTrail = harpoon.isPointOnLine({
x: bubble.x,
y: bubble.y
- });
+ }, bubble.size);
if (hitsHarpoon || hitsTrail) {
+ // Log small bubble collisions for debugging
+ if (bubble.size <= 0.3 && hitsTrail) {
+ console.log("Small bubble hit by trail: size=" + bubble.size + ", x=" + bubble.x + ", harpoon.x=" + harpoon.x);
+ }
// Store current position and data for explosion
var bubbleX = bubble.x;
var bubbleY = bubble.y;
var bubbleSize = bubble.size || 1.0;
@@ -677,9 +692,9 @@
var hitsHarpoon = box.intersects(harpoon);
var hitsTrail = harpoon.isPointOnLine({
x: box.x,
y: box.y
- });
+ }, 1.0);
if (hitsHarpoon || hitsTrail) {
box.destroy();
LK.getSound('powerup').play();
harpoon.trail.destroy();
a green cross, icon, pixel style. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
a sand clock pixel style.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
a bomb, pixel style. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
a pixel harpoon, vertical and looking up, retro like in pang games.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A banner to show a message, pixel art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
two harpoons looking up, retro, pixel. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A Mount fuji background with a big rainbow crossing from side to side in the sky, pixel style, colourful. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows