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 maximum 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;
// Removed update method since position is now handled directly in updateBubbles
});
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);
// Set a static bright color instead of cycling through rainbow colors
instructionsText.tint = 0x00AAFF; // Bright blue color that stands out
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;
var dragonX = dragon.x;
var dragonWidth = dragon.width;
// Only check floors that could be beneath the dragon based on X position
for (var i = 0; i < floors.length; i++) {
var floor = floors[i];
// Quick bounds check to skip distant floors
if (Math.abs(floor.x - dragonX) > dragonWidth / 2 + floor.width / 2) {
continue;
}
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
dragon.y += 20;
// Only check floors that are below the dragon's previous position
var isIntersecting = false;
var dragonX = dragon.x;
var dragonWidth = dragon.width;
for (var i = 0; i < floors.length; i++) {
var floor = floors[i];
// Quick bounds check to skip distant floors
if (Math.abs(floor.x - dragonX) > dragonWidth / 2 + floor.width / 2 || floor.y < lastY) {
continue;
}
// Check if dragon is intersecting with a floor
if (dragon.intersects(floor)) {
isIntersecting = true;
// Only stop falling if we weren't intersecting before (just collided)
if (!dragon.lastWasIntersecting || lastY < floor.y - floor.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 = floor.y - floor.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 optimized performance
game.update = function () {
// Handle game over animation for dragon without using tweens
if (dragon.gameOverAnimation) {
dragon.y += dragon.gameOverSpeed;
if (dragon.y > 2732 + dragon.height) {
LK.showGameOver();
return;
}
} else {
// Move dragon incrementally towards target x with improved movement
if (dragon.targetX !== undefined) {
var dx = dragon.targetX - dragon.x;
var increment = dx / 5; // Faster movement for better responsiveness
// Only move if the distance is significant
if (Math.abs(dx) > 1) {
dragon.x += increment;
// Adjust dragon's scale based on movement direction
dragon.scale.x = dx > 0 ? 1 : -1;
}
}
// Update last known position
dragon.lastX = dragon.x;
dragon.lastY = dragon.y;
// Only check floor standing if not already falling or jumping
if (!isFalling && !isJumping) {
if (!isStandingOnFloor()) {
isFalling = true;
}
}
// Update jumping and falling - these functions have efficient early returns
updateJump();
updateFall();
}
// Update enemy movement and bubble collisions
updateBubbles();
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() {
// Only process enemies that need updating to reduce iteration overhead
var capturedCount = 0;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (!enemy) {
continue;
}
if (enemy.captured) {
capturedCount++;
if (enemy.isMoving) {
enemy.isMoving = false;
enemy.floating = true;
enemy.floatSpeed = 5;
enemy.floatStartY = enemy.y;
} else if (enemy.floating) {
// Direct position update for floating enemies
enemy.y -= enemy.floatSpeed;
// Check if enemy has reached the target height
if (enemy.y <= 100) {
// Change tint when reaching the top
if (enemy.children && enemy.children[1]) {
enemy.children[1].tint = 0xbf5555;
}
}
}
} else {
// Initialize movement if not already moving
if (!enemy.isMoving && !enemy.movementInitialized) {
enemy.isMoving = true;
enemy.movementInitialized = true;
// Find platform bounds in a single pass
var platformY = enemy.y + 100;
var startX = 2048;
var endX = 0;
var foundPlatform = false;
for (var j = 0; j < floors.length; j++) {
var floor = floors[j];
if (Math.abs(floor.y - platformY) < 10 && floor.x > 0 && floor.x < 2048 - 50) {
foundPlatform = true;
if (floor.x < startX) {
startX = floor.x;
}
if (floor.x > endX) {
endX = floor.x;
}
}
}
// Ensure we have a valid range to move in
if (foundPlatform && 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;
enemy.moveSpeed = 3; // Pixels per frame
enemy.isMovingRight = true; // Start moving right
}
}
// Handle horizontal movement for non-captured enemies
if (enemy.isMoving && !enemy.captured) {
// Update movement direction and position
if (enemy.isMovingRight) {
enemy.x += enemy.moveSpeed;
if (enemy.x >= enemy.endX) {
enemy.isMovingRight = false;
}
} else {
enemy.x -= enemy.moveSpeed;
if (enemy.x <= enemy.startX) {
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)) {
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;
// Direct position and property updates for game over animation
dragon.gameOverAnimation = true;
dragon.gameOverSpeed = 15;
dragon.tint = 0xFF0000;
}
}
}
// Update last known position
enemy.lastX = enemy.x;
enemy.lastY = enemy.y;
}
// Check for level completion only once per update
if (capturedCount === enemies.length && 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
// Create level text just once
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();
}
}
}
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 position directly
bubble.x += bubble.speed;
// Remove bubbles that go off-screen with quick boundary check
if (bubble.y < -50 || bubble.x < -50 || bubble.x > 2100) {
bubble.destroy();
bubbles.splice(i, 1);
continue; // Skip further checks for this bubble
}
// Check all collision types in a single pass to avoid redundant intersection checks
var bubbleDestroyed = false;
// 1. Check bubble-bubble intersections first
for (var j = i - 1; j >= 0 && !bubbleDestroyed; j--) {
var otherBubble = bubbles[j];
if (!otherBubble) {
bubbles.splice(j, 1);
i--; // Adjust our index accordingly
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);
bubbleDestroyed = true;
break; // Exit inner loop after collision
}
}
// If the bubble was destroyed in a bubble-bubble collision, skip to next bubble
if (bubbleDestroyed) {
continue;
}
// 2. Check for bubble-enemy collisions
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);
bubbleDestroyed = true;
break; // Exit enemy collision check
}
}
// If the bubble was destroyed in an enemy collision, skip to next bubble
if (bubbleDestroyed) {
continue;
}
// 3. Check for bubble-floor collisions
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);
bubbleDestroyed = true;
break; // Exit floor collision check
}
}
// If the bubble was destroyed in a floor collision, skip to next bubble
if (bubbleDestroyed) {
continue;
}
// 4. Check for dragon-bubble collisions
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);
bubbleDestroyed = true;
}
}
// 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)) {
var enemyFound = false;
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);
enemyFound = true;
break; // Exit enemy search loop
}
}
// If enemy was found and handled, break out of capturing bubble loop
if (enemyFound) {
break;
}
}
}
}
function updateJump() {
if (isJumping) {
// Calculate jump height more efficiently
var jumpHeight = Math.max(1, (dragon.y - jumpStartY) / 10);
dragon.y -= jumpHeight; // Move dragon upwards based on calculated jump height
// Calculate elapsed time only once
var elapsed = Date.now() - jumpStartTime;
// End jump after time limit to avoid excess calculations
if (elapsed >= 400) {
isJumping = false;
isFalling = true;
return; // Skip collision detection if jump is already ending
}
// Fast checking for ceiling collision
for (var i = 0; i < floors.length; i++) {
var floor = floors[i];
// Only check floors above or near the dragon
if (floor.y < dragon.y + dragon.height && dragon.intersects(floor)) {
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; // Push down to avoid getting stuck
}
dragon.lastWasIntersecting = true;
return; // Exit early after collision
}
}
// Update last known intersection state
dragon.lastWasIntersecting = false;
}
}
// 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
@@ -5,9 +5,9 @@
/****
* Classes
****/
-// Class for Bubbles - optimized for performance
+// Class for Bubbles - optimized for maximum performance
var Bubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphics = self.attachAsset('bubble', {
anchorX: 0.5,
@@ -15,16 +15,9 @@
});
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
- };
+ // Removed update method since position is now handled directly in updateBubbles
});
var CapturingBubble = Container.expand(function () {
var self = Container.call(this);
var bubbleGraphics = self.attachAsset('bubble', {
@@ -133,18 +126,10 @@
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);
+// Set a static bright color instead of cycling through rainbow colors
+instructionsText.tint = 0x00AAFF; // Bright blue color that stands out
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,
@@ -334,10 +319,17 @@
LK.playMusic('music');
function isStandingOnFloor() {
// Store the dragon's position
var dragonBottom = dragon.y + dragon.height / 2;
+ var dragonX = dragon.x;
+ var dragonWidth = dragon.width;
+ // Only check floors that could be beneath the dragon based on X position
for (var i = 0; i < floors.length; i++) {
var floor = floors[i];
+ // Quick bounds check to skip distant floors
+ if (Math.abs(floor.x - dragonX) > dragonWidth / 2 + floor.width / 2) {
+ continue;
+ }
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;
@@ -348,22 +340,29 @@
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
+ // Move dragon downwards
dragon.y += 20;
- // Check for collisions after moving
+ // Only check floors that are below the dragon's previous position
var isIntersecting = false;
+ var dragonX = dragon.x;
+ var dragonWidth = dragon.width;
for (var i = 0; i < floors.length; i++) {
+ var floor = floors[i];
+ // Quick bounds check to skip distant floors
+ if (Math.abs(floor.x - dragonX) > dragonWidth / 2 + floor.width / 2 || floor.y < lastY) {
+ continue;
+ }
// Check if dragon is intersecting with a floor
- if (dragon.intersects(floors[i])) {
+ if (dragon.intersects(floor)) {
isIntersecting = true;
// Only stop falling if we weren't intersecting before (just collided)
- if (!dragon.lastWasIntersecting || lastY < floors[i].y - floors[i].height) {
+ if (!dragon.lastWasIntersecting || lastY < floor.y - floor.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
+ dragon.y = floor.y - floor.height * 1.5; // Align dragon to the top of the floor
break;
}
}
}
@@ -384,47 +383,44 @@
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
+ // Handle game updates with optimized performance
game.update = function () {
// Handle game over animation for dragon without using tweens
if (dragon.gameOverAnimation) {
dragon.y += dragon.gameOverSpeed;
if (dragon.y > 2732 + dragon.height) {
LK.showGameOver();
return;
}
- }
- // Move dragon incrementally towards target x with improved movement
- if (dragon.targetX !== undefined && !dragon.gameOverAnimation) {
- var increment = (dragon.targetX - dragon.x) / 5; // Faster movement for better responsiveness
- if (Math.abs(dragon.targetX - dragon.x) > 1) {
- dragon.x += increment;
+ } else {
+ // Move dragon incrementally towards target x with improved movement
+ if (dragon.targetX !== undefined) {
+ var dx = dragon.targetX - dragon.x;
+ var increment = dx / 5; // Faster movement for better responsiveness
+ // Only move if the distance is significant
+ if (Math.abs(dx) > 1) {
+ dragon.x += increment;
+ // Adjust dragon's scale based on movement direction
+ dragon.scale.x = dx > 0 ? 1 : -1;
+ }
}
// 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;
+ // Only check floor standing if not already falling or jumping
+ if (!isFalling && !isJumping) {
+ if (!isStandingOnFloor()) {
+ isFalling = true;
+ }
}
- }
- // Always check floor standing to prevent falling through platforms
- var standingOnFloor = isStandingOnFloor();
- if (!standingOnFloor && !isJumping && !dragon.gameOverAnimation) {
- isFalling = true;
- }
- // Always update jumping and falling if not in game over state
- if (!dragon.gameOverAnimation) {
+ // Update jumping and falling - these functions have efficient early returns
updateJump();
updateFall();
}
- // Update bubbles every frame for consistent collision detection
+ // Update enemy movement and bubble collisions
updateBubbles();
- // Update enemy movement every frame for consistent movement
updateEnemiesMovement();
};
// Handle touch events for shooting bubbles
var lastShot = 0;
@@ -451,15 +447,17 @@
}
lastClick = now;
};
function updateEnemiesMovement() {
- // Process all enemies every frame to ensure consistent movement
+ // Only process enemies that need updating to reduce iteration overhead
+ var capturedCount = 0;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (!enemy) {
continue;
}
if (enemy.captured) {
+ capturedCount++;
if (enemy.isMoving) {
enemy.isMoving = false;
enemy.floating = true;
enemy.floatSpeed = 5;
@@ -472,78 +470,41 @@
// Change tint when reaching the top
if (enemy.children && enemy.children[1]) {
enemy.children[1].tint = 0xbf5555;
}
- // Check if all enemies are captured
- 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();
- }
- }
}
}
} else {
// Initialize movement if not already moving
if (!enemy.isMoving && !enemy.movementInitialized) {
enemy.isMoving = true;
enemy.movementInitialized = true;
- // Find all platform floors for this enemy
- var platformFloors = [];
+ // Find platform bounds in a single pass
var platformY = enemy.y + 100;
+ var startX = 2048;
+ var endX = 0;
+ var foundPlatform = false;
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;
+ var floor = floors[j];
+ if (Math.abs(floor.y - platformY) < 10 && floor.x > 0 && floor.x < 2048 - 50) {
+ foundPlatform = true;
+ if (floor.x < startX) {
+ startX = floor.x;
}
- if (platformFloors[j].x > endX) {
- endX = platformFloors[j].x;
+ if (floor.x > endX) {
+ endX = floor.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;
- enemy.moveSpeed = 3; // Pixels per frame
- enemy.isMovingRight = true; // Start moving right
- enemy.moveTime = 0; // Track movement time
- }
}
+ // Ensure we have a valid range to move in
+ if (foundPlatform && 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;
+ enemy.moveSpeed = 3; // Pixels per frame
+ enemy.isMovingRight = true; // Start moving right
+ }
}
// Handle horizontal movement for non-captured enemies
if (enemy.isMoving && !enemy.captured) {
// Update movement direction and position
@@ -564,40 +525,54 @@
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;
- // Direct position and property updates for game over animation
- dragon.gameOverAnimation = true;
- dragon.gameOverSpeed = 15;
- dragon.tint = 0xFF0000;
+ 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;
+ // Direct position and property updates for game over animation
+ dragon.gameOverAnimation = true;
+ dragon.gameOverSpeed = 15;
+ dragon.tint = 0xFF0000;
+ }
}
}
// 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;
- // Direct position and property updates for game over
- dragon.gameOverAnimation = true;
- dragon.gameOverSpeed = 15;
- dragon.tint = 0xFF0000;
- }
- break;
+ // Check for level completion only once per update
+ if (capturedCount === enemies.length && 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
+ // Create level text just once
+ 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();
}
}
}
function updateBubbles() {
@@ -612,21 +587,24 @@
if (!bubble) {
bubbles.splice(i, 1);
continue;
}
- // Move bubble
+ // Move bubble position directly
bubble.x += bubble.speed;
- // Remove bubbles that go off-screen
+ // Remove bubbles that go off-screen with quick boundary check
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--) {
+ // Check all collision types in a single pass to avoid redundant intersection checks
+ var bubbleDestroyed = false;
+ // 1. Check bubble-bubble intersections first
+ for (var j = i - 1; j >= 0 && !bubbleDestroyed; j--) {
var otherBubble = bubbles[j];
if (!otherBubble) {
bubbles.splice(j, 1);
+ i--; // Adjust our index accordingly
continue;
}
if (bubble.intersects(otherBubble)) {
// Create PoppedBubbles
@@ -650,56 +628,44 @@
LK.setTimeout(function () {
pop1.destroy();
pop2.destroy();
}, 500);
+ bubbleDestroyed = true;
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
- }
- }
+ // If the bubble was destroyed in a bubble-bubble collision, skip to next bubble
+ if (bubbleDestroyed) {
+ continue;
}
- // 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
- }
+ // 2. Check for bubble-enemy collisions
+ 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);
+ bubbleDestroyed = true;
+ break; // Exit enemy collision check
+ }
}
- // Check for dragon-bubble collisions
- if (bubble && !bubble.destroyed) {
- // Check if bubble still exists
- if (dragon.intersects(bubble)) {
+ // If the bubble was destroyed in an enemy collision, skip to next bubble
+ if (bubbleDestroyed) {
+ continue;
+ }
+ // 3. Check for bubble-floor collisions
+ 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();
@@ -707,10 +673,29 @@
LK.getSound('pop').play();
LK.setTimeout(function () {
pop.destroy();
}, 500);
+ bubbleDestroyed = true;
+ break; // Exit floor collision check
}
}
+ // If the bubble was destroyed in a floor collision, skip to next bubble
+ if (bubbleDestroyed) {
+ continue;
+ }
+ // 4. Check for dragon-bubble collisions
+ 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);
+ bubbleDestroyed = true;
+ }
}
// Update capturing bubbles and check for dragon-capturing bubble collisions
for (var i = capturingBubbles.length - 1; i >= 0; i--) {
var capturingBubble = capturingBubbles[i];
@@ -723,9 +708,9 @@
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
+ var enemyFound = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (!enemy) {
continue;
@@ -745,39 +730,49 @@
// Destroy the PoppedBubble after 1 second
LK.setTimeout(function () {
pop.destroy();
}, 1000);
- break; // Exit inner loop after collision
+ enemyFound = true;
+ break; // Exit enemy search loop
}
}
+ // If enemy was found and handled, break out of capturing bubble loop
+ if (enemyFound) {
+ break;
+ }
}
}
}
function updateJump() {
if (isJumping) {
- var jumpHeight = (dragon.y - jumpStartY) / 10;
+ // Calculate jump height more efficiently
+ var jumpHeight = Math.max(1, (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;
+ // Calculate elapsed time only once
+ var elapsed = Date.now() - jumpStartTime;
+ // End jump after time limit to avoid excess calculations
+ if (elapsed >= 400) {
+ isJumping = false;
+ isFalling = true;
+ return; // Skip collision detection if jump is already ending
+ }
+ // Fast checking for ceiling collision
for (var i = 0; i < floors.length; i++) {
- if (dragon.intersects(floors[i])) {
- dragonIntersectsFloor = true;
+ var floor = floors[i];
+ // Only check floors above or near the dragon
+ if (floor.y < dragon.y + dragon.height && dragon.intersects(floor)) {
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;
+ dragon.y += 25; // Push down to avoid getting stuck
}
- break;
+ dragon.lastWasIntersecting = true;
+ return; // Exit early after collision
}
}
- // 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;
+ dragon.lastWasIntersecting = false;
}
}
// 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