/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { score: 0, highScore: 0 }); /**** * Classes ****/ var Alien = Container.expand(function () { var self = Container.call(this); var alienGraphics = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5 }); // Track if the alien was hit self.lastWasIntersecting = false; // Motion pattern variables self.amplitude = Math.random() * 50 + 30; self.frequency = Math.random() * 0.05 + 0.02; self.baseX = 0; self.time = Math.random() * 100; self.points = 50; self.rotationSpeed = (Math.random() - 0.5) * 0.03; // Pulsate and color effect tween(alienGraphics, { alpha: 0.7 }, { duration: 1000 + Math.random() * 1000, easing: tween.easeInOut, repeat: -1, yoyo: true }); // Update alien position with sine wave motion and rotation self.update = function () { if (game.isPaused) { return; } self.time += 0.05; self.x = self.baseX + Math.sin(self.time * self.frequency) * self.amplitude; // Slowly rotate for visual effect self.rotation += self.rotationSpeed; }; return self; }); var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); // Create trail effect var trailEnabled = true; var trailInterval = 3; // Create trail every N frames var trailCount = 0; var trails = []; var maxTrails = 5; // Initial speed properties self.speedX = 5; self.speedY = 5; self.baseSpeed = 5; self.maxSpeed = 15; // Track previous position for collision detection self.lastX = 0; self.lastY = 0; // Pulse effect for the ball tween(ballGraphics, { alpha: 0.8 }, { duration: 500, easing: tween.easeInOut, repeat: -1, yoyo: true }); // Increase ball speed with limits self.accelerate = function (amount) { // Stop any ongoing speed tweens tween.stop(self, { speedX: true, speedY: true }); // Calculate new speed maintaining direction var directionX = self.speedX >= 0 ? 1 : -1; var directionY = self.speedY >= 0 ? 1 : -1; var currentSpeed = Math.abs(self.speedX); var newSpeed = Math.min(currentSpeed + amount, self.maxSpeed); // Apply the new speed with tween effect tween(self, { speedX: newSpeed * directionX, speedY: newSpeed * directionY }, { duration: 300, easing: tween.easeOut }); // Visual feedback for speed increase ballGraphics.tint = 0xFFFF00; // Yellow tint LK.setTimeout(function () { ballGraphics.tint = 0xFFFFFF; // Reset to white }, 500); }; // Toggle trail effect self.enableTrail = function () { trailEnabled = true; }; self.disableTrail = function () { trailEnabled = false; // Remove existing trails for (var i = 0; i < trails.length; i++) { if (trails[i].parent) { trails[i].parent.removeChild(trails[i]); } } trails = []; }; // Reset ball speed to base value self.resetSpeed = function () { var directionX = self.speedX >= 0 ? 1 : -1; var directionY = self.speedY >= 0 ? 1 : -1; self.speedX = self.baseSpeed * directionX; self.speedY = self.baseSpeed * directionY; // Reset visual properties ballGraphics.tint = 0xFFFFFF; }; // Update ball position and handle boundary collisions self.update = function () { // Skip updates if game is paused if (game.isPaused) { return; } // Create trail effect if (trailEnabled) { trailCount++; if (trailCount >= trailInterval) { trailCount = 0; // Create trail particle if (self.parent) { // Make sure ball is attached to something var trail = LK.getAsset('ball', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3, tint: 0xf5e642 }); trail.x = self.x; trail.y = self.y; trail.scale.set(0.5); self.parent.addChild(trail); trails.push(trail); // Fade out and remove trail tween(trail, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 300, easing: tween.easeOut, onComplete: function onComplete() { if (trail.parent) { trail.parent.removeChild(trail); } var index = trails.indexOf(trail); if (index !== -1) { trails.splice(index, 1); } } }); // Limit number of trails if (trails.length > maxTrails) { var oldestTrail = trails.shift(); if (oldestTrail.parent) { oldestTrail.parent.removeChild(oldestTrail); } } } } } // Store last position for collision detection self.lastX = self.x; self.lastY = self.y; // Update position based on speed self.x += self.speedX; self.y += self.speedY; // Handle wall collisions if (self.x <= 0 || self.x >= 2048) { self.speedX *= -1; // Visual feedback for wall bounce LK.effects.flashObject(self, 0x00FFFF, 200); } if (self.y <= 0) { self.speedY *= -1; // Visual feedback for wall bounce LK.effects.flashObject(self, 0x00FFFF, 200); } }; return self; }); var Button = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); self.label = new Text2('', { size: 20, fill: 0xFFFFFF }); self.label.anchor.set(0.5, 0.5); self.addChild(self.label); self.setText = function (text) { self.label.setText(text); }; self.down = function () { if (self.onPress) { self.onPress(); } LK.effects.flashObject(self, 0xFFFFFF, 300); }; return self; }); var Paddle = Container.expand(function () { var self = Container.call(this); var paddleGraphics = self.attachAsset('paddle', { anchorX: 0.5, anchorY: 0.5 }); // Add glow effect to paddle var glowEnabled = true; function updateGlow() { if (!glowEnabled) { return; } // Pulse effect tween(paddleGraphics, { alpha: 0.8 }, { duration: 1000, easing: tween.easeInOut, repeat: -1, yoyo: true }); } // Call it once to start the effect updateGlow(); // Add methods to enable/disable glow self.enableGlow = function () { glowEnabled = true; updateGlow(); }; self.disableGlow = function () { glowEnabled = false; paddleGraphics.alpha = 1; }; // Handle paddle movement with constraints to keep paddle on screen self.move = function (x, y) { // Constrain paddle to screen bounds var halfWidth = paddleGraphics.width * self.scale.x / 2; if (x < halfWidth) { x = halfWidth; } else if (x > 2048 - halfWidth) { x = 2048 - halfWidth; } // Smooth movement with tween if (Math.abs(self.x - x) > 10) { tween.stop(self, { x: true }); tween(self, { x: x }, { duration: 100, easing: tween.easeOut }); } else { self.x = x; } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); // PowerUp properties self.fallSpeed = 3; self.type = "speed"; // Default type self.lastWasIntersecting = false; // Set the type and color of the power-up self.setType = function (type) { self.type = type; // Set different colors based on power-up type switch (type) { case "speed": powerUpGraphics.tint = 0xFF0000; // Red break; case "multiball": powerUpGraphics.tint = 0x00FF00; // Green break; case "expand": powerUpGraphics.tint = 0x0000FF; // Blue break; default: powerUpGraphics.tint = 0xFFFFFF; // White } }; // Update PowerUp position self.update = function () { if (game.isPaused) { return; } // Fall down self.y += self.fallSpeed; // Rotate slightly for visual effect self.rotation += 0.01; // Remove if off screen if (self.y > 2732) { self.parent.removeChild(self); } }; return self; }); var Star = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); // Initialize with random speed self.speed = Math.random() * 2 + 1; // Update star position, looping from bottom to top self.update = function () { if (game.isPaused) { return; } self.y += self.speed; // Loop back to top when star goes off screen if (self.y > 2732) { self.y = 0; self.x = Math.random() * 2048; self.speed = Math.random() * 2 + 1; self.alpha = Math.random() * 0.5 + 0.5; self.scale.set(Math.random() * 2 + 0.5); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Create starry background var stars = []; for (var i = 0; i < 100; i++) { var star = new Star(); star.x = Math.random() * 2048; star.y = Math.random() * 2732; star.alpha = Math.random() * 0.5 + 0.5; star.scale.set(Math.random() * 2 + 0.5); stars.push(star); game.addChild(star); } // Create alien targets var aliens = []; var alienRows = 3; var aliensPerRow = 7; var alienSpacingX = 250; var alienSpacingY = 120; var alienStartY = 400; for (var row = 0; row < alienRows; row++) { for (var col = 0; col < aliensPerRow; col++) { var alien = new Alien(); alien.baseX = 2048 / 2 - (aliensPerRow - 1) * alienSpacingX / 2 + col * alienSpacingX; alien.y = alienStartY + row * alienSpacingY; alien.x = alien.baseX; alien.points = 50 - row * 10; // First row worth more points alien.scale.set(0.8 - row * 0.1); // First row bigger aliens.push(alien); game.addChild(alien); } } // Create the game ball var ball = new Ball(); ball.x = 2048 / 2; ball.y = 2732 / 2; game.addChild(ball); // Create the player paddle var paddle = new Paddle(); paddle.x = 2048 / 2; paddle.y = 2732 - 100; game.addChild(paddle); // Tracking variables var score = storage.score || 0; // Load saved score or start at 0 var speedUpTimer = null; var consecutiveHits = 0; var powerUps = []; var alienCount = aliens.length; game.isPaused = false; // Initialize game paused state var paddleOriginalWidth = paddle.width; // Create score display var scoreText = new Text2('Score: ' + score, { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Create speed indicator var speedText = new Text2('Ball Speed: Normal', { size: 60, fill: 0xFFFF00 }); speedText.anchor.set(0.5, 0); speedText.y = 100; LK.gui.top.addChild(speedText); // Create high score display var highScoreText = new Text2('High Score: ' + storage.highScore, { size: 60, fill: 0xFFA500 }); highScoreText.anchor.set(0.5, 0); highScoreText.y = 200; LK.gui.top.addChild(highScoreText); // Create game status text var statusText = new Text2('', { size: 70, fill: 0x00FFFF }); statusText.anchor.set(0.5, 0.5); statusText.x = 2048 / 2; statusText.y = 2732 / 2; game.addChild(statusText); // Create hits counter display var hitsText = new Text2('Consecutive Hits: 0', { size: 50, fill: 0x00FF00 }); hitsText.anchor.set(0, 0); hitsText.x = 50; hitsText.y = 100; LK.gui.left.addChild(hitsText); // Update score display function updateScore(points) { score += points; scoreText.setText('Score: ' + score); LK.setScore(score); // Save current score to storage storage.score = score; // Update high score if needed if (score > storage.highScore) { storage.highScore = score; } } // Update speed display function updateSpeedDisplay() { var currentSpeed = Math.abs(ball.speedX); var speedLabel = "Normal"; if (currentSpeed >= ball.maxSpeed) { speedLabel = "MAX!"; } else if (currentSpeed > ball.baseSpeed + 6) { speedLabel = "Super Fast"; } else if (currentSpeed > ball.baseSpeed + 3) { speedLabel = "Fast"; } speedText.setText('Ball Speed: ' + speedLabel); } // Speed up the ball with visual effect function speedUpBall() { ball.accelerate(1); updateSpeedDisplay(); // Visual feedback for speed increase LK.effects.flashObject(ball, 0xff0000, 500); // Reset timer countdown lastSpeedUpTick = LK.ticks; } // Create a speed up button var speedUpButton = new Button(); speedUpButton.x = 2048 - 100; speedUpButton.y = 200; speedUpButton.setText("Speed"); game.addChild(speedUpButton); // Create a reset button var resetButton = new Button(); resetButton.x = 2048 - 100; resetButton.y = 300; resetButton.setText("Reset"); game.addChild(resetButton); // Create a pause button var pauseButton = new Button(); pauseButton.x = 2048 - 100; pauseButton.y = 400; pauseButton.setText("Pause"); game.addChild(pauseButton); // Event handlers speedUpButton.onPress = function () { speedUpBall(); }; resetButton.onPress = function () { // Reset ball position ball.x = 2048 / 2; ball.y = 2732 / 2; ball.resetSpeed(); updateSpeedDisplay(); }; pauseButton.onPress = function () { // Toggle game paused state var isPaused = !game.isPaused; game.isPaused = isPaused; pauseButton.setText(isPaused ? "Resume" : "Pause"); }; // Track paddle movement game.move = function (x, y) { paddle.move(x, y); }; // Collision detection function checkCollisions() { // Ball-paddle collision if (ball.lastY <= paddle.y - paddle.height / 2 && ball.y > paddle.y - paddle.height / 2 && ball.x >= paddle.x - paddle.width / 2 && ball.x <= paddle.x + paddle.width / 2) { // Bounce the ball ball.speedY *= -1; // Adjust horizontal speed based on where the ball hits the paddle var hitPoint = (ball.x - paddle.x) / (paddle.width / 2); ball.speedX = ball.speedX * 0.5 + hitPoint * 5; // Increase consecutive hits counter consecutiveHits++; // Update hits text hitsText.setText('Consecutive Hits: ' + consecutiveHits); // Speed up after certain number of consecutive hits if (consecutiveHits >= 3) { speedUpBall(); consecutiveHits = 0; statusText.setText('SPEED BOOST!'); // Flash status and make it disappear LK.effects.flashObject(statusText, 0xFFFF00, 500); LK.setTimeout(function () { statusText.setText(''); }, 1500); // Update hits text again hitsText.setText('Consecutive Hits: ' + consecutiveHits); } // Score points updateScore(10); // Play hit animation LK.effects.flashObject(paddle, 0x00FFFF, 300); } // Check ball-alien collisions for (var i = aliens.length - 1; i >= 0; i--) { var alien = aliens[i]; var currentIntersecting = ball.intersects(alien); if (!alien.lastWasIntersecting && currentIntersecting) { // Bounce ball ball.speedY *= -1; // Add points based on alien value updateScore(alien.points); // Visual feedback LK.effects.flashObject(alien, 0xFFFFFF, 200); // Remove alien game.removeChild(alien); aliens.splice(i, 1); alienCount--; // Drop power-up with 20% chance if (Math.random() < 0.2) { var powerUp = new PowerUp(); powerUp.x = alien.x; powerUp.y = alien.y; // Randomly select power-up type var types = ["speed", "multiball", "expand"]; var randomType = types[Math.floor(Math.random() * types.length)]; powerUp.setType(randomType); powerUps.push(powerUp); game.addChild(powerUp); } // Check if all aliens are destroyed if (alienCount === 0) { statusText.setText('LEVEL COMPLETE!'); LK.effects.flashScreen(0x00FF00, 800); // Add bonus points updateScore(500); // Respawn aliens after delay LK.setTimeout(function () { respawnAliens(); statusText.setText(''); }, 2000); } } // Update last intersecting state alien.lastWasIntersecting = currentIntersecting; } // Check paddle-powerup collisions for (var j = powerUps.length - 1; j >= 0; j--) { var powerUp = powerUps[j]; var isIntersecting = powerUp.intersects(paddle); if (!powerUp.lastWasIntersecting && isIntersecting) { // Apply power-up effect applyPowerUp(powerUp.type); // Visual feedback LK.effects.flashObject(paddle, 0xFFFF00, 500); // Remove power-up game.removeChild(powerUp); powerUps.splice(j, 1); } // Update last intersecting state powerUp.lastWasIntersecting = isIntersecting; } // Ball off bottom of screen (game over condition) if (ball.y > 2732) { // Show game over notification statusText.setText('GAME OVER!'); LK.effects.flashObject(statusText, 0xFF0000, 800); // Save high score before game ends if (score > storage.highScore) { storage.highScore = score; // Show new high score notification statusText.setText('NEW HIGH SCORE!'); } // Reset current score to 0 in storage storage.score = 0; // Short delay before showing game over screen LK.setTimeout(function () { LK.showGameOver(); }, 1000); } } // Apply power-up effects function applyPowerUp(type) { switch (type) { case "speed": // Speed boost speedUpBall(); statusText.setText('SPEED BOOST!'); break; case "multiball": // Multiball feature would go here // For simplicity, let's just add points updateScore(100); statusText.setText('BONUS POINTS!'); break; case "expand": // Expand paddle var originalWidth = paddle.width; tween.stop(paddle.scale); tween(paddle.scale, { x: 1.5 }, { duration: 300, easing: tween.easeOut }); // Reset after 10 seconds LK.setTimeout(function () { tween(paddle.scale, { x: 1 }, { duration: 300, easing: tween.easeIn }); }, 10000); statusText.setText('PADDLE EXPANDED!'); break; } // Clear status text after delay LK.setTimeout(function () { statusText.setText(''); }, 1500); } // Respawn aliens function respawnAliens() { // Clear any remaining aliens for (var i = aliens.length - 1; i >= 0; i--) { game.removeChild(aliens[i]); } aliens = []; // Respawn with more difficulty aliensPerRow += 1; // More aliens per row for (var row = 0; row < alienRows; row++) { for (var col = 0; col < aliensPerRow; col++) { var alien = new Alien(); alien.baseX = 2048 / 2 - (aliensPerRow - 1) * alienSpacingX / 2 + col * alienSpacingX; alien.y = alienStartY + row * alienSpacingY; alien.x = alien.baseX; alien.points = (50 - row * 10) * 1.5; // Increased points alien.scale.set(0.8 - row * 0.1); alien.frequency += 0.01; // Faster movement aliens.push(alien); game.addChild(alien); } } alienCount = aliens.length; // Speed up ball slightly speedUpBall(); } // Auto speed up every 30 seconds var speedUpInterval = LK.setInterval(function () { speedUpBall(); // Visual feedback for automatic speed up statusText.setText('AUTO SPEED BOOST!'); LK.setTimeout(function () { statusText.setText(''); }, 1500); }, 30000); // Track time until next speed up var nextSpeedUpTime = 30000; var lastSpeedUpTick = LK.ticks; // Main game update loop game.update = function () { // Skip updates if game is paused if (game.isPaused) { return; } // Update all stars for (var i = 0; i < stars.length; i++) { stars[i].update(); } // Update all aliens for (var j = 0; j < aliens.length; j++) { aliens[j].update(); } // Update all power-ups for (var k = powerUps.length - 1; k >= 0; k--) { powerUps[k].update(); // Remove power-ups that have gone off screen if (powerUps[k].y > 2732) { game.removeChild(powerUps[k]); powerUps.splice(k, 1); } } checkCollisions(); updateSpeedDisplay(); // Update speed up timer display if (!game.isPaused) { var elapsedTicks = LK.ticks - lastSpeedUpTick; var elapsedMs = elapsedTicks * (1000 / 60); // Convert ticks to ms at 60fps var remainingTime = Math.max(0, Math.ceil((nextSpeedUpTime - elapsedMs) / 1000)); // Display countdown when less than 10 seconds if (remainingTime <= 10) { // Get the current speed label without trying to parse the existing text var currentSpeed = Math.abs(ball.speedX); var speedLabel = "Normal"; if (currentSpeed >= ball.maxSpeed) { speedLabel = "MAX!"; } else if (currentSpeed > ball.baseSpeed + 6) { speedLabel = "Super Fast"; } else if (currentSpeed > ball.baseSpeed + 3) { speedLabel = "Fast"; } speedText.setText('Ball Speed: ' + speedLabel + ' (Speed up in ' + remainingTime + ')'); speedText.tint = 0xFF0000; // Red for emphasis } else { speedText.tint = 0xFFFF00; // Default yellow } // Check if it's time for speed boost (handles missed intervals) if (elapsedMs >= nextSpeedUpTime) { speedUpBall(); statusText.setText('AUTO SPEED BOOST!'); LK.setTimeout(function () { statusText.setText(''); }, 1500); lastSpeedUpTick = LK.ticks; } } // Fancy visual effect - pulsate active power-ups if (paddle.scale.x > 1) { paddle.alpha = 0.7 + Math.sin(LK.ticks * 0.1) * 0.3; } else { paddle.alpha = 1; } }; // Create speed up keyboard shortcut for testing LK.setTimeout(function () { // Initial speed boost to make the game more exciting from the start speedUpBall(); }, 3000);
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
score: 0,
highScore: 0
});
/****
* Classes
****/
var Alien = Container.expand(function () {
var self = Container.call(this);
var alienGraphics = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5
});
// Track if the alien was hit
self.lastWasIntersecting = false;
// Motion pattern variables
self.amplitude = Math.random() * 50 + 30;
self.frequency = Math.random() * 0.05 + 0.02;
self.baseX = 0;
self.time = Math.random() * 100;
self.points = 50;
self.rotationSpeed = (Math.random() - 0.5) * 0.03;
// Pulsate and color effect
tween(alienGraphics, {
alpha: 0.7
}, {
duration: 1000 + Math.random() * 1000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
// Update alien position with sine wave motion and rotation
self.update = function () {
if (game.isPaused) {
return;
}
self.time += 0.05;
self.x = self.baseX + Math.sin(self.time * self.frequency) * self.amplitude;
// Slowly rotate for visual effect
self.rotation += self.rotationSpeed;
};
return self;
});
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Create trail effect
var trailEnabled = true;
var trailInterval = 3; // Create trail every N frames
var trailCount = 0;
var trails = [];
var maxTrails = 5;
// Initial speed properties
self.speedX = 5;
self.speedY = 5;
self.baseSpeed = 5;
self.maxSpeed = 15;
// Track previous position for collision detection
self.lastX = 0;
self.lastY = 0;
// Pulse effect for the ball
tween(ballGraphics, {
alpha: 0.8
}, {
duration: 500,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
// Increase ball speed with limits
self.accelerate = function (amount) {
// Stop any ongoing speed tweens
tween.stop(self, {
speedX: true,
speedY: true
});
// Calculate new speed maintaining direction
var directionX = self.speedX >= 0 ? 1 : -1;
var directionY = self.speedY >= 0 ? 1 : -1;
var currentSpeed = Math.abs(self.speedX);
var newSpeed = Math.min(currentSpeed + amount, self.maxSpeed);
// Apply the new speed with tween effect
tween(self, {
speedX: newSpeed * directionX,
speedY: newSpeed * directionY
}, {
duration: 300,
easing: tween.easeOut
});
// Visual feedback for speed increase
ballGraphics.tint = 0xFFFF00; // Yellow tint
LK.setTimeout(function () {
ballGraphics.tint = 0xFFFFFF; // Reset to white
}, 500);
};
// Toggle trail effect
self.enableTrail = function () {
trailEnabled = true;
};
self.disableTrail = function () {
trailEnabled = false;
// Remove existing trails
for (var i = 0; i < trails.length; i++) {
if (trails[i].parent) {
trails[i].parent.removeChild(trails[i]);
}
}
trails = [];
};
// Reset ball speed to base value
self.resetSpeed = function () {
var directionX = self.speedX >= 0 ? 1 : -1;
var directionY = self.speedY >= 0 ? 1 : -1;
self.speedX = self.baseSpeed * directionX;
self.speedY = self.baseSpeed * directionY;
// Reset visual properties
ballGraphics.tint = 0xFFFFFF;
};
// Update ball position and handle boundary collisions
self.update = function () {
// Skip updates if game is paused
if (game.isPaused) {
return;
}
// Create trail effect
if (trailEnabled) {
trailCount++;
if (trailCount >= trailInterval) {
trailCount = 0;
// Create trail particle
if (self.parent) {
// Make sure ball is attached to something
var trail = LK.getAsset('ball', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
tint: 0xf5e642
});
trail.x = self.x;
trail.y = self.y;
trail.scale.set(0.5);
self.parent.addChild(trail);
trails.push(trail);
// Fade out and remove trail
tween(trail, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
easing: tween.easeOut,
onComplete: function onComplete() {
if (trail.parent) {
trail.parent.removeChild(trail);
}
var index = trails.indexOf(trail);
if (index !== -1) {
trails.splice(index, 1);
}
}
});
// Limit number of trails
if (trails.length > maxTrails) {
var oldestTrail = trails.shift();
if (oldestTrail.parent) {
oldestTrail.parent.removeChild(oldestTrail);
}
}
}
}
}
// Store last position for collision detection
self.lastX = self.x;
self.lastY = self.y;
// Update position based on speed
self.x += self.speedX;
self.y += self.speedY;
// Handle wall collisions
if (self.x <= 0 || self.x >= 2048) {
self.speedX *= -1;
// Visual feedback for wall bounce
LK.effects.flashObject(self, 0x00FFFF, 200);
}
if (self.y <= 0) {
self.speedY *= -1;
// Visual feedback for wall bounce
LK.effects.flashObject(self, 0x00FFFF, 200);
}
};
return self;
});
var Button = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.label = new Text2('', {
size: 20,
fill: 0xFFFFFF
});
self.label.anchor.set(0.5, 0.5);
self.addChild(self.label);
self.setText = function (text) {
self.label.setText(text);
};
self.down = function () {
if (self.onPress) {
self.onPress();
}
LK.effects.flashObject(self, 0xFFFFFF, 300);
};
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
// Add glow effect to paddle
var glowEnabled = true;
function updateGlow() {
if (!glowEnabled) {
return;
}
// Pulse effect
tween(paddleGraphics, {
alpha: 0.8
}, {
duration: 1000,
easing: tween.easeInOut,
repeat: -1,
yoyo: true
});
}
// Call it once to start the effect
updateGlow();
// Add methods to enable/disable glow
self.enableGlow = function () {
glowEnabled = true;
updateGlow();
};
self.disableGlow = function () {
glowEnabled = false;
paddleGraphics.alpha = 1;
};
// Handle paddle movement with constraints to keep paddle on screen
self.move = function (x, y) {
// Constrain paddle to screen bounds
var halfWidth = paddleGraphics.width * self.scale.x / 2;
if (x < halfWidth) {
x = halfWidth;
} else if (x > 2048 - halfWidth) {
x = 2048 - halfWidth;
}
// Smooth movement with tween
if (Math.abs(self.x - x) > 10) {
tween.stop(self, {
x: true
});
tween(self, {
x: x
}, {
duration: 100,
easing: tween.easeOut
});
} else {
self.x = x;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
// PowerUp properties
self.fallSpeed = 3;
self.type = "speed"; // Default type
self.lastWasIntersecting = false;
// Set the type and color of the power-up
self.setType = function (type) {
self.type = type;
// Set different colors based on power-up type
switch (type) {
case "speed":
powerUpGraphics.tint = 0xFF0000; // Red
break;
case "multiball":
powerUpGraphics.tint = 0x00FF00; // Green
break;
case "expand":
powerUpGraphics.tint = 0x0000FF; // Blue
break;
default:
powerUpGraphics.tint = 0xFFFFFF;
// White
}
};
// Update PowerUp position
self.update = function () {
if (game.isPaused) {
return;
}
// Fall down
self.y += self.fallSpeed;
// Rotate slightly for visual effect
self.rotation += 0.01;
// Remove if off screen
if (self.y > 2732) {
self.parent.removeChild(self);
}
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize with random speed
self.speed = Math.random() * 2 + 1;
// Update star position, looping from bottom to top
self.update = function () {
if (game.isPaused) {
return;
}
self.y += self.speed;
// Loop back to top when star goes off screen
if (self.y > 2732) {
self.y = 0;
self.x = Math.random() * 2048;
self.speed = Math.random() * 2 + 1;
self.alpha = Math.random() * 0.5 + 0.5;
self.scale.set(Math.random() * 2 + 0.5);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Create starry background
var stars = [];
for (var i = 0; i < 100; i++) {
var star = new Star();
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.alpha = Math.random() * 0.5 + 0.5;
star.scale.set(Math.random() * 2 + 0.5);
stars.push(star);
game.addChild(star);
}
// Create alien targets
var aliens = [];
var alienRows = 3;
var aliensPerRow = 7;
var alienSpacingX = 250;
var alienSpacingY = 120;
var alienStartY = 400;
for (var row = 0; row < alienRows; row++) {
for (var col = 0; col < aliensPerRow; col++) {
var alien = new Alien();
alien.baseX = 2048 / 2 - (aliensPerRow - 1) * alienSpacingX / 2 + col * alienSpacingX;
alien.y = alienStartY + row * alienSpacingY;
alien.x = alien.baseX;
alien.points = 50 - row * 10; // First row worth more points
alien.scale.set(0.8 - row * 0.1); // First row bigger
aliens.push(alien);
game.addChild(alien);
}
}
// Create the game ball
var ball = new Ball();
ball.x = 2048 / 2;
ball.y = 2732 / 2;
game.addChild(ball);
// Create the player paddle
var paddle = new Paddle();
paddle.x = 2048 / 2;
paddle.y = 2732 - 100;
game.addChild(paddle);
// Tracking variables
var score = storage.score || 0; // Load saved score or start at 0
var speedUpTimer = null;
var consecutiveHits = 0;
var powerUps = [];
var alienCount = aliens.length;
game.isPaused = false; // Initialize game paused state
var paddleOriginalWidth = paddle.width;
// Create score display
var scoreText = new Text2('Score: ' + score, {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Create speed indicator
var speedText = new Text2('Ball Speed: Normal', {
size: 60,
fill: 0xFFFF00
});
speedText.anchor.set(0.5, 0);
speedText.y = 100;
LK.gui.top.addChild(speedText);
// Create high score display
var highScoreText = new Text2('High Score: ' + storage.highScore, {
size: 60,
fill: 0xFFA500
});
highScoreText.anchor.set(0.5, 0);
highScoreText.y = 200;
LK.gui.top.addChild(highScoreText);
// Create game status text
var statusText = new Text2('', {
size: 70,
fill: 0x00FFFF
});
statusText.anchor.set(0.5, 0.5);
statusText.x = 2048 / 2;
statusText.y = 2732 / 2;
game.addChild(statusText);
// Create hits counter display
var hitsText = new Text2('Consecutive Hits: 0', {
size: 50,
fill: 0x00FF00
});
hitsText.anchor.set(0, 0);
hitsText.x = 50;
hitsText.y = 100;
LK.gui.left.addChild(hitsText);
// Update score display
function updateScore(points) {
score += points;
scoreText.setText('Score: ' + score);
LK.setScore(score);
// Save current score to storage
storage.score = score;
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
}
// Update speed display
function updateSpeedDisplay() {
var currentSpeed = Math.abs(ball.speedX);
var speedLabel = "Normal";
if (currentSpeed >= ball.maxSpeed) {
speedLabel = "MAX!";
} else if (currentSpeed > ball.baseSpeed + 6) {
speedLabel = "Super Fast";
} else if (currentSpeed > ball.baseSpeed + 3) {
speedLabel = "Fast";
}
speedText.setText('Ball Speed: ' + speedLabel);
}
// Speed up the ball with visual effect
function speedUpBall() {
ball.accelerate(1);
updateSpeedDisplay();
// Visual feedback for speed increase
LK.effects.flashObject(ball, 0xff0000, 500);
// Reset timer countdown
lastSpeedUpTick = LK.ticks;
}
// Create a speed up button
var speedUpButton = new Button();
speedUpButton.x = 2048 - 100;
speedUpButton.y = 200;
speedUpButton.setText("Speed");
game.addChild(speedUpButton);
// Create a reset button
var resetButton = new Button();
resetButton.x = 2048 - 100;
resetButton.y = 300;
resetButton.setText("Reset");
game.addChild(resetButton);
// Create a pause button
var pauseButton = new Button();
pauseButton.x = 2048 - 100;
pauseButton.y = 400;
pauseButton.setText("Pause");
game.addChild(pauseButton);
// Event handlers
speedUpButton.onPress = function () {
speedUpBall();
};
resetButton.onPress = function () {
// Reset ball position
ball.x = 2048 / 2;
ball.y = 2732 / 2;
ball.resetSpeed();
updateSpeedDisplay();
};
pauseButton.onPress = function () {
// Toggle game paused state
var isPaused = !game.isPaused;
game.isPaused = isPaused;
pauseButton.setText(isPaused ? "Resume" : "Pause");
};
// Track paddle movement
game.move = function (x, y) {
paddle.move(x, y);
};
// Collision detection
function checkCollisions() {
// Ball-paddle collision
if (ball.lastY <= paddle.y - paddle.height / 2 && ball.y > paddle.y - paddle.height / 2 && ball.x >= paddle.x - paddle.width / 2 && ball.x <= paddle.x + paddle.width / 2) {
// Bounce the ball
ball.speedY *= -1;
// Adjust horizontal speed based on where the ball hits the paddle
var hitPoint = (ball.x - paddle.x) / (paddle.width / 2);
ball.speedX = ball.speedX * 0.5 + hitPoint * 5;
// Increase consecutive hits counter
consecutiveHits++;
// Update hits text
hitsText.setText('Consecutive Hits: ' + consecutiveHits);
// Speed up after certain number of consecutive hits
if (consecutiveHits >= 3) {
speedUpBall();
consecutiveHits = 0;
statusText.setText('SPEED BOOST!');
// Flash status and make it disappear
LK.effects.flashObject(statusText, 0xFFFF00, 500);
LK.setTimeout(function () {
statusText.setText('');
}, 1500);
// Update hits text again
hitsText.setText('Consecutive Hits: ' + consecutiveHits);
}
// Score points
updateScore(10);
// Play hit animation
LK.effects.flashObject(paddle, 0x00FFFF, 300);
}
// Check ball-alien collisions
for (var i = aliens.length - 1; i >= 0; i--) {
var alien = aliens[i];
var currentIntersecting = ball.intersects(alien);
if (!alien.lastWasIntersecting && currentIntersecting) {
// Bounce ball
ball.speedY *= -1;
// Add points based on alien value
updateScore(alien.points);
// Visual feedback
LK.effects.flashObject(alien, 0xFFFFFF, 200);
// Remove alien
game.removeChild(alien);
aliens.splice(i, 1);
alienCount--;
// Drop power-up with 20% chance
if (Math.random() < 0.2) {
var powerUp = new PowerUp();
powerUp.x = alien.x;
powerUp.y = alien.y;
// Randomly select power-up type
var types = ["speed", "multiball", "expand"];
var randomType = types[Math.floor(Math.random() * types.length)];
powerUp.setType(randomType);
powerUps.push(powerUp);
game.addChild(powerUp);
}
// Check if all aliens are destroyed
if (alienCount === 0) {
statusText.setText('LEVEL COMPLETE!');
LK.effects.flashScreen(0x00FF00, 800);
// Add bonus points
updateScore(500);
// Respawn aliens after delay
LK.setTimeout(function () {
respawnAliens();
statusText.setText('');
}, 2000);
}
}
// Update last intersecting state
alien.lastWasIntersecting = currentIntersecting;
}
// Check paddle-powerup collisions
for (var j = powerUps.length - 1; j >= 0; j--) {
var powerUp = powerUps[j];
var isIntersecting = powerUp.intersects(paddle);
if (!powerUp.lastWasIntersecting && isIntersecting) {
// Apply power-up effect
applyPowerUp(powerUp.type);
// Visual feedback
LK.effects.flashObject(paddle, 0xFFFF00, 500);
// Remove power-up
game.removeChild(powerUp);
powerUps.splice(j, 1);
}
// Update last intersecting state
powerUp.lastWasIntersecting = isIntersecting;
}
// Ball off bottom of screen (game over condition)
if (ball.y > 2732) {
// Show game over notification
statusText.setText('GAME OVER!');
LK.effects.flashObject(statusText, 0xFF0000, 800);
// Save high score before game ends
if (score > storage.highScore) {
storage.highScore = score;
// Show new high score notification
statusText.setText('NEW HIGH SCORE!');
}
// Reset current score to 0 in storage
storage.score = 0;
// Short delay before showing game over screen
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Apply power-up effects
function applyPowerUp(type) {
switch (type) {
case "speed":
// Speed boost
speedUpBall();
statusText.setText('SPEED BOOST!');
break;
case "multiball":
// Multiball feature would go here
// For simplicity, let's just add points
updateScore(100);
statusText.setText('BONUS POINTS!');
break;
case "expand":
// Expand paddle
var originalWidth = paddle.width;
tween.stop(paddle.scale);
tween(paddle.scale, {
x: 1.5
}, {
duration: 300,
easing: tween.easeOut
});
// Reset after 10 seconds
LK.setTimeout(function () {
tween(paddle.scale, {
x: 1
}, {
duration: 300,
easing: tween.easeIn
});
}, 10000);
statusText.setText('PADDLE EXPANDED!');
break;
}
// Clear status text after delay
LK.setTimeout(function () {
statusText.setText('');
}, 1500);
}
// Respawn aliens
function respawnAliens() {
// Clear any remaining aliens
for (var i = aliens.length - 1; i >= 0; i--) {
game.removeChild(aliens[i]);
}
aliens = [];
// Respawn with more difficulty
aliensPerRow += 1; // More aliens per row
for (var row = 0; row < alienRows; row++) {
for (var col = 0; col < aliensPerRow; col++) {
var alien = new Alien();
alien.baseX = 2048 / 2 - (aliensPerRow - 1) * alienSpacingX / 2 + col * alienSpacingX;
alien.y = alienStartY + row * alienSpacingY;
alien.x = alien.baseX;
alien.points = (50 - row * 10) * 1.5; // Increased points
alien.scale.set(0.8 - row * 0.1);
alien.frequency += 0.01; // Faster movement
aliens.push(alien);
game.addChild(alien);
}
}
alienCount = aliens.length;
// Speed up ball slightly
speedUpBall();
}
// Auto speed up every 30 seconds
var speedUpInterval = LK.setInterval(function () {
speedUpBall();
// Visual feedback for automatic speed up
statusText.setText('AUTO SPEED BOOST!');
LK.setTimeout(function () {
statusText.setText('');
}, 1500);
}, 30000);
// Track time until next speed up
var nextSpeedUpTime = 30000;
var lastSpeedUpTick = LK.ticks;
// Main game update loop
game.update = function () {
// Skip updates if game is paused
if (game.isPaused) {
return;
}
// Update all stars
for (var i = 0; i < stars.length; i++) {
stars[i].update();
}
// Update all aliens
for (var j = 0; j < aliens.length; j++) {
aliens[j].update();
}
// Update all power-ups
for (var k = powerUps.length - 1; k >= 0; k--) {
powerUps[k].update();
// Remove power-ups that have gone off screen
if (powerUps[k].y > 2732) {
game.removeChild(powerUps[k]);
powerUps.splice(k, 1);
}
}
checkCollisions();
updateSpeedDisplay();
// Update speed up timer display
if (!game.isPaused) {
var elapsedTicks = LK.ticks - lastSpeedUpTick;
var elapsedMs = elapsedTicks * (1000 / 60); // Convert ticks to ms at 60fps
var remainingTime = Math.max(0, Math.ceil((nextSpeedUpTime - elapsedMs) / 1000));
// Display countdown when less than 10 seconds
if (remainingTime <= 10) {
// Get the current speed label without trying to parse the existing text
var currentSpeed = Math.abs(ball.speedX);
var speedLabel = "Normal";
if (currentSpeed >= ball.maxSpeed) {
speedLabel = "MAX!";
} else if (currentSpeed > ball.baseSpeed + 6) {
speedLabel = "Super Fast";
} else if (currentSpeed > ball.baseSpeed + 3) {
speedLabel = "Fast";
}
speedText.setText('Ball Speed: ' + speedLabel + ' (Speed up in ' + remainingTime + ')');
speedText.tint = 0xFF0000; // Red for emphasis
} else {
speedText.tint = 0xFFFF00; // Default yellow
}
// Check if it's time for speed boost (handles missed intervals)
if (elapsedMs >= nextSpeedUpTime) {
speedUpBall();
statusText.setText('AUTO SPEED BOOST!');
LK.setTimeout(function () {
statusText.setText('');
}, 1500);
lastSpeedUpTick = LK.ticks;
}
}
// Fancy visual effect - pulsate active power-ups
if (paddle.scale.x > 1) {
paddle.alpha = 0.7 + Math.sin(LK.ticks * 0.1) * 0.3;
} else {
paddle.alpha = 1;
}
};
// Create speed up keyboard shortcut for testing
LK.setTimeout(function () {
// Initial speed boost to make the game more exciting from the start
speedUpBall();
}, 3000);