/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Clone = Container.expand(function (x, y) { var self = Container.call(this); self.isDestroyed = false; self.speed = 1.5; var cloneGraphics = self.attachAsset('clone', { anchorX: 0.5, anchorY: 0.5 }); self.x = x; self.y = y; // Calculate direction to center var dx = 1024 - self.x; var dy = 1366 - self.y; var distance = Math.sqrt(dx * dx + dy * dy); self.dirX = dx / distance; self.dirY = dy / distance; self.destroy = function () { if (self.isDestroyed) return; self.isDestroyed = true; }; self.update = function () { if (self.isDestroyed) return; // Move toward center self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; // Check if reached center var distanceToCenter = Math.sqrt((self.x - 1024) * (self.x - 1024) + (self.y - 1366) * (self.y - 1366)); if (distanceToCenter < 110) { // Game over gameOver = true; LK.showGameOver(); return; } }; self.down = function (x, y, obj) { // Clones disappear when clicked but give no points self.destroy(); }; return self; }); var Enemy = Container.expand(function (type, health, speed, x, y) { var self = Container.call(this); self.type = type; self.health = health; self.maxHealth = health; self.speed = speed; self.originalSpeed = speed; self.isDestroyed = false; self.lastHealth = health; var enemyGraphics = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5 }); self.healthText = new Text2(health.toString(), { size: 40, fill: 0xFFFFFF }); self.healthText.anchor.set(0.5, 0.5); self.addChild(self.healthText); self.x = x; self.y = y; // Calculate direction to center var dx = 1024 - self.x; var dy = 1366 - self.y; var distance = Math.sqrt(dx * dx + dy * dy); self.dirX = dx / distance; self.dirY = dy / distance; self.takeDamage = function () { if (self.isDestroyed) return; self.health -= 1; self.healthText.setText(self.health.toString()); if (self.health <= 0) { self.destroy(); return; } // Special abilities if (self.type === 'randomizer') { // Teleport to random position var angle = Math.random() * Math.PI * 2; var radius = 400 + Math.random() * 600; self.x = 1024 + Math.cos(angle) * radius; self.y = 1366 + Math.sin(angle) * radius; // Recalculate direction dx = 1024 - self.x; dy = 1366 - self.y; distance = Math.sqrt(dx * dx + dy * dy); self.dirX = dx / distance; self.dirY = dy / distance; } LK.getSound('hit').play(); }; self.destroy = function () { if (self.isDestroyed) return; self.isDestroyed = true; // Award points based on enemy type var points = 1; if (self.type === 'witch') points = 2;else if (self.type === 'guardian') points = 3;else if (self.type === 'randomizer') points = 2;else if (self.type === 'illusionist') points = 4;else if (self.type === 'titan') points = 10; LK.setScore(LK.getScore() + points); // Guardian special ability - restore shield if (self.type === 'guardian') { playerShield = Math.min(playerShield + 2, 10); } LK.getSound('destroy').play(); }; self.update = function () { if (self.isDestroyed) return; // Move toward center self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; // Check if reached center var distanceToCenter = Math.sqrt((self.x - 1024) * (self.x - 1024) + (self.y - 1366) * (self.y - 1366)); var collisionRadius = self.type === 'titan' ? 160 : 110; if (distanceToCenter < collisionRadius) { // Game over gameOver = true; LK.showGameOver(); return; } // Witch attack ability if (self.type === 'witch' && LK.ticks % 120 === 0) { var distanceToPlayer = Math.sqrt((self.x - 1024) * (self.x - 1024) + (self.y - 1366) * (self.y - 1366)); if (distanceToPlayer < 300) { playerShield -= 1; LK.getSound('damage').play(); LK.effects.flashScreen(0xff0000, 300); if (playerShield <= 0) { gameOver = true; LK.showGameOver(); } } } }; self.down = function (x, y, obj) { self.takeDamage(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x001122 }); /**** * Game Code ****/ // Game variables var enemies = []; var clones = []; var playerShield = 10; var gameOver = false; var spawnTimer = 0; var difficultyLevel = 1; var slowdownActive = false; var slowdownCooldown = 0; var lastSlowdownTime = 0; // Create player at center var player = game.addChild(LK.getAsset('player', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 })); // UI Elements var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.top.addChild(scoreText); var shieldText = new Text2('Shield: 10', { size: 60, fill: 0x00FF00 }); shieldText.anchor.set(1, 0); LK.gui.topRight.addChild(shieldText); var slowdownText = new Text2('Slowdown Ready', { size: 50, fill: 0xFFFF00 }); slowdownText.anchor.set(0.5, 1); LK.gui.bottom.addChild(slowdownText); // Slowdown button var slowdownButton = game.addChild(LK.getAsset('normalEnemy', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2500, scaleX: 1.5, scaleY: 1.5 })); slowdownButton.tint = 0x00ffff; slowdownButton.down = function (x, y, obj) { if (slowdownCooldown <= 0 && !slowdownActive) { activateSlowdown(); } }; function activateSlowdown() { slowdownActive = true; slowdownCooldown = 1800; // 30 seconds cooldown (30 * 60 ticks) lastSlowdownTime = LK.ticks; // Slow down all enemies for (var i = 0; i < enemies.length; i++) { if (!enemies[i].isDestroyed) { enemies[i].speed = enemies[i].originalSpeed * 0.3; } } // Slow down clones for (var i = 0; i < clones.length; i++) { if (!clones[i].isDestroyed) { clones[i].speed = 1.5 * 0.3; } } LK.getSound('slowdown').play(); LK.effects.flashScreen(0x0088ff, 500); // End slowdown after 20 seconds LK.setTimeout(function () { slowdownActive = false; // Restore enemy speeds for (var i = 0; i < enemies.length; i++) { if (!enemies[i].isDestroyed) { enemies[i].speed = enemies[i].originalSpeed; } } // Restore clone speeds for (var i = 0; i < clones.length; i++) { if (!clones[i].isDestroyed) { clones[i].speed = 1.5; } } }, 1200); // 20 seconds (20 * 60 ticks = 1200) } function spawnEnemy() { // Check if there's already a titan alive var titanExists = false; for (var i = 0; i < enemies.length; i++) { if (enemies[i].type === 'titan' && !enemies[i].isDestroyed) { titanExists = true; break; } } // If score >= 100 and no titan exists, spawn titan instead of other enemies if (LK.getScore() >= 100 && !titanExists) { var edge = Math.floor(Math.random() * 4); var x, y; // Spawn from screen edges switch (edge) { case 0: // Top x = Math.random() * 2048; y = -50; break; case 1: // Right x = 2098; y = Math.random() * 2732; break; case 2: // Bottom x = Math.random() * 2048; y = 2782; break; case 3: // Left x = -50; y = Math.random() * 2732; break; } var titanHealth = 30 + Math.floor(Math.random() * 11); // 30-40 health var enemy = new Enemy('titan', titanHealth, 0.3, x, y); // Very slow speed enemies.push(enemy); game.addChild(enemy); return; } // If titan exists, don't spawn any other enemies if (titanExists) { return; } var edge = Math.floor(Math.random() * 4); var x, y; // Spawn from screen edges switch (edge) { case 0: // Top x = Math.random() * 2048; y = -50; break; case 1: // Right x = 2098; y = Math.random() * 2732; break; case 2: // Bottom x = Math.random() * 2048; y = 2782; break; case 3: // Left x = -50; y = Math.random() * 2732; break; } // Determine enemy type based on difficulty and randomness var enemyType = 'normalEnemy'; var health = 1 + Math.floor(difficultyLevel / 3); var speed = 1; var rand = Math.random(); if (rand < 0.4) { enemyType = 'normalEnemy'; speed = 1 + difficultyLevel * 0.1; } else if (rand < 0.6) { enemyType = 'witch'; speed = 2 + difficultyLevel * 0.15; health = Math.max(1, health - 1); } else if (rand < 0.75) { enemyType = 'guardian'; speed = 0.8 + difficultyLevel * 0.05; health = health + 2; } else if (rand < 0.9) { enemyType = 'randomizer'; speed = 1.2 + difficultyLevel * 0.1; health = health + 1; } else { enemyType = 'illusionist'; speed = 1.5 + difficultyLevel * 0.1; health = health + 3; } var enemy = new Enemy(enemyType, health, speed, x, y); enemies.push(enemy); game.addChild(enemy); // Illusionist creates clones if (enemyType === 'illusionist') { var numClones = 2 + Math.floor(difficultyLevel / 5); for (var i = 0; i < numClones; i++) { var cloneX = x + (Math.random() - 0.5) * 200; var cloneY = y + (Math.random() - 0.5) * 200; var clone = new Clone(cloneX, cloneY); clones.push(clone); game.addChild(clone); } } } game.update = function () { if (gameOver) return; // Update UI scoreText.setText('Score: ' + LK.getScore()); shieldText.setText('Shield: ' + playerShield); // Update shield color based on health if (playerShield > 7) { shieldText.fill = "#00ff00"; } else if (playerShield > 3) { shieldText.fill = "#ffff00"; } else { shieldText.fill = "#ff0000"; } // Update slowdown UI if (slowdownCooldown > 0) { slowdownCooldown--; var remainingSeconds = Math.ceil(slowdownCooldown / 60); slowdownText.setText('Slowdown: ' + remainingSeconds + 's'); slowdownText.fill = "#888888"; slowdownButton.tint = 0x444444; } else { slowdownText.setText('Slowdown Ready'); slowdownText.fill = "#ffff00"; slowdownButton.tint = 0x00ffff; } // Spawn enemies spawnTimer++; var spawnRate = Math.max(30, 120 - difficultyLevel * 5); // Faster spawning as difficulty increases if (spawnTimer >= spawnRate) { spawnEnemy(); spawnTimer = 0; } // Clean up destroyed enemies for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].isDestroyed) { enemies[i].parent.removeChild(enemies[i]); enemies.splice(i, 1); } } // Clean up destroyed clones for (var i = clones.length - 1; i >= 0; i--) { if (clones[i].isDestroyed) { clones[i].parent.removeChild(clones[i]); clones.splice(i, 1); } } // Update difficulty based on score difficultyLevel = Math.floor(LK.getScore() / 10) + 1; // Guardian shield ability - protect nearby enemies for (var i = 0; i < enemies.length; i++) { var guardian = enemies[i]; if (guardian.type === 'guardian' && !guardian.isDestroyed) { for (var j = 0; j < enemies.length; j++) { var other = enemies[j]; if (other !== guardian && !other.isDestroyed) { var distance = Math.sqrt((guardian.x - other.x) * (guardian.x - other.x) + (guardian.y - other.y) * (guardian.y - other.y)); if (distance < 150) { // Visual indicator of protection (slight green tint) other.tint = 0xaaffaa; } else { other.tint = 0xffffff; } } } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Clone = Container.expand(function (x, y) {
var self = Container.call(this);
self.isDestroyed = false;
self.speed = 1.5;
var cloneGraphics = self.attachAsset('clone', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
// Calculate direction to center
var dx = 1024 - self.x;
var dy = 1366 - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.dirX = dx / distance;
self.dirY = dy / distance;
self.destroy = function () {
if (self.isDestroyed) return;
self.isDestroyed = true;
};
self.update = function () {
if (self.isDestroyed) return;
// Move toward center
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
// Check if reached center
var distanceToCenter = Math.sqrt((self.x - 1024) * (self.x - 1024) + (self.y - 1366) * (self.y - 1366));
if (distanceToCenter < 110) {
// Game over
gameOver = true;
LK.showGameOver();
return;
}
};
self.down = function (x, y, obj) {
// Clones disappear when clicked but give no points
self.destroy();
};
return self;
});
var Enemy = Container.expand(function (type, health, speed, x, y) {
var self = Container.call(this);
self.type = type;
self.health = health;
self.maxHealth = health;
self.speed = speed;
self.originalSpeed = speed;
self.isDestroyed = false;
self.lastHealth = health;
var enemyGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.healthText = new Text2(health.toString(), {
size: 40,
fill: 0xFFFFFF
});
self.healthText.anchor.set(0.5, 0.5);
self.addChild(self.healthText);
self.x = x;
self.y = y;
// Calculate direction to center
var dx = 1024 - self.x;
var dy = 1366 - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.dirX = dx / distance;
self.dirY = dy / distance;
self.takeDamage = function () {
if (self.isDestroyed) return;
self.health -= 1;
self.healthText.setText(self.health.toString());
if (self.health <= 0) {
self.destroy();
return;
}
// Special abilities
if (self.type === 'randomizer') {
// Teleport to random position
var angle = Math.random() * Math.PI * 2;
var radius = 400 + Math.random() * 600;
self.x = 1024 + Math.cos(angle) * radius;
self.y = 1366 + Math.sin(angle) * radius;
// Recalculate direction
dx = 1024 - self.x;
dy = 1366 - self.y;
distance = Math.sqrt(dx * dx + dy * dy);
self.dirX = dx / distance;
self.dirY = dy / distance;
}
LK.getSound('hit').play();
};
self.destroy = function () {
if (self.isDestroyed) return;
self.isDestroyed = true;
// Award points based on enemy type
var points = 1;
if (self.type === 'witch') points = 2;else if (self.type === 'guardian') points = 3;else if (self.type === 'randomizer') points = 2;else if (self.type === 'illusionist') points = 4;else if (self.type === 'titan') points = 10;
LK.setScore(LK.getScore() + points);
// Guardian special ability - restore shield
if (self.type === 'guardian') {
playerShield = Math.min(playerShield + 2, 10);
}
LK.getSound('destroy').play();
};
self.update = function () {
if (self.isDestroyed) return;
// Move toward center
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
// Check if reached center
var distanceToCenter = Math.sqrt((self.x - 1024) * (self.x - 1024) + (self.y - 1366) * (self.y - 1366));
var collisionRadius = self.type === 'titan' ? 160 : 110;
if (distanceToCenter < collisionRadius) {
// Game over
gameOver = true;
LK.showGameOver();
return;
}
// Witch attack ability
if (self.type === 'witch' && LK.ticks % 120 === 0) {
var distanceToPlayer = Math.sqrt((self.x - 1024) * (self.x - 1024) + (self.y - 1366) * (self.y - 1366));
if (distanceToPlayer < 300) {
playerShield -= 1;
LK.getSound('damage').play();
LK.effects.flashScreen(0xff0000, 300);
if (playerShield <= 0) {
gameOver = true;
LK.showGameOver();
}
}
}
};
self.down = function (x, y, obj) {
self.takeDamage();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001122
});
/****
* Game Code
****/
// Game variables
var enemies = [];
var clones = [];
var playerShield = 10;
var gameOver = false;
var spawnTimer = 0;
var difficultyLevel = 1;
var slowdownActive = false;
var slowdownCooldown = 0;
var lastSlowdownTime = 0;
// Create player at center
var player = game.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// UI Elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.top.addChild(scoreText);
var shieldText = new Text2('Shield: 10', {
size: 60,
fill: 0x00FF00
});
shieldText.anchor.set(1, 0);
LK.gui.topRight.addChild(shieldText);
var slowdownText = new Text2('Slowdown Ready', {
size: 50,
fill: 0xFFFF00
});
slowdownText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(slowdownText);
// Slowdown button
var slowdownButton = game.addChild(LK.getAsset('normalEnemy', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2500,
scaleX: 1.5,
scaleY: 1.5
}));
slowdownButton.tint = 0x00ffff;
slowdownButton.down = function (x, y, obj) {
if (slowdownCooldown <= 0 && !slowdownActive) {
activateSlowdown();
}
};
function activateSlowdown() {
slowdownActive = true;
slowdownCooldown = 1800; // 30 seconds cooldown (30 * 60 ticks)
lastSlowdownTime = LK.ticks;
// Slow down all enemies
for (var i = 0; i < enemies.length; i++) {
if (!enemies[i].isDestroyed) {
enemies[i].speed = enemies[i].originalSpeed * 0.3;
}
}
// Slow down clones
for (var i = 0; i < clones.length; i++) {
if (!clones[i].isDestroyed) {
clones[i].speed = 1.5 * 0.3;
}
}
LK.getSound('slowdown').play();
LK.effects.flashScreen(0x0088ff, 500);
// End slowdown after 20 seconds
LK.setTimeout(function () {
slowdownActive = false;
// Restore enemy speeds
for (var i = 0; i < enemies.length; i++) {
if (!enemies[i].isDestroyed) {
enemies[i].speed = enemies[i].originalSpeed;
}
}
// Restore clone speeds
for (var i = 0; i < clones.length; i++) {
if (!clones[i].isDestroyed) {
clones[i].speed = 1.5;
}
}
}, 1200); // 20 seconds (20 * 60 ticks = 1200)
}
function spawnEnemy() {
// Check if there's already a titan alive
var titanExists = false;
for (var i = 0; i < enemies.length; i++) {
if (enemies[i].type === 'titan' && !enemies[i].isDestroyed) {
titanExists = true;
break;
}
}
// If score >= 100 and no titan exists, spawn titan instead of other enemies
if (LK.getScore() >= 100 && !titanExists) {
var edge = Math.floor(Math.random() * 4);
var x, y;
// Spawn from screen edges
switch (edge) {
case 0:
// Top
x = Math.random() * 2048;
y = -50;
break;
case 1:
// Right
x = 2098;
y = Math.random() * 2732;
break;
case 2:
// Bottom
x = Math.random() * 2048;
y = 2782;
break;
case 3:
// Left
x = -50;
y = Math.random() * 2732;
break;
}
var titanHealth = 30 + Math.floor(Math.random() * 11); // 30-40 health
var enemy = new Enemy('titan', titanHealth, 0.3, x, y); // Very slow speed
enemies.push(enemy);
game.addChild(enemy);
return;
}
// If titan exists, don't spawn any other enemies
if (titanExists) {
return;
}
var edge = Math.floor(Math.random() * 4);
var x, y;
// Spawn from screen edges
switch (edge) {
case 0:
// Top
x = Math.random() * 2048;
y = -50;
break;
case 1:
// Right
x = 2098;
y = Math.random() * 2732;
break;
case 2:
// Bottom
x = Math.random() * 2048;
y = 2782;
break;
case 3:
// Left
x = -50;
y = Math.random() * 2732;
break;
}
// Determine enemy type based on difficulty and randomness
var enemyType = 'normalEnemy';
var health = 1 + Math.floor(difficultyLevel / 3);
var speed = 1;
var rand = Math.random();
if (rand < 0.4) {
enemyType = 'normalEnemy';
speed = 1 + difficultyLevel * 0.1;
} else if (rand < 0.6) {
enemyType = 'witch';
speed = 2 + difficultyLevel * 0.15;
health = Math.max(1, health - 1);
} else if (rand < 0.75) {
enemyType = 'guardian';
speed = 0.8 + difficultyLevel * 0.05;
health = health + 2;
} else if (rand < 0.9) {
enemyType = 'randomizer';
speed = 1.2 + difficultyLevel * 0.1;
health = health + 1;
} else {
enemyType = 'illusionist';
speed = 1.5 + difficultyLevel * 0.1;
health = health + 3;
}
var enemy = new Enemy(enemyType, health, speed, x, y);
enemies.push(enemy);
game.addChild(enemy);
// Illusionist creates clones
if (enemyType === 'illusionist') {
var numClones = 2 + Math.floor(difficultyLevel / 5);
for (var i = 0; i < numClones; i++) {
var cloneX = x + (Math.random() - 0.5) * 200;
var cloneY = y + (Math.random() - 0.5) * 200;
var clone = new Clone(cloneX, cloneY);
clones.push(clone);
game.addChild(clone);
}
}
}
game.update = function () {
if (gameOver) return;
// Update UI
scoreText.setText('Score: ' + LK.getScore());
shieldText.setText('Shield: ' + playerShield);
// Update shield color based on health
if (playerShield > 7) {
shieldText.fill = "#00ff00";
} else if (playerShield > 3) {
shieldText.fill = "#ffff00";
} else {
shieldText.fill = "#ff0000";
}
// Update slowdown UI
if (slowdownCooldown > 0) {
slowdownCooldown--;
var remainingSeconds = Math.ceil(slowdownCooldown / 60);
slowdownText.setText('Slowdown: ' + remainingSeconds + 's');
slowdownText.fill = "#888888";
slowdownButton.tint = 0x444444;
} else {
slowdownText.setText('Slowdown Ready');
slowdownText.fill = "#ffff00";
slowdownButton.tint = 0x00ffff;
}
// Spawn enemies
spawnTimer++;
var spawnRate = Math.max(30, 120 - difficultyLevel * 5); // Faster spawning as difficulty increases
if (spawnTimer >= spawnRate) {
spawnEnemy();
spawnTimer = 0;
}
// Clean up destroyed enemies
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].isDestroyed) {
enemies[i].parent.removeChild(enemies[i]);
enemies.splice(i, 1);
}
}
// Clean up destroyed clones
for (var i = clones.length - 1; i >= 0; i--) {
if (clones[i].isDestroyed) {
clones[i].parent.removeChild(clones[i]);
clones.splice(i, 1);
}
}
// Update difficulty based on score
difficultyLevel = Math.floor(LK.getScore() / 10) + 1;
// Guardian shield ability - protect nearby enemies
for (var i = 0; i < enemies.length; i++) {
var guardian = enemies[i];
if (guardian.type === 'guardian' && !guardian.isDestroyed) {
for (var j = 0; j < enemies.length; j++) {
var other = enemies[j];
if (other !== guardian && !other.isDestroyed) {
var distance = Math.sqrt((guardian.x - other.x) * (guardian.x - other.x) + (guardian.y - other.y) * (guardian.y - other.y));
if (distance < 150) {
// Visual indicator of protection (slight green tint)
other.tint = 0xaaffaa;
} else {
other.tint = 0xffffff;
}
}
}
}
}
};