/****
* 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