/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy Car
var EnemyCar = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('enemyCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = car.width;
self.height = car.height;
self.speed = 0;
self.lane = 0;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Lane Mark
var LaneMark = Container.expand(function () {
var self = Container.call(this);
var mark = self.attachAsset('laneMark', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = mark.width;
self.height = mark.height;
self.speed = 0;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Obstacle (barrier)
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obs = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = obs.width;
self.height = obs.height;
self.speed = 0;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Car
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = car.width;
self.height = car.height;
// For near-miss detection
self.lastNearMissTick = 0;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222831
});
/****
* Game Code
****/
// --- Road Lane Marks ---
LK.playMusic('sound');
// Obstacle (barrier)
// Enemy car
// Car (player)
// --- Game Constants ---
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var ROAD_WIDTH = 1200;
var ROAD_LEFT = (GAME_WIDTH - ROAD_WIDTH) / 2;
var ROAD_RIGHT = ROAD_LEFT + ROAD_WIDTH;
var LANE_COUNT = 4;
var LANE_WIDTH = ROAD_WIDTH / LANE_COUNT;
var PLAYER_START_LANE = 1;
var PLAYER_Y = GAME_HEIGHT - 500;
var ENEMY_MIN_SPEED = 18;
var ENEMY_MAX_SPEED = 32;
var OBSTACLE_SPEED = 24;
var LANE_MARK_SPEED = 28;
var LANE_MARK_SPACING = 320;
var NEAR_MISS_DIST = 120;
var NEAR_MISS_SCORE = 5;
// --- Game State ---
var playerCar;
var enemyCars = [];
var obstacles = [];
var laneMarks = [];
var dragNode = null;
var dragOffsetX = 0;
var score = 0;
var scoreTxt;
var distance = 0;
var distanceTxt;
var lastEnemySpawnTick = 0;
var lastObstacleSpawnTick = 0;
var lastNearMissTick = 0;
var speedMultiplier = 1;
var gameOver = false;
// --- GUI ---
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
distanceTxt = new Text2('0 m', {
size: 80,
fill: "#fff"
});
distanceTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(distanceTxt);
distanceTxt.y = 130;
// --- Road Lane Marks ---
function spawnLaneMarks() {
for (var lane = 0; lane < LANE_COUNT + 1; lane++) {
var x = ROAD_LEFT + lane * LANE_WIDTH;
for (var y = -LANE_MARK_SPACING; y < GAME_HEIGHT + LANE_MARK_SPACING; y += LANE_MARK_SPACING * 2) {
var mark = new LaneMark();
mark.x = x;
mark.y = y;
mark.speed = LANE_MARK_SPEED;
laneMarks.push(mark);
game.addChild(mark);
}
}
}
spawnLaneMarks();
// --- Player Car ---
playerCar = new PlayerCar();
playerCar.x = ROAD_LEFT + (PLAYER_START_LANE + 0.5) * LANE_WIDTH;
playerCar.y = PLAYER_Y;
game.addChild(playerCar);
// --- Helper: Get nearest lane center for a given x ---
function getNearestLaneCenter(x) {
var lane = Math.floor((x - ROAD_LEFT) / LANE_WIDTH);
if (lane < 0) lane = 0;
if (lane >= LANE_COUNT) lane = LANE_COUNT - 1;
return ROAD_LEFT + (lane + 0.5) * LANE_WIDTH;
}
// --- Helper: Clamp player within road ---
function clampPlayerX(x) {
var half = playerCar.width / 2;
var minX = ROAD_LEFT + half;
var maxX = ROAD_RIGHT - half;
if (x < minX) x = minX;
if (x > maxX) x = maxX;
return x;
}
// --- Touch/Drag Controls ---
game.down = function (x, y, obj) {
// Only start drag if touch is on player car
var local = playerCar.toLocal(game.toGlobal({
x: x,
y: y
}));
if (local.x > -playerCar.width / 2 && local.x < playerCar.width / 2 && local.y > -playerCar.height / 2 && local.y < playerCar.height / 2) {
dragNode = playerCar;
dragOffsetX = playerCar.x - x;
}
};
game.move = function (x, y, obj) {
if (dragNode) {
var newX = clampPlayerX(x + dragOffsetX);
playerCar.x = newX;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// --- Enemy Car Spawning ---
function spawnEnemyCar() {
// Pick a random lane
var lane = Math.floor(Math.random() * LANE_COUNT);
var x = ROAD_LEFT + (lane + 0.5) * LANE_WIDTH;
var y = -200;
var car = new EnemyCar();
car.x = x;
car.y = y;
car.lane = lane;
car.speed = ENEMY_MIN_SPEED + Math.random() * (ENEMY_MAX_SPEED - ENEMY_MIN_SPEED) * speedMultiplier;
enemyCars.push(car);
game.addChild(car);
}
// --- Obstacle Spawning ---
function spawnObstacle() {
// Pick a random lane
var lane = Math.floor(Math.random() * LANE_COUNT);
var x = ROAD_LEFT + (lane + 0.5) * LANE_WIDTH;
var y = -100;
var obs = new Obstacle();
obs.x = x;
obs.y = y;
obs.speed = OBSTACLE_SPEED * speedMultiplier;
obstacles.push(obs);
game.addChild(obs);
}
// --- Main Game Loop ---
game.update = function () {
if (gameOver) return;
// --- Lane Marks ---
for (var i = laneMarks.length - 1; i >= 0; i--) {
var mark = laneMarks[i];
mark.y += mark.speed * speedMultiplier;
if (mark.y > GAME_HEIGHT + LANE_MARK_SPACING) {
mark.y -= GAME_HEIGHT + LANE_MARK_SPACING * 2;
}
}
// --- Enemy Cars ---
for (var i = enemyCars.length - 1; i >= 0; i--) {
var car = enemyCars[i];
car.y += car.speed * speedMultiplier;
// Remove if off screen
if (car.y > GAME_HEIGHT + 400) {
car.destroy();
enemyCars.splice(i, 1);
continue;
}
// Collision with player
if (car.intersects(playerCar)) {
LK.getSound('21334535').play();
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
}
// Near-miss detection (side-by-side, close y, but not colliding)
var dx = Math.abs(car.x - playerCar.x);
var dy = Math.abs(car.y - playerCar.y);
if (dx > playerCar.width * 0.7 && dy < NEAR_MISS_DIST && LK.ticks - playerCar.lastNearMissTick > 30) {
score += NEAR_MISS_SCORE;
playerCar.lastNearMissTick = LK.ticks;
LK.effects.flashObject(playerCar, 0x00ff00, 200);
}
}
// --- Obstacles ---
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.y += obs.speed * speedMultiplier;
if (obs.y > GAME_HEIGHT + 200) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
if (obs.intersects(playerCar)) {
LK.getSound('21334535').play();
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
}
}
// --- Spawning Enemies ---
if (LK.ticks - lastEnemySpawnTick > Math.max(32 - speedMultiplier * 8, 12)) {
spawnEnemyCar();
lastEnemySpawnTick = LK.ticks;
}
// --- Spawning Obstacles ---
if (LK.ticks - lastObstacleSpawnTick > 120 + Math.floor(Math.random() * 80)) {
if (Math.random() < 0.35) {
spawnObstacle();
}
lastObstacleSpawnTick = LK.ticks;
}
// --- Score & Distance ---
distance += 1.5 * speedMultiplier;
score += Math.floor(0.08 * speedMultiplier);
scoreTxt.setText(score);
distanceTxt.setText(Math.floor(distance) + " m");
// --- Difficulty Scaling ---
if (LK.ticks % 180 == 0 && speedMultiplier < 2.5) {
speedMultiplier += 0.04;
}
};
// --- Reset on Game Over ---
game.on('destroy', function () {
// Clean up arrays
for (var i = 0; i < enemyCars.length; i++) enemyCars[i].destroy();
for (var i = 0; i < obstacles.length; i++) obstacles[i].destroy();
for (var i = 0; i < laneMarks.length; i++) laneMarks[i].destroy();
enemyCars = [];
obstacles = [];
laneMarks = [];
score = 0;
distance = 0;
speedMultiplier = 1;
gameOver = false;
// Recreate lane marks and player
spawnLaneMarks();
playerCar.x = ROAD_LEFT + (PLAYER_START_LANE + 0.5) * LANE_WIDTH;
playerCar.y = PLAYER_Y;
scoreTxt.setText('0');
distanceTxt.setText('0 m');
}); ===================================================================
--- original.js
+++ change.js
@@ -234,8 +234,9 @@
continue;
}
// Collision with player
if (car.intersects(playerCar)) {
+ LK.getSound('21334535').play();
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;
@@ -258,8 +259,9 @@
obstacles.splice(i, 1);
continue;
}
if (obs.intersects(playerCar)) {
+ LK.getSound('21334535').play();
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.showGameOver();
return;