/****
* Classes
****/
var Ball = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.ballType = type || 'red';
self.x = x || 0;
self.y = y || 0;
// Speed system: 1=very slow, 2=slow, 3=normal, 4=fast, 5=very fast
var speedData = {
'red': 2,
// slow
'blue': 2,
// slow
'green': 3,
// normal
'yellow': 3,
// normal
'pink': 4,
// fast
'white': 4,
// fast
'black': 4,
// fast
'rainbow': 3,
// normal
'ceramic': 2,
// slow
'gb': 1 // very slow
};
self.speed = speedData[self.ballType] || 2;
self.pathIndex = 0;
self.lastX = self.x;
self.lastY = self.y;
// Define ball properties
var ballData = {
'red': {
hp: 1,
asset: 'redBall',
reward: 1,
spawns: []
},
'blue': {
hp: 1,
asset: 'blueBall',
reward: 2,
spawns: ['red']
},
'green': {
hp: 1,
asset: 'greenBall',
reward: 3,
spawns: ['blue']
},
'yellow': {
hp: 1,
asset: 'yellowBall',
reward: 4,
spawns: ['green']
},
'pink': {
hp: 1,
asset: 'pinkBall',
reward: 5,
spawns: ['yellow']
},
'white': {
hp: 1,
asset: 'whiteBall',
reward: 6,
spawns: ['red'],
immuneToDarts: true
},
'black': {
hp: 1,
asset: 'blackBall',
reward: 7,
spawns: ['red'],
immuneToSwords: true
},
'rainbow': {
hp: 5,
asset: 'rainbowBall',
reward: 15,
spawns: ['pink', 'pink']
},
'ceramic': {
hp: 10,
asset: 'ceramicBall',
reward: 30,
spawns: ['rainbow', 'rainbow']
},
'gb': {
hp: 25,
asset: 'gbBall',
reward: 75,
spawns: ['ceramic', 'ceramic', 'ceramic', 'ceramic']
}
};
self.data = ballData[self.ballType];
self.hp = self.data.hp;
self.maxHp = self.data.hp;
var ballGraphics = self.attachAsset(self.data.asset, {
anchorX: 0.5,
anchorY: 0.5
});
self.takeDamage = function (damage, weaponType) {
// Check immunities
if (weaponType === 'dart' && self.data.immuneToDarts) {
return false;
}
if (weaponType === 'sword' && self.data.immuneToSwords) {
return false;
}
self.hp -= damage;
if (self.hp <= 0) {
return true; // Ball destroyed
}
return false;
};
self.update = function () {
if (pathPoints.length === 0) {
return;
}
self.lastX = self.x;
self.lastY = self.y;
if (self.pathIndex < pathPoints.length - 1) {
var target = pathPoints[self.pathIndex + 1];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.pathIndex++;
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
};
return self;
});
var DartProjectile = Container.expand(function (x, y, targetX, targetY, damage, pierce) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.damage = damage || 2;
self.pierce = pierce || 2;
self.pierceCount = 0;
self.speed = 8;
var dx = targetX - x;
var dy = targetY - y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
var projectileGraphics = self.attachAsset('dartProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
projectileGraphics.rotation = Math.atan2(dy, dx);
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Check collision with balls
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
if (self.intersects(ball)) {
var destroyed = ball.takeDamage(self.damage, 'dart');
if (destroyed) {
// Award money
money += ball.data.reward;
updateMoneyDisplay();
// Spawn child balls
for (var j = 0; j < ball.data.spawns.length; j++) {
spawnBall(ball.data.spawns[j], ball.x, ball.y);
}
// Remove ball
ball.destroy();
balls.splice(i, 1);
LK.getSound('pop').play();
}
self.pierceCount++;
if (self.pierceCount >= self.pierce) {
return true; // Destroy projectile
}
break;
}
}
// Remove if off screen
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
return true;
}
return false;
};
return self;
});
var DartTower = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.damage = 2;
self.pierce = 2;
self.range = 150;
self.fireRate = 30; // speed 4 (fast) - 30 frames between shots
self.lastShot = 0;
self.clickCount = 0;
var towerGraphics = self.attachAsset('dartTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.findTarget = function () {
var closestBall = null;
var closestDistance = self.range + 1;
for (var i = 0; i < balls.length; i++) {
var ball = balls[i];
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestBall = ball;
closestDistance = distance;
}
}
return closestBall;
};
self.shoot = function (target) {
if (!target) {
return;
}
LK.getSound('shoot').play();
var projectile = new DartProjectile(self.x, self.y, target.x, target.y, self.damage, self.pierce);
projectiles.push(projectile);
game.addChild(projectile);
};
self.update = function () {
if (LK.ticks - self.lastShot >= self.fireRate) {
var target = self.findTarget();
if (target) {
self.shoot(target);
self.lastShot = LK.ticks;
}
}
};
self.down = function (x, y, obj) {
self.clickCount++;
if (self.clickCount >= 2) {
// Give $80 reward for deleting tower
money += 80;
updateMoneyDisplay();
// Remove tower from towers array
for (var i = towers.length - 1; i >= 0; i--) {
if (towers[i] === self) {
towers.splice(i, 1);
break;
}
}
// Destroy the tower
self.destroy();
}
};
return self;
});
var SwordProjectile = Container.expand(function (x, y, targetX, targetY, damage, pierce) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.damage = damage || 5;
self.pierce = pierce || 1;
self.pierceCount = 0;
self.speed = 10;
var dx = targetX - x;
var dy = targetY - y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
var projectileGraphics = self.attachAsset('swordProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
projectileGraphics.rotation = Math.atan2(dy, dx);
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Check collision with balls
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
if (self.intersects(ball)) {
var destroyed = ball.takeDamage(self.damage, 'sword');
if (destroyed) {
// Award money
money += ball.data.reward;
updateMoneyDisplay();
// Spawn child balls
for (var j = 0; j < ball.data.spawns.length; j++) {
spawnBall(ball.data.spawns[j], ball.x, ball.y);
}
// Remove ball
ball.destroy();
balls.splice(i, 1);
LK.getSound('pop').play();
}
self.pierceCount++;
if (self.pierceCount >= self.pierce) {
return true; // Destroy projectile
}
break;
}
}
// Remove if off screen
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
return true;
}
return false;
};
return self;
});
var SwordTower = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.damage = 5;
self.pierce = 1;
self.range = 450; // long 3 means 3x the base range of 150
self.fireRate = 120; // speed 1 (very slow) - 120 frames between shots
self.lastShot = 0;
self.clickCount = 0;
var towerGraphics = self.attachAsset('swordTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.findTarget = function () {
var closestBall = null;
var closestDistance = self.range + 1;
for (var i = 0; i < balls.length; i++) {
var ball = balls[i];
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestBall = ball;
closestDistance = distance;
}
}
return closestBall;
};
self.shoot = function (target) {
if (!target) {
return;
}
LK.getSound('shoot').play();
var projectile = new SwordProjectile(self.x, self.y, target.x, target.y, self.damage, self.pierce);
projectiles.push(projectile);
game.addChild(projectile);
};
self.update = function () {
if (LK.ticks - self.lastShot >= self.fireRate) {
var target = self.findTarget();
if (target) {
self.shoot(target);
self.lastShot = LK.ticks;
}
}
};
self.down = function (x, y, obj) {
self.clickCount++;
if (self.clickCount >= 2) {
// Give $300 reward for deleting tower
money += 300;
updateMoneyDisplay();
// Remove tower from towers array
for (var i = towers.length - 1; i >= 0; i--) {
if (towers[i] === self) {
towers.splice(i, 1);
break;
}
}
// Destroy the tower
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
;
// Game variables
var balls = [];
var towers = [];
var projectiles = [];
var money = 500;
var lives = 100;
var wave = 1;
var waveTimer = 0;
var ballsSpawned = 0;
var ballsToSpawn = 5;
// Path points for balls to follow
var pathPoints = [{
x: -50,
y: 400
}, {
x: 300,
y: 400
}, {
x: 300,
y: 800
}, {
x: 800,
y: 800
}, {
x: 800,
y: 1200
}, {
x: 1400,
y: 1200
}, {
x: 1400,
y: 600
}, {
x: 1800,
y: 600
}, {
x: 2100,
y: 600
}];
// Create permanent gray path visualization
for (var i = 0; i < pathPoints.length; i++) {
var pathViz = LK.getAsset('pathSegment', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
pathViz.x = pathPoints[i].x;
pathViz.y = pathPoints[i].y;
game.addChild(pathViz);
}
// UI Elements
var moneyText = new Text2('Money: $' + money, {
size: 60,
fill: 0xFFFF00
});
moneyText.anchor.set(0, 0);
LK.gui.topRight.addChild(moneyText);
moneyText.x = -400;
moneyText.y = 20;
var livesText = new Text2('Lives: ' + lives, {
size: 60,
fill: 0xFF0000
});
livesText.anchor.set(0, 0);
LK.gui.topRight.addChild(livesText);
livesText.x = -400;
livesText.y = 90;
var waveText = new Text2('Wave: ' + wave, {
size: 60,
fill: 0x00FF00
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
waveText.x = 120;
waveText.y = 20;
// Tower purchase button
var towerButton = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(towerButton);
towerButton.x = 100;
towerButton.y = -100;
var buttonText = new Text2('Dart\n$100', {
size: 40,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
towerButton.addChild(buttonText);
// Sword tower button
var swordTowerButton = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(swordTowerButton);
swordTowerButton.x = 250;
swordTowerButton.y = -100;
var swordButtonText = new Text2('Sword\n$340', {
size: 40,
fill: 0xFFFFFF
});
swordButtonText.anchor.set(0.5, 0.5);
swordTowerButton.addChild(swordButtonText);
var selectedTowerType = 'dart';
var placingTower = false;
function updateMoneyDisplay() {
moneyText.setText('Money: $' + money);
}
function updateLivesDisplay() {
livesText.setText('Lives: ' + lives);
}
function updateWaveDisplay() {
waveText.setText('Wave: ' + wave);
}
function spawnBall(type, x, y) {
var ball = new Ball(type, x || -50, y || 400);
balls.push(ball);
game.addChild(ball);
}
function startWave() {
ballsSpawned = 0;
ballsToSpawn = 5 + wave * 2;
waveTimer = 0;
updateWaveDisplay();
}
// Start first wave
startWave();
// Event handlers
towerButton.down = function (x, y, obj) {
if (money >= 100) {
selectedTowerType = 'dart';
placingTower = true;
}
};
swordTowerButton.down = function (x, y, obj) {
if (money >= 340) {
selectedTowerType = 'sword';
placingTower = true;
}
};
game.down = function (x, y, obj) {
if (placingTower) {
var cost = selectedTowerType === 'dart' ? 100 : 340;
if (money >= cost) {
// Check if position is valid (not too close to path)
var validPosition = true;
for (var i = 0; i < pathPoints.length; i++) {
var point = pathPoints[i];
var dx = x - point.x;
var dy = y - point.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
validPosition = false;
break;
}
}
if (validPosition) {
money -= cost;
updateMoneyDisplay();
var newTower;
if (selectedTowerType === 'dart') {
newTower = new DartTower(x, y);
} else {
newTower = new SwordTower(x, y);
}
towers.push(newTower);
game.addChild(newTower);
placingTower = false;
}
}
}
};
game.update = function () {
// Spawn balls for current wave
if (ballsSpawned < ballsToSpawn) {
waveTimer++;
if (waveTimer >= 60) {
// Spawn every second
var ballType = 'red';
if (wave >= 3) {
ballType = 'blue';
}
if (wave >= 5) {
ballType = 'green';
}
if (wave >= 8) {
ballType = 'yellow';
}
if (wave >= 12) {
ballType = 'pink';
}
if (wave === 15) {
ballType = 'gb';
} // GB balls only in the last round
else if (wave >= 12) {
ballType = Math.random() < 0.3 ? 'white' : ballType;
} else if (wave >= 10) {
ballType = Math.random() < 0.3 ? 'black' : ballType;
} else if (wave >= 8) {
ballType = Math.random() < 0.2 ? 'rainbow' : ballType;
}
spawnBall(ballType);
ballsSpawned++;
waveTimer = 0;
}
}
// Update balls
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
// Check if ball reached the end
if (ball.pathIndex >= pathPoints.length - 1) {
lives--;
updateLivesDisplay();
ball.destroy();
balls.splice(i, 1);
if (lives <= 0) {
LK.showGameOver();
return;
}
}
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
var shouldDestroy = projectile.update();
if (shouldDestroy) {
projectile.destroy();
projectiles.splice(i, 1);
}
}
// Check for wave completion
if (ballsSpawned >= ballsToSpawn && balls.length === 0) {
wave++;
money += 100; // Wave completion bonus
updateMoneyDisplay();
startWave();
}
// Victory condition
if (wave > 15) {
LK.showYouWin();
}
};
// Ball assets
// Tower assets
// UI assets
// Sound effects; /****
* Classes
****/
var Ball = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.ballType = type || 'red';
self.x = x || 0;
self.y = y || 0;
// Speed system: 1=very slow, 2=slow, 3=normal, 4=fast, 5=very fast
var speedData = {
'red': 2,
// slow
'blue': 2,
// slow
'green': 3,
// normal
'yellow': 3,
// normal
'pink': 4,
// fast
'white': 4,
// fast
'black': 4,
// fast
'rainbow': 3,
// normal
'ceramic': 2,
// slow
'gb': 1 // very slow
};
self.speed = speedData[self.ballType] || 2;
self.pathIndex = 0;
self.lastX = self.x;
self.lastY = self.y;
// Define ball properties
var ballData = {
'red': {
hp: 1,
asset: 'redBall',
reward: 1,
spawns: []
},
'blue': {
hp: 1,
asset: 'blueBall',
reward: 2,
spawns: ['red']
},
'green': {
hp: 1,
asset: 'greenBall',
reward: 3,
spawns: ['blue']
},
'yellow': {
hp: 1,
asset: 'yellowBall',
reward: 4,
spawns: ['green']
},
'pink': {
hp: 1,
asset: 'pinkBall',
reward: 5,
spawns: ['yellow']
},
'white': {
hp: 1,
asset: 'whiteBall',
reward: 6,
spawns: ['red'],
immuneToDarts: true
},
'black': {
hp: 1,
asset: 'blackBall',
reward: 7,
spawns: ['red'],
immuneToSwords: true
},
'rainbow': {
hp: 5,
asset: 'rainbowBall',
reward: 15,
spawns: ['pink', 'pink']
},
'ceramic': {
hp: 10,
asset: 'ceramicBall',
reward: 30,
spawns: ['rainbow', 'rainbow']
},
'gb': {
hp: 25,
asset: 'gbBall',
reward: 75,
spawns: ['ceramic', 'ceramic', 'ceramic', 'ceramic']
}
};
self.data = ballData[self.ballType];
self.hp = self.data.hp;
self.maxHp = self.data.hp;
var ballGraphics = self.attachAsset(self.data.asset, {
anchorX: 0.5,
anchorY: 0.5
});
self.takeDamage = function (damage, weaponType) {
// Check immunities
if (weaponType === 'dart' && self.data.immuneToDarts) {
return false;
}
if (weaponType === 'sword' && self.data.immuneToSwords) {
return false;
}
self.hp -= damage;
if (self.hp <= 0) {
return true; // Ball destroyed
}
return false;
};
self.update = function () {
if (pathPoints.length === 0) {
return;
}
self.lastX = self.x;
self.lastY = self.y;
if (self.pathIndex < pathPoints.length - 1) {
var target = pathPoints[self.pathIndex + 1];
var dx = target.x - self.x;
var dy = target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 10) {
self.pathIndex++;
} else {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
};
return self;
});
var DartProjectile = Container.expand(function (x, y, targetX, targetY, damage, pierce) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.damage = damage || 2;
self.pierce = pierce || 2;
self.pierceCount = 0;
self.speed = 8;
var dx = targetX - x;
var dy = targetY - y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
var projectileGraphics = self.attachAsset('dartProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
projectileGraphics.rotation = Math.atan2(dy, dx);
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Check collision with balls
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
if (self.intersects(ball)) {
var destroyed = ball.takeDamage(self.damage, 'dart');
if (destroyed) {
// Award money
money += ball.data.reward;
updateMoneyDisplay();
// Spawn child balls
for (var j = 0; j < ball.data.spawns.length; j++) {
spawnBall(ball.data.spawns[j], ball.x, ball.y);
}
// Remove ball
ball.destroy();
balls.splice(i, 1);
LK.getSound('pop').play();
}
self.pierceCount++;
if (self.pierceCount >= self.pierce) {
return true; // Destroy projectile
}
break;
}
}
// Remove if off screen
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
return true;
}
return false;
};
return self;
});
var DartTower = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.damage = 2;
self.pierce = 2;
self.range = 150;
self.fireRate = 30; // speed 4 (fast) - 30 frames between shots
self.lastShot = 0;
self.clickCount = 0;
var towerGraphics = self.attachAsset('dartTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.findTarget = function () {
var closestBall = null;
var closestDistance = self.range + 1;
for (var i = 0; i < balls.length; i++) {
var ball = balls[i];
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestBall = ball;
closestDistance = distance;
}
}
return closestBall;
};
self.shoot = function (target) {
if (!target) {
return;
}
LK.getSound('shoot').play();
var projectile = new DartProjectile(self.x, self.y, target.x, target.y, self.damage, self.pierce);
projectiles.push(projectile);
game.addChild(projectile);
};
self.update = function () {
if (LK.ticks - self.lastShot >= self.fireRate) {
var target = self.findTarget();
if (target) {
self.shoot(target);
self.lastShot = LK.ticks;
}
}
};
self.down = function (x, y, obj) {
self.clickCount++;
if (self.clickCount >= 2) {
// Give $80 reward for deleting tower
money += 80;
updateMoneyDisplay();
// Remove tower from towers array
for (var i = towers.length - 1; i >= 0; i--) {
if (towers[i] === self) {
towers.splice(i, 1);
break;
}
}
// Destroy the tower
self.destroy();
}
};
return self;
});
var SwordProjectile = Container.expand(function (x, y, targetX, targetY, damage, pierce) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.damage = damage || 5;
self.pierce = pierce || 1;
self.pierceCount = 0;
self.speed = 10;
var dx = targetX - x;
var dy = targetY - y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
var projectileGraphics = self.attachAsset('swordProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
projectileGraphics.rotation = Math.atan2(dy, dx);
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Check collision with balls
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
if (self.intersects(ball)) {
var destroyed = ball.takeDamage(self.damage, 'sword');
if (destroyed) {
// Award money
money += ball.data.reward;
updateMoneyDisplay();
// Spawn child balls
for (var j = 0; j < ball.data.spawns.length; j++) {
spawnBall(ball.data.spawns[j], ball.x, ball.y);
}
// Remove ball
ball.destroy();
balls.splice(i, 1);
LK.getSound('pop').play();
}
self.pierceCount++;
if (self.pierceCount >= self.pierce) {
return true; // Destroy projectile
}
break;
}
}
// Remove if off screen
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
return true;
}
return false;
};
return self;
});
var SwordTower = Container.expand(function (x, y) {
var self = Container.call(this);
self.x = x;
self.y = y;
self.damage = 5;
self.pierce = 1;
self.range = 450; // long 3 means 3x the base range of 150
self.fireRate = 120; // speed 1 (very slow) - 120 frames between shots
self.lastShot = 0;
self.clickCount = 0;
var towerGraphics = self.attachAsset('swordTower', {
anchorX: 0.5,
anchorY: 0.5
});
self.findTarget = function () {
var closestBall = null;
var closestDistance = self.range + 1;
for (var i = 0; i < balls.length; i++) {
var ball = balls[i];
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.range && distance < closestDistance) {
closestBall = ball;
closestDistance = distance;
}
}
return closestBall;
};
self.shoot = function (target) {
if (!target) {
return;
}
LK.getSound('shoot').play();
var projectile = new SwordProjectile(self.x, self.y, target.x, target.y, self.damage, self.pierce);
projectiles.push(projectile);
game.addChild(projectile);
};
self.update = function () {
if (LK.ticks - self.lastShot >= self.fireRate) {
var target = self.findTarget();
if (target) {
self.shoot(target);
self.lastShot = LK.ticks;
}
}
};
self.down = function (x, y, obj) {
self.clickCount++;
if (self.clickCount >= 2) {
// Give $300 reward for deleting tower
money += 300;
updateMoneyDisplay();
// Remove tower from towers array
for (var i = towers.length - 1; i >= 0; i--) {
if (towers[i] === self) {
towers.splice(i, 1);
break;
}
}
// Destroy the tower
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
;
// Game variables
var balls = [];
var towers = [];
var projectiles = [];
var money = 500;
var lives = 100;
var wave = 1;
var waveTimer = 0;
var ballsSpawned = 0;
var ballsToSpawn = 5;
// Path points for balls to follow
var pathPoints = [{
x: -50,
y: 400
}, {
x: 300,
y: 400
}, {
x: 300,
y: 800
}, {
x: 800,
y: 800
}, {
x: 800,
y: 1200
}, {
x: 1400,
y: 1200
}, {
x: 1400,
y: 600
}, {
x: 1800,
y: 600
}, {
x: 2100,
y: 600
}];
// Create permanent gray path visualization
for (var i = 0; i < pathPoints.length; i++) {
var pathViz = LK.getAsset('pathSegment', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
pathViz.x = pathPoints[i].x;
pathViz.y = pathPoints[i].y;
game.addChild(pathViz);
}
// UI Elements
var moneyText = new Text2('Money: $' + money, {
size: 60,
fill: 0xFFFF00
});
moneyText.anchor.set(0, 0);
LK.gui.topRight.addChild(moneyText);
moneyText.x = -400;
moneyText.y = 20;
var livesText = new Text2('Lives: ' + lives, {
size: 60,
fill: 0xFF0000
});
livesText.anchor.set(0, 0);
LK.gui.topRight.addChild(livesText);
livesText.x = -400;
livesText.y = 90;
var waveText = new Text2('Wave: ' + wave, {
size: 60,
fill: 0x00FF00
});
waveText.anchor.set(0, 0);
LK.gui.topLeft.addChild(waveText);
waveText.x = 120;
waveText.y = 20;
// Tower purchase button
var towerButton = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(towerButton);
towerButton.x = 100;
towerButton.y = -100;
var buttonText = new Text2('Dart\n$100', {
size: 40,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
towerButton.addChild(buttonText);
// Sword tower button
var swordTowerButton = LK.getAsset('towerButton', {
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.bottomLeft.addChild(swordTowerButton);
swordTowerButton.x = 250;
swordTowerButton.y = -100;
var swordButtonText = new Text2('Sword\n$340', {
size: 40,
fill: 0xFFFFFF
});
swordButtonText.anchor.set(0.5, 0.5);
swordTowerButton.addChild(swordButtonText);
var selectedTowerType = 'dart';
var placingTower = false;
function updateMoneyDisplay() {
moneyText.setText('Money: $' + money);
}
function updateLivesDisplay() {
livesText.setText('Lives: ' + lives);
}
function updateWaveDisplay() {
waveText.setText('Wave: ' + wave);
}
function spawnBall(type, x, y) {
var ball = new Ball(type, x || -50, y || 400);
balls.push(ball);
game.addChild(ball);
}
function startWave() {
ballsSpawned = 0;
ballsToSpawn = 5 + wave * 2;
waveTimer = 0;
updateWaveDisplay();
}
// Start first wave
startWave();
// Event handlers
towerButton.down = function (x, y, obj) {
if (money >= 100) {
selectedTowerType = 'dart';
placingTower = true;
}
};
swordTowerButton.down = function (x, y, obj) {
if (money >= 340) {
selectedTowerType = 'sword';
placingTower = true;
}
};
game.down = function (x, y, obj) {
if (placingTower) {
var cost = selectedTowerType === 'dart' ? 100 : 340;
if (money >= cost) {
// Check if position is valid (not too close to path)
var validPosition = true;
for (var i = 0; i < pathPoints.length; i++) {
var point = pathPoints[i];
var dx = x - point.x;
var dy = y - point.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
validPosition = false;
break;
}
}
if (validPosition) {
money -= cost;
updateMoneyDisplay();
var newTower;
if (selectedTowerType === 'dart') {
newTower = new DartTower(x, y);
} else {
newTower = new SwordTower(x, y);
}
towers.push(newTower);
game.addChild(newTower);
placingTower = false;
}
}
}
};
game.update = function () {
// Spawn balls for current wave
if (ballsSpawned < ballsToSpawn) {
waveTimer++;
if (waveTimer >= 60) {
// Spawn every second
var ballType = 'red';
if (wave >= 3) {
ballType = 'blue';
}
if (wave >= 5) {
ballType = 'green';
}
if (wave >= 8) {
ballType = 'yellow';
}
if (wave >= 12) {
ballType = 'pink';
}
if (wave === 15) {
ballType = 'gb';
} // GB balls only in the last round
else if (wave >= 12) {
ballType = Math.random() < 0.3 ? 'white' : ballType;
} else if (wave >= 10) {
ballType = Math.random() < 0.3 ? 'black' : ballType;
} else if (wave >= 8) {
ballType = Math.random() < 0.2 ? 'rainbow' : ballType;
}
spawnBall(ballType);
ballsSpawned++;
waveTimer = 0;
}
}
// Update balls
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
// Check if ball reached the end
if (ball.pathIndex >= pathPoints.length - 1) {
lives--;
updateLivesDisplay();
ball.destroy();
balls.splice(i, 1);
if (lives <= 0) {
LK.showGameOver();
return;
}
}
}
// Update projectiles
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
var shouldDestroy = projectile.update();
if (shouldDestroy) {
projectile.destroy();
projectiles.splice(i, 1);
}
}
// Check for wave completion
if (ballsSpawned >= ballsToSpawn && balls.length === 0) {
wave++;
money += 100; // Wave completion bonus
updateMoneyDisplay();
startWave();
}
// Victory condition
if (wave > 15) {
LK.showYouWin();
}
};
// Ball assets
// Tower assets
// UI assets
// Sound effects;
Red ball. In-Game asset. 2d. High contrast. No shadows
Yellow ball. In-Game asset. 2d. High contrast. No shadows
Green ball. In-Game asset. 2d. High contrast. No shadows
Brown ball (not basketball) . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
White ball. In-Game asset. 2d. High contrast. No shadows
Rainbow ball. In-Game asset. 2d. High contrast. No shadows
Pink ball. In-Game asset. 2d. High contrast. No shadows
Off orange Ball (not a basketball). In-Game asset. 2d. High contrast. No shadows
Blue ball. In-Game asset. 2d. High contrast. No shadows
Grey ball. In-Game asset. 2d. High contrast. No shadows
Dart. In-Game asset. 2d. High contrast. No shadows
Sword. In-Game asset. 2d. High contrast. No shadows