/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.maxSpeed = 8;
self.acceleration = 0.3;
self.deceleration = 0.2;
self.update = function () {
// Apply speed limits
if (self.speed > self.maxSpeed) self.speed = self.maxSpeed;
if (self.speed < -self.maxSpeed) self.speed = -self.maxSpeed;
// Apply deceleration when no input
if (self.speed > 0) {
self.speed -= self.deceleration;
if (self.speed < 0) self.speed = 0;
} else if (self.speed < 0) {
self.speed += self.deceleration;
if (self.speed > 0) self.speed = 0;
}
self.x += self.speed;
// Keep player car within screen bounds
if (self.x < 60) self.x = 60;
if (self.x > 1988) self.x = 1988;
};
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.y += gameSpeed;
};
return self;
});
var TrafficCar = Container.expand(function (carType) {
var self = Container.call(this);
var assetId = carType || 'enemyCar';
var carGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8 + Math.random() * 4;
self.type = carType;
self.update = function () {
self.y += self.speed + gameSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Menu system
var gameState = 'menu'; // 'menu', 'playing', 'tutorial'
var menuContainer = null;
var playerCar = null;
var trafficCars = [];
var roadLines = [];
var gameSpeed = 6;
var spawnTimer = 0;
var lineSpawnTimer = 0;
var speedIncreaseTimer = 0;
var distanceScore = 0;
var nearMissScore = 0;
var lanes = [400, 650, 900, 1150, 1400];
var dragNode = null;
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create speed display
var speedTxt = new Text2('Speed: 6', {
size: 60,
fill: 0xFFFFFF
});
speedTxt.anchor.set(1, 0);
speedTxt.y = 100;
LK.gui.topRight.addChild(speedTxt);
// Create best score display
var bestScore = storage.bestScore || 0;
var bestScoreTxt = new Text2('Best: ' + bestScore, {
size: 60,
fill: 0xFF0000
});
bestScoreTxt.anchor.set(0, 0);
bestScoreTxt.y = 200;
LK.gui.topLeft.addChild(bestScoreTxt);
// Create menu
menuContainer = game.addChild(new Container());
// Menu title
var titleText = new Text2('Highway Dash', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
menuContainer.addChild(titleText);
// Play button
var playButton = new Text2('PLAY', {
size: 80,
fill: 0x00FF00
});
playButton.anchor.set(0.5, 0.5);
playButton.x = 1024;
playButton.y = 1200;
playButton.down = function (x, y, obj) {
startGame();
};
menuContainer.addChild(playButton);
// Tutorial button
var tutorialButton = new Text2('TUTORIAL', {
size: 80,
fill: 0x0099FF
});
tutorialButton.anchor.set(0.5, 0.5);
tutorialButton.x = 1024;
tutorialButton.y = 1400;
tutorialButton.down = function (x, y, obj) {
startTutorial();
};
menuContainer.addChild(tutorialButton);
// Hide game UI initially
scoreTxt.visible = false;
speedTxt.visible = false;
bestScoreTxt.visible = false;
// Setup initial controls
setupGameControls();
function spawnTrafficCar() {
var carType = Math.random() < 0.3 ? 'truck' : 'enemyCar';
var trafficCar = new TrafficCar(carType);
var laneIndex = Math.floor(Math.random() * lanes.length);
trafficCar.x = lanes[laneIndex];
trafficCar.y = -100;
trafficCars.push(trafficCar);
game.addChild(trafficCar);
}
function checkNearMiss(car) {
var distance = Math.sqrt(Math.pow(playerCar.x - car.x, 2) + Math.pow(playerCar.y - car.y, 2));
if (distance < 200 && distance > 120) {
if (!car.nearMissTriggered) {
car.nearMissTriggered = true;
nearMissScore += 10;
LK.getSound('whoosh').play();
// Flash effect for near miss
tween(car, {
tint: 0xffff00
}, {
duration: 100,
onFinish: function onFinish() {
tween(car, {
tint: 0xffffff
}, {
duration: 100
});
}
});
}
}
}
function startGame() {
gameState = 'playing';
menuContainer.visible = false;
scoreTxt.visible = true;
speedTxt.visible = true;
bestScoreTxt.visible = true;
// Reset game variables
trafficCars = [];
roadLines = [];
gameSpeed = 6;
spawnTimer = 0;
lineSpawnTimer = 0;
speedIncreaseTimer = 0;
distanceScore = 0;
nearMissScore = 0;
LK.setScore(0);
// Clear existing traffic cars and road lines
for (var i = 0; i < trafficCars.length; i++) {
trafficCars[i].destroy();
}
for (var j = 0; j < roadLines.length; j++) {
roadLines[j].destroy();
}
trafficCars = [];
roadLines = [];
// Add road background
var roadBackground = game.addChild(LK.getAsset('roadBackground', {
anchorX: 0.5,
anchorY: 0.5
}));
roadBackground.x = 1024;
roadBackground.y = 1366;
// Add road shoulders (grass)
var leftShoulder = game.addChild(LK.getAsset('roadShoulder', {
anchorX: 0.5,
anchorY: 0.5
}));
leftShoulder.x = 100;
leftShoulder.y = 1366;
var rightShoulder = game.addChild(LK.getAsset('roadShoulder', {
anchorX: 0.5,
anchorY: 0.5
}));
rightShoulder.x = 1948;
rightShoulder.y = 1366;
// Initialize player car
if (!playerCar) {
playerCar = game.addChild(new PlayerCar());
}
playerCar.x = 1024;
playerCar.y = 2200;
// Move player car to front to ensure it renders on top of road elements
game.removeChild(playerCar);
game.addChild(playerCar);
// Create initial road lines
for (var i = 0; i < 8; i++) {
for (var lane = 1; lane < lanes.length; lane++) {
var roadLine = new RoadLine();
roadLine.x = lanes[lane] - 75;
roadLine.y = i * 200;
roadLines.push(roadLine);
game.addChild(roadLine);
}
}
}
function startTutorial() {
gameState = 'tutorial';
menuContainer.visible = false;
// Create tutorial container
var tutorialContainer = game.addChild(new Container());
// Tutorial text
var tutorialText = new Text2('How to Play:\n\nDrag left and right to move your car\nAvoid traffic to survive\nScore points by dodging cars\n\nTap anywhere to return to menu', {
size: 60,
fill: 0xFFFFFF
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.x = 1024;
tutorialText.y = 1366;
tutorialContainer.addChild(tutorialText);
// Tutorial tap handler
game.down = function (x, y, obj) {
tutorialContainer.destroy();
gameState = 'menu';
menuContainer.visible = true;
setupGameControls();
};
}
function setupGameControls() {
game.down = function (x, y, obj) {
if (gameState !== 'playing') return;
dragNode = {
lastX: x
};
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
dragNode = null;
};
}
function handleMove(x, y, obj) {
if (dragNode) {
var deltaX = x - dragNode.lastX;
dragNode.lastX = x;
// Move player car based on drag
if (deltaX > 0) {
playerCar.speed += playerCar.acceleration;
} else if (deltaX < 0) {
playerCar.speed -= playerCar.acceleration;
}
}
}
game.move = function (x, y, obj) {
if (gameState === 'playing') {
handleMove(x, y, obj);
}
};
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') return;
// Update distance score
distanceScore += 1;
var totalScore = distanceScore + nearMissScore;
LK.setScore(totalScore);
scoreTxt.setText('Score: ' + totalScore);
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1));
// Increase game speed over time
speedIncreaseTimer++;
if (speedIncreaseTimer > 180) {
// Every 3 seconds at 60fps
gameSpeed += 0.5;
speedIncreaseTimer = 0;
}
// Spawn traffic cars
spawnTimer++;
var spawnRate = Math.max(60 - Math.floor(gameSpeed), 30);
if (spawnTimer > spawnRate) {
spawnTrafficCar();
spawnTimer = 0;
}
// Spawn road lines
lineSpawnTimer++;
if (lineSpawnTimer > 50) {
for (var lane = 1; lane < lanes.length; lane++) {
var roadLine = new RoadLine();
roadLine.x = lanes[lane] - 75;
roadLine.y = -30;
roadLines.push(roadLine);
game.addChild(roadLine);
}
lineSpawnTimer = 0;
// Move player car to front to ensure it stays on top of road lines
if (playerCar) {
game.removeChild(playerCar);
game.addChild(playerCar);
}
}
// Update and check traffic cars
for (var i = trafficCars.length - 1; i >= 0; i--) {
var car = trafficCars[i];
// Check for collision
if (playerCar.intersects(car)) {
// Play crash sound
LK.getSound('crash').play();
// Update best score if current score is higher
var currentScore = distanceScore + nearMissScore;
var bestScore = storage.bestScore || 0;
if (currentScore > bestScore) {
storage.bestScore = currentScore;
// Update best score display in game
bestScoreTxt.setText('Best: ' + currentScore);
}
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check for near miss
checkNearMiss(car);
// Remove cars that are off screen
if (car.y > 2800) {
car.destroy();
trafficCars.splice(i, 1);
}
}
// Update and remove road lines
for (var j = roadLines.length - 1; j >= 0; j--) {
var line = roadLines[j];
if (line.y > 2800) {
line.destroy();
roadLines.splice(j, 1);
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.maxSpeed = 8;
self.acceleration = 0.3;
self.deceleration = 0.2;
self.update = function () {
// Apply speed limits
if (self.speed > self.maxSpeed) self.speed = self.maxSpeed;
if (self.speed < -self.maxSpeed) self.speed = -self.maxSpeed;
// Apply deceleration when no input
if (self.speed > 0) {
self.speed -= self.deceleration;
if (self.speed < 0) self.speed = 0;
} else if (self.speed < 0) {
self.speed += self.deceleration;
if (self.speed > 0) self.speed = 0;
}
self.x += self.speed;
// Keep player car within screen bounds
if (self.x < 60) self.x = 60;
if (self.x > 1988) self.x = 1988;
};
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.y += gameSpeed;
};
return self;
});
var TrafficCar = Container.expand(function (carType) {
var self = Container.call(this);
var assetId = carType || 'enemyCar';
var carGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8 + Math.random() * 4;
self.type = carType;
self.update = function () {
self.y += self.speed + gameSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Menu system
var gameState = 'menu'; // 'menu', 'playing', 'tutorial'
var menuContainer = null;
var playerCar = null;
var trafficCars = [];
var roadLines = [];
var gameSpeed = 6;
var spawnTimer = 0;
var lineSpawnTimer = 0;
var speedIncreaseTimer = 0;
var distanceScore = 0;
var nearMissScore = 0;
var lanes = [400, 650, 900, 1150, 1400];
var dragNode = null;
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create speed display
var speedTxt = new Text2('Speed: 6', {
size: 60,
fill: 0xFFFFFF
});
speedTxt.anchor.set(1, 0);
speedTxt.y = 100;
LK.gui.topRight.addChild(speedTxt);
// Create best score display
var bestScore = storage.bestScore || 0;
var bestScoreTxt = new Text2('Best: ' + bestScore, {
size: 60,
fill: 0xFF0000
});
bestScoreTxt.anchor.set(0, 0);
bestScoreTxt.y = 200;
LK.gui.topLeft.addChild(bestScoreTxt);
// Create menu
menuContainer = game.addChild(new Container());
// Menu title
var titleText = new Text2('Highway Dash', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
menuContainer.addChild(titleText);
// Play button
var playButton = new Text2('PLAY', {
size: 80,
fill: 0x00FF00
});
playButton.anchor.set(0.5, 0.5);
playButton.x = 1024;
playButton.y = 1200;
playButton.down = function (x, y, obj) {
startGame();
};
menuContainer.addChild(playButton);
// Tutorial button
var tutorialButton = new Text2('TUTORIAL', {
size: 80,
fill: 0x0099FF
});
tutorialButton.anchor.set(0.5, 0.5);
tutorialButton.x = 1024;
tutorialButton.y = 1400;
tutorialButton.down = function (x, y, obj) {
startTutorial();
};
menuContainer.addChild(tutorialButton);
// Hide game UI initially
scoreTxt.visible = false;
speedTxt.visible = false;
bestScoreTxt.visible = false;
// Setup initial controls
setupGameControls();
function spawnTrafficCar() {
var carType = Math.random() < 0.3 ? 'truck' : 'enemyCar';
var trafficCar = new TrafficCar(carType);
var laneIndex = Math.floor(Math.random() * lanes.length);
trafficCar.x = lanes[laneIndex];
trafficCar.y = -100;
trafficCars.push(trafficCar);
game.addChild(trafficCar);
}
function checkNearMiss(car) {
var distance = Math.sqrt(Math.pow(playerCar.x - car.x, 2) + Math.pow(playerCar.y - car.y, 2));
if (distance < 200 && distance > 120) {
if (!car.nearMissTriggered) {
car.nearMissTriggered = true;
nearMissScore += 10;
LK.getSound('whoosh').play();
// Flash effect for near miss
tween(car, {
tint: 0xffff00
}, {
duration: 100,
onFinish: function onFinish() {
tween(car, {
tint: 0xffffff
}, {
duration: 100
});
}
});
}
}
}
function startGame() {
gameState = 'playing';
menuContainer.visible = false;
scoreTxt.visible = true;
speedTxt.visible = true;
bestScoreTxt.visible = true;
// Reset game variables
trafficCars = [];
roadLines = [];
gameSpeed = 6;
spawnTimer = 0;
lineSpawnTimer = 0;
speedIncreaseTimer = 0;
distanceScore = 0;
nearMissScore = 0;
LK.setScore(0);
// Clear existing traffic cars and road lines
for (var i = 0; i < trafficCars.length; i++) {
trafficCars[i].destroy();
}
for (var j = 0; j < roadLines.length; j++) {
roadLines[j].destroy();
}
trafficCars = [];
roadLines = [];
// Add road background
var roadBackground = game.addChild(LK.getAsset('roadBackground', {
anchorX: 0.5,
anchorY: 0.5
}));
roadBackground.x = 1024;
roadBackground.y = 1366;
// Add road shoulders (grass)
var leftShoulder = game.addChild(LK.getAsset('roadShoulder', {
anchorX: 0.5,
anchorY: 0.5
}));
leftShoulder.x = 100;
leftShoulder.y = 1366;
var rightShoulder = game.addChild(LK.getAsset('roadShoulder', {
anchorX: 0.5,
anchorY: 0.5
}));
rightShoulder.x = 1948;
rightShoulder.y = 1366;
// Initialize player car
if (!playerCar) {
playerCar = game.addChild(new PlayerCar());
}
playerCar.x = 1024;
playerCar.y = 2200;
// Move player car to front to ensure it renders on top of road elements
game.removeChild(playerCar);
game.addChild(playerCar);
// Create initial road lines
for (var i = 0; i < 8; i++) {
for (var lane = 1; lane < lanes.length; lane++) {
var roadLine = new RoadLine();
roadLine.x = lanes[lane] - 75;
roadLine.y = i * 200;
roadLines.push(roadLine);
game.addChild(roadLine);
}
}
}
function startTutorial() {
gameState = 'tutorial';
menuContainer.visible = false;
// Create tutorial container
var tutorialContainer = game.addChild(new Container());
// Tutorial text
var tutorialText = new Text2('How to Play:\n\nDrag left and right to move your car\nAvoid traffic to survive\nScore points by dodging cars\n\nTap anywhere to return to menu', {
size: 60,
fill: 0xFFFFFF
});
tutorialText.anchor.set(0.5, 0.5);
tutorialText.x = 1024;
tutorialText.y = 1366;
tutorialContainer.addChild(tutorialText);
// Tutorial tap handler
game.down = function (x, y, obj) {
tutorialContainer.destroy();
gameState = 'menu';
menuContainer.visible = true;
setupGameControls();
};
}
function setupGameControls() {
game.down = function (x, y, obj) {
if (gameState !== 'playing') return;
dragNode = {
lastX: x
};
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
dragNode = null;
};
}
function handleMove(x, y, obj) {
if (dragNode) {
var deltaX = x - dragNode.lastX;
dragNode.lastX = x;
// Move player car based on drag
if (deltaX > 0) {
playerCar.speed += playerCar.acceleration;
} else if (deltaX < 0) {
playerCar.speed -= playerCar.acceleration;
}
}
}
game.move = function (x, y, obj) {
if (gameState === 'playing') {
handleMove(x, y, obj);
}
};
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') return;
// Update distance score
distanceScore += 1;
var totalScore = distanceScore + nearMissScore;
LK.setScore(totalScore);
scoreTxt.setText('Score: ' + totalScore);
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1));
// Increase game speed over time
speedIncreaseTimer++;
if (speedIncreaseTimer > 180) {
// Every 3 seconds at 60fps
gameSpeed += 0.5;
speedIncreaseTimer = 0;
}
// Spawn traffic cars
spawnTimer++;
var spawnRate = Math.max(60 - Math.floor(gameSpeed), 30);
if (spawnTimer > spawnRate) {
spawnTrafficCar();
spawnTimer = 0;
}
// Spawn road lines
lineSpawnTimer++;
if (lineSpawnTimer > 50) {
for (var lane = 1; lane < lanes.length; lane++) {
var roadLine = new RoadLine();
roadLine.x = lanes[lane] - 75;
roadLine.y = -30;
roadLines.push(roadLine);
game.addChild(roadLine);
}
lineSpawnTimer = 0;
// Move player car to front to ensure it stays on top of road lines
if (playerCar) {
game.removeChild(playerCar);
game.addChild(playerCar);
}
}
// Update and check traffic cars
for (var i = trafficCars.length - 1; i >= 0; i--) {
var car = trafficCars[i];
// Check for collision
if (playerCar.intersects(car)) {
// Play crash sound
LK.getSound('crash').play();
// Update best score if current score is higher
var currentScore = distanceScore + nearMissScore;
var bestScore = storage.bestScore || 0;
if (currentScore > bestScore) {
storage.bestScore = currentScore;
// Update best score display in game
bestScoreTxt.setText('Best: ' + currentScore);
}
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check for near miss
checkNearMiss(car);
// Remove cars that are off screen
if (car.y > 2800) {
car.destroy();
trafficCars.splice(i, 1);
}
}
// Update and remove road lines
for (var j = roadLines.length - 1; j >= 0; j--) {
var line = roadLines[j];
if (line.y > 2800) {
line.destroy();
roadLines.splice(j, 1);
}
}
};