/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var CaptureZone = Container.expand(function () { var self = Container.call(this); var heart = self.attachAsset('heartCaptureZone', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); self.isExpanded = false; self.baseScale = 1; self.expandZone = function (duration) { self.isExpanded = true; var targetScale = self.baseScale * 1.5; tween(self, { scaleX: targetScale, scaleY: targetScale }, { duration: 200, easing: tween.easeOut }); LK.setTimeout(function () { self.isExpanded = false; tween(self, { scaleX: self.baseScale, scaleY: self.baseScale }, { duration: 200, easing: tween.easeIn }); }, duration); }; self.pulse = function () { tween(heart, { alpha: 0.9, scaleX: 1.1, scaleY: 1.1 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(heart, { alpha: 0.7, scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeIn }); } }); }; return self; }); var Ghost = Container.expand(function () { var self = Container.call(this); // Ghost body parts var body = self.attachAsset('ghostBody', { anchorX: 0.5, anchorY: 0.5 }); var bottom = self.attachAsset('ghostBottom', { anchorX: 0.5, anchorY: 0, y: 70 }); var leftEye = self.attachAsset('ghostEye', { anchorX: 0.5, anchorY: 0.5, x: -40, y: -30 }); var rightEye = self.attachAsset('ghostEye', { anchorX: 0.5, anchorY: 0.5, x: 40, y: -30 }); var mouth = self.attachAsset('ghostMouth', { anchorX: 0.5, anchorY: 0.5, y: 30 }); // Ghost properties self.speed = 3; self.targetX = 0; self.targetY = 0; self.changeDirectionTimer = 0; self.elusiveness = 1.0; self.isCaught = false; self.isSlowed = false; self.setRandomTarget = function () { self.targetX = Math.random() * (2048 - 400) + 200; self.targetY = Math.random() * (2732 - 400) + 200; self.changeDirectionTimer = Math.floor(Math.random() * 120) + 60; }; self.fleeFromPoint = function (x, y) { if (!self.isSlowed) { var dx = self.x - x; var dy = self.y - y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 400) { self.targetX = self.x + dx / distance * 500; self.targetY = self.y + dy / distance * 500; // Constrain to screen boundaries self.targetX = Math.max(100, Math.min(2048 - 100, self.targetX)); self.targetY = Math.max(100, Math.min(2732 - 100, self.targetY)); self.changeDirectionTimer = 60; } } }; self.applySlowEffect = function (duration) { self.isSlowed = true; tween(self, { tint: 0x00ffff }, { duration: 200 }); LK.setTimeout(function () { self.isSlowed = false; tween(self, { tint: 0xffffff }, { duration: 200 }); }, duration); }; self.update = function () { if (self.isCaught) { return; } self.changeDirectionTimer--; if (self.changeDirectionTimer <= 0) { self.setRandomTarget(); } // Move toward target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { var actualSpeed = self.isSlowed ? self.speed / 2 : self.speed * self.elusiveness; self.x += dx / distance * actualSpeed; self.y += dy / distance * actualSpeed; } // Ghostly hovering animation body.y = Math.sin(LK.ticks / 20) * 5; bottom.y = 70 + Math.sin(LK.ticks / 20) * 5; leftEye.y = -30 + Math.sin(LK.ticks / 25) * 3; rightEye.y = -30 + Math.sin(LK.ticks / 25) * 3; mouth.y = 30 + Math.sin(LK.ticks / 22) * 3; }; self.setCaught = function (isCaught) { self.isCaught = isCaught; if (isCaught) { tween(self, { alpha: 0.6, scaleX: 0.8, scaleY: 0.8 }, { duration: 300, easing: tween.easeOut }); } else { tween(self, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); } }; self.down = function (x, y, obj) { if (!self.isCaught) { // Change direction when tapped self.fleeFromPoint(x, y); // Start dragging if close enough var localPoint = self.toLocal({ x: x, y: y }); var distance = Math.sqrt(localPoint.x * localPoint.x + localPoint.y * localPoint.y); if (distance < 100) { game.dragTarget = self; } } }; // Initialize with random target self.setRandomTarget(); return self; }); var PowerUp = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'slow'; var asset = self.type === 'slow' ? 'powerupSlow' : 'powerupExpand'; var graphic = self.attachAsset(asset, { anchorX: 0.5, anchorY: 0.5 }); self.lifespan = 300; // 5 seconds at 60fps self.update = function () { self.lifespan--; // Fade out when nearing the end of lifespan if (self.lifespan < 60) { graphic.alpha = self.lifespan / 60; } // Hover animation self.y += Math.sin(LK.ticks / 10) * 0.5; // Remove when expired if (self.lifespan <= 0) { self.destroy(); var index = powerups.indexOf(self); if (index !== -1) { powerups.splice(index, 1); } } }; self.down = function (x, y, obj) { // Collect the powerup LK.getSound('powerup').play(); if (self.type === 'slow') { ghost.applySlowEffect(3000); // 3 seconds slow } else if (self.type === 'expand') { captureZone.expandZone(3000); // 3 seconds expanded } // Remove powerup self.destroy(); var index = powerups.indexOf(self); if (index !== -1) { powerups.splice(index, 1); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x6a89cc }); /**** * Game Code ****/ // Variables to track game state var score = 0; var ghostsCaught = 0; var gameTime = 0; var level = 1; var powerups = []; var powerupTimer = 0; var ghostElusiveness = 1.0; // Create scoreboard var scoreText = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); scoreText.y = 20; // Create level display var levelText = new Text2('Level: 1', { size: 60, fill: 0xFFFFFF }); levelText.anchor.set(0, 0); LK.gui.topRight.addChild(levelText); levelText.x = -200; levelText.y = 30; // Create time display var timeText = new Text2('Time: 0', { size: 60, fill: 0xFFFFFF }); timeText.anchor.set(1, 0); LK.gui.topRight.addChild(timeText); timeText.x = -20; timeText.y = 30; // Create capture zone (heart) var captureZone = new CaptureZone(); captureZone.x = 2048 / 2; captureZone.y = 2732 / 2; game.addChild(captureZone); // Create ghost var ghost = new Ghost(); ghost.x = 2048 / 4; ghost.y = 2732 / 4; game.addChild(ghost); // Track dragging game.dragTarget = null; // Handle touch/mouse events game.down = function (x, y, obj) { // This will be primarily handled by the ghost's own down method if (!game.dragTarget) { var dragDist = Math.sqrt(Math.pow(x - captureZone.x, 2) + Math.pow(y - captureZone.y, 2)); if (dragDist < 150) { game.dragTarget = captureZone; } } }; game.move = function (x, y, obj) { if (game.dragTarget) { game.dragTarget.x = x; game.dragTarget.y = y; // Keep within screen bounds game.dragTarget.x = Math.max(150, Math.min(2048 - 150, game.dragTarget.x)); game.dragTarget.y = Math.max(150, Math.min(2732 - 150, game.dragTarget.y)); } // If dragging ghost, make the ghost flee if (game.dragTarget !== ghost && !ghost.isCaught) { ghost.fleeFromPoint(x, y); } }; game.up = function (x, y, obj) { game.dragTarget = null; }; function spawnPowerup() { var type = Math.random() > 0.5 ? 'slow' : 'expand'; var powerup = new PowerUp(type); // Position away from edges and the current ghost position var minDistance = 300; var maxTries = 10; var tries = 0; var validPosition = false; while (!validPosition && tries < maxTries) { powerup.x = Math.random() * (2048 - 300) + 150; powerup.y = Math.random() * (2732 - 300) + 150; var distanceToGhost = Math.sqrt(Math.pow(powerup.x - ghost.x, 2) + Math.pow(powerup.y - ghost.y, 2)); var distanceToCaptureZone = Math.sqrt(Math.pow(powerup.x - captureZone.x, 2) + Math.pow(powerup.y - captureZone.y, 2)); if (distanceToGhost > minDistance && distanceToCaptureZone > minDistance) { validPosition = true; } tries++; } powerups.push(powerup); game.addChild(powerup); // Reset powerup timer powerupTimer = Math.floor(Math.random() * 300) + 300; // 5-10 seconds } function updateLevel() { level = Math.floor(ghostsCaught / 5) + 1; levelText.setText('Level: ' + level); // Increase ghost elusiveness with level ghostElusiveness = 1.0 + (level - 1) * 0.15; ghost.elusiveness = ghostElusiveness; // Visual feedback for level up if (ghostsCaught % 5 === 0 && ghostsCaught > 0) { LK.effects.flashScreen(0xffff00, 500); } } function checkGhostCapture() { if (ghost.isCaught) { return; } var distance = Math.sqrt(Math.pow(ghost.x - captureZone.x, 2) + Math.pow(ghost.y - captureZone.y, 2)); var captureRadius = captureZone.isExpanded ? 150 * 1.5 : 150; if (distance < captureRadius) { // Ghost is caught! ghost.setCaught(true); LK.getSound('catch').play(); captureZone.pulse(); // Award points score += level * 10; scoreText.setText('Score: ' + score); LK.setScore(score); // Increment captures count ghostsCaught++; updateLevel(); // Release ghost after a short delay LK.setTimeout(function () { ghost.setCaught(false); // Move ghost to random position ghost.x = Math.random() * (2048 - 400) + 200; ghost.y = Math.random() * (2732 - 400) + 200; ghost.setRandomTarget(); LK.getSound('escaped').play(); }, 1500); } } // Save high score when game over function saveHighScore() { var currentHighScore = storage.highScore || 0; if (score > currentHighScore) { storage.highScore = score; } } // Update function called every frame game.update = function () { // Update game time (in seconds) if (LK.ticks % 60 === 0) { gameTime++; timeText.setText('Time: ' + gameTime); } // Check if ghost is in capture zone checkGhostCapture(); // Update powerup timer and spawn new ones powerupTimer--; if (powerupTimer <= 0 && powerups.length < 2) { spawnPowerup(); } // Game over condition - if player reaches very high level or time runs out if (level >= 20) { saveHighScore(); LK.showYouWin(); } }; // Start background music LK.playMusic('bgMusic', { fade: { start: 0, end: 0.4, duration: 1000 } });
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,423 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var CaptureZone = Container.expand(function () {
+ var self = Container.call(this);
+ var heart = self.attachAsset('heartCaptureZone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.7
+ });
+ self.isExpanded = false;
+ self.baseScale = 1;
+ self.expandZone = function (duration) {
+ self.isExpanded = true;
+ var targetScale = self.baseScale * 1.5;
+ tween(self, {
+ scaleX: targetScale,
+ scaleY: targetScale
+ }, {
+ duration: 200,
+ easing: tween.easeOut
+ });
+ LK.setTimeout(function () {
+ self.isExpanded = false;
+ tween(self, {
+ scaleX: self.baseScale,
+ scaleY: self.baseScale
+ }, {
+ duration: 200,
+ easing: tween.easeIn
+ });
+ }, duration);
+ };
+ self.pulse = function () {
+ tween(heart, {
+ alpha: 0.9,
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: 150,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(heart, {
+ alpha: 0.7,
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200,
+ easing: tween.easeIn
+ });
+ }
+ });
+ };
+ return self;
+});
+var Ghost = Container.expand(function () {
+ var self = Container.call(this);
+ // Ghost body parts
+ var body = self.attachAsset('ghostBody', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var bottom = self.attachAsset('ghostBottom', {
+ anchorX: 0.5,
+ anchorY: 0,
+ y: 70
+ });
+ var leftEye = self.attachAsset('ghostEye', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: -40,
+ y: -30
+ });
+ var rightEye = self.attachAsset('ghostEye', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 40,
+ y: -30
+ });
+ var mouth = self.attachAsset('ghostMouth', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: 30
+ });
+ // Ghost properties
+ self.speed = 3;
+ self.targetX = 0;
+ self.targetY = 0;
+ self.changeDirectionTimer = 0;
+ self.elusiveness = 1.0;
+ self.isCaught = false;
+ self.isSlowed = false;
+ self.setRandomTarget = function () {
+ self.targetX = Math.random() * (2048 - 400) + 200;
+ self.targetY = Math.random() * (2732 - 400) + 200;
+ self.changeDirectionTimer = Math.floor(Math.random() * 120) + 60;
+ };
+ self.fleeFromPoint = function (x, y) {
+ if (!self.isSlowed) {
+ var dx = self.x - x;
+ var dy = self.y - y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 400) {
+ self.targetX = self.x + dx / distance * 500;
+ self.targetY = self.y + dy / distance * 500;
+ // Constrain to screen boundaries
+ self.targetX = Math.max(100, Math.min(2048 - 100, self.targetX));
+ self.targetY = Math.max(100, Math.min(2732 - 100, self.targetY));
+ self.changeDirectionTimer = 60;
+ }
+ }
+ };
+ self.applySlowEffect = function (duration) {
+ self.isSlowed = true;
+ tween(self, {
+ tint: 0x00ffff
+ }, {
+ duration: 200
+ });
+ LK.setTimeout(function () {
+ self.isSlowed = false;
+ tween(self, {
+ tint: 0xffffff
+ }, {
+ duration: 200
+ });
+ }, duration);
+ };
+ self.update = function () {
+ if (self.isCaught) {
+ return;
+ }
+ self.changeDirectionTimer--;
+ if (self.changeDirectionTimer <= 0) {
+ self.setRandomTarget();
+ }
+ // Move toward target
+ var dx = self.targetX - self.x;
+ var dy = self.targetY - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 5) {
+ var actualSpeed = self.isSlowed ? self.speed / 2 : self.speed * self.elusiveness;
+ self.x += dx / distance * actualSpeed;
+ self.y += dy / distance * actualSpeed;
+ }
+ // Ghostly hovering animation
+ body.y = Math.sin(LK.ticks / 20) * 5;
+ bottom.y = 70 + Math.sin(LK.ticks / 20) * 5;
+ leftEye.y = -30 + Math.sin(LK.ticks / 25) * 3;
+ rightEye.y = -30 + Math.sin(LK.ticks / 25) * 3;
+ mouth.y = 30 + Math.sin(LK.ticks / 22) * 3;
+ };
+ self.setCaught = function (isCaught) {
+ self.isCaught = isCaught;
+ if (isCaught) {
+ tween(self, {
+ alpha: 0.6,
+ scaleX: 0.8,
+ scaleY: 0.8
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ } else {
+ tween(self, {
+ alpha: 1,
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ }
+ };
+ self.down = function (x, y, obj) {
+ if (!self.isCaught) {
+ // Change direction when tapped
+ self.fleeFromPoint(x, y);
+ // Start dragging if close enough
+ var localPoint = self.toLocal({
+ x: x,
+ y: y
+ });
+ var distance = Math.sqrt(localPoint.x * localPoint.x + localPoint.y * localPoint.y);
+ if (distance < 100) {
+ game.dragTarget = self;
+ }
+ }
+ };
+ // Initialize with random target
+ self.setRandomTarget();
+ return self;
+});
+var PowerUp = Container.expand(function (type) {
+ var self = Container.call(this);
+ self.type = type || 'slow';
+ var asset = self.type === 'slow' ? 'powerupSlow' : 'powerupExpand';
+ var graphic = self.attachAsset(asset, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.lifespan = 300; // 5 seconds at 60fps
+ self.update = function () {
+ self.lifespan--;
+ // Fade out when nearing the end of lifespan
+ if (self.lifespan < 60) {
+ graphic.alpha = self.lifespan / 60;
+ }
+ // Hover animation
+ self.y += Math.sin(LK.ticks / 10) * 0.5;
+ // Remove when expired
+ if (self.lifespan <= 0) {
+ self.destroy();
+ var index = powerups.indexOf(self);
+ if (index !== -1) {
+ powerups.splice(index, 1);
+ }
+ }
+ };
+ self.down = function (x, y, obj) {
+ // Collect the powerup
+ LK.getSound('powerup').play();
+ if (self.type === 'slow') {
+ ghost.applySlowEffect(3000); // 3 seconds slow
+ } else if (self.type === 'expand') {
+ captureZone.expandZone(3000); // 3 seconds expanded
+ }
+ // Remove powerup
+ self.destroy();
+ var index = powerups.indexOf(self);
+ if (index !== -1) {
+ powerups.splice(index, 1);
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x6a89cc
+});
+
+/****
+* Game Code
+****/
+// Variables to track game state
+var score = 0;
+var ghostsCaught = 0;
+var gameTime = 0;
+var level = 1;
+var powerups = [];
+var powerupTimer = 0;
+var ghostElusiveness = 1.0;
+// Create scoreboard
+var scoreText = new Text2('Score: 0', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreText);
+scoreText.y = 20;
+// Create level display
+var levelText = new Text2('Level: 1', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+levelText.anchor.set(0, 0);
+LK.gui.topRight.addChild(levelText);
+levelText.x = -200;
+levelText.y = 30;
+// Create time display
+var timeText = new Text2('Time: 0', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+timeText.anchor.set(1, 0);
+LK.gui.topRight.addChild(timeText);
+timeText.x = -20;
+timeText.y = 30;
+// Create capture zone (heart)
+var captureZone = new CaptureZone();
+captureZone.x = 2048 / 2;
+captureZone.y = 2732 / 2;
+game.addChild(captureZone);
+// Create ghost
+var ghost = new Ghost();
+ghost.x = 2048 / 4;
+ghost.y = 2732 / 4;
+game.addChild(ghost);
+// Track dragging
+game.dragTarget = null;
+// Handle touch/mouse events
+game.down = function (x, y, obj) {
+ // This will be primarily handled by the ghost's own down method
+ if (!game.dragTarget) {
+ var dragDist = Math.sqrt(Math.pow(x - captureZone.x, 2) + Math.pow(y - captureZone.y, 2));
+ if (dragDist < 150) {
+ game.dragTarget = captureZone;
+ }
+ }
+};
+game.move = function (x, y, obj) {
+ if (game.dragTarget) {
+ game.dragTarget.x = x;
+ game.dragTarget.y = y;
+ // Keep within screen bounds
+ game.dragTarget.x = Math.max(150, Math.min(2048 - 150, game.dragTarget.x));
+ game.dragTarget.y = Math.max(150, Math.min(2732 - 150, game.dragTarget.y));
+ }
+ // If dragging ghost, make the ghost flee
+ if (game.dragTarget !== ghost && !ghost.isCaught) {
+ ghost.fleeFromPoint(x, y);
+ }
+};
+game.up = function (x, y, obj) {
+ game.dragTarget = null;
+};
+function spawnPowerup() {
+ var type = Math.random() > 0.5 ? 'slow' : 'expand';
+ var powerup = new PowerUp(type);
+ // Position away from edges and the current ghost position
+ var minDistance = 300;
+ var maxTries = 10;
+ var tries = 0;
+ var validPosition = false;
+ while (!validPosition && tries < maxTries) {
+ powerup.x = Math.random() * (2048 - 300) + 150;
+ powerup.y = Math.random() * (2732 - 300) + 150;
+ var distanceToGhost = Math.sqrt(Math.pow(powerup.x - ghost.x, 2) + Math.pow(powerup.y - ghost.y, 2));
+ var distanceToCaptureZone = Math.sqrt(Math.pow(powerup.x - captureZone.x, 2) + Math.pow(powerup.y - captureZone.y, 2));
+ if (distanceToGhost > minDistance && distanceToCaptureZone > minDistance) {
+ validPosition = true;
+ }
+ tries++;
+ }
+ powerups.push(powerup);
+ game.addChild(powerup);
+ // Reset powerup timer
+ powerupTimer = Math.floor(Math.random() * 300) + 300; // 5-10 seconds
+}
+function updateLevel() {
+ level = Math.floor(ghostsCaught / 5) + 1;
+ levelText.setText('Level: ' + level);
+ // Increase ghost elusiveness with level
+ ghostElusiveness = 1.0 + (level - 1) * 0.15;
+ ghost.elusiveness = ghostElusiveness;
+ // Visual feedback for level up
+ if (ghostsCaught % 5 === 0 && ghostsCaught > 0) {
+ LK.effects.flashScreen(0xffff00, 500);
+ }
+}
+function checkGhostCapture() {
+ if (ghost.isCaught) {
+ return;
+ }
+ var distance = Math.sqrt(Math.pow(ghost.x - captureZone.x, 2) + Math.pow(ghost.y - captureZone.y, 2));
+ var captureRadius = captureZone.isExpanded ? 150 * 1.5 : 150;
+ if (distance < captureRadius) {
+ // Ghost is caught!
+ ghost.setCaught(true);
+ LK.getSound('catch').play();
+ captureZone.pulse();
+ // Award points
+ score += level * 10;
+ scoreText.setText('Score: ' + score);
+ LK.setScore(score);
+ // Increment captures count
+ ghostsCaught++;
+ updateLevel();
+ // Release ghost after a short delay
+ LK.setTimeout(function () {
+ ghost.setCaught(false);
+ // Move ghost to random position
+ ghost.x = Math.random() * (2048 - 400) + 200;
+ ghost.y = Math.random() * (2732 - 400) + 200;
+ ghost.setRandomTarget();
+ LK.getSound('escaped').play();
+ }, 1500);
+ }
+}
+// Save high score when game over
+function saveHighScore() {
+ var currentHighScore = storage.highScore || 0;
+ if (score > currentHighScore) {
+ storage.highScore = score;
+ }
+}
+// Update function called every frame
+game.update = function () {
+ // Update game time (in seconds)
+ if (LK.ticks % 60 === 0) {
+ gameTime++;
+ timeText.setText('Time: ' + gameTime);
+ }
+ // Check if ghost is in capture zone
+ checkGhostCapture();
+ // Update powerup timer and spawn new ones
+ powerupTimer--;
+ if (powerupTimer <= 0 && powerups.length < 2) {
+ spawnPowerup();
+ }
+ // Game over condition - if player reaches very high level or time runs out
+ if (level >= 20) {
+ saveHighScore();
+ LK.showYouWin();
+ }
+};
+// Start background music
+LK.playMusic('bgMusic', {
+ fade: {
+ start: 0,
+ end: 0.4,
+ duration: 1000
+ }
});
\ No newline at end of file