/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Button = Container.expand(function (label, width, height) {
var self = Container.call(this);
//{button_init}
self.interactive = true;
self.buttonMode = true;
var buttonBg = self.attachAsset('Button', {
anchorX: 0.5,
anchorY: 0.5
}); //{button_bg}
buttonBg.width = width;
buttonBg.height = height;
buttonBg.scale.x = 1;
buttonBg.scale.y = 1;
var buttonText = new Text2(label, {
size: 80,
fill: 0x000000,
weight: '800'
}); //{button_text}
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.onDown = function () {
buttonBg.alpha = 0.7;
}; //{button_down}
self.onUp = function () {
buttonBg.alpha = 1;
}; //{button_up}
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.speed = 5;
self.direction = 0;
self.momentum = {
x: 0,
y: 0
};
self._move_migrated = function () {
var momentumModifier = 0.1;
if (self.direction === 0) {
// Move along X axis
self.momentum.x += self.speed * momentumModifier;
} else {
// Move along Y axis
self.momentum.y -= self.speed * momentumModifier;
}
var projectedMovement = self.projectMovement(self.momentum);
// Check if car reaches the center of the screen on the X coordinate
if (self.lastX <= 2048 / 2 && self.x > 2048 / 2) {
console.log("Car reached the center of the screen on the X coordinate");
}
self.lastX = self.x;
self.x += projectedMovement.x;
self.y += projectedMovement.y;
// Check if car arrives at a specific X, Y coordinate
if (self.lastY <= 1500 && self.y > 1500 && self.lastX <= 1000 && self.x > 1000) {
console.log("Car arrived at the specific X, Y coordinate");
}
self.lastY = self.y;
self.lastX = self.x;
// Check if car comes close to the bottom of the screen on the Y coordinate
if (self.lastY <= 2732 - 100 && self.y > 2732 - 100) {
console.log("Car is close to the bottom of the screen");
}
self.lastY = self.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;
carGraphics.scale.x *= -1;
};
});
var DifficultyPopup = Container.expand(function () {
var self = Container.call(this);
//{popup_init}
self.interactive = true;
self.buttonMode = false;
var hardBtn = new Button('HARD', 400, 160); //{popup_hard_btn}
hardBtn.x = 0;
hardBtn.y = -254;
self.addChild(hardBtn);
hardBtn.down = function (x, y, obj) {
console.log("Hard difficulty selected");
if (difficultyPopupContainer) {
difficultyPopupContainer.destroy();
difficultyPopupContainer = null;
}
}; //{popup_hard_down}
var mediumBtn = new Button('MEDIUM', 400, 160); //{popup_medium_btn}
mediumBtn.x = 0;
mediumBtn.y = -74;
self.addChild(mediumBtn);
mediumBtn.down = function (x, y, obj) {
console.log("Medium difficulty selected");
if (difficultyPopupContainer) {
difficultyPopupContainer.destroy();
difficultyPopupContainer = null;
}
}; //{popup_medium_down}
var easyBtn = new Button('EASY', 400, 160); //{popup_easy_btn}
easyBtn.x = 0;
easyBtn.y = 104;
self.addChild(easyBtn);
easyBtn.down = function (x, y, obj) {
console.log("Easy difficulty selected");
if (difficultyPopupContainer) {
difficultyPopupContainer.destroy();
difficultyPopupContainer = null;
}
}; //{popup_easy_down}
return self; //{popup_return}
});
var DriftAndDodge = Container.expand(function () {
var self = Container.call(this);
});
//{popup_end}
//{button_end}
var Menu = Container.expand(function () {
var self = Container.call(this);
//{1a_menu}
var currentWallpaperIndex = 0;
var wallpaperAssets = ['W2', 'W1', 'W3'];
var menuBackground = self.attachAsset(wallpaperAssets[currentWallpaperIndex], {
anchorX: 0.5,
//{1a_menu_bg1}
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}); //{1a_menu_bg2}
menuBackground.alpha = 0.8;
self.startWallpaperRotation = function () {
var _rotateWallpaper = function rotateWallpaper() {
currentWallpaperIndex = (currentWallpaperIndex + 1) % wallpaperAssets.length;
var newBackground = self.attachAsset(wallpaperAssets[currentWallpaperIndex], {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
newBackground.alpha = 0;
self.addChildAt(newBackground, 0);
tween(menuBackground, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeInOut
});
tween(newBackground, {
alpha: 0.8
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
menuBackground.destroy();
menuBackground = newBackground;
LK.setTimeout(_rotateWallpaper, 3000);
}
});
};
LK.setTimeout(_rotateWallpaper, 3000);
};
var titleText = new Text2('DRIFT AND DODGE', {
size: 120,
//{1a_menu_title1}
fill: 0x00FFFF,
weight: '800',
//{1a_menu_title2}
dropShadow: true,
dropShadowColor: '#373330',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6 //{1a_menu_title3}
}); //{1a_menu_title4}
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 2732 / 3;
titleText.visible = false;
self.addChild(titleText);
var buttonContainerMenu = new Container(); //{menu_button_container}
buttonContainerMenu.x = 2048 / 2;
buttonContainerMenu.y = 2732 / 2 + 100 + 555 + 777 - 333;
self.addChild(buttonContainerMenu);
var difficultyBtn = new Button('Difficulty', 400, 160); //{menu_diff_btn}
difficultyBtn.x = -650;
difficultyBtn.y = 0;
buttonContainerMenu.addChild(difficultyBtn);
difficultyBtn.down = function (x, y, obj) {
console.log("Difficulty selected");
if (!difficultyPopupContainer) {
difficultyPopupContainer = game.addChild(new DifficultyPopup());
difficultyPopupContainer.x = difficultyBtn.parent.x + difficultyBtn.x;
difficultyPopupContainer.y = difficultyBtn.parent.y + difficultyBtn.y - 280;
}
}; //{menu_diff_down}
var weatherBtn = new Button('Weather', 400, 160); //{menu_weather_btn}
weatherBtn.x = -250;
weatherBtn.y = 0;
buttonContainerMenu.addChild(weatherBtn);
weatherBtn.down = function (x, y, obj) {
console.log("Weather selected");
}; //{menu_weather_down}
var carBtn = new Button('Car', 400, 160); //{menu_car_btn}
carBtn.x = 150;
carBtn.y = 0;
buttonContainerMenu.addChild(carBtn);
carBtn.down = function (x, y, obj) {
console.log("Car selected");
}; //{menu_car_down}
var startBtn = Container.call(new Container());
startBtn.interactive = true;
startBtn.buttonMode = true;
var startButtonBg = startBtn.attachAsset('Startbutton', {
anchorX: 0.5,
anchorY: 0.5
});
startButtonBg.width = 500;
startButtonBg.height = 160;
startButtonBg.scale.x = 1;
startButtonBg.scale.y = 1;
var startButtonText = new Text2('START GAME', {
size: 80,
fill: 0x000000,
weight: '800'
});
startButtonText.anchor.set(0.5, 0.5);
startBtn.addChild(startButtonText);
startBtn.onDown = function () {
startButtonBg.alpha = 0.7;
};
startBtn.onUp = function () {
startButtonBg.alpha = 1;
};
startBtn.x = 599;
startBtn.y = 0;
buttonContainerMenu.addChild(startBtn);
startBtn.down = function (x, y, obj) {
self.visible = false;
self.interactive = false;
}; //{menu_start_down}
self.startWallpaperRotation();
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('wheelTrack', {
anchorX: 0.5,
anchorY: 0.5
});
particleGraphics.rotation = Math.PI / 4;
self.lifetime = 100;
self.tick = function () {
if (--self.lifetime <= 0) {
self.destroy();
}
};
});
var Rock = Container.expand(function () {
var self = Container.call(this);
var rockGraphics = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5
});
});
var SnowFog = Container.expand(function () {
var self = Container.call(this);
var fogGraphics = self.attachAsset('wheelTrack', {
anchorX: 0.5,
anchorY: 0.5
});
fogGraphics.scale.x = 0.6;
fogGraphics.scale.y = 0.6;
fogGraphics.tint = 0xFFFFFF;
self.lifetime = 80;
self.initialize = function (startX, startY) {
self.x = startX;
self.y = startY;
self.alpha = 0.7;
tween(self, {
alpha: 0,
y: self.y - 200
}, {
duration: 800,
easing: tween.easeOut
});
};
self.tick = function () {
if (--self.lifetime <= 0) {
self.destroy();
}
};
});
var SnowyEmbankment = Container.expand(function () {
var self = Container.call(this);
var embankmentGraphics = self.attachAsset('rods', {
anchorX: 0.5,
anchorY: 0.5
});
});
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 0.5
});
});
var Tree2 = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree2', {
anchorX: 0.5,
anchorY: 0.5
});
});
/****
* Initialize Game
****/
//{1a_menu_end}
var game = new LK.Game({
backgroundColor: 0xFFFFFF
});
/****
* Game Code
****/
var difficultyPopupContainer = null;
var driftAndDodge = game.addChild(new DriftAndDodge());
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;
// Reduce road width more during turns to make turns harder but still playable
if (zigzag) {
segmentWidth = Math.max(400, segmentWidth - 45); // Less narrow on turns after turn 10
} else {
segmentWidth = Math.max(400, segmentWidth - 12); // Less narrow on straights after turn 10
}
segment.height = (i === 1 ? 3000 : Math.floor(Math.random() * (4000 - 1200 + 1)) + 1200) * 2;
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);
// Add multiple trees to the left and right of the road segment
var treeSpacing = 150; // Space between trees
var numberOfTrees = Math.floor(segment.height / treeSpacing) - 3; // Decrease the number of trees by 3
var numberOfTree2 = Math.floor(segment.height / treeSpacing) - 3; // Decrease the number of tree2 by 3
for (var i = 0; i < numberOfTree2; i++) {
var leftTree = new Tree();
leftTree.x = segment.x - segment.width - 200 - i * treeSpacing; // Decrease the distance from the road by 100 units
leftTree.y = segment.y + i * treeSpacing;
roadContainer.addChild(leftTree);
var rightTree = new Tree2();
rightTree.x = segment.x + segment.width + 200 + i * treeSpacing; // Decrease the distance from the road by 100 units
rightTree.y = segment.y + i * treeSpacing;
roadContainer.addChild(rightTree);
}
// Add rocks to the left and right of the road segment
var leftRock = new Rock();
leftRock.x = segment.x - segment.width - 1000; // Double the distance from the road
leftRock.y = segment.y;
roadContainer.addChildAt(leftRock, 0);
var rightRock = new Rock();
rightRock.x = segment.x + segment.width + 1000; // Double the distance from the road
rightRock.y = segment.y;
roadContainer.addChildAt(rightRock, 0);
// Attach snowy embankments to the left and right of the road segment
var leftEmbankment = new SnowyEmbankment();
leftEmbankment.x = segment.x - segment.width / 2 - 50; // Increase distance by 50 units
leftEmbankment.y = segment.y;
roadContainer.addChild(leftEmbankment);
var rightEmbankment = new SnowyEmbankment();
rightEmbankment.x = segment.x + segment.width / 2 + 50; // Increase distance by 50 units
rightEmbankment.y = segment.y;
roadContainer.addChild(rightEmbankment);
};
var menu = game.addChild(new Menu());
var particles = [];
var snowFogs = [];
var mainContainer = game.addChild(new Container()); //{1x_main}
mainContainer.visible = false;
var roadContainer = mainContainer.addChild(new Container());
var roadSegments = [];
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 <= 15; i++) {
// Gradually increase turn sharpness and narrow road as player progresses
if (i > 5 && i <= 10) {
segmentWidth = Math.max(400, segmentWidth - 30); // Slightly harder
} else if (i > 10) {
segmentWidth = Math.max(450, segmentWidth - 40); // Less narrow after turn 10
}
game.addRoadSegment();
}
var scoreText = new Text2('Turn: 0', {
size: 75,
fill: 0xFFFFFF,
weight: '800',
dropShadow: true,
dropShadowColor: '#373330',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
scoreText.anchor.set(1, 0); // Anchor to the top right
scoreText.visible = false;
LK.gui.topRight.addChild(scoreText);
// Timer Text2 for minutes:seconds display
var timerText = new Text2('00:00', {
size: 50,
fill: 0xFFFFFF,
weight: '800',
dropShadow: true,
dropShadowColor: '#373330',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
timerText.anchor.set(1, 1); // Bottom right
timerText.visible = false;
LK.gui.bottomRight.addChild(timerText);
// Timer variables
var timerStartTicks = LK.ticks;
var timerLastSeconds = 0;
// Add a neon blue-colored speedometer to the bottom left corner of the map
var speedometer = new Text2('Speed: 0', {
size: 50,
fill: 0x00FFFF,
// Neon blue color
weight: '800',
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
speedometer.anchor.set(0, 1); // Anchor to bottom left
speedometer.visible = false;
LK.gui.bottomLeft.addChild(speedometer);
var car = mainContainer.addChild(new Car());
car.x = 2048 / 2;
car.y = 2732 / 2;
var isGameOver = false;
var score = 0;
var closestSegment = null;
game.down = function (x, y, obj) {
if (!mainContainer.visible) return;
car.changeDirection();
};
game.up = function () {};
LK.on('tick', function () {
if (!mainContainer.visible && !menu.visible) {
mainContainer.visible = true;
scoreText.visible = true;
timerText.visible = true;
speedometer.visible = true;
car._move_migrated();
} else if (mainContainer.visible) {
car._move_migrated();
LK.playMusic('Car', {
loop: true
});
}
// Update timerText with hours:minutes:seconds:milliseconds format
var elapsedTicks = LK.ticks - timerStartTicks;
var elapsedMilliseconds = Math.floor(elapsedTicks % 60 * (1000 / 60));
var elapsedSeconds = Math.floor(elapsedTicks / 60);
var elapsedMinutes = Math.floor(elapsedSeconds / 60);
var elapsedHours = Math.floor(elapsedMinutes / 60);
var hours = elapsedHours;
var minutes = elapsedMinutes % 60;
var seconds = elapsedSeconds % 60;
var milliseconds = elapsedMilliseconds;
var hourStr = hours < 10 ? '0' + hours : '' + hours;
var minStr = minutes < 10 ? '0' + minutes : '' + minutes;
var secStr = seconds < 10 ? '0' + seconds : '' + seconds;
var msStr = milliseconds < 100 ? milliseconds < 10 ? '00' + milliseconds : '0' + milliseconds : '' + milliseconds;
timerText.setText(hourStr + ':' + minStr + ':' + secStr + ':' + msStr);
var carIsOnRoad = false;
var carPosition = {
x: car.x,
y: car.y
};
// Update the speedometer with the current speed
speedometer.setText('Speed: ' + Math.round(Math.sqrt(car.momentum.x * car.momentum.x + car.momentum.y * car.momentum.y) * 5) + ' km/h');
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) {
// Check for intersection between car and road segment
if (car.lastWasIntersecting === false && car.intersects(currentClosestSegment)) {
console.log("Car intersected with a road segment");
}
car.lastWasIntersecting = car.intersects(currentClosestSegment);
closestSegment = currentClosestSegment;
closestSegment.used = true;
score++;
LK.setScore(score);
scoreText.setText('Turn: ' + score.toString());
}
if (!carIsOnRoad) {
LK.showGameOver();
} else {}
var particle = new Particle();
particle.alpha = Math.max(0, Math.min(1, Math.abs(car.nonTravelMomentum) / 5 - 0.5));
if (particle.alpha > 0) {
var noiseX = (Math.random() - 0.5) * 10;
var noiseY = (Math.random() - 0.5) * 10;
particle.x = car.x + noiseX;
particle.y = car.y + noiseY;
mainContainer.addChildAt(particle, 1);
particles.push(particle);
}
particles.forEach(function (particle, index) {
particle.tick();
if (particle.lifetime <= 0) {
particles.splice(index, 1);
}
});
if (LK.ticks % 3 === 0 && Math.abs(car.nonTravelMomentum) > 0.5) {
var snowFog = new SnowFog();
var fogOffsetX = (Math.random() - 0.5) * 150;
var fogOffsetY = 150;
snowFog.initialize(car.x + fogOffsetX, car.y + fogOffsetY);
mainContainer.addChildAt(snowFog, 1);
snowFogs.push(snowFog);
}
snowFogs.forEach(function (fog, index) {
fog.tick();
if (fog.lifetime <= 0) {
snowFogs.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();
}
// Destroy embankments which are off screen
if (roadSegments[i].leftEmbankment && roadSegments[i].leftEmbankment.y < -50) {
roadSegments[i].leftEmbankment.destroy();
}
if (roadSegments[i].rightEmbankment && roadSegments[i].rightEmbankment.y < -50) {
roadSegments[i].rightEmbankment.destroy();
}
}
});
// Add the game logic for 'DriftAndDodge' here /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Button = Container.expand(function (label, width, height) {
var self = Container.call(this);
//{button_init}
self.interactive = true;
self.buttonMode = true;
var buttonBg = self.attachAsset('Button', {
anchorX: 0.5,
anchorY: 0.5
}); //{button_bg}
buttonBg.width = width;
buttonBg.height = height;
buttonBg.scale.x = 1;
buttonBg.scale.y = 1;
var buttonText = new Text2(label, {
size: 80,
fill: 0x000000,
weight: '800'
}); //{button_text}
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.onDown = function () {
buttonBg.alpha = 0.7;
}; //{button_down}
self.onUp = function () {
buttonBg.alpha = 1;
}; //{button_up}
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.speed = 5;
self.direction = 0;
self.momentum = {
x: 0,
y: 0
};
self._move_migrated = function () {
var momentumModifier = 0.1;
if (self.direction === 0) {
// Move along X axis
self.momentum.x += self.speed * momentumModifier;
} else {
// Move along Y axis
self.momentum.y -= self.speed * momentumModifier;
}
var projectedMovement = self.projectMovement(self.momentum);
// Check if car reaches the center of the screen on the X coordinate
if (self.lastX <= 2048 / 2 && self.x > 2048 / 2) {
console.log("Car reached the center of the screen on the X coordinate");
}
self.lastX = self.x;
self.x += projectedMovement.x;
self.y += projectedMovement.y;
// Check if car arrives at a specific X, Y coordinate
if (self.lastY <= 1500 && self.y > 1500 && self.lastX <= 1000 && self.x > 1000) {
console.log("Car arrived at the specific X, Y coordinate");
}
self.lastY = self.y;
self.lastX = self.x;
// Check if car comes close to the bottom of the screen on the Y coordinate
if (self.lastY <= 2732 - 100 && self.y > 2732 - 100) {
console.log("Car is close to the bottom of the screen");
}
self.lastY = self.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;
carGraphics.scale.x *= -1;
};
});
var DifficultyPopup = Container.expand(function () {
var self = Container.call(this);
//{popup_init}
self.interactive = true;
self.buttonMode = false;
var hardBtn = new Button('HARD', 400, 160); //{popup_hard_btn}
hardBtn.x = 0;
hardBtn.y = -254;
self.addChild(hardBtn);
hardBtn.down = function (x, y, obj) {
console.log("Hard difficulty selected");
if (difficultyPopupContainer) {
difficultyPopupContainer.destroy();
difficultyPopupContainer = null;
}
}; //{popup_hard_down}
var mediumBtn = new Button('MEDIUM', 400, 160); //{popup_medium_btn}
mediumBtn.x = 0;
mediumBtn.y = -74;
self.addChild(mediumBtn);
mediumBtn.down = function (x, y, obj) {
console.log("Medium difficulty selected");
if (difficultyPopupContainer) {
difficultyPopupContainer.destroy();
difficultyPopupContainer = null;
}
}; //{popup_medium_down}
var easyBtn = new Button('EASY', 400, 160); //{popup_easy_btn}
easyBtn.x = 0;
easyBtn.y = 104;
self.addChild(easyBtn);
easyBtn.down = function (x, y, obj) {
console.log("Easy difficulty selected");
if (difficultyPopupContainer) {
difficultyPopupContainer.destroy();
difficultyPopupContainer = null;
}
}; //{popup_easy_down}
return self; //{popup_return}
});
var DriftAndDodge = Container.expand(function () {
var self = Container.call(this);
});
//{popup_end}
//{button_end}
var Menu = Container.expand(function () {
var self = Container.call(this);
//{1a_menu}
var currentWallpaperIndex = 0;
var wallpaperAssets = ['W2', 'W1', 'W3'];
var menuBackground = self.attachAsset(wallpaperAssets[currentWallpaperIndex], {
anchorX: 0.5,
//{1a_menu_bg1}
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}); //{1a_menu_bg2}
menuBackground.alpha = 0.8;
self.startWallpaperRotation = function () {
var _rotateWallpaper = function rotateWallpaper() {
currentWallpaperIndex = (currentWallpaperIndex + 1) % wallpaperAssets.length;
var newBackground = self.attachAsset(wallpaperAssets[currentWallpaperIndex], {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
newBackground.alpha = 0;
self.addChildAt(newBackground, 0);
tween(menuBackground, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeInOut
});
tween(newBackground, {
alpha: 0.8
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
menuBackground.destroy();
menuBackground = newBackground;
LK.setTimeout(_rotateWallpaper, 3000);
}
});
};
LK.setTimeout(_rotateWallpaper, 3000);
};
var titleText = new Text2('DRIFT AND DODGE', {
size: 120,
//{1a_menu_title1}
fill: 0x00FFFF,
weight: '800',
//{1a_menu_title2}
dropShadow: true,
dropShadowColor: '#373330',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6 //{1a_menu_title3}
}); //{1a_menu_title4}
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 2732 / 3;
titleText.visible = false;
self.addChild(titleText);
var buttonContainerMenu = new Container(); //{menu_button_container}
buttonContainerMenu.x = 2048 / 2;
buttonContainerMenu.y = 2732 / 2 + 100 + 555 + 777 - 333;
self.addChild(buttonContainerMenu);
var difficultyBtn = new Button('Difficulty', 400, 160); //{menu_diff_btn}
difficultyBtn.x = -650;
difficultyBtn.y = 0;
buttonContainerMenu.addChild(difficultyBtn);
difficultyBtn.down = function (x, y, obj) {
console.log("Difficulty selected");
if (!difficultyPopupContainer) {
difficultyPopupContainer = game.addChild(new DifficultyPopup());
difficultyPopupContainer.x = difficultyBtn.parent.x + difficultyBtn.x;
difficultyPopupContainer.y = difficultyBtn.parent.y + difficultyBtn.y - 280;
}
}; //{menu_diff_down}
var weatherBtn = new Button('Weather', 400, 160); //{menu_weather_btn}
weatherBtn.x = -250;
weatherBtn.y = 0;
buttonContainerMenu.addChild(weatherBtn);
weatherBtn.down = function (x, y, obj) {
console.log("Weather selected");
}; //{menu_weather_down}
var carBtn = new Button('Car', 400, 160); //{menu_car_btn}
carBtn.x = 150;
carBtn.y = 0;
buttonContainerMenu.addChild(carBtn);
carBtn.down = function (x, y, obj) {
console.log("Car selected");
}; //{menu_car_down}
var startBtn = Container.call(new Container());
startBtn.interactive = true;
startBtn.buttonMode = true;
var startButtonBg = startBtn.attachAsset('Startbutton', {
anchorX: 0.5,
anchorY: 0.5
});
startButtonBg.width = 500;
startButtonBg.height = 160;
startButtonBg.scale.x = 1;
startButtonBg.scale.y = 1;
var startButtonText = new Text2('START GAME', {
size: 80,
fill: 0x000000,
weight: '800'
});
startButtonText.anchor.set(0.5, 0.5);
startBtn.addChild(startButtonText);
startBtn.onDown = function () {
startButtonBg.alpha = 0.7;
};
startBtn.onUp = function () {
startButtonBg.alpha = 1;
};
startBtn.x = 599;
startBtn.y = 0;
buttonContainerMenu.addChild(startBtn);
startBtn.down = function (x, y, obj) {
self.visible = false;
self.interactive = false;
}; //{menu_start_down}
self.startWallpaperRotation();
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('wheelTrack', {
anchorX: 0.5,
anchorY: 0.5
});
particleGraphics.rotation = Math.PI / 4;
self.lifetime = 100;
self.tick = function () {
if (--self.lifetime <= 0) {
self.destroy();
}
};
});
var Rock = Container.expand(function () {
var self = Container.call(this);
var rockGraphics = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5
});
});
var SnowFog = Container.expand(function () {
var self = Container.call(this);
var fogGraphics = self.attachAsset('wheelTrack', {
anchorX: 0.5,
anchorY: 0.5
});
fogGraphics.scale.x = 0.6;
fogGraphics.scale.y = 0.6;
fogGraphics.tint = 0xFFFFFF;
self.lifetime = 80;
self.initialize = function (startX, startY) {
self.x = startX;
self.y = startY;
self.alpha = 0.7;
tween(self, {
alpha: 0,
y: self.y - 200
}, {
duration: 800,
easing: tween.easeOut
});
};
self.tick = function () {
if (--self.lifetime <= 0) {
self.destroy();
}
};
});
var SnowyEmbankment = Container.expand(function () {
var self = Container.call(this);
var embankmentGraphics = self.attachAsset('rods', {
anchorX: 0.5,
anchorY: 0.5
});
});
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 0.5
});
});
var Tree2 = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree2', {
anchorX: 0.5,
anchorY: 0.5
});
});
/****
* Initialize Game
****/
//{1a_menu_end}
var game = new LK.Game({
backgroundColor: 0xFFFFFF
});
/****
* Game Code
****/
var difficultyPopupContainer = null;
var driftAndDodge = game.addChild(new DriftAndDodge());
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;
// Reduce road width more during turns to make turns harder but still playable
if (zigzag) {
segmentWidth = Math.max(400, segmentWidth - 45); // Less narrow on turns after turn 10
} else {
segmentWidth = Math.max(400, segmentWidth - 12); // Less narrow on straights after turn 10
}
segment.height = (i === 1 ? 3000 : Math.floor(Math.random() * (4000 - 1200 + 1)) + 1200) * 2;
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);
// Add multiple trees to the left and right of the road segment
var treeSpacing = 150; // Space between trees
var numberOfTrees = Math.floor(segment.height / treeSpacing) - 3; // Decrease the number of trees by 3
var numberOfTree2 = Math.floor(segment.height / treeSpacing) - 3; // Decrease the number of tree2 by 3
for (var i = 0; i < numberOfTree2; i++) {
var leftTree = new Tree();
leftTree.x = segment.x - segment.width - 200 - i * treeSpacing; // Decrease the distance from the road by 100 units
leftTree.y = segment.y + i * treeSpacing;
roadContainer.addChild(leftTree);
var rightTree = new Tree2();
rightTree.x = segment.x + segment.width + 200 + i * treeSpacing; // Decrease the distance from the road by 100 units
rightTree.y = segment.y + i * treeSpacing;
roadContainer.addChild(rightTree);
}
// Add rocks to the left and right of the road segment
var leftRock = new Rock();
leftRock.x = segment.x - segment.width - 1000; // Double the distance from the road
leftRock.y = segment.y;
roadContainer.addChildAt(leftRock, 0);
var rightRock = new Rock();
rightRock.x = segment.x + segment.width + 1000; // Double the distance from the road
rightRock.y = segment.y;
roadContainer.addChildAt(rightRock, 0);
// Attach snowy embankments to the left and right of the road segment
var leftEmbankment = new SnowyEmbankment();
leftEmbankment.x = segment.x - segment.width / 2 - 50; // Increase distance by 50 units
leftEmbankment.y = segment.y;
roadContainer.addChild(leftEmbankment);
var rightEmbankment = new SnowyEmbankment();
rightEmbankment.x = segment.x + segment.width / 2 + 50; // Increase distance by 50 units
rightEmbankment.y = segment.y;
roadContainer.addChild(rightEmbankment);
};
var menu = game.addChild(new Menu());
var particles = [];
var snowFogs = [];
var mainContainer = game.addChild(new Container()); //{1x_main}
mainContainer.visible = false;
var roadContainer = mainContainer.addChild(new Container());
var roadSegments = [];
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 <= 15; i++) {
// Gradually increase turn sharpness and narrow road as player progresses
if (i > 5 && i <= 10) {
segmentWidth = Math.max(400, segmentWidth - 30); // Slightly harder
} else if (i > 10) {
segmentWidth = Math.max(450, segmentWidth - 40); // Less narrow after turn 10
}
game.addRoadSegment();
}
var scoreText = new Text2('Turn: 0', {
size: 75,
fill: 0xFFFFFF,
weight: '800',
dropShadow: true,
dropShadowColor: '#373330',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
scoreText.anchor.set(1, 0); // Anchor to the top right
scoreText.visible = false;
LK.gui.topRight.addChild(scoreText);
// Timer Text2 for minutes:seconds display
var timerText = new Text2('00:00', {
size: 50,
fill: 0xFFFFFF,
weight: '800',
dropShadow: true,
dropShadowColor: '#373330',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
timerText.anchor.set(1, 1); // Bottom right
timerText.visible = false;
LK.gui.bottomRight.addChild(timerText);
// Timer variables
var timerStartTicks = LK.ticks;
var timerLastSeconds = 0;
// Add a neon blue-colored speedometer to the bottom left corner of the map
var speedometer = new Text2('Speed: 0', {
size: 50,
fill: 0x00FFFF,
// Neon blue color
weight: '800',
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6
});
speedometer.anchor.set(0, 1); // Anchor to bottom left
speedometer.visible = false;
LK.gui.bottomLeft.addChild(speedometer);
var car = mainContainer.addChild(new Car());
car.x = 2048 / 2;
car.y = 2732 / 2;
var isGameOver = false;
var score = 0;
var closestSegment = null;
game.down = function (x, y, obj) {
if (!mainContainer.visible) return;
car.changeDirection();
};
game.up = function () {};
LK.on('tick', function () {
if (!mainContainer.visible && !menu.visible) {
mainContainer.visible = true;
scoreText.visible = true;
timerText.visible = true;
speedometer.visible = true;
car._move_migrated();
} else if (mainContainer.visible) {
car._move_migrated();
LK.playMusic('Car', {
loop: true
});
}
// Update timerText with hours:minutes:seconds:milliseconds format
var elapsedTicks = LK.ticks - timerStartTicks;
var elapsedMilliseconds = Math.floor(elapsedTicks % 60 * (1000 / 60));
var elapsedSeconds = Math.floor(elapsedTicks / 60);
var elapsedMinutes = Math.floor(elapsedSeconds / 60);
var elapsedHours = Math.floor(elapsedMinutes / 60);
var hours = elapsedHours;
var minutes = elapsedMinutes % 60;
var seconds = elapsedSeconds % 60;
var milliseconds = elapsedMilliseconds;
var hourStr = hours < 10 ? '0' + hours : '' + hours;
var minStr = minutes < 10 ? '0' + minutes : '' + minutes;
var secStr = seconds < 10 ? '0' + seconds : '' + seconds;
var msStr = milliseconds < 100 ? milliseconds < 10 ? '00' + milliseconds : '0' + milliseconds : '' + milliseconds;
timerText.setText(hourStr + ':' + minStr + ':' + secStr + ':' + msStr);
var carIsOnRoad = false;
var carPosition = {
x: car.x,
y: car.y
};
// Update the speedometer with the current speed
speedometer.setText('Speed: ' + Math.round(Math.sqrt(car.momentum.x * car.momentum.x + car.momentum.y * car.momentum.y) * 5) + ' km/h');
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) {
// Check for intersection between car and road segment
if (car.lastWasIntersecting === false && car.intersects(currentClosestSegment)) {
console.log("Car intersected with a road segment");
}
car.lastWasIntersecting = car.intersects(currentClosestSegment);
closestSegment = currentClosestSegment;
closestSegment.used = true;
score++;
LK.setScore(score);
scoreText.setText('Turn: ' + score.toString());
}
if (!carIsOnRoad) {
LK.showGameOver();
} else {}
var particle = new Particle();
particle.alpha = Math.max(0, Math.min(1, Math.abs(car.nonTravelMomentum) / 5 - 0.5));
if (particle.alpha > 0) {
var noiseX = (Math.random() - 0.5) * 10;
var noiseY = (Math.random() - 0.5) * 10;
particle.x = car.x + noiseX;
particle.y = car.y + noiseY;
mainContainer.addChildAt(particle, 1);
particles.push(particle);
}
particles.forEach(function (particle, index) {
particle.tick();
if (particle.lifetime <= 0) {
particles.splice(index, 1);
}
});
if (LK.ticks % 3 === 0 && Math.abs(car.nonTravelMomentum) > 0.5) {
var snowFog = new SnowFog();
var fogOffsetX = (Math.random() - 0.5) * 150;
var fogOffsetY = 150;
snowFog.initialize(car.x + fogOffsetX, car.y + fogOffsetY);
mainContainer.addChildAt(snowFog, 1);
snowFogs.push(snowFog);
}
snowFogs.forEach(function (fog, index) {
fog.tick();
if (fog.lifetime <= 0) {
snowFogs.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();
}
// Destroy embankments which are off screen
if (roadSegments[i].leftEmbankment && roadSegments[i].leftEmbankment.y < -50) {
roadSegments[i].leftEmbankment.destroy();
}
if (roadSegments[i].rightEmbankment && roadSegments[i].rightEmbankment.y < -50) {
roadSegments[i].rightEmbankment.destroy();
}
}
});
// Add the game logic for 'DriftAndDodge' here