User prompt
Some trail segments seem to not be destroyed, especially those created after a powerbox.
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'destroy')' in or related to this line: 'harpoon.trail.destroy();' Line Number: 1031
Code edit (2 edits merged)
Please save this source code
User prompt
The trail now is 1 and it's scaled (self.trail.height) going from the startY to self.y. Instead, please divide that height by 100 and generate 1 trail per each 100 pixels.
User prompt
The trails, redo them completely. THere should be 1 trail always attached to the harpoon, rendering from the harpoon y position to 100 pixels below. And then if 1 more trail segment per 100 pixels of distance between the harpoon and the player on y
User prompt
I don't see any trail at all.
User prompt
As the harpoon goes up, generate "trail" segments using the "trail" asset from the player to the harpoon as it goes up.
User prompt
Remove the trails / line completely
Code edit (1 edits merged)
Please save this source code
User prompt
Segment heights are small. They sholuld be higher. And segments hsould stack on top of each other, they are being now overlapped on the same place
Code edit (1 edits merged)
Please save this source code
User prompt
Only harpoons at the player position are being drawn. They are not drawn higher than that! There should be m ore segments higher one of top of another, up to the harpoon!
User prompt
Redo the harppon and the trails completely. Here is what I need: When fired, the harpoon shoots straight upward from the player’s position, extending all the way to the top of the screen in a perfect vertical line. The harpoon itself is instant— abd the trail / cable follows after, covering the space between the player and the harpoon, as the harpoon goes up. Creating an effect of "trail". The condition: the trail should consist of different segments of height 100 pixels. So if you have 100 pixels, it's 1 trail segment. If you have 200, 2 segments. If you have 250, 3 segments (last segment 50 pixels as it's the last).
User prompt
No trails are renderer at all.
User prompt
I don't see the trails? What happened? As the harpoon goes up, trails should be generated from the player to the harpoon
User prompt
You've got it wrong: the trail segments are drawn from the player to the harpoon!
User prompt
Harpoon should always be up, trails should always follow below, like this> ^^^ | | | |
User prompt
Reverse the rendering of the trail segments and the harpoon
User prompt
Something is not right: the harpoon should be going up first, and then the trail and trail segments should follow below, but can't never overpass it. A trail can-t have an upper position than a harpoon.
User prompt
Ok the issue now is that the trail should always be below the harpoon, now the trail segments are rendered above the harpoon. The logic is the following: as the harpoon goes up, it will be generating trail segments.
User prompt
Ok, the trail is 1 and it gets scaled vertically. The issue - the texture gets a lot of distorsion as we scale it on y. Please do the following - instead of scaling the trail, create trails one after another so that the texture is kept intact. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Make the bubbles spawn not at a 10% from the bottom, but a 25% from the bottom
User prompt
Create boxes at half the probability as are created now
/**** * 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.lastIntersecting = false; // Track last intersection state with player self.update = function () { self.y += self.speed; // Check for player intersection transitions var currentIntersecting = self.intersects(player); if (!self.lastIntersecting && currentIntersecting) { // Flash the box briefly to indicate collection is possible tween(boxGraphics, { tint: 0xFFFF00, scaleX: 1.3, scaleY: 1.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(boxGraphics, { tint: 0xFFFFFF, scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeIn }); } }); } self.lastIntersecting = currentIntersecting; 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.lastIntersecting = false; // Track last intersection state with player self.update = function () { self.y += self.speed; // Check for player intersection transitions var currentIntersecting = self.intersects(player); if (!self.lastIntersecting && currentIntersecting) { // Flash the box briefly to indicate collection is possible tween(boxGraphics, { tint: 0xFF00FF, scaleX: 1.3, scaleY: 1.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(boxGraphics, { tint: 0xFFFFFF, scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeIn }); } }); } self.lastIntersecting = currentIntersecting; 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.lastIntersecting = false; // Track last intersection state with player self.update = function () { self.y += self.speed; // Check for player intersection transitions var currentIntersecting = self.intersects(player); if (!self.lastIntersecting && currentIntersecting) { // Flash the box briefly to indicate collection is possible tween(boxGraphics, { tint: 0x00FFFF, scaleX: 1.3, scaleY: 1.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(boxGraphics, { tint: 0xFFFFFF, scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeIn }); } }); } self.lastIntersecting = currentIntersecting; 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.lastIntersecting = false; // Track last intersection state with player self.update = function () { self.y += self.speed; // Check for player intersection transitions var currentIntersecting = self.intersects(player); if (!self.lastIntersecting && currentIntersecting) { // Flash the box briefly to indicate collection is possible with heart color tween(boxGraphics, { tint: 0xFF0000, scaleX: 1.3, scaleY: 1.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(boxGraphics, { tint: 0xFFFFFF, scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeIn }); } }); } self.lastIntersecting = currentIntersecting; 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: 0 // Start transparent }); // Make the bubble opaque after 1 second tween(bubbleGraphics, { alpha: 1 }, { duration: 1000 }); self.speed = -10; // Negative speed to move upward self.lastY = undefined; // Track last position for intersection checks self.hasHitTop = false; // Flag to track if lantern has gone off screen at top self.update = function () { if (self.lastY === undefined) { self.lastY = self.y; } self.y += self.speed; if (self.y < 1200) { // Start tinting when approaching the top tween(self, { tint: 0xFF0000 }, { duration: 500, easing: tween.linear }); } // Check if the lantern is going off the top of the screen without being destroyed if (self.lastY >= 0 && self.y < 0 && !self.hasHitTop) { self.hasHitTop = true; // Mark as hit top to prevent multiple life deductions // Player didn't destroy the lantern in time lives -= 1; // Create explosion effect at the top where the lantern left var explosion = new Explosion(); explosion.x = self.x; explosion.y = 10; // Just at the edge of the screen game.addChild(explosion); // Play explosion sound LK.getSound('explosion').play(); // 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) { // Handle player death with dramatic effect handlePlayerDeath(); return; } self.destroy(); } // Handle going completely off screen // Note: Not removing the lantern when it intersects with player // as per the requirement that player collision shouldn't remove lives if (self.y < -200) { self.destroy(); } self.lastY = self.y; }; }); // Explosion class with color customization var Explosion = Container.expand(function () { var self = Container.call(this); var explosionGraphics = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5 }); // Extend self with tint property accessor/mutator to allow tinting the explosion Object.defineProperty(self, 'tint', { get: function get() { return explosionGraphics.tint; }, set: function set(value) { explosionGraphics.tint = value; } }); // Apply explosion animation 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.005; } 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 = -30; // Reduced speed for slower movement self.originalSpeed = -30; self.maxDistance = 2732 * 0.85; // Increased maximum distance - 85% of screen height self.startY = 0; // Will store the starting Y position // Create trail that will be displayed below the harpoon self.trail = new Trail(); // Game code will add the trail first, then the harpoon to maintain proper rendering order // Apply a quick acceleration tween to give a nice launch effect tween(self, { speed: self.speed * 1.5 // Accelerate to 1.5x the slower speed }, { duration: 200, easing: tween.easeOut }); self.update = function () { // Store initial position on first update if (self.startY === 0) { self.startY = self.y; } self.y += self.speed; // Calculate total trail height needed var totalHeight = self.startY - self.y; // Create new segments as necessary var segmentHeight = 100; // Fixed segment height var segmentsNeeded = Math.ceil(totalHeight / segmentHeight); var existingSegments = self.trail.segments.length; // Add new segments if needed if (segmentsNeeded > existingSegments) { for (var i = existingSegments; i < segmentsNeeded; i++) { var yOffset = i * segmentHeight; self.trail.createSegment(yOffset, segmentHeight); } } // Position trail to start from player and extend to the harpoon self.trail.x = self.x; // Match trail x with harpoon x self.trail.y = player.y - 200; // Start trail from player position self.trail.height = self.startY - self.y; // Set height to span from player to harpoon // Destroy when reaching max distance or going off-screen if (self.y < 0 || self.startY - self.y > self.maxDistance) { 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(); // Position harpoon harpoon.x = player.x; harpoon.y = player.y - 200; // Position trail to start at player harpoon.trail.x = player.x; harpoon.trail.y = player.y - 200; // Create first trail segment starting from player harpoon.trail.createSegment(0, 100); // Set proper starting y position to measure distance correctly harpoon.startY = harpoon.y; // Create a more dramatic scale effect for shooting with extended range harpoon.scale.x = 0.7; harpoon.scale.y = 1.3; // Flag normal harpoons (from player) to allow them to create boxes harpoon.isPlayerCreated = true; // Apply a tween to normalize the scale while launching, with longer stretch for better visual feedback tween(harpoon.scale, { x: 1, y: 1 }, { duration: 250, easing: tween.easeOut }); // Add the trail first so it renders below the harpoon game.addChild(harpoon.trail); // Then add the harpoon so it renders on top of the trail game.addChild(harpoon); LK.getSound('crossbow').play(); }; }); // PlayerDeathEffect class - creates a dramatic death sequence with rainbow colors var PlayerDeathEffect = Container.expand(function () { var self = Container.call(this); // Create the main container for all death effect elements var effectContainer = new Container(); self.addChild(effectContainer); // Rainbow colors array (red, orange, yellow, green, blue, indigo, violet) var rainbowColors = [ // Indigo 0x9400D3, // Violet 0xfaadad, // Red 0xFF7F00, // Orange 0xFFFF00, // Yellow 0x00FF00, // Green 0x0000FF, // Blue 0x4B0082]; // Add a full-screen overlay for dramatic effect var overlay = LK.getAsset('deadBg', { anchorX: 0, anchorY: 0, scaleX: 20.48, // Full width (2048px) scaleY: 27.32, // Full height (2732px) tint: rainbowColors[0], // Start with red alpha: 0 }); effectContainer.addChild(overlay); // Add dramatic text var gameOverText = new Text2('GAME OVER', { size: 150, fill: 0xFFFFFF, font: "'Comic Sans MS', cursive, sans-serif" }); gameOverText.anchor.set(0.5, 0.5); gameOverText.x = 2048 / 2; gameOverText.y = 2732 / 2; gameOverText.alpha = 0; gameOverText.scale.set(0.1); effectContainer.addChild(gameOverText); // Function to create a rainbow tint sequence function createRainbowTintSequence(target, startIndex, duration) { var colorIndex = startIndex % rainbowColors.length; var nextColorIndex = (colorIndex + 1) % rainbowColors.length; tween(target, { tint: rainbowColors[nextColorIndex] }, { duration: duration, easing: tween.linear, onFinish: function onFinish() { createRainbowTintSequence(target, nextColorIndex, duration); } }); } // Add rainbow flickering effect self.startEffect = function () { // Pulse the overlay with rainbow colors tween(overlay, { alpha: 0.5 }, { duration: 400, easing: tween.easeIn, onFinish: function onFinish() { // Start the rainbow color sequence createRainbowTintSequence(overlay, 0, 300); } }); // Show and scale the text tween(gameOverText, { alpha: 1, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, easing: tween.elasticOut }); // Create explosion effects at random positions with rainbow colors for (var i = 0; i < 5; i++) { LK.setTimeout(function (colorIndex) { var explosion = new Explosion(); explosion.x = Math.random() * 2048; explosion.y = Math.random() * 2732; // Give each explosion a different color from the rainbow explosion.tint = rainbowColors[colorIndex % rainbowColors.length]; effectContainer.addChild(explosion); // Play explosion sound LK.getSound('explosion').play(); }.bind(null, i), 300 * i); } // Show actual game over screen after the effect LK.setTimeout(function () { self.destroy(); LK.showGameOver(); }, 2500); // Show game over after 2.5 seconds }; return self; }); // 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); self.segments = []; self.createSegment = function (yOffset, height) { var segment = new Container(); var segmentGraphics = segment.attachAsset('line', { anchorX: 0.5, anchorY: 0, width: 18, alpha: 0.9, scaleY: height / 3490.91 // Scale proportionally to fit desired height }); segment.y = yOffset; self.addChild(segment); self.segments.push(segment); return segment; }; // The trail doesn't need its own update movement since it's positioned relative to the harpoon self.update = function () { // Trail no longer moves independently // Its position is now fully controlled by the Harpoon 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); // Add a warning zone at the top to indicate the danger area var warningZone = new Container(); var warningGraphics = LK.getAsset('scoreBg', { anchorX: 0, anchorY: 0, scaleX: 20.48, // Make it span the entire width (2048px) scaleY: 1.5, tint: 0xFF3333, // Red tint to indicate danger alpha: 0.3 // Semi-transparent }); warningZone.addChild(warningGraphics); warningZone.x = 0; warningZone.y = 0; game.addChild(warningZone); var player = new Player(); player.x = 2048 / 2; player.y = 2732 - 180; game.addChild(player); // Add player after trail to ensure correct rendering order // Add a description text for the warning zone var warningText = new Text2('Lanterns escaping at the top will cost a life!', { size: 30, fill: 0xFFFFFF, font: "'Comic Sans MS', cursive, sans-serif" }); warningText.anchor.set(0.5, 0); warningText.x = 2048 / 2; warningText.y = 130; game.addChild(warningText); // Make the warning text pulse to draw attention var _pulseWarning = function pulseWarning() { tween(warningText.scale, { x: 1.2, y: 1.2 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(warningText.scale, { x: 1.0, y: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: _pulseWarning }); } }); }; _pulseWarning(); 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 scoreBackground = new Container(); var scoreBgGraphics = scoreBackground.attachAsset('scoreBg', { anchorX: 0.5, anchorY: 0.1, scaleX: 5, scaleY: 5, alpha: 1 }); scoreBackground.addChild(scoreBgGraphics); scoreBackground.x = 0; scoreBackground.y = 0; LK.gui.top.addChild(scoreBackground); var scoreTxt = new Text2('Lanterns destroyed: 0', { size: 30, fill: 0xFF3659, font: "'Comic Sans MS', cursive, sans-serif" }); scoreTxt.anchor.set(0.5, -0.1); scoreBackground.addChild(scoreTxt); 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); } // Function to apply box effects based on box type function applyBoxEffect(box) { // Check if the collected box is an instance of Box1 if (box instanceof Box1) { // If we already have box1 harpoons, destroy them first var existingHarpoons = game.children.filter(function (child) { return child instanceof Harpoon && child.isFromBox1 === true; }); existingHarpoons.forEach(function (harpoon) { harpoon.trail.destroy(); harpoon.destroy(); }); // 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 - 200; leftHarpoon.startY = leftHarpoon.y; leftHarpoon.trail.x = leftHarpoon.x; leftHarpoon.trail.y = player.y - 200; // Create first trail segment from player to harpoon leftHarpoon.trail.createSegment(0, 100); // Mark harpoons created by box power-up leftHarpoon.isPlayerCreated = false; leftHarpoon.isFromBox1 = true; // Mark specifically as from Box1 power-up // Add trail first so it renders below the harpoon game.addChild(leftHarpoon.trail); // Then add the harpoon so it renders on top of the trail game.addChild(leftHarpoon); var rightHarpoon = new Harpoon(); rightHarpoon.x = player.x + i * 150; rightHarpoon.y = player.y - 200; rightHarpoon.startY = rightHarpoon.y; rightHarpoon.trail.x = rightHarpoon.x; rightHarpoon.trail.y = player.y - 200; // Create first trail segment from player to harpoon rightHarpoon.trail.createSegment(0, 100); // Mark harpoons created by box power-up rightHarpoon.isPlayerCreated = false; rightHarpoon.isFromBox1 = true; // Mark specifically as from Box1 power-up // Add trail first so it renders below the harpoon game.addChild(rightHarpoon.trail); // Then add the harpoon so it renders on top of the trail 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 collected 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 collected 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 collected 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("Lanterns destroyed: " + 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 }); } }); } // Create toast message based on box type showToastForBox(box); } // Function to show toast message for box effects function showToastForBox(box) { 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(); } }); } // Function to handle player death sequence with rainbow colors function handlePlayerDeath() { // Rainbow colors array var rainbowColors = [0xFF0000, // Red 0xFF7F00, // Orange 0xFFFF00, // Yellow 0x00FF00, // Green 0x0000FF, // Blue 0x4B0082, // Indigo 0x9400D3 // Violet ]; // Create dramatic death effect var deathEffect = new PlayerDeathEffect(); game.addChild(deathEffect); deathEffect.startEffect(); // Mark game as over to stop spawning bubbles game.isGameOver = true; // Create a function for sequential rainbow color animation function playerRainbowSequence(colorIndex) { if (colorIndex >= rainbowColors.length) { // One full cycle completed, start fading out tween(player, { alpha: 0, tint: 0xFFFFFF }, { duration: 500, easing: tween.easeOut }); return; } tween(player, { alpha: 0.3, tint: rainbowColors[colorIndex] }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { playerRainbowSequence(colorIndex + 1); } }); } // Start the rainbow sequence playerRainbowSequence(0); } var lastShot = -999; game.down = function (x, y, obj) { if (LK.ticks - lastShot > 10) { player.shoot(); lastShot = LK.ticks; } }; // Start the music 'chinese' upon starting the game LK.playMusic('chinese'); game.update = function () { // Initialize game.isGameOver if it doesn't exist if (game.isGameOver === undefined) { game.isGameOver = false; } // Only spawn new bubbles if game isn't over if (!game.isGameOver && LK.ticks % 50 == 0) { var newBubble = new Bubble(); newBubble.x = Math.random() * 2048; newBubble.y = 2732 * 0.75; // Start at 25% from bottom of screen game.addChild(newBubble); var randomTween = { delta: Math.random() * (300 - 100) + 100, // Random delta between 100 and 300 duration: Math.random() * (1500 - 800) + 800, // Random duration between 800 and 1500 easing: [tween.easeIn, tween.easeOut, tween.elasticIn, tween.elasticOut, tween.bounceIn, tween.bounceOut, tween.easeInOut, tween.bounceInOut, tween.elasticInOut][Math.floor(Math.random() * 9)] // Random easing }; tween(newBubble, { x: Math.max(0, Math.min(2048, newBubble.x + randomTween.delta)) }, { duration: randomTween.duration, easing: randomTween.easing, onFinish: function onFinish() { tween(newBubble, { x: Math.max(0, Math.min(2048, newBubble.x - randomTween.delta)) }, { duration: randomTween.duration, easing: randomTween.easing }); } }); } var bubbles = game.children.filter(function (child) { return child instanceof Bubble; }); var harpoons = game.children.filter(function (child) { return child instanceof Harpoon; }); for (var i = 0; i < bubbles.length; i++) { var bubble = bubbles[i]; // Check for player intersection but don't damage the player // We allow lanterns to pass through the player harmlessly if (bubble.intersects(player)) { // Don't destroy the bubble or harm the player // This allows the bubble to continue moving up // It will only damage the player if it exits off the top without being destroyed } for (var j = 0; j < harpoons.length; j++) { var harpoon = harpoons[j]; // Enhanced collision detection for longer harpoon reach if (bubble.intersects(harpoon) || Math.abs(bubble.x - harpoon.x) < 50 && Math.abs(bubble.y - harpoon.trail.y - harpoon.trail.height / 4) < harpoon.trail.height / 2) { bubble.destroy(); LK.getSound('explosion').play(); harpoon.trail.destroy(); // Destroy the harpoon trail harpoon.destroy(); bubbles.splice(i, 1); // Remove bubble from the array score += 1; scoreTxt.setText("Lanterns destroyed: " + 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 }); } }); harpoons.splice(j, 1); // Remove harpoon from the array // Create an explosion at the intersection point var explosion = new Explosion(); explosion.x = bubble.x; explosion.y = bubble.y; game.addChild(explosion); // Create a box at the intersection point with a 5% probability (half the previous 10%) // Only spawn boxes when balloons are popped by player harpoons, not by explosion effects if (!game.children.some(function (child) { return child instanceof Box || child instanceof Box1 || child instanceof Box2 || child instanceof Box3; })) { // Only create boxes when bubble is popped by a player-created harpoon, not by power-up harpoons // Check explicitly that the harpoon was created by the player, not by any box power-up if (Math.random() < 0.5 && harpoon instanceof Harpoon && harpoon.isPlayerCreated === true) { 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 = bubble.x; box.y = bubble.y; game.addChild(box); } } } } var boxes = game.children.filter(function (child) { return child instanceof Box || child instanceof Box1 || child instanceof Box2 || child instanceof Box3; }); for (var k = 0; k < boxes.length; k++) { var box = boxes[k]; // Check if player collects/intersects the box if (box.intersects(player)) { // Create collection animation tween(box.scale, { x: 0, y: 0 }, { duration: 300, easing: tween.easeInOut, onFinish: function (boxToDestroy) { boxToDestroy.destroy(); }.bind(null, box) }); // Play pickup sound LK.getSound('powerup').play(); // Apply the power-up effect based on box type using centralized handler applyBoxEffect(box); // Remove box from tracking array boxes.splice(k, 1); // Break out of the loop since we've handled the box break; } // Check for harpoon intersecting with boxes for (var l = 0; l < harpoons.length; l++) { var harpoon = harpoons[l]; if (box.intersects(harpoon)) { // Store reference to box before destroying it var boxToApplyEffect = box; // Destroy elements box.destroy(); LK.getSound('powerup').play(); harpoon.trail.destroy(); harpoon.destroy(); // Apply the power-up effect based on box type using centralized handler applyBoxEffect(boxToApplyEffect); // Remove from arrays boxes.splice(k, 1); harpoons.splice(l, 1); break; } } } } };
===================================================================
--- original.js
+++ change.js
@@ -329,11 +329,12 @@
var yOffset = i * segmentHeight;
self.trail.createSegment(yOffset, segmentHeight);
}
}
- // Position trail beneath the harpoon and extend back to player
- self.trail.y = player.y - 200; // Connect to player's position
- self.trail.height = self.startY - self.y;
+ // Position trail to start from player and extend to the harpoon
+ self.trail.x = self.x; // Match trail x with harpoon x
+ self.trail.y = player.y - 200; // Start trail from player position
+ self.trail.height = self.startY - self.y; // Set height to span from player to harpoon
// Destroy when reaching max distance or going off-screen
if (self.y < 0 || self.startY - self.y > self.maxDistance) {
self.destroy();
self.trail.destroy();
@@ -364,8 +365,10 @@
harpoon.trail.x = player.x;
harpoon.trail.y = player.y - 200;
// Create first trail segment starting from player
harpoon.trail.createSegment(0, 100);
+ // Set proper starting y position to measure distance correctly
+ harpoon.startY = harpoon.y;
// Create a more dramatic scale effect for shooting with extended range
harpoon.scale.x = 0.7;
harpoon.scale.y = 1.3;
// Flag normal harpoons (from player) to allow them to create boxes
@@ -653,11 +656,12 @@
// 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;
+ leftHarpoon.y = player.y - 200;
+ leftHarpoon.startY = leftHarpoon.y;
+ leftHarpoon.trail.x = leftHarpoon.x;
+ leftHarpoon.trail.y = player.y - 200;
// Create first trail segment from player to harpoon
leftHarpoon.trail.createSegment(0, 100);
// Mark harpoons created by box power-up
leftHarpoon.isPlayerCreated = false;
@@ -667,11 +671,12 @@
// Then add the harpoon so it renders on top of the trail
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;
+ rightHarpoon.y = player.y - 200;
+ rightHarpoon.startY = rightHarpoon.y;
+ rightHarpoon.trail.x = rightHarpoon.x;
+ rightHarpoon.trail.y = player.y - 200;
// Create first trail segment from player to harpoon
rightHarpoon.trail.createSegment(0, 100);
// Mark harpoons created by box power-up
rightHarpoon.isPlayerCreated = false;
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 chinese flying paper lantern, retro pixel style. In-Game asset. 2d. High contrast. No shadows
fireworks, retro pixel style, colorful. In-Game asset. 2d. High contrast. No shadows
A chinese pixel background of an arcade game, sunset, retro style,. In-Game asset. 2d. High contrast. No shadows