/**** * 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(); };
/****
* 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();
};
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