/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Coin Class var Coin = Container.expand(function () { var self = Container.call(this); // Gold ellipse for coin var coin = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5, color: 0xffd700, width: 100, height: 100, shape: 'ellipse' }); self.width = coin.width; self.height = coin.height; // Speed will be set on spawn self.speed = 10; self.update = function () { self.y += self.speed; }; return self; }); // Obstacle Car Class var ObstacleCar = Container.expand(function () { var self = Container.call(this); // Random color for variety var colors = [0x1e90ff, 0x32cd32, 0xffa500, 0x8a2be2, 0xff1493, 0x00ced1]; var color = colors[Math.floor(Math.random() * colors.length)]; var car = self.attachAsset('obstacleCar', { anchorX: 0.5, anchorY: 0.5, color: color, width: 200, height: 300 }); self.width = car.width; self.height = car.height; // Speed will be set on spawn self.speed = 10; self.update = function () { self.y += self.speed; }; return self; }); // Player Car Class var PlayerCar = Container.expand(function () { var self = Container.call(this); // Attach car asset (red box) var car = self.attachAsset('playerCar', { anchorX: 0.5, anchorY: 0.5 }); // Set initial size (about 200x300 px) car.width = 200; car.height = 300; // For collision, use self as the hitbox self.width = car.width; self.height = car.height; // No update needed; position is set by drag return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game area: 2048x2732 // Road boundaries (leave 200px margin on each side) var roadLeft = 200; var roadRight = 2048 - 200; var roadWidth = roadRight - roadLeft; // Lane count and positions var laneCount = 4; var laneWidth = roadWidth / laneCount; var laneCenters = []; for (var i = 0; i < laneCount; i++) { laneCenters.push(roadLeft + laneWidth * (i + 0.5)); } // Game state variables var playerCar; var obstacles = []; var coins = []; var dragNode = null; var lastCrash = false; var speed = 18; // Initial speed (pixels per frame) var minSpeed = 12; var maxSpeed = 38; var speedIncreaseEvery = 600; // Increase speed every 600 ticks (~10s) var ticksSinceStart = 0; var distance = 0; // Distance in meters (1 meter = 10px) var coinScore = 0; // Score text var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Coin text var coinTxt = new Text2('0', { size: 80, fill: 0xFFD700 }); coinTxt.anchor.set(0.5, 0); LK.gui.topRight.addChild(coinTxt); // Draw road (gray box) var road = LK.getAsset('road', { anchorX: 0, anchorY: 0, color: 0x444444, width: roadWidth, height: 2732 }); road.x = roadLeft; road.y = 0; game.addChild(road); // Draw lane lines (white boxes) for (var i = 1; i < laneCount; i++) { var line = LK.getAsset('laneLine' + i, { anchorX: 0.5, anchorY: 0, color: 0xffffff, width: 16, height: 2732, shape: 'box' }); line.x = roadLeft + laneWidth * i; line.y = 0; line.alpha = 0.2; game.addChild(line); } // Create player car playerCar = new PlayerCar(); playerCar.x = laneCenters[1]; // Start in lane 2 playerCar.y = 2732 - 400; game.addChild(playerCar); // Touch/drag controls function handleMove(x, y, obj) { if (dragNode) { // Clamp x to road var newX = Math.max(roadLeft + playerCar.width / 2, Math.min(roadRight - playerCar.width / 2, x)); dragNode.x = newX; } // Crash detection var crashed = false; for (var i = 0; i < obstacles.length; i++) { if (playerCar.intersects(obstacles[i])) { crashed = true; break; } } if (!lastCrash && crashed) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } lastCrash = crashed; // Coin collection for (var i = coins.length - 1; i >= 0; i--) { if (playerCar.intersects(coins[i])) { coinScore += 1; coinTxt.setText(coinScore); LK.effects.flashObject(coins[i], 0xffd700, 300); coins[i].destroy(); coins.splice(i, 1); } } } game.move = handleMove; game.down = function (x, y, obj) { // Only allow drag if touch is on player car or below it if (x >= playerCar.x - playerCar.width / 2 && x <= playerCar.x + playerCar.width / 2 && y >= playerCar.y - playerCar.height / 2 && y <= playerCar.y + playerCar.height / 2) { dragNode = playerCar; } else if (y > playerCar.y) { dragNode = playerCar; } handleMove(x, y, obj); }; game.up = function (x, y, obj) { dragNode = null; }; // Main game loop game.update = function () { ticksSinceStart += 1; // Increase speed over time if (ticksSinceStart % speedIncreaseEvery === 0 && speed < maxSpeed) { speed += 2; if (speed > maxSpeed) speed = maxSpeed; } // Move obstacles and coins for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.speed = speed; obs.update(); if (obs.y > 2732 + 200) { obs.destroy(); obstacles.splice(i, 1); } } for (var i = coins.length - 1; i >= 0; i--) { var coin = coins[i]; coin.speed = speed; coin.update(); if (coin.y > 2732 + 100) { coin.destroy(); coins.splice(i, 1); } } // Spawn obstacles // Every 45 ticks (~0.75s at 60fps) if (LK.ticks % 45 === 0) { // Randomly pick 1-2 lanes to spawn cars var lanesToUse = []; var laneIndexes = [0, 1, 2, 3]; // Shuffle for (var i = laneIndexes.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var t = laneIndexes[i]; laneIndexes[i] = laneIndexes[j]; laneIndexes[j] = t; } var carCount = Math.random() < 0.7 ? 1 : 2; for (var i = 0; i < carCount; i++) { lanesToUse.push(laneIndexes[i]); } for (var i = 0; i < lanesToUse.length; i++) { var obs = new ObstacleCar(); obs.x = laneCenters[lanesToUse[i]]; obs.y = -200; obs.speed = speed; obstacles.push(obs); game.addChild(obs); } } // Spawn coins // Every 60 ticks (~1s) if (LK.ticks % 60 === 0) { // 50% chance to spawn a coin in a random lane not blocked by a car if (Math.random() < 0.5) { // Find lanes without a car near the top var freeLanes = []; for (var i = 0; i < laneCount; i++) { var blocked = false; for (var j = 0; j < obstacles.length; j++) { if (Math.abs(obstacles[j].x - laneCenters[i]) < 10 && obstacles[j].y < 200) { blocked = true; break; } } if (!blocked) freeLanes.push(i); } if (freeLanes.length > 0) { var laneIdx = freeLanes[Math.floor(Math.random() * freeLanes.length)]; var coin = new Coin(); coin.x = laneCenters[laneIdx]; coin.y = -100; coin.speed = speed; coins.push(coin); game.addChild(coin); } } } // Update distance and score distance += speed / 10; // 1 meter = 10px var score = Math.floor(distance) + coinScore * 10; scoreTxt.setText(score); // Coin text (already updated on collect) }; // Set initial score and coin text scoreTxt.setText('0'); coinTxt.setText('0');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Coin Class
var Coin = Container.expand(function () {
var self = Container.call(this);
// Gold ellipse for coin
var coin = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5,
color: 0xffd700,
width: 100,
height: 100,
shape: 'ellipse'
});
self.width = coin.width;
self.height = coin.height;
// Speed will be set on spawn
self.speed = 10;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Obstacle Car Class
var ObstacleCar = Container.expand(function () {
var self = Container.call(this);
// Random color for variety
var colors = [0x1e90ff, 0x32cd32, 0xffa500, 0x8a2be2, 0xff1493, 0x00ced1];
var color = colors[Math.floor(Math.random() * colors.length)];
var car = self.attachAsset('obstacleCar', {
anchorX: 0.5,
anchorY: 0.5,
color: color,
width: 200,
height: 300
});
self.width = car.width;
self.height = car.height;
// Speed will be set on spawn
self.speed = 10;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Car Class
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
// Attach car asset (red box)
var car = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
// Set initial size (about 200x300 px)
car.width = 200;
car.height = 300;
// For collision, use self as the hitbox
self.width = car.width;
self.height = car.height;
// No update needed; position is set by drag
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Game area: 2048x2732
// Road boundaries (leave 200px margin on each side)
var roadLeft = 200;
var roadRight = 2048 - 200;
var roadWidth = roadRight - roadLeft;
// Lane count and positions
var laneCount = 4;
var laneWidth = roadWidth / laneCount;
var laneCenters = [];
for (var i = 0; i < laneCount; i++) {
laneCenters.push(roadLeft + laneWidth * (i + 0.5));
}
// Game state variables
var playerCar;
var obstacles = [];
var coins = [];
var dragNode = null;
var lastCrash = false;
var speed = 18; // Initial speed (pixels per frame)
var minSpeed = 12;
var maxSpeed = 38;
var speedIncreaseEvery = 600; // Increase speed every 600 ticks (~10s)
var ticksSinceStart = 0;
var distance = 0; // Distance in meters (1 meter = 10px)
var coinScore = 0;
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Coin text
var coinTxt = new Text2('0', {
size: 80,
fill: 0xFFD700
});
coinTxt.anchor.set(0.5, 0);
LK.gui.topRight.addChild(coinTxt);
// Draw road (gray box)
var road = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
color: 0x444444,
width: roadWidth,
height: 2732
});
road.x = roadLeft;
road.y = 0;
game.addChild(road);
// Draw lane lines (white boxes)
for (var i = 1; i < laneCount; i++) {
var line = LK.getAsset('laneLine' + i, {
anchorX: 0.5,
anchorY: 0,
color: 0xffffff,
width: 16,
height: 2732,
shape: 'box'
});
line.x = roadLeft + laneWidth * i;
line.y = 0;
line.alpha = 0.2;
game.addChild(line);
}
// Create player car
playerCar = new PlayerCar();
playerCar.x = laneCenters[1]; // Start in lane 2
playerCar.y = 2732 - 400;
game.addChild(playerCar);
// Touch/drag controls
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp x to road
var newX = Math.max(roadLeft + playerCar.width / 2, Math.min(roadRight - playerCar.width / 2, x));
dragNode.x = newX;
}
// Crash detection
var crashed = false;
for (var i = 0; i < obstacles.length; i++) {
if (playerCar.intersects(obstacles[i])) {
crashed = true;
break;
}
}
if (!lastCrash && crashed) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
lastCrash = crashed;
// Coin collection
for (var i = coins.length - 1; i >= 0; i--) {
if (playerCar.intersects(coins[i])) {
coinScore += 1;
coinTxt.setText(coinScore);
LK.effects.flashObject(coins[i], 0xffd700, 300);
coins[i].destroy();
coins.splice(i, 1);
}
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if touch is on player car or below it
if (x >= playerCar.x - playerCar.width / 2 && x <= playerCar.x + playerCar.width / 2 && y >= playerCar.y - playerCar.height / 2 && y <= playerCar.y + playerCar.height / 2) {
dragNode = playerCar;
} else if (y > playerCar.y) {
dragNode = playerCar;
}
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game loop
game.update = function () {
ticksSinceStart += 1;
// Increase speed over time
if (ticksSinceStart % speedIncreaseEvery === 0 && speed < maxSpeed) {
speed += 2;
if (speed > maxSpeed) speed = maxSpeed;
}
// Move obstacles and coins
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.speed = speed;
obs.update();
if (obs.y > 2732 + 200) {
obs.destroy();
obstacles.splice(i, 1);
}
}
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
coin.speed = speed;
coin.update();
if (coin.y > 2732 + 100) {
coin.destroy();
coins.splice(i, 1);
}
}
// Spawn obstacles
// Every 45 ticks (~0.75s at 60fps)
if (LK.ticks % 45 === 0) {
// Randomly pick 1-2 lanes to spawn cars
var lanesToUse = [];
var laneIndexes = [0, 1, 2, 3];
// Shuffle
for (var i = laneIndexes.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var t = laneIndexes[i];
laneIndexes[i] = laneIndexes[j];
laneIndexes[j] = t;
}
var carCount = Math.random() < 0.7 ? 1 : 2;
for (var i = 0; i < carCount; i++) {
lanesToUse.push(laneIndexes[i]);
}
for (var i = 0; i < lanesToUse.length; i++) {
var obs = new ObstacleCar();
obs.x = laneCenters[lanesToUse[i]];
obs.y = -200;
obs.speed = speed;
obstacles.push(obs);
game.addChild(obs);
}
}
// Spawn coins
// Every 60 ticks (~1s)
if (LK.ticks % 60 === 0) {
// 50% chance to spawn a coin in a random lane not blocked by a car
if (Math.random() < 0.5) {
// Find lanes without a car near the top
var freeLanes = [];
for (var i = 0; i < laneCount; i++) {
var blocked = false;
for (var j = 0; j < obstacles.length; j++) {
if (Math.abs(obstacles[j].x - laneCenters[i]) < 10 && obstacles[j].y < 200) {
blocked = true;
break;
}
}
if (!blocked) freeLanes.push(i);
}
if (freeLanes.length > 0) {
var laneIdx = freeLanes[Math.floor(Math.random() * freeLanes.length)];
var coin = new Coin();
coin.x = laneCenters[laneIdx];
coin.y = -100;
coin.speed = speed;
coins.push(coin);
game.addChild(coin);
}
}
}
// Update distance and score
distance += speed / 10; // 1 meter = 10px
var score = Math.floor(distance) + coinScore * 10;
scoreTxt.setText(score);
// Coin text (already updated on collect)
};
// Set initial score and coin text
scoreTxt.setText('0');
coinTxt.setText('0');