/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// City Building Left Class
var CityBuildingLeft = Container.expand(function () {
var self = Container.call(this);
var shape = self.attachAsset('cityBuildingLeft', {
anchorX: 0.5,
anchorY: 1.0,
width: 600,
height: 900,
orientation: 1 // rotate 90 degrees clockwise
});
// Use a neutral grayish tint for less color, with very little variation
shape.tint = 0x888899 + Math.floor(Math.random() * 0x000011);
self.width = shape.width;
self.height = shape.height;
self.speed = 0;
return self;
});
// City Building Right Class
var CityBuildingRight = Container.expand(function () {
var self = Container.call(this);
var shape = self.attachAsset('cityBuildingRight', {
anchorX: 0.5,
anchorY: 1.0,
width: 600,
height: 900,
orientation: 1 // rotate 90 degrees clockwise
});
// Use a neutral grayish tint for less color, with very little variation
shape.tint = 0x888899 + Math.floor(Math.random() * 0x000011);
self.width = shape.width;
self.height = shape.height;
self.speed = 0;
return self;
});
// Enemy Car Class
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; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed;
};
return self;
});
// Blue Enemy Car Class
var EnemyCarBlue = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('enemyCarBlue', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = car.width;
self.height = car.height;
self.speed = 0; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed * 1.1; // Slightly faster than normal enemy
};
return self;
});
// Truck Enemy Car Class
var EnemyCarTruck = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('enemyCarTruck', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = car.width;
self.height = car.height;
self.speed = 0; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed * 0.8; // Slightly slower, but bigger
};
return self;
});
// Lane Divider Class
var LaneDivider = Container.expand(function () {
var self = Container.call(this);
var divider = self.attachAsset('laneDivider', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = divider.width;
self.height = divider.height;
self.speed = 0; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed;
};
return self;
});
// Obstacle Class
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; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Car Class
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
// For collision box, use self
self.width = car.width;
self.height = car.height;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Road settings
// Game area: 2048x2732
// Car (player)
// Enemy car
// Obstacle (barrier)
// Road lane divider
// Example asset id, replace with actual
var roadWidth = 1200;
var roadLeft = (2048 - roadWidth) / 2;
var roadRight = roadLeft + roadWidth;
var laneCount = 4;
var laneWidth = roadWidth / laneCount;
var laneCenters = [];
for (var i = 0; i < laneCount; i++) {
laneCenters.push(roadLeft + laneWidth * (i + 0.5));
}
// --- Cityscape background (left and right) ---
var cityBuildingsLeft = [];
var cityBuildingsRight = [];
function spawnCityBuildings() {
// Remove old
for (var i = 0; i < cityBuildingsLeft.length; i++) cityBuildingsLeft[i].destroy();
for (var i = 0; i < cityBuildingsRight.length; i++) cityBuildingsRight[i].destroy();
cityBuildingsLeft = [];
cityBuildingsRight = [];
// Building parameters
var buildingWidth = 600;
var buildingHeight = 900;
var gap = 0;
var yStart = -buildingHeight;
var yEnd = 2732 + buildingHeight;
// Left side
for (var y = yStart; y < yEnd; y += buildingHeight + gap) {
var b = new CityBuildingLeft();
b.x = roadLeft / 2;
b.y = y;
b.speed = 0;
cityBuildingsLeft.push(b);
game.addChild(b);
}
// Right side
for (var y = yStart + (buildingHeight + gap) / 4; y < yEnd; y += buildingHeight + gap) {
var b = new CityBuildingRight();
b.x = roadRight + (2048 - roadRight) / 2;
b.y = y;
b.speed = 0;
cityBuildingsRight.push(b);
game.addChild(b);
}
}
spawnCityBuildings();
// Player
var playerCar = new PlayerCar();
playerCar.x = laneCenters[1];
playerCar.y = 2732 - 400;
playerCar.lane = 1;
game.addChild(playerCar);
// Lane Dividers
var laneDividers = [];
function spawnLaneDividers() {
// Remove old
for (var i = 0; i < laneDividers.length; i++) {
laneDividers[i].destroy();
}
laneDividers = [];
// For each lane (except leftmost), spawn vertical dashed lines
for (var l = 1; l < laneCount; l++) {
// Offset the lane divider pattern so that no divider is at the same Y as the player car at spawn
// Player car spawns at y = 2732 - 400 = 2332
// Lane divider height is 120, so offset by half the gap to avoid overlap
var offsetY = 160; // 320/2, so the first divider is not at y=0
for (var y = -120 + offsetY; y < 2732 + 120; y += 320) {
var divider = new LaneDivider();
divider.x = roadLeft + laneWidth * l;
divider.y = y;
divider.speed = 0; // Set in update
laneDividers.push(divider);
game.addChild(divider);
}
}
}
spawnLaneDividers();
// Enemies and obstacles
var enemyCars = [];
var obstacles = [];
// Score
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Survival timer
var timeSurvived = 0;
var timeTxt = new Text2('0.0s', {
size: 80,
fill: "#fff"
});
timeTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timeTxt);
timeTxt.y = 130;
// Difficulty
var baseSpeed = 18; // px per frame
var speed = baseSpeed;
var speedIncrease = 0.003; // per tick
var spawnInterval = 60; // frames between spawns
var minSpawnInterval = 24;
var lastSpawnTick = 0;
// Dragging
var dragNode = null;
var dragOffsetX = 0;
// Touch controls: drag left/right to move car
game.down = function (x, y, obj) {
// Only allow 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.up = function (x, y, obj) {
dragNode = null;
};
game.move = function (x, y, obj) {
if (dragNode) {
// Only move horizontally, clamp to road
var newX = x + dragOffsetX;
if (newX < roadLeft + playerCar.width / 2) newX = roadLeft + playerCar.width / 2;
if (newX > roadRight - playerCar.width / 2) newX = roadRight - playerCar.width / 2;
playerCar.x = newX;
}
};
// Helper: get lane index from x
function getLaneIndex(x) {
var idx = Math.floor((x - roadLeft) / laneWidth);
if (idx < 0) idx = 0;
if (idx >= laneCount) idx = laneCount - 1;
return idx;
}
// Helper: check collision
function checkCollision(a, b) {
// Use .intersects
return a.intersects(b);
}
// Main update loop
game.update = function () {
// Increase speed over time
speed += speedIncrease;
if (speed > 40) speed = 40;
// Scroll city buildings
for (var i = cityBuildingsLeft.length - 1; i >= 0; i--) {
var b = cityBuildingsLeft[i];
b.y += speed * 0.7; // Move a bit slower than road for parallax
if (b.y > 2732 + 500) {
b.y -= 2732 + 1000;
}
}
for (var i = cityBuildingsRight.length - 1; i >= 0; i--) {
var b = cityBuildingsRight[i];
b.y += speed * 0.7;
if (b.y > 2732 + 500) {
b.y -= 2732 + 1000;
}
}
// Update lane dividers
for (var i = laneDividers.length - 1; i >= 0; i--) {
var divider = laneDividers[i];
divider.speed = speed;
divider.update();
if (divider.y > 2732 + 120) {
divider.y -= 2732 + 240;
}
}
// Update enemies
for (var i = enemyCars.length - 1; i >= 0; i--) {
var enemy = enemyCars[i];
enemy.speed = speed;
enemy.update();
// Remove if off screen
if (enemy.y > 2732 + 200) {
enemy.destroy();
enemyCars.splice(i, 1);
continue;
}
// Collision with player
if (checkCollision(playerCar, enemy)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Overtake: if enemy passes player and not yet counted
if (!enemy.overtaken && enemy.y > playerCar.y + playerCar.height / 2) {
enemy.overtaken = true;
score += 5;
scoreTxt.setText(score);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.speed = speed;
obs.update();
if (obs.y > 2732 + 100) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
if (checkCollision(playerCar, obs)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
// Spawn enemies/obstacles
if (LK.ticks - lastSpawnTick > spawnInterval) {
lastSpawnTick = LK.ticks;
// Randomly decide: enemy car or obstacle
var spawnType = Math.random() < 0.7 ? 'enemy' : 'obstacle';
// Pick random lane(s)
var availableLanes = [];
for (var l = 0; l < laneCount; l++) availableLanes.push(l);
// Avoid spawning in player's lane if possible
var playerLane = getLaneIndex(playerCar.x);
if (availableLanes.length > 1) {
var idx = availableLanes.indexOf(playerLane);
if (idx !== -1 && Math.random() < 0.7) {
availableLanes.splice(idx, 1);
}
}
// For obstacles, sometimes block 2 lanes
if (spawnType === 'obstacle' && Math.random() < 0.3 && laneCount >= 3) {
// Block two adjacent lanes
var lane = availableLanes[Math.floor(Math.random() * (availableLanes.length - 1))];
for (var d = 0; d < 2; d++) {
var obs = new Obstacle();
obs.x = laneCenters[lane + d];
obs.y = -100;
obs.speed = speed;
obs.lane = lane + d;
obstacles.push(obs);
game.addChild(obs);
}
} else {
// Single enemy or obstacle
var lane = availableLanes[Math.floor(Math.random() * availableLanes.length)];
if (spawnType === 'enemy') {
// Randomly pick enemy type
var enemyTypeRand = Math.random();
var enemy;
if (enemyTypeRand < 0.6) {
enemy = new EnemyCar();
enemy.x = laneCenters[lane];
enemy.y = -180;
enemy.speed = speed;
enemy.lane = lane;
enemy.overtaken = false;
} else if (enemyTypeRand < 0.85) {
enemy = new EnemyCarBlue();
enemy.x = laneCenters[lane];
enemy.y = -180;
enemy.speed = speed;
enemy.lane = lane;
enemy.overtaken = false;
} else {
enemy = new EnemyCarTruck();
enemy.x = laneCenters[lane];
enemy.y = -220; // Truck is taller, spawn a bit higher
enemy.speed = speed;
enemy.lane = lane;
enemy.overtaken = false;
}
enemyCars.push(enemy);
game.addChild(enemy);
} else {
var obs = new Obstacle();
obs.x = laneCenters[lane];
obs.y = -100;
obs.speed = speed;
obs.lane = lane;
obstacles.push(obs);
game.addChild(obs);
}
}
// Decrease spawn interval as speed increases
spawnInterval = Math.max(minSpawnInterval, 60 - Math.floor((speed - baseSpeed) * 1.5));
}
// Score: +1 per 30 frames survived
if (LK.ticks % 30 === 0) {
score += 1;
scoreTxt.setText(score);
}
// Survival time
timeSurvived = LK.ticks / 60;
timeTxt.setText(timeSurvived.toFixed(1) + "s");
};
// Center score and time text
scoreTxt.x = LK.gui.top.width / 2;
scoreTxt.y = 10;
timeTxt.x = LK.gui.top.width / 2;
timeTxt.y = 130; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// City Building Left Class
var CityBuildingLeft = Container.expand(function () {
var self = Container.call(this);
var shape = self.attachAsset('cityBuildingLeft', {
anchorX: 0.5,
anchorY: 1.0,
width: 600,
height: 900,
orientation: 1 // rotate 90 degrees clockwise
});
// Use a neutral grayish tint for less color, with very little variation
shape.tint = 0x888899 + Math.floor(Math.random() * 0x000011);
self.width = shape.width;
self.height = shape.height;
self.speed = 0;
return self;
});
// City Building Right Class
var CityBuildingRight = Container.expand(function () {
var self = Container.call(this);
var shape = self.attachAsset('cityBuildingRight', {
anchorX: 0.5,
anchorY: 1.0,
width: 600,
height: 900,
orientation: 1 // rotate 90 degrees clockwise
});
// Use a neutral grayish tint for less color, with very little variation
shape.tint = 0x888899 + Math.floor(Math.random() * 0x000011);
self.width = shape.width;
self.height = shape.height;
self.speed = 0;
return self;
});
// Enemy Car Class
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; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed;
};
return self;
});
// Blue Enemy Car Class
var EnemyCarBlue = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('enemyCarBlue', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = car.width;
self.height = car.height;
self.speed = 0; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed * 1.1; // Slightly faster than normal enemy
};
return self;
});
// Truck Enemy Car Class
var EnemyCarTruck = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('enemyCarTruck', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = car.width;
self.height = car.height;
self.speed = 0; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed * 0.8; // Slightly slower, but bigger
};
return self;
});
// Lane Divider Class
var LaneDivider = Container.expand(function () {
var self = Container.call(this);
var divider = self.attachAsset('laneDivider', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = divider.width;
self.height = divider.height;
self.speed = 0; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed;
};
return self;
});
// Obstacle Class
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; // Set on spawn
self.lane = 0; // Set on spawn
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Car Class
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
// For collision box, use self
self.width = car.width;
self.height = car.height;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Road settings
// Game area: 2048x2732
// Car (player)
// Enemy car
// Obstacle (barrier)
// Road lane divider
// Example asset id, replace with actual
var roadWidth = 1200;
var roadLeft = (2048 - roadWidth) / 2;
var roadRight = roadLeft + roadWidth;
var laneCount = 4;
var laneWidth = roadWidth / laneCount;
var laneCenters = [];
for (var i = 0; i < laneCount; i++) {
laneCenters.push(roadLeft + laneWidth * (i + 0.5));
}
// --- Cityscape background (left and right) ---
var cityBuildingsLeft = [];
var cityBuildingsRight = [];
function spawnCityBuildings() {
// Remove old
for (var i = 0; i < cityBuildingsLeft.length; i++) cityBuildingsLeft[i].destroy();
for (var i = 0; i < cityBuildingsRight.length; i++) cityBuildingsRight[i].destroy();
cityBuildingsLeft = [];
cityBuildingsRight = [];
// Building parameters
var buildingWidth = 600;
var buildingHeight = 900;
var gap = 0;
var yStart = -buildingHeight;
var yEnd = 2732 + buildingHeight;
// Left side
for (var y = yStart; y < yEnd; y += buildingHeight + gap) {
var b = new CityBuildingLeft();
b.x = roadLeft / 2;
b.y = y;
b.speed = 0;
cityBuildingsLeft.push(b);
game.addChild(b);
}
// Right side
for (var y = yStart + (buildingHeight + gap) / 4; y < yEnd; y += buildingHeight + gap) {
var b = new CityBuildingRight();
b.x = roadRight + (2048 - roadRight) / 2;
b.y = y;
b.speed = 0;
cityBuildingsRight.push(b);
game.addChild(b);
}
}
spawnCityBuildings();
// Player
var playerCar = new PlayerCar();
playerCar.x = laneCenters[1];
playerCar.y = 2732 - 400;
playerCar.lane = 1;
game.addChild(playerCar);
// Lane Dividers
var laneDividers = [];
function spawnLaneDividers() {
// Remove old
for (var i = 0; i < laneDividers.length; i++) {
laneDividers[i].destroy();
}
laneDividers = [];
// For each lane (except leftmost), spawn vertical dashed lines
for (var l = 1; l < laneCount; l++) {
// Offset the lane divider pattern so that no divider is at the same Y as the player car at spawn
// Player car spawns at y = 2732 - 400 = 2332
// Lane divider height is 120, so offset by half the gap to avoid overlap
var offsetY = 160; // 320/2, so the first divider is not at y=0
for (var y = -120 + offsetY; y < 2732 + 120; y += 320) {
var divider = new LaneDivider();
divider.x = roadLeft + laneWidth * l;
divider.y = y;
divider.speed = 0; // Set in update
laneDividers.push(divider);
game.addChild(divider);
}
}
}
spawnLaneDividers();
// Enemies and obstacles
var enemyCars = [];
var obstacles = [];
// Score
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Survival timer
var timeSurvived = 0;
var timeTxt = new Text2('0.0s', {
size: 80,
fill: "#fff"
});
timeTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timeTxt);
timeTxt.y = 130;
// Difficulty
var baseSpeed = 18; // px per frame
var speed = baseSpeed;
var speedIncrease = 0.003; // per tick
var spawnInterval = 60; // frames between spawns
var minSpawnInterval = 24;
var lastSpawnTick = 0;
// Dragging
var dragNode = null;
var dragOffsetX = 0;
// Touch controls: drag left/right to move car
game.down = function (x, y, obj) {
// Only allow 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.up = function (x, y, obj) {
dragNode = null;
};
game.move = function (x, y, obj) {
if (dragNode) {
// Only move horizontally, clamp to road
var newX = x + dragOffsetX;
if (newX < roadLeft + playerCar.width / 2) newX = roadLeft + playerCar.width / 2;
if (newX > roadRight - playerCar.width / 2) newX = roadRight - playerCar.width / 2;
playerCar.x = newX;
}
};
// Helper: get lane index from x
function getLaneIndex(x) {
var idx = Math.floor((x - roadLeft) / laneWidth);
if (idx < 0) idx = 0;
if (idx >= laneCount) idx = laneCount - 1;
return idx;
}
// Helper: check collision
function checkCollision(a, b) {
// Use .intersects
return a.intersects(b);
}
// Main update loop
game.update = function () {
// Increase speed over time
speed += speedIncrease;
if (speed > 40) speed = 40;
// Scroll city buildings
for (var i = cityBuildingsLeft.length - 1; i >= 0; i--) {
var b = cityBuildingsLeft[i];
b.y += speed * 0.7; // Move a bit slower than road for parallax
if (b.y > 2732 + 500) {
b.y -= 2732 + 1000;
}
}
for (var i = cityBuildingsRight.length - 1; i >= 0; i--) {
var b = cityBuildingsRight[i];
b.y += speed * 0.7;
if (b.y > 2732 + 500) {
b.y -= 2732 + 1000;
}
}
// Update lane dividers
for (var i = laneDividers.length - 1; i >= 0; i--) {
var divider = laneDividers[i];
divider.speed = speed;
divider.update();
if (divider.y > 2732 + 120) {
divider.y -= 2732 + 240;
}
}
// Update enemies
for (var i = enemyCars.length - 1; i >= 0; i--) {
var enemy = enemyCars[i];
enemy.speed = speed;
enemy.update();
// Remove if off screen
if (enemy.y > 2732 + 200) {
enemy.destroy();
enemyCars.splice(i, 1);
continue;
}
// Collision with player
if (checkCollision(playerCar, enemy)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Overtake: if enemy passes player and not yet counted
if (!enemy.overtaken && enemy.y > playerCar.y + playerCar.height / 2) {
enemy.overtaken = true;
score += 5;
scoreTxt.setText(score);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.speed = speed;
obs.update();
if (obs.y > 2732 + 100) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
if (checkCollision(playerCar, obs)) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
// Spawn enemies/obstacles
if (LK.ticks - lastSpawnTick > spawnInterval) {
lastSpawnTick = LK.ticks;
// Randomly decide: enemy car or obstacle
var spawnType = Math.random() < 0.7 ? 'enemy' : 'obstacle';
// Pick random lane(s)
var availableLanes = [];
for (var l = 0; l < laneCount; l++) availableLanes.push(l);
// Avoid spawning in player's lane if possible
var playerLane = getLaneIndex(playerCar.x);
if (availableLanes.length > 1) {
var idx = availableLanes.indexOf(playerLane);
if (idx !== -1 && Math.random() < 0.7) {
availableLanes.splice(idx, 1);
}
}
// For obstacles, sometimes block 2 lanes
if (spawnType === 'obstacle' && Math.random() < 0.3 && laneCount >= 3) {
// Block two adjacent lanes
var lane = availableLanes[Math.floor(Math.random() * (availableLanes.length - 1))];
for (var d = 0; d < 2; d++) {
var obs = new Obstacle();
obs.x = laneCenters[lane + d];
obs.y = -100;
obs.speed = speed;
obs.lane = lane + d;
obstacles.push(obs);
game.addChild(obs);
}
} else {
// Single enemy or obstacle
var lane = availableLanes[Math.floor(Math.random() * availableLanes.length)];
if (spawnType === 'enemy') {
// Randomly pick enemy type
var enemyTypeRand = Math.random();
var enemy;
if (enemyTypeRand < 0.6) {
enemy = new EnemyCar();
enemy.x = laneCenters[lane];
enemy.y = -180;
enemy.speed = speed;
enemy.lane = lane;
enemy.overtaken = false;
} else if (enemyTypeRand < 0.85) {
enemy = new EnemyCarBlue();
enemy.x = laneCenters[lane];
enemy.y = -180;
enemy.speed = speed;
enemy.lane = lane;
enemy.overtaken = false;
} else {
enemy = new EnemyCarTruck();
enemy.x = laneCenters[lane];
enemy.y = -220; // Truck is taller, spawn a bit higher
enemy.speed = speed;
enemy.lane = lane;
enemy.overtaken = false;
}
enemyCars.push(enemy);
game.addChild(enemy);
} else {
var obs = new Obstacle();
obs.x = laneCenters[lane];
obs.y = -100;
obs.speed = speed;
obs.lane = lane;
obstacles.push(obs);
game.addChild(obs);
}
}
// Decrease spawn interval as speed increases
spawnInterval = Math.max(minSpawnInterval, 60 - Math.floor((speed - baseSpeed) * 1.5));
}
// Score: +1 per 30 frames survived
if (LK.ticks % 30 === 0) {
score += 1;
scoreTxt.setText(score);
}
// Survival time
timeSurvived = LK.ticks / 60;
timeTxt.setText(timeSurvived.toFixed(1) + "s");
};
// Center score and time text
scoreTxt.x = LK.gui.top.width / 2;
scoreTxt.y = 10;
timeTxt.x = LK.gui.top.width / 2;
timeTxt.y = 130;
a top down red car . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a top down obstacle for car driving game. In-Game asset. 2d. High contrast. No shadows
a top down sport blue car. In-Game asset. 2d. High contrast. No shadows
can you make a green top down view suv car. In-Game asset. 2d. High contrast. No shadows
Can yo draw the white road line. In-Game asset. 2d. High contrast. No shadows
Can you make top down truck. In-Game asset. 2d. High contrast. No shadows
buildings seen from the side of the road from a bird's eye view, but do not draw the road, the buildings should be vertical and unlimited from above. In-Game asset. 2d. High contrast. No shadows