/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highscore: 0 }); /**** * Classes ****/ // Player Car var Car = Container.expand(function () { var self = Container.call(this); var carAsset = self.attachAsset('car', { anchorX: 0.5, anchorY: 0.5 }); self.width = carAsset.width; self.height = carAsset.height; // For collision box // Removed custom getBounds to avoid recursion bug return self; }); // Coin var Coin = Container.expand(function () { var self = Container.call(this); var coinAsset = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.width = coinAsset.width; self.height = coinAsset.height; self.speed = 10; // Will be increased by game self.update = function () { self.y += self.speed; }; // Removed custom getBounds to avoid recursion bug return self; }); // Obstacle var Obstacle = Container.expand(function () { var self = Container.call(this); var obsAsset = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); // Assign a random color tint to the obstacle asset var obstacleColors = [0xff4444, // red 0x44aaff, // blue 0x44ff44, // green 0xffcc44, // yellow 0xff44cc, // pink 0xffffff, // white 0xff8800, // orange 0x888888 // gray ]; var colorIdx = Math.floor(Math.random() * obstacleColors.length); obsAsset.tint = obstacleColors[colorIdx]; self.width = obsAsset.width; self.height = obsAsset.height; self.speed = 10; // Will be increased by game self.update = function () { // Store lastX for event triggers if needed if (self.lastX === undefined) self.lastX = self.x; // Move down self.y += self.speed; // Smoothly tween X position for swerving if (!self._swerveTween || self._swerveTween.finished) { // Pick a new target X within lane bounds var laneIdx = Math.floor(self.x / (2048 / 3)); var laneLeft = laneIdx * (2048 / 3); var laneRight = (laneIdx + 1) * (2048 / 3); var minX = laneLeft + self.width / 2; var maxX = laneRight - self.width / 2; var swerveAmount = 120 + Math.random() * 120; // up to 240px swerve var direction = Math.random() < 0.5 ? -1 : 1; var targetX = self.x + direction * swerveAmount; targetX = Math.max(minX, Math.min(maxX, targetX)); // Tween to new X over 0.3-0.6s var duration = 300 + Math.random() * 300; self._swerveTween = { finished: false }; tween(self, { x: targetX }, { duration: duration, easing: tween.easeInOut, onFinish: function onFinish() { self._swerveTween.finished = true; } }); } self.lastX = self.x; }; // Removed custom getBounds to avoid recursion bug return self; }); // RoadLine: vertical dashed line for road center/lanes var RoadLine = Container.expand(function () { var self = Container.call(this); // Parameters for dashed line var dashHeight = 120; var gap = 80; var lineWidth = 24; var color = 0xffffff; var y = 0; // Fill vertical line with dashes while (y < 2732 + dashHeight) { var dash = LK.getAsset('roadline_dash', { width: lineWidth, height: dashHeight, color: color, shape: 'box', anchorX: 0.5, anchorY: 0 }); dash.x = 0; dash.y = y; self.addChild(dash); y += dashHeight + gap; } return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game area // Car (player) // Obstacle // Coin var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; // Lane system (3 lanes) var LANE_COUNT = 3; var LANE_WIDTH = GAME_WIDTH / LANE_COUNT; var LANE_X = [Math.floor(LANE_WIDTH / 2), Math.floor(GAME_WIDTH / 2), Math.floor(GAME_WIDTH - LANE_WIDTH / 2)]; // Draw road lines (between lanes) var roadLines = []; for (var i = 1; i < LANE_COUNT; i++) { var line = new RoadLine(); line.x = i * LANE_WIDTH; line.y = 0; game.addChild(line); roadLines.push(line); } // Add roadside bars (left and right) var barWidth = 60; var barColor = 0x888888; var barHeight = GAME_HEIGHT + 200; // a bit longer for scrolling var leftBar = LK.getAsset('roadline_dash', { width: barWidth, height: barHeight, color: barColor, shape: 'box', anchorX: 0.5, anchorY: 0 }); leftBar.x = barWidth / 2; leftBar.y = -100; game.addChild(leftBar); var rightBar = LK.getAsset('roadline_dash', { width: barWidth, height: barHeight, color: barColor, shape: 'box', anchorX: 0.5, anchorY: 0 }); rightBar.x = GAME_WIDTH - barWidth / 2; rightBar.y = -100; game.addChild(rightBar); // For rolling stripes var roadLineSpeed = 14; // Stripes move faster than obstacles // Player car var car = new Car(); game.addChild(car); car.x = GAME_WIDTH / 2; car.y = GAME_HEIGHT - 400; // Dragging var dragCar = false; var dragOffsetX = 0; // Mouse control toggle var mouseEnabled = true; function toggleMouse() { mouseEnabled = !mouseEnabled; } // Obstacles and coins var obstacles = []; var coins = []; // Difficulty var baseSpeed = 10; // Slower starting speed var speed = baseSpeed; var speedIncreaseInterval = 600; // every 10 seconds (60*10) var minObstacleInterval = 36; // minimum ticks between obstacles var obstacleInterval = 60; // ticks between obstacles, will decrease var minCoinInterval = 30; var coinInterval = 60; // Score var score = 0; var highscore = storage.highscore || 0; // Game state: wait for click to start var gameStarted = false; // Lives for extra life mechanic var lives = 0; // Start with zero life // Heart asset for lives display (show as hearts in lower left) var heartAssets = []; var maxHearts = 10; // reasonable max for display for (var h = 0; h < maxHearts; h++) { var heart = LK.getAsset('coin', { // Use coin as heart for now anchorX: 0.5, anchorY: 0.5 }); heart.width = 80; heart.height = 80; // Place hearts in lower right, spaced leftward, with 60px margin from right heart.x = LK.gui.bottom.width - 60 - h * 90; heart.y = LK.gui.bottom.height - 80; heart.visible = false; LK.gui.bottom.addChild(heart); heartAssets.push(heart); } // Helper to update hearts display function updateHearts() { for (var i = 0; i < heartAssets.length; i++) { heartAssets[i].visible = i < lives; } } updateHearts(); var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var highscoreTxt = new Text2('High Score: ' + highscore, { size: 60, fill: 0xFFFF88 }); highscoreTxt.anchor.set(0.5, 0); highscoreTxt.x = LK.gui.top.width / 2; highscoreTxt.y = 150; LK.gui.top.addChild(highscoreTxt); // Start text overlay var startTxt = new Text2('Tap to Start', { size: 120, fill: "#fff" }); startTxt.anchor.set(0.5, 0.5); startTxt.x = LK.gui.top.width / 2; startTxt.y = 400; LK.gui.top.addChild(startTxt); // Helper: collision function rectsIntersect(a, b) { return !(a.x + a.width < b.x || a.x > b.x + b.width || a.y + a.height < b.y || a.y > b.y + b.height); } // Touch controls function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); } game.down = function (x, y, obj) { if (!gameStarted) { // Start game on first tap gameStarted = true; if (startTxt && startTxt.parent) { startTxt.parent.removeChild(startTxt); } return; } // Only start drag if touch is on car and mouse is enabled if (!mouseEnabled) return; var local = car.toLocal(game.toGlobal({ x: x, y: y })); if (local.x >= -car.width / 2 && local.x <= car.width / 2 && local.y >= -car.height / 2 && local.y <= car.height / 2) { dragCar = true; dragOffsetX = car.x - x; } }; game.move = function (x, y, obj) { if (!gameStarted) return; if (!mouseEnabled) return; if (dragCar) { // Only move horizontally, clamp to game area var newX = clamp(x + dragOffsetX, car.width / 2, GAME_WIDTH - car.width / 2); car.x = newX; } }; game.up = function (x, y, obj) { if (!gameStarted) return; if (!mouseEnabled) return; dragCar = false; }; // Spawning var lastObstacleTick = 0; var lastCoinTick = 0; // Main update loop game.update = function () { if (!gameStarted) return; // Increase speed and difficulty over time if (LK.ticks % speedIncreaseInterval === 0 && LK.ticks > 0) { speed += 1; // Slower speed increase obstacleInterval = Math.max(minObstacleInterval, obstacleInterval - 4); coinInterval = Math.max(minCoinInterval, coinInterval - 2); } // Spawn obstacles if (LK.ticks - lastObstacleTick >= obstacleInterval) { // Randomly choose which obstacle type to spawn var obsType = Math.random() < 0.5 ? 'obstacle' : 'obstacle2'; var obs; if (obsType === 'obstacle') { obs = new Obstacle(); } else { // Use obstacle2 asset for variety obs = new Obstacle(); var obsAsset = obs.children[0]; obsAsset.texture = LK.getAsset('obstacle2', { anchorX: 0.5, anchorY: 0.5 }).texture; obs.width = obsAsset.width; obs.height = obsAsset.height; } obs.speed = speed; // Random lane var lane = Math.floor(Math.random() * LANE_COUNT); // Allow obstacle to be anywhere inside the lane, not just center var laneLeft = lane * LANE_WIDTH; var laneRight = (lane + 1) * LANE_WIDTH; var minX = laneLeft + obs.width / 2; var maxX = laneRight - obs.width / 2; obs.x = minX + Math.random() * (maxX - minX); obs.y = -obs.height / 2; obstacles.push(obs); game.addChild(obs); lastObstacleTick = LK.ticks; } // Spawn coins if (LK.ticks - lastCoinTick >= coinInterval) { var coin = new Coin(); coin.speed = speed; // Random lane, but not same as last obstacle var lane = Math.floor(Math.random() * LANE_COUNT); coin.x = LANE_X[lane]; coin.y = -coin.height / 2 - 200; coins.push(coin); game.addChild(coin); lastCoinTick = LK.ticks; } // Move road lines down and wrap for (var rl = 0; rl < roadLines.length; rl++) { var line = roadLines[rl]; line.y += roadLineSpeed; // The height of the dashed line pattern is dash+gap repeated, so wrap when y > dash+gap // We know from RoadLine: dashHeight=120, gap=80, so pattern=200 var patternHeight = 120 + 80; if (line.y >= patternHeight) { line.y -= patternHeight; } } // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.update(); // Remove if off screen if (obs.y - obs.height / 2 > GAME_HEIGHT + 100) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision with car if (rectsIntersect(obs.getBounds(), car.getBounds())) { // Flash LK.effects.flashScreen(0xff0000, 800); if (lives > 0) { lives -= 1; updateHearts(); // Remove the obstacle and continue obs.destroy(); obstacles.splice(i, 1); continue; } else { LK.showGameOver(); return; } } } // Update coins for (var j = coins.length - 1; j >= 0; j--) { var coin = coins[j]; coin.update(); // Remove if off screen if (coin.y - coin.height / 2 > GAME_HEIGHT + 100) { coin.destroy(); coins.splice(j, 1); continue; } // Collect coin if (rectsIntersect(coin.getBounds(), car.getBounds())) { score += 1; LK.setScore(score); scoreTxt.setText(score); // Grant extra life every 50 points if (score > 0 && score % 50 === 0) { lives += 1; updateHearts(); } // Update highscore if beaten if (score > highscore) { highscore = score; storage.highscore = highscore; highscoreTxt.setText('High Score: ' + highscore); } // Speed up game by 10% every 10 points if (score % 10 === 0 && score > 0) { speed = Math.round(speed * 1.1); // Also update all current obstacles and coins to new speed for (var oi = 0; oi < obstacles.length; oi++) { obstacles[oi].speed = speed; } for (var ci = 0; ci < coins.length; ci++) { coins[ci].speed = speed; } // Also speed up road lines by 10% roadLineSpeed = Math.round(roadLineSpeed * 1.1); } // Animate coin tween(coin, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { coin.destroy(); } }); coins.splice(j, 1); } } }; // Center score text at top, avoid top left 100x100 scoreTxt.x = LK.gui.top.width / 2; scoreTxt.y = 20;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highscore: 0
});
/****
* Classes
****/
// Player Car
var Car = Container.expand(function () {
var self = Container.call(this);
var carAsset = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = carAsset.width;
self.height = carAsset.height;
// For collision box
// Removed custom getBounds to avoid recursion bug
return self;
});
// Coin
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinAsset = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = coinAsset.width;
self.height = coinAsset.height;
self.speed = 10; // Will be increased by game
self.update = function () {
self.y += self.speed;
};
// Removed custom getBounds to avoid recursion bug
return self;
});
// Obstacle
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsAsset = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Assign a random color tint to the obstacle asset
var obstacleColors = [0xff4444,
// red
0x44aaff,
// blue
0x44ff44,
// green
0xffcc44,
// yellow
0xff44cc,
// pink
0xffffff,
// white
0xff8800,
// orange
0x888888 // gray
];
var colorIdx = Math.floor(Math.random() * obstacleColors.length);
obsAsset.tint = obstacleColors[colorIdx];
self.width = obsAsset.width;
self.height = obsAsset.height;
self.speed = 10; // Will be increased by game
self.update = function () {
// Store lastX for event triggers if needed
if (self.lastX === undefined) self.lastX = self.x;
// Move down
self.y += self.speed;
// Smoothly tween X position for swerving
if (!self._swerveTween || self._swerveTween.finished) {
// Pick a new target X within lane bounds
var laneIdx = Math.floor(self.x / (2048 / 3));
var laneLeft = laneIdx * (2048 / 3);
var laneRight = (laneIdx + 1) * (2048 / 3);
var minX = laneLeft + self.width / 2;
var maxX = laneRight - self.width / 2;
var swerveAmount = 120 + Math.random() * 120; // up to 240px swerve
var direction = Math.random() < 0.5 ? -1 : 1;
var targetX = self.x + direction * swerveAmount;
targetX = Math.max(minX, Math.min(maxX, targetX));
// Tween to new X over 0.3-0.6s
var duration = 300 + Math.random() * 300;
self._swerveTween = {
finished: false
};
tween(self, {
x: targetX
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
self._swerveTween.finished = true;
}
});
}
self.lastX = self.x;
};
// Removed custom getBounds to avoid recursion bug
return self;
});
// RoadLine: vertical dashed line for road center/lanes
var RoadLine = Container.expand(function () {
var self = Container.call(this);
// Parameters for dashed line
var dashHeight = 120;
var gap = 80;
var lineWidth = 24;
var color = 0xffffff;
var y = 0;
// Fill vertical line with dashes
while (y < 2732 + dashHeight) {
var dash = LK.getAsset('roadline_dash', {
width: lineWidth,
height: dashHeight,
color: color,
shape: 'box',
anchorX: 0.5,
anchorY: 0
});
dash.x = 0;
dash.y = y;
self.addChild(dash);
y += dashHeight + gap;
}
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Game area
// Car (player)
// Obstacle
// Coin
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Lane system (3 lanes)
var LANE_COUNT = 3;
var LANE_WIDTH = GAME_WIDTH / LANE_COUNT;
var LANE_X = [Math.floor(LANE_WIDTH / 2), Math.floor(GAME_WIDTH / 2), Math.floor(GAME_WIDTH - LANE_WIDTH / 2)];
// Draw road lines (between lanes)
var roadLines = [];
for (var i = 1; i < LANE_COUNT; i++) {
var line = new RoadLine();
line.x = i * LANE_WIDTH;
line.y = 0;
game.addChild(line);
roadLines.push(line);
}
// Add roadside bars (left and right)
var barWidth = 60;
var barColor = 0x888888;
var barHeight = GAME_HEIGHT + 200; // a bit longer for scrolling
var leftBar = LK.getAsset('roadline_dash', {
width: barWidth,
height: barHeight,
color: barColor,
shape: 'box',
anchorX: 0.5,
anchorY: 0
});
leftBar.x = barWidth / 2;
leftBar.y = -100;
game.addChild(leftBar);
var rightBar = LK.getAsset('roadline_dash', {
width: barWidth,
height: barHeight,
color: barColor,
shape: 'box',
anchorX: 0.5,
anchorY: 0
});
rightBar.x = GAME_WIDTH - barWidth / 2;
rightBar.y = -100;
game.addChild(rightBar);
// For rolling stripes
var roadLineSpeed = 14; // Stripes move faster than obstacles
// Player car
var car = new Car();
game.addChild(car);
car.x = GAME_WIDTH / 2;
car.y = GAME_HEIGHT - 400;
// Dragging
var dragCar = false;
var dragOffsetX = 0;
// Mouse control toggle
var mouseEnabled = true;
function toggleMouse() {
mouseEnabled = !mouseEnabled;
}
// Obstacles and coins
var obstacles = [];
var coins = [];
// Difficulty
var baseSpeed = 10; // Slower starting speed
var speed = baseSpeed;
var speedIncreaseInterval = 600; // every 10 seconds (60*10)
var minObstacleInterval = 36; // minimum ticks between obstacles
var obstacleInterval = 60; // ticks between obstacles, will decrease
var minCoinInterval = 30;
var coinInterval = 60;
// Score
var score = 0;
var highscore = storage.highscore || 0;
// Game state: wait for click to start
var gameStarted = false;
// Lives for extra life mechanic
var lives = 0; // Start with zero life
// Heart asset for lives display (show as hearts in lower left)
var heartAssets = [];
var maxHearts = 10; // reasonable max for display
for (var h = 0; h < maxHearts; h++) {
var heart = LK.getAsset('coin', {
// Use coin as heart for now
anchorX: 0.5,
anchorY: 0.5
});
heart.width = 80;
heart.height = 80;
// Place hearts in lower right, spaced leftward, with 60px margin from right
heart.x = LK.gui.bottom.width - 60 - h * 90;
heart.y = LK.gui.bottom.height - 80;
heart.visible = false;
LK.gui.bottom.addChild(heart);
heartAssets.push(heart);
}
// Helper to update hearts display
function updateHearts() {
for (var i = 0; i < heartAssets.length; i++) {
heartAssets[i].visible = i < lives;
}
}
updateHearts();
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var highscoreTxt = new Text2('High Score: ' + highscore, {
size: 60,
fill: 0xFFFF88
});
highscoreTxt.anchor.set(0.5, 0);
highscoreTxt.x = LK.gui.top.width / 2;
highscoreTxt.y = 150;
LK.gui.top.addChild(highscoreTxt);
// Start text overlay
var startTxt = new Text2('Tap to Start', {
size: 120,
fill: "#fff"
});
startTxt.anchor.set(0.5, 0.5);
startTxt.x = LK.gui.top.width / 2;
startTxt.y = 400;
LK.gui.top.addChild(startTxt);
// Helper: collision
function rectsIntersect(a, b) {
return !(a.x + a.width < b.x || a.x > b.x + b.width || a.y + a.height < b.y || a.y > b.y + b.height);
}
// Touch controls
function clamp(val, min, max) {
return Math.max(min, Math.min(max, val));
}
game.down = function (x, y, obj) {
if (!gameStarted) {
// Start game on first tap
gameStarted = true;
if (startTxt && startTxt.parent) {
startTxt.parent.removeChild(startTxt);
}
return;
}
// Only start drag if touch is on car and mouse is enabled
if (!mouseEnabled) return;
var local = car.toLocal(game.toGlobal({
x: x,
y: y
}));
if (local.x >= -car.width / 2 && local.x <= car.width / 2 && local.y >= -car.height / 2 && local.y <= car.height / 2) {
dragCar = true;
dragOffsetX = car.x - x;
}
};
game.move = function (x, y, obj) {
if (!gameStarted) return;
if (!mouseEnabled) return;
if (dragCar) {
// Only move horizontally, clamp to game area
var newX = clamp(x + dragOffsetX, car.width / 2, GAME_WIDTH - car.width / 2);
car.x = newX;
}
};
game.up = function (x, y, obj) {
if (!gameStarted) return;
if (!mouseEnabled) return;
dragCar = false;
};
// Spawning
var lastObstacleTick = 0;
var lastCoinTick = 0;
// Main update loop
game.update = function () {
if (!gameStarted) return;
// Increase speed and difficulty over time
if (LK.ticks % speedIncreaseInterval === 0 && LK.ticks > 0) {
speed += 1; // Slower speed increase
obstacleInterval = Math.max(minObstacleInterval, obstacleInterval - 4);
coinInterval = Math.max(minCoinInterval, coinInterval - 2);
}
// Spawn obstacles
if (LK.ticks - lastObstacleTick >= obstacleInterval) {
// Randomly choose which obstacle type to spawn
var obsType = Math.random() < 0.5 ? 'obstacle' : 'obstacle2';
var obs;
if (obsType === 'obstacle') {
obs = new Obstacle();
} else {
// Use obstacle2 asset for variety
obs = new Obstacle();
var obsAsset = obs.children[0];
obsAsset.texture = LK.getAsset('obstacle2', {
anchorX: 0.5,
anchorY: 0.5
}).texture;
obs.width = obsAsset.width;
obs.height = obsAsset.height;
}
obs.speed = speed;
// Random lane
var lane = Math.floor(Math.random() * LANE_COUNT);
// Allow obstacle to be anywhere inside the lane, not just center
var laneLeft = lane * LANE_WIDTH;
var laneRight = (lane + 1) * LANE_WIDTH;
var minX = laneLeft + obs.width / 2;
var maxX = laneRight - obs.width / 2;
obs.x = minX + Math.random() * (maxX - minX);
obs.y = -obs.height / 2;
obstacles.push(obs);
game.addChild(obs);
lastObstacleTick = LK.ticks;
}
// Spawn coins
if (LK.ticks - lastCoinTick >= coinInterval) {
var coin = new Coin();
coin.speed = speed;
// Random lane, but not same as last obstacle
var lane = Math.floor(Math.random() * LANE_COUNT);
coin.x = LANE_X[lane];
coin.y = -coin.height / 2 - 200;
coins.push(coin);
game.addChild(coin);
lastCoinTick = LK.ticks;
}
// Move road lines down and wrap
for (var rl = 0; rl < roadLines.length; rl++) {
var line = roadLines[rl];
line.y += roadLineSpeed;
// The height of the dashed line pattern is dash+gap repeated, so wrap when y > dash+gap
// We know from RoadLine: dashHeight=120, gap=80, so pattern=200
var patternHeight = 120 + 80;
if (line.y >= patternHeight) {
line.y -= patternHeight;
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.update();
// Remove if off screen
if (obs.y - obs.height / 2 > GAME_HEIGHT + 100) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with car
if (rectsIntersect(obs.getBounds(), car.getBounds())) {
// Flash
LK.effects.flashScreen(0xff0000, 800);
if (lives > 0) {
lives -= 1;
updateHearts();
// Remove the obstacle and continue
obs.destroy();
obstacles.splice(i, 1);
continue;
} else {
LK.showGameOver();
return;
}
}
}
// Update coins
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
coin.update();
// Remove if off screen
if (coin.y - coin.height / 2 > GAME_HEIGHT + 100) {
coin.destroy();
coins.splice(j, 1);
continue;
}
// Collect coin
if (rectsIntersect(coin.getBounds(), car.getBounds())) {
score += 1;
LK.setScore(score);
scoreTxt.setText(score);
// Grant extra life every 50 points
if (score > 0 && score % 50 === 0) {
lives += 1;
updateHearts();
}
// Update highscore if beaten
if (score > highscore) {
highscore = score;
storage.highscore = highscore;
highscoreTxt.setText('High Score: ' + highscore);
}
// Speed up game by 10% every 10 points
if (score % 10 === 0 && score > 0) {
speed = Math.round(speed * 1.1);
// Also update all current obstacles and coins to new speed
for (var oi = 0; oi < obstacles.length; oi++) {
obstacles[oi].speed = speed;
}
for (var ci = 0; ci < coins.length; ci++) {
coins[ci].speed = speed;
}
// Also speed up road lines by 10%
roadLineSpeed = Math.round(roadLineSpeed * 1.1);
}
// Animate coin
tween(coin, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
coin.destroy();
}
});
coins.splice(j, 1);
}
}
};
// Center score text at top, avoid top left 100x100
scoreTxt.x = LK.gui.top.width / 2;
scoreTxt.y = 20;