/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Enemy = Container.expand(function (speed, lifetime) { var self = Container.call(this); // Create eye white var eyeWhite = self.attachAsset('eye', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); // Create pupil var pupil = self.attachAsset('pupil', { anchorX: 0.5, anchorY: 0.5 }); // Create hit indicator (initially invisible) var hitCircle = self.attachAsset('hitCircle', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Set properties self.speed = speed || 1; self.vx = (Math.random() - 0.5) * self.speed * 3; self.vy = (Math.random() - 0.5) * self.speed * 3; self.targetTime = lifetime || 2000; // Time needed to hold to destroy (in ms) self.holdTime = 0; // Current time being held self.isHeld = false; self.isDying = false; self.value = Math.floor(self.targetTime / 500); // Score value based on difficulty // Looking animation self.lookTimer = 0; self.lookInterval = Math.random() * 1000 + 500; self.lookAt = function (x, y) { // Calculate angle to look at cursor var dx = x - self.x; var dy = y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Limit pupil movement within eye var maxDistance = eyeWhite.width * 0.3; var scale = distance > maxDistance ? maxDistance / distance : 1; // Move pupil pupil.x = dx * scale * 0.3; pupil.y = dy * scale * 0.3; }; // Hold and destroy functionality self.hold = function (deltaTime) { if (self.isDying) return; if (!self.isHeld) { self.isHeld = true; hitCircle.alpha = 0.7; hitCircle.scaleX = 0; hitCircle.scaleY = 0; tween(hitCircle, { scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); } self.holdTime += deltaTime; // Update visual feedback var progress = Math.min(self.holdTime / self.targetTime, 1); hitCircle.alpha = 0.3 + progress * 0.7; eyeWhite.scaleX = eyeWhite.scaleY = 1 + progress * 0.2; // Check if enemy is destroyed if (self.holdTime >= self.targetTime) { self.destroy(); return true; } return false; }; self.release = function () { if (self.isHeld && !self.isDying) { self.isHeld = false; // Shrink hit circle tween(hitCircle, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 200, easing: tween.easeIn }); // Shrink eye back to normal tween(eyeWhite, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); // Decay hold time when released self.holdTime = Math.max(0, self.holdTime - 500); } }; self.destroy = function () { if (self.isDying) return; self.isDying = true; LK.getSound('destroy').play(); // Play destroy animation tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Remove from parent after animation if (self.parent) { self.parent.removeChild(self); } } }); }; self.update = function (cursorX, cursorY) { if (self.isDying) return; // Move the enemy self.x += self.vx; self.y += self.vy; // Bounce off edges if (self.x < 50 || self.x > 2048 - 50) { self.vx *= -1; } if (self.y < 50 || self.y > 2732 - 50) { self.vy *= -1; } // Look at cursor if provided if (cursorX !== undefined && cursorY !== undefined) { self.lookAt(cursorX, cursorY); } else { // Random eye movement when cursor not provided self.lookTimer += 16.67; // Approx 1 frame at 60fps if (self.lookTimer > self.lookInterval) { pupil.x = (Math.random() - 0.5) * 15; pupil.y = (Math.random() - 0.5) * 15; self.lookTimer = 0; self.lookInterval = Math.random() * 1000 + 500; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x111111 }); /**** * Game Code ****/ // Background var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0 })); // Game variables var enemies = []; var score = 0; var level = 1; var lives = 3; var spawnTimer = 0; var spawnInterval = 3000; // Initial spawn interval var minSpawnInterval = 500; // Minimum spawn interval at highest difficulty var maxEnemies = 5 + level * 2; // Max enemies on screen var heldEnemy = null; var cursorX = 1024; var cursorY = 1366; var gameRunning = true; // Initialize score text var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 40; LK.gui.top.addChild(scoreTxt); // Initialize level text var levelTxt = new Text2('Level: 1', { size: 50, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); levelTxt.x = 50; levelTxt.y = 40; LK.gui.topRight.addChild(levelTxt); // Initialize lives text var livesTxt = new Text2('Lives: 3', { size: 50, fill: 0xFFFFFF }); livesTxt.anchor.set(1, 0); livesTxt.x = -50; livesTxt.y = 40; LK.gui.topRight.addChild(livesTxt); // Helper function to spawn an enemy function spawnEnemy() { if (enemies.length >= maxEnemies || !gameRunning) return; // Create enemy with speed and lifetime based on level var enemySpeed = 1 + level * 0.3; var lifetime = 2000 - level * 100; lifetime = Math.max(lifetime, 800); // Minimum 800ms to destroy var enemy = new Enemy(enemySpeed, lifetime); // Position randomly, keeping away from edges enemy.x = Math.random() * (2048 - 200) + 100; enemy.y = Math.random() * (2732 - 200) + 100; // Add to game and array game.addChild(enemy); enemies.push(enemy); // Reset spawn timer spawnTimer = 0; } // Increase difficulty level function levelUp() { level++; // Increase difficulty parameters maxEnemies = 5 + level * 2; spawnInterval = Math.max(minSpawnInterval, 3000 - level * 200); // Update level display levelTxt.setText('Level: ' + level); // Play level up sound LK.getSound('levelup').play(); // Visual feedback LK.effects.flashScreen(0x6666FF, 500); } // Check for level up condition function checkLevelUp() { // Level up every 10 score points if (score > 0 && score % 10 === 0) { levelUp(); } } // Update score function updateScore(points) { var oldScore = score; score += points; scoreTxt.setText('Score: ' + score); // Check if we should level up if (Math.floor(score / 10) > Math.floor(oldScore / 10)) { levelUp(); } } // Lose a life function loseLife() { lives--; livesTxt.setText('Lives: ' + lives); // Visual feedback LK.effects.flashScreen(0xFF0000, 500); // Check for game over if (lives <= 0) { gameOver(); } } // Game over function gameOver() { gameRunning = false; LK.setScore(score); LK.showGameOver(); } // Mouse/touch down event game.down = function (x, y) { if (!gameRunning) return; cursorX = x; cursorY = y; // Check if we hit an enemy for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Simple distance check (could be replaced with intersects()) var dx = enemy.x - x; var dy = enemy.y - y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 50) { heldEnemy = enemy; LK.getSound('catch').play(); break; } } }; // Mouse/touch move event game.move = function (x, y) { cursorX = x; cursorY = y; }; // Mouse/touch up event game.up = function () { if (heldEnemy) { heldEnemy.release(); heldEnemy = null; } }; // Main game update loop game.update = function () { if (!gameRunning) return; // Spawn enemies spawnTimer += 16.67; // Approx 1 frame at 60fps if (spawnTimer >= spawnInterval) { spawnEnemy(); } // Check for escaped enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; // Check if enemy is completely off screen if (enemy.x < -100 || enemy.x > 2148 || enemy.y < -100 || enemy.y > 2832) { // Remove enemy and lose a life enemy.parent.removeChild(enemy); enemies.splice(i, 1); loseLife(); continue; } // Update enemy enemy.update(cursorX, cursorY); } // Handle held enemy if (heldEnemy && heldEnemy.hold(16.67)) { // Enemy was destroyed, add score updateScore(heldEnemy.value); // Remove from array var index = enemies.indexOf(heldEnemy); if (index !== -1) { enemies.splice(index, 1); } heldEnemy = null; } }; // Start game music LK.playMusic('gameBgm', { fade: { start: 0, end: 0.4, duration: 1000 } });
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,345 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var Enemy = Container.expand(function (speed, lifetime) {
+ var self = Container.call(this);
+ // Create eye white
+ var eyeWhite = self.attachAsset('eye', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 1,
+ scaleY: 1
+ });
+ // Create pupil
+ var pupil = self.attachAsset('pupil', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Create hit indicator (initially invisible)
+ var hitCircle = self.attachAsset('hitCircle', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0
+ });
+ // Set properties
+ self.speed = speed || 1;
+ self.vx = (Math.random() - 0.5) * self.speed * 3;
+ self.vy = (Math.random() - 0.5) * self.speed * 3;
+ self.targetTime = lifetime || 2000; // Time needed to hold to destroy (in ms)
+ self.holdTime = 0; // Current time being held
+ self.isHeld = false;
+ self.isDying = false;
+ self.value = Math.floor(self.targetTime / 500); // Score value based on difficulty
+ // Looking animation
+ self.lookTimer = 0;
+ self.lookInterval = Math.random() * 1000 + 500;
+ self.lookAt = function (x, y) {
+ // Calculate angle to look at cursor
+ var dx = x - self.x;
+ var dy = y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ // Limit pupil movement within eye
+ var maxDistance = eyeWhite.width * 0.3;
+ var scale = distance > maxDistance ? maxDistance / distance : 1;
+ // Move pupil
+ pupil.x = dx * scale * 0.3;
+ pupil.y = dy * scale * 0.3;
+ };
+ // Hold and destroy functionality
+ self.hold = function (deltaTime) {
+ if (self.isDying) return;
+ if (!self.isHeld) {
+ self.isHeld = true;
+ hitCircle.alpha = 0.7;
+ hitCircle.scaleX = 0;
+ hitCircle.scaleY = 0;
+ tween(hitCircle, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ }
+ self.holdTime += deltaTime;
+ // Update visual feedback
+ var progress = Math.min(self.holdTime / self.targetTime, 1);
+ hitCircle.alpha = 0.3 + progress * 0.7;
+ eyeWhite.scaleX = eyeWhite.scaleY = 1 + progress * 0.2;
+ // Check if enemy is destroyed
+ if (self.holdTime >= self.targetTime) {
+ self.destroy();
+ return true;
+ }
+ return false;
+ };
+ self.release = function () {
+ if (self.isHeld && !self.isDying) {
+ self.isHeld = false;
+ // Shrink hit circle
+ tween(hitCircle, {
+ alpha: 0,
+ scaleX: 0.8,
+ scaleY: 0.8
+ }, {
+ duration: 200,
+ easing: tween.easeIn
+ });
+ // Shrink eye back to normal
+ tween(eyeWhite, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ // Decay hold time when released
+ self.holdTime = Math.max(0, self.holdTime - 500);
+ }
+ };
+ self.destroy = function () {
+ if (self.isDying) return;
+ self.isDying = true;
+ LK.getSound('destroy').play();
+ // Play destroy animation
+ tween(self, {
+ alpha: 0,
+ scaleX: 1.5,
+ scaleY: 1.5
+ }, {
+ duration: 300,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ // Remove from parent after animation
+ if (self.parent) {
+ self.parent.removeChild(self);
+ }
+ }
+ });
+ };
+ self.update = function (cursorX, cursorY) {
+ if (self.isDying) return;
+ // Move the enemy
+ self.x += self.vx;
+ self.y += self.vy;
+ // Bounce off edges
+ if (self.x < 50 || self.x > 2048 - 50) {
+ self.vx *= -1;
+ }
+ if (self.y < 50 || self.y > 2732 - 50) {
+ self.vy *= -1;
+ }
+ // Look at cursor if provided
+ if (cursorX !== undefined && cursorY !== undefined) {
+ self.lookAt(cursorX, cursorY);
+ } else {
+ // Random eye movement when cursor not provided
+ self.lookTimer += 16.67; // Approx 1 frame at 60fps
+ if (self.lookTimer > self.lookInterval) {
+ pupil.x = (Math.random() - 0.5) * 15;
+ pupil.y = (Math.random() - 0.5) * 15;
+ self.lookTimer = 0;
+ self.lookInterval = Math.random() * 1000 + 500;
+ }
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x111111
+});
+
+/****
+* Game Code
+****/
+// Background
+var background = game.addChild(LK.getAsset('background', {
+ anchorX: 0,
+ anchorY: 0
+}));
+// Game variables
+var enemies = [];
+var score = 0;
+var level = 1;
+var lives = 3;
+var spawnTimer = 0;
+var spawnInterval = 3000; // Initial spawn interval
+var minSpawnInterval = 500; // Minimum spawn interval at highest difficulty
+var maxEnemies = 5 + level * 2; // Max enemies on screen
+var heldEnemy = null;
+var cursorX = 1024;
+var cursorY = 1366;
+var gameRunning = true;
+// Initialize score text
+var scoreTxt = new Text2('Score: 0', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+scoreTxt.y = 40;
+LK.gui.top.addChild(scoreTxt);
+// Initialize level text
+var levelTxt = new Text2('Level: 1', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+levelTxt.anchor.set(0, 0);
+levelTxt.x = 50;
+levelTxt.y = 40;
+LK.gui.topRight.addChild(levelTxt);
+// Initialize lives text
+var livesTxt = new Text2('Lives: 3', {
+ size: 50,
+ fill: 0xFFFFFF
+});
+livesTxt.anchor.set(1, 0);
+livesTxt.x = -50;
+livesTxt.y = 40;
+LK.gui.topRight.addChild(livesTxt);
+// Helper function to spawn an enemy
+function spawnEnemy() {
+ if (enemies.length >= maxEnemies || !gameRunning) return;
+ // Create enemy with speed and lifetime based on level
+ var enemySpeed = 1 + level * 0.3;
+ var lifetime = 2000 - level * 100;
+ lifetime = Math.max(lifetime, 800); // Minimum 800ms to destroy
+ var enemy = new Enemy(enemySpeed, lifetime);
+ // Position randomly, keeping away from edges
+ enemy.x = Math.random() * (2048 - 200) + 100;
+ enemy.y = Math.random() * (2732 - 200) + 100;
+ // Add to game and array
+ game.addChild(enemy);
+ enemies.push(enemy);
+ // Reset spawn timer
+ spawnTimer = 0;
+}
+// Increase difficulty level
+function levelUp() {
+ level++;
+ // Increase difficulty parameters
+ maxEnemies = 5 + level * 2;
+ spawnInterval = Math.max(minSpawnInterval, 3000 - level * 200);
+ // Update level display
+ levelTxt.setText('Level: ' + level);
+ // Play level up sound
+ LK.getSound('levelup').play();
+ // Visual feedback
+ LK.effects.flashScreen(0x6666FF, 500);
+}
+// Check for level up condition
+function checkLevelUp() {
+ // Level up every 10 score points
+ if (score > 0 && score % 10 === 0) {
+ levelUp();
+ }
+}
+// Update score
+function updateScore(points) {
+ var oldScore = score;
+ score += points;
+ scoreTxt.setText('Score: ' + score);
+ // Check if we should level up
+ if (Math.floor(score / 10) > Math.floor(oldScore / 10)) {
+ levelUp();
+ }
+}
+// Lose a life
+function loseLife() {
+ lives--;
+ livesTxt.setText('Lives: ' + lives);
+ // Visual feedback
+ LK.effects.flashScreen(0xFF0000, 500);
+ // Check for game over
+ if (lives <= 0) {
+ gameOver();
+ }
+}
+// Game over
+function gameOver() {
+ gameRunning = false;
+ LK.setScore(score);
+ LK.showGameOver();
+}
+// Mouse/touch down event
+game.down = function (x, y) {
+ if (!gameRunning) return;
+ cursorX = x;
+ cursorY = y;
+ // Check if we hit an enemy
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ // Simple distance check (could be replaced with intersects())
+ var dx = enemy.x - x;
+ var dy = enemy.y - y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 50) {
+ heldEnemy = enemy;
+ LK.getSound('catch').play();
+ break;
+ }
+ }
+};
+// Mouse/touch move event
+game.move = function (x, y) {
+ cursorX = x;
+ cursorY = y;
+};
+// Mouse/touch up event
+game.up = function () {
+ if (heldEnemy) {
+ heldEnemy.release();
+ heldEnemy = null;
+ }
+};
+// Main game update loop
+game.update = function () {
+ if (!gameRunning) return;
+ // Spawn enemies
+ spawnTimer += 16.67; // Approx 1 frame at 60fps
+ if (spawnTimer >= spawnInterval) {
+ spawnEnemy();
+ }
+ // Check for escaped enemies
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var enemy = enemies[i];
+ // Check if enemy is completely off screen
+ if (enemy.x < -100 || enemy.x > 2148 || enemy.y < -100 || enemy.y > 2832) {
+ // Remove enemy and lose a life
+ enemy.parent.removeChild(enemy);
+ enemies.splice(i, 1);
+ loseLife();
+ continue;
+ }
+ // Update enemy
+ enemy.update(cursorX, cursorY);
+ }
+ // Handle held enemy
+ if (heldEnemy && heldEnemy.hold(16.67)) {
+ // Enemy was destroyed, add score
+ updateScore(heldEnemy.value);
+ // Remove from array
+ var index = enemies.indexOf(heldEnemy);
+ if (index !== -1) {
+ enemies.splice(index, 1);
+ }
+ heldEnemy = null;
+ }
+};
+// Start game music
+LK.playMusic('gameBgm', {
+ fade: {
+ start: 0,
+ end: 0.4,
+ duration: 1000
+ }
});
\ No newline at end of file