/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Collectible = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'fuel';
var assetType = self.type === 'fuel' ? 'fuel' : 'speedBoost';
var collectibleGraphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.pulseDirection = 1;
self.pulseAmount = 0;
self.update = function () {
if (!self.active) {
return;
}
self.x -= gameSpeed;
// Pulsing animation
self.pulseAmount += 0.02 * self.pulseDirection;
if (self.pulseAmount > 0.2 || self.pulseAmount < 0) {
self.pulseDirection *= -1;
}
collectibleGraphics.scaleX = 1 + self.pulseAmount;
collectibleGraphics.scaleY = 1 + self.pulseAmount;
// Remove if off screen
if (self.x < -100) {
self.active = false;
}
};
self.collect = function () {
if (self.active) {
self.active = false;
LK.getSound('collect').play();
var effect = {
alpha: 1,
scaleX: 1,
scaleY: 1,
y: self.y
};
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2,
y: self.y - 100
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self.type;
}
return null;
};
return self;
});
var FareObstacle = Container.expand(function () {
var self = Container.call(this);
var fareObstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'fareObstacle';
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
self.x -= gameSpeed;
if (self.x < -100) {
self.active = false;
}
};
return self;
});
var FuelItem = Container.expand(function () {
var self = Container.call(this);
var fuelItemGraphics = self.attachAsset('fuel', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'fuelItem';
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
self.x -= gameSpeed;
if (self.x < -100) {
self.active = false;
}
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'obstacle';
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
self.x -= gameSpeed;
// Remove if off screen
if (self.x < -100) {
self.active = false;
}
};
return self;
});
var RoadLine = Container.expand(function () {
var self = Container.call(this);
var lineGraphics = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x -= gameSpeed;
// Reset position if off screen
if (self.x < -100) {
self.x = 2148;
}
};
return self;
});
var Vehicle = Container.expand(function () {
var self = Container.call(this);
var vehicleGraphics = self.attachAsset('vehicle', {
anchorX: 0.5,
anchorY: 0.5
});
// Vehicle properties
self.speed = 1;
self.maxSpeed = 15;
self.acceleration = 0.005;
self.jumping = false;
self.jumpHeight = 200;
self.jumpSpeed = 15;
self.jumpVelocity = 0;
self.gravity = 0.8;
self.crashed = false;
// Movement control
self.moveUp = function () {
if (self.y > roadTop + 50) {
self.y -= 20;
}
};
self.moveDown = function () {
if (self.y < roadBottom - 50) {
self.y += 20;
}
};
self.jump = function () {
if (!self.jumping && !self.crashed) {
self.jumping = true;
self.jumpVelocity = -self.jumpSpeed;
}
};
self.crash = function () {
if (!self.crashed) {
self.crashed = true;
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xff0000, 1000);
// Create explosion effect
var explosion = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.8
});
game.addChild(explosion);
// Scale explosion and fade out
tween(explosion, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Tilt vehicle
tween(vehicleGraphics, {
rotation: Math.PI / 4
}, {
duration: 500,
easing: tween.bounceOut
});
// Game over after short delay
LK.setTimeout(function () {
if (distance > storage.highScore) {
storage.highScore = Math.floor(distance);
}
LK.showGameOver();
}, 1200);
}
};
self.update = function () {
if (self.crashed) {
return;
}
// Update speed
if (self.speed < self.maxSpeed) {
self.speed += self.acceleration;
}
// Handle jumping
if (self.jumping) {
self.y += self.jumpVelocity;
self.jumpVelocity += self.gravity;
// Check if landing
if (self.jumpVelocity > 0 && self.y >= self.jumpStartY) {
self.y = self.jumpStartY;
self.jumping = false;
self.jumpVelocity = 0;
}
}
// Small bounce effect
if (!self.jumping && !self.tweening) {
self.tweening = true;
tween(vehicleGraphics, {
rotation: -0.05
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
tween(vehicleGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
self.tweening = false;
}
});
}
});
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue
});
/****
* Game Code
****/
// Game variables
var vehicle;
var obstacles = [];
var collectibles = [];
var roadLines = [];
var gameSpeed = 8;
var baseSpeed = 8;
var speedMultiplier = 1;
var distance = 0;
var fuelLevel = 100;
var gameStarted = false;
var roadTop = 2732 - 500; // Top of road area
var roadBottom = 2732 - 200; // Bottom of road area
var spawnTimer = 0;
var obstacleSpawnRate = 180; // frames between obstacle spawns
var collectibleSpawnRate = 180; // frames between collectible spawns
var lastObstacleSpawn = 0;
var lastCollectibleSpawn = 0;
// Add background image
var background = LK.getAsset('backgroundImage', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(background);
// Create road
var road = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
x: 0,
y: roadTop,
width: 2048
});
game.addChild(road);
// Create road lines
for (var i = 0; i < 10; i++) {
var roadLine = new RoadLine();
roadLine.x = i * 220;
roadLine.y = roadTop + 150;
roadLines.push(roadLine);
game.addChild(roadLine);
}
// Create player vehicle
vehicle = new Vehicle();
vehicle.x = 300;
vehicle.y = roadTop + 150;
vehicle.jumpStartY = vehicle.y;
game.addChild(vehicle);
// Create score text
var scoreTxt = new Text2('Distance: 0m', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create fuel meter
var fuelBarBg = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
width: 300,
height: 30,
color: 0x555555,
x: 0,
y: 0
});
var fuelBar = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
width: 300,
height: 30,
color: 0x2ecc71,
x: 0,
y: 0
});
var fuelText = new Text2('FUEL', {
size: 20,
fill: 0xFFFFFF
});
fuelText.anchor.set(0.5, 0.5);
fuelText.x = 150;
fuelText.y = 15;
var fuelContainer = new Container();
fuelContainer.addChild(fuelBarBg);
fuelContainer.addChild(fuelBar);
fuelContainer.addChild(fuelText);
fuelContainer.x = 20;
fuelContainer.y = 20;
LK.gui.topLeft.addChild(fuelContainer);
// Create high score display
var highScoreTxt = new Text2('Best: ' + storage.highScore + 'm', {
size: 50,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(1, 0);
highScoreTxt.x = -20;
highScoreTxt.y = 20;
LK.gui.topRight.addChild(highScoreTxt);
// Speed boost indicator
var boostIndicator = new Text2('BOOST!', {
size: 60,
fill: 0xF1C40F
});
boostIndicator.anchor.set(0.5, 0);
boostIndicator.y = 100;
boostIndicator.alpha = 0;
LK.gui.top.addChild(boostIndicator);
// Create tap controls
function createControlButton(text, x, y, action) {
var button = new Container();
var buttonBg = LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 200,
color: 0x000000,
alpha: 0.3
});
button.addChild(buttonBg);
var buttonText = new Text2(text, {
size: 60,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
button.addChild(buttonText);
button.x = x;
button.y = y;
button.interactive = true;
button.down = function () {
buttonBg.alpha = 0.5;
action();
};
button.up = function () {
buttonBg.alpha = 0.3;
};
return button;
}
var upButton = createControlButton("↑", -300, -200, function () {
vehicle.moveUp();
});
var downButton = createControlButton("↓", -300, -50, function () {
vehicle.moveDown();
});
var jumpButton = createControlButton("JUMP", 300, -125, function () {
vehicle.jump();
});
LK.gui.bottom.addChild(upButton);
LK.gui.bottom.addChild(downButton);
LK.gui.bottom.addChild(jumpButton);
// Start the game
LK.playMusic('gameMusic');
gameStarted = true;
// Spawn objects
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.x = 2200;
// Random position on road
obstacle.y = roadTop + 50 + Math.random() * (roadBottom - roadTop - 100);
obstacles.push(obstacle);
game.addChild(obstacle);
lastObstacleSpawn = LK.ticks;
}
function spawnCollectible() {
var type = Math.random() < 0.7 ? 'fuel' : 'speedBoost';
var collectible = new Collectible(type);
collectible.x = 2200;
// Random position on road
collectible.y = roadTop + 50 + Math.random() * (roadBottom - roadTop - 100);
collectibles.push(collectible);
game.addChild(collectible);
lastCollectibleSpawn = LK.ticks;
}
// Game update function
game.update = function () {
if (!gameStarted || vehicle.crashed) {
return;
}
// Calculate game speed
gameSpeed = baseSpeed * speedMultiplier;
// Update vehicle
vehicle.update();
// Update road lines
for (var i = 0; i < roadLines.length; i++) {
roadLines[i].update();
}
// Spawn obstacles
if (LK.ticks - lastObstacleSpawn > obstacleSpawnRate) {
spawnObstacle();
// Gradually decrease spawn rate to increase difficulty
obstacleSpawnRate = Math.max(60, obstacleSpawnRate - 0.5);
// Randomly spawn fare obstacle with a lower probability
if (Math.random() < 0.1) {
var fareObstacle = new FareObstacle();
fareObstacle.x = 2200;
fareObstacle.y = roadTop + 50 + Math.random() * (roadBottom - roadTop - 100);
obstacles.push(fareObstacle);
game.addChild(fareObstacle);
}
}
// Spawn fuel items separately
if (LK.ticks - lastCollectibleSpawn > collectibleSpawnRate) {
// Randomly spawn fuel item with a lower probability
if (Math.random() < 0.1) {
var fuelItem = new FuelItem();
fuelItem.x = 2200;
fuelItem.y = roadTop + 50 + Math.random() * (roadBottom - roadTop - 100);
collectibles.push(fuelItem);
game.addChild(fuelItem);
}
}
// Spawn collectibles
if (LK.ticks - lastCollectibleSpawn > collectibleSpawnRate) {
spawnCollectible();
}
// Update obstacles and check collisions
for (var j = obstacles.length - 1; j >= 0; j--) {
var obstacle = obstacles[j];
obstacle.update();
// Check collision with vehicle
if (obstacle.active && !vehicle.crashed && !vehicle.invulnerable && vehicle.intersects(obstacle)) {
vehicle.crash();
}
// Remove inactive obstacles
if (!obstacle.active) {
obstacle.destroy();
obstacles.splice(j, 1);
}
}
// Update collectibles and check collection
for (var k = collectibles.length - 1; k >= 0; k--) {
var collectible = collectibles[k];
collectible.update();
// Check collection
if (collectible.active && vehicle.intersects(collectible)) {
if (typeof collectible.collect === 'function') {
var collectibleType = collectible.collect();
}
if (collectibleType === 'fuel') {
// Add fuel
fuelLevel = Math.min(100, fuelLevel + 30);
fuelBar.width = fuelLevel / 100 * 300;
// Flash fuel text
tween(fuelText, {
tint: 0x2ecc71
}, {
duration: 300,
onFinish: function onFinish() {
tween(fuelText, {
tint: 0xffffff
}, {
duration: 300
});
}
});
} else if (collectibleType === 'speedBoost') {
// Speed boost
LK.getSound('boost').play();
speedMultiplier = 1.5;
// Show boost indicator
boostIndicator.alpha = 1;
// Reset multiplier after 3 seconds
LK.setTimeout(function () {
tween(boostIndicator, {
alpha: 0
}, {
duration: 500
});
speedMultiplier = 1;
}, 3000);
}
collectibles.splice(k, 1);
}
}
// Update distance and score
distance += gameSpeed / 30;
scoreTxt.setText('Distance: ' + Math.floor(distance) + 'm');
// Update fuel
fuelLevel -= 0.05 * speedMultiplier;
fuelBar.width = fuelLevel / 100 * 300;
// Change fuel bar color based on level
if (fuelLevel < 30) {
fuelBar.tint = 0xe74c3c; // Red when low
} else if (fuelLevel < 60) {
fuelBar.tint = 0xf39c12; // Orange when medium
} else {
fuelBar.tint = 0x2ecc71; // Green when high
}
// Game over if fuel depleted
if (fuelLevel <= 0) {
vehicle.crash();
}
// Increase speed over time (difficulty progression)
if (LK.ticks % 300 === 0) {
baseSpeed += 0.2;
}
};
// Game input handling
game.down = function (x, y, obj) {
// Jump if tap in the right half of the screen
if (x > 1024 && !vehicle.jumping && !vehicle.crashed) {
vehicle.jump();
}
// Move up if tap in the top quarter of left half
else if (x < 1024 && y < 683) {
vehicle.moveUp();
}
// Move down if tap in the bottom quarter of left half
else if (x < 1024 && y >= 683) {
vehicle.moveDown();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Collectible = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'fuel';
var assetType = self.type === 'fuel' ? 'fuel' : 'speedBoost';
var collectibleGraphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
self.active = true;
self.pulseDirection = 1;
self.pulseAmount = 0;
self.update = function () {
if (!self.active) {
return;
}
self.x -= gameSpeed;
// Pulsing animation
self.pulseAmount += 0.02 * self.pulseDirection;
if (self.pulseAmount > 0.2 || self.pulseAmount < 0) {
self.pulseDirection *= -1;
}
collectibleGraphics.scaleX = 1 + self.pulseAmount;
collectibleGraphics.scaleY = 1 + self.pulseAmount;
// Remove if off screen
if (self.x < -100) {
self.active = false;
}
};
self.collect = function () {
if (self.active) {
self.active = false;
LK.getSound('collect').play();
var effect = {
alpha: 1,
scaleX: 1,
scaleY: 1,
y: self.y
};
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2,
y: self.y - 100
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
return self.type;
}
return null;
};
return self;
});
var FareObstacle = Container.expand(function () {
var self = Container.call(this);
var fareObstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'fareObstacle';
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
self.x -= gameSpeed;
if (self.x < -100) {
self.active = false;
}
};
return self;
});
var FuelItem = Container.expand(function () {
var self = Container.call(this);
var fuelItemGraphics = self.attachAsset('fuel', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'fuelItem';
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
self.x -= gameSpeed;
if (self.x < -100) {
self.active = false;
}
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'obstacle';
self.active = true;
self.update = function () {
if (!self.active) {
return;
}
self.x -= gameSpeed;
// Remove if off screen
if (self.x < -100) {
self.active = false;
}
};
return self;
});
var RoadLine = Container.expand(function () {
var self = Container.call(this);
var lineGraphics = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.x -= gameSpeed;
// Reset position if off screen
if (self.x < -100) {
self.x = 2148;
}
};
return self;
});
var Vehicle = Container.expand(function () {
var self = Container.call(this);
var vehicleGraphics = self.attachAsset('vehicle', {
anchorX: 0.5,
anchorY: 0.5
});
// Vehicle properties
self.speed = 1;
self.maxSpeed = 15;
self.acceleration = 0.005;
self.jumping = false;
self.jumpHeight = 200;
self.jumpSpeed = 15;
self.jumpVelocity = 0;
self.gravity = 0.8;
self.crashed = false;
// Movement control
self.moveUp = function () {
if (self.y > roadTop + 50) {
self.y -= 20;
}
};
self.moveDown = function () {
if (self.y < roadBottom - 50) {
self.y += 20;
}
};
self.jump = function () {
if (!self.jumping && !self.crashed) {
self.jumping = true;
self.jumpVelocity = -self.jumpSpeed;
}
};
self.crash = function () {
if (!self.crashed) {
self.crashed = true;
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xff0000, 1000);
// Create explosion effect
var explosion = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
alpha: 0.8
});
game.addChild(explosion);
// Scale explosion and fade out
tween(explosion, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Tilt vehicle
tween(vehicleGraphics, {
rotation: Math.PI / 4
}, {
duration: 500,
easing: tween.bounceOut
});
// Game over after short delay
LK.setTimeout(function () {
if (distance > storage.highScore) {
storage.highScore = Math.floor(distance);
}
LK.showGameOver();
}, 1200);
}
};
self.update = function () {
if (self.crashed) {
return;
}
// Update speed
if (self.speed < self.maxSpeed) {
self.speed += self.acceleration;
}
// Handle jumping
if (self.jumping) {
self.y += self.jumpVelocity;
self.jumpVelocity += self.gravity;
// Check if landing
if (self.jumpVelocity > 0 && self.y >= self.jumpStartY) {
self.y = self.jumpStartY;
self.jumping = false;
self.jumpVelocity = 0;
}
}
// Small bounce effect
if (!self.jumping && !self.tweening) {
self.tweening = true;
tween(vehicleGraphics, {
rotation: -0.05
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
tween(vehicleGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
self.tweening = false;
}
});
}
});
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue
});
/****
* Game Code
****/
// Game variables
var vehicle;
var obstacles = [];
var collectibles = [];
var roadLines = [];
var gameSpeed = 8;
var baseSpeed = 8;
var speedMultiplier = 1;
var distance = 0;
var fuelLevel = 100;
var gameStarted = false;
var roadTop = 2732 - 500; // Top of road area
var roadBottom = 2732 - 200; // Bottom of road area
var spawnTimer = 0;
var obstacleSpawnRate = 180; // frames between obstacle spawns
var collectibleSpawnRate = 180; // frames between collectible spawns
var lastObstacleSpawn = 0;
var lastCollectibleSpawn = 0;
// Add background image
var background = LK.getAsset('backgroundImage', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(background);
// Create road
var road = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
x: 0,
y: roadTop,
width: 2048
});
game.addChild(road);
// Create road lines
for (var i = 0; i < 10; i++) {
var roadLine = new RoadLine();
roadLine.x = i * 220;
roadLine.y = roadTop + 150;
roadLines.push(roadLine);
game.addChild(roadLine);
}
// Create player vehicle
vehicle = new Vehicle();
vehicle.x = 300;
vehicle.y = roadTop + 150;
vehicle.jumpStartY = vehicle.y;
game.addChild(vehicle);
// Create score text
var scoreTxt = new Text2('Distance: 0m', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create fuel meter
var fuelBarBg = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
width: 300,
height: 30,
color: 0x555555,
x: 0,
y: 0
});
var fuelBar = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
width: 300,
height: 30,
color: 0x2ecc71,
x: 0,
y: 0
});
var fuelText = new Text2('FUEL', {
size: 20,
fill: 0xFFFFFF
});
fuelText.anchor.set(0.5, 0.5);
fuelText.x = 150;
fuelText.y = 15;
var fuelContainer = new Container();
fuelContainer.addChild(fuelBarBg);
fuelContainer.addChild(fuelBar);
fuelContainer.addChild(fuelText);
fuelContainer.x = 20;
fuelContainer.y = 20;
LK.gui.topLeft.addChild(fuelContainer);
// Create high score display
var highScoreTxt = new Text2('Best: ' + storage.highScore + 'm', {
size: 50,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(1, 0);
highScoreTxt.x = -20;
highScoreTxt.y = 20;
LK.gui.topRight.addChild(highScoreTxt);
// Speed boost indicator
var boostIndicator = new Text2('BOOST!', {
size: 60,
fill: 0xF1C40F
});
boostIndicator.anchor.set(0.5, 0);
boostIndicator.y = 100;
boostIndicator.alpha = 0;
LK.gui.top.addChild(boostIndicator);
// Create tap controls
function createControlButton(text, x, y, action) {
var button = new Container();
var buttonBg = LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 200,
color: 0x000000,
alpha: 0.3
});
button.addChild(buttonBg);
var buttonText = new Text2(text, {
size: 60,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
button.addChild(buttonText);
button.x = x;
button.y = y;
button.interactive = true;
button.down = function () {
buttonBg.alpha = 0.5;
action();
};
button.up = function () {
buttonBg.alpha = 0.3;
};
return button;
}
var upButton = createControlButton("↑", -300, -200, function () {
vehicle.moveUp();
});
var downButton = createControlButton("↓", -300, -50, function () {
vehicle.moveDown();
});
var jumpButton = createControlButton("JUMP", 300, -125, function () {
vehicle.jump();
});
LK.gui.bottom.addChild(upButton);
LK.gui.bottom.addChild(downButton);
LK.gui.bottom.addChild(jumpButton);
// Start the game
LK.playMusic('gameMusic');
gameStarted = true;
// Spawn objects
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.x = 2200;
// Random position on road
obstacle.y = roadTop + 50 + Math.random() * (roadBottom - roadTop - 100);
obstacles.push(obstacle);
game.addChild(obstacle);
lastObstacleSpawn = LK.ticks;
}
function spawnCollectible() {
var type = Math.random() < 0.7 ? 'fuel' : 'speedBoost';
var collectible = new Collectible(type);
collectible.x = 2200;
// Random position on road
collectible.y = roadTop + 50 + Math.random() * (roadBottom - roadTop - 100);
collectibles.push(collectible);
game.addChild(collectible);
lastCollectibleSpawn = LK.ticks;
}
// Game update function
game.update = function () {
if (!gameStarted || vehicle.crashed) {
return;
}
// Calculate game speed
gameSpeed = baseSpeed * speedMultiplier;
// Update vehicle
vehicle.update();
// Update road lines
for (var i = 0; i < roadLines.length; i++) {
roadLines[i].update();
}
// Spawn obstacles
if (LK.ticks - lastObstacleSpawn > obstacleSpawnRate) {
spawnObstacle();
// Gradually decrease spawn rate to increase difficulty
obstacleSpawnRate = Math.max(60, obstacleSpawnRate - 0.5);
// Randomly spawn fare obstacle with a lower probability
if (Math.random() < 0.1) {
var fareObstacle = new FareObstacle();
fareObstacle.x = 2200;
fareObstacle.y = roadTop + 50 + Math.random() * (roadBottom - roadTop - 100);
obstacles.push(fareObstacle);
game.addChild(fareObstacle);
}
}
// Spawn fuel items separately
if (LK.ticks - lastCollectibleSpawn > collectibleSpawnRate) {
// Randomly spawn fuel item with a lower probability
if (Math.random() < 0.1) {
var fuelItem = new FuelItem();
fuelItem.x = 2200;
fuelItem.y = roadTop + 50 + Math.random() * (roadBottom - roadTop - 100);
collectibles.push(fuelItem);
game.addChild(fuelItem);
}
}
// Spawn collectibles
if (LK.ticks - lastCollectibleSpawn > collectibleSpawnRate) {
spawnCollectible();
}
// Update obstacles and check collisions
for (var j = obstacles.length - 1; j >= 0; j--) {
var obstacle = obstacles[j];
obstacle.update();
// Check collision with vehicle
if (obstacle.active && !vehicle.crashed && !vehicle.invulnerable && vehicle.intersects(obstacle)) {
vehicle.crash();
}
// Remove inactive obstacles
if (!obstacle.active) {
obstacle.destroy();
obstacles.splice(j, 1);
}
}
// Update collectibles and check collection
for (var k = collectibles.length - 1; k >= 0; k--) {
var collectible = collectibles[k];
collectible.update();
// Check collection
if (collectible.active && vehicle.intersects(collectible)) {
if (typeof collectible.collect === 'function') {
var collectibleType = collectible.collect();
}
if (collectibleType === 'fuel') {
// Add fuel
fuelLevel = Math.min(100, fuelLevel + 30);
fuelBar.width = fuelLevel / 100 * 300;
// Flash fuel text
tween(fuelText, {
tint: 0x2ecc71
}, {
duration: 300,
onFinish: function onFinish() {
tween(fuelText, {
tint: 0xffffff
}, {
duration: 300
});
}
});
} else if (collectibleType === 'speedBoost') {
// Speed boost
LK.getSound('boost').play();
speedMultiplier = 1.5;
// Show boost indicator
boostIndicator.alpha = 1;
// Reset multiplier after 3 seconds
LK.setTimeout(function () {
tween(boostIndicator, {
alpha: 0
}, {
duration: 500
});
speedMultiplier = 1;
}, 3000);
}
collectibles.splice(k, 1);
}
}
// Update distance and score
distance += gameSpeed / 30;
scoreTxt.setText('Distance: ' + Math.floor(distance) + 'm');
// Update fuel
fuelLevel -= 0.05 * speedMultiplier;
fuelBar.width = fuelLevel / 100 * 300;
// Change fuel bar color based on level
if (fuelLevel < 30) {
fuelBar.tint = 0xe74c3c; // Red when low
} else if (fuelLevel < 60) {
fuelBar.tint = 0xf39c12; // Orange when medium
} else {
fuelBar.tint = 0x2ecc71; // Green when high
}
// Game over if fuel depleted
if (fuelLevel <= 0) {
vehicle.crash();
}
// Increase speed over time (difficulty progression)
if (LK.ticks % 300 === 0) {
baseSpeed += 0.2;
}
};
// Game input handling
game.down = function (x, y, obj) {
// Jump if tap in the right half of the screen
if (x > 1024 && !vehicle.jumping && !vehicle.crashed) {
vehicle.jump();
}
// Move up if tap in the top quarter of left half
else if (x < 1024 && y < 683) {
vehicle.moveUp();
}
// Move down if tap in the bottom quarter of left half
else if (x < 1024 && y >= 683) {
vehicle.moveDown();
}
};