/**** * 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 = -20; // Increased speed for much faster bubble movement 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 CapturedPoppedBubble = Container.expand(function () { var self = Container.call(this); var popGraphics = self.attachAsset('poppedBubbleEnemy', { anchorX: 0.5, anchorY: 0.5 }); }); 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; // Initially set bubble scale to 0.5 bubble.scale.x = 0.5; bubble.scale.y = 0.5; // If the dragon is looking right, the bubble should move to the right if (self.scale.x == 1) { bubble.speed = 50; } else { // If the dragon is looking left, the bubble should move to the left bubble.speed = -50; } game.addChild(bubble); bubbles.push(bubble); // Animate bubble scale from 0.5 to 1 over 0.5 seconds tween(bubble.scale, { x: 1, y: 1 }, { duration: 500, easing: tween.easeOut }); // 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 level = 1; // Initialize level variable in global scope 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, stroke: 0xFFFFFF, strokeThickness: 5, 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: 0xFFFFFF, align: "center", stroke: 0xFFFFFF, strokeThickness: 5, 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", stroke: 0xFFFFFF, strokeThickness: 5 }); 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; function restartGame() { level++; if (level > 5) { LK.showYouWin(); return; } 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 // Restart game with new platforms and enemies // 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(); addLevelText(); } 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 += 185; // 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(); } // Check every 5 seconds (300 frames at 60fps) if any enemies are still alive if (LK.ticks % 300 === 0) { if (enemies.length === 0) { restartGame(); } } }; // 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 // 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) { restartGame(); } } }); } } else if (!enemy.isMoving) { enemy.isMoving = true; // Use the stored platform for this enemy if available, otherwise find it if (!enemy.platform) { var platformFloors = floors.filter(function (floor) { return Math.abs(floor.y - (enemy.y + 100)) < 10 && floor.x > 0 && floor.x < 2048 - 50; }); // Check if we have platform floors if (platformFloors.length === 0) { enemy.isMoving = false; return; } // Store the platform for this enemy enemy.platform = platformFloors[0]; } // Use the pre-calculated platform boundaries for this enemy var startX = enemy.minX; var endX = enemy.maxX; 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.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 CapturedPoppedBubble()); 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 = 500; // 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(); addLevelText(); } 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('floorV', { anchorX: 0.5, anchorY: 0.5, x: 50, y: 15 * 100, height: 3000 }); game.addChild(leftFloor); floors.push(leftFloor); var rightFloor = LK.getAsset('floorV', { 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() * 1200) + 500; // Random length between 500-1000 var maxStartX = 2048 - platformLength - 50; // Max start X, ensuring platform stays in screen var minStartX = 50; // Min start X to avoid left margin collision var startX = minStartX + Math.random() * maxStartX; 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, 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 + platformLength / 2, y: platformYPositions[j] - 100, type: enemyType }); enemy.captured = false; // Store the reference to this enemy's platform enemy.platform = platform; // Store platform boundaries for this enemy enemy.minX = startX + enemy.width / 2; enemy.maxX = startX + platformLength - enemy.width / 2; 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; } function addLevelText() { var levelTextBackground = new Text2('LEVEL ' + level.toString(), { size: 210, fill: 0x000000, stroke: 0xFFFFFF, strokeThickness: 5 }); 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: 0xFFFF00 // Changed to bright white for maximum visibility }); 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
@@ -68,17 +68,28 @@
self.shootBubble = function () {
var bubble = new Bubble();
bubble.x = self.x + 200 * self.scaleX;
bubble.y = self.y - 5;
+ // Initially set bubble scale to 0.5
+ bubble.scale.x = 0.5;
+ bubble.scale.y = 0.5;
// If the dragon is looking right, the bubble should move to the right
if (self.scale.x == 1) {
- bubble.speed = 125;
+ bubble.speed = 50;
} else {
// If the dragon is looking left, the bubble should move to the left
- bubble.speed = -125;
+ bubble.speed = -50;
}
game.addChild(bubble);
bubbles.push(bubble);
+ // Animate bubble scale from 0.5 to 1 over 0.5 seconds
+ tween(bubble.scale, {
+ x: 1,
+ y: 1
+ }, {
+ duration: 500,
+ easing: tween.easeOut
+ });
// Play bubble sound when a bubble is shot
LK.getSound('bubble').play();
};
});
@@ -158,10 +169,12 @@
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,
+ fill: 0xFFFFFF,
align: "center",
+ stroke: 0xFFFFFF,
+ strokeThickness: 5,
font: "Comic Sans MS" // Adding a cool font and bold style
});
controlText.anchor.set(0.5, 0.5);
controlText.x = 2048 / 2;
@@ -195,9 +208,11 @@
dragonOnContainer.addChild(bubbleOnContainer);
var understoodButton = new Text2('Click anywhere to start', {
size: 150,
fill: 0x1570e0,
- align: "center"
+ align: "center",
+ stroke: 0xFFFFFF,
+ strokeThickness: 5
});
understoodButton.anchor.set(0.5, 0.5);
understoodButton.x = 2048 / 2;
understoodButton.y = 800;
@@ -414,9 +429,9 @@
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
+ dragon.y += 185; // 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 {
@@ -529,9 +544,9 @@
dragon.y - dragon.height * 0.75,
// Taller hit area top
hitBoxWidth,
// 50% wider hit area
- dragon.height * 1.5 // 50% taller hit area
+ dragon.height * 1 // 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
@@ -743,9 +758,9 @@
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 jumpDuration = 500; // 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
@@ -883,9 +898,11 @@
}
function addLevelText() {
var levelTextBackground = new Text2('LEVEL ' + level.toString(), {
size: 210,
- fill: 0x000000
+ fill: 0x000000,
+ stroke: 0xFFFFFF,
+ strokeThickness: 5
});
levelTextBackground.anchor.set(0.5, 0.5);
levelTextBackground.x = 2048 / 2;
levelTextBackground.y = 2732 / 2;
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