/****
* Classes
****/
var BounceEffect = Container.expand(function (x, y, color) {
var self = Container.call(this);
self.x = x;
self.y = y;
var bounceGraphics = self.attachAsset('bounceEffect', {
anchorX: 0.5,
anchorY: 0.5
});
bounceGraphics.tint = color;
var duration = 30;
self._update_migrated = function () {
duration--;
bounceGraphics.scaleX += 0.1;
bounceGraphics.scaleY += 0.1;
bounceGraphics.alpha -= 0.033;
bounceGraphics.scaleX -= 0.01;
bounceGraphics.scaleY -= 0.01;
if (duration <= 0) {
self.destroy();
}
};
game.addChild(self);
});
var Challenge = Container.expand(function (color, amount, bounceLimit) {
var self = Container.call(this);
self.color = color;
self.amount = amount;
self.bounceLimit = bounceLimit;
self.remainingBounces = bounceLimit; // Initialize remainingBounces correctly
self.completed = false;
var obstacleIcon = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: color,
scaleX: 0.5,
scaleY: 0.5
});
obstacleIcon.x = 250;
obstacleIcon.y = 40;
var challengeText = new Text2('0/' + amount, {
size: 75,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 8,
anchorX: 0.5,
anchorY: 0.5
});
challengeText.x = 300;
challengeText.y -= 10;
self.addChild(obstacleIcon);
self.addChild(challengeText);
self.updateProgress = function () {
self.amount -= 1;
challengeText.setText(amount - self.amount + '/' + amount);
if (self.amount <= 0) {
console.log("Objective complete for challenge with color:", self.color);
self.completed = true;
if (currentChallenge.every(function (challenge) {
console.log("All objectives complete for current challenge set. Whole challenge complete.");
return challenge.completed;
})) {
if (gameMode === 'challenges') {
LK.setScore(LK.getScore() + 1);
}
hud.updateScore(LK.getScore());
showChallengeCompletePopup(self.color);
currentChallenge.forEach(function (challenge) {
hud.removeChild(challenge);
console.log("Destroying challenge with color:", challenge.color);
challenge.destroy();
});
currentChallenge = [];
hud.updateChallenges(currentChallenge);
self.destroy(); // Ensure the challenge container is deleted
resetGameToStartingPoint();
startNextChallenge();
} else {}
}
};
});
var CircularObstacle = Container.expand(function (starX, starY, radius, angleSpeed, initialAngle) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: getRandomTint()
});
self.angle = initialAngle || 0;
self.radius = radius;
self.angleSpeed = angleSpeed * 0.75;
self.starX = starX;
self.starY = starY;
self.updatePosition = function () {
self.x = self.starX + Math.cos(self.angle) * self.radius;
self.y = self.starY + Math.sin(self.angle) * self.radius;
self.angle += self.angleSpeed * 0.35;
obstacleGraphics.rotation += self.angleSpeed * 0.35;
};
self.moveDown = function (distance, dotY) {
self.starY += distance * getSpeedMultiplier(dotY);
};
self.updatePosition();
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudTypes = ['cloud1', 'cloud2', 'cloud3'];
var cloudType = cloudTypes[Math.floor(Math.random() * cloudTypes.length)];
var cloudGraphics = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3 // Make clouds even more transparent
});
self.speed = Math.random() * 0.5 + 0.25; // Random speed between 0.25 and 0.75
self.alpha = 0;
var fadeInDuration = 60; // Duration of the fade-in effect in frames
var fadeInFrame = 0;
var fadeInInterval = LK.setInterval(function () {
fadeInFrame++;
self.alpha += 1 / fadeInDuration;
if (fadeInFrame >= fadeInDuration) {
LK.clearInterval(fadeInInterval);
}
}, 1000 / 60);
self.direction = Math.random() < 0.5 ? 1 : -1; // Random direction
self._update_migrated = function () {
self.x += self.speed * self.direction;
if (self.x > 2048 + cloudGraphics.width / 2) {
self.x = -cloudGraphics.width / 2;
} else if (self.x < -cloudGraphics.width / 2) {
self.x = 2048 + cloudGraphics.width / 2;
}
if (self.y > 2732 + cloudGraphics.height / 2) {
self.y = -cloudGraphics.height / 2;
}
};
});
var Dot = Container.expand(function () {
var self = Container.call(this);
var dotGraphics = self.attachAsset('dot', {
anchorX: 0.5,
anchorY: 0.5
});
self.destroyed = false;
self.alpha = 0;
var fadeInDuration = 60; // Duration of the fade-in effect in frames
var fadeInFrame = 0;
var fadeInInterval = LK.setInterval(function () {
fadeInFrame++;
self.alpha += 1 / fadeInDuration;
if (fadeInFrame >= fadeInDuration) {
LK.clearInterval(fadeInInterval);
}
}, 1000 / 60);
self.velocityY = 0;
self.gravity = 0.7;
self.bounce = -15;
self._update_migrated = function () {
if (!dotBouncing) {
return;
}
var previousY = self.y;
self.velocityY += self.gravity;
if (self.velocityY > 0 && dotGraphics.scaleX < 1) {
dotGraphics.scaleX += 0.02;
dotGraphics.scaleY -= 0.02;
} else if (self.velocityY < 0 && dotGraphics.scaleX > 0.9) {
dotGraphics.scaleX -= 0.01;
dotGraphics.scaleY += 0.01;
}
self.y += self.velocityY;
if (!self.firstTouch && !self.intersects(hand)) {
self.y = 2732 - self.height / 2 - 500;
} else if (self.intersects(hand)) {
self.bounceUp();
} else if (self.y > 2232 - self.height / 2 && self.firstTouch && !self.firstStarDestroyed) {
self.velocityY = self.bounce;
} else if (self.y > 2832 && !self.destroyed) {
handleDotDestruction();
}
self.movedDistance = self.y - previousY;
};
self.bounceUp = function () {
if (!self.destroyed) {
self.velocityY = self.bounce;
dot.scale.x *= 0.8;
dot.scale.y = 1.02;
LK.setTimeout(function () {
dot.scale.x = 1;
dot.scale.y = 1;
}, 90);
LK.getSound('bounce').play();
if (!self.intersects(hand)) {
createBounceEffect(self.x, self.y, dotGraphics.tint);
}
self.firstTouch = true;
if (!self.firstStarDestroyed) {
self.firstStarDestroyed = true;
}
if (gameMode === 'challenges' && !self.intersects(hand)) {
if (!currentChallenge[0].completed) {
remainingBounces--;
console.log("Remaining bounces decremented to:", remainingBounces);
hud.remainingBouncesTxt.setText(remainingBounces.toString());
if (remainingBounces <= 0) {
handleDotDestruction();
}
}
}
}
};
self.inheritStarColor = function (star) {
dotGraphics.tint = star.children[0].tint;
};
});
var DotParticleEffect = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var particles = [];
var angleIncrement = Math.PI * 2 / 20;
var speed = 30;
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff].slice(0, CONFIG.numColors);
for (var i = 0; i < 20; i++) {
var particle = self.attachAsset('dotParticle', {
anchorX: 0.5,
anchorY: 0.5,
tint: colors[Math.floor(Math.random() * colors.length)]
});
particle.scaleX = particle.scaleY = 0.5;
particle.alpha = 1;
var angle = i * angleIncrement;
particle.vx = Math.cos(angle) * speed;
particle.vy = Math.sin(angle) * speed;
particles.push(particle);
}
self._update_migrated = function () {
for (var i = particles.length - 1; i >= 0; i--) {
particles[i].x += particles[i].vx;
particles[i].y += particles[i].vy;
particles[i].rotation += 0.1; // Rotate the particle
particles[i].alpha -= 0.0167;
if (particles[i].alpha <= 0) {
particles[i].destroy();
particles.splice(i, 1);
}
}
if (particles.length === 0) {
self.destroy();
}
};
game.addChild(self);
});
var HUD = Container.expand(function () {
var self = Container.call(this);
// Create background line for HUD
var backgroundLine = self.attachAsset('backgroundLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.5
});
backgroundLine.x = 2048 / 2 + 200;
backgroundLine.y = 75;
// Create score text
scoreTxt = new Text2('0', {
size: 200,
// Reduced size to fit within the HUD
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 8
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = 2048 - 200 + 80; // Adjusted position to fit within the HUD
scoreTxt.y = -10; // Adjusted position to fit within the HUD
self.addChild(scoreTxt);
// Create challenge level text
self.challengeLevelTxt = new Text2('LVL 0', {
size: 75,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 8
});
self.challengeLevelTxt.anchor.set(0, 0);
self.challengeLevelTxt.x = 320;
self.challengeLevelTxt.y = 80;
self.addChild(self.challengeLevelTxt);
// Create remaining bounces text
self.remainingBouncesIcon = self.attachAsset('dot', {
anchorX: 1,
anchorY: 0,
scaleX: 0.5,
scaleY: 0.5
});
self.remainingBouncesIcon.x = 2048 - 30 + 150;
self.remainingBouncesIcon.y = 40;
self.remainingBouncesIcon.visible = true; // Ensure the remaining bounces icon is always visible
self.addChild(self.remainingBouncesIcon);
self.remainingBouncesTxt = new Text2('0', {
size: 75,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 8
});
self.remainingBouncesTxt.anchor.set(1, 0);
self.remainingBouncesTxt.x = 2048 + 70 + 150;
self.remainingBouncesTxt.y = 30;
self.remainingBouncesTxt.visible = true; // Ensure the remaining bounces text is always visible
self.addChild(self.remainingBouncesTxt);
// Removed challenges container
self.updateScore = function (score) {
scoreTxt.setText(score.toString());
};
self.updateChallenges = function (challenges) {
var totalWidth = challenges.reduce(function (acc, challenge) {
return acc + challenge.width + 20; // 20px gap
}, -20); // Subtract the last gap
var startX = (2048 - totalWidth) / 2;
challenges.forEach(function (challenge, i) {
challenge.x = startX + i * (challenge.width + 20);
challenge.y = 40; // Ensure all challenges are aligned vertically
self.addChild(challenge);
});
// Keep the level text fixed in the initial spot
self.challengeLevelTxt.x = 320;
self.challengeLevelTxt.y = 30;
self.challengeLevelTxt.visible = true; // Ensure the level text is always visible
};
return self;
});
// Add Hand asset below the dot
var Hand = Container.expand(function () {
var self = Container.call(this);
var handGraphics = self.attachAsset('hand', {
anchorX: 0.5,
anchorY: 0,
alpha: 0.7
});
self.alpha = 0;
var fadeInDuration = 60; // Duration of the fade-in effect in frames
var fadeInFrame = 0;
var fadeInInterval = LK.setInterval(function () {
fadeInFrame++;
self.alpha += 1 / fadeInDuration;
if (fadeInFrame >= fadeInDuration) {
LK.clearInterval(fadeInInterval);
}
}, 1000 / 60);
self._update_migrated = function (distance) {
if (distance) {
self.y += distance;
}
};
});
var HandDestroyEffect = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var handGraphics = self.attachAsset('hand', {
anchorX: 0.5,
anchorY: 0
});
self._update_migrated = function () {
self.y += 10; // Move the hand downwards faster
if (self.y > 2732 + handGraphics.height / 2) {
// Check if the hand is off-screen
self.destroy();
}
};
game.addChild(self);
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
// Removed background
// Create Endless button using endless asset
var endlessButton = self.attachAsset('Endless', {
anchorX: 0.5,
anchorY: 0.5
});
endlessButton.x = 0;
endlessButton.y = 1200;
endlessButton.floatDirection = 1;
endlessButton.floatSpeed = 0.5;
endlessButton.floatRange = 10;
endlessButton.down = function () {
LK.getSound('button').play();
LK.getSound('bounce').play();
// LK.stopMusic();
fadeOutElements([gameTitle, endlessButton, challengesButton, howToPlayButton].concat(mainMenuClouds), function () {
startGame('endless');
});
};
endlessButton._update_migrated = function () {
endlessButton.y += endlessButton.floatSpeed * endlessButton.floatDirection;
if (endlessButton.y >= 1200 + endlessButton.floatRange || endlessButton.y <= 1200 - endlessButton.floatRange) {
endlessButton.floatDirection *= -1;
}
};
LK.on('tick', function () {
endlessButton._update_migrated();
});
// Create Challenges button using challenges asset
var challengesButton = self.attachAsset('Challenges', {
anchorX: 0.5,
anchorY: 0.5
});
challengesButton.x = 0;
challengesButton.y = 1450;
challengesButton.floatDirection = 1;
challengesButton.floatSpeed = 0.5;
challengesButton.floatRange = 10;
challengesButton.down = function () {
LK.getSound('button').play();
LK.getSound('bounce').play();
// LK.stopMusic();
fadeOutElements([gameTitle, endlessButton, challengesButton, howToPlayButton].concat(mainMenuClouds), function () {
startGame('challenges');
});
};
challengesButton._update_migrated = function () {
challengesButton.y += challengesButton.floatSpeed * challengesButton.floatDirection;
if (challengesButton.y >= 1450 + challengesButton.floatRange || challengesButton.y <= 1450 - challengesButton.floatRange) {
challengesButton.floatDirection *= -1;
}
};
LK.on('tick', function () {
challengesButton._update_migrated();
});
// Create game title using gametitle asset
var gameTitle = self.attachAsset('gametitle', {
anchorX: 0.5,
anchorY: 0.5
});
gameTitle.x = 0;
gameTitle.y = 600;
// self.addChild(background); // Removed undefined background reference
// Create How to Play button using a new asset
var howToPlayButton = new Text2('how to play', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
// Add border color
strokeThickness: 8,
// Add border thickness
anchorX: 0.5,
anchorY: 0.5,
align: 'center' // Center justify the text
});
howToPlayButton.x = -125;
howToPlayButton.y = 1700;
howToPlayButton.blinking = true;
howToPlayButton.blinkSpeed = 0.005;
howToPlayButton.blinkDirection = 1;
howToPlayButton.down = function () {
LK.getSound('button').play();
showHowToPlay();
};
howToPlayButton._update_migrated = function () {
if (howToPlayButton.blinking) {
howToPlayButton.alpha += howToPlayButton.blinkSpeed * howToPlayButton.blinkDirection;
if (howToPlayButton.alpha >= 1) {
howToPlayButton.alpha = 1;
howToPlayButton.blinkDirection = -1;
} else if (howToPlayButton.alpha <= 0.1) {
howToPlayButton.alpha = 0.1;
howToPlayButton.blinkDirection = 1;
}
}
};
LK.on('tick', function () {
howToPlayButton._update_migrated();
});
gameTitle.tiltDirection = 1;
gameTitle.tiltSpeed = 0.001;
gameTitle.maxTilt = 0.1;
gameTitle._update_migrated = function () {
gameTitle.rotation += gameTitle.tiltSpeed * gameTitle.tiltDirection;
if (gameTitle.rotation >= gameTitle.maxTilt || gameTitle.rotation <= -gameTitle.maxTilt) {
gameTitle.tiltDirection *= -1;
}
};
LK.on('tick', function () {
gameTitle._update_migrated();
});
// Add clouds to the main menu background
var mainMenuClouds = [];
for (var i = 0; i < 10; i++) {
var cloud = new MainMenuCloud();
cloud.x = Math.random() * 2048 - 2600;
var newY;
do {
newY = Math.random() * 2732;
} while (!isCloudPositionValid(newY, mainMenuClouds, 200)); // Ensure clouds are at least 200 pixels apart
cloud.y = newY;
mainMenuClouds.push(cloud);
self.addChild(cloud);
}
self.addChild(gameTitle);
self.addChild(endlessButton);
self.addChild(challengesButton);
self.addChild(howToPlayButton);
// Update clouds on the main menu background
LK.on('tick', function () {
for (var i = 0; i < mainMenuClouds.length; i++) {
mainMenuClouds[i]._update_migrated();
}
});
// Play game music after 2 seconds
LK.setTimeout(function () {
LK.playMusic('gamemusic');
}, 2000);
});
var MainMenuCloud = Container.expand(function () {
var self = Container.call(this);
var cloudTypes = ['cloud1', 'cloud2', 'cloud3'];
var cloudType = cloudTypes[Math.floor(Math.random() * cloudTypes.length)];
var cloudGraphics = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3 // Make clouds even more transparent
});
self.speed = Math.random() * 0.5 + 0.25; // Random speed between 0.25 and 0.75
self.direction = Math.random() < 0.5 ? 1 : -1; // Random direction
self._update_migrated = function () {
self.x += self.speed * self.direction;
if (self.x > 2048 + cloudGraphics.width / 2) {
self.x = -cloudGraphics.width / 2;
} else if (self.x < -cloudGraphics.width / 2) {
self.x = 2048 + cloudGraphics.width / 2;
}
if (self.y > 2732 + cloudGraphics.height / 2) {
self.y = -cloudGraphics.height / 2;
}
};
});
var ObstacleParticleEffect = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var particles = [];
var angleIncrement = Math.PI * 2 / 30;
var speed = 20;
var dotColor = dot.children[0].tint; // Get the current color of the dot
for (var i = 0; i < 30; i++) {
var particle = self.attachAsset('obstacleParticle', {
anchorX: 0.5,
anchorY: 0.5,
tint: dotColor
});
particle.scaleX = particle.scaleY = 0.5;
particle.alpha = 1;
var angle = i * angleIncrement;
particle.vx = Math.cos(angle) * speed;
particle.vy = Math.sin(angle) * speed;
particles.push(particle);
}
self._update_migrated = function () {
for (var i = particles.length - 1; i >= 0; i--) {
particles[i].x += particles[i].vx;
particles[i].y += particles[i].vy;
particles[i].rotation += 0.1; // Rotate the particle
particles[i].alpha -= 0.0167;
if (particles[i].alpha <= 0) {
particles[i].destroy();
particles.splice(i, 1);
}
}
if (particles.length === 0) {
self.destroy();
particles = [];
}
};
game.addChild(self);
});
var ObstacleScorePopup = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var scoreText = new Text2('+10', {
size: 100,
fill: "#ffffff",
anchorX: 0.5,
anchorY: 0.5
});
scoreText.x = -scoreText.width / 2;
scoreText.y = -scoreText.height / 2;
self.addChild(scoreText);
self.alpha = 1;
var duration = 120;
self._update_migrated = function () {
duration--;
self.y -= 2;
self.alpha -= 1 / 120;
if (duration <= 0) {
self.destroy();
}
};
game.addChild(self);
});
var OrbitLine = Container.expand(function (starX, starY, radius) {
var self = Container.call(this);
self.starX = starX;
self.starY = starY;
self.radius = radius;
var segments = 50;
var angleIncrement = Math.PI * 2 / segments;
for (var i = 0; i < segments; i++) {
var angle = i * angleIncrement;
var dot = self.attachAsset('smallObstacle', {
x: starX + Math.cos(angle) * radius,
y: starY + Math.sin(angle) * radius,
anchorX: 0.5,
anchorY: 0.5,
tint: [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff, 0xffa500][Math.floor(Math.random() * 5)]
});
if (i % 2 === 0) {
dot.alpha = 0;
}
}
self.moveDown = function (distance, dotY) {
var speedMultiplier = dotY < 1200 ? 3 : dotY < 1400 ? 2 : dotY < 2000 ? 1.3 : dotY < 2300 ? 1.2 : 1;
self.y += distance * speedMultiplier;
};
});
var ParticleEffect = Container.expand(function (x, y, color) {
var self = Container.call(this);
self.x = x;
self.y = y;
var particles = [];
for (var i = 0; i < 20; i++) {
var particle = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
particle.scaleX = particle.scaleY = Math.random() * 0.5 + 0.5;
particle.alpha = 0.7;
particle.vx = (Math.random() - 0.5) * 10;
particle.vy = (Math.random() - 0.5) * 10;
particles.push(particle);
}
self._update_migrated = function () {
for (var i = particles.length - 1; i >= 0; i--) {
particles[i].x += particles[i].vx;
particles[i].y += particles[i].vy;
particles[i].alpha -= 0.02;
if (particles[i].alpha <= 0) {
particles[i].destroy();
particles.splice(i, 1);
}
}
if (particles.length === 0) {
self.destroy();
}
};
game.addChild(self);
});
var ScorePopup = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var scoreText = new Text2('+' + (10 * (starCount + 1)).toString(), {
size: 100,
fill: "#ffffff",
anchorX: 0.5,
anchorY: 0.5
});
scoreText.x = -scoreText.width / 2;
scoreText.y = -scoreText.height / 2;
self.addChild(scoreText);
self.alpha = 1;
var duration = 120;
self._update_migrated = function () {
duration--;
self.y -= 2;
self.alpha -= 1 / 120;
if (duration <= 0) {
self.destroy();
}
};
game.addChild(self);
});
var Star = Container.expand(function (starNumber) {
var self = Container.call(this);
self.starNumber = starNumber;
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
tint: getRandomTint()
});
self.scaleDirection = 1;
self.scaleSpeed = 0.005;
self.minScale = 1;
self.maxScale = 1.2;
self.moveDown = function (distance, dotY) {
self.y += distance * getSpeedMultiplier(dotY);
if (self.y > 2732 - self.height / 2) {
self.y = -self.height / 2;
}
for (var i = 0; i < clouds.length; i++) {
clouds[i].y += distance * getSpeedMultiplier(dotY);
}
};
self.updateScale = function () {
if (self.scaleDirection === 1 && starGraphics.scale.x < self.maxScale) {
starGraphics.scale.x += self.scaleSpeed;
starGraphics.scale.y += self.scaleSpeed;
} else if (self.scaleDirection === -1 && starGraphics.scale.x > self.minScale) {
starGraphics.scale.x -= self.scaleSpeed;
starGraphics.scale.y -= self.scaleSpeed;
}
if (starGraphics.scale.x >= self.maxScale || starGraphics.scale.x <= self.minScale) {
self.scaleDirection *= -1;
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xD3D3D3 // Light grey color
});
/****
* Game Code
****/
function fadeOutElements(elements, callback) {
var duration = 60; // Duration of the fade-out effect in frames
var frame = 0;
var interval = LK.setInterval(function () {
frame++;
elements.forEach(function (element) {
element.alpha -= 1 / duration;
});
if (frame >= duration) {
LK.clearInterval(interval);
elements.forEach(function (element) {
element.destroy();
});
if (callback) {
callback();
}
}
}, 1000 / 60);
}
// Removed mainMenuBackground asset initialization
function createHandDestroyEffect() {
var effect = new HandDestroyEffect(hand.x, hand.y);
LK.on('tick', function () {
effect._update_migrated();
});
}
function destroyHand() {
if (hand) {
createHandDestroyEffect(hand.x, hand.y);
hand.destroy();
hand = null;
}
}
function isCloudPositionValid(newY, existingClouds, minDistance) {
for (var i = 0; i < existingClouds.length; i++) {
if (Math.abs(newY - existingClouds[i].y) < minDistance) {
return false;
}
}
return true;
}
var remainingBounces;
var clouds = [];
for (var i = 0; i < 5; i++) {
var cloud = new Cloud();
cloud.x = Math.random() * 2048;
var newY;
do {
newY = Math.random() * 2732;
} while (!isCloudPositionValid(newY, clouds, 200)); // Ensure clouds are at least 200 pixels apart
cloud.y = newY;
clouds.push(cloud);
game.addChildAt(cloud, 0); // Add clouds behind other elements
}
function showHowToPlay() {
var howToPlayScreen = new Container({
width: 2048,
height: 2732,
alpha: 0.5
});
var background = howToPlayScreen.attachAsset('mainMenuBackground', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
width: 2048,
height: 2732
});
background.x = 2048 / 4;
background.y = 2732 / 2;
var endlessModeText = new Text2('Endless:\n\n• Tap to bounce!\n• Collect stars to score points and change color!\n• Avoid different colored obstacles! \n•. Destroy same colored obstacles to clear the path and get extra points!', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
// Add border color
strokeThickness: 8,
// Add border thickness
anchorX: 0.5,
anchorY: 0.5,
align: 'left',
wordWrap: true,
wordWrapWidth: 900
});
endlessModeText.x = 2048 / 4 - 900;
endlessModeText.y = 2732 / 2 - 900;
var challengesText = new Text2('Challenges:\n\n• Complete objectives by destroying obstacles! \n• Keep an eye on your remaining bounces! \n• Reach the higher level possible!', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
// Add border color
strokeThickness: 8,
// Add border thickness
anchorX: 0.5,
anchorY: 0.5,
align: 'left',
wordWrap: true,
wordWrapWidth: 900
});
challengesText.x = 2048 / 4 - 900;
challengesText.y = 2732 / 2 - 300;
var backButton = new Text2('Back', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
// Add border color
strokeThickness: 8,
// Add border thickness
anchorX: 0.5,
anchorY: 0.5
});
backButton.x = 2048 / 4;
backButton.y = 2732 - 200;
backButton.down = function () {
howToPlayScreen.destroy();
};
howToPlayScreen.addChild(background);
howToPlayScreen.addChild(endlessModeText);
howToPlayScreen.addChild(challengesText);
howToPlayScreen.addChild(backButton);
// Add event listener to close overlay when screen is touched
howToPlayScreen.down = function () {
howToPlayScreen.destroy();
};
LK.gui.top.addChild(howToPlayScreen);
}
function isValidStar(star) {
return star && star.children && star.children[0] && typeof star.children[0].tint !== 'undefined' && star.y !== null && typeof star.y !== 'undefined';
}
function resetGameToStartingPoint() {
// Destroy all existing stars, obstacles, particles from ObstacleParticleEffect, and the dot
stars.forEach(function (star) {
star.destroy();
});
stars = [];
obstacles.forEach(function (obstacle) {
if (obstacle instanceof ObstacleParticleEffect) {
obstacle.destroy();
}
obstacle.destroy();
});
obstacles = [];
if (dot) {
dot.destroy();
dot = null;
}
remainingBounces = challenges[currentChallengeIndex].remainingBounces;
console.log("Remaining bounces reset to initial value:", remainingBounces);
// Reset star count
starCount = 0;
// Add initial star
var star = game.addChildAt(new Star(), 1);
star.x = 2048 / 2;
star.y = 2732 / 2 - 500;
stars.push(star);
// Add initial dot
if (!dot) {
dot = game.addChild(new Dot());
dot.x = 2048 / 2;
dot.y = 2732 - dot.height / 2 - 200;
dotBouncing = true;
}
if (!hand) {
createHand();
}
handMoved = false;
// Add initial orbit line
var orbitLine = game.addChildAt(new OrbitLine(star.x, star.y, 300), 0);
obstacles.push(orbitLine);
// Add initial circular obstacle
var starX = 2048 / 2;
var starY = 2732 / 2 - 500;
var radius = 300;
var angleSpeed = 0.05;
var obstacle = new CircularObstacle(starX, starY, radius, angleSpeed);
game.addChildAt(obstacle, 2);
obstacles.push(obstacle);
// Check if the first star has at least one obstacle, if not, create it
if (obstacles.length === 0) {
var newObstacle = new CircularObstacle(starX, starY, radius, angleSpeed);
game.addChildAt(newObstacle, 1);
obstacles.push(newObstacle);
}
}
// Ensure HUD is still over the rest of the elements
game.addChild(hud);
var CONFIG = {
numColors: 2 // Default number of colors, can be set between 2 and 5
};
var gameMode = 'challenges'; // Default game mode
var mainMenu = new MainMenu();
LK.gui.top.addChild(mainMenu);
var scoreTxt;
var hud = new HUD();
hud.visible = false; // Hide HUD on game start
game.addChild(hud);
function getRandomTint() {
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff].slice(0, CONFIG.numColors);
return colors[Math.floor(Math.random() * Math.min(CONFIG.numColors, colors.length))];
}
function showChallengeCompletePopup(color) {
var successAssets = ['success', 'success2', 'success3'];
var randomSuccessAsset = successAssets[Math.floor(Math.random() * successAssets.length)];
var challengeCompletePopup = LK.getAsset(randomSuccessAsset, {
anchorX: 0.5,
anchorY: 0.5,
tint: color,
alpha: 0
});
challengeCompletePopup.x = 2048 / 2;
challengeCompletePopup.y = 2732 / 2;
game.addChild(challengeCompletePopup);
var animationDuration = 120;
var animationFrame = 0;
var animationInterval = LK.setInterval(function () {
if (animationFrame < animationDuration / 2) {
if (animationFrame === 0) {
challengeCompletePopup.alpha = 1;
}
challengeCompletePopup.scaleX = challengeCompletePopup.scaleY = 1 + 0.5 * (animationFrame / (animationDuration / 2));
} else {
challengeCompletePopup.alpha = 1 - (animationFrame - animationDuration / 2) / (animationDuration / 2);
challengeCompletePopup.scaleX = challengeCompletePopup.scaleY = 1.5 - 0.5 * (animationFrame - animationDuration / 2) / (animationDuration / 2);
}
animationFrame++;
if (animationFrame >= animationDuration) {
LK.clearInterval(animationInterval);
challengeCompletePopup.destroy();
}
}, 1000 / 60);
}
function getStarColor(starNumber) {
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff].slice(0, CONFIG.numColors);
return colors[starNumber % Math.min(CONFIG.numColors, colors.length)];
}
function getSpeedMultiplier(dotY) {
if (dotY < 1200) {
return 3;
}
if (dotY < 1400) {
return 2;
}
if (dotY < 2000) {
return 1.3;
}
return 1.2;
}
function handleDotDestruction() {
createDotParticleEffect(dot.x, dot.y);
LK.getSound('explosion').play();
dot.destroyed = true;
dot.destroy();
LK.setTimeout(function () {
remainingBounces = challenges[currentChallengeIndex].remainingBounces;
console.log("Remaining bounces reset due to dot destruction:", remainingBounces);
LK.stopMusic();
LK.showGameOver();
}, 1000);
}
function createBounceEffect(x, y, color) {
var effect = new BounceEffect(x, y + 80, color); // Adjust y position to start from a little more lower on the ball
LK.on('tick', function () {
// Ensure HUD is on top of everything
if (game.children.indexOf(hud) !== game.children.length - 1) {
game.addChild(hud);
}
effect._update_migrated();
});
}
var shrinkFrame = 0;
var shrinkDuration = 60;
function startGame(mode) {
gameMode = mode;
hud.visible = true; // Show HUD when a game mode is selected
if (!dot) {
dot = game.addChild(new Dot());
dot.x = 2048 / 2;
dot.y = 2732 - dot.height / 2 - 200;
dotBouncing = true;
}
if (!hand) {
hand = new Hand();
game.addChild(hand);
hand.x = dot.x;
hand.y = dot.y + dot.height / 2;
}
// Ensure obstacles are always on a higher layer than orbit lines
for (var i = 0; i < obstacles.length; i++) {
if (obstacles[i] instanceof CircularObstacle) {
var obstacleIndex = game.children.indexOf(obstacles[i]);
var orbitLineIndex = game.children.indexOf(orbitLine);
if (obstacleIndex < orbitLineIndex) {
game.setChildIndex(obstacles[i], orbitLineIndex + 1);
}
}
}
if (mode === 'endless') {
CONFIG.numColors = 5;
// Start endless mode
// Add your endless mode initialization code here
hud.removeChild(hud.children[0]); // Remove HUD background
hud.challengeLevelTxt.visible = false; // Hide level text in endless mode
hud.remainingBouncesIcon.visible = false; // Hide remaining bounces icon in endless mode
hud.remainingBouncesTxt.visible = false; // Hide remaining bounces text in endless mode
scoreTxt.x -= 100; // Move score text 100 pixels to the left
scoreTxt.size *= 2; // Double the size of the score text
scoreTxt.visible = true; // Show score text in endless mode
} else if (mode === 'challenges') {
CONFIG.numColors = 2;
// Start challenges mode
hud.challengeLevelTxt.visible = true; // Show level text in challenge mode
hud.remainingBouncesIcon.visible = true; // Show remaining bounces icon in challenge mode
hud.remainingBouncesTxt.visible = true; // Show remaining bounces text in challenge mode
scoreTxt.visible = false; // Hide score text in challenge mode
console.log("Remaining bounces reset for new game mode.");
startNextChallenge();
}
}
// Pregame screen removed
var challenges = [{
id: 1,
numColors: 2,
remainingBounces: 30,
obstacles: [1]
}, {
id: 2,
numColors: 2,
remainingBounces: 40,
obstacles: [1, 1]
}, {
id: 3,
numColors: 2,
remainingBounces: 50,
obstacles: [2, 2]
}, {
id: 4,
numColors: 3,
remainingBounces: 50,
obstacles: [1, 1, 1]
}, {
id: 5,
numColors: 3,
remainingBounces: 60,
obstacles: [3, 2, 1]
}, {
id: 6,
numColors: 3,
remainingBounces: 70,
obstacles: [2, 2, 2]
}, {
id: 7,
numColors: 3,
remainingBounces: 80,
obstacles: [3, 3, 3]
}, {
id: 8,
numColors: 4,
remainingBounces: 70,
obstacles: [1, 1, 1, 1]
}, {
id: 9,
numColors: 4,
remainingBounces: 80,
obstacles: [1, 2, 3, 4]
}, {
id: 10,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 11,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 12,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 13,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 14,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 15,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}];
var currentChallengeIndex = 0;
var currentChallenge = null;
function startNextChallenge() {
if (gameMode === 'endless') {
return;
}
if (currentChallengeIndex < challenges.length) {
console.log("Starting next challenge with index:", currentChallengeIndex);
// Clear previous challenge obstacles
if (currentChallenge) {
currentChallenge.forEach(function (challenge) {
hud.removeChild(challenge);
challenge.destroy();
});
currentChallenge = [];
hud.updateChallenges(currentChallenge);
}
// Clear the challenges container
hud.children.forEach(function (child) {
if (child instanceof Challenge) {
hud.removeChild(child);
child.destroy();
}
});
// Clear the challenges container
hud.children.forEach(function (child) {
if (child instanceof Challenge) {
hud.removeChild(child);
child.destroy();
}
});
CONFIG.numColors = challenges[currentChallengeIndex].numColors;
var challengeData = challenges[currentChallengeIndex];
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff, 0xffa500].slice(0, CONFIG.numColors);
currentChallenge = [];
challengeData.obstacles.forEach(function (amount, i) {
var challengeColor = colors[i % colors.length];
var challenge = new Challenge(challengeColor, amount, challengeData.remainingBounces);
currentChallenge.push(challenge);
game.addChildAt(challenge, 2);
});
bounceCount = 0;
var totalWidth = currentChallenge.reduce(function (acc, challenge) {
return acc + challenge.width + 20; // 20px gap
}, -20); // Subtract the last gap
hud.updateChallenges(currentChallenge);
hud.challengeLevelTxt.setText('LVL ' + currentChallengeIndex);
hud.updateScore(LK.getScore()); // Ensure score is updated in the HUD
remainingBounces = challengeData.remainingBounces;
hud.remainingBouncesTxt.setText(remainingBounces.toString()); // Reset remaining bounces text
console.log("Remaining bounces reset to:", remainingBounces);
// Ensure HUD is still over the rest of the elements
if (hud.y < 0) {
hud.y = 0;
}
if (hud.x < 0) {
hud.x = 0;
}
if (hud.x + hud.width > 2048) {
hud.x = 2048 - hud.width;
}
if (hud.y + hud.height > 2732) {
hud.y = 2732 - hud.height;
}
}
currentChallengeIndex++;
}
// startNextChallenge(); // Removed initial call to startNextChallenge
function createObstacleParticleEffect(x, y) {
var effect = new ObstacleParticleEffect(x, y);
LK.on('tick', function () {
effect._update_migrated();
});
}
function changeStarColor(star) {
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff].slice(0, CONFIG.numColors);
var currentColorIndex = colors.indexOf(star.children[0].tint);
var nextColorIndex = (currentColorIndex + 1) % Math.min(CONFIG.numColors, colors.length);
star.children[0].tint = colors[nextColorIndex];
}
function updateStarColors() {
for (var i = 0; i < stars.length; i++) {
changeStarColor(stars[i]);
}
}
LK.setInterval(updateStarColors, 2000);
var starCount = 0;
// Initialize the offscreen threshold for destroying obstacles
var offscreenThreshold = 2732 + 1000;
function createParticleEffect(x, y, color) {
var effect = new ParticleEffect(x, y, color);
LK.on('tick', function () {
effect._update_migrated();
});
}
function createDotParticleEffect(x, y) {
var effect = new DotParticleEffect(x, y);
LK.on('tick', function () {
effect._update_migrated();
});
}
var obstacles = [];
function updateObstacles() {
var obstacleCount = 5 + starCount;
while (obstacles.length < obstacleCount) {
var obstacle = game.addChildAt(new Obstacle(), game.children.length - 1); // Ensure obstacle is in front of clouds
obstacle.x = obstacle.direction === 1 ? -obstacle.width / 2 : 2048 + obstacle.width / 2;
obstacle.y = Math.random() * (2732 - obstacle.height) + obstacle.height / 2;
obstacles.push(obstacle);
}
// No longer move clouds when a star is destroyed
}
// Removed duplicate score text initialization and addition to the screen
game.on('down', function (x, y, obj) {
if (dot) {
dot.bounceUp();
}
});
var stars = [];
var star = game.addChildAt(new Star(), 1);
star.x = 2048 / 2;
star.y = 2732 / 2 - 500;
stars.push(star);
LK.setInterval(function () {
changeStarColor(star);
}, 1000); // Initialize star with a random color from the obstacles
// Add dotted orbit for the first star
var orbitLine = game.addChild(new OrbitLine(star.x, star.y, 300));
obstacles.push(orbitLine);
function spawnInitialObstacles() {
var starX = 2048 / 2;
var starY = 2732 / 2 - 500;
var radius = 300;
var angleSpeed = 0.05;
var obstacle = new CircularObstacle(starX, starY, radius, angleSpeed);
game.addChildAt(obstacle, game.children.length - 1); // Ensure obstacle is in front of clouds
obstacles.push(obstacle);
game.setChildIndex(star, game.children.length - 1); // Ensure star is in front of clouds
// No additional obstacles for the first star
}
spawnInitialObstacles();
game.addChild(hud);
LK.on('tick', function () {
if (dot) {
dot._update_migrated();
}
for (var i = 0; i < obstacles.length; i++) {
if (obstacles[i] instanceof CircularObstacle) {
obstacles[i].updatePosition();
} else {
if (typeof obstacles[i]._move_migrated === 'function') {
obstacles[i]._move_migrated();
}
}
if (dot && dot.y < 2300 && dot.movedDistance < 0) {
obstacles[i].moveDown(-dot.movedDistance, dot.y);
}
if (dot && dot.intersects && obstacles[i] && dot.intersects(obstacles[i]) && !(obstacles[i] instanceof OrbitLine) && dot !== null && obstacles[i] !== null && typeof dot.intersects === 'function') {
if (dot.children[0].tint === obstacles[i].children[0].tint) {
createObstacleParticleEffect(obstacles[i].x, obstacles[i].y);
if (gameMode === 'endless') {
if (gameMode === 'endless') {
LK.setScore(LK.getScore() + 10);
} else if (gameMode === 'challenges') {
// Do not display points addition in challenge mode
}
}
hud.updateScore(LK.getScore());
if (gameMode === 'endless') {
var obstacleScorePopup = new ObstacleScorePopup(obstacles[i].x, obstacles[i].y);
LK.on('tick', function () {
obstacleScorePopup._update_migrated();
});
}
LK.getSound('obstacle').play();
// Update challenge progress before destroying the obstacle
if (currentChallenge) {
for (var j = 0; j < currentChallenge.length; j++) {
if (obstacles[i].children[0].tint === currentChallenge[j].color) {
currentChallenge[j].updateProgress();
if (currentChallenge[j].completed) {
currentChallenge.splice(j, 1);
if (currentChallenge.length === 0) {
startNextChallenge();
}
}
break;
}
}
}
if (obstacles[i]) {
obstacles[i].destroy();
}
obstacles.splice(i, 1);
} else {
if (!dot.destroyed) {
createDotParticleEffect(dot.x, dot.y);
LK.getSound('explosion').play();
dot.destroyed = true;
}
dot.destroy();
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
} else if (obstacles[i] && obstacles[i].y > offscreenThreshold) {
if (obstacles[i] && typeof obstacles[i].destroy === 'function') {
obstacles[i].destroy();
}
obstacles.splice(i, 1);
}
}
for (var j = stars.length - 1; j >= 0; j--) {
if (!dot || !stars[j]) {
continue;
}
stars[j].updateScale();
if (dot && dot.intersects && stars[j] && isValidStar(stars[j]) && dot.intersects(stars[j]) && dot.y != null && stars[j].y != null && typeof dot.intersects === 'function' && dot.children && dot.children[0] && dot.children[0].y != null && stars[j].children && stars[j].children[0]) {
destroyHand();
dot.inheritStarColor(stars[j]);
if (gameMode === 'endless') {
LK.setScore(LK.getScore() + 10 * (starCount + 1));
} else if (gameMode === 'challenges') {
// Do not display points addition in challenge mode
}
hud.updateScore(LK.getScore());
var oldStarY = stars[j].y;
createParticleEffect(stars[j].x, stars[j].y, stars[j].children[0].tint);
LK.getSound('star').play();
if (gameMode === 'endless') {
var scorePopup = new ScorePopup(stars[j].x, stars[j].y);
LK.on('tick', function () {
scorePopup._update_migrated();
});
}
stars[j].destroy();
stars.splice(j, 1);
starCount += 1;
var newStar = game.addChildAt(new Star(), 1);
game.setChildIndex(newStar, game.children.length - 1); // Ensure new star is in front of clouds
newStar.x = 2048 / 2;
var additionalYOffset = starCount > 1 ? (starCount - 1) * 200 : 0;
newStar.y = oldStarY - 2000 - additionalYOffset;
// Create new clouds if needed when a star is destroyed
while (clouds.length < 5) {
var cloud = new Cloud();
cloud.x = Math.random() * 2048;
var newY;
do {
newY = Math.random() * 2732;
} while (!isCloudPositionValid(newY, clouds, 200)); // Ensure clouds are at least 200 pixels apart
cloud.y = newY;
clouds.push(cloud);
game.addChildAt(cloud, 0); // Add clouds behind other elements
}
stars.push(newStar);
// Ensure new star also has the color change function
changeStarColor(newStar);
if (!handMoved && hand) {
var handMoveDistance = 0;
var handMoveInterval = LK.setInterval(function () {
handMoveDistance += 1;
hand._update_migrated(handMoveDistance);
if (handMoveDistance >= 1000) {
LK.clearInterval(handMoveInterval);
}
}, 10);
handMoved = true;
}
// Increase the offscreen threshold for destroying obstacles
offscreenThreshold += 300;
// Add a cumulative number of CircularObstacles at random positions around the new star
var cumulativeObstacles = 1 + starCount;
for (var k = 0; k < cumulativeObstacles; k++) {
var randomAngle = Math.random() * Math.PI * 2; // Random angle in radians
var radiusOffset = k * 100;
var circularObstacle = game.addChildAt(new CircularObstacle(newStar.x, newStar.y, 300 + radiusOffset, 0.05 * (k % 2 === 0 ? 1 : -1), randomAngle), 1);
obstacles.push(circularObstacle);
}
// Add orbit line before creating all obstacles
var orbitLine = new OrbitLine(newStar.x, newStar.y, 300 + radiusOffset);
game.addChildAt(orbitLine, 1);
obstacles.push(orbitLine);
} else if (dot.y < 2300 && dot.movedDistance < 0) {
stars[j].moveDown(-dot.movedDistance, dot.y);
}
}
for (var i = 0; i < clouds.length; i++) {
clouds[i]._update_migrated();
}
});
var dot = null;
var dotBouncing = false;
var hand;
var handMoved = false;
function createHand() {
hand = new Hand();
game.addChild(hand);
hand.x = dot.x;
hand.y = dot.y + dot.height / 2;
} /****
* Classes
****/
var BounceEffect = Container.expand(function (x, y, color) {
var self = Container.call(this);
self.x = x;
self.y = y;
var bounceGraphics = self.attachAsset('bounceEffect', {
anchorX: 0.5,
anchorY: 0.5
});
bounceGraphics.tint = color;
var duration = 30;
self._update_migrated = function () {
duration--;
bounceGraphics.scaleX += 0.1;
bounceGraphics.scaleY += 0.1;
bounceGraphics.alpha -= 0.033;
bounceGraphics.scaleX -= 0.01;
bounceGraphics.scaleY -= 0.01;
if (duration <= 0) {
self.destroy();
}
};
game.addChild(self);
});
var Challenge = Container.expand(function (color, amount, bounceLimit) {
var self = Container.call(this);
self.color = color;
self.amount = amount;
self.bounceLimit = bounceLimit;
self.remainingBounces = bounceLimit; // Initialize remainingBounces correctly
self.completed = false;
var obstacleIcon = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: color,
scaleX: 0.5,
scaleY: 0.5
});
obstacleIcon.x = 250;
obstacleIcon.y = 40;
var challengeText = new Text2('0/' + amount, {
size: 75,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 8,
anchorX: 0.5,
anchorY: 0.5
});
challengeText.x = 300;
challengeText.y -= 10;
self.addChild(obstacleIcon);
self.addChild(challengeText);
self.updateProgress = function () {
self.amount -= 1;
challengeText.setText(amount - self.amount + '/' + amount);
if (self.amount <= 0) {
console.log("Objective complete for challenge with color:", self.color);
self.completed = true;
if (currentChallenge.every(function (challenge) {
console.log("All objectives complete for current challenge set. Whole challenge complete.");
return challenge.completed;
})) {
if (gameMode === 'challenges') {
LK.setScore(LK.getScore() + 1);
}
hud.updateScore(LK.getScore());
showChallengeCompletePopup(self.color);
currentChallenge.forEach(function (challenge) {
hud.removeChild(challenge);
console.log("Destroying challenge with color:", challenge.color);
challenge.destroy();
});
currentChallenge = [];
hud.updateChallenges(currentChallenge);
self.destroy(); // Ensure the challenge container is deleted
resetGameToStartingPoint();
startNextChallenge();
} else {}
}
};
});
var CircularObstacle = Container.expand(function (starX, starY, radius, angleSpeed, initialAngle) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
tint: getRandomTint()
});
self.angle = initialAngle || 0;
self.radius = radius;
self.angleSpeed = angleSpeed * 0.75;
self.starX = starX;
self.starY = starY;
self.updatePosition = function () {
self.x = self.starX + Math.cos(self.angle) * self.radius;
self.y = self.starY + Math.sin(self.angle) * self.radius;
self.angle += self.angleSpeed * 0.35;
obstacleGraphics.rotation += self.angleSpeed * 0.35;
};
self.moveDown = function (distance, dotY) {
self.starY += distance * getSpeedMultiplier(dotY);
};
self.updatePosition();
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudTypes = ['cloud1', 'cloud2', 'cloud3'];
var cloudType = cloudTypes[Math.floor(Math.random() * cloudTypes.length)];
var cloudGraphics = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3 // Make clouds even more transparent
});
self.speed = Math.random() * 0.5 + 0.25; // Random speed between 0.25 and 0.75
self.alpha = 0;
var fadeInDuration = 60; // Duration of the fade-in effect in frames
var fadeInFrame = 0;
var fadeInInterval = LK.setInterval(function () {
fadeInFrame++;
self.alpha += 1 / fadeInDuration;
if (fadeInFrame >= fadeInDuration) {
LK.clearInterval(fadeInInterval);
}
}, 1000 / 60);
self.direction = Math.random() < 0.5 ? 1 : -1; // Random direction
self._update_migrated = function () {
self.x += self.speed * self.direction;
if (self.x > 2048 + cloudGraphics.width / 2) {
self.x = -cloudGraphics.width / 2;
} else if (self.x < -cloudGraphics.width / 2) {
self.x = 2048 + cloudGraphics.width / 2;
}
if (self.y > 2732 + cloudGraphics.height / 2) {
self.y = -cloudGraphics.height / 2;
}
};
});
var Dot = Container.expand(function () {
var self = Container.call(this);
var dotGraphics = self.attachAsset('dot', {
anchorX: 0.5,
anchorY: 0.5
});
self.destroyed = false;
self.alpha = 0;
var fadeInDuration = 60; // Duration of the fade-in effect in frames
var fadeInFrame = 0;
var fadeInInterval = LK.setInterval(function () {
fadeInFrame++;
self.alpha += 1 / fadeInDuration;
if (fadeInFrame >= fadeInDuration) {
LK.clearInterval(fadeInInterval);
}
}, 1000 / 60);
self.velocityY = 0;
self.gravity = 0.7;
self.bounce = -15;
self._update_migrated = function () {
if (!dotBouncing) {
return;
}
var previousY = self.y;
self.velocityY += self.gravity;
if (self.velocityY > 0 && dotGraphics.scaleX < 1) {
dotGraphics.scaleX += 0.02;
dotGraphics.scaleY -= 0.02;
} else if (self.velocityY < 0 && dotGraphics.scaleX > 0.9) {
dotGraphics.scaleX -= 0.01;
dotGraphics.scaleY += 0.01;
}
self.y += self.velocityY;
if (!self.firstTouch && !self.intersects(hand)) {
self.y = 2732 - self.height / 2 - 500;
} else if (self.intersects(hand)) {
self.bounceUp();
} else if (self.y > 2232 - self.height / 2 && self.firstTouch && !self.firstStarDestroyed) {
self.velocityY = self.bounce;
} else if (self.y > 2832 && !self.destroyed) {
handleDotDestruction();
}
self.movedDistance = self.y - previousY;
};
self.bounceUp = function () {
if (!self.destroyed) {
self.velocityY = self.bounce;
dot.scale.x *= 0.8;
dot.scale.y = 1.02;
LK.setTimeout(function () {
dot.scale.x = 1;
dot.scale.y = 1;
}, 90);
LK.getSound('bounce').play();
if (!self.intersects(hand)) {
createBounceEffect(self.x, self.y, dotGraphics.tint);
}
self.firstTouch = true;
if (!self.firstStarDestroyed) {
self.firstStarDestroyed = true;
}
if (gameMode === 'challenges' && !self.intersects(hand)) {
if (!currentChallenge[0].completed) {
remainingBounces--;
console.log("Remaining bounces decremented to:", remainingBounces);
hud.remainingBouncesTxt.setText(remainingBounces.toString());
if (remainingBounces <= 0) {
handleDotDestruction();
}
}
}
}
};
self.inheritStarColor = function (star) {
dotGraphics.tint = star.children[0].tint;
};
});
var DotParticleEffect = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var particles = [];
var angleIncrement = Math.PI * 2 / 20;
var speed = 30;
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff].slice(0, CONFIG.numColors);
for (var i = 0; i < 20; i++) {
var particle = self.attachAsset('dotParticle', {
anchorX: 0.5,
anchorY: 0.5,
tint: colors[Math.floor(Math.random() * colors.length)]
});
particle.scaleX = particle.scaleY = 0.5;
particle.alpha = 1;
var angle = i * angleIncrement;
particle.vx = Math.cos(angle) * speed;
particle.vy = Math.sin(angle) * speed;
particles.push(particle);
}
self._update_migrated = function () {
for (var i = particles.length - 1; i >= 0; i--) {
particles[i].x += particles[i].vx;
particles[i].y += particles[i].vy;
particles[i].rotation += 0.1; // Rotate the particle
particles[i].alpha -= 0.0167;
if (particles[i].alpha <= 0) {
particles[i].destroy();
particles.splice(i, 1);
}
}
if (particles.length === 0) {
self.destroy();
}
};
game.addChild(self);
});
var HUD = Container.expand(function () {
var self = Container.call(this);
// Create background line for HUD
var backgroundLine = self.attachAsset('backgroundLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.5
});
backgroundLine.x = 2048 / 2 + 200;
backgroundLine.y = 75;
// Create score text
scoreTxt = new Text2('0', {
size: 200,
// Reduced size to fit within the HUD
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 8
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = 2048 - 200 + 80; // Adjusted position to fit within the HUD
scoreTxt.y = -10; // Adjusted position to fit within the HUD
self.addChild(scoreTxt);
// Create challenge level text
self.challengeLevelTxt = new Text2('LVL 0', {
size: 75,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 8
});
self.challengeLevelTxt.anchor.set(0, 0);
self.challengeLevelTxt.x = 320;
self.challengeLevelTxt.y = 80;
self.addChild(self.challengeLevelTxt);
// Create remaining bounces text
self.remainingBouncesIcon = self.attachAsset('dot', {
anchorX: 1,
anchorY: 0,
scaleX: 0.5,
scaleY: 0.5
});
self.remainingBouncesIcon.x = 2048 - 30 + 150;
self.remainingBouncesIcon.y = 40;
self.remainingBouncesIcon.visible = true; // Ensure the remaining bounces icon is always visible
self.addChild(self.remainingBouncesIcon);
self.remainingBouncesTxt = new Text2('0', {
size: 75,
fill: "#ffffff",
stroke: "#000000",
strokeThickness: 8
});
self.remainingBouncesTxt.anchor.set(1, 0);
self.remainingBouncesTxt.x = 2048 + 70 + 150;
self.remainingBouncesTxt.y = 30;
self.remainingBouncesTxt.visible = true; // Ensure the remaining bounces text is always visible
self.addChild(self.remainingBouncesTxt);
// Removed challenges container
self.updateScore = function (score) {
scoreTxt.setText(score.toString());
};
self.updateChallenges = function (challenges) {
var totalWidth = challenges.reduce(function (acc, challenge) {
return acc + challenge.width + 20; // 20px gap
}, -20); // Subtract the last gap
var startX = (2048 - totalWidth) / 2;
challenges.forEach(function (challenge, i) {
challenge.x = startX + i * (challenge.width + 20);
challenge.y = 40; // Ensure all challenges are aligned vertically
self.addChild(challenge);
});
// Keep the level text fixed in the initial spot
self.challengeLevelTxt.x = 320;
self.challengeLevelTxt.y = 30;
self.challengeLevelTxt.visible = true; // Ensure the level text is always visible
};
return self;
});
// Add Hand asset below the dot
var Hand = Container.expand(function () {
var self = Container.call(this);
var handGraphics = self.attachAsset('hand', {
anchorX: 0.5,
anchorY: 0,
alpha: 0.7
});
self.alpha = 0;
var fadeInDuration = 60; // Duration of the fade-in effect in frames
var fadeInFrame = 0;
var fadeInInterval = LK.setInterval(function () {
fadeInFrame++;
self.alpha += 1 / fadeInDuration;
if (fadeInFrame >= fadeInDuration) {
LK.clearInterval(fadeInInterval);
}
}, 1000 / 60);
self._update_migrated = function (distance) {
if (distance) {
self.y += distance;
}
};
});
var HandDestroyEffect = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var handGraphics = self.attachAsset('hand', {
anchorX: 0.5,
anchorY: 0
});
self._update_migrated = function () {
self.y += 10; // Move the hand downwards faster
if (self.y > 2732 + handGraphics.height / 2) {
// Check if the hand is off-screen
self.destroy();
}
};
game.addChild(self);
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
// Removed background
// Create Endless button using endless asset
var endlessButton = self.attachAsset('Endless', {
anchorX: 0.5,
anchorY: 0.5
});
endlessButton.x = 0;
endlessButton.y = 1200;
endlessButton.floatDirection = 1;
endlessButton.floatSpeed = 0.5;
endlessButton.floatRange = 10;
endlessButton.down = function () {
LK.getSound('button').play();
LK.getSound('bounce').play();
// LK.stopMusic();
fadeOutElements([gameTitle, endlessButton, challengesButton, howToPlayButton].concat(mainMenuClouds), function () {
startGame('endless');
});
};
endlessButton._update_migrated = function () {
endlessButton.y += endlessButton.floatSpeed * endlessButton.floatDirection;
if (endlessButton.y >= 1200 + endlessButton.floatRange || endlessButton.y <= 1200 - endlessButton.floatRange) {
endlessButton.floatDirection *= -1;
}
};
LK.on('tick', function () {
endlessButton._update_migrated();
});
// Create Challenges button using challenges asset
var challengesButton = self.attachAsset('Challenges', {
anchorX: 0.5,
anchorY: 0.5
});
challengesButton.x = 0;
challengesButton.y = 1450;
challengesButton.floatDirection = 1;
challengesButton.floatSpeed = 0.5;
challengesButton.floatRange = 10;
challengesButton.down = function () {
LK.getSound('button').play();
LK.getSound('bounce').play();
// LK.stopMusic();
fadeOutElements([gameTitle, endlessButton, challengesButton, howToPlayButton].concat(mainMenuClouds), function () {
startGame('challenges');
});
};
challengesButton._update_migrated = function () {
challengesButton.y += challengesButton.floatSpeed * challengesButton.floatDirection;
if (challengesButton.y >= 1450 + challengesButton.floatRange || challengesButton.y <= 1450 - challengesButton.floatRange) {
challengesButton.floatDirection *= -1;
}
};
LK.on('tick', function () {
challengesButton._update_migrated();
});
// Create game title using gametitle asset
var gameTitle = self.attachAsset('gametitle', {
anchorX: 0.5,
anchorY: 0.5
});
gameTitle.x = 0;
gameTitle.y = 600;
// self.addChild(background); // Removed undefined background reference
// Create How to Play button using a new asset
var howToPlayButton = new Text2('how to play', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
// Add border color
strokeThickness: 8,
// Add border thickness
anchorX: 0.5,
anchorY: 0.5,
align: 'center' // Center justify the text
});
howToPlayButton.x = -125;
howToPlayButton.y = 1700;
howToPlayButton.blinking = true;
howToPlayButton.blinkSpeed = 0.005;
howToPlayButton.blinkDirection = 1;
howToPlayButton.down = function () {
LK.getSound('button').play();
showHowToPlay();
};
howToPlayButton._update_migrated = function () {
if (howToPlayButton.blinking) {
howToPlayButton.alpha += howToPlayButton.blinkSpeed * howToPlayButton.blinkDirection;
if (howToPlayButton.alpha >= 1) {
howToPlayButton.alpha = 1;
howToPlayButton.blinkDirection = -1;
} else if (howToPlayButton.alpha <= 0.1) {
howToPlayButton.alpha = 0.1;
howToPlayButton.blinkDirection = 1;
}
}
};
LK.on('tick', function () {
howToPlayButton._update_migrated();
});
gameTitle.tiltDirection = 1;
gameTitle.tiltSpeed = 0.001;
gameTitle.maxTilt = 0.1;
gameTitle._update_migrated = function () {
gameTitle.rotation += gameTitle.tiltSpeed * gameTitle.tiltDirection;
if (gameTitle.rotation >= gameTitle.maxTilt || gameTitle.rotation <= -gameTitle.maxTilt) {
gameTitle.tiltDirection *= -1;
}
};
LK.on('tick', function () {
gameTitle._update_migrated();
});
// Add clouds to the main menu background
var mainMenuClouds = [];
for (var i = 0; i < 10; i++) {
var cloud = new MainMenuCloud();
cloud.x = Math.random() * 2048 - 2600;
var newY;
do {
newY = Math.random() * 2732;
} while (!isCloudPositionValid(newY, mainMenuClouds, 200)); // Ensure clouds are at least 200 pixels apart
cloud.y = newY;
mainMenuClouds.push(cloud);
self.addChild(cloud);
}
self.addChild(gameTitle);
self.addChild(endlessButton);
self.addChild(challengesButton);
self.addChild(howToPlayButton);
// Update clouds on the main menu background
LK.on('tick', function () {
for (var i = 0; i < mainMenuClouds.length; i++) {
mainMenuClouds[i]._update_migrated();
}
});
// Play game music after 2 seconds
LK.setTimeout(function () {
LK.playMusic('gamemusic');
}, 2000);
});
var MainMenuCloud = Container.expand(function () {
var self = Container.call(this);
var cloudTypes = ['cloud1', 'cloud2', 'cloud3'];
var cloudType = cloudTypes[Math.floor(Math.random() * cloudTypes.length)];
var cloudGraphics = self.attachAsset(cloudType, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3 // Make clouds even more transparent
});
self.speed = Math.random() * 0.5 + 0.25; // Random speed between 0.25 and 0.75
self.direction = Math.random() < 0.5 ? 1 : -1; // Random direction
self._update_migrated = function () {
self.x += self.speed * self.direction;
if (self.x > 2048 + cloudGraphics.width / 2) {
self.x = -cloudGraphics.width / 2;
} else if (self.x < -cloudGraphics.width / 2) {
self.x = 2048 + cloudGraphics.width / 2;
}
if (self.y > 2732 + cloudGraphics.height / 2) {
self.y = -cloudGraphics.height / 2;
}
};
});
var ObstacleParticleEffect = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var particles = [];
var angleIncrement = Math.PI * 2 / 30;
var speed = 20;
var dotColor = dot.children[0].tint; // Get the current color of the dot
for (var i = 0; i < 30; i++) {
var particle = self.attachAsset('obstacleParticle', {
anchorX: 0.5,
anchorY: 0.5,
tint: dotColor
});
particle.scaleX = particle.scaleY = 0.5;
particle.alpha = 1;
var angle = i * angleIncrement;
particle.vx = Math.cos(angle) * speed;
particle.vy = Math.sin(angle) * speed;
particles.push(particle);
}
self._update_migrated = function () {
for (var i = particles.length - 1; i >= 0; i--) {
particles[i].x += particles[i].vx;
particles[i].y += particles[i].vy;
particles[i].rotation += 0.1; // Rotate the particle
particles[i].alpha -= 0.0167;
if (particles[i].alpha <= 0) {
particles[i].destroy();
particles.splice(i, 1);
}
}
if (particles.length === 0) {
self.destroy();
particles = [];
}
};
game.addChild(self);
});
var ObstacleScorePopup = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var scoreText = new Text2('+10', {
size: 100,
fill: "#ffffff",
anchorX: 0.5,
anchorY: 0.5
});
scoreText.x = -scoreText.width / 2;
scoreText.y = -scoreText.height / 2;
self.addChild(scoreText);
self.alpha = 1;
var duration = 120;
self._update_migrated = function () {
duration--;
self.y -= 2;
self.alpha -= 1 / 120;
if (duration <= 0) {
self.destroy();
}
};
game.addChild(self);
});
var OrbitLine = Container.expand(function (starX, starY, radius) {
var self = Container.call(this);
self.starX = starX;
self.starY = starY;
self.radius = radius;
var segments = 50;
var angleIncrement = Math.PI * 2 / segments;
for (var i = 0; i < segments; i++) {
var angle = i * angleIncrement;
var dot = self.attachAsset('smallObstacle', {
x: starX + Math.cos(angle) * radius,
y: starY + Math.sin(angle) * radius,
anchorX: 0.5,
anchorY: 0.5,
tint: [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff, 0xffa500][Math.floor(Math.random() * 5)]
});
if (i % 2 === 0) {
dot.alpha = 0;
}
}
self.moveDown = function (distance, dotY) {
var speedMultiplier = dotY < 1200 ? 3 : dotY < 1400 ? 2 : dotY < 2000 ? 1.3 : dotY < 2300 ? 1.2 : 1;
self.y += distance * speedMultiplier;
};
});
var ParticleEffect = Container.expand(function (x, y, color) {
var self = Container.call(this);
self.x = x;
self.y = y;
var particles = [];
for (var i = 0; i < 20; i++) {
var particle = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
particle.scaleX = particle.scaleY = Math.random() * 0.5 + 0.5;
particle.alpha = 0.7;
particle.vx = (Math.random() - 0.5) * 10;
particle.vy = (Math.random() - 0.5) * 10;
particles.push(particle);
}
self._update_migrated = function () {
for (var i = particles.length - 1; i >= 0; i--) {
particles[i].x += particles[i].vx;
particles[i].y += particles[i].vy;
particles[i].alpha -= 0.02;
if (particles[i].alpha <= 0) {
particles[i].destroy();
particles.splice(i, 1);
}
}
if (particles.length === 0) {
self.destroy();
}
};
game.addChild(self);
});
var ScorePopup = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
var scoreText = new Text2('+' + (10 * (starCount + 1)).toString(), {
size: 100,
fill: "#ffffff",
anchorX: 0.5,
anchorY: 0.5
});
scoreText.x = -scoreText.width / 2;
scoreText.y = -scoreText.height / 2;
self.addChild(scoreText);
self.alpha = 1;
var duration = 120;
self._update_migrated = function () {
duration--;
self.y -= 2;
self.alpha -= 1 / 120;
if (duration <= 0) {
self.destroy();
}
};
game.addChild(self);
});
var Star = Container.expand(function (starNumber) {
var self = Container.call(this);
self.starNumber = starNumber;
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
tint: getRandomTint()
});
self.scaleDirection = 1;
self.scaleSpeed = 0.005;
self.minScale = 1;
self.maxScale = 1.2;
self.moveDown = function (distance, dotY) {
self.y += distance * getSpeedMultiplier(dotY);
if (self.y > 2732 - self.height / 2) {
self.y = -self.height / 2;
}
for (var i = 0; i < clouds.length; i++) {
clouds[i].y += distance * getSpeedMultiplier(dotY);
}
};
self.updateScale = function () {
if (self.scaleDirection === 1 && starGraphics.scale.x < self.maxScale) {
starGraphics.scale.x += self.scaleSpeed;
starGraphics.scale.y += self.scaleSpeed;
} else if (self.scaleDirection === -1 && starGraphics.scale.x > self.minScale) {
starGraphics.scale.x -= self.scaleSpeed;
starGraphics.scale.y -= self.scaleSpeed;
}
if (starGraphics.scale.x >= self.maxScale || starGraphics.scale.x <= self.minScale) {
self.scaleDirection *= -1;
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xD3D3D3 // Light grey color
});
/****
* Game Code
****/
function fadeOutElements(elements, callback) {
var duration = 60; // Duration of the fade-out effect in frames
var frame = 0;
var interval = LK.setInterval(function () {
frame++;
elements.forEach(function (element) {
element.alpha -= 1 / duration;
});
if (frame >= duration) {
LK.clearInterval(interval);
elements.forEach(function (element) {
element.destroy();
});
if (callback) {
callback();
}
}
}, 1000 / 60);
}
// Removed mainMenuBackground asset initialization
function createHandDestroyEffect() {
var effect = new HandDestroyEffect(hand.x, hand.y);
LK.on('tick', function () {
effect._update_migrated();
});
}
function destroyHand() {
if (hand) {
createHandDestroyEffect(hand.x, hand.y);
hand.destroy();
hand = null;
}
}
function isCloudPositionValid(newY, existingClouds, minDistance) {
for (var i = 0; i < existingClouds.length; i++) {
if (Math.abs(newY - existingClouds[i].y) < minDistance) {
return false;
}
}
return true;
}
var remainingBounces;
var clouds = [];
for (var i = 0; i < 5; i++) {
var cloud = new Cloud();
cloud.x = Math.random() * 2048;
var newY;
do {
newY = Math.random() * 2732;
} while (!isCloudPositionValid(newY, clouds, 200)); // Ensure clouds are at least 200 pixels apart
cloud.y = newY;
clouds.push(cloud);
game.addChildAt(cloud, 0); // Add clouds behind other elements
}
function showHowToPlay() {
var howToPlayScreen = new Container({
width: 2048,
height: 2732,
alpha: 0.5
});
var background = howToPlayScreen.attachAsset('mainMenuBackground', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
width: 2048,
height: 2732
});
background.x = 2048 / 4;
background.y = 2732 / 2;
var endlessModeText = new Text2('Endless:\n\n• Tap to bounce!\n• Collect stars to score points and change color!\n• Avoid different colored obstacles! \n•. Destroy same colored obstacles to clear the path and get extra points!', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
// Add border color
strokeThickness: 8,
// Add border thickness
anchorX: 0.5,
anchorY: 0.5,
align: 'left',
wordWrap: true,
wordWrapWidth: 900
});
endlessModeText.x = 2048 / 4 - 900;
endlessModeText.y = 2732 / 2 - 900;
var challengesText = new Text2('Challenges:\n\n• Complete objectives by destroying obstacles! \n• Keep an eye on your remaining bounces! \n• Reach the higher level possible!', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
// Add border color
strokeThickness: 8,
// Add border thickness
anchorX: 0.5,
anchorY: 0.5,
align: 'left',
wordWrap: true,
wordWrapWidth: 900
});
challengesText.x = 2048 / 4 - 900;
challengesText.y = 2732 / 2 - 300;
var backButton = new Text2('Back', {
size: 50,
fill: "#ffffff",
stroke: "#000000",
// Add border color
strokeThickness: 8,
// Add border thickness
anchorX: 0.5,
anchorY: 0.5
});
backButton.x = 2048 / 4;
backButton.y = 2732 - 200;
backButton.down = function () {
howToPlayScreen.destroy();
};
howToPlayScreen.addChild(background);
howToPlayScreen.addChild(endlessModeText);
howToPlayScreen.addChild(challengesText);
howToPlayScreen.addChild(backButton);
// Add event listener to close overlay when screen is touched
howToPlayScreen.down = function () {
howToPlayScreen.destroy();
};
LK.gui.top.addChild(howToPlayScreen);
}
function isValidStar(star) {
return star && star.children && star.children[0] && typeof star.children[0].tint !== 'undefined' && star.y !== null && typeof star.y !== 'undefined';
}
function resetGameToStartingPoint() {
// Destroy all existing stars, obstacles, particles from ObstacleParticleEffect, and the dot
stars.forEach(function (star) {
star.destroy();
});
stars = [];
obstacles.forEach(function (obstacle) {
if (obstacle instanceof ObstacleParticleEffect) {
obstacle.destroy();
}
obstacle.destroy();
});
obstacles = [];
if (dot) {
dot.destroy();
dot = null;
}
remainingBounces = challenges[currentChallengeIndex].remainingBounces;
console.log("Remaining bounces reset to initial value:", remainingBounces);
// Reset star count
starCount = 0;
// Add initial star
var star = game.addChildAt(new Star(), 1);
star.x = 2048 / 2;
star.y = 2732 / 2 - 500;
stars.push(star);
// Add initial dot
if (!dot) {
dot = game.addChild(new Dot());
dot.x = 2048 / 2;
dot.y = 2732 - dot.height / 2 - 200;
dotBouncing = true;
}
if (!hand) {
createHand();
}
handMoved = false;
// Add initial orbit line
var orbitLine = game.addChildAt(new OrbitLine(star.x, star.y, 300), 0);
obstacles.push(orbitLine);
// Add initial circular obstacle
var starX = 2048 / 2;
var starY = 2732 / 2 - 500;
var radius = 300;
var angleSpeed = 0.05;
var obstacle = new CircularObstacle(starX, starY, radius, angleSpeed);
game.addChildAt(obstacle, 2);
obstacles.push(obstacle);
// Check if the first star has at least one obstacle, if not, create it
if (obstacles.length === 0) {
var newObstacle = new CircularObstacle(starX, starY, radius, angleSpeed);
game.addChildAt(newObstacle, 1);
obstacles.push(newObstacle);
}
}
// Ensure HUD is still over the rest of the elements
game.addChild(hud);
var CONFIG = {
numColors: 2 // Default number of colors, can be set between 2 and 5
};
var gameMode = 'challenges'; // Default game mode
var mainMenu = new MainMenu();
LK.gui.top.addChild(mainMenu);
var scoreTxt;
var hud = new HUD();
hud.visible = false; // Hide HUD on game start
game.addChild(hud);
function getRandomTint() {
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff].slice(0, CONFIG.numColors);
return colors[Math.floor(Math.random() * Math.min(CONFIG.numColors, colors.length))];
}
function showChallengeCompletePopup(color) {
var successAssets = ['success', 'success2', 'success3'];
var randomSuccessAsset = successAssets[Math.floor(Math.random() * successAssets.length)];
var challengeCompletePopup = LK.getAsset(randomSuccessAsset, {
anchorX: 0.5,
anchorY: 0.5,
tint: color,
alpha: 0
});
challengeCompletePopup.x = 2048 / 2;
challengeCompletePopup.y = 2732 / 2;
game.addChild(challengeCompletePopup);
var animationDuration = 120;
var animationFrame = 0;
var animationInterval = LK.setInterval(function () {
if (animationFrame < animationDuration / 2) {
if (animationFrame === 0) {
challengeCompletePopup.alpha = 1;
}
challengeCompletePopup.scaleX = challengeCompletePopup.scaleY = 1 + 0.5 * (animationFrame / (animationDuration / 2));
} else {
challengeCompletePopup.alpha = 1 - (animationFrame - animationDuration / 2) / (animationDuration / 2);
challengeCompletePopup.scaleX = challengeCompletePopup.scaleY = 1.5 - 0.5 * (animationFrame - animationDuration / 2) / (animationDuration / 2);
}
animationFrame++;
if (animationFrame >= animationDuration) {
LK.clearInterval(animationInterval);
challengeCompletePopup.destroy();
}
}, 1000 / 60);
}
function getStarColor(starNumber) {
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff].slice(0, CONFIG.numColors);
return colors[starNumber % Math.min(CONFIG.numColors, colors.length)];
}
function getSpeedMultiplier(dotY) {
if (dotY < 1200) {
return 3;
}
if (dotY < 1400) {
return 2;
}
if (dotY < 2000) {
return 1.3;
}
return 1.2;
}
function handleDotDestruction() {
createDotParticleEffect(dot.x, dot.y);
LK.getSound('explosion').play();
dot.destroyed = true;
dot.destroy();
LK.setTimeout(function () {
remainingBounces = challenges[currentChallengeIndex].remainingBounces;
console.log("Remaining bounces reset due to dot destruction:", remainingBounces);
LK.stopMusic();
LK.showGameOver();
}, 1000);
}
function createBounceEffect(x, y, color) {
var effect = new BounceEffect(x, y + 80, color); // Adjust y position to start from a little more lower on the ball
LK.on('tick', function () {
// Ensure HUD is on top of everything
if (game.children.indexOf(hud) !== game.children.length - 1) {
game.addChild(hud);
}
effect._update_migrated();
});
}
var shrinkFrame = 0;
var shrinkDuration = 60;
function startGame(mode) {
gameMode = mode;
hud.visible = true; // Show HUD when a game mode is selected
if (!dot) {
dot = game.addChild(new Dot());
dot.x = 2048 / 2;
dot.y = 2732 - dot.height / 2 - 200;
dotBouncing = true;
}
if (!hand) {
hand = new Hand();
game.addChild(hand);
hand.x = dot.x;
hand.y = dot.y + dot.height / 2;
}
// Ensure obstacles are always on a higher layer than orbit lines
for (var i = 0; i < obstacles.length; i++) {
if (obstacles[i] instanceof CircularObstacle) {
var obstacleIndex = game.children.indexOf(obstacles[i]);
var orbitLineIndex = game.children.indexOf(orbitLine);
if (obstacleIndex < orbitLineIndex) {
game.setChildIndex(obstacles[i], orbitLineIndex + 1);
}
}
}
if (mode === 'endless') {
CONFIG.numColors = 5;
// Start endless mode
// Add your endless mode initialization code here
hud.removeChild(hud.children[0]); // Remove HUD background
hud.challengeLevelTxt.visible = false; // Hide level text in endless mode
hud.remainingBouncesIcon.visible = false; // Hide remaining bounces icon in endless mode
hud.remainingBouncesTxt.visible = false; // Hide remaining bounces text in endless mode
scoreTxt.x -= 100; // Move score text 100 pixels to the left
scoreTxt.size *= 2; // Double the size of the score text
scoreTxt.visible = true; // Show score text in endless mode
} else if (mode === 'challenges') {
CONFIG.numColors = 2;
// Start challenges mode
hud.challengeLevelTxt.visible = true; // Show level text in challenge mode
hud.remainingBouncesIcon.visible = true; // Show remaining bounces icon in challenge mode
hud.remainingBouncesTxt.visible = true; // Show remaining bounces text in challenge mode
scoreTxt.visible = false; // Hide score text in challenge mode
console.log("Remaining bounces reset for new game mode.");
startNextChallenge();
}
}
// Pregame screen removed
var challenges = [{
id: 1,
numColors: 2,
remainingBounces: 30,
obstacles: [1]
}, {
id: 2,
numColors: 2,
remainingBounces: 40,
obstacles: [1, 1]
}, {
id: 3,
numColors: 2,
remainingBounces: 50,
obstacles: [2, 2]
}, {
id: 4,
numColors: 3,
remainingBounces: 50,
obstacles: [1, 1, 1]
}, {
id: 5,
numColors: 3,
remainingBounces: 60,
obstacles: [3, 2, 1]
}, {
id: 6,
numColors: 3,
remainingBounces: 70,
obstacles: [2, 2, 2]
}, {
id: 7,
numColors: 3,
remainingBounces: 80,
obstacles: [3, 3, 3]
}, {
id: 8,
numColors: 4,
remainingBounces: 70,
obstacles: [1, 1, 1, 1]
}, {
id: 9,
numColors: 4,
remainingBounces: 80,
obstacles: [1, 2, 3, 4]
}, {
id: 10,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 11,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 12,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 13,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 14,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}, {
id: 15,
numColors: 4,
remainingBounces: 99,
obstacles: [5, 5, 5, 5]
}];
var currentChallengeIndex = 0;
var currentChallenge = null;
function startNextChallenge() {
if (gameMode === 'endless') {
return;
}
if (currentChallengeIndex < challenges.length) {
console.log("Starting next challenge with index:", currentChallengeIndex);
// Clear previous challenge obstacles
if (currentChallenge) {
currentChallenge.forEach(function (challenge) {
hud.removeChild(challenge);
challenge.destroy();
});
currentChallenge = [];
hud.updateChallenges(currentChallenge);
}
// Clear the challenges container
hud.children.forEach(function (child) {
if (child instanceof Challenge) {
hud.removeChild(child);
child.destroy();
}
});
// Clear the challenges container
hud.children.forEach(function (child) {
if (child instanceof Challenge) {
hud.removeChild(child);
child.destroy();
}
});
CONFIG.numColors = challenges[currentChallengeIndex].numColors;
var challengeData = challenges[currentChallengeIndex];
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff, 0xffa500].slice(0, CONFIG.numColors);
currentChallenge = [];
challengeData.obstacles.forEach(function (amount, i) {
var challengeColor = colors[i % colors.length];
var challenge = new Challenge(challengeColor, amount, challengeData.remainingBounces);
currentChallenge.push(challenge);
game.addChildAt(challenge, 2);
});
bounceCount = 0;
var totalWidth = currentChallenge.reduce(function (acc, challenge) {
return acc + challenge.width + 20; // 20px gap
}, -20); // Subtract the last gap
hud.updateChallenges(currentChallenge);
hud.challengeLevelTxt.setText('LVL ' + currentChallengeIndex);
hud.updateScore(LK.getScore()); // Ensure score is updated in the HUD
remainingBounces = challengeData.remainingBounces;
hud.remainingBouncesTxt.setText(remainingBounces.toString()); // Reset remaining bounces text
console.log("Remaining bounces reset to:", remainingBounces);
// Ensure HUD is still over the rest of the elements
if (hud.y < 0) {
hud.y = 0;
}
if (hud.x < 0) {
hud.x = 0;
}
if (hud.x + hud.width > 2048) {
hud.x = 2048 - hud.width;
}
if (hud.y + hud.height > 2732) {
hud.y = 2732 - hud.height;
}
}
currentChallengeIndex++;
}
// startNextChallenge(); // Removed initial call to startNextChallenge
function createObstacleParticleEffect(x, y) {
var effect = new ObstacleParticleEffect(x, y);
LK.on('tick', function () {
effect._update_migrated();
});
}
function changeStarColor(star) {
var colors = [0xffe066, 0xcc66ff, 0xff6666, 0x99ccff].slice(0, CONFIG.numColors);
var currentColorIndex = colors.indexOf(star.children[0].tint);
var nextColorIndex = (currentColorIndex + 1) % Math.min(CONFIG.numColors, colors.length);
star.children[0].tint = colors[nextColorIndex];
}
function updateStarColors() {
for (var i = 0; i < stars.length; i++) {
changeStarColor(stars[i]);
}
}
LK.setInterval(updateStarColors, 2000);
var starCount = 0;
// Initialize the offscreen threshold for destroying obstacles
var offscreenThreshold = 2732 + 1000;
function createParticleEffect(x, y, color) {
var effect = new ParticleEffect(x, y, color);
LK.on('tick', function () {
effect._update_migrated();
});
}
function createDotParticleEffect(x, y) {
var effect = new DotParticleEffect(x, y);
LK.on('tick', function () {
effect._update_migrated();
});
}
var obstacles = [];
function updateObstacles() {
var obstacleCount = 5 + starCount;
while (obstacles.length < obstacleCount) {
var obstacle = game.addChildAt(new Obstacle(), game.children.length - 1); // Ensure obstacle is in front of clouds
obstacle.x = obstacle.direction === 1 ? -obstacle.width / 2 : 2048 + obstacle.width / 2;
obstacle.y = Math.random() * (2732 - obstacle.height) + obstacle.height / 2;
obstacles.push(obstacle);
}
// No longer move clouds when a star is destroyed
}
// Removed duplicate score text initialization and addition to the screen
game.on('down', function (x, y, obj) {
if (dot) {
dot.bounceUp();
}
});
var stars = [];
var star = game.addChildAt(new Star(), 1);
star.x = 2048 / 2;
star.y = 2732 / 2 - 500;
stars.push(star);
LK.setInterval(function () {
changeStarColor(star);
}, 1000); // Initialize star with a random color from the obstacles
// Add dotted orbit for the first star
var orbitLine = game.addChild(new OrbitLine(star.x, star.y, 300));
obstacles.push(orbitLine);
function spawnInitialObstacles() {
var starX = 2048 / 2;
var starY = 2732 / 2 - 500;
var radius = 300;
var angleSpeed = 0.05;
var obstacle = new CircularObstacle(starX, starY, radius, angleSpeed);
game.addChildAt(obstacle, game.children.length - 1); // Ensure obstacle is in front of clouds
obstacles.push(obstacle);
game.setChildIndex(star, game.children.length - 1); // Ensure star is in front of clouds
// No additional obstacles for the first star
}
spawnInitialObstacles();
game.addChild(hud);
LK.on('tick', function () {
if (dot) {
dot._update_migrated();
}
for (var i = 0; i < obstacles.length; i++) {
if (obstacles[i] instanceof CircularObstacle) {
obstacles[i].updatePosition();
} else {
if (typeof obstacles[i]._move_migrated === 'function') {
obstacles[i]._move_migrated();
}
}
if (dot && dot.y < 2300 && dot.movedDistance < 0) {
obstacles[i].moveDown(-dot.movedDistance, dot.y);
}
if (dot && dot.intersects && obstacles[i] && dot.intersects(obstacles[i]) && !(obstacles[i] instanceof OrbitLine) && dot !== null && obstacles[i] !== null && typeof dot.intersects === 'function') {
if (dot.children[0].tint === obstacles[i].children[0].tint) {
createObstacleParticleEffect(obstacles[i].x, obstacles[i].y);
if (gameMode === 'endless') {
if (gameMode === 'endless') {
LK.setScore(LK.getScore() + 10);
} else if (gameMode === 'challenges') {
// Do not display points addition in challenge mode
}
}
hud.updateScore(LK.getScore());
if (gameMode === 'endless') {
var obstacleScorePopup = new ObstacleScorePopup(obstacles[i].x, obstacles[i].y);
LK.on('tick', function () {
obstacleScorePopup._update_migrated();
});
}
LK.getSound('obstacle').play();
// Update challenge progress before destroying the obstacle
if (currentChallenge) {
for (var j = 0; j < currentChallenge.length; j++) {
if (obstacles[i].children[0].tint === currentChallenge[j].color) {
currentChallenge[j].updateProgress();
if (currentChallenge[j].completed) {
currentChallenge.splice(j, 1);
if (currentChallenge.length === 0) {
startNextChallenge();
}
}
break;
}
}
}
if (obstacles[i]) {
obstacles[i].destroy();
}
obstacles.splice(i, 1);
} else {
if (!dot.destroyed) {
createDotParticleEffect(dot.x, dot.y);
LK.getSound('explosion').play();
dot.destroyed = true;
}
dot.destroy();
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
} else if (obstacles[i] && obstacles[i].y > offscreenThreshold) {
if (obstacles[i] && typeof obstacles[i].destroy === 'function') {
obstacles[i].destroy();
}
obstacles.splice(i, 1);
}
}
for (var j = stars.length - 1; j >= 0; j--) {
if (!dot || !stars[j]) {
continue;
}
stars[j].updateScale();
if (dot && dot.intersects && stars[j] && isValidStar(stars[j]) && dot.intersects(stars[j]) && dot.y != null && stars[j].y != null && typeof dot.intersects === 'function' && dot.children && dot.children[0] && dot.children[0].y != null && stars[j].children && stars[j].children[0]) {
destroyHand();
dot.inheritStarColor(stars[j]);
if (gameMode === 'endless') {
LK.setScore(LK.getScore() + 10 * (starCount + 1));
} else if (gameMode === 'challenges') {
// Do not display points addition in challenge mode
}
hud.updateScore(LK.getScore());
var oldStarY = stars[j].y;
createParticleEffect(stars[j].x, stars[j].y, stars[j].children[0].tint);
LK.getSound('star').play();
if (gameMode === 'endless') {
var scorePopup = new ScorePopup(stars[j].x, stars[j].y);
LK.on('tick', function () {
scorePopup._update_migrated();
});
}
stars[j].destroy();
stars.splice(j, 1);
starCount += 1;
var newStar = game.addChildAt(new Star(), 1);
game.setChildIndex(newStar, game.children.length - 1); // Ensure new star is in front of clouds
newStar.x = 2048 / 2;
var additionalYOffset = starCount > 1 ? (starCount - 1) * 200 : 0;
newStar.y = oldStarY - 2000 - additionalYOffset;
// Create new clouds if needed when a star is destroyed
while (clouds.length < 5) {
var cloud = new Cloud();
cloud.x = Math.random() * 2048;
var newY;
do {
newY = Math.random() * 2732;
} while (!isCloudPositionValid(newY, clouds, 200)); // Ensure clouds are at least 200 pixels apart
cloud.y = newY;
clouds.push(cloud);
game.addChildAt(cloud, 0); // Add clouds behind other elements
}
stars.push(newStar);
// Ensure new star also has the color change function
changeStarColor(newStar);
if (!handMoved && hand) {
var handMoveDistance = 0;
var handMoveInterval = LK.setInterval(function () {
handMoveDistance += 1;
hand._update_migrated(handMoveDistance);
if (handMoveDistance >= 1000) {
LK.clearInterval(handMoveInterval);
}
}, 10);
handMoved = true;
}
// Increase the offscreen threshold for destroying obstacles
offscreenThreshold += 300;
// Add a cumulative number of CircularObstacles at random positions around the new star
var cumulativeObstacles = 1 + starCount;
for (var k = 0; k < cumulativeObstacles; k++) {
var randomAngle = Math.random() * Math.PI * 2; // Random angle in radians
var radiusOffset = k * 100;
var circularObstacle = game.addChildAt(new CircularObstacle(newStar.x, newStar.y, 300 + radiusOffset, 0.05 * (k % 2 === 0 ? 1 : -1), randomAngle), 1);
obstacles.push(circularObstacle);
}
// Add orbit line before creating all obstacles
var orbitLine = new OrbitLine(newStar.x, newStar.y, 300 + radiusOffset);
game.addChildAt(orbitLine, 1);
obstacles.push(orbitLine);
} else if (dot.y < 2300 && dot.movedDistance < 0) {
stars[j].moveDown(-dot.movedDistance, dot.y);
}
}
for (var i = 0; i < clouds.length; i++) {
clouds[i]._update_migrated();
}
});
var dot = null;
var dotBouncing = false;
var hand;
var handMoved = false;
function createHand() {
hand = new Hand();
game.addChild(hand);
hand.x = dot.x;
hand.y = dot.y + dot.height / 2;
}
Cartoon, white star. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Cartoon. white circle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon white dot with eyes (just black dots).. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon white ring. simple.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
cartoon white cloud.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.