/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Car = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('car', { anchorX: 0.5, anchorY: 0.5 }); // Set hitbox size based on actual car asset dimensions self.hitArea = new Rectangle(-150, -200, 300, 400); // Smaller than full 400x500 for realistic collision self.currentLane = 1; // Start in second lane (0-3) self.isMoving = false; self.switchLane = function (direction) { if (self.isMoving) return; var newLane = self.currentLane + direction; if (newLane < 0 || newLane > 3) return; self.isMoving = true; self.currentLane = newLane; var targetX = lanePositions[self.currentLane]; tween(self, { x: targetX }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { self.isMoving = false; } }); }; return self; }); var LaneDivider = Container.expand(function () { var self = Container.call(this); var dividerGraphics = self.attachAsset('laneDivider', { anchorX: 0.5, anchorY: 0.5 }); self.speed = baseSpeed; self.update = function () { self.y += self.speed; if (self.y > 2732 + 50) { self.y = -50; } }; return self; }); var Obstacle = Container.expand(function (carRef) { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); // Set hitbox size based on actual obstacle asset dimensions self.hitArea = new Rectangle(-80, -120, 160, 240); // Smaller than full 210x300 for realistic collision self.speed = baseSpeed; self.transformed = false; self.carRef = carRef; self.lane = -1; // Initialize lane property self.dodged = false; // Track if this obstacle has been dodged self.update = function () { self.y += self.speed; // Track if we're close to the car if (self.carRef) { var distance = Math.abs(self.y - self.carRef.y); // Check if close AND in the same lane AND in front of car for transformation to green if (!self.transformed && distance < 750 && self.lane === self.carRef.currentLane && self.y < self.carRef.y) { // When really close and in same lane and in front of car self.transformed = true; // Transform into green circle self.removeChildren(); var greenCircle = self.attachAsset('greenCircle', { anchorX: 0.5, anchorY: 0.5 }); // Update hitbox for green circle (300x300 asset) self.hitArea = new Rectangle(-120, -120, 240, 240); } else if (self.transformed && (self.y > self.carRef.y + 100 || self.lane !== self.carRef.currentLane)) { // Transform back when car has passed or in different lane self.transformed = false; // Transform back to red obstacle self.removeChildren(); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); // Restore original obstacle hitbox self.hitArea = new Rectangle(-80, -120, 160, 240); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game constants var laneWidth = 512; // Width of each lane (2048 / 4) var lanePositions = [256, 768, 1280, 1792]; // Center of each lane var baseSpeed = 8; var currentSpeed = baseSpeed; var speedIncreaseRate = 0.0002; var obstacleSpawnDelay = 90; // Ticks between obstacle spawns var lastObstacleSpawn = 0; // Game variables var car; var obstacles = []; var laneDividers = []; var distance = 0; var scoreText; // Create road background var road = game.addChild(LK.getAsset('road', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 })); // Create lane dividers for (var lane = 0; lane < 3; lane++) { for (var i = 0; i < 30; i++) { var divider = new LaneDivider(); divider.x = (lane + 1) * laneWidth; // Place dividers at lane boundaries divider.y = i * 120; laneDividers.push(divider); game.addChild(divider); } } // Create car car = new Car(); car.x = lanePositions[1]; // Start in second lane car.y = 2200; game.addChild(car); // Score tracking without display // Input handling game.down = function (x, y, obj) { if (x < 1024) { // Left side - move left car.switchLane(-1); } else { // Right side - move right car.switchLane(1); } }; // Main game loop game.update = function () { // Update speed currentSpeed = baseSpeed + LK.ticks * speedIncreaseRate; // Update distance and score distance += currentSpeed; LK.setScore(Math.floor(distance / 10)); // Spawn obstacles if (LK.ticks - lastObstacleSpawn > obstacleSpawnDelay) { lastObstacleSpawn = LK.ticks; // Random lane for obstacle var lane = Math.floor(Math.random() * 4); var obstacle = new Obstacle(car); obstacle.x = lanePositions[lane]; obstacle.y = -100; obstacle.speed = currentSpeed; obstacle.lane = lane; // Set the lane for this obstacle obstacles.push(obstacle); game.addChild(obstacle); // Decrease spawn delay as game progresses obstacleSpawnDelay = Math.max(30, 90 - Math.floor(distance / 5000)); } // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; obstacle.speed = currentSpeed; // Check if obstacle is off screen if (obstacle.y > 2732 + 100) { obstacle.destroy(); obstacles.splice(i, 1); continue; } // Check collision with car if (obstacle.intersects(car)) { LK.showGameOver(); } // Check if obstacle has been dodged (passed the car without collision) if (!obstacle.dodged && obstacle.y > car.y + 100) { obstacle.dodged = true; LK.setScore(LK.getScore() + 10); } } // Update lane dividers speed for (var j = 0; j < laneDividers.length; j++) { laneDividers[j].speed = currentSpeed; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Car = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
// Set hitbox size based on actual car asset dimensions
self.hitArea = new Rectangle(-150, -200, 300, 400); // Smaller than full 400x500 for realistic collision
self.currentLane = 1; // Start in second lane (0-3)
self.isMoving = false;
self.switchLane = function (direction) {
if (self.isMoving) return;
var newLane = self.currentLane + direction;
if (newLane < 0 || newLane > 3) return;
self.isMoving = true;
self.currentLane = newLane;
var targetX = lanePositions[self.currentLane];
tween(self, {
x: targetX
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isMoving = false;
}
});
};
return self;
});
var LaneDivider = Container.expand(function () {
var self = Container.call(this);
var dividerGraphics = self.attachAsset('laneDivider', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = baseSpeed;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + 50) {
self.y = -50;
}
};
return self;
});
var Obstacle = Container.expand(function (carRef) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Set hitbox size based on actual obstacle asset dimensions
self.hitArea = new Rectangle(-80, -120, 160, 240); // Smaller than full 210x300 for realistic collision
self.speed = baseSpeed;
self.transformed = false;
self.carRef = carRef;
self.lane = -1; // Initialize lane property
self.dodged = false; // Track if this obstacle has been dodged
self.update = function () {
self.y += self.speed;
// Track if we're close to the car
if (self.carRef) {
var distance = Math.abs(self.y - self.carRef.y);
// Check if close AND in the same lane AND in front of car for transformation to green
if (!self.transformed && distance < 750 && self.lane === self.carRef.currentLane && self.y < self.carRef.y) {
// When really close and in same lane and in front of car
self.transformed = true;
// Transform into green circle
self.removeChildren();
var greenCircle = self.attachAsset('greenCircle', {
anchorX: 0.5,
anchorY: 0.5
});
// Update hitbox for green circle (300x300 asset)
self.hitArea = new Rectangle(-120, -120, 240, 240);
} else if (self.transformed && (self.y > self.carRef.y + 100 || self.lane !== self.carRef.currentLane)) {
// Transform back when car has passed or in different lane
self.transformed = false;
// Transform back to red obstacle
self.removeChildren();
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Restore original obstacle hitbox
self.hitArea = new Rectangle(-80, -120, 160, 240);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Game constants
var laneWidth = 512; // Width of each lane (2048 / 4)
var lanePositions = [256, 768, 1280, 1792]; // Center of each lane
var baseSpeed = 8;
var currentSpeed = baseSpeed;
var speedIncreaseRate = 0.0002;
var obstacleSpawnDelay = 90; // Ticks between obstacle spawns
var lastObstacleSpawn = 0;
// Game variables
var car;
var obstacles = [];
var laneDividers = [];
var distance = 0;
var scoreText;
// Create road background
var road = game.addChild(LK.getAsset('road', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// Create lane dividers
for (var lane = 0; lane < 3; lane++) {
for (var i = 0; i < 30; i++) {
var divider = new LaneDivider();
divider.x = (lane + 1) * laneWidth; // Place dividers at lane boundaries
divider.y = i * 120;
laneDividers.push(divider);
game.addChild(divider);
}
}
// Create car
car = new Car();
car.x = lanePositions[1]; // Start in second lane
car.y = 2200;
game.addChild(car);
// Score tracking without display
// Input handling
game.down = function (x, y, obj) {
if (x < 1024) {
// Left side - move left
car.switchLane(-1);
} else {
// Right side - move right
car.switchLane(1);
}
};
// Main game loop
game.update = function () {
// Update speed
currentSpeed = baseSpeed + LK.ticks * speedIncreaseRate;
// Update distance and score
distance += currentSpeed;
LK.setScore(Math.floor(distance / 10));
// Spawn obstacles
if (LK.ticks - lastObstacleSpawn > obstacleSpawnDelay) {
lastObstacleSpawn = LK.ticks;
// Random lane for obstacle
var lane = Math.floor(Math.random() * 4);
var obstacle = new Obstacle(car);
obstacle.x = lanePositions[lane];
obstacle.y = -100;
obstacle.speed = currentSpeed;
obstacle.lane = lane; // Set the lane for this obstacle
obstacles.push(obstacle);
game.addChild(obstacle);
// Decrease spawn delay as game progresses
obstacleSpawnDelay = Math.max(30, 90 - Math.floor(distance / 5000));
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.speed = currentSpeed;
// Check if obstacle is off screen
if (obstacle.y > 2732 + 100) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with car
if (obstacle.intersects(car)) {
LK.showGameOver();
}
// Check if obstacle has been dodged (passed the car without collision)
if (!obstacle.dodged && obstacle.y > car.y + 100) {
obstacle.dodged = true;
LK.setScore(LK.getScore() + 10);
}
}
// Update lane dividers speed
for (var j = 0; j < laneDividers.length; j++) {
laneDividers[j].speed = currentSpeed;
}
};