/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
// Make bomb look dangerous with dark red tint and smaller size
bombGraphics.tint = 0x660000;
bombGraphics.scaleX = 0.6;
bombGraphics.scaleY = 0.6;
self.speed = 13.86;
self.targetLane = 1;
self.rotationSpeed = 0.3;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.speed = 13.86 * gameSpeed;
self.y += self.speed;
// Move towards target lane (player's position when thrown)
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
if (Math.abs(diff) > 10) {
self.x += diff * 0.1;
}
// Spinning and pulsing animation for danger effect
bombGraphics.rotation += self.rotationSpeed;
self.pulseScale += self.pulseDirection * 0.05;
if (self.pulseScale > 1.3) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.8) {
self.pulseDirection = 1;
}
bombGraphics.scaleX = 0.6 * self.pulseScale;
bombGraphics.scaleY = 0.6 * self.pulseScale;
};
return self;
});
var Bomber = Container.expand(function () {
var self = Container.call(this);
var bomberGraphics = self.attachAsset('bomberPerson', {
anchorX: 0.5,
anchorY: 0.5
});
// Make bomber distinct with darker brown color and human-like proportions
bomberGraphics.scaleX = 0.8;
bomberGraphics.scaleY = 0.9;
self.speed = 6.93;
self.lane = 0;
self.throwTimer = 0;
self.throwInterval = 120; // Throw bomb every 2 seconds
self.hasThrown = false;
self.update = function () {
var difficultyMultiplier = 1 + distanceTraveled / 10000;
self.speed = 6.93 * gameSpeed * difficultyMultiplier;
self.y += self.speed;
// Throw bomb when close to player
self.throwTimer++;
if (!self.hasThrown && self.throwTimer >= self.throwInterval && self.y > 500 && self.y < 1800) {
self.throwBomb();
self.hasThrown = true;
}
// Add slight bobbing motion
bomberGraphics.rotation = Math.sin(LK.ticks * 0.03) * 0.1;
};
self.throwBomb = function () {
var bomb = game.addChild(new Bomb());
bomb.x = self.x;
bomb.y = self.y + 50;
bomb.targetLane = playerCar.currentLane;
bomb.speed = 13.86 * gameSpeed;
bombs.push(bomb);
};
return self;
});
var Cup = Container.expand(function () {
var self = Container.call(this);
var cupGraphics = self.attachAsset('cup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.15;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
cupGraphics.rotation += self.rotationSpeed;
// Enhanced pulsing effect with sparkle
self.pulseScale += self.pulseDirection * 0.04;
if (self.pulseScale > 1.6) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.8) {
self.pulseDirection = 1;
}
cupGraphics.scaleX = self.pulseScale;
cupGraphics.scaleY = self.pulseScale;
// Enhanced golden effect with sparkle animation
var sparkleIntensity = 0.8 + Math.sin(LK.ticks * 0.15) * 0.2;
cupGraphics.alpha = sparkleIntensity;
// Alternating between bright gold and white for sparkle effect
if (Math.sin(LK.ticks * 0.1) > 0.7) {
cupGraphics.tint = 0xFFFFFF; // Bright white sparkle
} else {
cupGraphics.tint = 0xFFD700; // Rich gold
}
};
return self;
});
var EnemyCar = Container.expand(function (carType) {
var self = Container.call(this);
var assetId = carType || 'enemyCar1';
var carGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.lane = 0;
self.update = function () {
// Progressive speed increase with difficulty
var difficultyMultiplier = 1 + distanceTraveled / 8000; // Enemies get faster over time
self.speed = 9.24 * gameSpeed * difficultyMultiplier * (nitroSpeedMultiplier > 1 ? nitroSpeedMultiplier * 0.7 : 1);
self.y += self.speed;
// Add subtle bobbing motion for visual interest
carGraphics.rotation = Math.sin(LK.ticks * 0.05) * 0.02;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
self.particles = [];
self.lifeTime = 0;
self.maxLifeTime = 60; // 1 second at 60fps
// Create enhanced explosion particles with more variety
for (var i = 0; i < 20; i++) {
var particle = self.addChild(LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2 + Math.random() * 0.4,
scaleY: 0.2 + Math.random() * 0.4
}));
// More vibrant explosion colors
var colors = [0xFF1100, 0xFF4400, 0xFF6600, 0xFF8800, 0xFFAA00, 0xFFCC00, 0xFFFF00, 0xFFFFFF];
particle.tint = colors[Math.floor(Math.random() * colors.length)];
particle.vx = (Math.random() - 0.5) * 30;
particle.vy = (Math.random() - 0.5) * 30;
particle.gravity = 0.3 + Math.random() * 0.4;
particle.friction = 0.92 + Math.random() * 0.06;
particle.rotationSpeed = (Math.random() - 0.5) * 0.3;
self.particles.push(particle);
}
self.update = function () {
self.lifeTime++;
// Update particles with enhanced physics
for (var i = 0; i < self.particles.length; i++) {
var particle = self.particles[i];
particle.x += particle.vx;
particle.y += particle.vy;
particle.vy += particle.gravity;
particle.vx *= particle.friction;
particle.vy *= particle.friction;
// Add rotation to particles
particle.rotation += particle.rotationSpeed;
// Enhanced fade out with size reduction
var fadeProgress = self.lifeTime / self.maxLifeTime;
particle.alpha = 1 - fadeProgress;
particle.scaleX *= 0.98;
particle.scaleY *= 0.98;
// Color intensity decreases over time
if (fadeProgress > 0.5) {
var intensity = 1 - (fadeProgress - 0.5) * 2;
particle.tint = particle.tint & 0xFFFFFF * intensity;
}
}
// Destroy explosion when done
if (self.lifeTime >= self.maxLifeTime) {
self.destroy();
}
};
return self;
});
var Nitro = Container.expand(function () {
var self = Container.call(this);
var nitroGraphics = self.attachAsset('nitro', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.2;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.y += self.speed;
nitroGraphics.rotation += self.rotationSpeed;
// Enhanced pulsing effect with electric blue glow
self.pulseScale += self.pulseDirection * 0.03;
if (self.pulseScale > 1.5) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.7) {
self.pulseDirection = 1;
}
nitroGraphics.scaleX = self.pulseScale;
nitroGraphics.scaleY = self.pulseScale;
// Electric blue glow effect with lightning-like intensity changes
var electricIntensity = 0.6 + Math.sin(LK.ticks * 0.2) * 0.4;
nitroGraphics.alpha = electricIntensity;
// Bright electric blue with occasional white flashes
if (Math.random() < 0.1) {
nitroGraphics.tint = 0xFFFFFF; // White flash
} else {
nitroGraphics.tint = 0x00BFFF; // Electric blue
}
};
return self;
});
var Pedestrian = Container.expand(function () {
var self = Container.call(this);
var pedestrianGraphics = self.attachAsset('pedestrian', {
anchorX: 0.5,
anchorY: 0.5
});
// Make pedestrian look different from bomber with varied appearances
var appearances = [{
tint: 0xFF6B6B,
scaleX: 0.6,
scaleY: 0.9
},
// Red shirt, tall
{
tint: 0x4ECDC4,
scaleX: 0.8,
scaleY: 0.7
},
// Teal shirt, short
{
tint: 0xFFE66D,
scaleX: 0.7,
scaleY: 0.8
},
// Yellow shirt, medium
{
tint: 0xA8E6CF,
scaleX: 0.75,
scaleY: 0.85
},
// Green shirt, medium-tall
{
tint: 0xFF8B94,
scaleX: 0.65,
scaleY: 0.75
},
// Pink shirt, small
{
tint: 0xB4A7D6,
scaleX: 0.9,
scaleY: 0.6
} // Purple shirt, wide
];
var appearance = appearances[Math.floor(Math.random() * appearances.length)];
pedestrianGraphics.tint = appearance.tint;
pedestrianGraphics.scaleX = appearance.scaleX;
pedestrianGraphics.scaleY = appearance.scaleY;
self.speed = 6.93;
self.lane = 0;
self.jumpPhase = 'waiting'; // 'waiting', 'jumping', 'crossing'
self.jumpTimer = 0;
self.jumpInterval = 180; // 3 seconds to decide to jump
self.targetLane = Math.floor(Math.random() * 4); // Target lane to reach
self.crossingSpeed = 3;
self.update = function () {
var difficultyMultiplier = 1 + distanceTraveled / 10000;
self.speed = 6.93 * gameSpeed * difficultyMultiplier;
self.y += self.speed;
// Handle jumping behavior
self.jumpTimer++;
if (self.jumpPhase === 'waiting' && self.jumpTimer >= self.jumpInterval && self.y > 500 && self.y < 1800) {
// Start jumping onto road
self.jumpPhase = 'jumping';
self.jumpTimer = 0;
}
if (self.jumpPhase === 'jumping') {
// Move toward target lane
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
if (Math.abs(diff) > 20) {
self.x += diff * 0.08;
} else {
self.jumpPhase = 'crossing';
}
}
if (self.jumpPhase === 'crossing') {
// Cross the road randomly
if (Math.random() < 0.02) {
self.targetLane = Math.floor(Math.random() * 4);
}
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
self.x += diff * 0.05;
}
// Add walking animation
pedestrianGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.1;
};
return self;
});
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35;
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
// Jump finished
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
// Calculate jump arc (parabolic motion)
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
// Add rotation during jump
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar2 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar2', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.42; // Much faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.25;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.35
}, {
duration: 180,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 280,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar3 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar3', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.38; // Faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.15;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.25
}, {
duration: 220,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 320,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar4 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar4', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35; // Standard lane switching speed like other cars
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; // Standard jump height
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar5 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar5', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.75; // Much faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.3;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.4
}, {
duration: 160,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 250,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar6 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar6', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35; // Standard lane switching speed like PlayerCar
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; // Standard jump height
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.1;
self.update = function () {
self.speed = 9.24 * gameSpeed * (nitroSpeedMultiplier > 1 ? nitroSpeedMultiplier * 0.8 : 1);
self.y += self.speed;
powerUpGraphics.rotation += self.rotationSpeed;
// Enhanced visual effects with glow pulsing
var glowIntensity = 0.7 + Math.sin(LK.ticks * 0.1) * 0.3;
powerUpGraphics.alpha = glowIntensity;
// Add rainbow tint cycling for more appealing visuals
var hue = LK.ticks * 0.05 % (Math.PI * 2);
var r = Math.floor(Math.sin(hue) * 127 + 128);
var g = Math.floor(Math.sin(hue + Math.PI * 2 / 3) * 127 + 128);
var b = Math.floor(Math.sin(hue + Math.PI * 4 / 3) * 127 + 128);
powerUpGraphics.tint = r << 16 | g << 8 | b;
};
return self;
});
var Ramp = Container.expand(function () {
var self = Container.call(this);
// Create ramp visual using multiple road line assets
var rampBase = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 2
});
rampBase.tint = 0x888888;
var rampTop = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 1,
y: -20
});
rampTop.tint = 0xAAAAA;
self.speed = 9.24;
self.lane = 0;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
// Add slight glow effect
rampBase.alpha = 0.8 + Math.sin(LK.ticks * 0.1) * 0.2;
};
return self;
});
var RoadLine = Container.expand(function () {
var self = Container.call(this);
var lineGraphics = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
// Game state management
var gameState = 'splash'; // 'splash', 'menu', 'playing', 'gameOver'
var menuElements = [];
var bestDistance = 0;
// Load best score from storage
function loadBestScore() {
var saved = storage.bestDistance;
if (saved !== undefined) {
bestDistance = saved;
}
}
// Save best score to storage
function saveBestScore() {
storage.bestDistance = bestDistance;
}
// Start menu creation
function createStartMenu() {
// Simple road background - just a few lines for context
for (var i = 0; i < 8; i++) {
for (var lane = 0; lane < 4; lane++) {
var menuLine = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 624 + lane * 400,
y: i * 250 + 300
});
menuLine.alpha = 0.2;
game.addChild(menuLine);
menuElements.push(menuLine);
}
}
// Clean title - big and centered
var titleText = new Text2('HIGHWAY RUSH', {
size: 160,
fill: '#FFD700',
stroke: '#000000',
strokeThickness: 6
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
game.addChild(titleText);
menuElements.push(titleText);
// Best score display - simple and clear
var bestScoreText = new Text2('Best: ' + bestDistance + 'm', {
size: 70,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 4
});
bestScoreText.anchor.set(0.5, 0.5);
bestScoreText.x = 1024;
bestScoreText.y = 750;
game.addChild(bestScoreText);
menuElements.push(bestScoreText);
// Car selection section - clean and organized
var carSelectionText = new Text2('Choose Car:', {
size: 60,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 3
});
carSelectionText.anchor.set(0.5, 0.5);
carSelectionText.x = 1024;
carSelectionText.y = 950;
game.addChild(carSelectionText);
menuElements.push(carSelectionText);
// Car selection buttons - properly centered for mobile
var car1Button = LK.getAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5,
x: 341,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car1Button);
menuElements.push(car1Button);
var car2Button = LK.getAsset('playerCar2', {
anchorX: 0.5,
anchorY: 0.5,
x: 574,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car2Button);
menuElements.push(car2Button);
var car3Button = LK.getAsset('playerCar3', {
anchorX: 0.5,
anchorY: 0.5,
x: 807,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car3Button);
menuElements.push(car3Button);
// Add playerCar4 button
var car4Button = LK.getAsset('playerCar4', {
anchorX: 0.5,
anchorY: 0.5,
x: 1040,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car4Button);
menuElements.push(car4Button);
// Add playerCar5 button
var car5Button = LK.getAsset('playerCar5', {
anchorX: 0.5,
anchorY: 0.5,
x: 1273,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car5Button);
menuElements.push(car5Button);
// Add playerCar6 button
var car6Button = LK.getAsset('playerCar6', {
anchorX: 0.5,
anchorY: 0.5,
x: 1506,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car6Button);
menuElements.push(car6Button);
// Selection indicator
selectionIndicator = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 0.6,
x: selectedCarType === 0 ? 341 : selectedCarType === 1 ? 574 : selectedCarType === 2 ? 807 : selectedCarType === 3 ? 1040 : selectedCarType === 4 ? 1273 : 1506,
y: 1280
});
selectionIndicator.tint = 0xFFD700;
game.addChild(selectionIndicator);
menuElements.push(selectionIndicator);
// Instructions - simple and clear
var instructionsText = new Text2('Swipe to change lanes • Avoid traffic • Collect power-ups', {
size: 50,
fill: '#CCCCCC',
stroke: '#000000',
strokeThickness: 2
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 1450;
game.addChild(instructionsText);
menuElements.push(instructionsText);
// Simple START BUTTON at bottom
var startButton = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 4,
x: 1024,
y: 2200
});
startButton.tint = 0x00BB00;
game.addChild(startButton);
menuElements.push(startButton);
// START text
var startButtonText = new Text2('START GAME', {
size: 120,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 6
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = 1024;
startButtonText.y = 2200;
game.addChild(startButtonText);
menuElements.push(startButtonText);
// Stats Chart button removed
// Store button references for animations
var buttonElements = {
button: startButton,
text: startButtonText
};
// Initialize selection visual state
updateCarSelection();
// Start menu music
LK.playMusic('menumusic', {
volume: 0.7
});
// Stylish fluid animations with enhanced effects
// Title pulsing with glow effect
tween(titleText, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 1800,
yoyo: true,
repeat: 50,
easing: tween.easeInOut
});
// Add floating animation to title
tween(titleText, {
y: 580
}, {
duration: 3000,
yoyo: true,
repeat: 30,
easing: tween.easeInOut
});
// Remove swinging animation - title stays in center position
// Car selection buttons - keep cars stationary (no movement animations)
// Cars will remain in their fixed positions without floating or rotation effects
// Enhanced button animations with elastic effect
tween(buttonElements.button, {
scaleX: 22,
scaleY: 3.5
}, {
duration: 2000,
yoyo: true,
repeat: 50,
easing: tween.elasticInOut
});
tween(buttonElements.text, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 2000,
yoyo: true,
repeat: 50,
easing: tween.bounceInOut
});
// Add color transition to start button
tween(buttonElements.button, {
tint: 0x00FF00
}, {
duration: 1000,
yoyo: true,
repeat: 100,
easing: tween.easeInOut
});
// Stats button animations removed
}
function removeStartMenu() {
// Stop all ongoing tweens to prevent memory leaks and performance issues
for (var i = 0; i < menuElements.length; i++) {
tween.stop(menuElements[i]); // Stop all tweens on this element
menuElements[i].destroy();
}
menuElements = [];
}
function startGame() {
gameState = 'playing';
// Stop all menu tweens before removing menu
if (menuElements.length > 0) {
for (var i = 0; i < menuElements.length; i++) {
tween.stop(menuElements[i]);
}
}
removeStartMenu();
loadBestScore();
initializeGameplay();
// Reset tap counter after starting game
car1TapCount = 0;
car2TapCount = 0;
car3TapCount = 0;
car6TapCount = 0;
// Initialize combo system for new game
comboCount = 0;
comboMultiplier = 1;
lastComboTime = 0;
// Statistics updates removed
}
// Camera shake system
var cameraShake = {
intensity: 0,
duration: 0,
originalX: 0,
originalY: 0
};
function addCameraShake(intensity, duration) {
if (cameraShake.intensity < intensity) {
cameraShake.intensity = intensity;
cameraShake.duration = duration;
cameraShake.originalX = game.x;
cameraShake.originalY = game.y;
}
}
function updateCameraShake() {
if (cameraShake.duration > 0) {
var shakeX = (Math.random() - 0.5) * cameraShake.intensity;
var shakeY = (Math.random() - 0.5) * cameraShake.intensity;
game.x = cameraShake.originalX + shakeX;
game.y = cameraShake.originalY + shakeY;
cameraShake.duration--;
cameraShake.intensity *= 0.95; // Fade out shake
if (cameraShake.duration <= 0) {
game.x = cameraShake.originalX;
game.y = cameraShake.originalY;
cameraShake.intensity = 0;
}
}
}
function initializeGameplay() {
// Initialize all game variables
gameSpeed = 1;
baseGameSpeed = 1;
gasPressed = false;
gasAcceleration = 1;
// Reset combo system variables
comboCount = 0;
comboMultiplier = 1;
lastComboTime = 0;
spawnTimer = 0;
spawnRate = 120;
lineSpawnTimer = 0;
powerUpSpawnTimer = 0;
nitroSpawnTimer = 0;
cupSpawnTimer = 0;
bomberSpawnTimer = 0;
rampSpawnTimer = 0;
pedestrianSpawnTimer = 0;
playerJumping = false;
jumpStartTime = 0;
jumpHeight = 0;
// Check if car1 was tapped 10 times for secret unlock
if (selectedCarType === 0 && car1TapCount >= 10) {
distanceTraveled = 2000;
gameSpeed = 1 + distanceTraveled / 7000 + Math.pow(distanceTraveled / 15000, 1.5);
gameSpeed = Math.min(gameSpeed, 4);
// Flash screen to indicate secret unlock
LK.effects.flashScreen(0x00ff00, 500);
} else if (selectedCarType === 1 && car2TapCount >= 10) {
// Trophy road mode - start with lots of trophies
distanceTraveled = 0;
// Flash screen golden to indicate trophy road
LK.effects.flashScreen(0xFFD700, 1000);
// Set flag for trophy road mode
trophyRoadMode = true;
} else if (selectedCarType === 5 && car6TapCount >= 31) {
// PlayerCar6 ultra speed mode - 11x faster than normal
distanceTraveled = 0;
gameSpeed = 11; // 11 times faster than normal
// Flash screen with bright cyan to indicate ultra speed
LK.effects.flashScreen(0x00FFFF, 1500);
// Add pulsing effect to player car for ultra speed mode
tween(playerCar, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
yoyo: true,
repeat: 3,
easing: tween.easeInOut
});
} else {
distanceTraveled = 0;
}
nitroEffect = false;
nitroEndTime = 0;
hasShield = false;
trophyRoadMode = false;
rapModeActive = false;
rapModeTimer = 0;
playerCar4Unlocked = true;
fastMusicPlaying = false;
// Reset score
LK.setScore(0);
// Add enhanced road background
var roadBackground = game.addChild(LK.getAsset('roadCenter', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
roadBackground.alpha = 0.8;
// Add road side markers
var leftSide = game.addChild(LK.getAsset('roadSide', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 1366
}));
var rightSide = game.addChild(LK.getAsset('roadSide', {
anchorX: 0.5,
anchorY: 0.5,
x: 1848,
y: 1366
}));
// Update UI texts with English
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
bestScoreTxt.setText('Best: ' + bestDistance);
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x');
// Add combo display
comboTxt = new Text2('', {
size: 70,
fill: '#FF6B00',
stroke: '#000000',
strokeThickness: 3
});
comboTxt.anchor.set(0.5, 0);
comboTxt.y = 160;
LK.gui.top.addChild(comboTxt);
// Reinitialize player car to ensure it's properly set up
initializePlayerCar();
// Gas pedal completely removed from play - no longer visible or interactive
gasButton = null; // Remove gas button reference
// Stop menu music and start gameplay music
LK.stopMusic();
LK.playMusic('bgmusic', {
volume: 0.7
});
}
// Initialize best score system
loadBestScore();
// Define combo system variables
var comboTimeWindow = 180; // 3 seconds at 60fps for combo window
var comboCount = 0;
var comboMultiplier = 1;
var lastComboTime = 0;
var comboTxt;
// Player statistics system removed
// Chart display system removed
// Achievement system
var achievements = {
speedDemon: storage.achievementSpeedDemon || false,
// Reach 3x speed
jumpMaster: storage.achievementJumpMaster || false,
// Jump 50 times
collector: storage.achievementCollector || false,
// Collect 100 power-ups
survivor: storage.achievementSurvivor || false,
// Travel 10000m in one game
nitroAddict: storage.achievementNitroAddict || false // Collect 25 nitros
};
function saveAchievements() {
storage.achievementSpeedDemon = achievements.speedDemon;
storage.achievementJumpMaster = achievements.jumpMaster;
storage.achievementCollector = achievements.collector;
storage.achievementSurvivor = achievements.survivor;
storage.achievementNitroAddict = achievements.nitroAddict;
}
function checkAchievements() {
// Speed Demon achievement
if (!achievements.speedDemon && gameSpeed >= 3.0) {
achievements.speedDemon = true;
showAchievement("SPEED DEMON!", "Reached 3x speed!");
saveAchievements();
}
// Jump Master achievement - removed since playerStats no longer exists
// Collector achievement - removed since playerStats no longer exists
// Survivor achievement
if (!achievements.survivor && distanceTraveled >= 10000) {
achievements.survivor = true;
showAchievement("SURVIVOR!", "Traveled 10,000m!");
saveAchievements();
}
// Nitro Addict achievement - removed since playerStats no longer exists
}
function showAchievement(title, description) {
var achievementBg = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 4,
x: 1024,
y: 400
});
achievementBg.tint = 0xFFD700;
achievementBg.alpha = 0;
game.addChild(achievementBg);
var achievementTitle = new Text2(title, {
size: 80,
fill: '#000000',
stroke: '#FFFFFF',
strokeThickness: 3
});
achievementTitle.anchor.set(0.5, 0.5);
achievementTitle.x = 1024;
achievementTitle.y = 370;
achievementTitle.alpha = 0;
game.addChild(achievementTitle);
var achievementDesc = new Text2(description, {
size: 50,
fill: '#000000',
stroke: '#FFFFFF',
strokeThickness: 2
});
achievementDesc.anchor.set(0.5, 0.5);
achievementDesc.x = 1024;
achievementDesc.y = 430;
achievementDesc.alpha = 0;
game.addChild(achievementDesc);
// Animate achievement popup
tween(achievementBg, {
alpha: 0.9
}, {
duration: 500,
easing: tween.easeOut
});
tween(achievementTitle, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(achievementDesc, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Auto-hide after 3 seconds
LK.setTimeout(function () {
tween(achievementBg, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementBg.destroy();
}
});
tween(achievementTitle, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementTitle.destroy();
}
});
tween(achievementDesc, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementDesc.destroy();
}
});
}, 3000);
LK.effects.flashScreen(0xFFD700, 800);
}
// Show KEMALDEV splash screen first
function showKemaldevSplash() {
// Set game state to splash to prevent other interactions
gameState = 'splash';
// Create black background covering full screen
var splashBg = LK.getAsset('roadCenter', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 2,
scaleY: 2,
tint: 0x000000
});
game.addChild(splashBg);
// Create KEMALDEV text
var kemaldevText = new Text2('KEMALDEV', {
size: 200,
fill: '#FFFFFF',
stroke: '#FFD700',
strokeThickness: 8
});
kemaldevText.anchor.set(0.5, 0.5);
kemaldevText.x = 1024;
kemaldevText.y = 1366;
kemaldevText.alpha = 0;
game.addChild(kemaldevText);
// Fade in animation
tween(kemaldevText, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
// Add pulsing effect
tween(kemaldevText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1000,
yoyo: true,
repeat: 2,
easing: tween.easeInOut
});
// Hide after 3 seconds and show main menu
LK.setTimeout(function () {
tween(kemaldevText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
kemaldevText.destroy();
splashBg.destroy();
gameState = 'menu';
createStartMenu();
}
});
}, 3000);
}
// Show KEMALDEV splash screen first, then create start menu
showKemaldevSplash();
// Car selection variable
var selectedCarType = 0; // 0 for PlayerCar, 1 for PlayerCar2, 2 for PlayerCar3
var playerCar;
var selectionIndicator;
var car1TapCount = 0; // Track taps on playercar1 for secret unlock
var car2TapCount = 0; // Track taps on playercar2 for trophy road
var car3TapCount = 0; // Track taps on playercar3 for secret message
var car6TapCount = 0; // Track taps on playercar6 for speed boost
// Update car selection visual state
function updateCarSelection() {
if (selectionIndicator) {
var targetX = selectedCarType === 0 ? 341 : selectedCarType === 1 ? 574 : selectedCarType === 2 ? 807 : selectedCarType === 3 ? 1040 : selectedCarType === 4 ? 1273 : 1506;
// Smooth fluid transition for selection indicator
tween(selectionIndicator, {
x: targetX
}, {
duration: 400,
easing: tween.elasticOut
});
// Add selection pulse effect
tween(selectionIndicator, {
scaleY: 1.2,
tint: 0xFFD700
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(selectionIndicator, {
scaleY: 0.6,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
}
// Check if car 3 is unlocked
var car3Unlocked = bestDistance >= 2000;
// Update car button tints if they exist
if (menuElements.length > 0) {
for (var i = 0; i < menuElements.length; i++) {
var element = menuElements[i];
if (element.x === 624 && element.y === 1650) {
element.tint = selectedCarType === 0 ? 0xFFD700 : 0xFFFFFF;
} else if (element.x === 1024 && element.y === 1650) {
element.tint = selectedCarType === 1 ? 0xFFD700 : 0xFFFFFF;
} else if (element.x === 1424 && element.y === 1650) {
if (car3Unlocked) {
element.tint = selectedCarType === 2 ? 0xFFD700 : 0xFFFFFF;
} else {
element.tint = 0x666666; // Gray out locked car
element.alpha = 0.5;
}
}
}
}
}
// Initialize player car based on selection
function initializePlayerCar() {
if (playerCar) {
playerCar.destroy();
}
if (selectedCarType === 0) {
playerCar = game.addChild(new PlayerCar());
} else if (selectedCarType === 1) {
playerCar = game.addChild(new PlayerCar2());
} else if (selectedCarType === 2) {
playerCar = game.addChild(new PlayerCar3());
} else if (selectedCarType === 3) {
playerCar = game.addChild(new PlayerCar4());
} else if (selectedCarType === 4) {
playerCar = game.addChild(new PlayerCar5());
} else if (selectedCarType === 5) {
playerCar = game.addChild(new PlayerCar6());
}
playerCar.x = 324 + 400; // Lane 1
playerCar.y = 2200;
}
// Initialize the first car
initializePlayerCar();
var enemyCars = [];
var powerUps = [];
var roadLines = [];
var nitros = [];
var cups = [];
var bombers = [];
var bombs = [];
var ramps = [];
var pedestrians = [];
var playerJumping = false;
var jumpStartTime = 0;
var jumpDuration = 60; // 1 second at 60fps
var jumpHeight = 0;
var gameSpeed = 1;
var spawnTimer = 0;
var spawnRate = 120;
var lineSpawnTimer = 0;
var powerUpSpawnTimer = 0;
var nitroSpawnTimer = 0;
var cupSpawnTimer = 0;
var bomberSpawnTimer = 0;
var rampSpawnTimer = 0;
var pedestrianSpawnTimer = 0;
var distanceTraveled = 0;
var nitroEffect = false;
var nitroEndTime = 0;
var nitroSpeedMultiplier = 1;
var nitroAcceleration = 1;
var hasShield = false;
var gasPressed = false;
var baseGameSpeed = 1;
var gasAcceleration = 1;
var maxGasMultiplier = 2.5;
var gasDecelerationRate = 0.98;
var gasAccelerationRate = 1.05;
var trophyRoadMode = false;
var rapModeActive = false;
var rapModeTimer = 0;
var rapModeCheckInterval = 600; // Check every 10 seconds (600 ticks at 60fps)
var playerCar4Unlocked = true;
// Create initial road lines
for (var i = 0; i < 20; i++) {
for (var lane = 0; lane < 4; lane++) {
var line = game.addChild(new RoadLine());
line.x = 524 + lane * 400; // Between lanes
line.y = i * 150 - 200;
roadLines.push(line);
}
}
// UI Elements
var scoreTxt = new Text2('Distance: 0', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var bestScoreTxt = new Text2('Best: ' + bestDistance, {
size: 60,
fill: 0xFFD700,
stroke: 0x000000,
strokeThickness: 3
});
bestScoreTxt.anchor.set(0.5, 0);
bestScoreTxt.y = 90;
LK.gui.top.addChild(bestScoreTxt);
var speedTxt = new Text2('Speed: 1x', {
size: 60,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 3
});
speedTxt.anchor.set(1, 1);
speedTxt.x = -20;
speedTxt.y = -20;
LK.gui.bottomRight.addChild(speedTxt);
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var touchStartTime = 0;
// Gas button element
var gasButton;
game.down = function (x, y, obj) {
if (gameState === 'splash') {
// Skip splash screen on tap
tween.stop();
LK.clearTimeout();
gameState = 'menu';
// Clean up splash elements
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child) {
child.destroy();
}
}
createStartMenu();
return;
}
if (gameState === 'menu') {
// Check car selection buttons
if (y >= 1050 && y <= 1250) {
if (x >= 241 && x <= 441) {
// Car 1 selected
selectedCarType = 0;
car1TapCount++; // Increment tap counter
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 474 && x <= 674) {
// Car 2 selected
selectedCarType = 1;
car2TapCount++; // Increment tap counter for car2
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 707 && x <= 907) {
// Car 3 selected - check if unlocked
if (bestDistance >= 2000) {
selectedCarType = 2;
car3TapCount++; // Increment tap counter for car3
// Check if tapped 10 times for secret message
if (car3TapCount >= 10) {
// Display "Thank you Yavuz Abi" in score area
scoreTxt.setText('Thank you Yavuz Abi');
// Flash screen to indicate special message
LK.effects.flashScreen(0xFFD700, 1000);
}
updateCarSelection();
initializePlayerCar();
} else {
// Car 3 is locked, flash red to indicate requirement
LK.effects.flashScreen(0xff0000, 300);
}
return;
} else if (x >= 940 && x <= 1140) {
// Car 4 selected - check if unlocked
if (playerCar4Unlocked) {
selectedCarType = 3;
updateCarSelection();
initializePlayerCar();
} else {
// Car 4 is locked, flash purple to indicate requirement
LK.effects.flashScreen(0x9932CC, 300);
}
return;
} else if (x >= 1173 && x <= 1373) {
// Car 5 selected
selectedCarType = 4;
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 1406 && x <= 1606) {
// Car 6 selected
selectedCarType = 5;
car6TapCount++; // Increment tap counter for car6
updateCarSelection();
initializePlayerCar();
return;
}
}
// Stats button interaction removed
// Check for start button tap at bottom - expanded touch area for better UX
if (y >= 2050 && y <= 2350 && x >= 300 && x <= 1748) {
startGame();
return;
}
}
if (gameState === 'playing') {
// Gas button interaction removed - no longer functional
}
touchStartX = x;
touchStartY = y;
touchStartTime = LK.ticks;
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
var touchEndX = x;
var swipeDistance = touchEndX - touchStartX;
var touchDuration = LK.ticks - touchStartTime;
// Gas button release interaction removed - no longer functional
// Detect swipe or tap for lane changing
if (Math.abs(swipeDistance) > 100 && touchDuration < 30) {
// Swipe detected
if (swipeDistance > 0) {
playerCar.switchLane(1); // Swipe right
} else {
playerCar.switchLane(-1); // Swipe left
}
} else if (touchDuration < 15) {
// Gas button area check removed - full screen available for lane changes
if (x > 1024) {
playerCar.switchLane(1); // Right side tap
} else {
playerCar.switchLane(-1); // Left side tap
}
}
};
function spawnEnemyCar() {
var lane = Math.floor(Math.random() * 4);
var enemy;
var carTypes = ['enemyCar1', 'enemyCar2', 'enemyCar3'];
var carType = carTypes[Math.floor(Math.random() * carTypes.length)];
enemy = game.addChild(new EnemyCar(carType));
enemy.x = 324 + lane * 400;
enemy.y = -100;
enemy.lane = lane;
enemy.speed = 9.24 * gameSpeed;
enemyCars.push(enemy);
}
function spawnPowerUp() {
// Reduce spawn chance as difficulty increases
var spawnChance = Math.max(0.1, 0.3 - distanceTraveled / 25000); // Decreases from 30% to 10%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var powerUp = game.addChild(new PowerUp());
powerUp.x = 324 + lane * 400;
powerUp.y = -100;
powerUp.speed = 9.24 * gameSpeed;
powerUps.push(powerUp);
}
}
function spawnNitro() {
// Significantly reduce spawn chance as difficulty increases
var spawnChance = Math.max(0.05, 0.2 - distanceTraveled / 20000); // Decreases from 20% to 5%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var nitro = game.addChild(new Nitro());
nitro.x = 324 + lane * 400;
nitro.y = -100;
nitro.speed = 9.24 * gameSpeed;
nitros.push(nitro);
}
}
function spawnCup() {
// Check if trophy road mode is active
if (trophyRoadMode) {
// In trophy road mode, spawn many cups (trophies)
var spawnChance = 0.8; // Very high spawn chance for trophies
if (Math.random() < spawnChance) {
// Spawn multiple cups across different lanes
for (var trophyLane = 0; trophyLane < 4; trophyLane++) {
if (Math.random() < 0.7) {
// 70% chance per lane
var cup = game.addChild(new Cup());
cup.x = 324 + trophyLane * 400;
cup.y = -100 - trophyLane * 150; // Stagger them vertically
cup.speed = 9.24 * gameSpeed;
cups.push(cup);
}
}
}
} else {
// Normal spawn chance for cups
var spawnChance = Math.max(0.03, 0.15 - distanceTraveled / 30000); // Decreases from 15% to 3%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var cup = game.addChild(new Cup());
cup.x = 324 + lane * 400;
cup.y = -100;
cup.speed = 9.24 * gameSpeed;
cups.push(cup);
}
}
}
function spawnRamp() {
// Spawn ramps occasionally to help player jump over obstacles
var spawnChance = Math.max(0.05, 0.15 - distanceTraveled / 20000); // Decreases from 15% to 5%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var ramp = game.addChild(new Ramp());
ramp.x = 324 + lane * 400;
ramp.y = -100;
ramp.lane = lane;
ramp.speed = 9.24 * gameSpeed;
ramps.push(ramp);
}
}
function spawnPedestrian() {
// Increased spawn chance for pedestrians by 80% more (from 25.92% to 46.66%)
var spawnChance = Math.max(0.1555, 0.4666 - distanceTraveled / 30000); // Decreases from 46.66% to 15.55%
if (Math.random() < spawnChance) {
// Spawn from sides of the road
var startSide = Math.random() < 0.5 ? 0 : 1; // 0 = left, 1 = right
var pedestrian = game.addChild(new Pedestrian());
pedestrian.x = startSide === 0 ? 124 : 1924; // Start from road sides
pedestrian.y = -100;
pedestrian.lane = startSide === 0 ? 0 : 3; // Start lane
pedestrian.speed = 6.93 * gameSpeed;
pedestrians.push(pedestrian);
}
}
function spawnBomber() {
// Moderate spawn chance for bombers
var spawnChance = Math.max(0.08, 0.25 - distanceTraveled / 25000); // Decreases from 25% to 8%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var bomber = game.addChild(new Bomber());
bomber.x = 324 + lane * 400;
bomber.y = -100;
bomber.lane = lane;
bomber.speed = 6.93 * gameSpeed;
bombers.push(bomber);
}
}
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') return;
// Update camera shake
updateCameraShake();
// Update combo system
if (LK.ticks - lastComboTime > comboTimeWindow && comboCount > 0) {
comboCount = 0;
comboMultiplier = 1;
if (comboTxt) {
tween(comboTxt, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
comboTxt.setText('');
comboTxt.alpha = 1;
}
});
}
}
// Player statistics updates removed
// Check achievements
checkAchievements();
// PlayerCar4 is now available from the start - no unlock required
// Check for rap mode activation
rapModeTimer++;
if (rapModeTimer >= rapModeCheckInterval) {
// 80% chance to activate rap mode every 10 seconds - rap appears frequently now!
if (Math.random() < 0.8 && !rapModeActive) {
rapModeActive = true;
// Flash screen with hip-hop colors (purple/gold)
LK.effects.flashScreen(0x9932CC, 800);
// Change UI text to rap style
scoreTxt.setText('Yo Distance: ' + Math.floor(distanceTraveled) + ' meters!');
speedTxt.setText('Speed Flow: ' + gameSpeed.toFixed(1) + 'x');
// Rap mode lasts for 5 seconds
LK.setTimeout(function () {
rapModeActive = false;
// Reset UI text to normal
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x');
LK.effects.flashScreen(0x00FFFF, 400);
}, 5000);
}
rapModeTimer = 0;
}
// Update gas acceleration system with accelerator pedal physics
if (gasPressed) {
// Accelerate when stepping on the gas pedal
gasAcceleration = Math.min(gasAcceleration * gasAccelerationRate, maxGasMultiplier);
// Enhanced visual feedback for stepping on accelerator
if (LK.ticks % 15 === 0) {
LK.effects.flashObject(playerCar, 0xFFFF00, 150);
}
// Add speed lines effect when accelerating hard
if (gasAcceleration > 1.8 && LK.ticks % 8 === 0) {
LK.effects.flashScreen(0x004488, 30);
}
// Pedal vibration effect
if (gasButton && gasAcceleration > 2.0) {
gasButton.x = 1024 + (Math.random() - 0.5) * 4;
gasButton.y = 2500 + (Math.random() - 0.5) * 4;
}
} else {
// Decelerate when lifting foot off gas pedal
gasAcceleration = Math.max(gasAcceleration * gasDecelerationRate, 1);
// Reset pedal position when not pressed
if (gasButton) {
gasButton.x = 1024;
gasButton.y = 2500;
}
}
// Update base game speed with progression - increased by 11%
baseGameSpeed = 1 + distanceTraveled / 7000 + Math.pow(distanceTraveled / 15000, 1.5);
baseGameSpeed = Math.min(baseGameSpeed, 4); // Cap maximum base speed
baseGameSpeed = baseGameSpeed * 1.11; // Increase speed by 11 percent
// Apply gas acceleration to game speed
gameSpeed = baseGameSpeed * gasAcceleration;
// Update distance and speed with accelerated progression and nitro boost
var effectiveSpeed = gameSpeed * nitroSpeedMultiplier * nitroAcceleration;
distanceTraveled += effectiveSpeed;
var lastGameSpeed = gameSpeed;
// Switch to faster music at high speeds (based on base speed to prevent flickering)
if (baseGameSpeed > 2.5 && !fastMusicPlaying) {
LK.playMusic('fastmusic', {
volume: 0.8
});
fastMusicPlaying = true;
} else if (baseGameSpeed <= 2.5 && fastMusicPlaying) {
LK.playMusic('bgmusic', {
volume: 0.7
});
fastMusicPlaying = false;
}
// Update UI text based on rap mode
if (rapModeActive) {
scoreTxt.setText('Yo Distance: ' + Math.floor(distanceTraveled) + ' meters!');
bestScoreTxt.setText('Best Flow: ' + bestDistance);
speedTxt.setText('Speed Flow: ' + gameSpeed.toFixed(1) + 'x' + (gasPressed ? ' ⚡' : ''));
} else {
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
bestScoreTxt.setText('Best: ' + bestDistance);
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x' + (gasPressed ? ' ⚡' : ''));
}
// Add pulsing effect when speed increases
if (gameSpeed > lastGameSpeed + 0.1) {
tween(speedTxt, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(speedTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
// Enhanced continuous nitro visual effects with fluid animations
if (nitroEffect) {
// Dynamic pulsing glow effect during nitro
if (LK.ticks % 8 === 0) {
var glowColor = Math.random() < 0.3 ? 0x00FFFF : Math.random() < 0.6 ? 0xFFFFFF : 0xFF00FF;
LK.effects.flashObject(playerCar, glowColor, 150);
}
// Enhanced speed lines effect with gradient
if (LK.ticks % 4 === 0) {
var speedColor = Math.random() < 0.5 ? 0x0066BB : 0x004488;
LK.effects.flashScreen(speedColor, 30);
}
// Add nitro trail effects with tween
if (LK.ticks % 12 === 0) {
// Create temporary trail effect
var trailEffect = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
x: playerCar.x + (Math.random() - 0.5) * 100,
y: playerCar.y + 50,
tint: 0x00FFFF,
alpha: 0.8
});
game.addChild(trailEffect);
tween(trailEffect, {
alpha: 0,
scaleX: 3,
scaleY: 0.2,
y: trailEffect.y + 200
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
trailEffect.destroy();
}
});
}
}
// Spawn enemies with progressive difficulty
spawnTimer++;
var adjustedSpawnRate = Math.max(30, spawnRate - Math.floor(distanceTraveled / 500)); // More aggressive spawn rate reduction
if (spawnTimer >= adjustedSpawnRate / gameSpeed) {
spawnEnemyCar();
spawnTimer = 0;
// Multiple enemy spawning at higher difficulty
if (distanceTraveled > 5000 && Math.random() < 0.3) {
spawnEnemyCar(); // 30% chance for double spawn after 5000 distance
}
if (distanceTraveled > 10000 && Math.random() < 0.2) {
spawnEnemyCar(); // Additional spawn chance after 10000 distance
}
}
// Spawn power-ups with reduced frequency at higher difficulty
powerUpSpawnTimer++;
var powerUpInterval = Math.max(200, 300 + Math.floor(distanceTraveled / 200)); // Longer intervals as distance increases
if (powerUpSpawnTimer >= powerUpInterval / gameSpeed) {
spawnPowerUp();
powerUpSpawnTimer = 0;
}
// Spawn nitro with increased rarity at higher difficulty
nitroSpawnTimer++;
var nitroInterval = Math.max(400, 600 + Math.floor(distanceTraveled / 150)); // Much longer intervals as distance increases
if (nitroSpawnTimer >= nitroInterval / gameSpeed) {
spawnNitro();
nitroSpawnTimer = 0;
}
// Spawn cups with very rare frequency
cupSpawnTimer++;
var cupInterval = Math.max(800, 1200 + Math.floor(distanceTraveled / 100)); // Very long intervals
if (cupSpawnTimer >= cupInterval / gameSpeed) {
spawnCup();
cupSpawnTimer = 0;
}
// Spawn bombers periodically
bomberSpawnTimer++;
var bomberInterval = Math.max(300, 500 + Math.floor(distanceTraveled / 200)); // Moderate intervals
if (bomberSpawnTimer >= bomberInterval / gameSpeed) {
spawnBomber();
bomberSpawnTimer = 0;
}
// Spawn ramps periodically
rampSpawnTimer++;
var rampInterval = Math.max(600, 800 + Math.floor(distanceTraveled / 300)); // Long intervals for ramps
if (rampSpawnTimer >= rampInterval / gameSpeed) {
spawnRamp();
rampSpawnTimer = 0;
}
// Spawn pedestrians occasionally
pedestrianSpawnTimer++;
var pedestrianInterval = Math.max(700, 1000 + Math.floor(distanceTraveled / 250)); // Moderate intervals
if (pedestrianSpawnTimer >= pedestrianInterval / gameSpeed) {
spawnPedestrian();
pedestrianSpawnTimer = 0;
}
// Check nitro effect end
if (nitroEffect && LK.ticks >= nitroEndTime) {
nitroEffect = false;
// Smooth transition back to normal speed
tween(playerCar, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Reset speed multipliers gradually
tween({
value: nitroSpeedMultiplier
}, {
value: 1
}, {
duration: 800,
easing: tween.easeOut,
onUpdate: function onUpdate(obj) {
nitroSpeedMultiplier = obj.value;
}
});
tween({
value: nitroAcceleration
}, {
value: 1
}, {
duration: 800,
easing: tween.easeOut,
onUpdate: function onUpdate(obj) {
nitroAcceleration = obj.value;
}
});
// Reset player car movement speed
if (playerCar.originalMoveSpeed) {
tween(playerCar, {
moveSpeed: playerCar.originalMoveSpeed
}, {
duration: 500,
easing: tween.easeOut
});
}
// Flash to indicate nitro ending
LK.effects.flashScreen(0xFF4400, 300);
}
// Spawn road lines
lineSpawnTimer++;
if (lineSpawnTimer >= 25) {
for (var lane = 0; lane < 4; lane++) {
var line = game.addChild(new RoadLine());
line.x = 524 + lane * 400;
line.y = -100;
line.speed = 9.24 * gameSpeed * nitroSpeedMultiplier;
roadLines.push(line);
}
lineSpawnTimer = 0;
}
// Update and check power-ups
for (var j = powerUps.length - 1; j >= 0; j--) {
var powerUp = powerUps[j];
// Remove off-screen power-ups
if (powerUp.y > 2800) {
powerUp.destroy();
powerUps.splice(j, 1);
continue;
}
// Check collection
if (powerUp.intersects(playerCar)) {
// Update combo system
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3); // Max 3x multiplier
var baseScore = 50;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
LK.effects.flashObject(powerUp, 0xffffff, 200);
addCameraShake(3, 10);
// Add smooth scale-out effect before destroying
tween(powerUp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
powerUp.destroy();
}
});
powerUps.splice(j, 1);
}
}
// Update and check nitros
for (var n = nitros.length - 1; n >= 0; n--) {
var nitro = nitros[n];
// Remove off-screen nitros
if (nitro.y > 2800) {
nitro.destroy();
nitros.splice(n, 1);
continue;
}
// Check collection
if (nitro.intersects(playerCar)) {
// Statistics update removed
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3);
var baseScore = 100;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1 && comboTxt) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
addCameraShake(8, 20);
// Activate nitro effect with massive speed boost
nitroEffect = true;
nitroEndTime = LK.ticks + 450; // 7.5 seconds at 60fps
// Dramatic speed boost - 3x multiplier
nitroSpeedMultiplier = 3.0;
nitroAcceleration = 2.5;
// Enhanced visual effects for nitro activation
if (playerCar) {
tween(playerCar, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut
});
// Add pulsing effect during nitro
tween(playerCar, {
tint: 0x00FFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(playerCar, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
// Enhanced player car movement speed during nitro
if (playerCar.moveSpeed !== undefined) {
playerCar.originalMoveSpeed = playerCar.moveSpeed;
tween(playerCar, {
moveSpeed: playerCar.moveSpeed * 2.5
}, {
duration: 200,
easing: tween.easeOut
});
}
}
// Screen flash for nitro activation
LK.effects.flashScreen(0x00FFFF, 800);
// Add smooth scale-out effect for nitro
tween(nitro, {
scaleX: 4,
scaleY: 4,
alpha: 0
}, {
duration: 600,
easing: tween.elasticOut,
onFinish: function onFinish() {
nitro.destroy();
}
});
nitros.splice(n, 1);
}
}
// Update and check cups
for (var c = cups.length - 1; c >= 0; c--) {
var cup = cups[c];
// Remove off-screen cups
if (cup.y > 2800) {
cup.destroy();
cups.splice(c, 1);
continue;
}
// Check collection
if (cup.intersects(playerCar)) {
hasShield = true;
// Statistics update removed
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3);
var baseScore = 150;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
addCameraShake(5, 15);
LK.effects.flashScreen(0xFFD700, 400);
// Visual feedback for shield activation
tween(playerCar, {
tint: 0xFFD700
}, {
duration: 200,
onFinish: function onFinish() {
tween(playerCar, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
// Add smooth scale-out effect for cup
tween(cup, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
easing: tween.elasticOut,
onFinish: function onFinish() {
cup.destroy();
}
});
cups.splice(c, 1);
}
}
// Update and check bombers
for (var b = bombers.length - 1; b >= 0; b--) {
var bomber = bombers[b];
// Remove off-screen bombers
if (bomber.y > 2800) {
bomber.destroy();
bombers.splice(b, 1);
continue;
}
// Check collision with player
if (bomber.intersects(playerCar)) {
// Always crush/kill the bomber person on collision
LK.setScore(LK.getScore() + 300);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at bomber position
var explosion = game.addChild(new Explosion());
explosion.x = bomber.x;
explosion.y = bomber.y;
// Destroy the bomber
bomber.destroy();
bombers.splice(b, 1);
continue;
}
}
// Update and check bombs
for (var bomb = bombs.length - 1; bomb >= 0; bomb--) {
var bombObj = bombs[bomb];
// Remove off-screen bombs
if (bombObj.y > 2800) {
bombObj.destroy();
bombs.splice(bomb, 1);
continue;
}
// Check collision with player
if (bombObj.intersects(playerCar)) {
if (hasShield) {
// Player has shield from cup - destroy bomb instead
hasShield = false;
LK.setScore(LK.getScore() + 200);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at bomb position
var explosion = game.addChild(new Explosion());
explosion.x = bombObj.x;
explosion.y = bombObj.y;
// Destroy the bomb
bombObj.destroy();
bombs.splice(bomb, 1);
continue;
} else {
// Normal collision - game over with bigger explosion
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Intense camera shake for crash
addCameraShake(25, 60);
// Create additional explosion for bomb impact
var bombExplosion = game.addChild(new Explosion());
bombExplosion.x = bombObj.x;
bombExplosion.y = bombObj.y;
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
}
}
// Update and check ramps
for (var r = ramps.length - 1; r >= 0; r--) {
var ramp = ramps[r];
// Remove off-screen ramps
if (ramp.y > 2800) {
ramp.destroy();
ramps.splice(r, 1);
continue;
}
// Check if player hits ramp to initiate jump
if (ramp.intersects(playerCar) && !playerJumping) {
playerJumping = true;
jumpStartTime = LK.ticks;
// Statistics update removed
var baseScore = 75;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore); // Bonus for using ramp
LK.getSound('collect').play();
addCameraShake(4, 12);
// Flash effect for ramp activation
LK.effects.flashScreen(0x00AAFF, 300);
// Scale out ramp effect
tween(ramp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
ramp.destroy();
}
});
ramps.splice(r, 1);
continue;
}
}
// Update and check pedestrians
for (var p = pedestrians.length - 1; p >= 0; p--) {
var pedestrian = pedestrians[p];
// Remove off-screen pedestrians
if (pedestrian.y > 2800) {
pedestrian.destroy();
pedestrians.splice(p, 1);
continue;
}
// Check collision with player
if (pedestrian.intersects(playerCar)) {
if (hasShield) {
// Player has shield - save pedestrian and get bonus
hasShield = false;
LK.setScore(LK.getScore() + 250);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create sparkle effect for saving pedestrian
var explosion = game.addChild(new Explosion());
explosion.x = pedestrian.x;
explosion.y = pedestrian.y;
// Destroy the pedestrian (saved)
pedestrian.destroy();
pedestrians.splice(p, 1);
continue;
} else {
// Normal collision - game over
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Heavy camera shake for pedestrian collision
addCameraShake(30, 80);
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
}
}
// Collision detection with enemies - skip if jumping high enough
for (var i = enemyCars.length - 1; i >= 0; i--) {
var enemy = enemyCars[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove off-screen enemies
if (enemy.lastY < 2800 && enemy.y >= 2800) {
enemy.destroy();
enemyCars.splice(i, 1);
continue;
}
// Check collision with player - but not if jumping high enough
if (enemy.intersects(playerCar) && (!playerJumping || jumpHeight < 50)) {
if (hasShield) {
// Player has shield from cup - destroy enemy instead
hasShield = false;
LK.setScore(LK.getScore() + 200);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at enemy position
var explosion = game.addChild(new Explosion());
explosion.x = enemy.x;
explosion.y = enemy.y;
// Destroy the enemy
enemy.destroy();
enemyCars.splice(i, 1);
continue;
} else {
// Normal collision - game over
// Create explosion at collision point
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Strong camera shake for car collision
addCameraShake(20, 50);
// Make player car explode with tween effect
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
// Update best score if needed
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
} else if (playerJumping && jumpHeight >= 50) {
// Player jumped over enemy - bonus points!
if (!enemy.jumpedOver) {
LK.setScore(LK.getScore() + 150);
LK.getSound('dodge').play();
enemy.jumpedOver = true; // Mark to prevent multiple bonuses
}
}
// Check for near miss (score bonus)
var distanceFromPlayer = Math.abs(enemy.x - playerCar.x);
if (enemy.y > playerCar.y - 150 && enemy.y < playerCar.y + 150 && distanceFromPlayer < 200 && distanceFromPlayer > 150) {
if (!enemy.nearMissScored) {
LK.setScore(LK.getScore() + 10);
LK.getSound('dodge').play();
enemy.nearMissScored = true;
}
}
enemy.lastY = enemy.y;
}
// Update road lines
for (var k = roadLines.length - 1; k >= 0; k--) {
var line = roadLines[k];
// Remove off-screen lines
if (line.y > 2800) {
line.destroy();
roadLines.splice(k, 1);
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
// Make bomb look dangerous with dark red tint and smaller size
bombGraphics.tint = 0x660000;
bombGraphics.scaleX = 0.6;
bombGraphics.scaleY = 0.6;
self.speed = 13.86;
self.targetLane = 1;
self.rotationSpeed = 0.3;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.speed = 13.86 * gameSpeed;
self.y += self.speed;
// Move towards target lane (player's position when thrown)
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
if (Math.abs(diff) > 10) {
self.x += diff * 0.1;
}
// Spinning and pulsing animation for danger effect
bombGraphics.rotation += self.rotationSpeed;
self.pulseScale += self.pulseDirection * 0.05;
if (self.pulseScale > 1.3) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.8) {
self.pulseDirection = 1;
}
bombGraphics.scaleX = 0.6 * self.pulseScale;
bombGraphics.scaleY = 0.6 * self.pulseScale;
};
return self;
});
var Bomber = Container.expand(function () {
var self = Container.call(this);
var bomberGraphics = self.attachAsset('bomberPerson', {
anchorX: 0.5,
anchorY: 0.5
});
// Make bomber distinct with darker brown color and human-like proportions
bomberGraphics.scaleX = 0.8;
bomberGraphics.scaleY = 0.9;
self.speed = 6.93;
self.lane = 0;
self.throwTimer = 0;
self.throwInterval = 120; // Throw bomb every 2 seconds
self.hasThrown = false;
self.update = function () {
var difficultyMultiplier = 1 + distanceTraveled / 10000;
self.speed = 6.93 * gameSpeed * difficultyMultiplier;
self.y += self.speed;
// Throw bomb when close to player
self.throwTimer++;
if (!self.hasThrown && self.throwTimer >= self.throwInterval && self.y > 500 && self.y < 1800) {
self.throwBomb();
self.hasThrown = true;
}
// Add slight bobbing motion
bomberGraphics.rotation = Math.sin(LK.ticks * 0.03) * 0.1;
};
self.throwBomb = function () {
var bomb = game.addChild(new Bomb());
bomb.x = self.x;
bomb.y = self.y + 50;
bomb.targetLane = playerCar.currentLane;
bomb.speed = 13.86 * gameSpeed;
bombs.push(bomb);
};
return self;
});
var Cup = Container.expand(function () {
var self = Container.call(this);
var cupGraphics = self.attachAsset('cup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.15;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
cupGraphics.rotation += self.rotationSpeed;
// Enhanced pulsing effect with sparkle
self.pulseScale += self.pulseDirection * 0.04;
if (self.pulseScale > 1.6) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.8) {
self.pulseDirection = 1;
}
cupGraphics.scaleX = self.pulseScale;
cupGraphics.scaleY = self.pulseScale;
// Enhanced golden effect with sparkle animation
var sparkleIntensity = 0.8 + Math.sin(LK.ticks * 0.15) * 0.2;
cupGraphics.alpha = sparkleIntensity;
// Alternating between bright gold and white for sparkle effect
if (Math.sin(LK.ticks * 0.1) > 0.7) {
cupGraphics.tint = 0xFFFFFF; // Bright white sparkle
} else {
cupGraphics.tint = 0xFFD700; // Rich gold
}
};
return self;
});
var EnemyCar = Container.expand(function (carType) {
var self = Container.call(this);
var assetId = carType || 'enemyCar1';
var carGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.lane = 0;
self.update = function () {
// Progressive speed increase with difficulty
var difficultyMultiplier = 1 + distanceTraveled / 8000; // Enemies get faster over time
self.speed = 9.24 * gameSpeed * difficultyMultiplier * (nitroSpeedMultiplier > 1 ? nitroSpeedMultiplier * 0.7 : 1);
self.y += self.speed;
// Add subtle bobbing motion for visual interest
carGraphics.rotation = Math.sin(LK.ticks * 0.05) * 0.02;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
self.particles = [];
self.lifeTime = 0;
self.maxLifeTime = 60; // 1 second at 60fps
// Create enhanced explosion particles with more variety
for (var i = 0; i < 20; i++) {
var particle = self.addChild(LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2 + Math.random() * 0.4,
scaleY: 0.2 + Math.random() * 0.4
}));
// More vibrant explosion colors
var colors = [0xFF1100, 0xFF4400, 0xFF6600, 0xFF8800, 0xFFAA00, 0xFFCC00, 0xFFFF00, 0xFFFFFF];
particle.tint = colors[Math.floor(Math.random() * colors.length)];
particle.vx = (Math.random() - 0.5) * 30;
particle.vy = (Math.random() - 0.5) * 30;
particle.gravity = 0.3 + Math.random() * 0.4;
particle.friction = 0.92 + Math.random() * 0.06;
particle.rotationSpeed = (Math.random() - 0.5) * 0.3;
self.particles.push(particle);
}
self.update = function () {
self.lifeTime++;
// Update particles with enhanced physics
for (var i = 0; i < self.particles.length; i++) {
var particle = self.particles[i];
particle.x += particle.vx;
particle.y += particle.vy;
particle.vy += particle.gravity;
particle.vx *= particle.friction;
particle.vy *= particle.friction;
// Add rotation to particles
particle.rotation += particle.rotationSpeed;
// Enhanced fade out with size reduction
var fadeProgress = self.lifeTime / self.maxLifeTime;
particle.alpha = 1 - fadeProgress;
particle.scaleX *= 0.98;
particle.scaleY *= 0.98;
// Color intensity decreases over time
if (fadeProgress > 0.5) {
var intensity = 1 - (fadeProgress - 0.5) * 2;
particle.tint = particle.tint & 0xFFFFFF * intensity;
}
}
// Destroy explosion when done
if (self.lifeTime >= self.maxLifeTime) {
self.destroy();
}
};
return self;
});
var Nitro = Container.expand(function () {
var self = Container.call(this);
var nitroGraphics = self.attachAsset('nitro', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.2;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.y += self.speed;
nitroGraphics.rotation += self.rotationSpeed;
// Enhanced pulsing effect with electric blue glow
self.pulseScale += self.pulseDirection * 0.03;
if (self.pulseScale > 1.5) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.7) {
self.pulseDirection = 1;
}
nitroGraphics.scaleX = self.pulseScale;
nitroGraphics.scaleY = self.pulseScale;
// Electric blue glow effect with lightning-like intensity changes
var electricIntensity = 0.6 + Math.sin(LK.ticks * 0.2) * 0.4;
nitroGraphics.alpha = electricIntensity;
// Bright electric blue with occasional white flashes
if (Math.random() < 0.1) {
nitroGraphics.tint = 0xFFFFFF; // White flash
} else {
nitroGraphics.tint = 0x00BFFF; // Electric blue
}
};
return self;
});
var Pedestrian = Container.expand(function () {
var self = Container.call(this);
var pedestrianGraphics = self.attachAsset('pedestrian', {
anchorX: 0.5,
anchorY: 0.5
});
// Make pedestrian look different from bomber with varied appearances
var appearances = [{
tint: 0xFF6B6B,
scaleX: 0.6,
scaleY: 0.9
},
// Red shirt, tall
{
tint: 0x4ECDC4,
scaleX: 0.8,
scaleY: 0.7
},
// Teal shirt, short
{
tint: 0xFFE66D,
scaleX: 0.7,
scaleY: 0.8
},
// Yellow shirt, medium
{
tint: 0xA8E6CF,
scaleX: 0.75,
scaleY: 0.85
},
// Green shirt, medium-tall
{
tint: 0xFF8B94,
scaleX: 0.65,
scaleY: 0.75
},
// Pink shirt, small
{
tint: 0xB4A7D6,
scaleX: 0.9,
scaleY: 0.6
} // Purple shirt, wide
];
var appearance = appearances[Math.floor(Math.random() * appearances.length)];
pedestrianGraphics.tint = appearance.tint;
pedestrianGraphics.scaleX = appearance.scaleX;
pedestrianGraphics.scaleY = appearance.scaleY;
self.speed = 6.93;
self.lane = 0;
self.jumpPhase = 'waiting'; // 'waiting', 'jumping', 'crossing'
self.jumpTimer = 0;
self.jumpInterval = 180; // 3 seconds to decide to jump
self.targetLane = Math.floor(Math.random() * 4); // Target lane to reach
self.crossingSpeed = 3;
self.update = function () {
var difficultyMultiplier = 1 + distanceTraveled / 10000;
self.speed = 6.93 * gameSpeed * difficultyMultiplier;
self.y += self.speed;
// Handle jumping behavior
self.jumpTimer++;
if (self.jumpPhase === 'waiting' && self.jumpTimer >= self.jumpInterval && self.y > 500 && self.y < 1800) {
// Start jumping onto road
self.jumpPhase = 'jumping';
self.jumpTimer = 0;
}
if (self.jumpPhase === 'jumping') {
// Move toward target lane
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
if (Math.abs(diff) > 20) {
self.x += diff * 0.08;
} else {
self.jumpPhase = 'crossing';
}
}
if (self.jumpPhase === 'crossing') {
// Cross the road randomly
if (Math.random() < 0.02) {
self.targetLane = Math.floor(Math.random() * 4);
}
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
self.x += diff * 0.05;
}
// Add walking animation
pedestrianGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.1;
};
return self;
});
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35;
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
// Jump finished
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
// Calculate jump arc (parabolic motion)
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
// Add rotation during jump
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar2 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar2', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.42; // Much faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.25;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.35
}, {
duration: 180,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 280,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar3 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar3', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.38; // Faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.15;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.25
}, {
duration: 220,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 320,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar4 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar4', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35; // Standard lane switching speed like other cars
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; // Standard jump height
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar5 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar5', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.75; // Much faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.3;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.4
}, {
duration: 160,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 250,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar6 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar6', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35; // Standard lane switching speed like PlayerCar
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; // Standard jump height
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.1;
self.update = function () {
self.speed = 9.24 * gameSpeed * (nitroSpeedMultiplier > 1 ? nitroSpeedMultiplier * 0.8 : 1);
self.y += self.speed;
powerUpGraphics.rotation += self.rotationSpeed;
// Enhanced visual effects with glow pulsing
var glowIntensity = 0.7 + Math.sin(LK.ticks * 0.1) * 0.3;
powerUpGraphics.alpha = glowIntensity;
// Add rainbow tint cycling for more appealing visuals
var hue = LK.ticks * 0.05 % (Math.PI * 2);
var r = Math.floor(Math.sin(hue) * 127 + 128);
var g = Math.floor(Math.sin(hue + Math.PI * 2 / 3) * 127 + 128);
var b = Math.floor(Math.sin(hue + Math.PI * 4 / 3) * 127 + 128);
powerUpGraphics.tint = r << 16 | g << 8 | b;
};
return self;
});
var Ramp = Container.expand(function () {
var self = Container.call(this);
// Create ramp visual using multiple road line assets
var rampBase = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 2
});
rampBase.tint = 0x888888;
var rampTop = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 1,
y: -20
});
rampTop.tint = 0xAAAAA;
self.speed = 9.24;
self.lane = 0;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
// Add slight glow effect
rampBase.alpha = 0.8 + Math.sin(LK.ticks * 0.1) * 0.2;
};
return self;
});
var RoadLine = Container.expand(function () {
var self = Container.call(this);
var lineGraphics = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
// Game state management
var gameState = 'splash'; // 'splash', 'menu', 'playing', 'gameOver'
var menuElements = [];
var bestDistance = 0;
// Load best score from storage
function loadBestScore() {
var saved = storage.bestDistance;
if (saved !== undefined) {
bestDistance = saved;
}
}
// Save best score to storage
function saveBestScore() {
storage.bestDistance = bestDistance;
}
// Start menu creation
function createStartMenu() {
// Simple road background - just a few lines for context
for (var i = 0; i < 8; i++) {
for (var lane = 0; lane < 4; lane++) {
var menuLine = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 624 + lane * 400,
y: i * 250 + 300
});
menuLine.alpha = 0.2;
game.addChild(menuLine);
menuElements.push(menuLine);
}
}
// Clean title - big and centered
var titleText = new Text2('HIGHWAY RUSH', {
size: 160,
fill: '#FFD700',
stroke: '#000000',
strokeThickness: 6
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
game.addChild(titleText);
menuElements.push(titleText);
// Best score display - simple and clear
var bestScoreText = new Text2('Best: ' + bestDistance + 'm', {
size: 70,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 4
});
bestScoreText.anchor.set(0.5, 0.5);
bestScoreText.x = 1024;
bestScoreText.y = 750;
game.addChild(bestScoreText);
menuElements.push(bestScoreText);
// Car selection section - clean and organized
var carSelectionText = new Text2('Choose Car:', {
size: 60,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 3
});
carSelectionText.anchor.set(0.5, 0.5);
carSelectionText.x = 1024;
carSelectionText.y = 950;
game.addChild(carSelectionText);
menuElements.push(carSelectionText);
// Car selection buttons - properly centered for mobile
var car1Button = LK.getAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5,
x: 341,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car1Button);
menuElements.push(car1Button);
var car2Button = LK.getAsset('playerCar2', {
anchorX: 0.5,
anchorY: 0.5,
x: 574,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car2Button);
menuElements.push(car2Button);
var car3Button = LK.getAsset('playerCar3', {
anchorX: 0.5,
anchorY: 0.5,
x: 807,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car3Button);
menuElements.push(car3Button);
// Add playerCar4 button
var car4Button = LK.getAsset('playerCar4', {
anchorX: 0.5,
anchorY: 0.5,
x: 1040,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car4Button);
menuElements.push(car4Button);
// Add playerCar5 button
var car5Button = LK.getAsset('playerCar5', {
anchorX: 0.5,
anchorY: 0.5,
x: 1273,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car5Button);
menuElements.push(car5Button);
// Add playerCar6 button
var car6Button = LK.getAsset('playerCar6', {
anchorX: 0.5,
anchorY: 0.5,
x: 1506,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car6Button);
menuElements.push(car6Button);
// Selection indicator
selectionIndicator = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 0.6,
x: selectedCarType === 0 ? 341 : selectedCarType === 1 ? 574 : selectedCarType === 2 ? 807 : selectedCarType === 3 ? 1040 : selectedCarType === 4 ? 1273 : 1506,
y: 1280
});
selectionIndicator.tint = 0xFFD700;
game.addChild(selectionIndicator);
menuElements.push(selectionIndicator);
// Instructions - simple and clear
var instructionsText = new Text2('Swipe to change lanes • Avoid traffic • Collect power-ups', {
size: 50,
fill: '#CCCCCC',
stroke: '#000000',
strokeThickness: 2
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 1450;
game.addChild(instructionsText);
menuElements.push(instructionsText);
// Simple START BUTTON at bottom
var startButton = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 4,
x: 1024,
y: 2200
});
startButton.tint = 0x00BB00;
game.addChild(startButton);
menuElements.push(startButton);
// START text
var startButtonText = new Text2('START GAME', {
size: 120,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 6
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = 1024;
startButtonText.y = 2200;
game.addChild(startButtonText);
menuElements.push(startButtonText);
// Stats Chart button removed
// Store button references for animations
var buttonElements = {
button: startButton,
text: startButtonText
};
// Initialize selection visual state
updateCarSelection();
// Start menu music
LK.playMusic('menumusic', {
volume: 0.7
});
// Stylish fluid animations with enhanced effects
// Title pulsing with glow effect
tween(titleText, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 1800,
yoyo: true,
repeat: 50,
easing: tween.easeInOut
});
// Add floating animation to title
tween(titleText, {
y: 580
}, {
duration: 3000,
yoyo: true,
repeat: 30,
easing: tween.easeInOut
});
// Remove swinging animation - title stays in center position
// Car selection buttons - keep cars stationary (no movement animations)
// Cars will remain in their fixed positions without floating or rotation effects
// Enhanced button animations with elastic effect
tween(buttonElements.button, {
scaleX: 22,
scaleY: 3.5
}, {
duration: 2000,
yoyo: true,
repeat: 50,
easing: tween.elasticInOut
});
tween(buttonElements.text, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 2000,
yoyo: true,
repeat: 50,
easing: tween.bounceInOut
});
// Add color transition to start button
tween(buttonElements.button, {
tint: 0x00FF00
}, {
duration: 1000,
yoyo: true,
repeat: 100,
easing: tween.easeInOut
});
// Stats button animations removed
}
function removeStartMenu() {
// Stop all ongoing tweens to prevent memory leaks and performance issues
for (var i = 0; i < menuElements.length; i++) {
tween.stop(menuElements[i]); // Stop all tweens on this element
menuElements[i].destroy();
}
menuElements = [];
}
function startGame() {
gameState = 'playing';
// Stop all menu tweens before removing menu
if (menuElements.length > 0) {
for (var i = 0; i < menuElements.length; i++) {
tween.stop(menuElements[i]);
}
}
removeStartMenu();
loadBestScore();
initializeGameplay();
// Reset tap counter after starting game
car1TapCount = 0;
car2TapCount = 0;
car3TapCount = 0;
car6TapCount = 0;
// Initialize combo system for new game
comboCount = 0;
comboMultiplier = 1;
lastComboTime = 0;
// Statistics updates removed
}
// Camera shake system
var cameraShake = {
intensity: 0,
duration: 0,
originalX: 0,
originalY: 0
};
function addCameraShake(intensity, duration) {
if (cameraShake.intensity < intensity) {
cameraShake.intensity = intensity;
cameraShake.duration = duration;
cameraShake.originalX = game.x;
cameraShake.originalY = game.y;
}
}
function updateCameraShake() {
if (cameraShake.duration > 0) {
var shakeX = (Math.random() - 0.5) * cameraShake.intensity;
var shakeY = (Math.random() - 0.5) * cameraShake.intensity;
game.x = cameraShake.originalX + shakeX;
game.y = cameraShake.originalY + shakeY;
cameraShake.duration--;
cameraShake.intensity *= 0.95; // Fade out shake
if (cameraShake.duration <= 0) {
game.x = cameraShake.originalX;
game.y = cameraShake.originalY;
cameraShake.intensity = 0;
}
}
}
function initializeGameplay() {
// Initialize all game variables
gameSpeed = 1;
baseGameSpeed = 1;
gasPressed = false;
gasAcceleration = 1;
// Reset combo system variables
comboCount = 0;
comboMultiplier = 1;
lastComboTime = 0;
spawnTimer = 0;
spawnRate = 120;
lineSpawnTimer = 0;
powerUpSpawnTimer = 0;
nitroSpawnTimer = 0;
cupSpawnTimer = 0;
bomberSpawnTimer = 0;
rampSpawnTimer = 0;
pedestrianSpawnTimer = 0;
playerJumping = false;
jumpStartTime = 0;
jumpHeight = 0;
// Check if car1 was tapped 10 times for secret unlock
if (selectedCarType === 0 && car1TapCount >= 10) {
distanceTraveled = 2000;
gameSpeed = 1 + distanceTraveled / 7000 + Math.pow(distanceTraveled / 15000, 1.5);
gameSpeed = Math.min(gameSpeed, 4);
// Flash screen to indicate secret unlock
LK.effects.flashScreen(0x00ff00, 500);
} else if (selectedCarType === 1 && car2TapCount >= 10) {
// Trophy road mode - start with lots of trophies
distanceTraveled = 0;
// Flash screen golden to indicate trophy road
LK.effects.flashScreen(0xFFD700, 1000);
// Set flag for trophy road mode
trophyRoadMode = true;
} else if (selectedCarType === 5 && car6TapCount >= 31) {
// PlayerCar6 ultra speed mode - 11x faster than normal
distanceTraveled = 0;
gameSpeed = 11; // 11 times faster than normal
// Flash screen with bright cyan to indicate ultra speed
LK.effects.flashScreen(0x00FFFF, 1500);
// Add pulsing effect to player car for ultra speed mode
tween(playerCar, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
yoyo: true,
repeat: 3,
easing: tween.easeInOut
});
} else {
distanceTraveled = 0;
}
nitroEffect = false;
nitroEndTime = 0;
hasShield = false;
trophyRoadMode = false;
rapModeActive = false;
rapModeTimer = 0;
playerCar4Unlocked = true;
fastMusicPlaying = false;
// Reset score
LK.setScore(0);
// Add enhanced road background
var roadBackground = game.addChild(LK.getAsset('roadCenter', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
roadBackground.alpha = 0.8;
// Add road side markers
var leftSide = game.addChild(LK.getAsset('roadSide', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 1366
}));
var rightSide = game.addChild(LK.getAsset('roadSide', {
anchorX: 0.5,
anchorY: 0.5,
x: 1848,
y: 1366
}));
// Update UI texts with English
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
bestScoreTxt.setText('Best: ' + bestDistance);
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x');
// Add combo display
comboTxt = new Text2('', {
size: 70,
fill: '#FF6B00',
stroke: '#000000',
strokeThickness: 3
});
comboTxt.anchor.set(0.5, 0);
comboTxt.y = 160;
LK.gui.top.addChild(comboTxt);
// Reinitialize player car to ensure it's properly set up
initializePlayerCar();
// Gas pedal completely removed from play - no longer visible or interactive
gasButton = null; // Remove gas button reference
// Stop menu music and start gameplay music
LK.stopMusic();
LK.playMusic('bgmusic', {
volume: 0.7
});
}
// Initialize best score system
loadBestScore();
// Define combo system variables
var comboTimeWindow = 180; // 3 seconds at 60fps for combo window
var comboCount = 0;
var comboMultiplier = 1;
var lastComboTime = 0;
var comboTxt;
// Player statistics system removed
// Chart display system removed
// Achievement system
var achievements = {
speedDemon: storage.achievementSpeedDemon || false,
// Reach 3x speed
jumpMaster: storage.achievementJumpMaster || false,
// Jump 50 times
collector: storage.achievementCollector || false,
// Collect 100 power-ups
survivor: storage.achievementSurvivor || false,
// Travel 10000m in one game
nitroAddict: storage.achievementNitroAddict || false // Collect 25 nitros
};
function saveAchievements() {
storage.achievementSpeedDemon = achievements.speedDemon;
storage.achievementJumpMaster = achievements.jumpMaster;
storage.achievementCollector = achievements.collector;
storage.achievementSurvivor = achievements.survivor;
storage.achievementNitroAddict = achievements.nitroAddict;
}
function checkAchievements() {
// Speed Demon achievement
if (!achievements.speedDemon && gameSpeed >= 3.0) {
achievements.speedDemon = true;
showAchievement("SPEED DEMON!", "Reached 3x speed!");
saveAchievements();
}
// Jump Master achievement - removed since playerStats no longer exists
// Collector achievement - removed since playerStats no longer exists
// Survivor achievement
if (!achievements.survivor && distanceTraveled >= 10000) {
achievements.survivor = true;
showAchievement("SURVIVOR!", "Traveled 10,000m!");
saveAchievements();
}
// Nitro Addict achievement - removed since playerStats no longer exists
}
function showAchievement(title, description) {
var achievementBg = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 4,
x: 1024,
y: 400
});
achievementBg.tint = 0xFFD700;
achievementBg.alpha = 0;
game.addChild(achievementBg);
var achievementTitle = new Text2(title, {
size: 80,
fill: '#000000',
stroke: '#FFFFFF',
strokeThickness: 3
});
achievementTitle.anchor.set(0.5, 0.5);
achievementTitle.x = 1024;
achievementTitle.y = 370;
achievementTitle.alpha = 0;
game.addChild(achievementTitle);
var achievementDesc = new Text2(description, {
size: 50,
fill: '#000000',
stroke: '#FFFFFF',
strokeThickness: 2
});
achievementDesc.anchor.set(0.5, 0.5);
achievementDesc.x = 1024;
achievementDesc.y = 430;
achievementDesc.alpha = 0;
game.addChild(achievementDesc);
// Animate achievement popup
tween(achievementBg, {
alpha: 0.9
}, {
duration: 500,
easing: tween.easeOut
});
tween(achievementTitle, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(achievementDesc, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Auto-hide after 3 seconds
LK.setTimeout(function () {
tween(achievementBg, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementBg.destroy();
}
});
tween(achievementTitle, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementTitle.destroy();
}
});
tween(achievementDesc, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementDesc.destroy();
}
});
}, 3000);
LK.effects.flashScreen(0xFFD700, 800);
}
// Show KEMALDEV splash screen first
function showKemaldevSplash() {
// Set game state to splash to prevent other interactions
gameState = 'splash';
// Create black background covering full screen
var splashBg = LK.getAsset('roadCenter', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 2,
scaleY: 2,
tint: 0x000000
});
game.addChild(splashBg);
// Create KEMALDEV text
var kemaldevText = new Text2('KEMALDEV', {
size: 200,
fill: '#FFFFFF',
stroke: '#FFD700',
strokeThickness: 8
});
kemaldevText.anchor.set(0.5, 0.5);
kemaldevText.x = 1024;
kemaldevText.y = 1366;
kemaldevText.alpha = 0;
game.addChild(kemaldevText);
// Fade in animation
tween(kemaldevText, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
// Add pulsing effect
tween(kemaldevText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1000,
yoyo: true,
repeat: 2,
easing: tween.easeInOut
});
// Hide after 3 seconds and show main menu
LK.setTimeout(function () {
tween(kemaldevText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
kemaldevText.destroy();
splashBg.destroy();
gameState = 'menu';
createStartMenu();
}
});
}, 3000);
}
// Show KEMALDEV splash screen first, then create start menu
showKemaldevSplash();
// Car selection variable
var selectedCarType = 0; // 0 for PlayerCar, 1 for PlayerCar2, 2 for PlayerCar3
var playerCar;
var selectionIndicator;
var car1TapCount = 0; // Track taps on playercar1 for secret unlock
var car2TapCount = 0; // Track taps on playercar2 for trophy road
var car3TapCount = 0; // Track taps on playercar3 for secret message
var car6TapCount = 0; // Track taps on playercar6 for speed boost
// Update car selection visual state
function updateCarSelection() {
if (selectionIndicator) {
var targetX = selectedCarType === 0 ? 341 : selectedCarType === 1 ? 574 : selectedCarType === 2 ? 807 : selectedCarType === 3 ? 1040 : selectedCarType === 4 ? 1273 : 1506;
// Smooth fluid transition for selection indicator
tween(selectionIndicator, {
x: targetX
}, {
duration: 400,
easing: tween.elasticOut
});
// Add selection pulse effect
tween(selectionIndicator, {
scaleY: 1.2,
tint: 0xFFD700
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(selectionIndicator, {
scaleY: 0.6,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
}
// Check if car 3 is unlocked
var car3Unlocked = bestDistance >= 2000;
// Update car button tints if they exist
if (menuElements.length > 0) {
for (var i = 0; i < menuElements.length; i++) {
var element = menuElements[i];
if (element.x === 624 && element.y === 1650) {
element.tint = selectedCarType === 0 ? 0xFFD700 : 0xFFFFFF;
} else if (element.x === 1024 && element.y === 1650) {
element.tint = selectedCarType === 1 ? 0xFFD700 : 0xFFFFFF;
} else if (element.x === 1424 && element.y === 1650) {
if (car3Unlocked) {
element.tint = selectedCarType === 2 ? 0xFFD700 : 0xFFFFFF;
} else {
element.tint = 0x666666; // Gray out locked car
element.alpha = 0.5;
}
}
}
}
}
// Initialize player car based on selection
function initializePlayerCar() {
if (playerCar) {
playerCar.destroy();
}
if (selectedCarType === 0) {
playerCar = game.addChild(new PlayerCar());
} else if (selectedCarType === 1) {
playerCar = game.addChild(new PlayerCar2());
} else if (selectedCarType === 2) {
playerCar = game.addChild(new PlayerCar3());
} else if (selectedCarType === 3) {
playerCar = game.addChild(new PlayerCar4());
} else if (selectedCarType === 4) {
playerCar = game.addChild(new PlayerCar5());
} else if (selectedCarType === 5) {
playerCar = game.addChild(new PlayerCar6());
}
playerCar.x = 324 + 400; // Lane 1
playerCar.y = 2200;
}
// Initialize the first car
initializePlayerCar();
var enemyCars = [];
var powerUps = [];
var roadLines = [];
var nitros = [];
var cups = [];
var bombers = [];
var bombs = [];
var ramps = [];
var pedestrians = [];
var playerJumping = false;
var jumpStartTime = 0;
var jumpDuration = 60; // 1 second at 60fps
var jumpHeight = 0;
var gameSpeed = 1;
var spawnTimer = 0;
var spawnRate = 120;
var lineSpawnTimer = 0;
var powerUpSpawnTimer = 0;
var nitroSpawnTimer = 0;
var cupSpawnTimer = 0;
var bomberSpawnTimer = 0;
var rampSpawnTimer = 0;
var pedestrianSpawnTimer = 0;
var distanceTraveled = 0;
var nitroEffect = false;
var nitroEndTime = 0;
var nitroSpeedMultiplier = 1;
var nitroAcceleration = 1;
var hasShield = false;
var gasPressed = false;
var baseGameSpeed = 1;
var gasAcceleration = 1;
var maxGasMultiplier = 2.5;
var gasDecelerationRate = 0.98;
var gasAccelerationRate = 1.05;
var trophyRoadMode = false;
var rapModeActive = false;
var rapModeTimer = 0;
var rapModeCheckInterval = 600; // Check every 10 seconds (600 ticks at 60fps)
var playerCar4Unlocked = true;
// Create initial road lines
for (var i = 0; i < 20; i++) {
for (var lane = 0; lane < 4; lane++) {
var line = game.addChild(new RoadLine());
line.x = 524 + lane * 400; // Between lanes
line.y = i * 150 - 200;
roadLines.push(line);
}
}
// UI Elements
var scoreTxt = new Text2('Distance: 0', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var bestScoreTxt = new Text2('Best: ' + bestDistance, {
size: 60,
fill: 0xFFD700,
stroke: 0x000000,
strokeThickness: 3
});
bestScoreTxt.anchor.set(0.5, 0);
bestScoreTxt.y = 90;
LK.gui.top.addChild(bestScoreTxt);
var speedTxt = new Text2('Speed: 1x', {
size: 60,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 3
});
speedTxt.anchor.set(1, 1);
speedTxt.x = -20;
speedTxt.y = -20;
LK.gui.bottomRight.addChild(speedTxt);
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var touchStartTime = 0;
// Gas button element
var gasButton;
game.down = function (x, y, obj) {
if (gameState === 'splash') {
// Skip splash screen on tap
tween.stop();
LK.clearTimeout();
gameState = 'menu';
// Clean up splash elements
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child) {
child.destroy();
}
}
createStartMenu();
return;
}
if (gameState === 'menu') {
// Check car selection buttons
if (y >= 1050 && y <= 1250) {
if (x >= 241 && x <= 441) {
// Car 1 selected
selectedCarType = 0;
car1TapCount++; // Increment tap counter
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 474 && x <= 674) {
// Car 2 selected
selectedCarType = 1;
car2TapCount++; // Increment tap counter for car2
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 707 && x <= 907) {
// Car 3 selected - check if unlocked
if (bestDistance >= 2000) {
selectedCarType = 2;
car3TapCount++; // Increment tap counter for car3
// Check if tapped 10 times for secret message
if (car3TapCount >= 10) {
// Display "Thank you Yavuz Abi" in score area
scoreTxt.setText('Thank you Yavuz Abi');
// Flash screen to indicate special message
LK.effects.flashScreen(0xFFD700, 1000);
}
updateCarSelection();
initializePlayerCar();
} else {
// Car 3 is locked, flash red to indicate requirement
LK.effects.flashScreen(0xff0000, 300);
}
return;
} else if (x >= 940 && x <= 1140) {
// Car 4 selected - check if unlocked
if (playerCar4Unlocked) {
selectedCarType = 3;
updateCarSelection();
initializePlayerCar();
} else {
// Car 4 is locked, flash purple to indicate requirement
LK.effects.flashScreen(0x9932CC, 300);
}
return;
} else if (x >= 1173 && x <= 1373) {
// Car 5 selected
selectedCarType = 4;
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 1406 && x <= 1606) {
// Car 6 selected
selectedCarType = 5;
car6TapCount++; // Increment tap counter for car6
updateCarSelection();
initializePlayerCar();
return;
}
}
// Stats button interaction removed
// Check for start button tap at bottom - expanded touch area for better UX
if (y >= 2050 && y <= 2350 && x >= 300 && x <= 1748) {
startGame();
return;
}
}
if (gameState === 'playing') {
// Gas button interaction removed - no longer functional
}
touchStartX = x;
touchStartY = y;
touchStartTime = LK.ticks;
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
var touchEndX = x;
var swipeDistance = touchEndX - touchStartX;
var touchDuration = LK.ticks - touchStartTime;
// Gas button release interaction removed - no longer functional
// Detect swipe or tap for lane changing
if (Math.abs(swipeDistance) > 100 && touchDuration < 30) {
// Swipe detected
if (swipeDistance > 0) {
playerCar.switchLane(1); // Swipe right
} else {
playerCar.switchLane(-1); // Swipe left
}
} else if (touchDuration < 15) {
// Gas button area check removed - full screen available for lane changes
if (x > 1024) {
playerCar.switchLane(1); // Right side tap
} else {
playerCar.switchLane(-1); // Left side tap
}
}
};
function spawnEnemyCar() {
var lane = Math.floor(Math.random() * 4);
var enemy;
var carTypes = ['enemyCar1', 'enemyCar2', 'enemyCar3'];
var carType = carTypes[Math.floor(Math.random() * carTypes.length)];
enemy = game.addChild(new EnemyCar(carType));
enemy.x = 324 + lane * 400;
enemy.y = -100;
enemy.lane = lane;
enemy.speed = 9.24 * gameSpeed;
enemyCars.push(enemy);
}
function spawnPowerUp() {
// Reduce spawn chance as difficulty increases
var spawnChance = Math.max(0.1, 0.3 - distanceTraveled / 25000); // Decreases from 30% to 10%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var powerUp = game.addChild(new PowerUp());
powerUp.x = 324 + lane * 400;
powerUp.y = -100;
powerUp.speed = 9.24 * gameSpeed;
powerUps.push(powerUp);
}
}
function spawnNitro() {
// Significantly reduce spawn chance as difficulty increases
var spawnChance = Math.max(0.05, 0.2 - distanceTraveled / 20000); // Decreases from 20% to 5%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var nitro = game.addChild(new Nitro());
nitro.x = 324 + lane * 400;
nitro.y = -100;
nitro.speed = 9.24 * gameSpeed;
nitros.push(nitro);
}
}
function spawnCup() {
// Check if trophy road mode is active
if (trophyRoadMode) {
// In trophy road mode, spawn many cups (trophies)
var spawnChance = 0.8; // Very high spawn chance for trophies
if (Math.random() < spawnChance) {
// Spawn multiple cups across different lanes
for (var trophyLane = 0; trophyLane < 4; trophyLane++) {
if (Math.random() < 0.7) {
// 70% chance per lane
var cup = game.addChild(new Cup());
cup.x = 324 + trophyLane * 400;
cup.y = -100 - trophyLane * 150; // Stagger them vertically
cup.speed = 9.24 * gameSpeed;
cups.push(cup);
}
}
}
} else {
// Normal spawn chance for cups
var spawnChance = Math.max(0.03, 0.15 - distanceTraveled / 30000); // Decreases from 15% to 3%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var cup = game.addChild(new Cup());
cup.x = 324 + lane * 400;
cup.y = -100;
cup.speed = 9.24 * gameSpeed;
cups.push(cup);
}
}
}
function spawnRamp() {
// Spawn ramps occasionally to help player jump over obstacles
var spawnChance = Math.max(0.05, 0.15 - distanceTraveled / 20000); // Decreases from 15% to 5%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var ramp = game.addChild(new Ramp());
ramp.x = 324 + lane * 400;
ramp.y = -100;
ramp.lane = lane;
ramp.speed = 9.24 * gameSpeed;
ramps.push(ramp);
}
}
function spawnPedestrian() {
// Increased spawn chance for pedestrians by 80% more (from 25.92% to 46.66%)
var spawnChance = Math.max(0.1555, 0.4666 - distanceTraveled / 30000); // Decreases from 46.66% to 15.55%
if (Math.random() < spawnChance) {
// Spawn from sides of the road
var startSide = Math.random() < 0.5 ? 0 : 1; // 0 = left, 1 = right
var pedestrian = game.addChild(new Pedestrian());
pedestrian.x = startSide === 0 ? 124 : 1924; // Start from road sides
pedestrian.y = -100;
pedestrian.lane = startSide === 0 ? 0 : 3; // Start lane
pedestrian.speed = 6.93 * gameSpeed;
pedestrians.push(pedestrian);
}
}
function spawnBomber() {
// Moderate spawn chance for bombers
var spawnChance = Math.max(0.08, 0.25 - distanceTraveled / 25000); // Decreases from 25% to 8%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var bomber = game.addChild(new Bomber());
bomber.x = 324 + lane * 400;
bomber.y = -100;
bomber.lane = lane;
bomber.speed = 6.93 * gameSpeed;
bombers.push(bomber);
}
}
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') return;
// Update camera shake
updateCameraShake();
// Update combo system
if (LK.ticks - lastComboTime > comboTimeWindow && comboCount > 0) {
comboCount = 0;
comboMultiplier = 1;
if (comboTxt) {
tween(comboTxt, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
comboTxt.setText('');
comboTxt.alpha = 1;
}
});
}
}
// Player statistics updates removed
// Check achievements
checkAchievements();
// PlayerCar4 is now available from the start - no unlock required
// Check for rap mode activation
rapModeTimer++;
if (rapModeTimer >= rapModeCheckInterval) {
// 80% chance to activate rap mode every 10 seconds - rap appears frequently now!
if (Math.random() < 0.8 && !rapModeActive) {
rapModeActive = true;
// Flash screen with hip-hop colors (purple/gold)
LK.effects.flashScreen(0x9932CC, 800);
// Change UI text to rap style
scoreTxt.setText('Yo Distance: ' + Math.floor(distanceTraveled) + ' meters!');
speedTxt.setText('Speed Flow: ' + gameSpeed.toFixed(1) + 'x');
// Rap mode lasts for 5 seconds
LK.setTimeout(function () {
rapModeActive = false;
// Reset UI text to normal
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x');
LK.effects.flashScreen(0x00FFFF, 400);
}, 5000);
}
rapModeTimer = 0;
}
// Update gas acceleration system with accelerator pedal physics
if (gasPressed) {
// Accelerate when stepping on the gas pedal
gasAcceleration = Math.min(gasAcceleration * gasAccelerationRate, maxGasMultiplier);
// Enhanced visual feedback for stepping on accelerator
if (LK.ticks % 15 === 0) {
LK.effects.flashObject(playerCar, 0xFFFF00, 150);
}
// Add speed lines effect when accelerating hard
if (gasAcceleration > 1.8 && LK.ticks % 8 === 0) {
LK.effects.flashScreen(0x004488, 30);
}
// Pedal vibration effect
if (gasButton && gasAcceleration > 2.0) {
gasButton.x = 1024 + (Math.random() - 0.5) * 4;
gasButton.y = 2500 + (Math.random() - 0.5) * 4;
}
} else {
// Decelerate when lifting foot off gas pedal
gasAcceleration = Math.max(gasAcceleration * gasDecelerationRate, 1);
// Reset pedal position when not pressed
if (gasButton) {
gasButton.x = 1024;
gasButton.y = 2500;
}
}
// Update base game speed with progression - increased by 11%
baseGameSpeed = 1 + distanceTraveled / 7000 + Math.pow(distanceTraveled / 15000, 1.5);
baseGameSpeed = Math.min(baseGameSpeed, 4); // Cap maximum base speed
baseGameSpeed = baseGameSpeed * 1.11; // Increase speed by 11 percent
// Apply gas acceleration to game speed
gameSpeed = baseGameSpeed * gasAcceleration;
// Update distance and speed with accelerated progression and nitro boost
var effectiveSpeed = gameSpeed * nitroSpeedMultiplier * nitroAcceleration;
distanceTraveled += effectiveSpeed;
var lastGameSpeed = gameSpeed;
// Switch to faster music at high speeds (based on base speed to prevent flickering)
if (baseGameSpeed > 2.5 && !fastMusicPlaying) {
LK.playMusic('fastmusic', {
volume: 0.8
});
fastMusicPlaying = true;
} else if (baseGameSpeed <= 2.5 && fastMusicPlaying) {
LK.playMusic('bgmusic', {
volume: 0.7
});
fastMusicPlaying = false;
}
// Update UI text based on rap mode
if (rapModeActive) {
scoreTxt.setText('Yo Distance: ' + Math.floor(distanceTraveled) + ' meters!');
bestScoreTxt.setText('Best Flow: ' + bestDistance);
speedTxt.setText('Speed Flow: ' + gameSpeed.toFixed(1) + 'x' + (gasPressed ? ' ⚡' : ''));
} else {
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
bestScoreTxt.setText('Best: ' + bestDistance);
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x' + (gasPressed ? ' ⚡' : ''));
}
// Add pulsing effect when speed increases
if (gameSpeed > lastGameSpeed + 0.1) {
tween(speedTxt, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(speedTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
// Enhanced continuous nitro visual effects with fluid animations
if (nitroEffect) {
// Dynamic pulsing glow effect during nitro
if (LK.ticks % 8 === 0) {
var glowColor = Math.random() < 0.3 ? 0x00FFFF : Math.random() < 0.6 ? 0xFFFFFF : 0xFF00FF;
LK.effects.flashObject(playerCar, glowColor, 150);
}
// Enhanced speed lines effect with gradient
if (LK.ticks % 4 === 0) {
var speedColor = Math.random() < 0.5 ? 0x0066BB : 0x004488;
LK.effects.flashScreen(speedColor, 30);
}
// Add nitro trail effects with tween
if (LK.ticks % 12 === 0) {
// Create temporary trail effect
var trailEffect = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
x: playerCar.x + (Math.random() - 0.5) * 100,
y: playerCar.y + 50,
tint: 0x00FFFF,
alpha: 0.8
});
game.addChild(trailEffect);
tween(trailEffect, {
alpha: 0,
scaleX: 3,
scaleY: 0.2,
y: trailEffect.y + 200
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
trailEffect.destroy();
}
});
}
}
// Spawn enemies with progressive difficulty
spawnTimer++;
var adjustedSpawnRate = Math.max(30, spawnRate - Math.floor(distanceTraveled / 500)); // More aggressive spawn rate reduction
if (spawnTimer >= adjustedSpawnRate / gameSpeed) {
spawnEnemyCar();
spawnTimer = 0;
// Multiple enemy spawning at higher difficulty
if (distanceTraveled > 5000 && Math.random() < 0.3) {
spawnEnemyCar(); // 30% chance for double spawn after 5000 distance
}
if (distanceTraveled > 10000 && Math.random() < 0.2) {
spawnEnemyCar(); // Additional spawn chance after 10000 distance
}
}
// Spawn power-ups with reduced frequency at higher difficulty
powerUpSpawnTimer++;
var powerUpInterval = Math.max(200, 300 + Math.floor(distanceTraveled / 200)); // Longer intervals as distance increases
if (powerUpSpawnTimer >= powerUpInterval / gameSpeed) {
spawnPowerUp();
powerUpSpawnTimer = 0;
}
// Spawn nitro with increased rarity at higher difficulty
nitroSpawnTimer++;
var nitroInterval = Math.max(400, 600 + Math.floor(distanceTraveled / 150)); // Much longer intervals as distance increases
if (nitroSpawnTimer >= nitroInterval / gameSpeed) {
spawnNitro();
nitroSpawnTimer = 0;
}
// Spawn cups with very rare frequency
cupSpawnTimer++;
var cupInterval = Math.max(800, 1200 + Math.floor(distanceTraveled / 100)); // Very long intervals
if (cupSpawnTimer >= cupInterval / gameSpeed) {
spawnCup();
cupSpawnTimer = 0;
}
// Spawn bombers periodically
bomberSpawnTimer++;
var bomberInterval = Math.max(300, 500 + Math.floor(distanceTraveled / 200)); // Moderate intervals
if (bomberSpawnTimer >= bomberInterval / gameSpeed) {
spawnBomber();
bomberSpawnTimer = 0;
}
// Spawn ramps periodically
rampSpawnTimer++;
var rampInterval = Math.max(600, 800 + Math.floor(distanceTraveled / 300)); // Long intervals for ramps
if (rampSpawnTimer >= rampInterval / gameSpeed) {
spawnRamp();
rampSpawnTimer = 0;
}
// Spawn pedestrians occasionally
pedestrianSpawnTimer++;
var pedestrianInterval = Math.max(700, 1000 + Math.floor(distanceTraveled / 250)); // Moderate intervals
if (pedestrianSpawnTimer >= pedestrianInterval / gameSpeed) {
spawnPedestrian();
pedestrianSpawnTimer = 0;
}
// Check nitro effect end
if (nitroEffect && LK.ticks >= nitroEndTime) {
nitroEffect = false;
// Smooth transition back to normal speed
tween(playerCar, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Reset speed multipliers gradually
tween({
value: nitroSpeedMultiplier
}, {
value: 1
}, {
duration: 800,
easing: tween.easeOut,
onUpdate: function onUpdate(obj) {
nitroSpeedMultiplier = obj.value;
}
});
tween({
value: nitroAcceleration
}, {
value: 1
}, {
duration: 800,
easing: tween.easeOut,
onUpdate: function onUpdate(obj) {
nitroAcceleration = obj.value;
}
});
// Reset player car movement speed
if (playerCar.originalMoveSpeed) {
tween(playerCar, {
moveSpeed: playerCar.originalMoveSpeed
}, {
duration: 500,
easing: tween.easeOut
});
}
// Flash to indicate nitro ending
LK.effects.flashScreen(0xFF4400, 300);
}
// Spawn road lines
lineSpawnTimer++;
if (lineSpawnTimer >= 25) {
for (var lane = 0; lane < 4; lane++) {
var line = game.addChild(new RoadLine());
line.x = 524 + lane * 400;
line.y = -100;
line.speed = 9.24 * gameSpeed * nitroSpeedMultiplier;
roadLines.push(line);
}
lineSpawnTimer = 0;
}
// Update and check power-ups
for (var j = powerUps.length - 1; j >= 0; j--) {
var powerUp = powerUps[j];
// Remove off-screen power-ups
if (powerUp.y > 2800) {
powerUp.destroy();
powerUps.splice(j, 1);
continue;
}
// Check collection
if (powerUp.intersects(playerCar)) {
// Update combo system
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3); // Max 3x multiplier
var baseScore = 50;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
LK.effects.flashObject(powerUp, 0xffffff, 200);
addCameraShake(3, 10);
// Add smooth scale-out effect before destroying
tween(powerUp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
powerUp.destroy();
}
});
powerUps.splice(j, 1);
}
}
// Update and check nitros
for (var n = nitros.length - 1; n >= 0; n--) {
var nitro = nitros[n];
// Remove off-screen nitros
if (nitro.y > 2800) {
nitro.destroy();
nitros.splice(n, 1);
continue;
}
// Check collection
if (nitro.intersects(playerCar)) {
// Statistics update removed
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3);
var baseScore = 100;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1 && comboTxt) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
addCameraShake(8, 20);
// Activate nitro effect with massive speed boost
nitroEffect = true;
nitroEndTime = LK.ticks + 450; // 7.5 seconds at 60fps
// Dramatic speed boost - 3x multiplier
nitroSpeedMultiplier = 3.0;
nitroAcceleration = 2.5;
// Enhanced visual effects for nitro activation
if (playerCar) {
tween(playerCar, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut
});
// Add pulsing effect during nitro
tween(playerCar, {
tint: 0x00FFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(playerCar, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
// Enhanced player car movement speed during nitro
if (playerCar.moveSpeed !== undefined) {
playerCar.originalMoveSpeed = playerCar.moveSpeed;
tween(playerCar, {
moveSpeed: playerCar.moveSpeed * 2.5
}, {
duration: 200,
easing: tween.easeOut
});
}
}
// Screen flash for nitro activation
LK.effects.flashScreen(0x00FFFF, 800);
// Add smooth scale-out effect for nitro
tween(nitro, {
scaleX: 4,
scaleY: 4,
alpha: 0
}, {
duration: 600,
easing: tween.elasticOut,
onFinish: function onFinish() {
nitro.destroy();
}
});
nitros.splice(n, 1);
}
}
// Update and check cups
for (var c = cups.length - 1; c >= 0; c--) {
var cup = cups[c];
// Remove off-screen cups
if (cup.y > 2800) {
cup.destroy();
cups.splice(c, 1);
continue;
}
// Check collection
if (cup.intersects(playerCar)) {
hasShield = true;
// Statistics update removed
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3);
var baseScore = 150;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
addCameraShake(5, 15);
LK.effects.flashScreen(0xFFD700, 400);
// Visual feedback for shield activation
tween(playerCar, {
tint: 0xFFD700
}, {
duration: 200,
onFinish: function onFinish() {
tween(playerCar, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
// Add smooth scale-out effect for cup
tween(cup, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
easing: tween.elasticOut,
onFinish: function onFinish() {
cup.destroy();
}
});
cups.splice(c, 1);
}
}
// Update and check bombers
for (var b = bombers.length - 1; b >= 0; b--) {
var bomber = bombers[b];
// Remove off-screen bombers
if (bomber.y > 2800) {
bomber.destroy();
bombers.splice(b, 1);
continue;
}
// Check collision with player
if (bomber.intersects(playerCar)) {
// Always crush/kill the bomber person on collision
LK.setScore(LK.getScore() + 300);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at bomber position
var explosion = game.addChild(new Explosion());
explosion.x = bomber.x;
explosion.y = bomber.y;
// Destroy the bomber
bomber.destroy();
bombers.splice(b, 1);
continue;
}
}
// Update and check bombs
for (var bomb = bombs.length - 1; bomb >= 0; bomb--) {
var bombObj = bombs[bomb];
// Remove off-screen bombs
if (bombObj.y > 2800) {
bombObj.destroy();
bombs.splice(bomb, 1);
continue;
}
// Check collision with player
if (bombObj.intersects(playerCar)) {
if (hasShield) {
// Player has shield from cup - destroy bomb instead
hasShield = false;
LK.setScore(LK.getScore() + 200);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at bomb position
var explosion = game.addChild(new Explosion());
explosion.x = bombObj.x;
explosion.y = bombObj.y;
// Destroy the bomb
bombObj.destroy();
bombs.splice(bomb, 1);
continue;
} else {
// Normal collision - game over with bigger explosion
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Intense camera shake for crash
addCameraShake(25, 60);
// Create additional explosion for bomb impact
var bombExplosion = game.addChild(new Explosion());
bombExplosion.x = bombObj.x;
bombExplosion.y = bombObj.y;
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
}
}
// Update and check ramps
for (var r = ramps.length - 1; r >= 0; r--) {
var ramp = ramps[r];
// Remove off-screen ramps
if (ramp.y > 2800) {
ramp.destroy();
ramps.splice(r, 1);
continue;
}
// Check if player hits ramp to initiate jump
if (ramp.intersects(playerCar) && !playerJumping) {
playerJumping = true;
jumpStartTime = LK.ticks;
// Statistics update removed
var baseScore = 75;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore); // Bonus for using ramp
LK.getSound('collect').play();
addCameraShake(4, 12);
// Flash effect for ramp activation
LK.effects.flashScreen(0x00AAFF, 300);
// Scale out ramp effect
tween(ramp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
ramp.destroy();
}
});
ramps.splice(r, 1);
continue;
}
}
// Update and check pedestrians
for (var p = pedestrians.length - 1; p >= 0; p--) {
var pedestrian = pedestrians[p];
// Remove off-screen pedestrians
if (pedestrian.y > 2800) {
pedestrian.destroy();
pedestrians.splice(p, 1);
continue;
}
// Check collision with player
if (pedestrian.intersects(playerCar)) {
if (hasShield) {
// Player has shield - save pedestrian and get bonus
hasShield = false;
LK.setScore(LK.getScore() + 250);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create sparkle effect for saving pedestrian
var explosion = game.addChild(new Explosion());
explosion.x = pedestrian.x;
explosion.y = pedestrian.y;
// Destroy the pedestrian (saved)
pedestrian.destroy();
pedestrians.splice(p, 1);
continue;
} else {
// Normal collision - game over
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Heavy camera shake for pedestrian collision
addCameraShake(30, 80);
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
}
}
// Collision detection with enemies - skip if jumping high enough
for (var i = enemyCars.length - 1; i >= 0; i--) {
var enemy = enemyCars[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove off-screen enemies
if (enemy.lastY < 2800 && enemy.y >= 2800) {
enemy.destroy();
enemyCars.splice(i, 1);
continue;
}
// Check collision with player - but not if jumping high enough
if (enemy.intersects(playerCar) && (!playerJumping || jumpHeight < 50)) {
if (hasShield) {
// Player has shield from cup - destroy enemy instead
hasShield = false;
LK.setScore(LK.getScore() + 200);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at enemy position
var explosion = game.addChild(new Explosion());
explosion.x = enemy.x;
explosion.y = enemy.y;
// Destroy the enemy
enemy.destroy();
enemyCars.splice(i, 1);
continue;
} else {
// Normal collision - game over
// Create explosion at collision point
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Strong camera shake for car collision
addCameraShake(20, 50);
// Make player car explode with tween effect
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
// Update best score if needed
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
} else if (playerJumping && jumpHeight >= 50) {
// Player jumped over enemy - bonus points!
if (!enemy.jumpedOver) {
LK.setScore(LK.getScore() + 150);
LK.getSound('dodge').play();
enemy.jumpedOver = true; // Mark to prevent multiple bonuses
}
}
// Check for near miss (score bonus)
var distanceFromPlayer = Math.abs(enemy.x - playerCar.x);
if (enemy.y > playerCar.y - 150 && enemy.y < playerCar.y + 150 && distanceFromPlayer < 200 && distanceFromPlayer > 150) {
if (!enemy.nearMissScored) {
LK.setScore(LK.getScore() + 10);
LK.getSound('dodge').play();
enemy.nearMissScored = true;
}
}
enemy.lastY = enemy.y;
}
// Update road lines
for (var k = roadLines.length - 1; k >= 0; k--) {
var line = roadLines[k];
// Remove off-screen lines
if (line.y > 2800) {
line.destroy();
roadLines.splice(k, 1);
}
}
};
pixel art ferrari bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art tofaş bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art Togg bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art gas pedal bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art nitro. In-Game asset. 2d. High contrast. No shadows
pixel art fantasy car bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art straight line,. In-Game asset. 2d. High contrast. No shadows
Gold and Glory pixel art cup. In-Game asset. 2d. High contrast. No shadows
bugatti bolide pixel art bird's eye view. In-Game asset. 2d. High contrast. No shadows
BMW X6 pixel art bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art joker. In-Game asset. 2d. High contrast. No shadows
düz sarı çizgi. In-Game asset. 2d. High contrast. No shadows
pixel art peter parker. In-Game asset. 2d. High contrast. No shadows
bird's eye pixel art motorcycle suzuki. In-Game asset. 2d. High contrast. No shadows