Code edit (2 edits merged)
Please save this source code
User prompt
If a bubble is popped that had captured an enemy, show the poppedBubbleEnemy asset graphic. If not, the poppedBubble asset graphic.
User prompt
If a bubble is popped with an enemy inside, use instead the poppedBubbleEnemy
Code edit (4 edits merged)
Please save this source code
User prompt
The bubble speed should be muuuch faster
Code edit (2 edits merged)
Please save this source code
User prompt
The enemy movement is broken. You need to store which are the platforms on top of which each enemy is. Then get the maxX and minX of that platform: the enemy can only move from minX to maxX of that specific platform.
User prompt
For some reason the enemy on the third created platform goes out of range of the platform. Only that enemy, the one on the third platform.
Code edit (1 edits merged)
Please save this source code
User prompt
Remove enemy3
User prompt
Enemy3 goes out of the platform! Change its behaviour
User prompt
Enemy3 goes out of the platform toooo far away, like to the left margin of the screen
User prompt
For some reason enemy3 ends up going out of the platform?
User prompt
Ok the enemies are running outside the platforms. Please restrict their movement to their platforms.
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught ReferenceError: i is not defined' in or related to this line: 'var enemyType = 'enemy' + (i % 5 + 1); // Cycle through enemy1 to enemy5' Line Number: 906
User prompt
Please fix the bug: 'Uncaught ReferenceError: i is not defined' in or related to this line: 'var platform = LK.getAsset('floor', {' Line Number: 895
User prompt
platformLength should be a random length from 500 to 1000 but making sure it's inside the screen borders and not colliding with left margin or right margin floors.
Code edit (1 edits merged)
Please save this source code
Code edit (14 edits merged)
Please save this source code
User prompt
The dragon should fall much quicker
Code edit (3 edits merged)
Please save this source code
User prompt
Fix
Code edit (3 edits merged)
Please save this source code
User prompt
addDragon after addFloors and addPlatforms every time you start the game or a new level
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Class for Bubbles
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.update = function () {
self.x += self.speed;
// Check for intersection with any floor
for (var i = 0; i < floors.length; i++) {
if (self.intersects(floors[i])) {
// Create a PoppedBubble at the bubble's position
var pop = game.addChild(new PoppedBubble());
pop.x = self.x;
pop.y = self.y;
// Destroy the bubble
self.destroy();
bubbles.splice(bubbles.indexOf(self), 1);
// Destroy the PoppedBubble after 0.5 seconds
LK.setTimeout(function () {
pop.destroy();
}, 500);
break;
}
}
// Update last known positions
self.lastX = self.x;
self.lastY = self.y;
};
});
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
var Dragon = Container.expand(function () {
var self = Container.call(this);
self.dragonGraphics = self.attachAsset('dragon', {
anchorX: 0.5,
anchorY: 0.5
});
self.isIntersectingBubble = false; // Add a variable to track if the dragon is intersecting a bubble
self.shootBubble = function () {
var bubble = new Bubble();
bubble.x = self.x + 200 * self.scaleX;
bubble.y = self.y - 5;
// 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;
}
game.addChild(bubble);
bubbles.push(bubble);
// Play bubble sound when a bubble is shot
LK.getSound('bubble').play();
};
});
// Class for Pop
var PoppedBubble = Container.expand(function () {
var self = Container.call(this);
var popGraphics = self.attachAsset('poppedBubble', {
anchorX: 0.5,
anchorY: 0.5
});
});
/****
* 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 every 500ms
LK.setInterval(cycleRainbowColors, 500);
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();
};
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 = [];
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 = [];
// Destroy the existing dragon
dragon.destroy();
// Update background for current level
background.destroy();
var bgId = level <= 5 ? 'pixel_background_' + level.toString() : 'pixel_background_6';
background = LK.getAsset(bgId, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0.95
});
game.addChild(background);
// Important: Always call these in this specific order
addFloors();
addPlatforms();
addDragon();
}
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);
function _toConsumableArray2(r) {
return _arrayWithoutHoles2(r) || _iterableToArray2(r) || _unsupportedIterableToArray3(r) || _nonIterableSpread2();
}
function _nonIterableSpread2() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray3(r, a) {
if (r) {
if ("string" == typeof r) {
return _arrayLikeToArray3(r, a);
}
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray3(r, a) : void 0;
}
}
function _iterableToArray2(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) {
return Array.from(r);
}
}
function _arrayWithoutHoles2(r) {
if (Array.isArray(r)) {
return _arrayLikeToArray3(r);
}
}
function _arrayLikeToArray3(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) {
n[e] = r[e];
}
return n;
}
function _createForOfIteratorHelper(r, e) {
var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (!t) {
if (Array.isArray(r) || (t = _unsupportedIterableToArray2(r)) || e && r && "number" == typeof r.length) {
t && (r = t);
var _n = 0,
F = function F() {};
return {
s: F,
n: function n() {
return _n >= r.length ? {
done: !0
} : {
done: !1,
value: r[_n++]
};
},
e: function e(r) {
throw r;
},
f: F
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var o,
a = !0,
u = !1;
return {
s: function s() {
t = t.call(r);
},
n: function n() {
var r = t.next();
return a = r.done, r;
},
e: function e(r) {
u = !0, o = r;
},
f: function f() {
try {
a || null == t["return"] || t["return"]();
} finally {
if (u) {
throw o;
}
}
}
};
}
function _unsupportedIterableToArray2(r, a) {
if (r) {
if ("string" == typeof r) {
return _arrayLikeToArray2(r, a);
}
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray2(r, a) : void 0;
}
}
function _arrayLikeToArray2(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) {
n[e] = r[e];
}
return n;
}
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) {
return _arrayLikeToArray(r, a);
}
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) {
return Array.from(r);
}
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) {
return _arrayLikeToArray(r);
}
}
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) {
n[e] = r[e];
}
return n;
}
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.cubicInOut, tween.expoIn, tween.expoOut, tween.expoInOut, tween.sineIn, tween.sineOut, tween.sineInOut];
LK.playMusic('music');
function isStandingOnFloor() {
for (var i = 0; i < floors.length; i++) {
if (dragon.intersects(floors[i])) {
return true;
}
}
return false;
}
function updateFall() {
if (isFalling) {
// Save previous position before moving
var previousY = dragon.y;
dragon.y += 85; // Move dragon downwards at a faster speed for quicker falling
// Check for intersection with any floor - do collision detection on EVERY frame
var _iterator = _createForOfIteratorHelper(floors),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var floor = _step.value;
// Check if dragon is intersecting with a floor
if (dragon.intersects(floor)) {
isJumping = false; // Stop jumping
isFalling = false; // Stop falling when colliding with a floor
canJump = true; // Allow jumping again when the dragon hits a floor
// Position the dragon precisely on top of the floor with proper offset
dragon.y = floor.y - floor.height * 1.5; // Align dragon to the top of the floor
break;
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
// Update last known intersection state
dragon.lastWasIntersecting = floors.some(function (floor) {
return dragon.intersects(floor);
});
}
//<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
// Handle game updates
game.update = function () {
// Move dragon incrementally towards target x
if (dragon.targetX !== undefined) {
var increment = (dragon.targetX - dragon.x) / 10; // Move in 0.5 seconds assuming 60 FPS
if (dragon.targetX !== undefined && (increment > 0 && dragon.x < dragon.targetX || increment < 0 && dragon.x > dragon.targetX)) {
dragon.x += increment;
}
// Update last known position
dragon.lastX = dragon.x;
dragon.lastY = dragon.y; // Track lastY position
// Adjust dragon's scale based on targetX position
if (dragon.targetX < dragon.x) {
dragon.scale.x = -1;
} else {
dragon.scale.x = 1;
}
}
var standingOnFloor = isStandingOnFloor();
if (!standingOnFloor && !isJumping) {
isFalling = true;
}
/*if (standingOnFloor && dragon.wings) {
dragon.wings = false;
dragon.removeChild(dragon.dragonGraphics); // Remove the current dragon graphics
dragon.dragonGraphics = dragon.attachAsset('dragon', {
anchorX: 0.5,
anchorY: 0.5
});
dragon.addChild(dragon.dragonGraphics);
}*/
if (LK.ticks % 2 === 0) {
updateJump();
}
if (LK.ticks % 2 === 0) {
updateFall();
}
if (LK.ticks % 1 === 0) {
updateBubbles();
}
if (LK.ticks % 15 === 0) {
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
}
// Check if click is anywhere near the dragon - use more generous hit testing
// Create a larger hit area rectangle for the dragon with 1.5x the size
var hitWidth = Math.abs(dragon.dragonGraphics.width);
var dragonCenterX = dragon.x; // Dragon's center position
var hitBoxWidth = hitWidth * 1.5; // 50% wider hit area
// Calculate the rectangle's top-left corner position based on dragon's direction
var rectX = dragon.scale.x < 0 ? dragonCenterX - hitBoxWidth * 0.25 : dragonCenterX - hitBoxWidth * 0.75;
var dragonBounds = new Rectangle(rectX,
// Adjust rectangle position based on dragon direction
dragon.y - dragon.height * 0.75,
// Taller hit area top
hitBoxWidth,
// 50% wider hit area
dragon.height * 1.5 // 50% taller hit area
);
// Check if click point is within the dragon's bounds
if (dragonBounds.contains(x, y)) {
// Only shoot a bubble when clicking on or near the dragon
if (now - lastShot > 200) {
dragon.shootBubble();
lastShot = now;
}
}
lastClick = now;
};
function updateEnemiesMovement() {
enemies.forEach(function (enemy) {
if (enemy.captured) {
if (enemy.isMoving) {
tween.stop(enemy);
enemy.isMoving = false;
enemy.floating = true;
} else if (enemy.floating) {
tween(enemy, {
y: 100
}, {
duration: 5000,
easing: tween.linear,
onFinish: function onFinish() {
enemy.children[1].tint = 0xbf5555;
if (enemies.length === 0) {
if (level < 6) {
level++;
background.destroy(); // Remove the previous background
var bgId = level <= 5 ? 'pixel_background_' + level.toString() : 'pixel_background_6';
background = LK.getAsset(bgId, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0.95
});
game.addChild(background); // Add the new background
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);
// Restart game with new platforms and enemies
restartGame();
} else {
LK.showYouWin();
}
}
}
});
}
} else if (!enemy.isMoving) {
enemy.isMoving = true;
var platformFloors = floors.filter(function (floor) {
return floor.y === enemy.y + 100 && floor.x > 0 && floor.x < 2048 - 50;
});
var startX = Math.min.apply(Math, _toConsumableArray2(platformFloors.map(function (floor) {
return floor.x;
})));
var endX = Math.max.apply(Math, _toConsumableArray2(platformFloors.map(function (floor) {
return floor.x;
})));
// Calculate platform width to restrict enemy movement
var platformWidth = platformFloors.reduce(function (width, floor) {
return width + floor.width;
}, 0);
// Calculate precise boundaries for enemy movement
// We need to constrain the movement more strictly for enemy3
var enemyHalfWidth = enemy.width / 2;
var padding = enemy.type === 'enemy3' ? 200 : 50; // Increase padding for enemy3 significantly
// For enemy3, ensure we're much more restrictive with the boundaries
if (enemy.type === 'enemy3') {
// Keep enemy3 more centered on the platform
var platformCenter = (startX + endX) / 2;
var safeRadius = Math.min((endX - startX) / 4, 300); // Limit to 1/4 of platform width, max 300px
startX = Math.max(platformCenter - safeRadius, startX + 250); // Ensure minimum distance from platform start
endX = Math.min(platformCenter + safeRadius, endX - 250); // Ensure minimum distance from platform end
} else {
// Regular boundary calculation for other enemies
startX = Math.max(startX + enemyHalfWidth, startX + padding);
endX = Math.min(endX - enemyHalfWidth, endX - padding);
}
// Extra safety check - ensure enemies can't go beyond platform bounds
if (endX - startX < enemyHalfWidth * 2) {
// If the movement range is too small, just keep the enemy in the center
startX = (startX + endX) / 2 - enemyHalfWidth;
endX = startX + enemyHalfWidth * 2;
}
enemy.alpha = 0.75; // Apply alpha when starting to move
tween(enemy, {
x: endX
}, {
duration: Math.random() * 10000,
easing: behaviours[enemy.type],
onFinish: function onFinish() {
tween(enemy, {
x: startX
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
enemy.isMoving = false;
enemy.alpha = 1; // Restore alpha on finish
}
});
}
});
}
enemy.scale.x = enemy.lastX < enemy.x ? 1 : -1;
if (!enemy.captured && dragon.intersects(enemy)) {
// Play game over sound when the dragon dies
LK.getSound('gameover').play();
// Rotate the dragon 90 degrees left
dragon.rotation = -3 * Math.PI * dragon.scale.x;
// Animate the dragon falling down
tween(dragon, {
y: 2732 + dragon.height,
// Move dragon off the screen
tint: 0xFF0000
}, {
duration: 500,
// Duration of the fall
easing: tween.linear,
onFinish: function onFinish() {
// Show game over after the dragon has fallen
LK.showGameOver();
}
});
}
enemy.lastX = enemy.x;
enemy.lastY = enemy.y;
});
}
function updateBubbles() {
// Update bubbles
for (var i = bubbles.length - 1; i >= 0; i--) {
var bubble = bubbles[i];
if (!bubble) {
continue;
}
// Check for bubble-bubble intersections
for (var j = i - 1; j >= 0; j--) {
var otherBubble = bubbles[j];
if (!otherBubble) {
continue;
}
if (bubble.intersects(otherBubble)) {
// Create a PoppedBubble for each intersecting bubble
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 both bubbles
bubble.destroy();
otherBubble.destroy();
bubbles.splice(i, 1);
bubbles.splice(j, 1);
// Play pop sound when a bubble is popped
LK.getSound('pop').play();
// Destroy the PoppedBubbles after 0.5 seconds
LK.setTimeout(function () {
pop1.destroy();
pop2.destroy();
}, 500);
break;
}
}
if (!bubble) {
return;
}
if (bubble.y < -50) {
bubble.destroy();
bubbles.splice(i, 1);
}
}
// Check for bubble-enemy collisions
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
for (var j = bubbles.length - 1; j >= 0; j--) {
var bubble = bubbles[j];
if (bubble.intersects(enemy)) {
// Destroy the original bubble
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);
break;
}
}
}
// Check if the dragon is intersecting a bubble
for (var i = 0; i < bubbles.length; i++) {
if (dragon.intersects(bubbles[i])) {
// Create a PoppedBubble at the bubble's position
var pop = game.addChild(new PoppedBubble());
pop.x = bubbles[i].x;
pop.y = bubbles[i].y;
// Destroy the bubble
bubbles[i].destroy();
bubbles.splice(i, 1);
// Play pop sound when a bubble is popped
LK.getSound('pop').play();
// Destroy the PoppedBubble after 0.5 seconds
LK.setTimeout(function () {
pop.destroy();
}, 500);
break;
}
}
// Check if the dragon is intersecting a CapturingBubble
for (var i = capturingBubbles.length - 1; i >= 0; i--) {
var capturingBubble = capturingBubbles[i];
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.children.includes(capturingBubble)) {
// 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);
// Play pop sound when a capturing bubble is popped
LK.getSound('pop').play();
// Destroy the PoppedBubble after 2 seconds
LK.setTimeout(function () {
pop.destroy();
}, 1000);
break;
}
}
}
}
capturingBubbles.forEach(function (capturingBubble) {
var enemy = capturingBubble.parent;
if (enemy && !enemy.captured) {
enemy.y -= 150; // Make the enemy jump with the dragon
}
});
}
function updateJump() {
if (isJumping) {
// Calculate how far into the jump we are (0 to 1)
var jumpElapsed = Date.now() - jumpStartTime;
var jumpDuration = 200; // 200ms jump duration
var jumpProgress = Math.min(jumpElapsed / jumpDuration, 1);
// Calculate the position based on jumpStartY and current progress
var initialY = dragon.y; // Starting position
// Calculate maximum jump height based on click position
// The higher the click, the smaller the jump (limited by dragon's current position)
var maxJumpHeight = Math.min(dragon.y - jumpStartY, 500); // Cap maximum jump at 500px
var targetY = dragon.y - maxJumpHeight; // Target position based on click
var jumpDistance = initialY - targetY; // Total distance to cover
// Save previous position
var previousY = dragon.y;
// Calculate new Y position
dragon.y = initialY - jumpDistance * jumpProgress;
// Check for intersection with any floor - check EVERY floor
var intersectingFloor = null;
for (var i = 0; i < floors.length; i++) {
if (dragon.intersects(floors[i])) {
intersectingFloor = floors[i];
break;
}
}
if (intersectingFloor) {
isJumping = false; // Stop jumping
isFalling = false; // Don't start falling - we're already on a floor
canJump = true; // Allow jumping as we're on a floor
dragon.y = intersectingFloor.y - intersectingFloor.height * 1.5; // Align dragon to the top of the floor
}
// Check if jump duration has exceeded jump time
if (jumpProgress >= 1) {
isJumping = false;
isFalling = true;
}
}
// Update last known intersection state
dragon.lastWasIntersecting = floors.some(function (floor) {
return dragon.intersects(floor);
});
}
addFloors();
addDragon();
addPlatforms();
/* 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);
}
function addFloors() {
// BLOCKS
// Add a floor to the bottom of the screen - create 1 floor out of 5
floors = [];
var floor = LK.getAsset('floor', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 - 30,
width: 2048
});
game.addChild(floor);
floors.push(floor);
// Add continuous floor on the left margin of the screen - only every 5th floor
var leftFloor = LK.getAsset('floor', {
anchorX: 0.5,
anchorY: 0.5,
x: 50,
y: 15 * 100,
height: 3000
});
game.addChild(leftFloor);
floors.push(leftFloor);
var rightFloor = LK.getAsset('floor', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 40,
y: 15 * 100,
height: 3000
});
game.addChild(rightFloor);
floors.push(rightFloor);
}
// Define easing functions array for platform movement - referenced both here and in updateFall function
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.cubicInOut, tween.expoIn, tween.expoOut, tween.expoInOut, tween.sineIn, tween.sineOut, tween.sineInOut];
function addPlatforms() {
// Add random platforms with irregular heights and positions
var platformYPositions = [];
var distinctHeights = [2300, 1900, 1500, 1100, 700]; // Define 4-5 distinct heights
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() * (1000 - 500 + 1)) + 500; // Random length between 500-1000
var maxStartX = 2048 - platformLength - 200; // Max start X, ensuring platform stays in screen
var minStartX = platformLength + 200; // Min start X to avoid left margin collision
var startX = Math.floor(Math.random() * (maxStartX - minStartX + 1)) + minStartX; // Random start position within safe bounds
var startY = platformYPositions[j];
// Generate a random tint color for the platforms
var randomTint = Math.floor(Math.random() * 16777215);
var platform = LK.getAsset('floor', {
anchorX: 0.5,
anchorY: 0.5,
x: startX,
y: platformYPositions[j],
width: platformLength
});
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' + (j % 5 + 1); // Cycle through enemy1 to enemy5 using the loop variable j
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);
}
}
function addDragon() {
// Recreate the dragon and add it to the game
dragon = game.addChild(new Dragon());
// Reposition dragon at the bottom - place it on top of the floor
dragon.x = 1024; // Center horizontally
dragon.y = 2732 - 170; // Fallback position if no floor found
// Initialize important tracking properties
dragon.lastWasIntersecting = false;
dragon.lastX = dragon.x;
dragon.lastY = dragon.y;
} ===================================================================
--- original.js
+++ change.js
@@ -591,11 +591,11 @@
// For enemy3, ensure we're much more restrictive with the boundaries
if (enemy.type === 'enemy3') {
// Keep enemy3 more centered on the platform
var platformCenter = (startX + endX) / 2;
- var safeRadius = (endX - startX) / 3; // Limit to 1/3 of platform width
- startX = platformCenter - safeRadius;
- endX = platformCenter + safeRadius;
+ var safeRadius = Math.min((endX - startX) / 4, 300); // Limit to 1/4 of platform width, max 300px
+ startX = Math.max(platformCenter - safeRadius, startX + 250); // Ensure minimum distance from platform start
+ endX = Math.min(platformCenter + safeRadius, endX - 250); // Ensure minimum distance from platform end
} else {
// Regular boundary calculation for other enemies
startX = Math.max(startX + enemyHalfWidth, startX + padding);
endX = Math.min(endX - enemyHalfWidth, endX - padding);
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