/**** * Classes ****/ var Barricade = Container.expand(function () { var self = Container.call(this); var blockGraphics = self.attachAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); blockGraphics.width = 300; blockGraphics.height = 300; self.width = blockGraphics.width; self.height = blockGraphics.height; self.hit = false; return self; }); var Car = Container.expand(function () { var self = Container.call(this); self.projectMovement = function (vector) { var angle = -Math.PI / 4; var cosAngle = Math.cos(angle); var sinAngle = Math.sin(angle); return { x: vector.x * cosAngle - vector.y * sinAngle, y: vector.x * sinAngle + vector.y * cosAngle }; }; var carGraphics = self.attachAsset('car', { anchorX: 0.5, anchorY: 0.5 }); self.ORIGINAL_SPEED = 2; self.speed = self.ORIGINAL_SPEED; self.direction = 0; self.momentum = { x: 0, y: 0 }; self._move_migrated = function () { var momentumModifier = 0.1; self.speed *= 1.01; if (self.direction === 0) { self.momentum.x += self.speed * momentumModifier; } else { self.momentum.y -= self.speed * momentumModifier; } var projectedMovement = self.projectMovement(self.momentum); self.x += projectedMovement.x; self.y += projectedMovement.y; var nonTravelMomentum; if (self.direction === 0) { self.momentum.x *= 0.98; self.momentum.y *= 0.95; nonTravelMomentum = self.momentum.y; } else { self.momentum.x *= 0.95; self.momentum.y *= 0.98; nonTravelMomentum = self.momentum.x; } self.nonTravelMomentum = nonTravelMomentum; }; self.changeDirection = function () { self.direction = self.direction === 0 ? 1 : 0; self.speed = self.ORIGINAL_SPEED; carGraphics.scale.x *= -1; LK.getSound('Skid').play(); }; }); var GoldenApple = Container.expand(function () { var self = Container.call(this); var appleGraphics = self.attachAsset('goldenApple', { anchorX: 0.5, anchorY: 0.5 }); self.width = appleGraphics.width; self.height = appleGraphics.height; self.collected = false; return self; }); var Heart = Container.expand(function () { var self = Container.call(this); var heartGraphics = self.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); self.width = heartGraphics.width; self.height = heartGraphics.height; self.collected = false; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); particleGraphics.rotation = Math.PI / 4; self.lifetime = 100; self.tick = function () { if (--self.lifetime <= 0) { self.destroy(); } }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ game.calculateDistanceToPoint = function (point, segmentStart, segmentEnd) { var A = point.x - segmentStart.x; var B = point.y - segmentStart.y; var C = segmentEnd.x - segmentStart.x; var D = segmentEnd.y - segmentStart.y; var dot = A * C + B * D; var len_sq = C * C + D * D; var param = -1; if (len_sq != 0) { param = dot / len_sq; } var xx, yy; if (param < 0) { xx = segmentStart.x; yy = segmentStart.y; } else if (param > 1) { xx = segmentEnd.x; yy = segmentEnd.y; } else { xx = segmentStart.x + param * C; yy = segmentStart.y + param * D; } var dx = point.x - xx; var dy = point.y - yy; return Math.sqrt(dx * dx + dy * dy); }; game.addRoadSegment = function () { var lastSegment = roadSegments[roadSegments.length - 1]; zigzag = !zigzag; var segment = roadContainer.attachAsset('roadSegment', { anchorX: 0.5 }); segment.width = segmentWidth; segmentWidth = Math.max(250, segmentWidth - 15); segment.height = i === 1 ? 3000 : Math.floor(Math.random() * (4000 - 1200 + 1)) + 1200; segment.rotation = zigzag ? -Math.PI - Math.PI / 4 : -Math.PI + Math.PI / 4; segment.y = currentY; segment.x = currentX; var adjustedHeight = segment.height - segmentWidth / 2; currentY += adjustedHeight * Math.cos(segment.rotation); currentX -= adjustedHeight * Math.sin(segment.rotation); segment.shadow = roadContainer.attachAsset('roadSegmentShadow', { anchorX: 0.5 }); segment.shadow.width = segment.width; segment.shadow.height = segment.height; segment.shadow.rotation = segment.rotation; segment.shadow.x = segment.x; segment.shadow.y = segment.y + 50; segment.shadow.alpha = 1; segment.used = false; roadSegments.push(segment); roadContainer.addChildAt(segment.shadow, 0); roadContainer.addChild(segment); }; game.setBackgroundColor(0xc39977); var particles = []; LK.playMusic('backgroundMusic'); var hearts = []; var goldenApples = []; var mainContainer = game.addChild(new Container()); var roadContainer = mainContainer.addChild(new Container()); var roadSegments = []; var roadblocks = []; var segmentLength = Math.floor(Math.random() * (1000 - 200 + 1)) + 200; var segmentWidth = 1200; var currentX = 2048 / 2; var currentY = 2732 / 2; var zigzag = true; for (var i = 1; i <= 25; i++) { game.addRoadSegment(); } // Place hearts on 5 random segments (not the first one) var heartSegments = []; while (heartSegments.length < 5) { var idx = Math.floor(Math.random() * (roadSegments.length - 2)) + 1; if (heartSegments.indexOf(idx) === -1) heartSegments.push(idx); } for (var h = 0; h < heartSegments.length; h++) { var seg = roadSegments[heartSegments[h]]; var heart = new Heart(); // Place heart at center of segment heart.x = seg.x; heart.y = seg.y; mainContainer.addChild(heart); hearts.push(heart); } // Place golden apples on 2 random segments (not the first one), rare var goldenAppleSegments = []; while (goldenAppleSegments.length < 2) { var idx = Math.floor(Math.random() * (roadSegments.length - 2)) + 1; if (goldenAppleSegments.indexOf(idx) === -1 && heartSegments.indexOf(idx) === -1) goldenAppleSegments.push(idx); } for (var g = 0; g < goldenAppleSegments.length; g++) { var seg = roadSegments[goldenAppleSegments[g]]; var goldenApple = new GoldenApple(); goldenApple.x = seg.x; goldenApple.y = seg.y; mainContainer.addChild(goldenApple); goldenApples.push(goldenApple); } // Place roadblocks on 4 random segments (not the first one) var roadblockSegments = []; while (roadblockSegments.length < 4) { var idx = Math.floor(Math.random() * (roadSegments.length - 2)) + 1; if (roadblockSegments.indexOf(idx) === -1 && heartSegments.indexOf(idx) === -1 && goldenAppleSegments.indexOf(idx) === -1) roadblockSegments.push(idx); } for (var r = 0; r < roadblockSegments.length; r++) { var seg = roadSegments[roadblockSegments[r]]; var barricade = new Barricade(); barricade.x = seg.x; barricade.y = seg.y; mainContainer.addChild(barricade); roadblocks.push(barricade); } var scoreText = new Text2('0', { size: 150, fill: 0xFFFFFF, weight: '800', dropShadow: true, dropShadowColor: '#373330', dropShadowBlur: 4, dropShadowAngle: Math.PI / 6, dropShadowDistance: 6 }); scoreText.anchor.set(0, 0); LK.gui.top.addChild(scoreText); // Level system removed var car = mainContainer.addChild(new Car()); car.x = 2048 / 2; car.y = 2732 / 2; var isGameOver = false; var score = 0; var closestSegment = null; game.on('down', function (x, y, obj) { car.changeDirection(); }); LK.on('tick', function () { car._move_migrated(); var carIsOnRoad = false; var carPosition = { x: car.x, y: car.y }; var currentClosestSegment = null; var currentClosestDistance = Infinity; roadSegments.forEach(function (segment) { var segmentStart = { x: segment.x + Math.sin(segment.rotation) * 100, y: segment.y - Math.cos(segment.rotation) * 100 }; var segmentEnd = { x: segment.x - Math.sin(segment.rotation) * (segment.height - segment.width / 2), y: segment.y + Math.cos(segment.rotation) * (segment.height - segment.width / 2) }; var distance = game.calculateDistanceToPoint(carPosition, segmentStart, segmentEnd); if (distance < currentClosestDistance) { currentClosestDistance = distance; currentClosestSegment = segment; } if (distance < segment.width / 2 - 50) { carIsOnRoad = true; } }); if (closestSegment !== currentClosestSegment && !currentClosestSegment.used) { closestSegment = currentClosestSegment; closestSegment.used = true; score++; car.ORIGINAL_SPEED += 0.1; scoreText.setText(score.toString()); } // Check for heart collection for (var h = 0; h < hearts.length; h++) { var heart = hearts[h]; if (!heart.collected && Math.abs(car.x - heart.x) < 80 && Math.abs(car.y - heart.y) < 80) { heart.collected = true; heart.visible = false; score = score * 2; scoreText.setText(score.toString()); } } // Check for golden apple collection for (var g = 0; g < goldenApples.length; g++) { var goldenApple = goldenApples[g]; if (!goldenApple.collected && Math.abs(car.x - goldenApple.x) < 80 && Math.abs(car.y - goldenApple.y) < 80) { goldenApple.collected = true; goldenApple.visible = false; score += 5; scoreText.setText(score.toString()); } } // Check for roadblock collision var hitRoadblock = false; for (var r = 0; r < roadblocks.length; r++) { var roadblock = roadblocks[r]; // Use .intersects for precise collision detection if (!roadblock.hit && car.intersects(roadblock)) { roadblock.hit = true; hitRoadblock = true; break; } } if (!carIsOnRoad || hitRoadblock) { LK.showGameOver(); } else {} var particleOffsets = [{ x: 20, y: 140 }, { x: 20 + 100, y: 140 - 100 }, { x: 20 - 150, y: 140 - 150 }, { x: 20 - 150 + 100, y: 140 - 150 - 100 }]; for (var i = 0; i < particleOffsets.length; i++) { var alphaValue = Math.max(0, Math.min(1, Math.abs(car.nonTravelMomentum) / 5 - 0.5)); if (alphaValue > 0) { var particle = new Particle(); particle.alpha = alphaValue; var noiseX = (Math.random() - 0.5) * 10; var noiseY = (Math.random() - 0.5) * 10; particle.x = car.x + (car.direction === 0 ? -1 : 1) * particleOffsets[i].x + noiseX; particle.y = car.y + particleOffsets[i].y + noiseY; mainContainer.addChildAt(particle, 1); particles.push(particle); } } particles.forEach(function (particle, index) { particle.tick(); if (particle.lifetime <= 0) { particles.splice(index, 1); } }); var carLocalPosition = game.toLocal(car.position, car.parent); var offsetX = (2048 / 2 - carLocalPosition.x) / 20; var offsetY = (2732 - 450 - carLocalPosition.y) / 20; mainContainer.x += offsetX; mainContainer.y += offsetY; for (var i = roadSegments.length - 1; i >= 0; i--) { var segmentGlobalPosition = game.toLocal(roadSegments[i].position, roadSegments[i].parent); if (segmentGlobalPosition.y - roadSegments[i].height > 2732 * 2) { roadSegments[i].shadow.destroy(); roadSegments[i].destroy(); roadSegments.splice(i, 1); game.addRoadSegment(); } } });
/****
* Classes
****/
var Barricade = Container.expand(function () {
var self = Container.call(this);
var blockGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
blockGraphics.width = 300;
blockGraphics.height = 300;
self.width = blockGraphics.width;
self.height = blockGraphics.height;
self.hit = false;
return self;
});
var Car = Container.expand(function () {
var self = Container.call(this);
self.projectMovement = function (vector) {
var angle = -Math.PI / 4;
var cosAngle = Math.cos(angle);
var sinAngle = Math.sin(angle);
return {
x: vector.x * cosAngle - vector.y * sinAngle,
y: vector.x * sinAngle + vector.y * cosAngle
};
};
var carGraphics = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
self.ORIGINAL_SPEED = 2;
self.speed = self.ORIGINAL_SPEED;
self.direction = 0;
self.momentum = {
x: 0,
y: 0
};
self._move_migrated = function () {
var momentumModifier = 0.1;
self.speed *= 1.01;
if (self.direction === 0) {
self.momentum.x += self.speed * momentumModifier;
} else {
self.momentum.y -= self.speed * momentumModifier;
}
var projectedMovement = self.projectMovement(self.momentum);
self.x += projectedMovement.x;
self.y += projectedMovement.y;
var nonTravelMomentum;
if (self.direction === 0) {
self.momentum.x *= 0.98;
self.momentum.y *= 0.95;
nonTravelMomentum = self.momentum.y;
} else {
self.momentum.x *= 0.95;
self.momentum.y *= 0.98;
nonTravelMomentum = self.momentum.x;
}
self.nonTravelMomentum = nonTravelMomentum;
};
self.changeDirection = function () {
self.direction = self.direction === 0 ? 1 : 0;
self.speed = self.ORIGINAL_SPEED;
carGraphics.scale.x *= -1;
LK.getSound('Skid').play();
};
});
var GoldenApple = Container.expand(function () {
var self = Container.call(this);
var appleGraphics = self.attachAsset('goldenApple', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = appleGraphics.width;
self.height = appleGraphics.height;
self.collected = false;
return self;
});
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartGraphics = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = heartGraphics.width;
self.height = heartGraphics.height;
self.collected = false;
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
particleGraphics.rotation = Math.PI / 4;
self.lifetime = 100;
self.tick = function () {
if (--self.lifetime <= 0) {
self.destroy();
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
game.calculateDistanceToPoint = function (point, segmentStart, segmentEnd) {
var A = point.x - segmentStart.x;
var B = point.y - segmentStart.y;
var C = segmentEnd.x - segmentStart.x;
var D = segmentEnd.y - segmentStart.y;
var dot = A * C + B * D;
var len_sq = C * C + D * D;
var param = -1;
if (len_sq != 0) {
param = dot / len_sq;
}
var xx, yy;
if (param < 0) {
xx = segmentStart.x;
yy = segmentStart.y;
} else if (param > 1) {
xx = segmentEnd.x;
yy = segmentEnd.y;
} else {
xx = segmentStart.x + param * C;
yy = segmentStart.y + param * D;
}
var dx = point.x - xx;
var dy = point.y - yy;
return Math.sqrt(dx * dx + dy * dy);
};
game.addRoadSegment = function () {
var lastSegment = roadSegments[roadSegments.length - 1];
zigzag = !zigzag;
var segment = roadContainer.attachAsset('roadSegment', {
anchorX: 0.5
});
segment.width = segmentWidth;
segmentWidth = Math.max(250, segmentWidth - 15);
segment.height = i === 1 ? 3000 : Math.floor(Math.random() * (4000 - 1200 + 1)) + 1200;
segment.rotation = zigzag ? -Math.PI - Math.PI / 4 : -Math.PI + Math.PI / 4;
segment.y = currentY;
segment.x = currentX;
var adjustedHeight = segment.height - segmentWidth / 2;
currentY += adjustedHeight * Math.cos(segment.rotation);
currentX -= adjustedHeight * Math.sin(segment.rotation);
segment.shadow = roadContainer.attachAsset('roadSegmentShadow', {
anchorX: 0.5
});
segment.shadow.width = segment.width;
segment.shadow.height = segment.height;
segment.shadow.rotation = segment.rotation;
segment.shadow.x = segment.x;
segment.shadow.y = segment.y + 50;
segment.shadow.alpha = 1;
segment.used = false;
roadSegments.push(segment);
roadContainer.addChildAt(segment.shadow, 0);
roadContainer.addChild(segment);
};
game.setBackgroundColor(0xc39977);
var particles = [];
LK.playMusic('backgroundMusic');
var hearts = [];
var goldenApples = [];
var mainContainer = game.addChild(new Container());
var roadContainer = mainContainer.addChild(new Container());
var roadSegments = [];
var roadblocks = [];
var segmentLength = Math.floor(Math.random() * (1000 - 200 + 1)) + 200;
var segmentWidth = 1200;
var currentX = 2048 / 2;
var currentY = 2732 / 2;
var zigzag = true;
for (var i = 1; i <= 25; i++) {
game.addRoadSegment();
}
// Place hearts on 5 random segments (not the first one)
var heartSegments = [];
while (heartSegments.length < 5) {
var idx = Math.floor(Math.random() * (roadSegments.length - 2)) + 1;
if (heartSegments.indexOf(idx) === -1) heartSegments.push(idx);
}
for (var h = 0; h < heartSegments.length; h++) {
var seg = roadSegments[heartSegments[h]];
var heart = new Heart();
// Place heart at center of segment
heart.x = seg.x;
heart.y = seg.y;
mainContainer.addChild(heart);
hearts.push(heart);
}
// Place golden apples on 2 random segments (not the first one), rare
var goldenAppleSegments = [];
while (goldenAppleSegments.length < 2) {
var idx = Math.floor(Math.random() * (roadSegments.length - 2)) + 1;
if (goldenAppleSegments.indexOf(idx) === -1 && heartSegments.indexOf(idx) === -1) goldenAppleSegments.push(idx);
}
for (var g = 0; g < goldenAppleSegments.length; g++) {
var seg = roadSegments[goldenAppleSegments[g]];
var goldenApple = new GoldenApple();
goldenApple.x = seg.x;
goldenApple.y = seg.y;
mainContainer.addChild(goldenApple);
goldenApples.push(goldenApple);
}
// Place roadblocks on 4 random segments (not the first one)
var roadblockSegments = [];
while (roadblockSegments.length < 4) {
var idx = Math.floor(Math.random() * (roadSegments.length - 2)) + 1;
if (roadblockSegments.indexOf(idx) === -1 && heartSegments.indexOf(idx) === -1 && goldenAppleSegments.indexOf(idx) === -1) roadblockSegments.push(idx);
}
for (var r = 0; r < roadblockSegments.length; r++) {
var seg = roadSegments[roadblockSegments[r]];
var barricade = new Barricade();
barricade.x = seg.x;
barricade.y = seg.y;
mainContainer.addChild(barricade);
roadblocks.push(barricade);
}
var scoreText = new Text2('0', {
size: 150,
fill: 0xFFFFFF,
weight: '800',
dropShadow: true,
dropShadowColor: '#373330',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
scoreText.anchor.set(0, 0);
LK.gui.top.addChild(scoreText);
// Level system removed
var car = mainContainer.addChild(new Car());
car.x = 2048 / 2;
car.y = 2732 / 2;
var isGameOver = false;
var score = 0;
var closestSegment = null;
game.on('down', function (x, y, obj) {
car.changeDirection();
});
LK.on('tick', function () {
car._move_migrated();
var carIsOnRoad = false;
var carPosition = {
x: car.x,
y: car.y
};
var currentClosestSegment = null;
var currentClosestDistance = Infinity;
roadSegments.forEach(function (segment) {
var segmentStart = {
x: segment.x + Math.sin(segment.rotation) * 100,
y: segment.y - Math.cos(segment.rotation) * 100
};
var segmentEnd = {
x: segment.x - Math.sin(segment.rotation) * (segment.height - segment.width / 2),
y: segment.y + Math.cos(segment.rotation) * (segment.height - segment.width / 2)
};
var distance = game.calculateDistanceToPoint(carPosition, segmentStart, segmentEnd);
if (distance < currentClosestDistance) {
currentClosestDistance = distance;
currentClosestSegment = segment;
}
if (distance < segment.width / 2 - 50) {
carIsOnRoad = true;
}
});
if (closestSegment !== currentClosestSegment && !currentClosestSegment.used) {
closestSegment = currentClosestSegment;
closestSegment.used = true;
score++;
car.ORIGINAL_SPEED += 0.1;
scoreText.setText(score.toString());
}
// Check for heart collection
for (var h = 0; h < hearts.length; h++) {
var heart = hearts[h];
if (!heart.collected && Math.abs(car.x - heart.x) < 80 && Math.abs(car.y - heart.y) < 80) {
heart.collected = true;
heart.visible = false;
score = score * 2;
scoreText.setText(score.toString());
}
}
// Check for golden apple collection
for (var g = 0; g < goldenApples.length; g++) {
var goldenApple = goldenApples[g];
if (!goldenApple.collected && Math.abs(car.x - goldenApple.x) < 80 && Math.abs(car.y - goldenApple.y) < 80) {
goldenApple.collected = true;
goldenApple.visible = false;
score += 5;
scoreText.setText(score.toString());
}
}
// Check for roadblock collision
var hitRoadblock = false;
for (var r = 0; r < roadblocks.length; r++) {
var roadblock = roadblocks[r];
// Use .intersects for precise collision detection
if (!roadblock.hit && car.intersects(roadblock)) {
roadblock.hit = true;
hitRoadblock = true;
break;
}
}
if (!carIsOnRoad || hitRoadblock) {
LK.showGameOver();
} else {}
var particleOffsets = [{
x: 20,
y: 140
}, {
x: 20 + 100,
y: 140 - 100
}, {
x: 20 - 150,
y: 140 - 150
}, {
x: 20 - 150 + 100,
y: 140 - 150 - 100
}];
for (var i = 0; i < particleOffsets.length; i++) {
var alphaValue = Math.max(0, Math.min(1, Math.abs(car.nonTravelMomentum) / 5 - 0.5));
if (alphaValue > 0) {
var particle = new Particle();
particle.alpha = alphaValue;
var noiseX = (Math.random() - 0.5) * 10;
var noiseY = (Math.random() - 0.5) * 10;
particle.x = car.x + (car.direction === 0 ? -1 : 1) * particleOffsets[i].x + noiseX;
particle.y = car.y + particleOffsets[i].y + noiseY;
mainContainer.addChildAt(particle, 1);
particles.push(particle);
}
}
particles.forEach(function (particle, index) {
particle.tick();
if (particle.lifetime <= 0) {
particles.splice(index, 1);
}
});
var carLocalPosition = game.toLocal(car.position, car.parent);
var offsetX = (2048 / 2 - carLocalPosition.x) / 20;
var offsetY = (2732 - 450 - carLocalPosition.y) / 20;
mainContainer.x += offsetX;
mainContainer.y += offsetY;
for (var i = roadSegments.length - 1; i >= 0; i--) {
var segmentGlobalPosition = game.toLocal(roadSegments[i].position, roadSegments[i].parent);
if (segmentGlobalPosition.y - roadSegments[i].height > 2732 * 2) {
roadSegments[i].shadow.destroy();
roadSegments[i].destroy();
roadSegments.splice(i, 1);
game.addRoadSegment();
}
}
});