/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Collectible = Container.expand(function () { var self = Container.call(this); self.init = function (type) { self.type = type; var assetType; switch (type) { case 'coin': assetType = 'coin'; break; case 'shield': assetType = 'shield'; break; case 'speedBoost': assetType = 'speedBoost'; break; case 'superSpeedBoost': assetType = 'speedBoost'; break; default: assetType = 'coin'; } self.collectibleGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); self.width = self.collectibleGraphics.width; self.height = self.collectibleGraphics.height; self.lane = Math.floor(Math.random() * 4); // Randomly assign one of the 4 lanes self.x = LANE_POSITIONS[self.lane]; // Animation self.collectibleGraphics.rotation = 0; return self; }; self.update = function () { self.y += gameSpeed.value; // Rotate collectible self.collectibleGraphics.rotation += 0.05; // Check if the collectible is off-screen if (self.y > 2732 + self.height) { self.active = false; } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.width = playerGraphics.width; self.height = playerGraphics.height; self.speed = 0; self.lane = 1; // Center lane self.shielded = false; self.speedBoostActive = false; self.speedBoostTimer = 0; self.shieldTimer = 0; self.shieldVisual = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.shieldVisual.scale.set(1.5, 1.5); self.moveHorizontally = function (deltaX) { self.x += deltaX; // Ensure the player doesn't move out of the road boundaries if (self.x < LANE_POSITIONS[0] - LANE_WIDTH / 2) { self.x = LANE_POSITIONS[0] - LANE_WIDTH / 2; } else if (self.x > LANE_POSITIONS[3] + LANE_WIDTH / 2) { self.x = LANE_POSITIONS[3] + LANE_WIDTH / 2; } }; self.activateShield = function () { self.shielded = true; self.shieldTimer = 5 * 60; // 5 seconds at 60fps tween(self.shieldVisual, { alpha: 0.7 }, { duration: 300 }); }; self.activateSpeedBoost = function () { self.speedBoostActive = true; self.speedBoostTimer = 3 * 60; // 3 seconds at 60fps var boostMultiplier = self.type === 'superSpeedBoost' ? 6 : 1.5; tween(gameSpeed, { value: BASE_GAME_SPEED * boostMultiplier }, { duration: 300 }); }; self.update = function () { if (self.shielded) { self.shieldTimer--; if (self.shieldTimer <= 0) { self.shielded = false; tween(self.shieldVisual, { alpha: 0 }, { duration: 300 }); } } if (self.speedBoostActive) { self.speedBoostTimer--; if (self.speedBoostTimer <= 0) { self.speedBoostActive = false; tween(gameSpeed, { value: BASE_GAME_SPEED }, { duration: 500 }); } } }; return self; }); var RoadSegment = Container.expand(function () { var self = Container.call(this); self.init = function () { self.roadGraphics = self.attachAsset('road', { anchorX: 0.5, anchorY: 0.5 }); self.dividers = []; for (var j = 0; j < 4; j++) { // Create dividers between the 4 lanes for (var i = 0; i < 20; i++) { var divider = self.attachAsset('laneDivider', { anchorX: 0.5, anchorY: 0.5 }); divider.x = LANE_POSITIONS[j] + LANE_WIDTH / 2; divider.y = i * 150; self.dividers.push(divider); } } return self; }; self.update = function () { for (var i = 0; i < self.dividers.length; i++) { var divider = self.dividers[i]; divider.y += gameSpeed.value; // Reset divider position if it's off-screen if (divider.y > 2732) { divider.y = -100; } } }; return self; }); var Vehicle = Container.expand(function () { var self = Container.call(this); self.init = function (type) { self.type = type; var assetType; switch (type) { case 'car1': case 'car2': case 'car3': assetType = type; break; case 'truck': assetType = 'truck'; break; default: assetType = 'car1'; } self.vehicleGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); self.width = self.vehicleGraphics.width; self.height = self.vehicleGraphics.height; self.lane = Math.floor(Math.random() * 4); // Randomly assign one of the 4 lanes self.x = LANE_POSITIONS[self.lane]; self.speed = BASE_VEHICLE_SPEED - Math.random() * 2; return self; }; self.update = function () { self.y += gameSpeed.value - self.speed; // Check if the vehicle is off-screen if (self.y > 2732 + self.height) { self.active = false; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x34495e }); /**** * Game Code ****/ // Constants var BASE_GAME_SPEED = 10; var BASE_VEHICLE_SPEED = 5; var LANE_WIDTH = 600; var LANE_POSITIONS = [512, 1024, 1536, 2048]; // Four lanes evenly spaced across the game width // Game variables var player; var roadSegment; var vehicles = []; var collectibles = []; var gameSpeed = { value: BASE_GAME_SPEED }; var score = 0; var distance = 0; var lastVehicleSpawn = 0; var lastCollectibleSpawn = 0; var spawnRate = 60; // Frames between vehicle spawns var collectibleSpawnRate = 180; // Frames between collectible spawns var difficultyTimer = 0; var difficultyInterval = 1000; // Increase difficulty every 1000 frames // Initialize game elements function initGame() { // Set up road roadSegment = new RoadSegment(); roadSegment.init(); roadSegment.x = 2048 / 2; roadSegment.y = 2732 / 2; game.addChild(roadSegment); // Set up player player = new Player(); player.x = LANE_POSITIONS[1]; // Start in the second lane from the left player.y = 2732 - 300; // Position near the bottom game.addChild(player); // Reset game state vehicles = []; collectibles = []; gameSpeed.value = BASE_GAME_SPEED; score = 0; distance = 0; lastVehicleSpawn = 0; lastCollectibleSpawn = 0; difficultyTimer = 0; spawnRate = 60; collectibleSpawnRate = 180; // Start playing background music LK.playMusic('highway_bgm'); // Update score display LK.setScore(score); updateScoreDisplay(); } function spawnVehicle() { var vehicleTypes = ['car1', 'car2', 'car3', 'truck']; var type = vehicleTypes[Math.floor(Math.random() * vehicleTypes.length)]; var vehicle = new Vehicle(); vehicle.init(type); vehicle.y = -vehicle.height; vehicle.active = true; vehicles.push(vehicle); game.addChild(vehicle); } function spawnCollectible() { var types = ['coin', 'shield', 'speedBoost', 'superSpeedBoost']; var weights = [0.7, 0.1, 0.1, 0.1]; // 70% coins, 10% shields, 10% speed boosts, 10% super speed boosts var rand = Math.random(); var type; if (rand < weights[0]) { type = types[0]; // coin } else if (rand < weights[0] + weights[1]) { type = types[1]; // shield } else if (rand < weights[0] + weights[1] + weights[2]) { type = types[2]; // speedBoost } else { type = types[3]; // superSpeedBoost } var collectible = new Collectible(); collectible.init(type); collectible.y = -collectible.height; collectible.active = true; collectibles.push(collectible); game.addChild(collectible); } function checkCollisions() { // Check vehicle collisions for (var i = 0; i < vehicles.length; i++) { if (vehicles[i].active && player.intersects(vehicles[i])) { if (player.shielded) { // Shield protects from collision player.shielded = false; player.shieldTimer = 0; tween(player.shieldVisual, { alpha: 0 }, { duration: 300 }); // Move the vehicle out of the way tween(vehicles[i], { x: vehicles[i].x + (Math.random() > 0.5 ? 200 : -200) }, { duration: 300, easing: tween.easeOut }); } else { // Collision LK.getSound('crash').play(); // Game over if (score > storage.highScore) { storage.highScore = score; } LK.showGameOver(); return true; } } } // Check collectible collisions for (var j = 0; j < collectibles.length; j++) { if (collectibles[j].active && player.intersects(collectibles[j])) { switch (collectibles[j].type) { case 'coin': score += 10; LK.getSound('coin_collect').play(); break; case 'shield': player.activateShield(); LK.getSound('powerup_collect').play(); break; case 'speedBoost': player.activateSpeedBoost(); LK.getSound('powerup_collect').play(); break; case 'superSpeedBoost': player.activateSpeedBoost(); LK.getSound('powerup_collect').play(); break; } collectibles[j].active = false; collectibles[j].destroy(); collectibles.splice(j, 1); j--; // Update score LK.setScore(score); updateScoreDisplay(); } } return false; } function updateScoreDisplay() { scoreText.setText("SCORE: " + score + "\nHIGH: " + storage.highScore); } function increaseDifficulty() { spawnRate = Math.max(30, spawnRate - 1); gameSpeed.value = Math.min(BASE_GAME_SPEED * 1.5, gameSpeed.value + 0.1); } // Set up UI var scoreText = new Text2("SCORE: 0\nHIGH: " + storage.highScore, { size: 70, fill: 0xFFFFFF }); scoreText.anchor.set(1, 0); LK.gui.topRight.addChild(scoreText); // Display speed on the top left corner var speedText = new Text2("SPEED: " + gameSpeed.value.toFixed(1), { size: 70, fill: 0xFFFFFF }); speedText.anchor.set(0, 0); LK.gui.topLeft.addChild(speedText); // Game controls var touchStartX = 0; var touchStartY = 0; var swipeThreshold = 50; game.down = function (x, y, obj) { touchStartX = x; touchStartY = y; }; game.move = function (x, y, obj) { // Implemented in the up handler for better control }; game.up = function (x, y, obj) { // Move player to the x-coordinate of the click player.x = x; }; // Initialize the game initGame(); // Game update loop game.update = function () { // Update distance/score distance += gameSpeed.value / 60; score = Math.floor(distance) + Math.floor(score); LK.setScore(score); // Update objects roadSegment.update(); player.update(); // Spawn vehicles lastVehicleSpawn++; if (lastVehicleSpawn >= spawnRate) { spawnVehicle(); lastVehicleSpawn = 0; } // Spawn collectibles lastCollectibleSpawn++; if (lastCollectibleSpawn >= collectibleSpawnRate) { spawnCollectible(); lastCollectibleSpawn = 0; } // Update vehicles for (var i = vehicles.length - 1; i >= 0; i--) { if (vehicles[i].active) { vehicles[i].update(); // Remove if inactive if (!vehicles[i].active) { vehicles[i].destroy(); vehicles.splice(i, 1); } } } // Update collectibles for (var j = collectibles.length - 1; j >= 0; j--) { if (collectibles[j].active) { collectibles[j].update(); // Remove if inactive if (!collectibles[j].active) { collectibles[j].destroy(); collectibles.splice(j, 1); } } } // Check collisions if (checkCollisions()) { return; // Game over, stop updating } // Increase difficulty over time difficultyTimer++; if (difficultyTimer >= difficultyInterval) { increaseDifficulty(); difficultyTimer = 0; } // Update the score display periodically if (LK.ticks % 10 === 0) { updateScoreDisplay(); speedText.setText("SPEED: " + gameSpeed.value.toFixed(1)); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Collectible = Container.expand(function () {
var self = Container.call(this);
self.init = function (type) {
self.type = type;
var assetType;
switch (type) {
case 'coin':
assetType = 'coin';
break;
case 'shield':
assetType = 'shield';
break;
case 'speedBoost':
assetType = 'speedBoost';
break;
case 'superSpeedBoost':
assetType = 'speedBoost';
break;
default:
assetType = 'coin';
}
self.collectibleGraphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.collectibleGraphics.width;
self.height = self.collectibleGraphics.height;
self.lane = Math.floor(Math.random() * 4); // Randomly assign one of the 4 lanes
self.x = LANE_POSITIONS[self.lane];
// Animation
self.collectibleGraphics.rotation = 0;
return self;
};
self.update = function () {
self.y += gameSpeed.value;
// Rotate collectible
self.collectibleGraphics.rotation += 0.05;
// Check if the collectible is off-screen
if (self.y > 2732 + self.height) {
self.active = false;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = playerGraphics.width;
self.height = playerGraphics.height;
self.speed = 0;
self.lane = 1; // Center lane
self.shielded = false;
self.speedBoostActive = false;
self.speedBoostTimer = 0;
self.shieldTimer = 0;
self.shieldVisual = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.shieldVisual.scale.set(1.5, 1.5);
self.moveHorizontally = function (deltaX) {
self.x += deltaX;
// Ensure the player doesn't move out of the road boundaries
if (self.x < LANE_POSITIONS[0] - LANE_WIDTH / 2) {
self.x = LANE_POSITIONS[0] - LANE_WIDTH / 2;
} else if (self.x > LANE_POSITIONS[3] + LANE_WIDTH / 2) {
self.x = LANE_POSITIONS[3] + LANE_WIDTH / 2;
}
};
self.activateShield = function () {
self.shielded = true;
self.shieldTimer = 5 * 60; // 5 seconds at 60fps
tween(self.shieldVisual, {
alpha: 0.7
}, {
duration: 300
});
};
self.activateSpeedBoost = function () {
self.speedBoostActive = true;
self.speedBoostTimer = 3 * 60; // 3 seconds at 60fps
var boostMultiplier = self.type === 'superSpeedBoost' ? 6 : 1.5;
tween(gameSpeed, {
value: BASE_GAME_SPEED * boostMultiplier
}, {
duration: 300
});
};
self.update = function () {
if (self.shielded) {
self.shieldTimer--;
if (self.shieldTimer <= 0) {
self.shielded = false;
tween(self.shieldVisual, {
alpha: 0
}, {
duration: 300
});
}
}
if (self.speedBoostActive) {
self.speedBoostTimer--;
if (self.speedBoostTimer <= 0) {
self.speedBoostActive = false;
tween(gameSpeed, {
value: BASE_GAME_SPEED
}, {
duration: 500
});
}
}
};
return self;
});
var RoadSegment = Container.expand(function () {
var self = Container.call(this);
self.init = function () {
self.roadGraphics = self.attachAsset('road', {
anchorX: 0.5,
anchorY: 0.5
});
self.dividers = [];
for (var j = 0; j < 4; j++) {
// Create dividers between the 4 lanes
for (var i = 0; i < 20; i++) {
var divider = self.attachAsset('laneDivider', {
anchorX: 0.5,
anchorY: 0.5
});
divider.x = LANE_POSITIONS[j] + LANE_WIDTH / 2;
divider.y = i * 150;
self.dividers.push(divider);
}
}
return self;
};
self.update = function () {
for (var i = 0; i < self.dividers.length; i++) {
var divider = self.dividers[i];
divider.y += gameSpeed.value;
// Reset divider position if it's off-screen
if (divider.y > 2732) {
divider.y = -100;
}
}
};
return self;
});
var Vehicle = Container.expand(function () {
var self = Container.call(this);
self.init = function (type) {
self.type = type;
var assetType;
switch (type) {
case 'car1':
case 'car2':
case 'car3':
assetType = type;
break;
case 'truck':
assetType = 'truck';
break;
default:
assetType = 'car1';
}
self.vehicleGraphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = self.vehicleGraphics.width;
self.height = self.vehicleGraphics.height;
self.lane = Math.floor(Math.random() * 4); // Randomly assign one of the 4 lanes
self.x = LANE_POSITIONS[self.lane];
self.speed = BASE_VEHICLE_SPEED - Math.random() * 2;
return self;
};
self.update = function () {
self.y += gameSpeed.value - self.speed;
// Check if the vehicle is off-screen
if (self.y > 2732 + self.height) {
self.active = false;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
// Constants
var BASE_GAME_SPEED = 10;
var BASE_VEHICLE_SPEED = 5;
var LANE_WIDTH = 600;
var LANE_POSITIONS = [512, 1024, 1536, 2048]; // Four lanes evenly spaced across the game width
// Game variables
var player;
var roadSegment;
var vehicles = [];
var collectibles = [];
var gameSpeed = {
value: BASE_GAME_SPEED
};
var score = 0;
var distance = 0;
var lastVehicleSpawn = 0;
var lastCollectibleSpawn = 0;
var spawnRate = 60; // Frames between vehicle spawns
var collectibleSpawnRate = 180; // Frames between collectible spawns
var difficultyTimer = 0;
var difficultyInterval = 1000; // Increase difficulty every 1000 frames
// Initialize game elements
function initGame() {
// Set up road
roadSegment = new RoadSegment();
roadSegment.init();
roadSegment.x = 2048 / 2;
roadSegment.y = 2732 / 2;
game.addChild(roadSegment);
// Set up player
player = new Player();
player.x = LANE_POSITIONS[1]; // Start in the second lane from the left
player.y = 2732 - 300; // Position near the bottom
game.addChild(player);
// Reset game state
vehicles = [];
collectibles = [];
gameSpeed.value = BASE_GAME_SPEED;
score = 0;
distance = 0;
lastVehicleSpawn = 0;
lastCollectibleSpawn = 0;
difficultyTimer = 0;
spawnRate = 60;
collectibleSpawnRate = 180;
// Start playing background music
LK.playMusic('highway_bgm');
// Update score display
LK.setScore(score);
updateScoreDisplay();
}
function spawnVehicle() {
var vehicleTypes = ['car1', 'car2', 'car3', 'truck'];
var type = vehicleTypes[Math.floor(Math.random() * vehicleTypes.length)];
var vehicle = new Vehicle();
vehicle.init(type);
vehicle.y = -vehicle.height;
vehicle.active = true;
vehicles.push(vehicle);
game.addChild(vehicle);
}
function spawnCollectible() {
var types = ['coin', 'shield', 'speedBoost', 'superSpeedBoost'];
var weights = [0.7, 0.1, 0.1, 0.1]; // 70% coins, 10% shields, 10% speed boosts, 10% super speed boosts
var rand = Math.random();
var type;
if (rand < weights[0]) {
type = types[0]; // coin
} else if (rand < weights[0] + weights[1]) {
type = types[1]; // shield
} else if (rand < weights[0] + weights[1] + weights[2]) {
type = types[2]; // speedBoost
} else {
type = types[3]; // superSpeedBoost
}
var collectible = new Collectible();
collectible.init(type);
collectible.y = -collectible.height;
collectible.active = true;
collectibles.push(collectible);
game.addChild(collectible);
}
function checkCollisions() {
// Check vehicle collisions
for (var i = 0; i < vehicles.length; i++) {
if (vehicles[i].active && player.intersects(vehicles[i])) {
if (player.shielded) {
// Shield protects from collision
player.shielded = false;
player.shieldTimer = 0;
tween(player.shieldVisual, {
alpha: 0
}, {
duration: 300
});
// Move the vehicle out of the way
tween(vehicles[i], {
x: vehicles[i].x + (Math.random() > 0.5 ? 200 : -200)
}, {
duration: 300,
easing: tween.easeOut
});
} else {
// Collision
LK.getSound('crash').play();
// Game over
if (score > storage.highScore) {
storage.highScore = score;
}
LK.showGameOver();
return true;
}
}
}
// Check collectible collisions
for (var j = 0; j < collectibles.length; j++) {
if (collectibles[j].active && player.intersects(collectibles[j])) {
switch (collectibles[j].type) {
case 'coin':
score += 10;
LK.getSound('coin_collect').play();
break;
case 'shield':
player.activateShield();
LK.getSound('powerup_collect').play();
break;
case 'speedBoost':
player.activateSpeedBoost();
LK.getSound('powerup_collect').play();
break;
case 'superSpeedBoost':
player.activateSpeedBoost();
LK.getSound('powerup_collect').play();
break;
}
collectibles[j].active = false;
collectibles[j].destroy();
collectibles.splice(j, 1);
j--;
// Update score
LK.setScore(score);
updateScoreDisplay();
}
}
return false;
}
function updateScoreDisplay() {
scoreText.setText("SCORE: " + score + "\nHIGH: " + storage.highScore);
}
function increaseDifficulty() {
spawnRate = Math.max(30, spawnRate - 1);
gameSpeed.value = Math.min(BASE_GAME_SPEED * 1.5, gameSpeed.value + 0.1);
}
// Set up UI
var scoreText = new Text2("SCORE: 0\nHIGH: " + storage.highScore, {
size: 70,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Display speed on the top left corner
var speedText = new Text2("SPEED: " + gameSpeed.value.toFixed(1), {
size: 70,
fill: 0xFFFFFF
});
speedText.anchor.set(0, 0);
LK.gui.topLeft.addChild(speedText);
// Game controls
var touchStartX = 0;
var touchStartY = 0;
var swipeThreshold = 50;
game.down = function (x, y, obj) {
touchStartX = x;
touchStartY = y;
};
game.move = function (x, y, obj) {
// Implemented in the up handler for better control
};
game.up = function (x, y, obj) {
// Move player to the x-coordinate of the click
player.x = x;
};
// Initialize the game
initGame();
// Game update loop
game.update = function () {
// Update distance/score
distance += gameSpeed.value / 60;
score = Math.floor(distance) + Math.floor(score);
LK.setScore(score);
// Update objects
roadSegment.update();
player.update();
// Spawn vehicles
lastVehicleSpawn++;
if (lastVehicleSpawn >= spawnRate) {
spawnVehicle();
lastVehicleSpawn = 0;
}
// Spawn collectibles
lastCollectibleSpawn++;
if (lastCollectibleSpawn >= collectibleSpawnRate) {
spawnCollectible();
lastCollectibleSpawn = 0;
}
// Update vehicles
for (var i = vehicles.length - 1; i >= 0; i--) {
if (vehicles[i].active) {
vehicles[i].update();
// Remove if inactive
if (!vehicles[i].active) {
vehicles[i].destroy();
vehicles.splice(i, 1);
}
}
}
// Update collectibles
for (var j = collectibles.length - 1; j >= 0; j--) {
if (collectibles[j].active) {
collectibles[j].update();
// Remove if inactive
if (!collectibles[j].active) {
collectibles[j].destroy();
collectibles.splice(j, 1);
}
}
}
// Check collisions
if (checkCollisions()) {
return; // Game over, stop updating
}
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer >= difficultyInterval) {
increaseDifficulty();
difficultyTimer = 0;
}
// Update the score display periodically
if (LK.ticks % 10 === 0) {
updateScoreDisplay();
speedText.setText("SPEED: " + gameSpeed.value.toFixed(1));
}
};