User prompt
There are some serious issues. After I jump to platforms I click on the dragon and bubbles are not shot.
User prompt
In here, you are not makign sure the buuble is only shoot if I click on myself, the dragon! game.down = function (x, y, obj) { var now = Date.now(); if (y < dragon.y - dragon.height && canJump && !isJumping) { isJumping = true; // Set isJumping to true when the dragon starts jumping // Play jump sound when the dragon starts jumping LK.getSound('jump').play(); jumpStartY = y; // Capture the Y position of the mouse click jumpStartTime = Date.now(); // Initialize jump start time } //else if (!isJumping) { if (now - lastClick > 200) { dragon.shootBubble(); lastShot = now; } lastClick = now; };
Code edit (1 edits merged)
Please save this source code
User prompt
I donm't understand. I click very low in the scren and jumps a lot! It should jump max to the place on y I click / tap on the screen
Code edit (3 edits merged)
Please save this source code
User prompt
UpdateJump is incorrect. You should use jumpStartY to see where the dragon should be in the period of time the interval of the jump lasts and update in intervals until it reaches jumpStartY in that time.
Code edit (2 edits merged)
Please save this source code
User prompt
Remove the updateJump() function. Instead, when the dragon should jump, create a tween to the target position and back. Keep the isJumping because you will need it to make sure it lands on a floor if it finds it in its falling trajectory, etc. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: dragon.containsPoint is not a function' in or related to this line: 'if (dragon.containsPoint(obj.position)) {' Line Number: 572
User prompt
The bubbles are not always being triggered when clicking the dragon player. Please make sure always a bubble is triggered on tapping the dragon.
User prompt
Make that the jump is not a tween but a just linear movement using an interval or something super quick and performant.
User prompt
Redo the game
Code edit (1 edits merged)
Please save this source code
User prompt
The amount of things you do on every tick (game.update) is insane! updateJump(); updateFall(); } // Update game elements in an optimized order updateBubbles(); updateEnemiesMovement(); You can't do that so frequently. You need to come up with another way of doing all of that not on a tick frequency
User prompt
The amount of things you do on every tick (game.update) is insane! updateJump(); updateFall(); } // Update game elements in an optimized order updateBubbles(); updateEnemiesMovement(); You can't do that so frequently. You need to come up with another way of doing all of that not on a tick frequency
User prompt
Remove everything being check at a tick to remove all performance issues. Instead please do optimized checks
User prompt
Keep removing and simplifying everything that runs on ticks without breaking functionalities, to reduce to the maximum the RAM consumed and the CPU used.
User prompt
Remove the tweens from the enemies. Replace them with just a normal movement without the tween library.
User prompt
The performance is terrible on mobile, as there are many things being checked on a tick level + the tweens. Please, optimize the performance to the max but keeping all the same features intact. Don't touche the collisions between the dragon and the floors. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The floor collisions are broken: sometimes the dragon falls just by walking on them. Please firx that, a floor should never be able to be crossed by a dragon. A dragon should be able to always walk on floors. A dragon can never fall across a floor, it should stop on top of any floor it finds.
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'var bottomFloorTop = floors.length > 0 ? bottomFloorY - floors[0].height / 2 : bottomFloorY; // Top edge of the bottom floor' Line Number: 497
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'var bottomFloorTop = floors.length > 0 ? bottomFloorY - floors[0].height / 2 : bottomFloorY; // Top edge of the bottom floor' Line Number: 490
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'var bottomFloorTop = bottomFloorY - floors[0].height / 2; // Top edge of the bottom floor' Line Number: 488
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Class for Bubbles - optimized for performance var Bubble = Container.expand(function () { var self = Container.call(this); var bubbleGraphics = self.attachAsset('bubble', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -5; self.lastX = 0; self.lastY = 0; self.update = function () { // Store last position self.lastX = self.x; self.lastY = self.y; // Move bubble self.x += self.speed; // Collision with floor is handled in updateBubbles function now }; }); var CapturingBubble = Container.expand(function () { var self = Container.call(this); var bubbleGraphics = self.attachAsset('bubble', { anchorX: 0.5, anchorY: 0.5 }); self.alpha = 0.5; self.scaleX = 2; self.scaleY = 2; self.update = function () {}; }); //<Assets used in the game will automatically appear here> // Class for the Dragon character - optimized for performance var Dragon = Container.expand(function () { var self = Container.call(this); self.dragonGraphics = self.attachAsset('dragon', { anchorX: 0.5, anchorY: 0.5 }); self.lastX = 0; self.lastY = 0; self.shootBubble = function () { // Create new bubble and ensure it's properly initialized var bubble = new Bubble(); bubble.x = self.x + 200 * self.scale.x; bubble.y = self.y - 5; bubble.lastX = bubble.x; bubble.lastY = bubble.y; // If the dragon is looking right, the bubble should move to the right if (self.scale.x == 1) { bubble.speed = 25; } else { // If the dragon is looking left, the bubble should move to the left bubble.speed = -25; } // Add bubble to game display list first to ensure it's rendered game.addChild(bubble); // Ensure bubbles array exists before trying to push to it if (!bubbles) { bubbles = []; } // Always add bubble to tracking array bubbles.push(bubble); // Play bubble sound when a bubble is shot LK.getSound('bubble').play(); }; }); // Class for Pop - optimized version var PoppedBubble = Container.expand(function () { var self = Container.call(this); var popGraphics = self.attachAsset('poppedBubble', { anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x09899d }); /**** * Game Code ****/ function tweenDragonContainer() { tween(dragonOnContainer, { y: dragonOnContainer.y + 300 }, { duration: 1000, onFinish: function onFinish() { tween(dragonOnContainer, { y: dragonOnContainer.y - 300 }, { duration: 1000 }); } }); } var started = false; // Initialize started flag var intervalId = LK.setInterval(function () { if (!started) { tweenDragonContainer(); } else { LK.clearInterval(intervalId); // Clear interval if started is true } }, 4000); var controlPanel = new Container(); var panelBackground = LK.getAsset('game_background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.8 }); controlPanel.addChild(panelBackground); var instructionsText = new Text2('INSTRUCTIONS', { size: 100, fill: 0xffffff, align: "center", font: "Comic Sans MS", fontWeight: "bold" }); instructionsText.anchor.set(0.5, 0.5); instructionsText.x = 2048 / 2; instructionsText.y = 75; controlPanel.addChild(instructionsText); // Rainbow color array var rainbowColors = [0xFF0000, 0xFF7F00, 0xFFFF00, 0x00FF00, 0x0000FF, 0x4B0082, 0x8B00FF]; var colorIndex = 0; // Function to cycle through rainbow colors function cycleRainbowColors() { instructionsText.tint = rainbowColors[colorIndex]; colorIndex = (colorIndex + 1) % rainbowColors.length; } // Set interval to change color less frequently to improve performance LK.setInterval(cycleRainbowColors, 1000); var controlText = new Text2('- Click on 🐲 to shoot 🫧\n- Click above the 🐲 to jump ⬆️.\n- The higher you click, the bigger the jump ⬆️⬆️!', { size: 85, // Increased size for better visibility fill: 0x000000, align: "center", font: "Comic Sans MS" // Adding a cool font and bold style }); controlText.anchor.set(0.5, 0.5); controlText.x = 2048 / 2; controlText.y = 400; controlPanel.addChild(controlText); var understoodButtonBackgroundBg = LK.getAsset('understoodBg', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 800, width: 2000, alpha: 0.5 }); controlPanel.addChild(understoodButtonBackgroundBg); var dragonOnContainer = LK.getAsset('dragon', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 1200, scaleX: 2, scaleY: 2 }); controlPanel.addChild(dragonOnContainer); var bubbleOnContainer = LK.getAsset('bubble', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2, alpha: 0.35 }); dragonOnContainer.addChild(bubbleOnContainer); var understoodButton = new Text2('Click anywhere to start', { size: 150, fill: 0x1570e0, align: "center" }); understoodButton.anchor.set(0.5, 0.5); understoodButton.x = 2048 / 2; understoodButton.y = 800; controlPanel.addChild(understoodButton); game.addChild(controlPanel); // Add event listener to the 'Understood' button understoodButton.interactive = true; understoodButton.buttonMode = true; game.down = function (x, y, obj) { controlPanel.destroy(); startGame(); }; // Properly initialize all global variables to prevent undefined errors var bubbles = []; // Initialize bubbles array to store bubble instances var floors = []; // Initialize floors array to store floor instances var behaviours = {}; // Initialize behaviours object var enemies = []; var capturingBubbles = []; var jumpStartY = 0; var isJumping = false; // Initialize jumping state var canJump = true; // Initialize jump permission flag var isFalling = false; // Initialize falling state var lastShot = 0; // Track the last time a bubble was shot var lastClick = 0; // Track the last time the screen was clicked var jumpStartTime = 0; // Initialize jump start time var dragon; // Will be initialized later var background; // Will be initialized with a background image function startGame() { started = true; var level = 1; function restartGame() { // Clear existing platforms and enemies floors.forEach(function (floor) { floor.destroy(); }); floors = []; enemies.forEach(function (enemy) { enemy.destroy(); }); enemies = []; // Recreate floors at the bottom, left, and right margins for (var i = 0; i < 21; i++) { var floor = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: i * 100, y: 2732 - 30 }); game.addChild(floor); floors.push(floor); } for (var j = 0; j < 27; j++) { var leftFloor = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: 0, y: j * 100 }); game.addChild(leftFloor); floors.push(leftFloor); } for (var k = 0; k < 27; k++) { var rightFloor = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: 2048 - 50, y: k * 100 }); game.addChild(rightFloor); floors.push(rightFloor); } // Destroy the existing dragon dragon.destroy(); // Recreate the dragon and add it to the game dragon = game.addChild(new Dragon()); // Reposition dragon at the bottom dragon.x = 1024; // Center horizontally dragon.y = 2532; // Position the dragon on top of the floor // Add new platforms and enemies for the new level for (var j = 0; j < platformYPositions.length; j++) { var platformLength = Math.floor(Math.random() * (maxPlatformLength - minPlatformLength + 1)) + minPlatformLength; var startX = Math.floor(Math.random() * (2048 - platformLength * 100)); var startY = platformYPositions[j]; var randomTint = Math.floor(Math.random() * 16777215); for (var i = 0; i < platformLength; i++) { var newX = startX + i * 100; if (newX > 1900 || newX < 120) { continue; } var platform = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: startX + i * 100, y: platformYPositions[j] }); platform.tint = randomTint; game.addChild(platform); floors.push(platform); } var enemyType = 'enemy' + (i % 5 + 1); var behaviour = behaviours[enemyType] || easingFunctions[Math.floor(Math.random() * easingFunctions.length)]; behaviours[enemyType] = behaviour; var enemy = LK.getAsset(enemyType, { anchorX: 0.5, anchorY: 0.5, x: startX + 100, y: platformYPositions[j] - 100, type: enemyType }); if (enemyType === 'enemy5' || enemyType === 'enemy2') { enemy.tint = Math.floor(Math.random() * 0x7FFFFF) + 0x808080; } enemy.captured = false; game.addChild(enemy); enemies.push(enemy); } } var background = LK.getAsset('pixel_background_' + level.toString(), { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, alpha: 0.95 }); game.addChild(background); // Simplified utility function that replaces all the complex array handlers function getMinMaxFromFloors(floors, property) { var min = Infinity; var max = -Infinity; for (var i = 0; i < floors.length; i++) { var value = floors[i][property]; if (value < min) { min = value; } if (value > max) { max = value; } } return { min: min, max: max }; } var jumpStartTime; // Declare jumpStartTime to track the start of the jump var easingFunctions = [tween.linear, tween.easeIn, tween.easeOut, tween.easeInOut, tween.bounceIn, tween.bounceOut, tween.bounceInOut, tween.elasticIn, tween.elasticOut, tween.elasticInOut, tween.cubicIn, tween.cubicOut, tween.cubitInOut, tween.expoIn, tween.expoOut, tween.expoInOut, tween.sineIn, tween.sineOut, tween.sineInOut]; LK.playMusic('music'); function isStandingOnFloor() { // Store the dragon's position var dragonBottom = dragon.y + dragon.height / 2; for (var i = 0; i < floors.length; i++) { var floor = floors[i]; var floorTop = floor.y - floor.height / 2; // More precise collision detection for standing on platforms if (dragon.intersects(floor) && Math.abs(dragonBottom - floorTop) < 20 && dragon.lastY < dragon.y) { return true; } } return false; } function updateFall() { if (isFalling) { // Store last position before moving var lastY = dragon.y; // Move dragon downwards with a smaller increment to prevent passing through platforms dragon.y += 20; // Check for collisions after moving var isIntersecting = false; for (var i = 0; i < floors.length; i++) { // Check if dragon is intersecting with a floor if (dragon.intersects(floors[i])) { isIntersecting = true; // Only stop falling if we weren't intersecting before (just collided) if (!dragon.lastWasIntersecting || lastY < floors[i].y - floors[i].height) { isJumping = false; // Stop jumping isFalling = false; // Stop falling when colliding with a floor canJump = true; // Allow jumping again when the dragon hits a floor dragon.y = floors[i].y - floors[i].height * 1.5; // Align dragon to the top of the floor break; } } } // Update last known intersection state dragon.lastWasIntersecting = isIntersecting; } } //<Assets used in the game will automatically appear here> // Handle mouse move events to move the dragon game.move = function (x, y, obj) { // Ignore the event if the target is outside the screen or close to its margins if (x > 150 && x < 2048 - 200) { // Set the target x position for the dragon dragon.targetX = x; } }; var isFalling = false; // Initialize isFalling to track dragon's fall state var dragon = game.addChild(new Dragon()); dragon.lastY = dragon.y; // Initialize lastY position dragon.x = 1024; // Center horizontally dragon.y = 2532; // Position the dragon on top of the floor // Handle game updates with improved frame handling game.update = function () { // Move dragon incrementally towards target x with improved movement if (dragon.targetX !== undefined) { var increment = (dragon.targetX - dragon.x) / 5; // Faster movement for better responsiveness if (Math.abs(dragon.targetX - dragon.x) > 1) { dragon.x += increment; } // Update last known position dragon.lastX = dragon.x; dragon.lastY = dragon.y; // Adjust dragon's scale based on targetX position if (dragon.targetX < dragon.x) { dragon.scale.x = -1; } else { dragon.scale.x = 1; } } // Always check floor standing to prevent falling through platforms var standingOnFloor = isStandingOnFloor(); if (!standingOnFloor && !isJumping) { isFalling = true; } // Always update jumping and falling updateJump(); updateFall(); // Update bubbles every frame for consistent collision detection updateBubbles(); // Update enemy movement every frame for consistent movement updateEnemiesMovement(); }; // Handle touch events for shooting bubbles var lastShot = 0; var lastClick = 0; var isJumping = false; // Add a variable to track if the dragon is jumping var canJump = true; // Initialize canJump flag to allow jumping game.down = function (x, y, obj) { var now = Date.now(); if (y < dragon.y - dragon.height && canJump && !isJumping) { isJumping = true; // Set isJumping to true when the dragon starts jumping // Play jump sound when the dragon starts jumping LK.getSound('jump').play(); jumpStartY = y; // Capture the Y position of the mouse click jumpStartTime = Date.now(); // Initialize jump start time } else if (!isJumping) { // Reduce cooldown for more responsive shooting and fix bubble creation if (now - lastShot > 300) { // Ensure dragon exists before calling shootBubble if (dragon && typeof dragon.shootBubble === 'function') { dragon.shootBubble(); lastShot = now; } } } lastClick = now; }; function updateEnemiesMovement() { // Process all enemies every frame to ensure consistent movement for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (!enemy) { continue; } if (enemy.captured) { if (enemy.isMoving) { tween.stop(enemy); enemy.isMoving = false; enemy.floating = true; } else if (enemy.floating) { var enemyRef = enemy; // Create a strong reference to avoid context loss // Store reference to current enemy in a closure variable (function (currentEnemy) { tween(currentEnemy, { y: 100 }, { duration: 5000, easing: tween.linear, onFinish: function onFinish() { // Use the closure variable instead of 'this' if (currentEnemy && currentEnemy.children && currentEnemy.children[1]) { currentEnemy.children[1].tint = 0xbf5555; } if (enemies.length === 0) { if (level < 5) { level++; background.destroy(); // Remove the previous background background = LK.getAsset('pixel_background_' + level.toString(), { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 - background.height / 2, alpha: 0.95 }); game.addChild(background); // Add the new background // Combined level text creation to reduce object creation var levelText = new Text2('LEVEL ' + level.toString(), { size: 200, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0.5); levelText.x = 2048 / 2; levelText.y = 2732 / 2; game.addChild(levelText); LK.setTimeout(function () { levelText.destroy(); }, 2000); // Restart game with new platforms and enemies restartGame(); } else { LK.showYouWin(); } } } }); })(enemyRef); } } else { // Initialize movement if not already moving if (!enemy.isMoving && !enemy.tweenInitialized) { enemy.isMoving = true; enemy.tweenInitialized = true; // Find all platform floors for this enemy var platformFloors = []; var platformY = enemy.y + 100; for (var j = 0; j < floors.length; j++) { if (Math.abs(floors[j].y - platformY) < 10 && floors[j].x > 0 && floors[j].x < 2048 - 50) { platformFloors.push(floors[j]); } } // Only proceed if we found platform floors if (platformFloors.length > 0) { // Find min and max X positions var startX = 2048; var endX = 0; for (var j = 0; j < platformFloors.length; j++) { if (platformFloors[j].x < startX) { startX = platformFloors[j].x; } if (platformFloors[j].x > endX) { endX = platformFloors[j].x; } } // Ensure we have a valid range to move in if (startX < endX) { enemy.alpha = 0.75; // Apply alpha when starting to move // Store the platform range for this enemy enemy.startX = startX; enemy.endX = endX; // Start the movement tween // Make sure to attach context to all tweens and store a strong reference to enemy var enemyRef = enemy; // Create a strong reference to avoid context loss // Use immediately invoked function to create closure for this enemy (function (currentEnemy, startPos, endPos) { function moveToStart(enemy) { enemy.isMovingRight = false; tween(enemy, { x: startPos }, { duration: 3000, easing: tween.linear, onFinish: function onFinish() { if (!enemy) { return; } enemy.isMovingRight = true; moveToEnd(enemy); } }); } function moveToEnd(enemy) { tween(enemy, { x: endPos }, { duration: 3000, easing: tween.linear, onFinish: function onFinish() { if (!enemy || enemy.isMovingRight === undefined) { return; } enemy.isMovingRight = false; moveToStart(enemy); } }); } // Start initial movement tween(currentEnemy, { x: endPos }, { duration: 3000, easing: behaviours[currentEnemy.type] || tween.linear, onFinish: function onFinish() { if (!currentEnemy) { return; } moveToStart(currentEnemy); } }); })(enemyRef, enemyRef.startX, enemyRef.endX); enemy.isMovingRight = true; } } } // Update enemy direction based on movement if (enemy.x !== enemy.lastX) { enemy.scale.x = enemy.x > enemy.lastX ? 1 : -1; } // Check for collision with dragon if (!enemy.captured && dragon.intersects(enemy)) { // Play game over sound when the dragon dies LK.getSound('gameover').play(); // Rotate the dragon 90 degrees dragon.rotation = -3 * Math.PI * dragon.scale.x; // Animate the dragon falling down - simplified tween with proper context var dragonRef = dragon; // Create a strong reference to avoid context loss // Use immediately invoked function to create closure (function (dragonToTween) { tween(dragonToTween, { y: 2732 + dragonToTween.height, tint: 0xFF0000 }, { duration: 500, easing: tween.linear, onFinish: function onFinish() { LK.showGameOver(); } }); })(dragonRef); } } // Update last known position enemy.lastX = enemy.x; enemy.lastY = enemy.y; } // Always check for collisions with the dragon for all enemies for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (!enemy.captured && dragon.intersects(enemy)) { // Game over handling moved outside the loop to avoid duplicate calls // Just mark for game over if (!game.gameOverTriggered) { game.gameOverTriggered = true; // Play game over sound when the dragon dies LK.getSound('gameover').play(); // Rotate the dragon 90 degrees dragon.rotation = -3 * Math.PI * dragon.scale.x; // Animate the dragon falling down - simplified tween with proper context var dragonRef = dragon; // Create a strong reference to avoid context loss // Use immediately invoked function to create closure (function (dragonToTween) { tween(dragonToTween, { y: 2732 + dragonToTween.height, tint: 0xFF0000 }, { duration: 500, easing: tween.linear, onFinish: function onFinish() { LK.showGameOver(); } }); })(dragonRef); } break; } } } function updateBubbles() { // Ensure bubbles array exists to prevent errors if (!bubbles) { bubbles = []; return; } // Process all bubbles every frame for consistent collision detection for (var i = bubbles.length - 1; i >= 0; i--) { var bubble = bubbles[i]; if (!bubble) { bubbles.splice(i, 1); continue; } // Move bubble bubble.x += bubble.speed; // Remove bubbles that go off-screen if (bubble.y < -50 || bubble.x < -50 || bubble.x > 2100) { bubble.destroy(); bubbles.splice(i, 1); continue; // Skip further checks for this bubble } // Check for bubble-bubble intersections for (var j = i - 1; j >= 0; j--) { var otherBubble = bubbles[j]; if (!otherBubble) { bubbles.splice(j, 1); continue; } if (bubble.intersects(otherBubble)) { // Create PoppedBubbles var pop1 = game.addChild(new PoppedBubble()); pop1.x = bubble.x; pop1.y = bubble.y; var pop2 = game.addChild(new PoppedBubble()); pop2.x = otherBubble.x; pop2.y = otherBubble.y; // Destroy bubbles bubble.destroy(); otherBubble.destroy(); // Remove from array bubbles.splice(i, 1); if (j < bubbles.length) { bubbles.splice(j, 1); } // Play pop sound LK.getSound('pop').play(); // Destroy PoppedBubbles after delay LK.setTimeout(function () { pop1.destroy(); pop2.destroy(); }, 500); break; // Exit inner loop after collision } } // Check for bubble-enemy collisions if (bubble && !bubble.destroyed) { // Check if bubble still exists for (var k = enemies.length - 1; k >= 0; k--) { var enemy = enemies[k]; if (!enemy || enemy.captured) { continue; } if (bubble.intersects(enemy)) { // Destroy the original bubble bubble.destroy(); bubbles.splice(i, 1); // Create a new bubble as a child of the enemy var newBubble = new CapturingBubble(); newBubble.x = 0; // Position relative to the enemy newBubble.y = 0; // Position relative to the enemy enemy.addChild(newBubble); enemy.captured = true; capturingBubbles.push(newBubble); break; // Exit inner loop after collision } } } // Check for bubble-floor collisions if (bubble && !bubble.destroyed) { // Check if bubble still exists for (var m = 0; m < floors.length; m++) { if (bubble.intersects(floors[m])) { var pop = game.addChild(new PoppedBubble()); pop.x = bubble.x; pop.y = bubble.y; bubble.destroy(); bubbles.splice(i, 1); LK.getSound('pop').play(); LK.setTimeout(function () { pop.destroy(); }, 500); break; // Exit inner loop after collision } } } // Check for dragon-bubble collisions if (bubble && !bubble.destroyed) { // Check if bubble still exists if (dragon.intersects(bubble)) { var pop = game.addChild(new PoppedBubble()); pop.x = bubble.x; pop.y = bubble.y; bubble.destroy(); bubbles.splice(i, 1); LK.getSound('pop').play(); LK.setTimeout(function () { pop.destroy(); }, 500); } } } // Update capturing bubbles and check for dragon-capturing bubble collisions for (var i = capturingBubbles.length - 1; i >= 0; i--) { var capturingBubble = capturingBubbles[i]; if (!capturingBubble) { capturingBubbles.splice(i, 1); continue; } var enemy = capturingBubble.parent; if (enemy && enemy.captured && !enemy.floating) { enemy.y -= 5; // Make the enemy float up more smoothly } // Check for dragon-capturing bubble collisions if (dragon.intersects(capturingBubble)) { // Find and destroy the enemy that is the parent of the CapturingBubble for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (!enemy) { continue; } if (enemy.children && enemy.children.indexOf(capturingBubble) !== -1) { // Create a PoppedBubble at the capturingBubble's position var pop = game.addChild(new PoppedBubble()); pop.x = enemy.x; pop.y = enemy.y; // Destroy the enemy and capturingBubble enemy.destroy(); enemies.splice(j, 1); // Remove from capturing bubbles array capturingBubbles.splice(i, 1); // Play pop sound when a capturing bubble is popped LK.getSound('pop').play(); // Destroy the PoppedBubble after 1 second LK.setTimeout(function () { pop.destroy(); }, 1000); break; // Exit inner loop after collision } } } } } function updateJump() { if (isJumping) { var jumpHeight = (dragon.y - jumpStartY) / 10; dragon.y -= jumpHeight; // Move dragon upwards based on calculated jump height // More efficient intersection check with early termination var dragonIntersectsFloor = false; for (var i = 0; i < floors.length; i++) { if (dragon.intersects(floors[i])) { dragonIntersectsFloor = true; if (!dragon.lastWasIntersecting) { isJumping = false; // Stop jumping isFalling = true; // Start falling when colliding with a floor canJump = false; // Disallow jumping again until the dragon hits a floor dragon.y -= 25; } break; } } // Check if jump duration has exceeded 0.4 seconds if (Date.now() - jumpStartTime >= 400) { isJumping = false; isFalling = true; } // Update last known intersection state dragon.lastWasIntersecting = dragonIntersectsFloor; } } // BLOCKS // Add a floor to the bottom of the screen var floors = []; for (var i = 0; i < 21; i++) { var floor = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: i * 100, y: 2732 - 30 }); game.addChild(floor); floors.push(floor); } // Add continuous floor on the left margin of the screen for (var j = 0; j < 27; j++) { var leftFloor = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: 0, y: j * 100 }); game.addChild(leftFloor); floors.push(leftFloor); } // Add continuous floor on the right margin of the screen for (var k = 0; k < 27; k++) { var rightFloor = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: 2048 - 50, y: k * 100 }); game.addChild(rightFloor); floors.push(rightFloor); } // Add random platforms with irregular heights and positions var platformYPositions = []; var distinctHeights = [2300, 1900, 1500, 1100, 700]; // Define 4-5 distinct heights var minPlatformLength = 5; var maxPlatformLength = 14; distinctHeights.forEach(function (height) { platformYPositions.push(height); }); // Add random platforms with irregular heights and positions for (var j = 0; j < platformYPositions.length; j++) { var _behaviours$enemyType; var platformLength = Math.floor(Math.random() * (maxPlatformLength - minPlatformLength + 1)) + minPlatformLength; var startX = Math.floor(Math.random() * (2048 - platformLength * 100)); // Random start position var startY = platformYPositions[j]; // Generate a random tint color for the platforms var randomTint = Math.floor(Math.random() * 16777215); for (var i = 0; i < platformLength; i++) { var newX = startX + i * 100; if (newX > 1900 || newX < 120) { continue; } var platform = LK.getAsset('floor', { anchorX: 0.5, anchorY: 0.5, x: startX + i * 100, y: platformYPositions[j] }); platform.tint = randomTint; // Apply the random tint to the platform game.addChild(platform); floors.push(platform); } // Spawn an enemy on top of each platform var enemyType = 'enemy' + (i % 5 + 1); // Cycle through enemy1 to enemy5 var behaviour = (_behaviours$enemyType = behaviours[enemyType]) !== null && _behaviours$enemyType !== void 0 ? _behaviours$enemyType : easingFunctions[Math.floor(Math.random() * easingFunctions.length)]; // Assign random easing function; behaviours[enemyType] = behaviour; var enemy = LK.getAsset(enemyType, { anchorX: 0.5, anchorY: 0.5, x: startX + 100, y: platformYPositions[j] - 100, type: enemyType }); if (enemyType === 'enemy5' || enemyType === 'enemy2') { enemy.tint = Math.floor(Math.random() * 0x7FFFFF) + 0x808080; // Ensure light tint } enemy.captured = false; game.addChild(enemy); enemies.push(enemy); } /* LEVEL MANAGEMENT 1 */ var levelTextBackground = new Text2('LEVEL ' + level.toString(), { size: 210, fill: 0x000000 }); levelTextBackground.anchor.set(0.5, 0.5); levelTextBackground.x = 2048 / 2; levelTextBackground.y = 2732 / 2; game.addChild(levelTextBackground); LK.setTimeout(function () { levelTextBackground.destroy(); }, 2000); var levelText = new Text2('LEVEL ' + level.toString(), { size: 200, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0.5); levelText.x = 2048 / 2; levelText.y = 2732 / 2; game.addChild(levelText); LK.setTimeout(function () { levelText.destroy(); }, 2000); }
===================================================================
--- original.js
+++ change.js
@@ -21,34 +21,9 @@
self.lastX = self.x;
self.lastY = self.y;
// Move bubble
self.x += self.speed;
- // Check for intersection with any floor
- var intersectingFloor = null;
- for (var i = 0; i < floors.length; i++) {
- if (self.intersects(floors[i])) {
- intersectingFloor = floors[i];
- break;
- }
- }
- // Handle collision with floor
- if (intersectingFloor) {
- // Create a PoppedBubble at the bubble's position
- var pop = game.addChild(new PoppedBubble());
- pop.x = self.x;
- pop.y = self.y;
- // Remove from bubbles array before destroying
- var bubbleIndex = bubbles.indexOf(self);
- if (bubbleIndex !== -1) {
- bubbles.splice(bubbleIndex, 1);
- }
- // Destroy the bubble
- self.destroy();
- // Destroy the PoppedBubble after 0.5 seconds
- LK.setTimeout(function () {
- pop.destroy();
- }, 500);
- }
+ // Collision with floor is handled in updateBubbles function now
};
});
var CapturingBubble = Container.expand(function () {
var self = Container.call(this);
@@ -68,10 +43,8 @@
self.dragonGraphics = self.attachAsset('dragon', {
anchorX: 0.5,
anchorY: 0.5
});
- self.isIntersectingBubble = false;
- self.lastWasIntersecting = false;
self.lastX = 0;
self.lastY = 0;
self.shootBubble = function () {
// Create new bubble and ensure it's properly initialized
@@ -359,23 +332,16 @@
var jumpStartTime; // Declare jumpStartTime to track the start of the jump
var easingFunctions = [tween.linear, tween.easeIn, tween.easeOut, tween.easeInOut, tween.bounceIn, tween.bounceOut, tween.bounceInOut, tween.elasticIn, tween.elasticOut, tween.elasticInOut, tween.cubicIn, tween.cubicOut, tween.cubitInOut, tween.expoIn, tween.expoOut, tween.expoInOut, tween.sineIn, tween.sineOut, tween.sineInOut];
LK.playMusic('music');
function isStandingOnFloor() {
- // Store the dragon's position and dimensions once
+ // Store the dragon's position
var dragonBottom = dragon.y + dragon.height / 2;
- var dragonX = dragon.x;
- var verticalThreshold = 50; // Check floors slightly below the dragon
- var horizontalThreshold = dragon.width * 1.5; // Check floors horizontally near the dragon
for (var i = 0; i < floors.length; i++) {
var floor = floors[i];
- // Optimization: Only check floors vertically close and horizontally relevant
- if (Math.abs(floor.y - dragonBottom) < verticalThreshold && Math.abs(floor.x - dragonX) < horizontalThreshold + floor.width / 2) {
- var floorTop = floor.y - floor.height / 2;
- // More precise collision detection for standing on platforms, ensuring dragon is slightly above or at the floor top
- if (dragon.intersects(floor) && dragonBottom >= floorTop - 5 && dragonBottom <= floorTop + 5) {
- // Use <= for lastY comparison
- return true;
- }
+ var floorTop = floor.y - floor.height / 2;
+ // More precise collision detection for standing on platforms
+ if (dragon.intersects(floor) && Math.abs(dragonBottom - floorTop) < 20 && dragon.lastY < dragon.y) {
+ return true;
}
}
return false;
}
@@ -385,35 +351,25 @@
var lastY = dragon.y;
// Move dragon downwards with a smaller increment to prevent passing through platforms
dragon.y += 20;
// Check for collisions after moving
- var didCollide = false;
- var dragonX = dragon.x;
- var dragonBottom = dragon.y + dragon.height / 2;
- var verticalThreshold = 50; // Generous threshold for falling collision
- var horizontalThreshold = dragon.width * 1.5;
+ var isIntersecting = false;
for (var i = 0; i < floors.length; i++) {
- var floor = floors[i];
- // Optimization: Only check floors vertically and horizontally close
- if (Math.abs(floor.y - dragonBottom) < verticalThreshold + floor.height && Math.abs(floor.x - dragonX) < horizontalThreshold + floor.width / 2) {
- // Check if dragon is intersecting with a floor
- if (dragon.intersects(floor)) {
- var floorTop = floor.y - floor.height / 2;
- // Ensure collision happened from above and is close to the top surface
- if (lastY < floorTop + 10 && dragonBottom >= floorTop - 5) {
- // Check if dragon was above or slightly overlapping the floor top
- isJumping = false; // Stop jumping
- isFalling = false; // Stop falling when colliding with a floor
- canJump = true; // Allow jumping again when the dragon hits a floor
- dragon.y = floorTop - dragon.height / 2; // Align dragon precisely on top of the floor
- didCollide = true;
- break;
- }
+ // Check if dragon is intersecting with a floor
+ if (dragon.intersects(floors[i])) {
+ isIntersecting = true;
+ // Only stop falling if we weren't intersecting before (just collided)
+ if (!dragon.lastWasIntersecting || lastY < floors[i].y - floors[i].height) {
+ isJumping = false; // Stop jumping
+ isFalling = false; // Stop falling when colliding with a floor
+ canJump = true; // Allow jumping again when the dragon hits a floor
+ dragon.y = floors[i].y - floors[i].height * 1.5; // Align dragon to the top of the floor
+ break;
}
}
}
- // Update last known intersection state outside the loop
- dragon.lastWasIntersecting = didCollide;
+ // Update last known intersection state
+ dragon.lastWasIntersecting = isIntersecting;
}
}
//<Assets used in the game will automatically appear here>
// Handle mouse move events to move the dragon
@@ -427,9 +383,9 @@
var isFalling = false; // Initialize isFalling to track dragon's fall state
var dragon = game.addChild(new Dragon());
dragon.lastY = dragon.y; // Initialize lastY position
dragon.x = 1024; // Center horizontally
- dragon.y = 2232; // Position the dragon on top of the floor
+ dragon.y = 2532; // Position the dragon on top of the floor
// Handle game updates with improved frame handling
game.update = function () {
// Move dragon incrementally towards target x with improved movement
if (dragon.targetX !== undefined) {
@@ -438,10 +394,8 @@
dragon.x += increment;
}
// Update last known position
dragon.lastX = dragon.x;
- // Update last known position
- dragon.lastX = dragon.x;
dragon.lastY = dragon.y;
// Adjust dragon's scale based on targetX position
if (dragon.targetX < dragon.x) {
dragon.scale.x = -1;
@@ -450,36 +404,18 @@
}
}
// Always check floor standing to prevent falling through platforms
var standingOnFloor = isStandingOnFloor();
- if (!standingOnFloor && !isJumping && !isFalling) {
+ if (!standingOnFloor && !isJumping) {
isFalling = true;
}
// Always update jumping and falling
updateJump();
updateFall();
// Update bubbles every frame for consistent collision detection
updateBubbles();
- // Update jump/fall state and position
- if (isJumping) {
- updateJump();
- } else if (isFalling) {
- updateFall(); // updateFall now handles landing and setting canJump=true
- }
- // Update bubbles (movement, off-screen checks, bubble-floor collision)
- updateBubbles(); // This function now handles its own internal optimizations
- // Update enemies and check dragon-enemy collision (less frequently)
- if (LK.ticks % 3 === 0) {
- // Reduced frequency slightly
- updateEnemiesMovement(); // This function handles enemy movement and dragon collision
- }
- // Check other collisions (bubble-related) - These happen inside updateBubbles now
- // updateBubbleCollisions(); // Removed, logic integrated into updateBubbles
- // Final check for game over state (if triggered by enemy collision)
- if (game.gameOverTriggered && !game.gameOverShowing) {
- game.gameOverShowing = true; // Prevent multiple triggers
- // Game over animation is already triggered in updateEnemiesMovement
- }
+ // Update enemy movement every frame for consistent movement
+ updateEnemiesMovement();
};
// Handle touch events for shooting bubbles
var lastShot = 0;
var lastClick = 0;
@@ -680,12 +616,41 @@
}
// Update last known position
enemy.lastX = enemy.x;
enemy.lastY = enemy.y;
- } //{50} // End of enemy processing loop
- // Dragon-enemy collision check is now inside the main enemy loop (lines 601-625), triggered immediately.
- // The redundant loop below is removed.
- } //{5r} // End of updateEnemiesMovement function
+ }
+ // Always check for collisions with the dragon for all enemies
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ if (!enemy.captured && dragon.intersects(enemy)) {
+ // Game over handling moved outside the loop to avoid duplicate calls
+ // Just mark for game over
+ if (!game.gameOverTriggered) {
+ game.gameOverTriggered = true;
+ // Play game over sound when the dragon dies
+ LK.getSound('gameover').play();
+ // Rotate the dragon 90 degrees
+ dragon.rotation = -3 * Math.PI * dragon.scale.x;
+ // Animate the dragon falling down - simplified tween with proper context
+ var dragonRef = dragon; // Create a strong reference to avoid context loss
+ // Use immediately invoked function to create closure
+ (function (dragonToTween) {
+ tween(dragonToTween, {
+ y: 2732 + dragonToTween.height,
+ tint: 0xFF0000
+ }, {
+ duration: 500,
+ easing: tween.linear,
+ onFinish: function onFinish() {
+ LK.showGameOver();
+ }
+ });
+ })(dragonRef);
+ }
+ break;
+ }
+ }
+ }
function updateBubbles() {
// Ensure bubbles array exists to prevent errors
if (!bubbles) {
bubbles = [];
@@ -697,225 +662,172 @@
if (!bubble) {
bubbles.splice(i, 1);
continue;
}
- // Call the bubble's update method to move it
- if (bubble.update) {
- bubble.update();
+ // Move bubble
+ bubble.x += bubble.speed;
+ // Remove bubbles that go off-screen
+ if (bubble.y < -50 || bubble.x < -50 || bubble.x > 2100) {
+ bubble.destroy();
+ bubbles.splice(i, 1);
+ continue; // Skip further checks for this bubble
}
- // Optimization: Check bubble-bubble intersections less frequently
- var bubbleDestroyed = false;
- if (LK.ticks % 3 === 0) {
- // Check only every 3 frames
- for (var j = i - 1; j >= 0; j--) {
- if (j >= bubbles.length) {
+ // Check for bubble-bubble intersections
+ for (var j = i - 1; j >= 0; j--) {
+ var otherBubble = bubbles[j];
+ if (!otherBubble) {
+ bubbles.splice(j, 1);
+ continue;
+ }
+ if (bubble.intersects(otherBubble)) {
+ // Create PoppedBubbles
+ var pop1 = game.addChild(new PoppedBubble());
+ pop1.x = bubble.x;
+ pop1.y = bubble.y;
+ var pop2 = game.addChild(new PoppedBubble());
+ pop2.x = otherBubble.x;
+ pop2.y = otherBubble.y;
+ // Destroy bubbles
+ bubble.destroy();
+ otherBubble.destroy();
+ // Remove from array
+ bubbles.splice(i, 1);
+ if (j < bubbles.length) {
+ bubbles.splice(j, 1);
+ }
+ // Play pop sound
+ LK.getSound('pop').play();
+ // Destroy PoppedBubbles after delay
+ LK.setTimeout(function () {
+ pop1.destroy();
+ pop2.destroy();
+ }, 500);
+ break; // Exit inner loop after collision
+ }
+ }
+ // Check for bubble-enemy collisions
+ if (bubble && !bubble.destroyed) {
+ // Check if bubble still exists
+ for (var k = enemies.length - 1; k >= 0; k--) {
+ var enemy = enemies[k];
+ if (!enemy || enemy.captured) {
continue;
- } // Safety check
- var otherBubble = bubbles[j];
- if (!otherBubble || !otherBubble.parent) {
- // Check if other bubble still exists
- // If otherBubble was already processed and removed in this loop iteration, skip
- if (j < bubbles.length) {
- bubbles.splice(j, 1);
- }
- continue;
}
- if (bubble.intersects(otherBubble)) {
- // Create PoppedBubbles
- var pop1 = game.addChild(new PoppedBubble());
- pop1.x = bubble.x;
- pop1.y = bubble.y;
- var pop2 = game.addChild(new PoppedBubble());
- pop2.x = otherBubble.x;
- pop2.y = otherBubble.y;
- // Safely destroy and remove bubbles
- var bubbleId = bubble.id; // Store id in case bubble reference becomes invalid
- var otherBubbleId = otherBubble.id;
+ if (bubble.intersects(enemy)) {
+ // Destroy the original bubble
bubble.destroy();
- otherBubble.destroy();
- // Remove from bubbles array by id or index, iterating backwards
- for (var k = bubbles.length - 1; k >= 0; k--) {
- if (bubbles[k].id === bubbleId || bubbles[k].id === otherBubbleId) {
- bubbles.splice(k, 1);
- }
- }
- // Play pop sound
+ bubbles.splice(i, 1);
+ // Create a new bubble as a child of the enemy
+ var newBubble = new CapturingBubble();
+ newBubble.x = 0; // Position relative to the enemy
+ newBubble.y = 0; // Position relative to the enemy
+ enemy.addChild(newBubble);
+ enemy.captured = true;
+ capturingBubbles.push(newBubble);
+ break; // Exit inner loop after collision
+ }
+ }
+ }
+ // Check for bubble-floor collisions
+ if (bubble && !bubble.destroyed) {
+ // Check if bubble still exists
+ for (var m = 0; m < floors.length; m++) {
+ if (bubble.intersects(floors[m])) {
+ var pop = game.addChild(new PoppedBubble());
+ pop.x = bubble.x;
+ pop.y = bubble.y;
+ bubble.destroy();
+ bubbles.splice(i, 1);
LK.getSound('pop').play();
- // Destroy PoppedBubbles later
LK.setTimeout(function () {
- if (pop1.parent) {
- pop1.destroy();
- }
- if (pop2.parent) {
- pop2.destroy();
- }
+ pop.destroy();
}, 500);
- bubbleDestroyed = true;
- // Exit inner loop as 'bubble' is gone
- break;
+ break; // Exit inner loop after collision
}
}
}
- // Skip further checks if bubble was destroyed in bubble-bubble collision
- if (bubbleDestroyed || !bubble.parent) {
- // Check parent as destroy might be async
- continue;
- }
- // Remove bubbles that go off-screen
- if (bubble.y < -50 || bubble.x < -50 || bubble.x > 2100) {
- bubble.destroy();
- if (i < bubbles.length) {
- bubbles.splice(i, 1);
- }
- }
- } // End of main bubble loop (i)
- // --- Collision Checks (Moved outside the main bubble loop for clarity/potential optimization) ---
- // Check for bubble-enemy collisions
- for (var i = enemies.length - 1; i >= 0; i--) {
- var enemy = enemies[i];
- if (!enemy || enemy.captured || !enemy.parent) {
- // Also check if enemy exists in scene
- continue;
- }
- for (var j = bubbles.length - 1; j >= 0; j--) {
- var bubble = bubbles[j];
- // Ensure bubble exists and hasn't been destroyed in this update cycle
- if (!bubble || !bubble.parent) {
- if (j < bubbles.length) {
- bubbles.splice(j, 1);
- } // Clean up missing bubbles
- continue;
- }
- if (bubble.intersects(enemy)) {
- // Destroy the original bubble
+ // Check for dragon-bubble collisions
+ if (bubble && !bubble.destroyed) {
+ // Check if bubble still exists
+ if (dragon.intersects(bubble)) {
+ var pop = game.addChild(new PoppedBubble());
+ pop.x = bubble.x;
+ pop.y = bubble.y;
bubble.destroy();
- bubbles.splice(j, 1);
- // Create a new bubble as a child of the enemy
- var newBubble = new CapturingBubble();
- newBubble.x = 0; // Position relative to the enemy
- newBubble.y = 0; // Position relative to the enemy
- enemy.addChild(newBubble);
- enemy.captured = true;
- capturingBubbles.push(newBubble);
- // Since bubble 'j' is gone, and enemy 'i' is captured,
- // we can break the inner loop and move to the next enemy
- break;
- }
- }
- }
- // Check if the dragon is intersecting a standard bubble
- for (var i = bubbles.length - 1; i >= 0; i--) {
- var bubble = bubbles[i];
- if (!bubble || !bubble.parent) {
- // Ensure bubble exists
- if (i < bubbles.length) {
bubbles.splice(i, 1);
+ LK.getSound('pop').play();
+ LK.setTimeout(function () {
+ pop.destroy();
+ }, 500);
}
- continue;
}
- if (dragon.intersects(bubble)) {
- var pop = game.addChild(new PoppedBubble());
- pop.x = bubble.x;
- pop.y = bubble.y;
- bubble.destroy();
- bubbles.splice(i, 1);
- LK.getSound('pop').play();
- LK.setTimeout(function () {
- if (pop.parent) {
- pop.destroy();
- }
- }, 500); //{6x} // Use safe destroy
- // Dragon can only pop one bubble per frame
- break;
- }
}
- // Process capturing bubbles (dragon collision and floating)
+ // Update capturing bubbles and check for dragon-capturing bubble collisions
for (var i = capturingBubbles.length - 1; i >= 0; i--) {
var capturingBubble = capturingBubbles[i];
- if (!capturingBubble || !capturingBubble.parent) {
- // Ensure bubble exists
- if (i < capturingBubbles.length) {
- capturingBubbles.splice(i, 1);
- }
+ if (!capturingBubble) {
+ capturingBubbles.splice(i, 1);
continue;
}
- var enemy = capturingBubble.parent; // Get the enemy parent
- // Check for dragon intersection first
+ var enemy = capturingBubble.parent;
+ if (enemy && enemy.captured && !enemy.floating) {
+ enemy.y -= 5; // Make the enemy float up more smoothly
+ }
+ // Check for dragon-capturing bubble collisions
if (dragon.intersects(capturingBubble)) {
- if (enemy && enemy.parent) {
- // Ensure enemy parent also exists
- var pop = game.addChild(new PoppedBubble());
- // Use enemy's global position for pop effect
- var enemyGlobalPos = enemy.parent.toGlobal(enemy.position);
- pop.x = enemyGlobalPos.x;
- pop.y = enemyGlobalPos.y;
- // Find enemy index to remove it
- var enemyIndex = enemies.indexOf(enemy);
- if (enemyIndex !== -1) {
- enemies.splice(enemyIndex, 1);
+ // Find and destroy the enemy that is the parent of the CapturingBubble
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var enemy = enemies[j];
+ if (!enemy) {
+ continue;
}
- enemy.destroy(); //{6N} // This also destroys the capturingBubble child
- capturingBubbles.splice(i, 1); // Remove from capturing array
- LK.getSound('pop').play();
- LK.setTimeout(function () {
- if (pop.parent) {
+ if (enemy.children && enemy.children.indexOf(capturingBubble) !== -1) {
+ // Create a PoppedBubble at the capturingBubble's position
+ var pop = game.addChild(new PoppedBubble());
+ pop.x = enemy.x;
+ pop.y = enemy.y;
+ // Destroy the enemy and capturingBubble
+ enemy.destroy();
+ enemies.splice(j, 1);
+ // Remove from capturing bubbles array
+ capturingBubbles.splice(i, 1);
+ // Play pop sound when a capturing bubble is popped
+ LK.getSound('pop').play();
+ // Destroy the PoppedBubble after 1 second
+ LK.setTimeout(function () {
pop.destroy();
- }
- }, 1000); // Use safe destroy
- // Since bubble 'i' and its enemy are gone, continue to next bubble
- continue;
- } else {
- // Enemy parent doesn't exist? Clean up bubble.
- capturingBubble.destroy();
- capturingBubbles.splice(i, 1);
- continue;
+ }, 1000);
+ break; // Exit inner loop after collision
+ }
}
}
- // Update floating behavior if not popped
- if (enemy && enemy.captured && !enemy.floating) {
- enemy.y -= 3; // Slightly reduced floating speed
- }
}
- } //{77} // End of updateBubbles function
+ }
function updateJump() {
if (isJumping) {
var jumpHeight = (dragon.y - jumpStartY) / 10;
dragon.y -= jumpHeight; // Move dragon upwards based on calculated jump height
// More efficient intersection check with early termination
- var didHitCeiling = false;
- var dragonX = dragon.x;
- var dragonTop = dragon.y - dragon.height / 2;
- var verticalThreshold = 50; // Check floors slightly above
- var horizontalThreshold = dragon.width * 1.5;
+ var dragonIntersectsFloor = false;
for (var i = 0; i < floors.length; i++) {
- var floor = floors[i];
- // Optimization: Only check floors vertically and horizontally close
- if (Math.abs(floor.y - dragonTop) < verticalThreshold + floor.height && Math.abs(floor.x - dragonX) < horizontalThreshold + floor.width / 2) {
- if (dragon.intersects(floor)) {
- var floorBottom = floor.y + floor.height / 2;
- // Check if hitting the bottom of a platform
- if (dragonTop <= floorBottom + 10) {
- // Allow slight overlap
- didHitCeiling = true;
- isJumping = false; // Stop jumping when hitting a ceiling
- isFalling = true; // Start falling when colliding with a floor
- canJump = false; // Disallow jumping again until the dragon hits a floor
- // Optional: Slightly push dragon down
- dragon.y = floorBottom + dragon.height / 2 + 5;
- break;
- }
+ if (dragon.intersects(floors[i])) {
+ dragonIntersectsFloor = true;
+ if (!dragon.lastWasIntersecting) {
+ isJumping = false; // Stop jumping
+ isFalling = true; // Start falling when colliding with a floor
+ canJump = false; // Disallow jumping again until the dragon hits a floor
+ dragon.y -= 25;
}
+ break;
}
}
- // Check if jump duration has exceeded 0.4 seconds OR hit ceiling
- if (didHitCeiling || Date.now() - jumpStartTime >= 400) {
+ // Check if jump duration has exceeded 0.4 seconds
+ if (Date.now() - jumpStartTime >= 400) {
isJumping = false;
- if (!didHitCeiling) {
- // Only start falling if max duration reached, not if ceiling hit (already falling)
- isFalling = true;
- }
+ isFalling = true;
}
- // Note: dragon.lastWasIntersecting is handled by updateFall now
+ // Update last known intersection state
+ dragon.lastWasIntersecting = dragonIntersectsFloor;
}
}
// BLOCKS
// Add a floor to the bottom of the screen
A version of this bubble but exploded
brick, brown color, pixel style. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
better wings, pixel style, more contrasted, more visible, blue color
a pixel clouds background. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a pixel clouds background, with mountains, full height full width Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a similar image. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
a pixel clouds background, with mountains, full height full width Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A popped blue bobble, pixel style, bubble booble arcade game inspired. In-Game asset. 2d. High contrast. No shadows
A bubble popping, pixel style, retro. In-Game asset. 2d. High contrast. No shadows