/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.radius = ballGraphics.width / 2; self.velocityX = 0; self.velocityY = 0; self.active = false; self.damage = 1; self.launch = function (startX, startY, velX, velY) { self.x = startX; self.y = startY; tween(self, { velocityX: velX * 2, velocityY: velY * 2 }, { duration: 500, easing: tween.quadraticOut }); self.active = true; }; self.update = function () { if (!self.active) { return; } // Move the ball self.x += self.velocityX; self.y += self.velocityY; // Bounce off walls if (self.x - self.radius < 0 || self.x + self.radius > 2048) { self.velocityX = -self.velocityX; LK.getSound('bounce').play(); // Fix position if out of bounds if (self.x - self.radius < 0) { self.x = self.radius; } else if (self.x + self.radius > 2048) { self.x = 2048 - self.radius; } } // Bounce off top if (self.y - self.radius < 0) { self.velocityY = -self.velocityY; LK.getSound('bounce').play(); self.y = self.radius; } // Check if ball is off-screen at bottom if (self.y - self.radius > 2732) { self.active = false; } }; return self; }); var EnemyProjectile = Container.expand(function () { var self = Container.call(this); var projectileGraphics = self.attachAsset('enemyProjectile', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.active = true; self.update = function () { self.y += self.speed; if (self.y > 2732) { self.active = false; } }; return self; }); var Explosion = Container.expand(function () { var self = Container.call(this); var explosionGraphics = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); self.lifetime = 30; // frames self.age = 0; self.update = function () { self.age++; // Scale up and fade out var progress = self.age / self.lifetime; self.scale.set(1 + progress); explosionGraphics.alpha = 0.8 * (1 - progress); return self.age >= self.lifetime; }; 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 = 15; self.targetX = null; self.move = function (x, y) { self.targetX = x; }; self.update = function () { if (self.targetX !== null) { tween(self, { x: self.targetX }, { duration: 300, easing: tween.quadraticOut, onUpdate: function onUpdate() { // Constrain to screen bounds if (self.x < self.width / 2) { self.x = self.width / 2; } else if (self.x > 2048 - self.width / 2) { self.x = 2048 - self.width / 2; } } }); self.targetX = null; // Reset targetX after tweening } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); self.type = 'none'; self.speed = 3; self.active = true; self.setType = function (type) { self.type = type; switch (type) { case 'multiball': powerUpGraphics.tint = 0xFFFF00; break; case 'widepaddle': powerUpGraphics.tint = 0x00FFFF; break; case 'slowmotion': powerUpGraphics.tint = 0xFF00FF; break; } return self; }; self.update = function () { self.y += self.speed; if (self.y > 2732) { self.active = false; } // Bob up and down animation self.y += Math.sin(LK.ticks / 10) * 0.5; }; return self; }); var Tank = Container.expand(function () { var self = Container.call(this); var tankBody = self.attachAsset('tank', { anchorX: 0.5, anchorY: 0.5 }); self.width = tankBody.width; self.height = tankBody.height; self.health = 3; self.maxHealth = 3; self.speed = 1; self.fireRate = 3000; self.lastFire = 0; self.value = 100; self.type = 'basic'; self.update = function () { // Stop tank movement when reaching the middle of the screen if (self.lastY <= screenHeight / 2 && self.y > screenHeight / 2) { self.speed = 0; } self.y += self.speed; // Check if tank has passed the paddle zone if (self.lastY <= paddle.y && self.y > paddle.y) { // Trigger game over LK.showGameOver(); return; } // Fire logic if (LK.ticks - self.lastFire > self.fireRate / (1000 / 60)) { self.lastFire = LK.ticks; return true; // Signal to the game that we should fire } return false; }; self.hit = function (damage) { self.health -= damage; // Visual feedback tween(tankBody, { alpha: 0.3 // Increase alpha for more noticeable feedback }, { duration: 100, onFinish: function onFinish() { tween(tankBody, { alpha: 1 }, { duration: 300 // Extend duration for more noticeable feedback }); } }); LK.getSound('tankHit').play(); return self.health <= 0; }; self.setType = function (type, wave) { self.type = type; switch (type) { case 'basic': tankBody.tint = 0xFFFFFF; self.health = self.maxHealth = 5; // Set health to 5 for destruction after 5 hits self.speed = 0.2 + wave * 0.03; self.fireRate = 3000; self.value = 100; break; case 'fast': tankBody.tint = 0x00AA00; self.health = self.maxHealth = 2; self.speed = 2 + wave * 0.15; self.fireRate = 4000; self.value = 150; break; case 'heavy': tankBody.tint = 0x0000AA; self.health = self.maxHealth = 5 + Math.floor(wave / 2); self.speed = 0.5 + wave * 0.05; self.fireRate = 5000; self.value = 200; break; } return self; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000033 }); /**** * Game Code ****/ //{0.1} // Game settings and variables var screenWidth = 2048; var screenHeight = 2732; var gameActive = false; var score = 0; var lives = 3; var wave = 1; var waveSize = 5; var defenseLine = null; var paddle = null; var balls = []; var tanks = []; var projectiles = []; var explosions = []; var powerUps = []; var nextBallId = 0; var powerUpTimer = 0; var slowMotionActive = false; var slowMotionTimer = 0; var dragTarget = null; // UI elements var scoreTxt = new Text2('SCORE: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -250; scoreTxt.y = 20; var livesTxt = new Text2('LIVES: ' + lives, { size: 60, fill: 0xFFFFFF }); livesTxt.anchor.set(0, 0); LK.gui.top.addChild(livesTxt); livesTxt.x = -80; livesTxt.y = 20; var waveTxt = new Text2('WAVE: ' + wave, { size: 60, fill: 0xFFFFFF }); waveTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(waveTxt); waveTxt.x = 120; // Keep away from top-left corner (menu area) waveTxt.y = 20; // Initialize game elements function initGame() { score = 0; var background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: screenWidth / 2, y: screenHeight / 2 }); game.addChild(background); lives = 3; wave = 1; gameActive = true; balls = []; tanks = []; projectiles = []; explosions = []; powerUps = []; powerUpTimer = 0; slowMotionActive = false; slowMotionTimer = 0; // Update UI updateUI(); // Create paddle paddle = game.addChild(new Paddle()); paddle.x = screenWidth / 2; paddle.y = screenHeight - 120; // Create initial ball createBall(); // Create initial wave createWave(); // Start music LK.playMusic('battleMusic', { fade: { start: 0, end: 0.7, duration: 1000 } }); } function createBall() { var ball = new Ball(); ball.id = nextBallId++; balls.push(ball); game.addChild(ball); // Start the ball from the paddle position ball.launch(paddle.x, paddle.y - paddle.height / 2 - ball.radius, Math.random() * 10 - 5, -8); return ball; } function createWave() { var currentWaveSize = waveSize + Math.floor(wave / 2); for (var i = 0; i < currentWaveSize; i++) { var tankType = 'basic'; var rand = Math.random(); // More advanced tanks in higher waves if (wave > 2) { if (rand < 0.2) { tankType = 'heavy'; } else if (rand < 0.5) { tankType = 'fast'; } } else if (wave > 1) { if (rand < 0.3) { tankType = 'fast'; } } var tank = new Tank().setType(tankType, wave); tank.x = 200 + (screenWidth - 400) * (i / Math.max(1, currentWaveSize - 1)); tank.y = 150 + Math.random() * 100; tanks.push(tank); game.addChild(tank); } // Update wave text waveTxt.setText('WAVE: ' + wave); } function createExplosion(x, y) { var explosion = new Explosion(); explosion.x = x; explosion.y = y; explosions.push(explosion); game.addChild(explosion); LK.getSound('tankDestroy').play(); } function createPowerUp(x, y) { if (Math.random() > 0.3) { return; } // 30% chance to drop var powerUp = new PowerUp(); // Choose power-up type var rand = Math.random(); var type = 'multiball'; if (rand < 0.33) { type = 'multiball'; } else if (rand < 0.66) { type = 'widepaddle'; } else { type = 'slowmotion'; } powerUp.setType(type); powerUp.x = x; powerUp.y = y; powerUps.push(powerUp); game.addChild(powerUp); } function tankFire(tank) { var projectile = new EnemyProjectile(); projectile.x = tank.x; projectile.y = tank.y + tank.height / 2; projectiles.push(projectile); game.addChild(projectile); } function activatePowerUp(type) { LK.getSound('powerUp').play(); switch (type) { case 'multiball': // Create 2 additional balls for (var i = 0; i < 2; i++) { var ball = createBall(); ball.velocityX = Math.random() * 10 - 5; } break; case 'widepaddle': // Make paddle wider temporarily tween(paddle, { scaleX: 1.5 }, { duration: 500, onFinish: function onFinish() { // Schedule return to normal size LK.setTimeout(function () { tween(paddle, { scaleX: 1 }, { duration: 500 }); }, 10000); } }); break; case 'slowmotion': // Slow down all enemy tanks and projectiles slowMotionActive = true; slowMotionTimer = 600; // 10 seconds at 60fps break; } } function checkCollisions() { // Ball collision with paddle for (var i = 0; i < balls.length; i++) { var ball = balls[i]; if (!ball.active) { continue; } // Check paddle collision if (ball.velocityY > 0 && 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 * paddle.scaleX && ball.x - ball.radius <= paddle.x + paddle.width / 2 * paddle.scaleX) { // Calculate reflection angle based on hit position var hitPos = (ball.x - paddle.x) / (paddle.width / 2 * paddle.scaleX); ball.velocityX = hitPos * 10; // More angle at edges ball.velocityY = -Math.abs(ball.velocityY); // Always bounce upward // Add some randomness ball.velocityX += (Math.random() - 0.5) * 2; ball.velocityY -= Math.random() * 2; // Ensure velocity doesn't get too small if (Math.abs(ball.velocityY) < 4) { ball.velocityY = -4; } LK.getSound('bounce').play(); } // Check tank collisions for (var j = 0; j < tanks.length; j++) { var tank = tanks[j]; if (ball.intersects(tank)) { // Bounce off tank if (ball.x < tank.x - tank.width / 4 || ball.x > tank.x + tank.width / 4) { ball.velocityX = -ball.velocityX; } else { ball.velocityY = -ball.velocityY; } // Add some randomness to bounce ball.velocityX += (Math.random() - 0.5) * 2; ball.velocityY += (Math.random() - 0.5) * 2; // Damage tank var destroyed = tank.hit(ball.damage); if (destroyed) { // Create explosion createExplosion(tank.x, tank.y); // Maybe drop a power-up createPowerUp(tank.x, tank.y); // Update score score += tank.value; updateUI(); // Remove tank tank.destroy(); tanks.splice(j, 1); j--; } break; } } } // Projectile collision with paddle and defense line for (var i = 0; i < projectiles.length; i++) { var projectile = projectiles[i]; if (!projectile.active) { continue; } // Check paddle collision if (projectile.intersects(paddle)) { // Trigger game over lives = 0; updateUI(); endGame(); return; // Remove projectile projectile.destroy(); projectiles.splice(i, 1); i--; LK.getSound('bounce').play(); } } // Power-up collision with paddle for (var i = 0; i < powerUps.length; i++) { var powerUp = powerUps[i]; if (!powerUp.active) { continue; } if (powerUp.intersects(paddle)) { activatePowerUp(powerUp.type); // Remove power-up powerUp.destroy(); powerUps.splice(i, 1); i--; } } } function updateUI() { scoreTxt.setText('SCORE: ' + score); livesTxt.setText('LIVES: ' + lives); waveTxt.setText('WAVE: ' + wave); } function endGame() { gameActive = false; // Check for high score if (score > storage.highScore) { storage.highScore = score; } // Stop music with fade out LK.playMusic('battleMusic', { fade: { start: 0.7, end: 0, duration: 800 } }); LK.setTimeout(function () { LK.stopMusic(); }, 800); // Show game over screen LK.showGameOver(); } // Event handlers game.down = function (x, y, obj) { if (!gameActive) { return; } dragTarget = paddle; paddle.move(x, y); }; game.up = function (x, y, obj) { dragTarget = null; }; game.move = function (x, y, obj) { if (dragTarget) { dragTarget.move(x, y); } }; // Main update loop game.update = function () { if (!gameActive) { initGame(); return; } // Update slow motion timer if (slowMotionActive) { slowMotionTimer--; if (slowMotionTimer <= 0) { slowMotionActive = false; } } // Update all game elements paddle.update(); // Update balls for (var i = balls.length - 1; i >= 0; i--) { balls[i].update(); if (!balls[i].active) { balls[i].destroy(); balls.splice(i, 1); } } // Check if all balls are gone if (balls.length === 0) { createBall(); // Create a new ball } // Update tanks for (var i = 0; i < tanks.length; i++) { var shouldFire = false; // Apply slow motion effect if (!slowMotionActive || LK.ticks % 3 === 0) { shouldFire = tanks[i].update(); } if (shouldFire) { tankFire(tanks[i]); } } // Check if all tanks are destroyed if (tanks.length === 0) { // Check if it's the first wave if (wave === 1) { // Player wins if all tanks in the first wave are destroyed LK.showYouWin(); } else { // End the game as the player has hit all tanks endGame(); } return; } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { // Apply slow motion effect if (!slowMotionActive || LK.ticks % 3 === 0) { projectiles[i].update(); } if (!projectiles[i].active) { projectiles[i].destroy(); projectiles.splice(i, 1); } } // Update explosions for (var i = explosions.length - 1; i >= 0; i--) { var done = explosions[i].update(); if (done) { explosions[i].destroy(); explosions.splice(i, 1); } } // Update power-ups for (var i = powerUps.length - 1; i >= 0; i--) { powerUps[i].update(); if (!powerUps[i].active) { powerUps[i].destroy(); powerUps.splice(i, 1); } } // Check all collisions checkCollisions(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = ballGraphics.width / 2;
self.velocityX = 0;
self.velocityY = 0;
self.active = false;
self.damage = 1;
self.launch = function (startX, startY, velX, velY) {
self.x = startX;
self.y = startY;
tween(self, {
velocityX: velX * 2,
velocityY: velY * 2
}, {
duration: 500,
easing: tween.quadraticOut
});
self.active = true;
};
self.update = function () {
if (!self.active) {
return;
}
// Move the ball
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce off walls
if (self.x - self.radius < 0 || self.x + self.radius > 2048) {
self.velocityX = -self.velocityX;
LK.getSound('bounce').play();
// Fix position if out of bounds
if (self.x - self.radius < 0) {
self.x = self.radius;
} else if (self.x + self.radius > 2048) {
self.x = 2048 - self.radius;
}
}
// Bounce off top
if (self.y - self.radius < 0) {
self.velocityY = -self.velocityY;
LK.getSound('bounce').play();
self.y = self.radius;
}
// Check if ball is off-screen at bottom
if (self.y - self.radius > 2732) {
self.active = false;
}
};
return self;
});
var EnemyProjectile = Container.expand(function () {
var self = Container.call(this);
var projectileGraphics = self.attachAsset('enemyProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.active = true;
self.update = function () {
self.y += self.speed;
if (self.y > 2732) {
self.active = false;
}
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
self.lifetime = 30; // frames
self.age = 0;
self.update = function () {
self.age++;
// Scale up and fade out
var progress = self.age / self.lifetime;
self.scale.set(1 + progress);
explosionGraphics.alpha = 0.8 * (1 - progress);
return self.age >= self.lifetime;
};
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 = 15;
self.targetX = null;
self.move = function (x, y) {
self.targetX = x;
};
self.update = function () {
if (self.targetX !== null) {
tween(self, {
x: self.targetX
}, {
duration: 300,
easing: tween.quadraticOut,
onUpdate: function onUpdate() {
// Constrain to screen bounds
if (self.x < self.width / 2) {
self.x = self.width / 2;
} else if (self.x > 2048 - self.width / 2) {
self.x = 2048 - self.width / 2;
}
}
});
self.targetX = null; // Reset targetX after tweening
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'none';
self.speed = 3;
self.active = true;
self.setType = function (type) {
self.type = type;
switch (type) {
case 'multiball':
powerUpGraphics.tint = 0xFFFF00;
break;
case 'widepaddle':
powerUpGraphics.tint = 0x00FFFF;
break;
case 'slowmotion':
powerUpGraphics.tint = 0xFF00FF;
break;
}
return self;
};
self.update = function () {
self.y += self.speed;
if (self.y > 2732) {
self.active = false;
}
// Bob up and down animation
self.y += Math.sin(LK.ticks / 10) * 0.5;
};
return self;
});
var Tank = Container.expand(function () {
var self = Container.call(this);
var tankBody = self.attachAsset('tank', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = tankBody.width;
self.height = tankBody.height;
self.health = 3;
self.maxHealth = 3;
self.speed = 1;
self.fireRate = 3000;
self.lastFire = 0;
self.value = 100;
self.type = 'basic';
self.update = function () {
// Stop tank movement when reaching the middle of the screen
if (self.lastY <= screenHeight / 2 && self.y > screenHeight / 2) {
self.speed = 0;
}
self.y += self.speed;
// Check if tank has passed the paddle zone
if (self.lastY <= paddle.y && self.y > paddle.y) {
// Trigger game over
LK.showGameOver();
return;
}
// Fire logic
if (LK.ticks - self.lastFire > self.fireRate / (1000 / 60)) {
self.lastFire = LK.ticks;
return true; // Signal to the game that we should fire
}
return false;
};
self.hit = function (damage) {
self.health -= damage;
// Visual feedback
tween(tankBody, {
alpha: 0.3 // Increase alpha for more noticeable feedback
}, {
duration: 100,
onFinish: function onFinish() {
tween(tankBody, {
alpha: 1
}, {
duration: 300 // Extend duration for more noticeable feedback
});
}
});
LK.getSound('tankHit').play();
return self.health <= 0;
};
self.setType = function (type, wave) {
self.type = type;
switch (type) {
case 'basic':
tankBody.tint = 0xFFFFFF;
self.health = self.maxHealth = 5; // Set health to 5 for destruction after 5 hits
self.speed = 0.2 + wave * 0.03;
self.fireRate = 3000;
self.value = 100;
break;
case 'fast':
tankBody.tint = 0x00AA00;
self.health = self.maxHealth = 2;
self.speed = 2 + wave * 0.15;
self.fireRate = 4000;
self.value = 150;
break;
case 'heavy':
tankBody.tint = 0x0000AA;
self.health = self.maxHealth = 5 + Math.floor(wave / 2);
self.speed = 0.5 + wave * 0.05;
self.fireRate = 5000;
self.value = 200;
break;
}
return self;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
//{0.1}
// Game settings and variables
var screenWidth = 2048;
var screenHeight = 2732;
var gameActive = false;
var score = 0;
var lives = 3;
var wave = 1;
var waveSize = 5;
var defenseLine = null;
var paddle = null;
var balls = [];
var tanks = [];
var projectiles = [];
var explosions = [];
var powerUps = [];
var nextBallId = 0;
var powerUpTimer = 0;
var slowMotionActive = false;
var slowMotionTimer = 0;
var dragTarget = null;
// UI elements
var scoreTxt = new Text2('SCORE: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -250;
scoreTxt.y = 20;
var livesTxt = new Text2('LIVES: ' + lives, {
size: 60,
fill: 0xFFFFFF
});
livesTxt.anchor.set(0, 0);
LK.gui.top.addChild(livesTxt);
livesTxt.x = -80;
livesTxt.y = 20;
var waveTxt = new Text2('WAVE: ' + wave, {
size: 60,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveTxt);
waveTxt.x = 120; // Keep away from top-left corner (menu area)
waveTxt.y = 20;
// Initialize game elements
function initGame() {
score = 0;
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: screenWidth / 2,
y: screenHeight / 2
});
game.addChild(background);
lives = 3;
wave = 1;
gameActive = true;
balls = [];
tanks = [];
projectiles = [];
explosions = [];
powerUps = [];
powerUpTimer = 0;
slowMotionActive = false;
slowMotionTimer = 0;
// Update UI
updateUI();
// Create paddle
paddle = game.addChild(new Paddle());
paddle.x = screenWidth / 2;
paddle.y = screenHeight - 120;
// Create initial ball
createBall();
// Create initial wave
createWave();
// Start music
LK.playMusic('battleMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
}
function createBall() {
var ball = new Ball();
ball.id = nextBallId++;
balls.push(ball);
game.addChild(ball);
// Start the ball from the paddle position
ball.launch(paddle.x, paddle.y - paddle.height / 2 - ball.radius, Math.random() * 10 - 5, -8);
return ball;
}
function createWave() {
var currentWaveSize = waveSize + Math.floor(wave / 2);
for (var i = 0; i < currentWaveSize; i++) {
var tankType = 'basic';
var rand = Math.random();
// More advanced tanks in higher waves
if (wave > 2) {
if (rand < 0.2) {
tankType = 'heavy';
} else if (rand < 0.5) {
tankType = 'fast';
}
} else if (wave > 1) {
if (rand < 0.3) {
tankType = 'fast';
}
}
var tank = new Tank().setType(tankType, wave);
tank.x = 200 + (screenWidth - 400) * (i / Math.max(1, currentWaveSize - 1));
tank.y = 150 + Math.random() * 100;
tanks.push(tank);
game.addChild(tank);
}
// Update wave text
waveTxt.setText('WAVE: ' + wave);
}
function createExplosion(x, y) {
var explosion = new Explosion();
explosion.x = x;
explosion.y = y;
explosions.push(explosion);
game.addChild(explosion);
LK.getSound('tankDestroy').play();
}
function createPowerUp(x, y) {
if (Math.random() > 0.3) {
return;
} // 30% chance to drop
var powerUp = new PowerUp();
// Choose power-up type
var rand = Math.random();
var type = 'multiball';
if (rand < 0.33) {
type = 'multiball';
} else if (rand < 0.66) {
type = 'widepaddle';
} else {
type = 'slowmotion';
}
powerUp.setType(type);
powerUp.x = x;
powerUp.y = y;
powerUps.push(powerUp);
game.addChild(powerUp);
}
function tankFire(tank) {
var projectile = new EnemyProjectile();
projectile.x = tank.x;
projectile.y = tank.y + tank.height / 2;
projectiles.push(projectile);
game.addChild(projectile);
}
function activatePowerUp(type) {
LK.getSound('powerUp').play();
switch (type) {
case 'multiball':
// Create 2 additional balls
for (var i = 0; i < 2; i++) {
var ball = createBall();
ball.velocityX = Math.random() * 10 - 5;
}
break;
case 'widepaddle':
// Make paddle wider temporarily
tween(paddle, {
scaleX: 1.5
}, {
duration: 500,
onFinish: function onFinish() {
// Schedule return to normal size
LK.setTimeout(function () {
tween(paddle, {
scaleX: 1
}, {
duration: 500
});
}, 10000);
}
});
break;
case 'slowmotion':
// Slow down all enemy tanks and projectiles
slowMotionActive = true;
slowMotionTimer = 600; // 10 seconds at 60fps
break;
}
}
function checkCollisions() {
// Ball collision with paddle
for (var i = 0; i < balls.length; i++) {
var ball = balls[i];
if (!ball.active) {
continue;
}
// Check paddle collision
if (ball.velocityY > 0 && 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 * paddle.scaleX && ball.x - ball.radius <= paddle.x + paddle.width / 2 * paddle.scaleX) {
// Calculate reflection angle based on hit position
var hitPos = (ball.x - paddle.x) / (paddle.width / 2 * paddle.scaleX);
ball.velocityX = hitPos * 10; // More angle at edges
ball.velocityY = -Math.abs(ball.velocityY); // Always bounce upward
// Add some randomness
ball.velocityX += (Math.random() - 0.5) * 2;
ball.velocityY -= Math.random() * 2;
// Ensure velocity doesn't get too small
if (Math.abs(ball.velocityY) < 4) {
ball.velocityY = -4;
}
LK.getSound('bounce').play();
}
// Check tank collisions
for (var j = 0; j < tanks.length; j++) {
var tank = tanks[j];
if (ball.intersects(tank)) {
// Bounce off tank
if (ball.x < tank.x - tank.width / 4 || ball.x > tank.x + tank.width / 4) {
ball.velocityX = -ball.velocityX;
} else {
ball.velocityY = -ball.velocityY;
}
// Add some randomness to bounce
ball.velocityX += (Math.random() - 0.5) * 2;
ball.velocityY += (Math.random() - 0.5) * 2;
// Damage tank
var destroyed = tank.hit(ball.damage);
if (destroyed) {
// Create explosion
createExplosion(tank.x, tank.y);
// Maybe drop a power-up
createPowerUp(tank.x, tank.y);
// Update score
score += tank.value;
updateUI();
// Remove tank
tank.destroy();
tanks.splice(j, 1);
j--;
}
break;
}
}
}
// Projectile collision with paddle and defense line
for (var i = 0; i < projectiles.length; i++) {
var projectile = projectiles[i];
if (!projectile.active) {
continue;
}
// Check paddle collision
if (projectile.intersects(paddle)) {
// Trigger game over
lives = 0;
updateUI();
endGame();
return;
// Remove projectile
projectile.destroy();
projectiles.splice(i, 1);
i--;
LK.getSound('bounce').play();
}
}
// Power-up collision with paddle
for (var i = 0; i < powerUps.length; i++) {
var powerUp = powerUps[i];
if (!powerUp.active) {
continue;
}
if (powerUp.intersects(paddle)) {
activatePowerUp(powerUp.type);
// Remove power-up
powerUp.destroy();
powerUps.splice(i, 1);
i--;
}
}
}
function updateUI() {
scoreTxt.setText('SCORE: ' + score);
livesTxt.setText('LIVES: ' + lives);
waveTxt.setText('WAVE: ' + wave);
}
function endGame() {
gameActive = false;
// Check for high score
if (score > storage.highScore) {
storage.highScore = score;
}
// Stop music with fade out
LK.playMusic('battleMusic', {
fade: {
start: 0.7,
end: 0,
duration: 800
}
});
LK.setTimeout(function () {
LK.stopMusic();
}, 800);
// Show game over screen
LK.showGameOver();
}
// Event handlers
game.down = function (x, y, obj) {
if (!gameActive) {
return;
}
dragTarget = paddle;
paddle.move(x, y);
};
game.up = function (x, y, obj) {
dragTarget = null;
};
game.move = function (x, y, obj) {
if (dragTarget) {
dragTarget.move(x, y);
}
};
// Main update loop
game.update = function () {
if (!gameActive) {
initGame();
return;
}
// Update slow motion timer
if (slowMotionActive) {
slowMotionTimer--;
if (slowMotionTimer <= 0) {
slowMotionActive = false;
}
}
// Update all game elements
paddle.update();
// Update balls
for (var i = balls.length - 1; i >= 0; i--) {
balls[i].update();
if (!balls[i].active) {
balls[i].destroy();
balls.splice(i, 1);
}
}
// Check if all balls are gone
if (balls.length === 0) {
createBall(); // Create a new ball
}
// Update tanks
for (var i = 0; i < tanks.length; i++) {
var shouldFire = false;
// Apply slow motion effect
if (!slowMotionActive || LK.ticks % 3 === 0) {
shouldFire = tanks[i].update();
}
if (shouldFire) {
tankFire(tanks[i]);
}
}
// Check if all tanks are destroyed
if (tanks.length === 0) {
// Check if it's the first wave
if (wave === 1) {
// Player wins if all tanks in the first wave are destroyed
LK.showYouWin();
} else {
// End the game as the player has hit all tanks
endGame();
}
return;
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
// Apply slow motion effect
if (!slowMotionActive || LK.ticks % 3 === 0) {
projectiles[i].update();
}
if (!projectiles[i].active) {
projectiles[i].destroy();
projectiles.splice(i, 1);
}
}
// Update explosions
for (var i = explosions.length - 1; i >= 0; i--) {
var done = explosions[i].update();
if (done) {
explosions[i].destroy();
explosions.splice(i, 1);
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
powerUps[i].update();
if (!powerUps[i].active) {
powerUps[i].destroy();
powerUps.splice(i, 1);
}
}
// Check all collisions
checkCollisions();
};
2d anime top down view style brown plains landscape image game photo.
captain america shield. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
vertical 2d anime image style. german nazi ww2 battle tank. top down image. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
vertical tank bullet. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
orange yellow float explosion. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
american flag. Single Game Texture. In-Game asset.