/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, totalWins: 0, totalMatches: 0 }); /**** * Classes ****/ var Entity = Container.expand(function () { var self = Container.call(this); self.speed = 0; self.health = 100; self.maxHealth = 100; self.size = 100; self.isDead = false; self.init = function (x, y, color) { self.x = x; self.y = y; }; self.takeDamage = function (amount) { if (self.isDead) { return; } self.health -= amount; if (self.health <= 0) { self.health = 0; self.die(); } // Flash red when taking damage LK.effects.flashObject(self, 0xff0000, 300); }; self.die = function () { if (self.isDead) { return; } self.isDead = true; tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); }; self.isOutOfBounds = function (bounds) { return self.x < bounds.x || self.x > bounds.x + bounds.width || self.y < bounds.y || self.y > bounds.y + bounds.height; }; self.keepInBounds = function (bounds) { if (self.x < bounds.x) { self.x = bounds.x; } else if (self.x > bounds.x + bounds.width) { self.x = bounds.x + bounds.width; } if (self.y < bounds.y) { self.y = bounds.y; } else if (self.y > bounds.y + bounds.height) { self.y = bounds.y + bounds.height; } }; return self; }); var Player = Entity.expand(function () { var self = Entity.call(this); self.speed = 5; self.cooldown = 0; self.shootCooldownMax = 30; // half a second at 60fps self.score = 0; var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Create health bar background var healthBarBg = self.attachAsset('healthBarBackground', { anchorX: 0.5, anchorY: 0, y: -80 }); // Create health bar var healthBar = self.attachAsset('healthBar', { anchorX: 0, anchorY: 0, y: -80, x: -100 }); self.init = function (x, y) { self.x = x; self.y = y; self.health = self.maxHealth; self.score = 0; self.isDead = false; self.alpha = 1; self.cooldown = 0; self.updateHealthBar(); }; self.updateHealthBar = function () { var healthPercentage = self.health / self.maxHealth; healthBar.width = 200 * healthPercentage; }; self.takeDamage = function (amount) { Entity.prototype.takeDamage.call(self, amount); self.updateHealthBar(); }; self.update = function () { if (self.isDead) { return; } if (self.cooldown > 0) { self.cooldown--; } self.updateHealthBar(); }; self.shoot = function () { if (self.cooldown > 0 || self.isDead) { return null; } var projectile = new Projectile(); projectile.init(self.x, self.y, 'up'); self.cooldown = self.shootCooldownMax; LK.getSound('projectileShoot').play(); return projectile; }; self.addScore = function (points) { self.score += points; if (self.score > storage.highScore) { storage.highScore = self.score; } }; return self; }); var Enemy = Entity.expand(function () { var self = Entity.call(this); self.speed = 2; self.attackCooldown = 0; self.attackRate = 120; // 2 seconds at 60fps self.scoreValue = 10; self.targetPlayer = null; var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.init = function (x, y, targetPlayer) { self.x = x; self.y = y; self.health = 50; self.maxHealth = 50; self.isDead = false; self.alpha = 1; self.targetPlayer = targetPlayer; self.attackCooldown = Math.floor(Math.random() * self.attackRate); }; self.update = function () { if (self.isDead || !self.targetPlayer) { return; } // Move toward player var dx = self.targetPlayer.x - self.x; var dy = self.targetPlayer.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 10) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // Attack logic if (self.attackCooldown > 0) { self.attackCooldown--; } else if (distance < 150) { self.attackPlayer(); } }; self.attackPlayer = function () { if (self.isDead || self.targetPlayer.isDead) { return null; } // Attack directly by touching if (self.intersects(self.targetPlayer)) { self.targetPlayer.takeDamage(10); LK.getSound('hit').play(); } // Sometimes shoot projectiles if (Math.random() < 0.3) { var projectile = new Projectile(); var angle = Math.atan2(self.targetPlayer.y - self.y, self.targetPlayer.x - self.x); projectile.init(self.x, self.y, 'custom', angle); self.attackCooldown = self.attackRate; return projectile; } self.attackCooldown = self.attackRate / 2; return null; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); self.type = 'health'; // Default type self.active = true; var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); self.init = function (x, y, type) { self.x = x; self.y = y; self.type = type || (Math.random() < 0.7 ? 'health' : 'speed'); self.active = true; self.alpha = 1; // Different colors for different power-up types if (self.type === 'health') { powerUpGraphics.tint = 0x2ecc71; // Green } else if (self.type === 'speed') { powerUpGraphics.tint = 0x3498db; // Blue } // Add a pulsing animation self.pulse(); }; self.pulse = function () { tween(powerUpGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.sinceOut, onFinish: function onFinish() { tween(powerUpGraphics, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.sinceIn, onFinish: function onFinish() { if (self.active) { self.pulse(); } } }); } }); }; self.collect = function (player) { if (!self.active) { return; } self.active = false; LK.getSound('powerUpCollect').play(); if (self.type === 'health') { player.health = Math.min(player.maxHealth, player.health + 25); } else if (self.type === 'speed') { var originalSpeed = player.speed; player.speed += 2; // Speed boost is temporary LK.setTimeout(function () { if (!player.isDead) { player.speed = originalSpeed; } }, 5000); } // Fade out and destroy tween(self, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); self.speed = 8; self.damage = 10; self.direction = 'up'; self.angleRad = 0; var projectileGraphics = self.attachAsset('projectile', { anchorX: 0.5, anchorY: 0.5 }); self.init = function (x, y, direction, angleRad) { self.x = x; self.y = y; self.direction = direction || 'up'; self.angleRad = angleRad || 0; }; self.update = function () { if (self.direction === 'up') { self.y -= self.speed; } else if (self.direction === 'down') { self.y += self.speed; } else if (self.direction === 'custom' && self.angleRad !== undefined) { self.x += Math.cos(self.angleRad) * self.speed; self.y += Math.sin(self.angleRad) * self.speed; } }; return self; }); var Trap = Container.expand(function () { var self = Container.call(this); self.damage = 15; self.active = true; var trapGraphics = self.attachAsset('trap', { anchorX: 0.5, anchorY: 0.5 }); self.init = function (x, y, damage) { self.x = x; self.y = y; self.damage = damage || 15; self.active = true; self.alpha = 1; // Add a rotating animation self.rotate(); }; self.rotate = function () { tween(trapGraphics, { rotation: Math.PI * 2 }, { duration: 3000, onFinish: function onFinish() { trapGraphics.rotation = 0; if (self.active) { self.rotate(); } } }); }; self.trigger = function (entity) { if (!self.active) { return; } LK.getSound('trapHit').play(); entity.takeDamage(self.damage); // Visual feedback LK.effects.flashObject(self, 0xff0000, 300); // Deactivate temporarily self.active = false; trapGraphics.alpha = 0.5; // Reactivate after a delay LK.setTimeout(function () { if (self.parent) { // Check if still in the scene self.active = true; trapGraphics.alpha = 1; } }, 3000); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ // Arena setup var arena = LK.getAsset('arena', { anchorX: 0.5, anchorY: 0.5 }); arena.x = 2048 / 2; arena.y = 2732 / 2; game.addChild(arena); // Game state variables var player = null; var enemies = []; var powerUps = []; var traps = []; var projectiles = []; var dragTarget = null; var gameActive = false; var waveNumber = 0; var enemiesDefeated = 0; var isGameStarting = false; // Game boundaries var bounds = { x: arena.x - arena.width / 2, y: arena.y - arena.height / 2, width: arena.width, height: arena.height }; // UI elements var scoreText = new Text2('0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var waveText = new Text2('Wave 1', { size: 50, fill: 0xFFFFFF }); waveText.anchor.set(0.5, 0); waveText.y = 80; LK.gui.top.addChild(waveText); var highScoreText = new Text2('High Score: ' + storage.highScore, { size: 40, fill: 0xFFFFFF }); highScoreText.anchor.set(1, 0); highScoreText.x = -20; highScoreText.y = 20; LK.gui.topRight.addChild(highScoreText); // Play music LK.playMusic('battleMusic', { fade: { start: 0, end: 0.3, duration: 1000 } }); // Initialize the game function startGame() { if (isGameStarting) { return; } isGameStarting = true; // Reset game state resetGameState(); // Create player player = new Player(); player.init(arena.x, arena.y + 300); game.addChild(player); // Create initial traps for (var i = 0; i < 5; i++) { createTrap(); } // Create initial power-ups for (var i = 0; i < 3; i++) { createPowerUp(); } // Start first wave startNextWave(); // Update UI updateScoreDisplay(); gameActive = true; isGameStarting = false; } function resetGameState() { // Remove existing entities if (player && !player.isDead) { player.die(); } // Clean up arrays cleanupArrays(); // Reset game variables waveNumber = 0; enemiesDefeated = 0; LK.setScore(0); } function cleanupArrays() { // Clean up enemies for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].parent) { enemies[i].destroy(); } enemies.splice(i, 1); } // Clean up power-ups for (var i = powerUps.length - 1; i >= 0; i--) { if (powerUps[i].parent) { powerUps[i].destroy(); } powerUps.splice(i, 1); } // Clean up traps for (var i = traps.length - 1; i >= 0; i--) { if (traps[i].parent) { traps[i].destroy(); } traps.splice(i, 1); } // Clean up projectiles for (var i = projectiles.length - 1; i >= 0; i--) { if (projectiles[i].parent) { projectiles[i].destroy(); } projectiles.splice(i, 1); } } function startNextWave() { waveNumber++; waveText.setText('Wave ' + waveNumber); // Display wave announcement var waveAnnouncement = new Text2('Wave ' + waveNumber, { size: 120, fill: 0xFFFFFF }); waveAnnouncement.anchor.set(0.5, 0.5); LK.gui.center.addChild(waveAnnouncement); // Fade in and out waveAnnouncement.alpha = 0; tween(waveAnnouncement, { alpha: 1 }, { duration: 800, onFinish: function onFinish() { LK.setTimeout(function () { tween(waveAnnouncement, { alpha: 0 }, { duration: 800, onFinish: function onFinish() { waveAnnouncement.destroy(); } }); }, 1000); } }); // Spawn enemies for this wave var enemiesToSpawn = Math.min(3 + waveNumber, 10); for (var i = 0; i < enemiesToSpawn; i++) { LK.setTimeout(function () { if (gameActive && player && !player.isDead) { spawnEnemy(); } }, i * 800); } // Add a new trap and powerup with each wave if (waveNumber > 1) { createTrap(); if (waveNumber % 2 === 0) { createPowerUp(); } } } function spawnEnemy() { if (!player || player.isDead) { return; } var enemy = new Enemy(); var edge = Math.floor(Math.random() * 4); var x, y; // Spawn from edges of the arena switch (edge) { case 0: // Top x = bounds.x + Math.random() * bounds.width; y = bounds.y; break; case 1: // Right x = bounds.x + bounds.width; y = bounds.y + Math.random() * bounds.height; break; case 2: // Bottom x = bounds.x + Math.random() * bounds.width; y = bounds.y + bounds.height; break; case 3: // Left x = bounds.x; y = bounds.y + Math.random() * bounds.height; break; } enemy.init(x, y, player); game.addChild(enemy); enemies.push(enemy); } function createPowerUp() { var powerUp = new PowerUp(); var x = bounds.x + 100 + Math.random() * (bounds.width - 200); var y = bounds.y + 100 + Math.random() * (bounds.height - 200); powerUp.init(x, y); game.addChild(powerUp); powerUps.push(powerUp); } function createTrap() { var trap = new Trap(); var x = bounds.x + 100 + Math.random() * (bounds.width - 200); var y = bounds.y + 100 + Math.random() * (bounds.height - 200); trap.init(x, y); game.addChild(trap); traps.push(trap); } function updateScoreDisplay() { scoreText.setText('Score: ' + LK.getScore()); highScoreText.setText('High Score: ' + storage.highScore); } function checkCollisions() { if (!player || player.isDead) { return; } // Player-Enemy collisions for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.isDead) { continue; } if (player.intersects(enemy)) { player.takeDamage(5); LK.getSound('hit').play(); } } // Player-PowerUp collisions for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; if (!powerUp.active) { continue; } if (player.intersects(powerUp)) { powerUp.collect(player); powerUps.splice(i, 1); } } // Player-Trap collisions for (var i = traps.length - 1; i >= 0; i--) { var trap = traps[i]; if (!trap.active) { continue; } if (player.intersects(trap)) { trap.trigger(player); } } // Projectile-Enemy collisions for (var i = projectiles.length - 1; i >= 0; i--) { var projectile = projectiles[i]; var hit = false; // Check if projectile is out of bounds if (projectile.isOutOfBounds(bounds)) { projectile.destroy(); projectiles.splice(i, 1); continue; } // Check hits against enemies (only if shot by player) if (projectile.direction === 'up') { for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (enemy.isDead) { continue; } if (projectile.intersects(enemy)) { enemy.takeDamage(projectile.damage); LK.getSound('hit').play(); if (enemy.health <= 0) { player.addScore(enemy.scoreValue); LK.setScore(player.score); updateScoreDisplay(); enemies.splice(j, 1); enemiesDefeated++; // Check if wave is complete if (enemies.length === 0) { LK.setTimeout(startNextWave, 2000); } } hit = true; break; } } } // Check hits against player (only if shot by enemy) else if (projectile.direction === 'custom' && player && !player.isDead) { if (projectile.intersects(player)) { player.takeDamage(projectile.damage); LK.getSound('hit').play(); hit = true; } } if (hit) { projectile.destroy(); projectiles.splice(i, 1); } } } // Game input handlers game.down = function (x, y, obj) { if (!gameActive) { startGame(); return; } if (player && !player.isDead) { dragTarget = player; player.x = x; player.y = y; player.keepInBounds(bounds); } }; game.up = function (x, y, obj) { dragTarget = null; // Shoot on release if game is active if (gameActive && player && !player.isDead) { var projectile = player.shoot(); if (projectile) { game.addChild(projectile); projectiles.push(projectile); } } }; game.move = function (x, y, obj) { if (dragTarget === player && player && !player.isDead) { player.x = x; player.y = y; player.keepInBounds(bounds); } }; // Main game update loop game.update = function () { if (!gameActive) { // Show start game message if not already started if (!isGameStarting && (!player || player.isDead)) { var _pulseMessage = function pulseMessage() { tween(startMessage, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.sinceOut, onFinish: function onFinish() { tween(startMessage, { scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.sinceIn, onFinish: function onFinish() { if (startMessage.parent) { _pulseMessage(); } } }); } }); }; var startMessage = new Text2('Tap to Start', { size: 80, fill: 0xFFFFFF }); startMessage.anchor.set(0.5, 0.5); LK.gui.center.addChild(startMessage); // Pulse animation for the start message _pulseMessage(); gameActive = true; // Set to true so message only shows once } return; } // If player is dead, show game over if (player && player.isDead) { storage.totalMatches++; LK.showGameOver(); return; } // Update all game entities if (player) { player.update(); } for (var i = 0; i < enemies.length; i++) { if (!enemies[i].isDead) { enemies[i].update(); // Chance for enemy to shoot if (Math.random() < 0.005) { var enemyProjectile = enemies[i].attackPlayer(); if (enemyProjectile) { game.addChild(enemyProjectile); projectiles.push(enemyProjectile); } } } } for (var i = 0; i < projectiles.length; i++) { projectiles[i].update(); } // Check various collisions checkCollisions(); // Spawn additional power-ups randomly if (Math.random() < 0.001 && powerUps.length < 5) { createPowerUp(); } // Spawn additional traps randomly in later waves if (waveNumber > 2 && Math.random() < 0.0005 && traps.length < waveNumber + 3) { createTrap(); } }; // Initial screen var titleText = new Text2('Arena Rivals', { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -200; LK.gui.center.addChild(titleText); var instructionText = new Text2('Tap and drag to move\nRelease to shoot', { size: 60, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); instructionText.y = 100; LK.gui.center.addChild(instructionText); // Start game message var startMessage = new Text2('Tap to Start', { size: 80, fill: 0xFFFFFF }); startMessage.anchor.set(0.5, 0.5); startMessage.y = 300; LK.gui.center.addChild(startMessage); // Pulse animation for the start message function pulseStartMessage() { tween(startMessage, { scaleX: 1.1, scaleY: 1.1 }, { duration: 800, easing: tween.sinceOut, onFinish: function onFinish() { tween(startMessage, { scaleX: 1, scaleY: 1 }, { duration: 800, easing: tween.sinceIn, onFinish: pulseStartMessage }); } }); } pulseStartMessage();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,827 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0,
+ totalWins: 0,
+ totalMatches: 0
+});
+
+/****
+* Classes
+****/
+var Entity = Container.expand(function () {
+ var self = Container.call(this);
+ self.speed = 0;
+ self.health = 100;
+ self.maxHealth = 100;
+ self.size = 100;
+ self.isDead = false;
+ self.init = function (x, y, color) {
+ self.x = x;
+ self.y = y;
+ };
+ self.takeDamage = function (amount) {
+ if (self.isDead) {
+ return;
+ }
+ self.health -= amount;
+ if (self.health <= 0) {
+ self.health = 0;
+ self.die();
+ }
+ // Flash red when taking damage
+ LK.effects.flashObject(self, 0xff0000, 300);
+ };
+ self.die = function () {
+ if (self.isDead) {
+ return;
+ }
+ self.isDead = true;
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ };
+ self.isOutOfBounds = function (bounds) {
+ return self.x < bounds.x || self.x > bounds.x + bounds.width || self.y < bounds.y || self.y > bounds.y + bounds.height;
+ };
+ self.keepInBounds = function (bounds) {
+ if (self.x < bounds.x) {
+ self.x = bounds.x;
+ } else if (self.x > bounds.x + bounds.width) {
+ self.x = bounds.x + bounds.width;
+ }
+ if (self.y < bounds.y) {
+ self.y = bounds.y;
+ } else if (self.y > bounds.y + bounds.height) {
+ self.y = bounds.y + bounds.height;
+ }
+ };
+ return self;
+});
+var Player = Entity.expand(function () {
+ var self = Entity.call(this);
+ self.speed = 5;
+ self.cooldown = 0;
+ self.shootCooldownMax = 30; // half a second at 60fps
+ self.score = 0;
+ var playerGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Create health bar background
+ var healthBarBg = self.attachAsset('healthBarBackground', {
+ anchorX: 0.5,
+ anchorY: 0,
+ y: -80
+ });
+ // Create health bar
+ var healthBar = self.attachAsset('healthBar', {
+ anchorX: 0,
+ anchorY: 0,
+ y: -80,
+ x: -100
+ });
+ self.init = function (x, y) {
+ self.x = x;
+ self.y = y;
+ self.health = self.maxHealth;
+ self.score = 0;
+ self.isDead = false;
+ self.alpha = 1;
+ self.cooldown = 0;
+ self.updateHealthBar();
+ };
+ self.updateHealthBar = function () {
+ var healthPercentage = self.health / self.maxHealth;
+ healthBar.width = 200 * healthPercentage;
+ };
+ self.takeDamage = function (amount) {
+ Entity.prototype.takeDamage.call(self, amount);
+ self.updateHealthBar();
+ };
+ self.update = function () {
+ if (self.isDead) {
+ return;
+ }
+ if (self.cooldown > 0) {
+ self.cooldown--;
+ }
+ self.updateHealthBar();
+ };
+ self.shoot = function () {
+ if (self.cooldown > 0 || self.isDead) {
+ return null;
+ }
+ var projectile = new Projectile();
+ projectile.init(self.x, self.y, 'up');
+ self.cooldown = self.shootCooldownMax;
+ LK.getSound('projectileShoot').play();
+ return projectile;
+ };
+ self.addScore = function (points) {
+ self.score += points;
+ if (self.score > storage.highScore) {
+ storage.highScore = self.score;
+ }
+ };
+ return self;
+});
+var Enemy = Entity.expand(function () {
+ var self = Entity.call(this);
+ self.speed = 2;
+ self.attackCooldown = 0;
+ self.attackRate = 120; // 2 seconds at 60fps
+ self.scoreValue = 10;
+ self.targetPlayer = null;
+ var enemyGraphics = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.init = function (x, y, targetPlayer) {
+ self.x = x;
+ self.y = y;
+ self.health = 50;
+ self.maxHealth = 50;
+ self.isDead = false;
+ self.alpha = 1;
+ self.targetPlayer = targetPlayer;
+ self.attackCooldown = Math.floor(Math.random() * self.attackRate);
+ };
+ self.update = function () {
+ if (self.isDead || !self.targetPlayer) {
+ return;
+ }
+ // Move toward player
+ var dx = self.targetPlayer.x - self.x;
+ var dy = self.targetPlayer.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 10) {
+ self.x += dx / distance * self.speed;
+ self.y += dy / distance * self.speed;
+ }
+ // Attack logic
+ if (self.attackCooldown > 0) {
+ self.attackCooldown--;
+ } else if (distance < 150) {
+ self.attackPlayer();
+ }
+ };
+ self.attackPlayer = function () {
+ if (self.isDead || self.targetPlayer.isDead) {
+ return null;
+ }
+ // Attack directly by touching
+ if (self.intersects(self.targetPlayer)) {
+ self.targetPlayer.takeDamage(10);
+ LK.getSound('hit').play();
+ }
+ // Sometimes shoot projectiles
+ if (Math.random() < 0.3) {
+ var projectile = new Projectile();
+ var angle = Math.atan2(self.targetPlayer.y - self.y, self.targetPlayer.x - self.x);
+ projectile.init(self.x, self.y, 'custom', angle);
+ self.attackCooldown = self.attackRate;
+ return projectile;
+ }
+ self.attackCooldown = self.attackRate / 2;
+ return null;
+ };
+ return self;
+});
+var PowerUp = Container.expand(function () {
+ var self = Container.call(this);
+ self.type = 'health'; // Default type
+ self.active = true;
+ var powerUpGraphics = self.attachAsset('powerUp', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.init = function (x, y, type) {
+ self.x = x;
+ self.y = y;
+ self.type = type || (Math.random() < 0.7 ? 'health' : 'speed');
+ self.active = true;
+ self.alpha = 1;
+ // Different colors for different power-up types
+ if (self.type === 'health') {
+ powerUpGraphics.tint = 0x2ecc71; // Green
+ } else if (self.type === 'speed') {
+ powerUpGraphics.tint = 0x3498db; // Blue
+ }
+ // Add a pulsing animation
+ self.pulse();
+ };
+ self.pulse = function () {
+ tween(powerUpGraphics, {
+ scaleX: 1.2,
+ scaleY: 1.2
+ }, {
+ duration: 500,
+ easing: tween.sinceOut,
+ onFinish: function onFinish() {
+ tween(powerUpGraphics, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 500,
+ easing: tween.sinceIn,
+ onFinish: function onFinish() {
+ if (self.active) {
+ self.pulse();
+ }
+ }
+ });
+ }
+ });
+ };
+ self.collect = function (player) {
+ if (!self.active) {
+ return;
+ }
+ self.active = false;
+ LK.getSound('powerUpCollect').play();
+ if (self.type === 'health') {
+ player.health = Math.min(player.maxHealth, player.health + 25);
+ } else if (self.type === 'speed') {
+ var originalSpeed = player.speed;
+ player.speed += 2;
+ // Speed boost is temporary
+ LK.setTimeout(function () {
+ if (!player.isDead) {
+ player.speed = originalSpeed;
+ }
+ }, 5000);
+ }
+ // Fade out and destroy
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ };
+ return self;
+});
+var Projectile = Container.expand(function () {
+ var self = Container.call(this);
+ self.speed = 8;
+ self.damage = 10;
+ self.direction = 'up';
+ self.angleRad = 0;
+ var projectileGraphics = self.attachAsset('projectile', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.init = function (x, y, direction, angleRad) {
+ self.x = x;
+ self.y = y;
+ self.direction = direction || 'up';
+ self.angleRad = angleRad || 0;
+ };
+ self.update = function () {
+ if (self.direction === 'up') {
+ self.y -= self.speed;
+ } else if (self.direction === 'down') {
+ self.y += self.speed;
+ } else if (self.direction === 'custom' && self.angleRad !== undefined) {
+ self.x += Math.cos(self.angleRad) * self.speed;
+ self.y += Math.sin(self.angleRad) * self.speed;
+ }
+ };
+ return self;
+});
+var Trap = Container.expand(function () {
+ var self = Container.call(this);
+ self.damage = 15;
+ self.active = true;
+ var trapGraphics = self.attachAsset('trap', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.init = function (x, y, damage) {
+ self.x = x;
+ self.y = y;
+ self.damage = damage || 15;
+ self.active = true;
+ self.alpha = 1;
+ // Add a rotating animation
+ self.rotate();
+ };
+ self.rotate = function () {
+ tween(trapGraphics, {
+ rotation: Math.PI * 2
+ }, {
+ duration: 3000,
+ onFinish: function onFinish() {
+ trapGraphics.rotation = 0;
+ if (self.active) {
+ self.rotate();
+ }
+ }
+ });
+ };
+ self.trigger = function (entity) {
+ if (!self.active) {
+ return;
+ }
+ LK.getSound('trapHit').play();
+ entity.takeDamage(self.damage);
+ // Visual feedback
+ LK.effects.flashObject(self, 0xff0000, 300);
+ // Deactivate temporarily
+ self.active = false;
+ trapGraphics.alpha = 0.5;
+ // Reactivate after a delay
+ LK.setTimeout(function () {
+ if (self.parent) {
+ // Check if still in the scene
+ self.active = true;
+ trapGraphics.alpha = 1;
+ }
+ }, 3000);
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2c3e50
+});
+
+/****
+* Game Code
+****/
+// Arena setup
+var arena = LK.getAsset('arena', {
+ anchorX: 0.5,
+ anchorY: 0.5
+});
+arena.x = 2048 / 2;
+arena.y = 2732 / 2;
+game.addChild(arena);
+// Game state variables
+var player = null;
+var enemies = [];
+var powerUps = [];
+var traps = [];
+var projectiles = [];
+var dragTarget = null;
+var gameActive = false;
+var waveNumber = 0;
+var enemiesDefeated = 0;
+var isGameStarting = false;
+// Game boundaries
+var bounds = {
+ x: arena.x - arena.width / 2,
+ y: arena.y - arena.height / 2,
+ width: arena.width,
+ height: arena.height
+};
+// UI elements
+var scoreText = new Text2('0', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreText);
+var waveText = new Text2('Wave 1', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+waveText.anchor.set(0.5, 0);
+waveText.y = 80;
+LK.gui.top.addChild(waveText);
+var highScoreText = new Text2('High Score: ' + storage.highScore, {
+ size: 40,
+ fill: 0xFFFFFF
+});
+highScoreText.anchor.set(1, 0);
+highScoreText.x = -20;
+highScoreText.y = 20;
+LK.gui.topRight.addChild(highScoreText);
+// Play music
+LK.playMusic('battleMusic', {
+ fade: {
+ start: 0,
+ end: 0.3,
+ duration: 1000
+ }
+});
+// Initialize the game
+function startGame() {
+ if (isGameStarting) {
+ return;
+ }
+ isGameStarting = true;
+ // Reset game state
+ resetGameState();
+ // Create player
+ player = new Player();
+ player.init(arena.x, arena.y + 300);
+ game.addChild(player);
+ // Create initial traps
+ for (var i = 0; i < 5; i++) {
+ createTrap();
+ }
+ // Create initial power-ups
+ for (var i = 0; i < 3; i++) {
+ createPowerUp();
+ }
+ // Start first wave
+ startNextWave();
+ // Update UI
+ updateScoreDisplay();
+ gameActive = true;
+ isGameStarting = false;
+}
+function resetGameState() {
+ // Remove existing entities
+ if (player && !player.isDead) {
+ player.die();
+ }
+ // Clean up arrays
+ cleanupArrays();
+ // Reset game variables
+ waveNumber = 0;
+ enemiesDefeated = 0;
+ LK.setScore(0);
+}
+function cleanupArrays() {
+ // Clean up enemies
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ if (enemies[i].parent) {
+ enemies[i].destroy();
+ }
+ enemies.splice(i, 1);
+ }
+ // Clean up power-ups
+ for (var i = powerUps.length - 1; i >= 0; i--) {
+ if (powerUps[i].parent) {
+ powerUps[i].destroy();
+ }
+ powerUps.splice(i, 1);
+ }
+ // Clean up traps
+ for (var i = traps.length - 1; i >= 0; i--) {
+ if (traps[i].parent) {
+ traps[i].destroy();
+ }
+ traps.splice(i, 1);
+ }
+ // Clean up projectiles
+ for (var i = projectiles.length - 1; i >= 0; i--) {
+ if (projectiles[i].parent) {
+ projectiles[i].destroy();
+ }
+ projectiles.splice(i, 1);
+ }
+}
+function startNextWave() {
+ waveNumber++;
+ waveText.setText('Wave ' + waveNumber);
+ // Display wave announcement
+ var waveAnnouncement = new Text2('Wave ' + waveNumber, {
+ size: 120,
+ fill: 0xFFFFFF
+ });
+ waveAnnouncement.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(waveAnnouncement);
+ // Fade in and out
+ waveAnnouncement.alpha = 0;
+ tween(waveAnnouncement, {
+ alpha: 1
+ }, {
+ duration: 800,
+ onFinish: function onFinish() {
+ LK.setTimeout(function () {
+ tween(waveAnnouncement, {
+ alpha: 0
+ }, {
+ duration: 800,
+ onFinish: function onFinish() {
+ waveAnnouncement.destroy();
+ }
+ });
+ }, 1000);
+ }
+ });
+ // Spawn enemies for this wave
+ var enemiesToSpawn = Math.min(3 + waveNumber, 10);
+ for (var i = 0; i < enemiesToSpawn; i++) {
+ LK.setTimeout(function () {
+ if (gameActive && player && !player.isDead) {
+ spawnEnemy();
+ }
+ }, i * 800);
+ }
+ // Add a new trap and powerup with each wave
+ if (waveNumber > 1) {
+ createTrap();
+ if (waveNumber % 2 === 0) {
+ createPowerUp();
+ }
+ }
+}
+function spawnEnemy() {
+ if (!player || player.isDead) {
+ return;
+ }
+ var enemy = new Enemy();
+ var edge = Math.floor(Math.random() * 4);
+ var x, y;
+ // Spawn from edges of the arena
+ switch (edge) {
+ case 0:
+ // Top
+ x = bounds.x + Math.random() * bounds.width;
+ y = bounds.y;
+ break;
+ case 1:
+ // Right
+ x = bounds.x + bounds.width;
+ y = bounds.y + Math.random() * bounds.height;
+ break;
+ case 2:
+ // Bottom
+ x = bounds.x + Math.random() * bounds.width;
+ y = bounds.y + bounds.height;
+ break;
+ case 3:
+ // Left
+ x = bounds.x;
+ y = bounds.y + Math.random() * bounds.height;
+ break;
+ }
+ enemy.init(x, y, player);
+ game.addChild(enemy);
+ enemies.push(enemy);
+}
+function createPowerUp() {
+ var powerUp = new PowerUp();
+ var x = bounds.x + 100 + Math.random() * (bounds.width - 200);
+ var y = bounds.y + 100 + Math.random() * (bounds.height - 200);
+ powerUp.init(x, y);
+ game.addChild(powerUp);
+ powerUps.push(powerUp);
+}
+function createTrap() {
+ var trap = new Trap();
+ var x = bounds.x + 100 + Math.random() * (bounds.width - 200);
+ var y = bounds.y + 100 + Math.random() * (bounds.height - 200);
+ trap.init(x, y);
+ game.addChild(trap);
+ traps.push(trap);
+}
+function updateScoreDisplay() {
+ scoreText.setText('Score: ' + LK.getScore());
+ highScoreText.setText('High Score: ' + storage.highScore);
+}
+function checkCollisions() {
+ if (!player || player.isDead) {
+ return;
+ }
+ // Player-Enemy collisions
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var enemy = enemies[i];
+ if (enemy.isDead) {
+ continue;
+ }
+ if (player.intersects(enemy)) {
+ player.takeDamage(5);
+ LK.getSound('hit').play();
+ }
+ }
+ // Player-PowerUp collisions
+ for (var i = powerUps.length - 1; i >= 0; i--) {
+ var powerUp = powerUps[i];
+ if (!powerUp.active) {
+ continue;
+ }
+ if (player.intersects(powerUp)) {
+ powerUp.collect(player);
+ powerUps.splice(i, 1);
+ }
+ }
+ // Player-Trap collisions
+ for (var i = traps.length - 1; i >= 0; i--) {
+ var trap = traps[i];
+ if (!trap.active) {
+ continue;
+ }
+ if (player.intersects(trap)) {
+ trap.trigger(player);
+ }
+ }
+ // Projectile-Enemy collisions
+ for (var i = projectiles.length - 1; i >= 0; i--) {
+ var projectile = projectiles[i];
+ var hit = false;
+ // Check if projectile is out of bounds
+ if (projectile.isOutOfBounds(bounds)) {
+ projectile.destroy();
+ projectiles.splice(i, 1);
+ continue;
+ }
+ // Check hits against enemies (only if shot by player)
+ if (projectile.direction === 'up') {
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var enemy = enemies[j];
+ if (enemy.isDead) {
+ continue;
+ }
+ if (projectile.intersects(enemy)) {
+ enemy.takeDamage(projectile.damage);
+ LK.getSound('hit').play();
+ if (enemy.health <= 0) {
+ player.addScore(enemy.scoreValue);
+ LK.setScore(player.score);
+ updateScoreDisplay();
+ enemies.splice(j, 1);
+ enemiesDefeated++;
+ // Check if wave is complete
+ if (enemies.length === 0) {
+ LK.setTimeout(startNextWave, 2000);
+ }
+ }
+ hit = true;
+ break;
+ }
+ }
+ }
+ // Check hits against player (only if shot by enemy)
+ else if (projectile.direction === 'custom' && player && !player.isDead) {
+ if (projectile.intersects(player)) {
+ player.takeDamage(projectile.damage);
+ LK.getSound('hit').play();
+ hit = true;
+ }
+ }
+ if (hit) {
+ projectile.destroy();
+ projectiles.splice(i, 1);
+ }
+ }
+}
+// Game input handlers
+game.down = function (x, y, obj) {
+ if (!gameActive) {
+ startGame();
+ return;
+ }
+ if (player && !player.isDead) {
+ dragTarget = player;
+ player.x = x;
+ player.y = y;
+ player.keepInBounds(bounds);
+ }
+};
+game.up = function (x, y, obj) {
+ dragTarget = null;
+ // Shoot on release if game is active
+ if (gameActive && player && !player.isDead) {
+ var projectile = player.shoot();
+ if (projectile) {
+ game.addChild(projectile);
+ projectiles.push(projectile);
+ }
+ }
+};
+game.move = function (x, y, obj) {
+ if (dragTarget === player && player && !player.isDead) {
+ player.x = x;
+ player.y = y;
+ player.keepInBounds(bounds);
+ }
+};
+// Main game update loop
+game.update = function () {
+ if (!gameActive) {
+ // Show start game message if not already started
+ if (!isGameStarting && (!player || player.isDead)) {
+ var _pulseMessage = function pulseMessage() {
+ tween(startMessage, {
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: 800,
+ easing: tween.sinceOut,
+ onFinish: function onFinish() {
+ tween(startMessage, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 800,
+ easing: tween.sinceIn,
+ onFinish: function onFinish() {
+ if (startMessage.parent) {
+ _pulseMessage();
+ }
+ }
+ });
+ }
+ });
+ };
+ var startMessage = new Text2('Tap to Start', {
+ size: 80,
+ fill: 0xFFFFFF
+ });
+ startMessage.anchor.set(0.5, 0.5);
+ LK.gui.center.addChild(startMessage);
+ // Pulse animation for the start message
+ _pulseMessage();
+ gameActive = true; // Set to true so message only shows once
+ }
+ return;
+ }
+ // If player is dead, show game over
+ if (player && player.isDead) {
+ storage.totalMatches++;
+ LK.showGameOver();
+ return;
+ }
+ // Update all game entities
+ if (player) {
+ player.update();
+ }
+ for (var i = 0; i < enemies.length; i++) {
+ if (!enemies[i].isDead) {
+ enemies[i].update();
+ // Chance for enemy to shoot
+ if (Math.random() < 0.005) {
+ var enemyProjectile = enemies[i].attackPlayer();
+ if (enemyProjectile) {
+ game.addChild(enemyProjectile);
+ projectiles.push(enemyProjectile);
+ }
+ }
+ }
+ }
+ for (var i = 0; i < projectiles.length; i++) {
+ projectiles[i].update();
+ }
+ // Check various collisions
+ checkCollisions();
+ // Spawn additional power-ups randomly
+ if (Math.random() < 0.001 && powerUps.length < 5) {
+ createPowerUp();
+ }
+ // Spawn additional traps randomly in later waves
+ if (waveNumber > 2 && Math.random() < 0.0005 && traps.length < waveNumber + 3) {
+ createTrap();
+ }
+};
+// Initial screen
+var titleText = new Text2('Arena Rivals', {
+ size: 120,
+ fill: 0xFFFFFF
+});
+titleText.anchor.set(0.5, 0.5);
+titleText.y = -200;
+LK.gui.center.addChild(titleText);
+var instructionText = new Text2('Tap and drag to move\nRelease to shoot', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+instructionText.anchor.set(0.5, 0.5);
+instructionText.y = 100;
+LK.gui.center.addChild(instructionText);
+// Start game message
+var startMessage = new Text2('Tap to Start', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+startMessage.anchor.set(0.5, 0.5);
+startMessage.y = 300;
+LK.gui.center.addChild(startMessage);
+// Pulse animation for the start message
+function pulseStartMessage() {
+ tween(startMessage, {
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: 800,
+ easing: tween.sinceOut,
+ onFinish: function onFinish() {
+ tween(startMessage, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 800,
+ easing: tween.sinceIn,
+ onFinish: pulseStartMessage
+ });
+ }
+ });
+}
+pulseStartMessage();
\ No newline at end of file