/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Alien = Container.expand(function () { var self = Container.call(this); var alienGraphics = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5 }); self.active = true; self.width = alienGraphics.width; self.height = alienGraphics.height; self.value = 10; // Point value self.canShoot = false; self.hit = function () { if (!self.active) { return false; } self.active = false; // Create explosion effect var explosion = LK.getAsset('alienExplosion', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y }); game.addChild(explosion); tween(explosion, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { explosion.destroy(); } }); tween(self, { alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); LK.getSound('explosion').play(); LK.setScore(LK.getScore() + self.value); // Chance to drop a power-up if (Math.random() < 0.15) { createPowerUp(self.x, self.y); } return true; }; self.update = function () { // Maybe shoot if this alien can shoot if (self.active && self.canShoot && Math.random() < 0.005) { var laser = new AlienLaser(); laser.x = self.x; laser.y = self.y + self.height / 2; game.addChild(laser); alienLasers.push(laser); LK.getSound('laser').play(); } }; return self; }); var AlienLaser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('alienlaser', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.width = laserGraphics.width; self.height = laserGraphics.height; self.update = function () { self.y += self.speed; // Destroy if off screen if (self.y > 2732 + self.height) { self.destroy(); var index = alienLasers.indexOf(self); if (index > -1) { alienLasers.splice(index, 1); } } }; return self; }); var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = 12; self.speedY = -12; self.radius = ballGraphics.width / 2; self.active = false; self.superBall = false; self.reset = function () { self.x = 2048 / 2; self.y = 2732 - 200; self.active = false; self.superBall = false; ballGraphics.tint = 0xffffff; }; self.launch = function () { if (!self.active) { self.active = true; // Random initial horizontal direction if (Math.random() > 0.5) { self.speedX = -Math.abs(self.speedX); } else { self.speedX = Math.abs(self.speedX); } // Always launch upward self.speedY = -Math.abs(self.speedY); } }; self.activatePowerUp = function (type) { if (type === 'super') { self.superBall = true; ballGraphics.tint = 0xff5500; // Reset after 10 seconds LK.setTimeout(function () { if (self.superBall) { self.superBall = false; ballGraphics.tint = 0xffffff; } }, 10000); } else if (type === 'speed') { self.speedX = self.speedX * 1.5; self.speedY = self.speedY * 1.5; // Reset after 7 seconds LK.setTimeout(function () { self.speedX = self.speedX / 1.5; self.speedY = self.speedY / 1.5; }, 7000); } }; self.update = function () { if (!self.active) { return; } // Move the ball self.x += self.speedX; self.y += self.speedY; // Bounce off walls if (self.x < self.radius) { self.x = self.radius; self.speedX = Math.abs(self.speedX); LK.getSound('bounce').play(); } else if (self.x > 2048 - self.radius) { self.x = 2048 - self.radius; self.speedX = -Math.abs(self.speedX); LK.getSound('bounce').play(); } // Bounce off ceiling if (self.y < self.radius) { self.y = self.radius; self.speedY = Math.abs(self.speedY); LK.getSound('bounce').play(); } // Ball fell off screen if (self.y > 2732 + self.radius) { lives--; updateLivesDisplay(); if (lives <= 0) { LK.showGameOver(); } else { self.reset(); } } }; return self; }); var Paddle = Container.expand(function () { var self = Container.call(this); var paddleGraphics = self.attachAsset('paddle', { anchorX: 0.5, anchorY: 0.5 }); self.width = paddleGraphics.width; self.height = paddleGraphics.height; self.speed = 20; self.powerUpActive = false; self.activatePowerUp = function (type) { self.powerUpActive = true; if (type === 'wide') { // Make paddle wider tween(paddleGraphics, { width: self.width * 1.5 }, { duration: 500, easing: tween.easeOut }); // Reset after 10 seconds LK.setTimeout(function () { if (self.powerUpActive) { tween(paddleGraphics, { width: self.width }, { duration: 500, easing: tween.easeIn }); self.powerUpActive = false; } }, 10000); } }; self.down = function (x, y, obj) { draggedObject = self; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var types = ['wide', 'super', 'speed']; self.type = types[Math.floor(Math.random() * types.length)]; var color = 0xf1c40f; // Default yellow if (self.type === 'wide') { color = 0x3498db; } // Blue if (self.type === 'super') { color = 0xff5500; } // Orange if (self.type === 'speed') { color = 0xe74c3c; } // Red var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5, tint: color }); self.speed = 4; self.width = powerUpGraphics.width; self.height = powerUpGraphics.height; self.update = function () { self.y += self.speed; // Destroy if off screen if (self.y > 2732 + self.height) { self.destroy(); var index = powerUps.indexOf(self); if (index > -1) { powerUps.splice(index, 1); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000033 // Dark blue space background }); /**** * Game Code ****/ // Game state variables var paddle; var ball; var aliens = []; var alienLasers = []; var powerUps = []; var draggedObject = null; var currentWave = 1; var lives = 1; var gameStarted = false; var alienDirection = 1; // 1 = right, -1 = left var alienSpeed = 1; var alienMoveDownTimer; var alienShootingTimer; var lastActiveAlienIndex = -1; // GUI elements var scoreTxt; var livesTxt; var waveTxt; var instructionsTxt; // Initialize game elements function initGame() { // Attach background var background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 }); game.addChild(background); // Create paddle paddle = new Paddle(); paddle.x = 2048 / 2; paddle.y = 2732 - 100; game.addChild(paddle); // Create ball ball = new Ball(); ball.reset(); game.addChild(ball); // Create score display scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); // Create lives display livesTxt = new Text2('Lives: ' + lives, { size: 60, fill: 0xFFFFFF }); livesTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(livesTxt); // Position livesTxt a bit to the right to avoid the platform level menu icon livesTxt.x = 120; // Create wave display waveTxt = new Text2('Wave: ' + currentWave, { size: 60, fill: 0xFFFFFF }); waveTxt.anchor.set(0.5, 0); LK.gui.top.addChild(waveTxt); // Create instruction text instructionsTxt = new Text2('Tap to Start\nDrag paddle to move', { size: 80, fill: 0xFFFFFF }); instructionsTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(instructionsTxt); // Create aliens for first wave createWave(); // Start alien movement timer alienMoveDownTimer = LK.setInterval(moveAliensDown, 10000); // Play background music LK.playMusic('gamebgm', { fade: { start: 0, end: 0.5, duration: 1000 } }); } function createWave() { // Clear any remaining aliens from previous wave for (var i = aliens.length - 1; i >= 0; i--) { aliens[i].destroy(); } aliens = []; var rows = Math.min(3 + Math.floor(currentWave / 2), 6); var cols = Math.min(6 + Math.floor(currentWave / 3), 10); var startX = (2048 - cols * 120) / 2 + 60; var startY = 200; for (var row = 0; row < rows; row++) { for (var col = 0; col < cols; col++) { var alien = new Alien(); alien.x = startX + col * 120; alien.y = startY + row * 100; // Aliens in the bottom row can shoot alien.canShoot = row === rows - 1; // Higher row aliens are worth more points alien.value = 10 + (rows - row) * 5; game.addChild(alien); aliens.push(alien); } } // Update wave text waveTxt.setText('Wave: ' + currentWave); // Increase speed with each wave alienSpeed = 1 + currentWave * 0.3; } function moveAliensDown() { var moveDownAmount = 50; var reachedBottom = false; for (var i = 0; i < aliens.length; i++) { if (aliens[i] !== undefined && aliens[i].active) { aliens[i].y += moveDownAmount; // Check if aliens reached the bottom (player loses) if (aliens[i].y > paddle.y - 100) { reachedBottom = true; } // Reset which aliens can shoot (bottom row can shoot) aliens[i].canShoot = false; } } // Determine which aliens are in the bottom row (can shoot) updateShootingAliens(); if (reachedBottom) { LK.showGameOver(); } } function updateShootingAliens() { // Create a map to track the bottom-most alien in each column var columnMap = {}; for (var i = 0; i < aliens.length; i++) { if (aliens[i] !== undefined && aliens[i].active) { var col = Math.round(aliens[i].x / 120); if (!columnMap[col] || aliens[i].y > columnMap[col].y) { columnMap[col] = aliens[i]; } } } // Reset all shooting abilities for (var i = 0; i < aliens.length; i++) { if (aliens[i] !== undefined) { aliens[i].canShoot = false; } } // Enable shooting for bottom aliens for (var col in columnMap) { columnMap[col].canShoot = true; } } function updateLivesDisplay() { livesTxt.setText('Lives: ' + lives); } function createPowerUp(x, y) { var powerUp = new PowerUp(); powerUp.x = x; powerUp.y = y; game.addChild(powerUp); powerUps.push(powerUp); } function checkCollisions() { // Ball collision with paddle if (ball.active && ball.y + ball.radius >= paddle.y - paddle.height / 2 && ball.y - ball.radius <= paddle.y + paddle.height / 2 && ball.x + ball.radius >= paddle.x - paddle.width / 2 && ball.x - ball.radius <= paddle.x + paddle.width / 2) { // Bounce ball up ball.y = paddle.y - paddle.height / 2 - ball.radius; ball.speedY = -Math.abs(ball.speedY); // Adjust horizontal direction based on where ball hit paddle var hitPos = (ball.x - paddle.x) / (paddle.width / 2); ball.speedX = ball.speedX * 0.3 + hitPos * 8; LK.getSound('bounce').play(); } // Ball collision with aliens for (var i = aliens.length - 1; i >= 0; i--) { if (aliens[i] !== undefined && aliens[i].active && ball.active && ball.y + ball.radius >= aliens[i].y - aliens[i].height / 2 && ball.y - ball.radius <= aliens[i].y + aliens[i].height / 2 && ball.x + ball.radius >= aliens[i].x - aliens[i].width / 2 && ball.x - ball.radius <= aliens[i].x + aliens[i].width / 2) { // Destroy alien aliens[i].hit(); // Remove from array if destroyed if (!aliens[i].active) { aliens.splice(i, 1); } // If superball, don't bounce if (!ball.superBall) { // Determine bounce direction based on collision side if (aliens[i] !== undefined && aliens[i].active) { var dx = ball.x - aliens[i].x; var dy = ball.y - aliens[i].y; } if (Math.abs(dx) > Math.abs(dy)) { ball.speedX = dx > 0 ? Math.abs(ball.speedX) : -Math.abs(ball.speedX); } else { ball.speedY = dy > 0 ? Math.abs(ball.speedY) : -Math.abs(ball.speedY); } } // Update score text scoreTxt.setText('Score: ' + LK.getScore()); // Create new wave if all aliens destroyed if (aliens.length === 0) { currentWave++; createWave(); } } } // Paddle collision with powerups for (var i = powerUps.length - 1; i >= 0; i--) { if (powerUps[i].y + powerUps[i].height / 2 >= paddle.y - paddle.height / 2 && powerUps[i].y - powerUps[i].height / 2 <= paddle.y + paddle.height / 2 && powerUps[i].x + powerUps[i].width / 2 >= paddle.x - paddle.width / 2 && powerUps[i].x - powerUps[i].width / 2 <= paddle.x + paddle.width / 2) { // Activate power-up var type = powerUps[i].type; if (type === 'wide') { paddle.activatePowerUp(type); } else { ball.activatePowerUp(type); } // Play power-up sound LK.getSound('powerup').play(); // Remove power-up powerUps[i].destroy(); powerUps.splice(i, 1); } } // Paddle collision with alien lasers for (var i = alienLasers.length - 1; i >= 0; i--) { if (alienLasers[i].y + alienLasers[i].height / 2 >= paddle.y - paddle.height / 2 && alienLasers[i].y - alienLasers[i].height / 2 <= paddle.y + paddle.height / 2 && alienLasers[i].x + alienLasers[i].width / 2 >= paddle.x - paddle.width / 2 && alienLasers[i].x - alienLasers[i].width / 2 <= paddle.x + paddle.width / 2) { // Remove laser alienLasers[i].destroy(); alienLasers.splice(i, 1); // Lose a life lives--; updateLivesDisplay(); // Flash paddle to indicate hit LK.effects.flashObject(paddle, 0xff0000, 500); if (lives <= 0) { LK.showGameOver(); } } // Ball collision with alien lasers if (alienLasers[i] !== undefined && ball.active && ball.y + ball.radius >= alienLasers[i].y - alienLasers[i].height / 2 && ball.y - ball.radius <= alienLasers[i].y + alienLasers[i].height / 2 && ball.x + ball.radius >= alienLasers[i].x - alienLasers[i].width / 2 && ball.x - ball.radius <= alienLasers[i].x + alienLasers[i].width / 2) { // Destroy laser alienLasers[i].destroy(); alienLasers.splice(i, 1); // Play bounce sound LK.getSound('bounce').play(); } } } function updateAliens() { // Move aliens horizontally var reachedEdge = false; var allAliensX = aliens.map(function (alien) { return alien.active ? alien.x : null; }).filter(Boolean); if (allAliensX.length === 0) { return; } var leftmostAlien = Math.min.apply(null, allAliensX); var rightmostAlien = Math.max.apply(null, allAliensX); if (rightmostAlien + 30 >= 2048 && alienDirection > 0) { alienDirection = -1; reachedEdge = true; } else if (leftmostAlien - 30 <= 0 && alienDirection < 0) { alienDirection = 1; reachedEdge = true; } for (var i = 0; i < aliens.length; i++) { if (aliens[i] !== undefined && aliens[i].active) { aliens[i].x += alienDirection * alienSpeed; // If aliens reached edge, move them down a bit if (reachedEdge) { aliens[i].y += 20; // Check if aliens reached the bottom (player loses) if (aliens[i].y > paddle.y - 100) { LK.showGameOver(); } } } } // If aliens reached edge, update which aliens can shoot if (reachedEdge) { updateShootingAliens(); } } // Game event handlers game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; instructionsTxt.visible = false; ball.launch(); } // Start dragging paddle draggedObject = paddle; draggedObject.x = x; }; game.move = function (x, y, obj) { if (draggedObject) { // Constrain paddle to screen bounds var halfWidth = draggedObject.width / 2; var targetX = Math.max(halfWidth, Math.min(2048 - halfWidth, x)); tween.stop(draggedObject, { x: true }); // Stop any ongoing tween on x tween(draggedObject, { x: targetX }, { duration: 200, // Adjusted duration for smoother movement easing: tween.easeInOut // Easing for smooth transition }); } }; game.up = function (x, y, obj) { draggedObject = null; }; // Main update loop game.update = function () { // Only update game elements if game has started if (gameStarted) { // Update aliens updateAliens(); // Check all collisions checkCollisions(); } // Update score display scoreTxt.setText('Score: ' + LK.getScore()); }; // Initialize the game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Alien = Container.expand(function () {
var self = Container.call(this);
var alienGraphics = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.width = alienGraphics.width;
self.height = alienGraphics.height;
self.value = 10; // Point value
self.canShoot = false;
self.hit = function () {
if (!self.active) {
return false;
}
self.active = false;
// Create explosion effect
var explosion = LK.getAsset('alienExplosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y
});
game.addChild(explosion);
tween(explosion, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
tween(self, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('explosion').play();
LK.setScore(LK.getScore() + self.value);
// Chance to drop a power-up
if (Math.random() < 0.15) {
createPowerUp(self.x, self.y);
}
return true;
};
self.update = function () {
// Maybe shoot if this alien can shoot
if (self.active && self.canShoot && Math.random() < 0.005) {
var laser = new AlienLaser();
laser.x = self.x;
laser.y = self.y + self.height / 2;
game.addChild(laser);
alienLasers.push(laser);
LK.getSound('laser').play();
}
};
return self;
});
var AlienLaser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('alienlaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.width = laserGraphics.width;
self.height = laserGraphics.height;
self.update = function () {
self.y += self.speed;
// Destroy if off screen
if (self.y > 2732 + self.height) {
self.destroy();
var index = alienLasers.indexOf(self);
if (index > -1) {
alienLasers.splice(index, 1);
}
}
};
return self;
});
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 12;
self.speedY = -12;
self.radius = ballGraphics.width / 2;
self.active = false;
self.superBall = false;
self.reset = function () {
self.x = 2048 / 2;
self.y = 2732 - 200;
self.active = false;
self.superBall = false;
ballGraphics.tint = 0xffffff;
};
self.launch = function () {
if (!self.active) {
self.active = true;
// Random initial horizontal direction
if (Math.random() > 0.5) {
self.speedX = -Math.abs(self.speedX);
} else {
self.speedX = Math.abs(self.speedX);
}
// Always launch upward
self.speedY = -Math.abs(self.speedY);
}
};
self.activatePowerUp = function (type) {
if (type === 'super') {
self.superBall = true;
ballGraphics.tint = 0xff5500;
// Reset after 10 seconds
LK.setTimeout(function () {
if (self.superBall) {
self.superBall = false;
ballGraphics.tint = 0xffffff;
}
}, 10000);
} else if (type === 'speed') {
self.speedX = self.speedX * 1.5;
self.speedY = self.speedY * 1.5;
// Reset after 7 seconds
LK.setTimeout(function () {
self.speedX = self.speedX / 1.5;
self.speedY = self.speedY / 1.5;
}, 7000);
}
};
self.update = function () {
if (!self.active) {
return;
}
// Move the ball
self.x += self.speedX;
self.y += self.speedY;
// Bounce off walls
if (self.x < self.radius) {
self.x = self.radius;
self.speedX = Math.abs(self.speedX);
LK.getSound('bounce').play();
} else if (self.x > 2048 - self.radius) {
self.x = 2048 - self.radius;
self.speedX = -Math.abs(self.speedX);
LK.getSound('bounce').play();
}
// Bounce off ceiling
if (self.y < self.radius) {
self.y = self.radius;
self.speedY = Math.abs(self.speedY);
LK.getSound('bounce').play();
}
// Ball fell off screen
if (self.y > 2732 + self.radius) {
lives--;
updateLivesDisplay();
if (lives <= 0) {
LK.showGameOver();
} else {
self.reset();
}
}
};
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = paddleGraphics.width;
self.height = paddleGraphics.height;
self.speed = 20;
self.powerUpActive = false;
self.activatePowerUp = function (type) {
self.powerUpActive = true;
if (type === 'wide') {
// Make paddle wider
tween(paddleGraphics, {
width: self.width * 1.5
}, {
duration: 500,
easing: tween.easeOut
});
// Reset after 10 seconds
LK.setTimeout(function () {
if (self.powerUpActive) {
tween(paddleGraphics, {
width: self.width
}, {
duration: 500,
easing: tween.easeIn
});
self.powerUpActive = false;
}
}, 10000);
}
};
self.down = function (x, y, obj) {
draggedObject = self;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var types = ['wide', 'super', 'speed'];
self.type = types[Math.floor(Math.random() * types.length)];
var color = 0xf1c40f; // Default yellow
if (self.type === 'wide') {
color = 0x3498db;
} // Blue
if (self.type === 'super') {
color = 0xff5500;
} // Orange
if (self.type === 'speed') {
color = 0xe74c3c;
} // Red
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
self.speed = 4;
self.width = powerUpGraphics.width;
self.height = powerUpGraphics.height;
self.update = function () {
self.y += self.speed;
// Destroy if off screen
if (self.y > 2732 + self.height) {
self.destroy();
var index = powerUps.indexOf(self);
if (index > -1) {
powerUps.splice(index, 1);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033 // Dark blue space background
});
/****
* Game Code
****/
// Game state variables
var paddle;
var ball;
var aliens = [];
var alienLasers = [];
var powerUps = [];
var draggedObject = null;
var currentWave = 1;
var lives = 1;
var gameStarted = false;
var alienDirection = 1; // 1 = right, -1 = left
var alienSpeed = 1;
var alienMoveDownTimer;
var alienShootingTimer;
var lastActiveAlienIndex = -1;
// GUI elements
var scoreTxt;
var livesTxt;
var waveTxt;
var instructionsTxt;
// Initialize game elements
function initGame() {
// Attach background
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(background);
// Create paddle
paddle = new Paddle();
paddle.x = 2048 / 2;
paddle.y = 2732 - 100;
game.addChild(paddle);
// Create ball
ball = new Ball();
ball.reset();
game.addChild(ball);
// Create score display
scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
// Create lives display
livesTxt = new Text2('Lives: ' + lives, {
size: 60,
fill: 0xFFFFFF
});
livesTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesTxt);
// Position livesTxt a bit to the right to avoid the platform level menu icon
livesTxt.x = 120;
// Create wave display
waveTxt = new Text2('Wave: ' + currentWave, {
size: 60,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(waveTxt);
// Create instruction text
instructionsTxt = new Text2('Tap to Start\nDrag paddle to move', {
size: 80,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionsTxt);
// Create aliens for first wave
createWave();
// Start alien movement timer
alienMoveDownTimer = LK.setInterval(moveAliensDown, 10000);
// Play background music
LK.playMusic('gamebgm', {
fade: {
start: 0,
end: 0.5,
duration: 1000
}
});
}
function createWave() {
// Clear any remaining aliens from previous wave
for (var i = aliens.length - 1; i >= 0; i--) {
aliens[i].destroy();
}
aliens = [];
var rows = Math.min(3 + Math.floor(currentWave / 2), 6);
var cols = Math.min(6 + Math.floor(currentWave / 3), 10);
var startX = (2048 - cols * 120) / 2 + 60;
var startY = 200;
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
var alien = new Alien();
alien.x = startX + col * 120;
alien.y = startY + row * 100;
// Aliens in the bottom row can shoot
alien.canShoot = row === rows - 1;
// Higher row aliens are worth more points
alien.value = 10 + (rows - row) * 5;
game.addChild(alien);
aliens.push(alien);
}
}
// Update wave text
waveTxt.setText('Wave: ' + currentWave);
// Increase speed with each wave
alienSpeed = 1 + currentWave * 0.3;
}
function moveAliensDown() {
var moveDownAmount = 50;
var reachedBottom = false;
for (var i = 0; i < aliens.length; i++) {
if (aliens[i] !== undefined && aliens[i].active) {
aliens[i].y += moveDownAmount;
// Check if aliens reached the bottom (player loses)
if (aliens[i].y > paddle.y - 100) {
reachedBottom = true;
}
// Reset which aliens can shoot (bottom row can shoot)
aliens[i].canShoot = false;
}
}
// Determine which aliens are in the bottom row (can shoot)
updateShootingAliens();
if (reachedBottom) {
LK.showGameOver();
}
}
function updateShootingAliens() {
// Create a map to track the bottom-most alien in each column
var columnMap = {};
for (var i = 0; i < aliens.length; i++) {
if (aliens[i] !== undefined && aliens[i].active) {
var col = Math.round(aliens[i].x / 120);
if (!columnMap[col] || aliens[i].y > columnMap[col].y) {
columnMap[col] = aliens[i];
}
}
}
// Reset all shooting abilities
for (var i = 0; i < aliens.length; i++) {
if (aliens[i] !== undefined) {
aliens[i].canShoot = false;
}
}
// Enable shooting for bottom aliens
for (var col in columnMap) {
columnMap[col].canShoot = true;
}
}
function updateLivesDisplay() {
livesTxt.setText('Lives: ' + lives);
}
function createPowerUp(x, y) {
var powerUp = new PowerUp();
powerUp.x = x;
powerUp.y = y;
game.addChild(powerUp);
powerUps.push(powerUp);
}
function checkCollisions() {
// Ball collision with paddle
if (ball.active && ball.y + ball.radius >= paddle.y - paddle.height / 2 && ball.y - ball.radius <= paddle.y + paddle.height / 2 && ball.x + ball.radius >= paddle.x - paddle.width / 2 && ball.x - ball.radius <= paddle.x + paddle.width / 2) {
// Bounce ball up
ball.y = paddle.y - paddle.height / 2 - ball.radius;
ball.speedY = -Math.abs(ball.speedY);
// Adjust horizontal direction based on where ball hit paddle
var hitPos = (ball.x - paddle.x) / (paddle.width / 2);
ball.speedX = ball.speedX * 0.3 + hitPos * 8;
LK.getSound('bounce').play();
}
// Ball collision with aliens
for (var i = aliens.length - 1; i >= 0; i--) {
if (aliens[i] !== undefined && aliens[i].active && ball.active && ball.y + ball.radius >= aliens[i].y - aliens[i].height / 2 && ball.y - ball.radius <= aliens[i].y + aliens[i].height / 2 && ball.x + ball.radius >= aliens[i].x - aliens[i].width / 2 && ball.x - ball.radius <= aliens[i].x + aliens[i].width / 2) {
// Destroy alien
aliens[i].hit();
// Remove from array if destroyed
if (!aliens[i].active) {
aliens.splice(i, 1);
}
// If superball, don't bounce
if (!ball.superBall) {
// Determine bounce direction based on collision side
if (aliens[i] !== undefined && aliens[i].active) {
var dx = ball.x - aliens[i].x;
var dy = ball.y - aliens[i].y;
}
if (Math.abs(dx) > Math.abs(dy)) {
ball.speedX = dx > 0 ? Math.abs(ball.speedX) : -Math.abs(ball.speedX);
} else {
ball.speedY = dy > 0 ? Math.abs(ball.speedY) : -Math.abs(ball.speedY);
}
}
// Update score text
scoreTxt.setText('Score: ' + LK.getScore());
// Create new wave if all aliens destroyed
if (aliens.length === 0) {
currentWave++;
createWave();
}
}
}
// Paddle collision with powerups
for (var i = powerUps.length - 1; i >= 0; i--) {
if (powerUps[i].y + powerUps[i].height / 2 >= paddle.y - paddle.height / 2 && powerUps[i].y - powerUps[i].height / 2 <= paddle.y + paddle.height / 2 && powerUps[i].x + powerUps[i].width / 2 >= paddle.x - paddle.width / 2 && powerUps[i].x - powerUps[i].width / 2 <= paddle.x + paddle.width / 2) {
// Activate power-up
var type = powerUps[i].type;
if (type === 'wide') {
paddle.activatePowerUp(type);
} else {
ball.activatePowerUp(type);
}
// Play power-up sound
LK.getSound('powerup').play();
// Remove power-up
powerUps[i].destroy();
powerUps.splice(i, 1);
}
}
// Paddle collision with alien lasers
for (var i = alienLasers.length - 1; i >= 0; i--) {
if (alienLasers[i].y + alienLasers[i].height / 2 >= paddle.y - paddle.height / 2 && alienLasers[i].y - alienLasers[i].height / 2 <= paddle.y + paddle.height / 2 && alienLasers[i].x + alienLasers[i].width / 2 >= paddle.x - paddle.width / 2 && alienLasers[i].x - alienLasers[i].width / 2 <= paddle.x + paddle.width / 2) {
// Remove laser
alienLasers[i].destroy();
alienLasers.splice(i, 1);
// Lose a life
lives--;
updateLivesDisplay();
// Flash paddle to indicate hit
LK.effects.flashObject(paddle, 0xff0000, 500);
if (lives <= 0) {
LK.showGameOver();
}
}
// Ball collision with alien lasers
if (alienLasers[i] !== undefined && ball.active && ball.y + ball.radius >= alienLasers[i].y - alienLasers[i].height / 2 && ball.y - ball.radius <= alienLasers[i].y + alienLasers[i].height / 2 && ball.x + ball.radius >= alienLasers[i].x - alienLasers[i].width / 2 && ball.x - ball.radius <= alienLasers[i].x + alienLasers[i].width / 2) {
// Destroy laser
alienLasers[i].destroy();
alienLasers.splice(i, 1);
// Play bounce sound
LK.getSound('bounce').play();
}
}
}
function updateAliens() {
// Move aliens horizontally
var reachedEdge = false;
var allAliensX = aliens.map(function (alien) {
return alien.active ? alien.x : null;
}).filter(Boolean);
if (allAliensX.length === 0) {
return;
}
var leftmostAlien = Math.min.apply(null, allAliensX);
var rightmostAlien = Math.max.apply(null, allAliensX);
if (rightmostAlien + 30 >= 2048 && alienDirection > 0) {
alienDirection = -1;
reachedEdge = true;
} else if (leftmostAlien - 30 <= 0 && alienDirection < 0) {
alienDirection = 1;
reachedEdge = true;
}
for (var i = 0; i < aliens.length; i++) {
if (aliens[i] !== undefined && aliens[i].active) {
aliens[i].x += alienDirection * alienSpeed;
// If aliens reached edge, move them down a bit
if (reachedEdge) {
aliens[i].y += 20;
// Check if aliens reached the bottom (player loses)
if (aliens[i].y > paddle.y - 100) {
LK.showGameOver();
}
}
}
}
// If aliens reached edge, update which aliens can shoot
if (reachedEdge) {
updateShootingAliens();
}
}
// Game event handlers
game.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
instructionsTxt.visible = false;
ball.launch();
}
// Start dragging paddle
draggedObject = paddle;
draggedObject.x = x;
};
game.move = function (x, y, obj) {
if (draggedObject) {
// Constrain paddle to screen bounds
var halfWidth = draggedObject.width / 2;
var targetX = Math.max(halfWidth, Math.min(2048 - halfWidth, x));
tween.stop(draggedObject, {
x: true
}); // Stop any ongoing tween on x
tween(draggedObject, {
x: targetX
}, {
duration: 200,
// Adjusted duration for smoother movement
easing: tween.easeInOut // Easing for smooth transition
});
}
};
game.up = function (x, y, obj) {
draggedObject = null;
};
// Main update loop
game.update = function () {
// Only update game elements if game has started
if (gameStarted) {
// Update aliens
updateAliens();
// Check all collisions
checkCollisions();
}
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
};
// Initialize the game
initGame();
oval fire and thunder explosive event. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
silver milenium ancient ball pattern. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
blue oval beam. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
epic movie scene style big titan ufo appear on upper sky city of ancient babylonia Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
combat ufo. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows