/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, totalCoins: 0 }); /**** * Classes ****/ var Coin = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.lane = Math.floor(Math.random() * 3); // 0, 1, 2 self.speed = 0; self.collected = false; self.update = function () { self.y += self.speed; // Rotate coin for visual effect sprite.rotation += 0.05; }; self.collect = function () { if (!self.collected) { self.collected = true; LK.getSound('coin_collect').play(); // Visual effect for collection tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300 }); return true; } return false; }; return self; }); var Obstacle = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'barrier'; // barrier, train, hole var assetId = self.type === 'train' ? 'train' : 'obstacle'; var sprite = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Customize appearance based on type if (self.type === 'barrier') { sprite.tint = 0x4285F4; // Blue barrier } else if (self.type === 'train') { sprite.tint = 0x34A853; // Green train } else if (self.type === 'hole') { sprite.tint = 0x000000; // Black hole } self.lane = Math.floor(Math.random() * 3); // 0, 1, 2 self.speed = 0; self.update = function () { self.y += self.speed; }; self.needsJump = function () { return self.type === 'barrier'; }; self.needsSlide = function () { return self.type === 'hole'; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.lane = 1; // 0, 1, 2 (left, center, right) self.isJumping = false; self.isSliding = false; self.isInvincible = false; self.magnetActive = false; self.jump = function () { if (!self.isJumping && !self.isSliding) { self.isJumping = true; var originalY = self.y; LK.getSound('jump').play(); // Jump animation tween(self, { y: originalY - 200 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { // Fall back down tween(self, { y: originalY }, { duration: 400, easing: tween.easeIn, onFinish: function onFinish() { self.isJumping = false; } }); } }); } }; self.slide = function () { if (!self.isJumping && !self.isSliding) { self.isSliding = true; // Scale the player to look like sliding var originalHeight = sprite.height; var originalY = self.y; tween(sprite, { height: originalHeight * 0.5 }, { duration: 300, onFinish: function onFinish() { // Move player's position to compensate for height change self.y = originalY + originalHeight * 0.25; // Return to normal after sliding LK.setTimeout(function () { tween(sprite, { height: originalHeight }, { duration: 300, onFinish: function onFinish() { self.y = originalY; self.isSliding = false; } }); }, 500); } }); } }; self.changeLane = function (direction) { // direction: -1 for left, 1 for right var newLane = self.lane + direction; // Ensure lane is valid (0, 1, 2) if (newLane >= 0 && newLane <= 2) { self.lane = newLane; // Animate movement to new lane tween(self, { x: getLaneXPosition(self.lane) }, { duration: 200, easing: tween.easeOut }); } }; self.activateInvincibility = function () { if (!self.isInvincible) { self.isInvincible = true; // Visual indicator for invincibility var flashInterval = LK.setInterval(function () { sprite.alpha = sprite.alpha === 1 ? 0.5 : 1; }, 150); // Deactivate after 5 seconds LK.setTimeout(function () { LK.clearInterval(flashInterval); sprite.alpha = 1; self.isInvincible = false; }, 5000); } }; self.activateMagnet = function () { if (!self.magnetActive) { self.magnetActive = true; // Deactivate after 7 seconds LK.setTimeout(function () { self.magnetActive = false; }, 7000); } }; return self; }); var PowerUp = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'invincibility'; // invincibility, magnet, speed var sprite = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); // Customize appearance based on type if (self.type === 'invincibility') { sprite.tint = 0xAB47BC; // Purple for invincibility } else if (self.type === 'magnet') { sprite.tint = 0xFF5722; // Orange for magnet } else if (self.type === 'speed') { sprite.tint = 0x00BCD4; // Cyan for speed boost } self.lane = Math.floor(Math.random() * 3); // 0, 1, 2 self.speed = 0; self.collected = false; self.update = function () { self.y += self.speed; // Pulsing effect for visibility if (Math.floor(LK.ticks / 10) % 2 === 0) { if (sprite.scaleX < 1.1) { sprite.scaleX += 0.01; sprite.scaleY += 0.01; } } else { if (sprite.scaleX > 0.9) { sprite.scaleX -= 0.01; sprite.scaleY -= 0.01; } } }; self.collect = function () { if (!self.collected) { self.collected = true; LK.getSound('powerup_collect').play(); // Visual effect for collection tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 300 }); return true; } return false; }; return self; }); var ThereAMan = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Make ThereAMan visually distinct sprite.tint = 0xFFEB3B; // Yellow tint self.lane = Math.floor(Math.random() * 3); // Random lane self.speed = 0; self.isActive = true; self.update = function () { self.y += self.speed; // Bobbing animation if (LK.ticks % 60 < 30) { self.y += 0.5; } else { self.y -= 0.5; } }; self.interact = function () { if (self.isActive) { self.isActive = false; // Visual effect on interaction tween(self, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500 }); return true; } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x212121 }); /**** * Game Code ****/ // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var LANE_WIDTH = 400; var LANE_SPACING = 100; var GAME_SPEED = 10; var SPAWN_INTERVAL = 60; // frames (1 second at 60fps) var LANE_X_POSITIONS = []; // Game variables var player; var obstacles = []; var coins = []; var powerups = []; var thereAMen = []; var lanes = []; var score = 0; var distance = 0; var coinCount = 0; var gameSpeed = GAME_SPEED; var isGameRunning = false; var swipeStartY = 0; var swipeStartX = 0; // UI elements var scoreTxt; var coinTxt; var distanceTxt; var speedMultiplier = 1; // Helper functions function getLaneXPosition(laneIndex) { return LANE_X_POSITIONS[laneIndex]; } function setupLanes() { // Calculate lane positions var startX = (GAME_WIDTH - (LANE_WIDTH * 3 + LANE_SPACING * 2)) / 2; for (var i = 0; i < 3; i++) { LANE_X_POSITIONS[i] = startX + i * (LANE_WIDTH + LANE_SPACING) + LANE_WIDTH / 2; var lane = LK.getAsset('lane', { anchorX: 0.5, anchorY: 0, alpha: 0.3, width: LANE_WIDTH }); lane.x = LANE_X_POSITIONS[i]; lane.y = 0; game.addChild(lane); lanes.push(lane); } } function setupPlayer() { player = new Player(); player.x = getLaneXPosition(player.lane); player.y = GAME_HEIGHT - 300; game.addChild(player); } function setupUI() { // Score display scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); scoreTxt.x = 120; scoreTxt.y = 50; LK.gui.addChild(scoreTxt); // Coin display coinTxt = new Text2('Coins: 0', { size: 80, fill: 0xFFC107 }); coinTxt.anchor.set(1, 0); coinTxt.x = GAME_WIDTH - 120; coinTxt.y = 50; LK.gui.addChild(coinTxt); // Distance display distanceTxt = new Text2('0m', { size: 80, fill: 0xFFFFFF }); distanceTxt.anchor.set(0.5, 0); distanceTxt.x = GAME_WIDTH / 2; distanceTxt.y = 50; LK.gui.addChild(distanceTxt); } function spawnObstacle() { if (Math.random() < 0.3) { var types = ['barrier', 'train', 'hole']; var type = types[Math.floor(Math.random() * types.length)]; var obstacle = new Obstacle(type); obstacle.x = getLaneXPosition(obstacle.lane); obstacle.y = -150; obstacle.speed = gameSpeed; game.addChild(obstacle); obstacles.push(obstacle); } } function spawnCoin() { if (Math.random() < 0.4) { var coin = new Coin(); coin.x = getLaneXPosition(coin.lane); coin.y = -80; coin.speed = gameSpeed; game.addChild(coin); coins.push(coin); } } function spawnPowerUp() { if (Math.random() < 0.05) { var types = ['invincibility', 'magnet', 'speed']; var type = types[Math.floor(Math.random() * types.length)]; var powerup = new PowerUp(type); powerup.x = getLaneXPosition(powerup.lane); powerup.y = -80; powerup.speed = gameSpeed; game.addChild(powerup); powerups.push(powerup); } } function spawnThereAMan() { if (Math.random() < 0.02) { // Rare spawn chance var thereAMan = new ThereAMan(); thereAMan.x = getLaneXPosition(thereAMan.lane); thereAMan.y = -150; thereAMan.speed = gameSpeed * 0.8; // Moves slower than regular game speed game.addChild(thereAMan); thereAMen.push(thereAMan); } } function checkCollisions() { // Check obstacle collisions for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; // Remove if off-screen if (obstacle.y > GAME_HEIGHT + 100) { obstacle.destroy(); obstacles.splice(i, 1); continue; } // Check collision with player if (obstacle.lane === player.lane && obstacle.intersects(player)) { var collision = false; if (obstacle.needsJump() && !player.isJumping) { collision = true; } else if (obstacle.needsSlide() && !player.isSliding) { collision = true; } else if (obstacle.type === 'train') { collision = true; } if (collision && !player.isInvincible) { gameOver(); break; } } } // Check coin collisions for (var j = coins.length - 1; j >= 0; j--) { var coin = coins[j]; // Remove if off-screen if (coin.y > GAME_HEIGHT + 100) { coin.destroy(); coins.splice(j, 1); continue; } // Check if in magnetic range if (player.magnetActive) { var dx = player.x - coin.x; var dy = player.y - coin.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 500) { // Move coin toward player for magnetic effect var angle = Math.atan2(dy, dx); coin.x += Math.cos(angle) * 15; coin.y += Math.sin(angle) * 15; } } // Check collision with player if ((coin.lane === player.lane || player.magnetActive) && coin.intersects(player)) { if (coin.collect()) { coinCount++; storage.totalCoins = (storage.totalCoins || 0) + 1; coinTxt.setText('Coins: ' + coinCount); coins.splice(j, 1); } } } // Check powerup collisions for (var k = powerups.length - 1; k >= 0; k--) { var powerup = powerups[k]; // Remove if off-screen if (powerup.y > GAME_HEIGHT + 100) { powerup.destroy(); powerups.splice(k, 1); continue; } // Check collision with player if (powerup.lane === player.lane && powerup.intersects(player)) { if (powerup.collect()) { activatePowerUp(powerup.type); powerups.splice(k, 1); } } } // Check ThereAMan collisions for (var m = thereAMen.length - 1; m >= 0; m--) { var thereAMan = thereAMen[m]; // Remove if off-screen if (thereAMan.y > GAME_HEIGHT + 100) { thereAMan.destroy(); thereAMen.splice(m, 1); continue; } // Check collision with player if (thereAMan.lane === player.lane && thereAMan.intersects(player)) { if (thereAMan.interact()) { // Add extra points for collecting ThereAMan score += 100; // Temporary speed boost var originalSpeed = gameSpeed; speedMultiplier = 1.2; gameSpeed = originalSpeed * speedMultiplier; // Show visual cue LK.effects.flashScreen(0xFFEB3B, 300); // Reset speed after a while LK.setTimeout(function () { speedMultiplier = 1; gameSpeed = originalSpeed; }, 3000); thereAMen.splice(m, 1); } } } } function activatePowerUp(type) { switch (type) { case 'invincibility': player.activateInvincibility(); break; case 'magnet': player.activateMagnet(); break; case 'speed': // Temporary speed boost var originalSpeed = gameSpeed; speedMultiplier = 1.5; gameSpeed = originalSpeed * speedMultiplier; LK.setTimeout(function () { speedMultiplier = 1; gameSpeed = originalSpeed; }, 5000); break; } } function gameOver() { LK.getSound('crash').play(); LK.stopMusic(); // Check if high score was beaten if (score > storage.highScore) { storage.highScore = score; } // Flash screen effect LK.effects.flashScreen(0xFF0000, 500); // Show game over screen after a brief delay LK.setTimeout(function () { LK.showGameOver(); }, 600); isGameRunning = false; } function updateScore() { // Update distance based on game speed distance += gameSpeed * 0.1; // Score is based on distance plus coins score = Math.floor(distance) + coinCount * 10; // Update UI scoreTxt.setText('Score: ' + score); distanceTxt.setText(Math.floor(distance) + 'm'); } function handleSwipe(startX, startY, endX, endY) { var deltaX = endX - startX; var deltaY = endY - startY; // Determine if it's a horizontal or vertical swipe if (Math.abs(deltaX) > Math.abs(deltaY)) { // Horizontal swipe if (deltaX > 100) { // Right swipe player.changeLane(1); } else if (deltaX < -100) { // Left swipe player.changeLane(-1); } } else { // Vertical swipe if (deltaY > 100) { // Down swipe player.slide(); } else if (deltaY < -100) { // Up swipe player.jump(); } } } // Game initialization setupLanes(); setupPlayer(); setupUI(); // Start game with music LK.playMusic('game_music'); isGameRunning = true; // Input handlers game.down = function (x, y, obj) { swipeStartX = x; swipeStartY = y; }; game.up = function (x, y, obj) { handleSwipe(swipeStartX, swipeStartY, x, y); }; game.update = function () { if (!isGameRunning) return; // Spawn game elements if (LK.ticks % SPAWN_INTERVAL === 0) { spawnObstacle(); spawnCoin(); spawnPowerUp(); spawnThereAMan(); // Gradually increase game speed if (LK.ticks % (SPAWN_INTERVAL * 5) === 0) { gameSpeed += 0.2; } } // Update all game elements for (var i = 0; i < obstacles.length; i++) { obstacles[i].speed = gameSpeed; } for (var j = 0; j < coins.length; j++) { coins[j].speed = gameSpeed; } for (var k = 0; k < powerups.length; k++) { powerups[k].speed = gameSpeed; } for (var m = 0; m < thereAMen.length; m++) { thereAMen[m].speed = gameSpeed * 0.8; // ThereAMan moves slower } // Check for collisions checkCollisions(); // Update score and distance updateScore(); };
===================================================================
--- original.js
+++ change.js
@@ -228,8 +228,45 @@
return false;
};
return self;
});
+var ThereAMan = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Make ThereAMan visually distinct
+ sprite.tint = 0xFFEB3B; // Yellow tint
+ self.lane = Math.floor(Math.random() * 3); // Random lane
+ self.speed = 0;
+ self.isActive = true;
+ self.update = function () {
+ self.y += self.speed;
+ // Bobbing animation
+ if (LK.ticks % 60 < 30) {
+ self.y += 0.5;
+ } else {
+ self.y -= 0.5;
+ }
+ };
+ self.interact = function () {
+ if (self.isActive) {
+ self.isActive = false;
+ // Visual effect on interaction
+ tween(self, {
+ alpha: 0,
+ scaleX: 2,
+ scaleY: 2
+ }, {
+ duration: 500
+ });
+ return true;
+ }
+ return false;
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -252,8 +289,9 @@
var player;
var obstacles = [];
var coins = [];
var powerups = [];
+var thereAMen = [];
var lanes = [];
var score = 0;
var distance = 0;
var coinCount = 0;
@@ -355,8 +393,19 @@
game.addChild(powerup);
powerups.push(powerup);
}
}
+function spawnThereAMan() {
+ if (Math.random() < 0.02) {
+ // Rare spawn chance
+ var thereAMan = new ThereAMan();
+ thereAMan.x = getLaneXPosition(thereAMan.lane);
+ thereAMan.y = -150;
+ thereAMan.speed = gameSpeed * 0.8; // Moves slower than regular game speed
+ game.addChild(thereAMan);
+ thereAMen.push(thereAMan);
+ }
+}
function checkCollisions() {
// Check obstacle collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
@@ -429,8 +478,37 @@
powerups.splice(k, 1);
}
}
}
+ // Check ThereAMan collisions
+ for (var m = thereAMen.length - 1; m >= 0; m--) {
+ var thereAMan = thereAMen[m];
+ // Remove if off-screen
+ if (thereAMan.y > GAME_HEIGHT + 100) {
+ thereAMan.destroy();
+ thereAMen.splice(m, 1);
+ continue;
+ }
+ // Check collision with player
+ if (thereAMan.lane === player.lane && thereAMan.intersects(player)) {
+ if (thereAMan.interact()) {
+ // Add extra points for collecting ThereAMan
+ score += 100;
+ // Temporary speed boost
+ var originalSpeed = gameSpeed;
+ speedMultiplier = 1.2;
+ gameSpeed = originalSpeed * speedMultiplier;
+ // Show visual cue
+ LK.effects.flashScreen(0xFFEB3B, 300);
+ // Reset speed after a while
+ LK.setTimeout(function () {
+ speedMultiplier = 1;
+ gameSpeed = originalSpeed;
+ }, 3000);
+ thereAMen.splice(m, 1);
+ }
+ }
+ }
}
function activatePowerUp(type) {
switch (type) {
case 'invincibility':
@@ -520,8 +598,9 @@
if (LK.ticks % SPAWN_INTERVAL === 0) {
spawnObstacle();
spawnCoin();
spawnPowerUp();
+ spawnThereAMan();
// Gradually increase game speed
if (LK.ticks % (SPAWN_INTERVAL * 5) === 0) {
gameSpeed += 0.2;
}
@@ -535,8 +614,11 @@
}
for (var k = 0; k < powerups.length; k++) {
powerups[k].speed = gameSpeed;
}
+ for (var m = 0; m < thereAMen.length; m++) {
+ thereAMen[m].speed = gameSpeed * 0.8; // ThereAMan moves slower
+ }
// Check for collisions
checkCollisions();
// Update score and distance
updateScore();
Modern App Store icon, high definition, square with rounded corners, for a game titled "Metro Dash" and with the description "An exciting endless runner where you dash through subway tracks, dodging obstacles and collecting coins. Swipe to change lanes, jump over barriers, and slide under obstacles while your character automatically runs forward at increasing speeds. Grab power-ups to enhance your run and see how far you can go!". No text on icon!
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Metro Dash" and with the description "An exciting endless runner where you dash through subway tracks, dodging obstacles and collecting coins. Swipe to change lanes, jump over barriers, and slide under obstacles while your character automatically runs forward at increasing speeds. Grab power-ups to enhance your run and see how far you can go!". No text on banner!
A train is coming down a narrow railway track that cuts through a rural road, surrounded by trees and open fields. It's early morning with light mist, headlights of the train glowing, and a sense of motion as the train approaches.. 2d. High contrast
A powerful and dynamic rocket launch sound effect for a 2D arcade game. It should include ignition, rising whoosh, and a subtle explosion fade as it flies off-screen.". In-Game asset. 2d. High contrast. No shadows