/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = gameSpeed;
self.collected = false;
self.update = function () {
self.y += self.speed;
// Spinning animation
graphics.rotation += 0.1;
};
return self;
});
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
self.obstacleType = type || 'train';
var graphics = self.attachAsset(self.obstacleType, {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
self.currentLane = 1; // 0=left, 1=center, 2=right
self.targetX = 0;
self.isJumping = false;
self.isSliding = false;
self.invincible = false;
self.getLaneX = function (lane) {
var laneWidth = 2048 / 3;
return laneWidth * lane + laneWidth / 2;
};
self.switchLane = function (newLane) {
if (newLane >= 0 && newLane <= 2) {
self.currentLane = newLane;
self.targetX = self.getLaneX(newLane);
}
};
self.jump = function () {
if (!self.isJumping && !self.isSliding) {
self.isJumping = true;
var originalY = self.y;
tween(self, {
y: originalY - 150
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
y: originalY
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
self.isJumping = false;
}
});
}
});
}
};
self.slide = function () {
if (!self.isJumping && !self.isSliding) {
self.isSliding = true;
graphics.height = 60;
LK.setTimeout(function () {
graphics.height = 120;
self.isSliding = false;
}, 800);
}
};
self.update = function () {
// Smooth lane switching
var diff = self.targetX - self.x;
if (Math.abs(diff) > 5) {
self.x += diff * 0.15;
}
// Flash effect when invincible
if (self.invincible) {
graphics.alpha = LK.ticks % 10 < 5 ? 0.5 : 1.0;
} else {
graphics.alpha = 1.0;
}
};
return self;
});
var Police = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('police', {
anchorX: 0.5,
anchorY: 1.0
});
self.currentLane = 1; // Start in center lane like player
self.targetX = 0;
self.speed = gameSpeed * 0.8; // Slightly slower than game speed
self.getLaneX = function (lane) {
var laneWidth = 2048 / 3;
return laneWidth * lane + laneWidth / 2;
};
self.chasePlayer = function (playerLane) {
// Police follows player's lane with some delay
if (LK.ticks % 60 === 0) {
// Update target lane every second
self.currentLane = playerLane;
self.targetX = self.getLaneX(playerLane);
}
};
self.update = function () {
// Move forward at chase speed
self.y += self.speed;
// Smooth lane switching like player
var diff = self.targetX - self.x;
if (Math.abs(diff) > 5) {
self.x += diff * 0.12; // Slightly slower lane switching than player
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
self.powerType = type || 'invincible';
var graphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
// Color code power-ups
if (self.powerType === 'invincible') {
graphics.tint = 0x00FF00;
} else if (self.powerType === 'magnet') {
graphics.tint = 0x0000FF;
}
self.speed = gameSpeed;
self.collected = false;
self.update = function () {
self.y += self.speed;
graphics.rotation += 0.05;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x212121
});
/****
* Game Code
****/
// Game variables
var gameSpeed = 8;
var baseSpeed = 8;
var player;
var police;
var obstacles = [];
var coins = [];
var powerups = [];
var distance = 0;
var coinCount = 0;
var lastObstacleY = -500;
var lastCoinY = -300;
var swipeStartX = 0;
var swipeStartY = 0;
var isSwipeStarted = false;
// Power-up states
var invincibleTimer = 0;
var magnetTimer = 0;
// Create background tracks
for (var i = 0; i < 4; i++) {
var track = game.addChild(LK.getAsset('track', {
anchorX: 0,
anchorY: 0,
x: 0,
y: i * 100 - 200
}));
}
// Create player
player = game.addChild(new Player());
player.x = player.getLaneX(1);
player.y = 2500;
player.targetX = player.x;
// Create police officer chasing behind
police = game.addChild(new Police());
police.x = police.getLaneX(1);
police.y = 2700; // Start behind player
police.targetX = police.x;
// UI Elements
var distanceText = new Text2('Distance: 0m', {
size: 60,
fill: 0xFFFFFF
});
distanceText.anchor.set(0, 0);
LK.gui.topRight.addChild(distanceText);
var coinText = new Text2('Coins: 0', {
size: 60,
fill: 0xFFD700
});
coinText.anchor.set(1, 0);
coinText.x = -20;
coinText.y = 80;
LK.gui.topRight.addChild(coinText);
// Touch controls
game.down = function (x, y, obj) {
swipeStartX = x;
swipeStartY = y;
isSwipeStarted = true;
};
game.up = function (x, y, obj) {
if (!isSwipeStarted) return;
var deltaX = x - swipeStartX;
var deltaY = y - swipeStartY;
var swipeThreshold = 100;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swipe
if (Math.abs(deltaX) > swipeThreshold) {
if (deltaX > 0) {
// Swipe right
player.switchLane(player.currentLane + 1);
} else {
// Swipe left
player.switchLane(player.currentLane - 1);
}
}
} else {
// Vertical swipe
if (Math.abs(deltaY) > swipeThreshold) {
if (deltaY < 0) {
// Swipe up - jump
player.jump();
} else {
// Swipe down - slide
player.slide();
}
}
}
// Tap to jump if no swipe detected
if (Math.abs(deltaX) < 50 && Math.abs(deltaY) < 50) {
player.jump();
}
isSwipeStarted = false;
};
function spawnObstacle() {
if (lastObstacleY > -800) return;
var lane = Math.floor(Math.random() * 3);
var type = Math.random() < 0.7 ? 'train' : 'barrier';
var obstacle = new Obstacle(type);
obstacle.x = player.getLaneX(lane);
obstacle.y = -200;
obstacles.push(obstacle);
game.addChild(obstacle);
lastObstacleY = obstacle.y;
}
function spawnCoin() {
if (lastCoinY > -400) return;
var lane = Math.floor(Math.random() * 3);
var coin = new Coin();
coin.x = player.getLaneX(lane);
coin.y = -150;
coins.push(coin);
game.addChild(coin);
lastCoinY = coin.y;
}
function spawnPowerUp() {
if (Math.random() < 0.02) {
// 2% chance per frame
var lane = Math.floor(Math.random() * 3);
var types = ['invincible', 'magnet'];
var type = types[Math.floor(Math.random() * types.length)];
var powerup = new PowerUp(type);
powerup.x = player.getLaneX(lane);
powerup.y = -100;
powerups.push(powerup);
game.addChild(powerup);
}
}
function checkCollisions() {
// Check obstacle collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.y > 2800) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with player
if (Math.abs(obstacle.x - player.x) < 100 && Math.abs(obstacle.y - player.y) < 100) {
// Check if player can avoid collision
var canAvoid = false;
if (obstacle.obstacleType === 'barrier' && player.isJumping) {
canAvoid = true;
} else if (obstacle.obstacleType === 'train' && player.isSliding) {
canAvoid = true;
}
if (!canAvoid && !player.invincible) {
LK.getSound('crash').play();
// When player crashes, police catches them
// Move police closer to simulate catching
police.y = player.y + 30;
LK.setTimeout(function () {
LK.showGameOver();
}, 500); // Small delay to show police catching player
return;
}
}
}
// Check coin collection
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (coin.y > 2800) {
coin.destroy();
coins.splice(i, 1);
continue;
}
var collectRadius = magnetTimer > 0 ? 200 : 60;
if (Math.abs(coin.x - player.x) < collectRadius && Math.abs(coin.y - player.y) < collectRadius && !coin.collected) {
coin.collected = true;
coinCount++;
LK.setScore(LK.getScore() + 10);
LK.getSound('collect').play();
coin.destroy();
coins.splice(i, 1);
}
}
// Check power-up collection
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.y > 2800) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
if (Math.abs(powerup.x - player.x) < 80 && Math.abs(powerup.y - player.y) < 80 && !powerup.collected) {
powerup.collected = true;
if (powerup.powerType === 'invincible') {
invincibleTimer = 300; // 5 seconds at 60fps
player.invincible = true;
} else if (powerup.powerType === 'magnet') {
magnetTimer = 600; // 10 seconds at 60fps
}
powerup.destroy();
powerups.splice(i, 1);
}
}
}
game.update = function () {
// Update distance and speed
distance += gameSpeed;
gameSpeed = baseSpeed + Math.floor(distance / 1000) * 0.5;
// Update power-up timers
if (invincibleTimer > 0) {
invincibleTimer--;
if (invincibleTimer <= 0) {
player.invincible = false;
}
}
if (magnetTimer > 0) {
magnetTimer--;
}
// Update obstacle spawn positions
lastObstacleY += gameSpeed;
lastCoinY += gameSpeed;
// Spawn new objects
spawnObstacle();
spawnCoin();
spawnPowerUp();
// Update police officer
police.speed = gameSpeed * 0.8; // Police moves slightly slower
police.chasePlayer(player.currentLane);
// Check if police catches player (when player hits obstacle)
if (Math.abs(police.y - player.y) < 50) {
// Police is close enough to catch player when they crash
LK.showGameOver();
return;
}
// Update all objects
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].speed = gameSpeed;
}
for (var i = 0; i < coins.length; i++) {
coins[i].speed = gameSpeed;
}
for (var i = 0; i < powerups.length; i++) {
powerups[i].speed = gameSpeed;
}
// Move background tracks
var tracks = game.children.slice(0, 4);
for (var i = 0; i < tracks.length; i++) {
tracks[i].y += gameSpeed;
if (tracks[i].y > 2732) {
tracks[i].y -= 400;
}
}
// Check collisions
checkCollisions();
// Update UI
distanceText.setText('Distance: ' + Math.floor(distance / 10) + 'm');
coinText.setText('Coins: ' + coinCount);
}; ===================================================================
--- original.js
+++ change.js
@@ -102,8 +102,40 @@
}
};
return self;
});
+var Police = Container.expand(function () {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('police', {
+ anchorX: 0.5,
+ anchorY: 1.0
+ });
+ self.currentLane = 1; // Start in center lane like player
+ self.targetX = 0;
+ self.speed = gameSpeed * 0.8; // Slightly slower than game speed
+ self.getLaneX = function (lane) {
+ var laneWidth = 2048 / 3;
+ return laneWidth * lane + laneWidth / 2;
+ };
+ self.chasePlayer = function (playerLane) {
+ // Police follows player's lane with some delay
+ if (LK.ticks % 60 === 0) {
+ // Update target lane every second
+ self.currentLane = playerLane;
+ self.targetX = self.getLaneX(playerLane);
+ }
+ };
+ self.update = function () {
+ // Move forward at chase speed
+ self.y += self.speed;
+ // Smooth lane switching like player
+ var diff = self.targetX - self.x;
+ if (Math.abs(diff) > 5) {
+ self.x += diff * 0.12; // Slightly slower lane switching than player
+ }
+ };
+ return self;
+});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
self.powerType = type || 'invincible';
var graphics = self.attachAsset('powerup', {
@@ -138,8 +170,9 @@
// Game variables
var gameSpeed = 8;
var baseSpeed = 8;
var player;
+var police;
var obstacles = [];
var coins = [];
var powerups = [];
var distance = 0;
@@ -165,8 +198,13 @@
player = game.addChild(new Player());
player.x = player.getLaneX(1);
player.y = 2500;
player.targetX = player.x;
+// Create police officer chasing behind
+police = game.addChild(new Police());
+police.x = police.getLaneX(1);
+police.y = 2700; // Start behind player
+police.targetX = police.x;
// UI Elements
var distanceText = new Text2('Distance: 0m', {
size: 60,
fill: 0xFFFFFF
@@ -274,9 +312,14 @@
canAvoid = true;
}
if (!canAvoid && !player.invincible) {
LK.getSound('crash').play();
- LK.showGameOver();
+ // When player crashes, police catches them
+ // Move police closer to simulate catching
+ police.y = player.y + 30;
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 500); // Small delay to show police catching player
return;
}
}
}
@@ -339,8 +382,17 @@
// Spawn new objects
spawnObstacle();
spawnCoin();
spawnPowerUp();
+ // Update police officer
+ police.speed = gameSpeed * 0.8; // Police moves slightly slower
+ police.chasePlayer(player.currentLane);
+ // Check if police catches player (when player hits obstacle)
+ if (Math.abs(police.y - player.y) < 50) {
+ // Police is close enough to catch player when they crash
+ LK.showGameOver();
+ return;
+ }
// Update all objects
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].speed = gameSpeed;
}