/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ 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(); }; }); // Coin class: type is 'blue' or 'red', assetId is one of the four var Coin = Container.expand(function () { var self = Container.call(this); self.type = 'blue'; // default, can be 'red' self.collected = false; self.assetId = 'coinBlue1'; // default, can be any of the 4 var coinGraphics = self.attachAsset(self.assetId, { anchorX: 0.5, anchorY: 0.5 }); // Allow setting asset after creation self.setTypeAndAsset = function (type, assetId) { self.type = type; self.assetId = assetId; // Remove old graphics if (coinGraphics && coinGraphics.parent) { coinGraphics.parent.removeChild(coinGraphics); } // Attach new asset var newGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; return self; }); var Driver = Container.expand(function () { var self = Container.call(this); self.x = +1500; self.y = +1500; var driverGraphics = self.attachAsset('driver', { anchorX: 0.5, anchorY: 0.5 }); }); 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 ****/ // Coin assets: 3 blue shades, 1 red 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(350, 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', { loop: true }); var mainContainer = game.addChild(new Container()); 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++) { game.addRoadSegment(); } 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); var notificationTexts = ['Tuz aldınız mı?', 'Badem suyu aldınız tuz almadınız mı?', 'Sizle iş yapanın anasını.', 'Ben çok iyi bir sürücüyüm ya', 'Drift intheworld.', 'Patlat Meto.', 'Hop bakkal.', 'Ronaldoya hiz lazim.', 'Anne beni affet.', 'Look mom I can fly.']; var usedNotificationTexts = []; function getRandomNotificationText() { if (notificationTexts.length === 0) { notificationTexts = usedNotificationTexts.splice(0, usedNotificationTexts.length); } var index = Math.floor(Math.random() * notificationTexts.length); var text = notificationTexts.splice(index, 1)[0]; usedNotificationTexts.push(text); return text; } var notificationText = new Text2(getRandomNotificationText(), { size: 60, fill: 0xFFFFFF, weight: '400', align: 'center', stroke: '#000000', strokeThickness: 8 }); notificationText.anchor.set(0, 4); notificationText.x -= 350; LK.gui.bottom.addChild(notificationText); var car = mainContainer.addChild(new Car()); car.x = 2048 / 2; car.y = 2732 / 2; var driver = LK.gui.addChild(new Driver()); driver.x = 250; driver.y = 1800; // Add hamzaa image to bottom-right corner and keep reference for glow var hamzaaImage = LK.getAsset('hamzaa', { anchorX: 1, anchorY: 1, x: 2048 - 40, y: 2732 - 40, scaleX: 0.25, scaleY: 0.25 }); var isGameOver = false; var score = 0; var closestSegment = null; var lastScoreForHamzaaGlow = 0; // Track last score that triggered glow // Global reference for special hamza image var hamzaSpecialImage = undefined; game.on('down', function (x, y, obj) { car.changeDirection(); }); // Import the tween plugin for animations // Coin logic: spawn, update, collision, scoring if (typeof coins === "undefined") { var coins = []; var coinSpawnTimer = 0; var coinTypes = [{ type: 'blue', assetId: 'coinBlue1' }, { type: 'blue', assetId: 'coinBlue2' }, { type: 'blue', assetId: 'coinBlue3' }, { type: 'red', assetId: 'coinRed' }]; } 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 (!segment._wasCarOnShadow) { segment._wasCarOnShadow = true; } } else { segment._wasCarOnShadow = false; } }); if (closestSegment !== currentClosestSegment && !currentClosestSegment.used) { closestSegment = currentClosestSegment; closestSegment.used = true; score++; car.ORIGINAL_SPEED += 0.1; scoreText.setText(score.toString()); notificationText.setText(getRandomNotificationText()); // Highlight hamzaa and play hamza sound at 80, 160, 240, ... if (score > 0 && score % 80 === 0 && lastScoreForHamzaaGlow !== score) { lastScoreForHamzaaGlow = score; // Use tween to create a glow effect (simulate by scaling up and down and changing alpha) tween(hamzaaImage, { scaleX: 0.35, scaleY: 0.35, alpha: 1 }, { duration: 200, onFinish: function onFinish() { tween(hamzaaImage, { scaleX: 0.25, scaleY: 0.25, alpha: 1 }, { duration: 400 }); } }); // --- NEW: Show 'hamza' image, stop music, play sound, then resume music --- if (typeof hamzaSpecialImage !== "undefined" && hamzaSpecialImage && hamzaSpecialImage.parent) { hamzaSpecialImage.parent.removeChild(hamzaSpecialImage); hamzaSpecialImage = undefined; } // Create and display the 'hamza' image in the bottom-right at 600x600 hamzaSpecialImage = LK.getAsset('hamza', { anchorX: 1, anchorY: 1, x: 2048 - 40, y: 2732 - 40, width: 600, height: 600 }); game.addChild(hamzaSpecialImage); // Stop the music, play the sound, then resume music after sound duration LK.stopMusic(); var hamzaSound = LK.getSound('hamza'); hamzaSound.play(); // Remove the image and resume music after the sound finishes (assume 1.5s for safety) LK.setTimeout(function () { if (hamzaSpecialImage && hamzaSpecialImage.parent) { hamzaSpecialImage.parent.removeChild(hamzaSpecialImage); hamzaSpecialImage = undefined; } LK.playMusic('backgroundMusic', { loop: true }); }, 1500); } } if (!carIsOnRoad) { LK.showGameOver(); } else {} LK.on('gameover', function () { // Defer sound play to next tick to ensure it plays even if scripts are halted LK.setTimeout(function () { LK.getSound('hamza').play(); }, 0); // Stop the sound when the Play Again button is pressed (game restarts) LK.on('restart', function () { LK.getSound('hamza').stop(); }); }); // --- COIN SPAWNING --- coinSpawnTimer++; if (coinSpawnTimer > 60) { // spawn a coin every ~1 second coinSpawnTimer = 0; // Pick a random road segment to spawn on var segIdx = Math.floor(Math.random() * roadSegments.length); var seg = roadSegments[segIdx]; // Pick a random type var coinTypeIdx = Math.floor(Math.random() * coinTypes.length); var coinType = coinTypes[coinTypeIdx]; var coin = new Coin(); coin.setTypeAndAsset(coinType.type, coinType.assetId); // Place coin at a random position along the segment, ensuring minimum distance from other coins var minCoinDistance = 250; // Minimum distance in px between coins var maxTries = 10; var t, tryCount = 0; var segStart = { x: seg.x + Math.sin(seg.rotation) * 100, y: seg.y - Math.cos(seg.rotation) * 100 }; var segEnd = { x: seg.x - Math.sin(seg.rotation) * (seg.height - seg.width / 2), y: seg.y + Math.cos(seg.rotation) * (seg.height - seg.width / 2) }; do { t = Math.random() * 0.5 + 0.25; coin.x = segStart.x + (segEnd.x - segStart.x) * t; coin.y = segStart.y + (segEnd.y - segStart.y) * t; var tooClose = false; for (var j = 0; j < coins.length; j++) { var other = coins[j]; var dx = coin.x - other.x; var dy = coin.y - other.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < minCoinDistance) { tooClose = true; break; } } tryCount++; } while (tooClose && tryCount < maxTries); mainContainer.addChild(coin); coins.push(coin); } // --- COIN COLLISION & COLLECTION --- for (var i = coins.length - 1; i >= 0; i--) { var coin = coins[i]; if (!coin.collected && car.intersects(coin)) { coin.collected = true; // Remove coin from scene coin.destroy(); coins.splice(i, 1); // Score logic if (coin.type === 'blue') { score += 5; } else if (coin.type === 'red') { score -= 5; if (score < 0) score = 0; } scoreText.setText(score.toString()); // Highlight hamzaa and play hamza sound at 80, 160, 240, ... if (score > 0 && score % 80 === 0 && lastScoreForHamzaaGlow !== score) { lastScoreForHamzaaGlow = score; tween(hamzaaImage, { scaleX: 0.35, scaleY: 0.35, alpha: 1 }, { duration: 200, onFinish: function onFinish() { tween(hamzaaImage, { scaleX: 0.25, scaleY: 0.25, alpha: 1 }, { duration: 400 }); } }); // --- NEW: Show 'hamza' image, stop music, play sound, then resume music --- if (typeof hamzaSpecialImage !== "undefined" && hamzaSpecialImage && hamzaSpecialImage.parent) { hamzaSpecialImage.parent.removeChild(hamzaSpecialImage); hamzaSpecialImage = undefined; } // Create and display the 'hamza' image in the bottom-right at 600x600 hamzaSpecialImage = LK.getAsset('hamza', { anchorX: 1, anchorY: 1, x: 2048 - 40, y: 2732 - 40, width: 600, height: 600 }); game.addChild(hamzaSpecialImage); // Stop the music, play the sound, then resume music after sound duration LK.stopMusic(); var hamzaSound = LK.getSound('hamza'); hamzaSound.play(); // Remove the image and resume music after the sound finishes (assume 1.5s for safety) LK.setTimeout(function () { if (hamzaSpecialImage && hamzaSpecialImage.parent) { hamzaSpecialImage.parent.removeChild(hamzaSpecialImage); hamzaSpecialImage = undefined; } LK.playMusic('backgroundMusic', { loop: true }); }, 1500); } } } // --- PARTICLE LOGIC --- 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(); } } });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
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();
};
});
// Coin class: type is 'blue' or 'red', assetId is one of the four
var Coin = Container.expand(function () {
var self = Container.call(this);
self.type = 'blue'; // default, can be 'red'
self.collected = false;
self.assetId = 'coinBlue1'; // default, can be any of the 4
var coinGraphics = self.attachAsset(self.assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Allow setting asset after creation
self.setTypeAndAsset = function (type, assetId) {
self.type = type;
self.assetId = assetId;
// Remove old graphics
if (coinGraphics && coinGraphics.parent) {
coinGraphics.parent.removeChild(coinGraphics);
}
// Attach new asset
var newGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
return self;
});
var Driver = Container.expand(function () {
var self = Container.call(this);
self.x = +1500;
self.y = +1500;
var driverGraphics = self.attachAsset('driver', {
anchorX: 0.5,
anchorY: 0.5
});
});
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
****/
// Coin assets: 3 blue shades, 1 red
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(350, 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', {
loop: true
});
var mainContainer = game.addChild(new Container());
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++) {
game.addRoadSegment();
}
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);
var notificationTexts = ['Tuz aldınız mı?', 'Badem suyu aldınız tuz almadınız mı?', 'Sizle iş yapanın anasını.', 'Ben çok iyi bir sürücüyüm ya', 'Drift intheworld.', 'Patlat Meto.', 'Hop bakkal.', 'Ronaldoya hiz lazim.', 'Anne beni affet.', 'Look mom I can fly.'];
var usedNotificationTexts = [];
function getRandomNotificationText() {
if (notificationTexts.length === 0) {
notificationTexts = usedNotificationTexts.splice(0, usedNotificationTexts.length);
}
var index = Math.floor(Math.random() * notificationTexts.length);
var text = notificationTexts.splice(index, 1)[0];
usedNotificationTexts.push(text);
return text;
}
var notificationText = new Text2(getRandomNotificationText(), {
size: 60,
fill: 0xFFFFFF,
weight: '400',
align: 'center',
stroke: '#000000',
strokeThickness: 8
});
notificationText.anchor.set(0, 4);
notificationText.x -= 350;
LK.gui.bottom.addChild(notificationText);
var car = mainContainer.addChild(new Car());
car.x = 2048 / 2;
car.y = 2732 / 2;
var driver = LK.gui.addChild(new Driver());
driver.x = 250;
driver.y = 1800;
// Add hamzaa image to bottom-right corner and keep reference for glow
var hamzaaImage = LK.getAsset('hamzaa', {
anchorX: 1,
anchorY: 1,
x: 2048 - 40,
y: 2732 - 40,
scaleX: 0.25,
scaleY: 0.25
});
var isGameOver = false;
var score = 0;
var closestSegment = null;
var lastScoreForHamzaaGlow = 0; // Track last score that triggered glow
// Global reference for special hamza image
var hamzaSpecialImage = undefined;
game.on('down', function (x, y, obj) {
car.changeDirection();
});
// Import the tween plugin for animations
// Coin logic: spawn, update, collision, scoring
if (typeof coins === "undefined") {
var coins = [];
var coinSpawnTimer = 0;
var coinTypes = [{
type: 'blue',
assetId: 'coinBlue1'
}, {
type: 'blue',
assetId: 'coinBlue2'
}, {
type: 'blue',
assetId: 'coinBlue3'
}, {
type: 'red',
assetId: 'coinRed'
}];
}
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 (!segment._wasCarOnShadow) {
segment._wasCarOnShadow = true;
}
} else {
segment._wasCarOnShadow = false;
}
});
if (closestSegment !== currentClosestSegment && !currentClosestSegment.used) {
closestSegment = currentClosestSegment;
closestSegment.used = true;
score++;
car.ORIGINAL_SPEED += 0.1;
scoreText.setText(score.toString());
notificationText.setText(getRandomNotificationText());
// Highlight hamzaa and play hamza sound at 80, 160, 240, ...
if (score > 0 && score % 80 === 0 && lastScoreForHamzaaGlow !== score) {
lastScoreForHamzaaGlow = score;
// Use tween to create a glow effect (simulate by scaling up and down and changing alpha)
tween(hamzaaImage, {
scaleX: 0.35,
scaleY: 0.35,
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {
tween(hamzaaImage, {
scaleX: 0.25,
scaleY: 0.25,
alpha: 1
}, {
duration: 400
});
}
});
// --- NEW: Show 'hamza' image, stop music, play sound, then resume music ---
if (typeof hamzaSpecialImage !== "undefined" && hamzaSpecialImage && hamzaSpecialImage.parent) {
hamzaSpecialImage.parent.removeChild(hamzaSpecialImage);
hamzaSpecialImage = undefined;
}
// Create and display the 'hamza' image in the bottom-right at 600x600
hamzaSpecialImage = LK.getAsset('hamza', {
anchorX: 1,
anchorY: 1,
x: 2048 - 40,
y: 2732 - 40,
width: 600,
height: 600
});
game.addChild(hamzaSpecialImage);
// Stop the music, play the sound, then resume music after sound duration
LK.stopMusic();
var hamzaSound = LK.getSound('hamza');
hamzaSound.play();
// Remove the image and resume music after the sound finishes (assume 1.5s for safety)
LK.setTimeout(function () {
if (hamzaSpecialImage && hamzaSpecialImage.parent) {
hamzaSpecialImage.parent.removeChild(hamzaSpecialImage);
hamzaSpecialImage = undefined;
}
LK.playMusic('backgroundMusic', {
loop: true
});
}, 1500);
}
}
if (!carIsOnRoad) {
LK.showGameOver();
} else {}
LK.on('gameover', function () {
// Defer sound play to next tick to ensure it plays even if scripts are halted
LK.setTimeout(function () {
LK.getSound('hamza').play();
}, 0);
// Stop the sound when the Play Again button is pressed (game restarts)
LK.on('restart', function () {
LK.getSound('hamza').stop();
});
});
// --- COIN SPAWNING ---
coinSpawnTimer++;
if (coinSpawnTimer > 60) {
// spawn a coin every ~1 second
coinSpawnTimer = 0;
// Pick a random road segment to spawn on
var segIdx = Math.floor(Math.random() * roadSegments.length);
var seg = roadSegments[segIdx];
// Pick a random type
var coinTypeIdx = Math.floor(Math.random() * coinTypes.length);
var coinType = coinTypes[coinTypeIdx];
var coin = new Coin();
coin.setTypeAndAsset(coinType.type, coinType.assetId);
// Place coin at a random position along the segment, ensuring minimum distance from other coins
var minCoinDistance = 250; // Minimum distance in px between coins
var maxTries = 10;
var t,
tryCount = 0;
var segStart = {
x: seg.x + Math.sin(seg.rotation) * 100,
y: seg.y - Math.cos(seg.rotation) * 100
};
var segEnd = {
x: seg.x - Math.sin(seg.rotation) * (seg.height - seg.width / 2),
y: seg.y + Math.cos(seg.rotation) * (seg.height - seg.width / 2)
};
do {
t = Math.random() * 0.5 + 0.25;
coin.x = segStart.x + (segEnd.x - segStart.x) * t;
coin.y = segStart.y + (segEnd.y - segStart.y) * t;
var tooClose = false;
for (var j = 0; j < coins.length; j++) {
var other = coins[j];
var dx = coin.x - other.x;
var dy = coin.y - other.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minCoinDistance) {
tooClose = true;
break;
}
}
tryCount++;
} while (tooClose && tryCount < maxTries);
mainContainer.addChild(coin);
coins.push(coin);
}
// --- COIN COLLISION & COLLECTION ---
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (!coin.collected && car.intersects(coin)) {
coin.collected = true;
// Remove coin from scene
coin.destroy();
coins.splice(i, 1);
// Score logic
if (coin.type === 'blue') {
score += 5;
} else if (coin.type === 'red') {
score -= 5;
if (score < 0) score = 0;
}
scoreText.setText(score.toString());
// Highlight hamzaa and play hamza sound at 80, 160, 240, ...
if (score > 0 && score % 80 === 0 && lastScoreForHamzaaGlow !== score) {
lastScoreForHamzaaGlow = score;
tween(hamzaaImage, {
scaleX: 0.35,
scaleY: 0.35,
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {
tween(hamzaaImage, {
scaleX: 0.25,
scaleY: 0.25,
alpha: 1
}, {
duration: 400
});
}
});
// --- NEW: Show 'hamza' image, stop music, play sound, then resume music ---
if (typeof hamzaSpecialImage !== "undefined" && hamzaSpecialImage && hamzaSpecialImage.parent) {
hamzaSpecialImage.parent.removeChild(hamzaSpecialImage);
hamzaSpecialImage = undefined;
}
// Create and display the 'hamza' image in the bottom-right at 600x600
hamzaSpecialImage = LK.getAsset('hamza', {
anchorX: 1,
anchorY: 1,
x: 2048 - 40,
y: 2732 - 40,
width: 600,
height: 600
});
game.addChild(hamzaSpecialImage);
// Stop the music, play the sound, then resume music after sound duration
LK.stopMusic();
var hamzaSound = LK.getSound('hamza');
hamzaSound.play();
// Remove the image and resume music after the sound finishes (assume 1.5s for safety)
LK.setTimeout(function () {
if (hamzaSpecialImage && hamzaSpecialImage.parent) {
hamzaSpecialImage.parent.removeChild(hamzaSpecialImage);
hamzaSpecialImage = undefined;
}
LK.playMusic('backgroundMusic', {
loop: true
});
}, 1500);
}
}
}
// --- PARTICLE LOGIC ---
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();
}
}
});