/**** * 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