User prompt
Haz nubes con hitbox que se generen aleatoria mente en el mapa
User prompt
Ponle unos rayos de sol al sol
User prompt
Haz un fondo con un cielo y un sol en una esquina
User prompt
Haz que haya una línea invisible que se ponga en un tercio y que arriba de ella la bola no se pueda ir a ese lugar
User prompt
Haz que si uno toca la bola se quede en ese lugar pero siga saltando
User prompt
Haz que la bola nunca pueda dejar de saltar
User prompt
Haz que la velocidad y sea siempre 20
User prompt
Revierte el cambio
User prompt
Ahora cuando uno toca la bola la bola se queda quieta en el lugar
User prompt
Haz que si uno no toca la bola no se mueva
User prompt
Haz que la bola sea visible
User prompt
Bouncing Ball Forever
Initial prompt
Crea una bola que salta indefinidamente
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
// Attach ball graphics
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
self.bounce = 0.8;
// Life tracking
self.lastY = 0;
self.hasLostLife = false;
// Update physics and bouncing
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce off left and right walls
if (self.x <= 40 || self.x >= 2008) {
self.velocityX = -self.velocityX * self.bounce;
self.x = self.x <= 40 ? 40 : 2008;
}
// Define invisible barrier at one-third of screen height
var barrierY = 2732 / 3; // One-third from top
// Bounce off invisible barrier (top third) and bottom wall
if (self.y <= barrierY || self.y >= 2692) {
self.velocityY = -self.velocityY * self.bounce;
self.y = self.y <= barrierY ? barrierY : 2692;
}
// Check if ball fell below screen (lose a life)
if (self.lastY <= 2732 && self.y > 2732 && !self.hasLostLife) {
self.hasLostLife = true;
currentLives--;
livesText.setText('Lives: ' + currentLives);
// Flash screen red to indicate life lost
LK.effects.flashScreen(0xFF0000, 300);
// Reset ball position to center
self.x = 2048 / 2;
self.y = 2732 / 2;
self.velocityX = 0;
self.velocityY = 0;
// Check for game over
if (currentLives <= 0) {
gameStarted = false;
LK.showGameOver();
}
}
// Reset life loss flag when ball is back in safe area
if (self.y <= 2700) {
self.hasLostLife = false;
}
// Update last Y position
self.lastY = self.y;
// Ensure minimum velocity to keep ball moving
var minVelocity = 2;
if (Math.abs(self.velocityX) < minVelocity && Math.abs(self.velocityY) < minVelocity) {
// Add random velocity if ball is moving too slowly
self.velocityX = (Math.random() - 0.5) * minVelocity * 2;
self.velocityY = Math.random() > 0.5 ? -minVelocity : minVelocity;
}
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
// Attach cloud graphics
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.velocityX = (Math.random() - 0.5) * 2; // Random horizontal movement
self.velocityY = 0;
// Update cloud movement
self.update = function () {
// Move cloud
self.x += self.velocityX;
// Wrap around screen horizontally
if (self.x < -150) {
self.x = 2048 + 150;
} else if (self.x > 2048 + 150) {
self.x = -150;
}
};
return self;
});
var GreenCloud = Container.expand(function () {
var self = Container.call(this);
// Attach green cloud graphics
var cloudGraphics = self.attachAsset('greenCloud', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.velocityX = (Math.random() - 0.5) * 2; // Random horizontal movement
self.velocityY = 0;
// Update cloud movement
self.update = function () {
// Move cloud
self.x += self.velocityX;
// Wrap around screen horizontally
if (self.x < -150) {
self.x = 2048 + 150;
} else if (self.x > 2048 + 150) {
self.x = -150;
}
};
return self;
});
var RedCloud = Container.expand(function () {
var self = Container.call(this);
// Attach red cloud graphics with red tint
var cloudGraphics = self.attachAsset('redCloud', {
anchorX: 0.5,
anchorY: 0.5
});
cloudGraphics.tint = 0xFF0000; // Red tint
// Movement properties
self.velocityX = (Math.random() - 0.5) * 2; // Random horizontal movement
self.velocityY = 0;
// Update cloud movement
self.update = function () {
// Move cloud
self.x += self.velocityX;
// Wrap around screen horizontally
if (self.x < -150) {
self.x = 2048 + 150;
} else if (self.x > 2048 + 150) {
self.x = -150;
}
};
return self;
});
var YellowCloud = Container.expand(function () {
var self = Container.call(this);
// Attach yellow cloud graphics
var cloudGraphics = self.attachAsset('yellowCloud', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.velocityX = (Math.random() - 0.5) * 2; // Random horizontal movement
self.velocityY = 0;
// Update cloud movement
self.update = function () {
// Move cloud
self.x += self.velocityX;
// Wrap around screen horizontally
if (self.x < -150) {
self.x = 2048 + 150;
} else if (self.x > 2048 + 150) {
self.x = -150;
}
};
return self;
});
/****
* Initialize Game
****/
// Create and add the ball to the game
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Create and add the ball to the game
var ball = game.addChild(new Ball());
// Add sun decoration to top-right corner
var sun = game.addChild(LK.getAsset('sun', {
anchorX: 0.5,
anchorY: 0.5
}));
sun.x = 2048 - 150; // Position near right edge
sun.y = 150; // Position near top edge
// Add sun rays around the sun
var sunRays = [];
var numRays = 8;
for (var i = 0; i < numRays; i++) {
var ray = game.addChild(LK.getAsset('sunRay', {
anchorX: 0,
anchorY: 0.5
}));
ray.x = sun.x;
ray.y = sun.y;
ray.rotation = i * Math.PI * 2 / numRays;
sunRays.push(ray);
}
// Position ball at center of screen
ball.x = 2048 / 2;
ball.y = 2732 / 2;
// Initialize scoring system
var currentScore = 0;
var highScore = storage.highScore || 0;
var currentLevel = 1;
var level2Unlocked = storage.level2Unlocked || false;
var level3Unlocked = storage.level3Unlocked || false;
var level4Unlocked = storage.level4Unlocked || false;
var level5Unlocked = storage.level5Unlocked || false;
var isInLevelSelect = false;
// Initialize lives system
var currentLives = 3;
var maxLives = 3;
// Initialize timer system (90 seconds = 5400 ticks at 60fps)
var gameTimeLeft = 5400; // 90 seconds in ticks
var gameStarted = true;
// Create score display
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create high score display
var highScoreText = new Text2('Best: ' + highScore, {
size: 60,
fill: 0xFFFF00
});
highScoreText.anchor.set(0.5, 0);
highScoreText.y = 100;
LK.gui.top.addChild(highScoreText);
// Create timer display
var timerText = new Text2('Time: 1:30', {
size: 70,
fill: 0xFF0000
});
timerText.anchor.set(0.5, 0);
timerText.y = 180;
LK.gui.top.addChild(timerText);
// Create level display
var levelText = new Text2('Level 1', {
size: 60,
fill: 0x00FF00
});
levelText.anchor.set(0.5, 0);
levelText.y = 260;
LK.gui.top.addChild(levelText);
// Create lives display
var livesText = new Text2('Lives: 3', {
size: 60,
fill: 0xFF0000
});
livesText.anchor.set(0.5, 0);
livesText.y = 330;
LK.gui.top.addChild(livesText);
// Create level selection button
var levelButton = game.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
levelButton.x = 2048 - 100;
levelButton.y = 350;
// Create level button text
var levelButtonText = new Text2('Levels', {
size: 40,
fill: 0xFFFFFF
});
levelButtonText.anchor.set(0.5, 0.5);
levelButtonText.x = levelButton.x;
levelButtonText.y = levelButton.y;
game.addChild(levelButtonText);
// Level selection menu container
var levelSelectContainer = new Container();
levelSelectContainer.visible = false;
game.addChild(levelSelectContainer);
// Background overlay for level selection
var overlay = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
overlay.width = 2048;
overlay.height = 2732;
overlay.x = 1024;
overlay.y = 1366;
overlay.tint = 0x000000;
overlay.alpha = 0.8;
// Level 1 button
var level1Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level1Button.x = 1024;
level1Button.y = 1000;
level1Button.width = 300;
level1Button.height = 100;
level1Button.tint = 0x4CAF50;
var level1Text = new Text2('Level 1', {
size: 60,
fill: 0xFFFFFF
});
level1Text.anchor.set(0.5, 0.5);
level1Text.x = level1Button.x;
level1Text.y = level1Button.y;
levelSelectContainer.addChild(level1Text);
// Level 2 button
var level2Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level2Button.x = 1024;
level2Button.y = 1200;
level2Button.width = 300;
level2Button.height = 100;
level2Button.tint = level2Unlocked ? 0xFFD700 : 0x808080;
var level2Text = new Text2(level2Unlocked ? 'Level 2' : 'Level 2 (Locked)', {
size: 60,
fill: 0xFFFFFF
});
level2Text.anchor.set(0.5, 0.5);
level2Text.x = level2Button.x;
level2Text.y = level2Button.y;
levelSelectContainer.addChild(level2Text);
// Level 3 button
var level3Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level3Button.x = 1024;
level3Button.y = 1400;
level3Button.width = 300;
level3Button.height = 100;
level3Button.tint = level3Unlocked ? 0xFF6B6B : 0x808080;
var level3Text = new Text2(level3Unlocked ? 'Level 3' : 'Level 3 (Locked)', {
size: 60,
fill: 0xFFFFFF
});
level3Text.anchor.set(0.5, 0.5);
level3Text.x = level3Button.x;
level3Text.y = level3Button.y;
levelSelectContainer.addChild(level3Text);
// Level 4 button
var level4Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level4Button.x = 1024;
level4Button.y = 1600;
level4Button.width = 300;
level4Button.height = 100;
level4Button.tint = level4Unlocked ? 0x9C27B0 : 0x808080;
var level4Text = new Text2(level4Unlocked ? 'Level 4' : 'Level 4 (Locked)', {
size: 60,
fill: 0xFFFFFF
});
level4Text.anchor.set(0.5, 0.5);
level4Text.x = level4Button.x;
level4Text.y = level4Button.y;
levelSelectContainer.addChild(level4Text);
// Level 5 button
var level5Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level5Button.x = 1024;
level5Button.y = 1800;
level5Button.width = 300;
level5Button.height = 100;
level5Button.tint = level5Unlocked ? 0x00FF7F : 0x808080;
var level5Text = new Text2(level5Unlocked ? 'Level 5' : 'Level 5 (Locked)', {
size: 60,
fill: 0xFFFFFF
});
level5Text.anchor.set(0.5, 0.5);
level5Text.x = level5Button.x;
level5Text.y = level5Button.y;
levelSelectContainer.addChild(level5Text);
// Infinite Mode button
var infiniteButton = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
infiniteButton.x = 1024;
infiniteButton.y = 2000;
infiniteButton.width = 300;
infiniteButton.height = 100;
infiniteButton.tint = 0x00BCD4;
var infiniteText = new Text2('Infinite Mode', {
size: 50,
fill: 0xFFFFFF
});
infiniteText.anchor.set(0.5, 0.5);
infiniteText.x = infiniteButton.x;
infiniteText.y = infiniteButton.y;
levelSelectContainer.addChild(infiniteText);
// Close button
var closeButton = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
closeButton.x = 1024;
closeButton.y = 2200;
closeButton.width = 200;
closeButton.height = 80;
closeButton.tint = 0xFF5252;
var closeText = new Text2('Close', {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = closeButton.x;
closeButton.y = closeButton.y;
levelSelectContainer.addChild(closeText);
// Button click handlers
levelButton.down = function () {
if (!isInLevelSelect && gameStarted) {
isInLevelSelect = true;
levelSelectContainer.visible = true;
gameStarted = false; // Pause the game
}
};
level1Button.down = function () {
// Start level 1
currentLevel = 1;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 1');
levelText.fill = 0x00FF00;
yellowCloudSpawnInterval = 480;
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
};
level2Button.down = function () {
if (level2Unlocked) {
// Start level 2
currentLevel = 2;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 2');
levelText.fill = 0xFFD700;
yellowCloudSpawnInterval = yellowCloudSpawnIntervalLevel2;
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
}
};
level3Button.down = function () {
if (level3Unlocked) {
// Start level 3
currentLevel = 3;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 3');
levelText.fill = 0xFF6B6B;
yellowCloudSpawnInterval = 240; // Spawn yellow clouds twice as fast as level 1
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
}
};
level4Button.down = function () {
if (level4Unlocked) {
// Start level 4
currentLevel = 4;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 4');
levelText.fill = 0x9C27B0;
yellowCloudSpawnInterval = Math.floor(960 / 1.5); // 1.5x more frequent than level 2
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
}
};
level5Button.down = function () {
if (level5Unlocked) {
// Start level 5
currentLevel = 5;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 5');
levelText.fill = 0x00FF7F;
yellowCloudSpawnInterval = Math.floor(240 * 1.5); // 1.5x less frequent than level 3
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
for (var i = redClouds.length - 1; i >= 0; i--) {
redClouds[i].destroy();
}
redClouds = [];
}
};
infiniteButton.down = function () {
// Start infinite mode
currentLevel = 6;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Infinite Mode');
levelText.fill = 0x00BCD4;
yellowCloudSpawnInterval = 240; // Fast spawn rate for all clouds
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
for (var i = redClouds.length - 1; i >= 0; i--) {
redClouds[i].destroy();
}
redClouds = [];
};
closeButton.down = function () {
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
};
// Function to update score
function updateScore(points) {
currentScore += points;
scoreText.setText('Score: ' + currentScore);
// Check for level transition at 250 points
if (currentLevel === 1 && currentScore >= 250) {
// Unlock level 2
level2Unlocked = true;
storage.level2Unlocked = true;
currentLevel = 2;
// Update yellow cloud spawn interval for level 2
yellowCloudSpawnInterval = yellowCloudSpawnIntervalLevel2;
// Reset timer to 90 seconds for level 2
gameTimeLeft = 5400; // Reset to 90 seconds
// Reset score to 0 for level 2
currentScore = 0;
scoreText.setText('Score: 0');
// Reset lives for new level
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
// Flash screen to indicate level change
LK.effects.flashScreen(0xFFD700, 500); // Gold flash for level transition
// Update level display
levelText.setText('Level 2');
levelText.fill = 0xFFD700; // Gold color for level 2
// Update level 2 button appearance and text
level2Button.tint = 0xFFD700;
level2Text.setText('Level 2');
}
// Check for level 3 unlock at 300 points in level 2
if (currentLevel === 2 && currentScore >= 300) {
// Unlock level 3
level3Unlocked = true;
storage.level3Unlocked = true;
currentLevel = 3;
// Update yellow cloud spawn interval for level 3 (more frequent)
yellowCloudSpawnInterval = 240; // Twice as fast as level 1
// Reset timer to 90 seconds for level 3
gameTimeLeft = 5400;
// Reset score to 0 for level 3
currentScore = 0;
scoreText.setText('Score: 0');
// Reset lives for new level
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
// Flash screen to indicate level change
LK.effects.flashScreen(0xFF6B6B, 500); // Red flash for level 3
// Update level display
levelText.setText('Level 3');
levelText.fill = 0xFF6B6B; // Red color for level 3
// Update level 3 button appearance and text
level3Button.tint = 0xFF6B6B;
level3Text.setText('Level 3');
}
// Check for level 4 unlock at 600 points in level 3
if (currentLevel === 3 && currentScore >= 600) {
// Unlock level 4
level4Unlocked = true;
storage.level4Unlocked = true;
currentLevel = 4;
// Update yellow cloud spawn interval for level 4 (1.5x more frequent than level 2)
yellowCloudSpawnInterval = Math.floor(960 / 1.5);
// Reset timer to 90 seconds for level 4
gameTimeLeft = 5400;
// Reset score to 0 for level 4
currentScore = 0;
scoreText.setText('Score: 0');
// Reset lives for new level
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
// Flash screen to indicate level change
LK.effects.flashScreen(0x9C27B0, 500); // Purple flash for level 4
// Update level display
levelText.setText('Level 4');
levelText.fill = 0x9C27B0; // Purple color for level 4
// Update level 4 button appearance and text
level4Button.tint = 0x9C27B0;
level4Text.setText('Level 4');
}
// Check for level 5 unlock at 800 points in level 4
if (currentLevel === 4 && currentScore >= 800) {
// Unlock level 5
level5Unlocked = true;
storage.level5Unlocked = true;
currentLevel = 5;
// Update yellow cloud spawn interval for level 5 (1.2x more frequent than level 3)
yellowCloudSpawnInterval = Math.floor(240 / 1.2);
// Reset timer to 90 seconds for level 5
gameTimeLeft = 5400;
// Reset score to 0 for level 5
currentScore = 0;
scoreText.setText('Score: 0');
// Reset lives for new level
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
// Flash screen to indicate level change
LK.effects.flashScreen(0x00FF7F, 500); // Spring green flash for level 5
// Update level display
levelText.setText('Level 5');
levelText.fill = 0x00FF7F; // Spring green color for level 5
// Update level 5 button appearance and text
level5Button.tint = 0x00FF7F;
level5Text.setText('Level 5');
}
// Check and update high score
if (currentScore > highScore) {
highScore = currentScore;
storage.highScore = highScore;
highScoreText.setText('Best: ' + highScore);
// Flash high score text when new record is achieved
tween(highScoreText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(highScoreText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
}
// Cloud generation and management
var clouds = [];
var yellowClouds = [];
var greenClouds = [];
var redClouds = [];
var cloudTimer = 0;
var yellowCloudTimer = 0;
var greenCloudTimer = 0;
var redCloudTimer = 0;
var cloudSpawnInterval = 180; // Spawn cloud every 3 seconds (60fps * 3)
var yellowCloudSpawnInterval = 480; // Spawn yellow cloud every 8 seconds (60fps * 8) - 2x less frequent
var yellowCloudSpawnIntervalLevel2 = 960; // Spawn yellow cloud every 16 seconds in level 2 - 4x less frequent than level 1
// Game update loop
game.update = function () {
// Don't update game if in level select menu
if (isInLevelSelect) {
return;
}
// Timer countdown logic
if (gameStarted && gameTimeLeft > 0) {
gameTimeLeft--;
// Update timer display
var minutes = Math.floor(gameTimeLeft / 3600); // 60 ticks per second * 60 seconds per minute
var seconds = Math.floor(gameTimeLeft % 3600 / 60);
var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timerText.setText('Time: ' + timeString);
// Change timer color when time is running low (last 30 seconds)
if (gameTimeLeft <= 1800) {
// 30 seconds
timerText.fill = 0xFF0000; // Red
} else if (gameTimeLeft <= 3600) {
// 1 minute
timerText.fill = 0xFFA500; // Orange
}
}
// End game when timer reaches zero
if (gameTimeLeft <= 0 && gameStarted) {
gameStarted = false;
// Save final score if it's a high score
if (currentScore > highScore) {
storage.highScore = currentScore;
}
// Show game over
LK.showGameOver();
}
// Cloud generation timer
cloudTimer++;
if (cloudTimer >= cloudSpawnInterval) {
cloudTimer = 0;
// Create new cloud at random position
var newCloud = new Cloud();
newCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newCloud.y = Math.random() * (maxY - minY) + minY;
clouds.push(newCloud);
game.addChild(newCloud);
}
// Yellow cloud generation timer
yellowCloudTimer++;
if (yellowCloudTimer >= yellowCloudSpawnInterval) {
yellowCloudTimer = 0;
// Create new yellow cloud at random position
var newYellowCloud = new YellowCloud();
newYellowCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newYellowCloud.y = Math.random() * (maxY - minY) + minY;
yellowClouds.push(newYellowCloud);
game.addChild(newYellowCloud);
}
// Green cloud generation timer (only in level 3 and 4)
if (currentLevel === 3) {
greenCloudTimer++;
// Green clouds spawn 2x less frequently than yellow clouds
var greenCloudSpawnInterval = yellowCloudSpawnInterval * 2;
if (greenCloudTimer >= greenCloudSpawnInterval) {
greenCloudTimer = 0;
// Create new green cloud at random position
var newGreenCloud = new GreenCloud();
newGreenCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newGreenCloud.y = Math.random() * (maxY - minY) + minY;
greenClouds.push(newGreenCloud);
game.addChild(newGreenCloud);
}
}
// Green cloud generation timer for level 4 (1.5x more frequent than level 3)
if (currentLevel === 4) {
greenCloudTimer++;
// Green clouds spawn with 1.5x probability compared to level 3
var greenCloudSpawnInterval = Math.floor(240 * 2 / 1.5); // Based on level 3 interval with 1.5x frequency
if (greenCloudTimer >= greenCloudSpawnInterval) {
greenCloudTimer = 0;
// Create new green cloud at random position
var newGreenCloud = new GreenCloud();
newGreenCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newGreenCloud.y = Math.random() * (maxY - minY) + minY;
greenClouds.push(newGreenCloud);
game.addChild(newGreenCloud);
}
}
// Level 5 cloud generation
if (currentLevel === 5) {
greenCloudTimer++;
redCloudTimer++;
// Green clouds spawn much less frequently (3x less than yellow clouds)
var greenCloudSpawnInterval = yellowCloudSpawnInterval * 3;
if (greenCloudTimer >= greenCloudSpawnInterval) {
greenCloudTimer = 0;
// Create new green cloud at random position
var newGreenCloud = new GreenCloud();
newGreenCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newGreenCloud.y = Math.random() * (maxY - minY) + minY;
greenClouds.push(newGreenCloud);
game.addChild(newGreenCloud);
}
// Red cloud generation for level 5 (same frequency as yellow clouds)
var redCloudSpawnInterval = yellowCloudSpawnInterval;
if (redCloudTimer >= redCloudSpawnInterval) {
redCloudTimer = 0;
// Create new red cloud at random position
var newRedCloud = new RedCloud();
newRedCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newRedCloud.y = Math.random() * (maxY - minY) + minY;
redClouds.push(newRedCloud);
game.addChild(newRedCloud);
}
}
// Infinite mode cloud generation (level 6)
if (currentLevel === 6) {
greenCloudTimer++;
// In infinite mode, spawn green clouds as frequently as yellow clouds
var greenCloudSpawnInterval = yellowCloudSpawnInterval;
if (greenCloudTimer >= greenCloudSpawnInterval) {
greenCloudTimer = 0;
// Create new green cloud at random position
var newGreenCloud = new GreenCloud();
newGreenCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newGreenCloud.y = Math.random() * (maxY - minY) + minY;
greenClouds.push(newGreenCloud);
game.addChild(newGreenCloud);
}
// Red cloud generation for infinite mode
redCloudTimer++;
// Red clouds spawn half as frequently as yellow clouds
var redCloudSpawnInterval = yellowCloudSpawnInterval * 2;
if (redCloudTimer >= redCloudSpawnInterval) {
redCloudTimer = 0;
// Create new red cloud at random position
var newRedCloud = new RedCloud();
newRedCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newRedCloud.y = Math.random() * (maxY - minY) + minY;
redClouds.push(newRedCloud);
game.addChild(newRedCloud);
}
}
// Check ball collision with clouds
for (var i = clouds.length - 1; i >= 0; i--) {
var cloud = clouds[i];
if (ball.intersects(cloud)) {
// Ball bounces off cloud
ball.velocityY = -Math.abs(ball.velocityY) * 0.8; // Bounce upward
ball.velocityX += cloud.velocityX * 0.5; // Transfer some cloud momentum
// Add points for hitting regular cloud
updateScore(10);
// Remove cloud on impact
cloud.destroy();
clouds.splice(i, 1);
}
}
// Check ball collision with yellow clouds
for (var i = yellowClouds.length - 1; i >= 0; i--) {
var yellowCloud = yellowClouds[i];
if (ball.intersects(yellowCloud)) {
// Ball bounces off yellow cloud with tween effect
ball.velocityY = -Math.abs(ball.velocityY) * 0.9; // Stronger bounce upward
ball.velocityX += yellowCloud.velocityX * 0.6; // Transfer more cloud momentum
// Add bonus points for hitting yellow cloud
updateScore(25);
// Add tween animation to yellow cloud before destroying
tween(yellowCloud, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
yellowCloud.destroy();
}
});
yellowClouds.splice(i, 1);
}
}
// Check ball collision with green clouds (level 3, 4, 5, and infinite mode)
if (currentLevel === 3 || currentLevel === 4 || currentLevel === 5 || currentLevel === 6) {
for (var i = greenClouds.length - 1; i >= 0; i--) {
var greenCloud = greenClouds[i];
if (ball.intersects(greenCloud)) {
// Ball bounces off green cloud with stronger effect
ball.velocityY = -Math.abs(ball.velocityY) * 1.0; // Even stronger bounce
ball.velocityX += greenCloud.velocityX * 0.7; // Transfer more momentum
// Add 50 points for hitting green cloud
updateScore(50);
// Add tween animation to green cloud before destroying
tween(greenCloud, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
greenCloud.destroy();
}
});
greenClouds.splice(i, 1);
}
}
}
// Check ball collision with red clouds (level 5 and infinite mode)
if (currentLevel === 5 || currentLevel === 6) {
for (var i = redClouds.length - 1; i >= 0; i--) {
var redCloud = redClouds[i];
if (ball.intersects(redCloud)) {
// Ball still bounces but loses a life
ball.velocityY = -Math.abs(ball.velocityY) * 0.8; // Normal bounce
ball.velocityX += redCloud.velocityX * 0.5; // Transfer some momentum
// Lose a life
currentLives--;
livesText.setText('Lives: ' + currentLives);
// Flash screen red to indicate life lost
LK.effects.flashScreen(0xFF0000, 500);
// Check for game over
if (currentLives <= 0) {
gameStarted = false;
LK.showGameOver();
}
// Add dramatic tween animation to red cloud before destroying
tween(redCloud, {
scaleX: 3.0,
scaleY: 3.0,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
redCloud.destroy();
}
});
redClouds.splice(i, 1);
}
}
}
};
// Touch interaction to set ball position to touch location
game.down = function (x, y, obj) {
// Set ball position to touch location
ball.x = x;
ball.y = y;
// Keep horizontal velocity but reset vertical velocity to maintain bouncing
ball.velocityY = 0;
};
// Play relaxing background music
LK.playMusic('relaxingMusic'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
// Attach ball graphics
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocityX = 0;
self.velocityY = 0;
self.gravity = 0.3;
self.bounce = 0.8;
// Life tracking
self.lastY = 0;
self.hasLostLife = false;
// Update physics and bouncing
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce off left and right walls
if (self.x <= 40 || self.x >= 2008) {
self.velocityX = -self.velocityX * self.bounce;
self.x = self.x <= 40 ? 40 : 2008;
}
// Define invisible barrier at one-third of screen height
var barrierY = 2732 / 3; // One-third from top
// Bounce off invisible barrier (top third) and bottom wall
if (self.y <= barrierY || self.y >= 2692) {
self.velocityY = -self.velocityY * self.bounce;
self.y = self.y <= barrierY ? barrierY : 2692;
}
// Check if ball fell below screen (lose a life)
if (self.lastY <= 2732 && self.y > 2732 && !self.hasLostLife) {
self.hasLostLife = true;
currentLives--;
livesText.setText('Lives: ' + currentLives);
// Flash screen red to indicate life lost
LK.effects.flashScreen(0xFF0000, 300);
// Reset ball position to center
self.x = 2048 / 2;
self.y = 2732 / 2;
self.velocityX = 0;
self.velocityY = 0;
// Check for game over
if (currentLives <= 0) {
gameStarted = false;
LK.showGameOver();
}
}
// Reset life loss flag when ball is back in safe area
if (self.y <= 2700) {
self.hasLostLife = false;
}
// Update last Y position
self.lastY = self.y;
// Ensure minimum velocity to keep ball moving
var minVelocity = 2;
if (Math.abs(self.velocityX) < minVelocity && Math.abs(self.velocityY) < minVelocity) {
// Add random velocity if ball is moving too slowly
self.velocityX = (Math.random() - 0.5) * minVelocity * 2;
self.velocityY = Math.random() > 0.5 ? -minVelocity : minVelocity;
}
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
// Attach cloud graphics
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.velocityX = (Math.random() - 0.5) * 2; // Random horizontal movement
self.velocityY = 0;
// Update cloud movement
self.update = function () {
// Move cloud
self.x += self.velocityX;
// Wrap around screen horizontally
if (self.x < -150) {
self.x = 2048 + 150;
} else if (self.x > 2048 + 150) {
self.x = -150;
}
};
return self;
});
var GreenCloud = Container.expand(function () {
var self = Container.call(this);
// Attach green cloud graphics
var cloudGraphics = self.attachAsset('greenCloud', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.velocityX = (Math.random() - 0.5) * 2; // Random horizontal movement
self.velocityY = 0;
// Update cloud movement
self.update = function () {
// Move cloud
self.x += self.velocityX;
// Wrap around screen horizontally
if (self.x < -150) {
self.x = 2048 + 150;
} else if (self.x > 2048 + 150) {
self.x = -150;
}
};
return self;
});
var RedCloud = Container.expand(function () {
var self = Container.call(this);
// Attach red cloud graphics with red tint
var cloudGraphics = self.attachAsset('redCloud', {
anchorX: 0.5,
anchorY: 0.5
});
cloudGraphics.tint = 0xFF0000; // Red tint
// Movement properties
self.velocityX = (Math.random() - 0.5) * 2; // Random horizontal movement
self.velocityY = 0;
// Update cloud movement
self.update = function () {
// Move cloud
self.x += self.velocityX;
// Wrap around screen horizontally
if (self.x < -150) {
self.x = 2048 + 150;
} else if (self.x > 2048 + 150) {
self.x = -150;
}
};
return self;
});
var YellowCloud = Container.expand(function () {
var self = Container.call(this);
// Attach yellow cloud graphics
var cloudGraphics = self.attachAsset('yellowCloud', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.velocityX = (Math.random() - 0.5) * 2; // Random horizontal movement
self.velocityY = 0;
// Update cloud movement
self.update = function () {
// Move cloud
self.x += self.velocityX;
// Wrap around screen horizontally
if (self.x < -150) {
self.x = 2048 + 150;
} else if (self.x > 2048 + 150) {
self.x = -150;
}
};
return self;
});
/****
* Initialize Game
****/
// Create and add the ball to the game
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Create and add the ball to the game
var ball = game.addChild(new Ball());
// Add sun decoration to top-right corner
var sun = game.addChild(LK.getAsset('sun', {
anchorX: 0.5,
anchorY: 0.5
}));
sun.x = 2048 - 150; // Position near right edge
sun.y = 150; // Position near top edge
// Add sun rays around the sun
var sunRays = [];
var numRays = 8;
for (var i = 0; i < numRays; i++) {
var ray = game.addChild(LK.getAsset('sunRay', {
anchorX: 0,
anchorY: 0.5
}));
ray.x = sun.x;
ray.y = sun.y;
ray.rotation = i * Math.PI * 2 / numRays;
sunRays.push(ray);
}
// Position ball at center of screen
ball.x = 2048 / 2;
ball.y = 2732 / 2;
// Initialize scoring system
var currentScore = 0;
var highScore = storage.highScore || 0;
var currentLevel = 1;
var level2Unlocked = storage.level2Unlocked || false;
var level3Unlocked = storage.level3Unlocked || false;
var level4Unlocked = storage.level4Unlocked || false;
var level5Unlocked = storage.level5Unlocked || false;
var isInLevelSelect = false;
// Initialize lives system
var currentLives = 3;
var maxLives = 3;
// Initialize timer system (90 seconds = 5400 ticks at 60fps)
var gameTimeLeft = 5400; // 90 seconds in ticks
var gameStarted = true;
// Create score display
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create high score display
var highScoreText = new Text2('Best: ' + highScore, {
size: 60,
fill: 0xFFFF00
});
highScoreText.anchor.set(0.5, 0);
highScoreText.y = 100;
LK.gui.top.addChild(highScoreText);
// Create timer display
var timerText = new Text2('Time: 1:30', {
size: 70,
fill: 0xFF0000
});
timerText.anchor.set(0.5, 0);
timerText.y = 180;
LK.gui.top.addChild(timerText);
// Create level display
var levelText = new Text2('Level 1', {
size: 60,
fill: 0x00FF00
});
levelText.anchor.set(0.5, 0);
levelText.y = 260;
LK.gui.top.addChild(levelText);
// Create lives display
var livesText = new Text2('Lives: 3', {
size: 60,
fill: 0xFF0000
});
livesText.anchor.set(0.5, 0);
livesText.y = 330;
LK.gui.top.addChild(livesText);
// Create level selection button
var levelButton = game.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
levelButton.x = 2048 - 100;
levelButton.y = 350;
// Create level button text
var levelButtonText = new Text2('Levels', {
size: 40,
fill: 0xFFFFFF
});
levelButtonText.anchor.set(0.5, 0.5);
levelButtonText.x = levelButton.x;
levelButtonText.y = levelButton.y;
game.addChild(levelButtonText);
// Level selection menu container
var levelSelectContainer = new Container();
levelSelectContainer.visible = false;
game.addChild(levelSelectContainer);
// Background overlay for level selection
var overlay = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
overlay.width = 2048;
overlay.height = 2732;
overlay.x = 1024;
overlay.y = 1366;
overlay.tint = 0x000000;
overlay.alpha = 0.8;
// Level 1 button
var level1Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level1Button.x = 1024;
level1Button.y = 1000;
level1Button.width = 300;
level1Button.height = 100;
level1Button.tint = 0x4CAF50;
var level1Text = new Text2('Level 1', {
size: 60,
fill: 0xFFFFFF
});
level1Text.anchor.set(0.5, 0.5);
level1Text.x = level1Button.x;
level1Text.y = level1Button.y;
levelSelectContainer.addChild(level1Text);
// Level 2 button
var level2Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level2Button.x = 1024;
level2Button.y = 1200;
level2Button.width = 300;
level2Button.height = 100;
level2Button.tint = level2Unlocked ? 0xFFD700 : 0x808080;
var level2Text = new Text2(level2Unlocked ? 'Level 2' : 'Level 2 (Locked)', {
size: 60,
fill: 0xFFFFFF
});
level2Text.anchor.set(0.5, 0.5);
level2Text.x = level2Button.x;
level2Text.y = level2Button.y;
levelSelectContainer.addChild(level2Text);
// Level 3 button
var level3Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level3Button.x = 1024;
level3Button.y = 1400;
level3Button.width = 300;
level3Button.height = 100;
level3Button.tint = level3Unlocked ? 0xFF6B6B : 0x808080;
var level3Text = new Text2(level3Unlocked ? 'Level 3' : 'Level 3 (Locked)', {
size: 60,
fill: 0xFFFFFF
});
level3Text.anchor.set(0.5, 0.5);
level3Text.x = level3Button.x;
level3Text.y = level3Button.y;
levelSelectContainer.addChild(level3Text);
// Level 4 button
var level4Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level4Button.x = 1024;
level4Button.y = 1600;
level4Button.width = 300;
level4Button.height = 100;
level4Button.tint = level4Unlocked ? 0x9C27B0 : 0x808080;
var level4Text = new Text2(level4Unlocked ? 'Level 4' : 'Level 4 (Locked)', {
size: 60,
fill: 0xFFFFFF
});
level4Text.anchor.set(0.5, 0.5);
level4Text.x = level4Button.x;
level4Text.y = level4Button.y;
levelSelectContainer.addChild(level4Text);
// Level 5 button
var level5Button = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
level5Button.x = 1024;
level5Button.y = 1800;
level5Button.width = 300;
level5Button.height = 100;
level5Button.tint = level5Unlocked ? 0x00FF7F : 0x808080;
var level5Text = new Text2(level5Unlocked ? 'Level 5' : 'Level 5 (Locked)', {
size: 60,
fill: 0xFFFFFF
});
level5Text.anchor.set(0.5, 0.5);
level5Text.x = level5Button.x;
level5Text.y = level5Button.y;
levelSelectContainer.addChild(level5Text);
// Infinite Mode button
var infiniteButton = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
infiniteButton.x = 1024;
infiniteButton.y = 2000;
infiniteButton.width = 300;
infiniteButton.height = 100;
infiniteButton.tint = 0x00BCD4;
var infiniteText = new Text2('Infinite Mode', {
size: 50,
fill: 0xFFFFFF
});
infiniteText.anchor.set(0.5, 0.5);
infiniteText.x = infiniteButton.x;
infiniteText.y = infiniteButton.y;
levelSelectContainer.addChild(infiniteText);
// Close button
var closeButton = levelSelectContainer.addChild(LK.getAsset('levelButton', {
anchorX: 0.5,
anchorY: 0.5
}));
closeButton.x = 1024;
closeButton.y = 2200;
closeButton.width = 200;
closeButton.height = 80;
closeButton.tint = 0xFF5252;
var closeText = new Text2('Close', {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = closeButton.x;
closeButton.y = closeButton.y;
levelSelectContainer.addChild(closeText);
// Button click handlers
levelButton.down = function () {
if (!isInLevelSelect && gameStarted) {
isInLevelSelect = true;
levelSelectContainer.visible = true;
gameStarted = false; // Pause the game
}
};
level1Button.down = function () {
// Start level 1
currentLevel = 1;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 1');
levelText.fill = 0x00FF00;
yellowCloudSpawnInterval = 480;
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
};
level2Button.down = function () {
if (level2Unlocked) {
// Start level 2
currentLevel = 2;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 2');
levelText.fill = 0xFFD700;
yellowCloudSpawnInterval = yellowCloudSpawnIntervalLevel2;
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
}
};
level3Button.down = function () {
if (level3Unlocked) {
// Start level 3
currentLevel = 3;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 3');
levelText.fill = 0xFF6B6B;
yellowCloudSpawnInterval = 240; // Spawn yellow clouds twice as fast as level 1
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
}
};
level4Button.down = function () {
if (level4Unlocked) {
// Start level 4
currentLevel = 4;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 4');
levelText.fill = 0x9C27B0;
yellowCloudSpawnInterval = Math.floor(960 / 1.5); // 1.5x more frequent than level 2
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
}
};
level5Button.down = function () {
if (level5Unlocked) {
// Start level 5
currentLevel = 5;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Level 5');
levelText.fill = 0x00FF7F;
yellowCloudSpawnInterval = Math.floor(240 * 1.5); // 1.5x less frequent than level 3
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
for (var i = redClouds.length - 1; i >= 0; i--) {
redClouds[i].destroy();
}
redClouds = [];
}
};
infiniteButton.down = function () {
// Start infinite mode
currentLevel = 6;
currentScore = 0;
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
gameTimeLeft = 5400;
scoreText.setText('Score: 0');
levelText.setText('Infinite Mode');
levelText.fill = 0x00BCD4;
yellowCloudSpawnInterval = 240; // Fast spawn rate for all clouds
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
// Clear existing clouds
for (var i = clouds.length - 1; i >= 0; i--) {
clouds[i].destroy();
}
clouds = [];
for (var i = yellowClouds.length - 1; i >= 0; i--) {
yellowClouds[i].destroy();
}
yellowClouds = [];
for (var i = greenClouds.length - 1; i >= 0; i--) {
greenClouds[i].destroy();
}
greenClouds = [];
for (var i = redClouds.length - 1; i >= 0; i--) {
redClouds[i].destroy();
}
redClouds = [];
};
closeButton.down = function () {
levelSelectContainer.visible = false;
isInLevelSelect = false;
gameStarted = true;
};
// Function to update score
function updateScore(points) {
currentScore += points;
scoreText.setText('Score: ' + currentScore);
// Check for level transition at 250 points
if (currentLevel === 1 && currentScore >= 250) {
// Unlock level 2
level2Unlocked = true;
storage.level2Unlocked = true;
currentLevel = 2;
// Update yellow cloud spawn interval for level 2
yellowCloudSpawnInterval = yellowCloudSpawnIntervalLevel2;
// Reset timer to 90 seconds for level 2
gameTimeLeft = 5400; // Reset to 90 seconds
// Reset score to 0 for level 2
currentScore = 0;
scoreText.setText('Score: 0');
// Reset lives for new level
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
// Flash screen to indicate level change
LK.effects.flashScreen(0xFFD700, 500); // Gold flash for level transition
// Update level display
levelText.setText('Level 2');
levelText.fill = 0xFFD700; // Gold color for level 2
// Update level 2 button appearance and text
level2Button.tint = 0xFFD700;
level2Text.setText('Level 2');
}
// Check for level 3 unlock at 300 points in level 2
if (currentLevel === 2 && currentScore >= 300) {
// Unlock level 3
level3Unlocked = true;
storage.level3Unlocked = true;
currentLevel = 3;
// Update yellow cloud spawn interval for level 3 (more frequent)
yellowCloudSpawnInterval = 240; // Twice as fast as level 1
// Reset timer to 90 seconds for level 3
gameTimeLeft = 5400;
// Reset score to 0 for level 3
currentScore = 0;
scoreText.setText('Score: 0');
// Reset lives for new level
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
// Flash screen to indicate level change
LK.effects.flashScreen(0xFF6B6B, 500); // Red flash for level 3
// Update level display
levelText.setText('Level 3');
levelText.fill = 0xFF6B6B; // Red color for level 3
// Update level 3 button appearance and text
level3Button.tint = 0xFF6B6B;
level3Text.setText('Level 3');
}
// Check for level 4 unlock at 600 points in level 3
if (currentLevel === 3 && currentScore >= 600) {
// Unlock level 4
level4Unlocked = true;
storage.level4Unlocked = true;
currentLevel = 4;
// Update yellow cloud spawn interval for level 4 (1.5x more frequent than level 2)
yellowCloudSpawnInterval = Math.floor(960 / 1.5);
// Reset timer to 90 seconds for level 4
gameTimeLeft = 5400;
// Reset score to 0 for level 4
currentScore = 0;
scoreText.setText('Score: 0');
// Reset lives for new level
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
// Flash screen to indicate level change
LK.effects.flashScreen(0x9C27B0, 500); // Purple flash for level 4
// Update level display
levelText.setText('Level 4');
levelText.fill = 0x9C27B0; // Purple color for level 4
// Update level 4 button appearance and text
level4Button.tint = 0x9C27B0;
level4Text.setText('Level 4');
}
// Check for level 5 unlock at 800 points in level 4
if (currentLevel === 4 && currentScore >= 800) {
// Unlock level 5
level5Unlocked = true;
storage.level5Unlocked = true;
currentLevel = 5;
// Update yellow cloud spawn interval for level 5 (1.2x more frequent than level 3)
yellowCloudSpawnInterval = Math.floor(240 / 1.2);
// Reset timer to 90 seconds for level 5
gameTimeLeft = 5400;
// Reset score to 0 for level 5
currentScore = 0;
scoreText.setText('Score: 0');
// Reset lives for new level
currentLives = maxLives;
livesText.setText('Lives: ' + currentLives);
// Flash screen to indicate level change
LK.effects.flashScreen(0x00FF7F, 500); // Spring green flash for level 5
// Update level display
levelText.setText('Level 5');
levelText.fill = 0x00FF7F; // Spring green color for level 5
// Update level 5 button appearance and text
level5Button.tint = 0x00FF7F;
level5Text.setText('Level 5');
}
// Check and update high score
if (currentScore > highScore) {
highScore = currentScore;
storage.highScore = highScore;
highScoreText.setText('Best: ' + highScore);
// Flash high score text when new record is achieved
tween(highScoreText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(highScoreText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
}
// Cloud generation and management
var clouds = [];
var yellowClouds = [];
var greenClouds = [];
var redClouds = [];
var cloudTimer = 0;
var yellowCloudTimer = 0;
var greenCloudTimer = 0;
var redCloudTimer = 0;
var cloudSpawnInterval = 180; // Spawn cloud every 3 seconds (60fps * 3)
var yellowCloudSpawnInterval = 480; // Spawn yellow cloud every 8 seconds (60fps * 8) - 2x less frequent
var yellowCloudSpawnIntervalLevel2 = 960; // Spawn yellow cloud every 16 seconds in level 2 - 4x less frequent than level 1
// Game update loop
game.update = function () {
// Don't update game if in level select menu
if (isInLevelSelect) {
return;
}
// Timer countdown logic
if (gameStarted && gameTimeLeft > 0) {
gameTimeLeft--;
// Update timer display
var minutes = Math.floor(gameTimeLeft / 3600); // 60 ticks per second * 60 seconds per minute
var seconds = Math.floor(gameTimeLeft % 3600 / 60);
var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timerText.setText('Time: ' + timeString);
// Change timer color when time is running low (last 30 seconds)
if (gameTimeLeft <= 1800) {
// 30 seconds
timerText.fill = 0xFF0000; // Red
} else if (gameTimeLeft <= 3600) {
// 1 minute
timerText.fill = 0xFFA500; // Orange
}
}
// End game when timer reaches zero
if (gameTimeLeft <= 0 && gameStarted) {
gameStarted = false;
// Save final score if it's a high score
if (currentScore > highScore) {
storage.highScore = currentScore;
}
// Show game over
LK.showGameOver();
}
// Cloud generation timer
cloudTimer++;
if (cloudTimer >= cloudSpawnInterval) {
cloudTimer = 0;
// Create new cloud at random position
var newCloud = new Cloud();
newCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newCloud.y = Math.random() * (maxY - minY) + minY;
clouds.push(newCloud);
game.addChild(newCloud);
}
// Yellow cloud generation timer
yellowCloudTimer++;
if (yellowCloudTimer >= yellowCloudSpawnInterval) {
yellowCloudTimer = 0;
// Create new yellow cloud at random position
var newYellowCloud = new YellowCloud();
newYellowCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newYellowCloud.y = Math.random() * (maxY - minY) + minY;
yellowClouds.push(newYellowCloud);
game.addChild(newYellowCloud);
}
// Green cloud generation timer (only in level 3 and 4)
if (currentLevel === 3) {
greenCloudTimer++;
// Green clouds spawn 2x less frequently than yellow clouds
var greenCloudSpawnInterval = yellowCloudSpawnInterval * 2;
if (greenCloudTimer >= greenCloudSpawnInterval) {
greenCloudTimer = 0;
// Create new green cloud at random position
var newGreenCloud = new GreenCloud();
newGreenCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newGreenCloud.y = Math.random() * (maxY - minY) + minY;
greenClouds.push(newGreenCloud);
game.addChild(newGreenCloud);
}
}
// Green cloud generation timer for level 4 (1.5x more frequent than level 3)
if (currentLevel === 4) {
greenCloudTimer++;
// Green clouds spawn with 1.5x probability compared to level 3
var greenCloudSpawnInterval = Math.floor(240 * 2 / 1.5); // Based on level 3 interval with 1.5x frequency
if (greenCloudTimer >= greenCloudSpawnInterval) {
greenCloudTimer = 0;
// Create new green cloud at random position
var newGreenCloud = new GreenCloud();
newGreenCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newGreenCloud.y = Math.random() * (maxY - minY) + minY;
greenClouds.push(newGreenCloud);
game.addChild(newGreenCloud);
}
}
// Level 5 cloud generation
if (currentLevel === 5) {
greenCloudTimer++;
redCloudTimer++;
// Green clouds spawn much less frequently (3x less than yellow clouds)
var greenCloudSpawnInterval = yellowCloudSpawnInterval * 3;
if (greenCloudTimer >= greenCloudSpawnInterval) {
greenCloudTimer = 0;
// Create new green cloud at random position
var newGreenCloud = new GreenCloud();
newGreenCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newGreenCloud.y = Math.random() * (maxY - minY) + minY;
greenClouds.push(newGreenCloud);
game.addChild(newGreenCloud);
}
// Red cloud generation for level 5 (same frequency as yellow clouds)
var redCloudSpawnInterval = yellowCloudSpawnInterval;
if (redCloudTimer >= redCloudSpawnInterval) {
redCloudTimer = 0;
// Create new red cloud at random position
var newRedCloud = new RedCloud();
newRedCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newRedCloud.y = Math.random() * (maxY - minY) + minY;
redClouds.push(newRedCloud);
game.addChild(newRedCloud);
}
}
// Infinite mode cloud generation (level 6)
if (currentLevel === 6) {
greenCloudTimer++;
// In infinite mode, spawn green clouds as frequently as yellow clouds
var greenCloudSpawnInterval = yellowCloudSpawnInterval;
if (greenCloudTimer >= greenCloudSpawnInterval) {
greenCloudTimer = 0;
// Create new green cloud at random position
var newGreenCloud = new GreenCloud();
newGreenCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newGreenCloud.y = Math.random() * (maxY - minY) + minY;
greenClouds.push(newGreenCloud);
game.addChild(newGreenCloud);
}
// Red cloud generation for infinite mode
redCloudTimer++;
// Red clouds spawn half as frequently as yellow clouds
var redCloudSpawnInterval = yellowCloudSpawnInterval * 2;
if (redCloudTimer >= redCloudSpawnInterval) {
redCloudTimer = 0;
// Create new red cloud at random position
var newRedCloud = new RedCloud();
newRedCloud.x = Math.random() * 2048;
// Define barrier position (same as in Ball class)
var barrierY = 2732 / 3;
// Spawn clouds only below the barrier where ball can reach
var minY = barrierY + 150; // Add some margin below barrier
var maxY = 2692 - 150; // Add some margin above ground
newRedCloud.y = Math.random() * (maxY - minY) + minY;
redClouds.push(newRedCloud);
game.addChild(newRedCloud);
}
}
// Check ball collision with clouds
for (var i = clouds.length - 1; i >= 0; i--) {
var cloud = clouds[i];
if (ball.intersects(cloud)) {
// Ball bounces off cloud
ball.velocityY = -Math.abs(ball.velocityY) * 0.8; // Bounce upward
ball.velocityX += cloud.velocityX * 0.5; // Transfer some cloud momentum
// Add points for hitting regular cloud
updateScore(10);
// Remove cloud on impact
cloud.destroy();
clouds.splice(i, 1);
}
}
// Check ball collision with yellow clouds
for (var i = yellowClouds.length - 1; i >= 0; i--) {
var yellowCloud = yellowClouds[i];
if (ball.intersects(yellowCloud)) {
// Ball bounces off yellow cloud with tween effect
ball.velocityY = -Math.abs(ball.velocityY) * 0.9; // Stronger bounce upward
ball.velocityX += yellowCloud.velocityX * 0.6; // Transfer more cloud momentum
// Add bonus points for hitting yellow cloud
updateScore(25);
// Add tween animation to yellow cloud before destroying
tween(yellowCloud, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
yellowCloud.destroy();
}
});
yellowClouds.splice(i, 1);
}
}
// Check ball collision with green clouds (level 3, 4, 5, and infinite mode)
if (currentLevel === 3 || currentLevel === 4 || currentLevel === 5 || currentLevel === 6) {
for (var i = greenClouds.length - 1; i >= 0; i--) {
var greenCloud = greenClouds[i];
if (ball.intersects(greenCloud)) {
// Ball bounces off green cloud with stronger effect
ball.velocityY = -Math.abs(ball.velocityY) * 1.0; // Even stronger bounce
ball.velocityX += greenCloud.velocityX * 0.7; // Transfer more momentum
// Add 50 points for hitting green cloud
updateScore(50);
// Add tween animation to green cloud before destroying
tween(greenCloud, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
greenCloud.destroy();
}
});
greenClouds.splice(i, 1);
}
}
}
// Check ball collision with red clouds (level 5 and infinite mode)
if (currentLevel === 5 || currentLevel === 6) {
for (var i = redClouds.length - 1; i >= 0; i--) {
var redCloud = redClouds[i];
if (ball.intersects(redCloud)) {
// Ball still bounces but loses a life
ball.velocityY = -Math.abs(ball.velocityY) * 0.8; // Normal bounce
ball.velocityX += redCloud.velocityX * 0.5; // Transfer some momentum
// Lose a life
currentLives--;
livesText.setText('Lives: ' + currentLives);
// Flash screen red to indicate life lost
LK.effects.flashScreen(0xFF0000, 500);
// Check for game over
if (currentLives <= 0) {
gameStarted = false;
LK.showGameOver();
}
// Add dramatic tween animation to red cloud before destroying
tween(redCloud, {
scaleX: 3.0,
scaleY: 3.0,
alpha: 0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
redCloud.destroy();
}
});
redClouds.splice(i, 1);
}
}
}
};
// Touch interaction to set ball position to touch location
game.down = function (x, y, obj) {
// Set ball position to touch location
ball.x = x;
ball.y = y;
// Keep horizontal velocity but reset vertical velocity to maintain bouncing
ball.velocityY = 0;
};
// Play relaxing background music
LK.playMusic('relaxingMusic');
Una nube . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Haz una nube amarilla . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Una bola con ojos. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Nube verde. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Nube roja. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat