/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Oyuncu arabası
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;
return self;
});
// Para (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 = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Vites butonu (D/R)
var GearButton = Container.expand(function () {
var self = Container.call(this);
self.txt = new Text2('D', {
size: 80,
fill: "#fff"
});
self.txt.anchor.set(0.5, 0.5);
self.addChild(self.txt);
self.gear = 'D'; // 'D' or 'R'
self.setGear = function (gear) {
self.gear = gear;
self.txt.setText(gear);
};
return self;
});
// Engel
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsAsset = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = obsAsset.width;
self.height = obsAsset.height;
self.speed = 18; // Başlangıç hızı, oyun ilerledikçe artacak
self.update = function () {
self.y += self.speed;
};
return self;
});
// Pedal butonu (gaz/fren)
var PedalButton = Container.expand(function () {
var self = Container.call(this);
self.txt = new Text2('Gaz', {
size: 70,
fill: "#fff"
});
self.txt.anchor.set(0.5, 0.5);
self.addChild(self.txt);
self.type = 'gaz'; // 'gaz' or 'fren'
self.setType = function (type) {
self.type = type;
self.txt.setText(type === 'gaz' ? 'Gaz' : 'Fren');
};
return self;
});
// Yol kenarı dekoru
var RoadEdge = Container.expand(function () {
var self = Container.call(this);
var edgeAsset = self.attachAsset('roadEdge', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = edgeAsset.width;
self.height = edgeAsset.height;
self.speed = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Yol çizgisi
var RoadLine = Container.expand(function () {
var self = Container.call(this);
var lineAsset = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = lineAsset.width;
self.height = lineAsset.height;
self.speed = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Dükkan simgesi
var ShopIcon = Container.expand(function () {
var self = Container.call(this);
var shopAsset = self.attachAsset('shopIcon', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = shopAsset.width;
self.height = shopAsset.height;
return self;
});
// Direksiyon simidi
var SteeringWheel = Container.expand(function () {
var self = Container.call(this);
self.txt = new Text2('🕹️', {
size: 200,
fill: "#fff"
});
self.txt.anchor.set(0.5, 0.5);
self.addChild(self.txt);
// Görsel büyüklüğü ve alanı
self.width = 260;
self.height = 260;
// Döndürme efekti için açı
self.angle = 0;
// Yana kaydırma için callback
self.onSteer = null;
// Basılı mı
self.isDown = false;
// Son X
self.lastX = 0;
// Sürükleme başlat
self.down = function (x, y, obj) {
self.isDown = true;
self.lastX = x;
};
// Sürükleme devam
self.move = function (x, y, obj) {
if (!self.isDown) return;
var dx = x - self.lastX;
self.lastX = x;
self.angle += dx * 0.2;
self.txt.rotation = self.angle * Math.PI / 180;
if (self.onSteer) self.onSteer(dx);
};
// Sürükleme bırak
self.up = function (x, y, obj) {
self.isDown = false;
// Direksiyon açısını sıfırla (animasyonla)
tween(self.txt, {
rotation: 0
}, 200, {
easing: 'easeOutQuad'
});
self.angle = 0;
};
return self;
});
// Ağaç dekoru
var Tree = Container.expand(function () {
var self = Container.call(this);
// Gövde
var trunk = self.attachAsset('treeTrunk', {
anchorX: 0.5,
anchorY: 1.0,
y: 180
});
// Yapraklar
var leaves = self.attachAsset('treeLeaves', {
anchorX: 0.5,
anchorY: 0.5,
y: 0,
scaleX: 4.5,
scaleY: 4.5
});
self.width = 600;
self.height = 700;
self.speed = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Arka plan dekorları
// Oyun alanı boyutları
// Araba (oyuncu) için kutu şeklinde bir asset
// Yol çizgisi için ince uzun kutu
// Engel için kırmızı kutu
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Yolun genişliği (ekranın ortasında)
var ROAD_WIDTH = 900;
var ROAD_X = (GAME_WIDTH - ROAD_WIDTH) / 2;
// Arabayı ve engelleri tutan değişkenler
var car;
var obstacles = [];
var roadLines = [];
var coins = [];
var score = 0;
var scoreTxt;
var money = 0;
var moneyTxt;
var dragNode = null;
var lastGameX = 0;
var gameSpeed = 18;
var ticksSinceStart = 0;
var spawnInterval = 60; // Engel oluşturma aralığı (frame cinsinden)
var minObstacleGap = 400; // Engeller arası minimum mesafe
// Skor gösterimi (üstte, ortada)
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Para gösterimi (sağ üstte)
moneyTxt = new Text2('₺0', {
size: 90,
fill: 0xFFD600
});
moneyTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(moneyTxt);
// Duraklatma butonu (oyunu durdurmak için, sağ üstte)
var pauseBtn = new Text2('⏸', {
size: 120,
fill: "#fff"
});
pauseBtn.anchor.set(1, 0);
pauseBtn.x = 0;
pauseBtn.y = 340;
LK.gui.topRight.addChild(pauseBtn);
// Pause butonuna tıklama kontrolü için koordinatları sakla
var pauseBtnArea = {
x: GAME_WIDTH - 180,
y: 340,
width: 160,
height: 160
};
// Dükkan açma butonu (duraklatma butonunun hemen altında)
var shopBtn = new ShopIcon();
// Shop iconu yeşil yap
if (shopBtn.children && shopBtn.children[0]) {
shopBtn.children[0].tint = 0x00e676;
}
shopBtn.x = -320; // Daha sola kaydır (daha kolay tıklansın)
shopBtn.y = pauseBtn.y + 180;
LK.gui.topRight.addChild(shopBtn);
// Shop butonuna tıklama kontrolü için koordinatları sakla
var shopBtnArea = {
x: GAME_WIDTH - 400,
// daha sola kaydırıldı
y: shopBtn.y,
width: 160,
height: 160
};
// Arka plan dekorları: yol kenarı ve ağaçlar
var leftEdges = [];
var rightEdges = [];
var leftTrees = [];
var rightTrees = [];
var edgeCount = 8;
var treeCount = 8;
for (var i = 0; i < edgeCount; i++) {
var lEdge = new RoadEdge();
lEdge.x = ROAD_X + 20;
lEdge.y = i * 400 + 200;
leftEdges.push(lEdge);
game.addChild(lEdge);
var rEdge = new RoadEdge();
rEdge.x = ROAD_X + ROAD_WIDTH - 20;
rEdge.y = i * 400 + 200;
rightEdges.push(rEdge);
game.addChild(rEdge);
}
for (var i = 0; i < treeCount; i++) {
var lTree = new Tree();
lTree.x = ROAD_X - 80;
lTree.y = i * 400 + 100;
leftTrees.push(lTree);
game.addChild(lTree);
var rTree = new Tree();
rTree.x = ROAD_X + ROAD_WIDTH + 80;
rTree.y = i * 400 + 300;
rightTrees.push(rTree);
game.addChild(rTree);
}
// Arabayı oluştur ve konumlandır
car = new Car();
game.addChild(car);
car.x = GAME_WIDTH / 2;
car.y = GAME_HEIGHT - 500;
// Yol çizgilerini oluştur
for (var i = 0; i < 7; i++) {
var line = new RoadLine();
line.x = GAME_WIDTH / 2;
line.y = i * 400 + 200;
roadLines.push(line);
game.addChild(line);
}
// Yol ayrımları için parametreler
var forkActive = false;
var forkXLeft = ROAD_X + ROAD_WIDTH * 0.25;
var forkXRight = ROAD_X + ROAD_WIDTH * 0.75;
var forkY = 900;
var forkTimer = 0;
var forkInterval = 900; // Her 900 frame'de bir yol ayrımı gelsin
var forkChoice = null; // 'left' veya 'right'
var forkVisuals = [];
// Yol ayrımı görseli (çatalı)
function showFork() {
forkActive = true;
forkChoice = null;
// Sol ve sağ oklar
var leftArrow = new Text2('⬅', {
size: 180,
fill: "#fff"
});
leftArrow.anchor.set(0.5, 0.5);
leftArrow.x = forkXLeft;
leftArrow.y = forkY - 100;
var rightArrow = new Text2('➡', {
size: 180,
fill: "#fff"
});
rightArrow.anchor.set(0.5, 0.5);
rightArrow.x = forkXRight;
rightArrow.y = forkY - 100;
forkVisuals.push(leftArrow, rightArrow);
game.addChild(leftArrow);
game.addChild(rightArrow);
// Çatal çizgisi (görsel için iki yol çizgisi)
for (var i = 0; i < 2; i++) {
var forkLine = new RoadLine();
forkLine.x = i === 0 ? forkXLeft : forkXRight;
forkLine.y = forkY;
forkLine.speed = 0;
forkVisuals.push(forkLine);
game.addChild(forkLine);
}
}
// Yol ayrımı görsellerini temizle
function clearFork() {
for (var i = 0; i < forkVisuals.length; i++) {
forkVisuals[i].destroy();
}
forkVisuals = [];
forkActive = false;
forkChoice = null;
}
// Vites butonları (D/R), gaz ve fren, direksiyon simidi
var gearBtn = new GearButton();
gearBtn.x = 0;
gearBtn.y = 0;
gearBtn.setGear('D');
LK.gui.right.addChild(gearBtn);
var pedalGaz = new PedalButton();
pedalGaz.setType('gaz');
pedalGaz.x = 0;
pedalGaz.y = 180;
LK.gui.right.addChild(pedalGaz);
var pedalFren = new PedalButton();
pedalFren.setType('fren');
pedalFren.x = 0;
pedalFren.y = 340;
LK.gui.right.addChild(pedalFren);
var steering = new SteeringWheel();
// Ekranın alt orta kısmına yerleştir (GUI overlay koordinatları ile)
steering.x = LK.gui.center.width / 2;
steering.y = LK.gui.bottom.height - 180;
LK.gui.bottom.addChild(steering);
// --- Fren butonu (sağ altta) ---
var brakeBtn = new Text2('🛑', {
size: 140,
fill: "#fff"
});
brakeBtn.anchor.set(1, 1);
brakeBtn.x = LK.gui.bottomRight.width - 40;
brakeBtn.y = LK.gui.bottomRight.height - 40;
LK.gui.bottomRight.addChild(brakeBtn);
// Brake button area for touch detection
var brakeBtnArea = {
x: GAME_WIDTH - 320,
y: GAME_HEIGHT - 320,
width: 260,
height: 260
};
var brakePressed = false;
// Oyun durumu için vites, gaz, fren
var currentGear = 'D'; // 'D' veya 'R'
var gazPressed = false;
var frenPressed = false;
// Direksiyon simidi ile araba kontrolü
steering.onSteer = function (dx) {
// dx: sağa/sola kaydırma miktarı
if (!car) return;
car.x += dx * 2.2; // Hassasiyet ayarı
// Yol dışına çıkmasın
var minX = ROAD_X + car.width / 2 + 10;
var maxX = ROAD_X + ROAD_WIDTH - car.width / 2 - 10;
if (car.x < minX) car.x = minX;
if (car.x > maxX) car.x = maxX;
};
// Oyun güncelleme fonksiyonu
game.update = function () {
ticksSinceStart++;
// Yol kenarı ve ağaçları hareket ettir ve döngüsel olarak tekrar yukarıya al
for (var i = 0; i < leftEdges.length; i++) {
var lEdge = leftEdges[i];
lEdge.speed = gameSpeed;
lEdge.update();
if (lEdge.y - lEdge.height / 2 > GAME_HEIGHT) {
lEdge.y -= edgeCount * 400;
}
var rEdge = rightEdges[i];
rEdge.speed = gameSpeed;
rEdge.update();
if (rEdge.y - rEdge.height / 2 > GAME_HEIGHT) {
rEdge.y -= edgeCount * 400;
}
}
for (var i = 0; i < leftTrees.length; i++) {
var lTree = leftTrees[i];
lTree.speed = gameSpeed;
lTree.update();
if (lTree.y - lTree.height / 2 > GAME_HEIGHT) {
lTree.y -= treeCount * 400;
}
var rTree = rightTrees[i];
rTree.speed = gameSpeed;
rTree.update();
if (rTree.y - rTree.height / 2 > GAME_HEIGHT) {
rTree.y -= treeCount * 400;
}
}
// Yol çizgilerini hareket ettir ve döngüsel olarak tekrar yukarıya al
for (var i = 0; i < roadLines.length; i++) {
var line = roadLines[i];
line.speed = gameSpeed;
line.update();
if (line.y - line.height / 2 > GAME_HEIGHT) {
line.y -= 7 * 400;
}
}
// Yol ayrımı (fork) oluşturma ve yönetimi
forkTimer++;
if (!forkActive && forkTimer > forkInterval) {
showFork();
forkTimer = 0;
}
// Eğer yol ayrımı aktifse, oyuncu seçim yapmalı
if (forkActive) {
// Araba çatal bölgesine geldi mi?
if (!forkChoice && car.y < forkY + 100 && car.y > forkY - 100) {
// Oyuncu sola veya sağa kayarsa seçim yap
if (car.x < GAME_WIDTH / 2) {
forkChoice = 'left';
} else if (car.x > GAME_WIDTH / 2) {
forkChoice = 'right';
}
if (forkChoice) {
// Arabayı seçilen yola kaydır
var targetX = forkChoice === 'left' ? forkXLeft : forkXRight;
tween(car, {
x: targetX
}, 300, {
easing: 'easeInOutQuad'
});
// Yol çizgilerini de kaydır
for (var i = 0; i < roadLines.length; i++) {
tween(roadLines[i], {
x: targetX
}, 300, {
easing: 'easeInOutQuad'
});
}
// 0.5 saniye sonra fork görsellerini kaldır
LK.setTimeout(clearFork, 500);
}
}
}
// Engelleri hareket ettir
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.speed = gameSpeed;
obs.update();
// Ekrandan çıktıysa sil
if (obs.y - obs.height / 2 > GAME_HEIGHT + 100) {
obs.destroy();
obstacles.splice(i, 1);
score++;
scoreTxt.setText(score);
continue;
}
// Çarpışma kontrolü
if (car.intersects(obs)) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
}
// Paraları hareket ettir
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
coin.speed = gameSpeed;
coin.update();
// Ekrandan çıktıysa sil
if (coin.y - coin.height / 2 > GAME_HEIGHT + 100) {
coin.destroy();
coins.splice(i, 1);
continue;
}
// Araba ile çarpışma (para toplama)
if (car.intersects(coin)) {
money += 10;
moneyTxt.setText('₺' + money);
coin.destroy();
coins.splice(i, 1);
continue;
}
}
// Engel oluşturma (aralıkla)
if (ticksSinceStart % spawnInterval === 0) {
var obs = new Obstacle();
// Rastgele x konumu, yolun dışına çıkmasın
var minX = ROAD_X + obs.width / 2 + 30;
var maxX = ROAD_X + ROAD_WIDTH - obs.width / 2 - 30;
obs.x = minX + Math.random() * (maxX - minX);
obs.y = -obs.height / 2;
obstacles.push(obs);
game.addChild(obs);
// %50 ihtimalle para da oluştur
if (Math.random() < 0.5) {
var coin = new Coin();
var minCoinX = ROAD_X + coin.width / 2 + 30;
var maxCoinX = ROAD_X + ROAD_WIDTH - coin.width / 2 - 30;
var tryCount = 0;
var maxTries = 8;
var validCoinPos = false;
while (!validCoinPos && tryCount < maxTries) {
coin.x = minCoinX + Math.random() * (maxCoinX - minCoinX);
coin.y = -coin.height / 2 - 120;
validCoinPos = true;
// Check if coin would overlap with any obstacle at spawn
for (var oi = 0; oi < obstacles.length; oi++) {
var obs = obstacles[oi];
// Only check obstacles that are close to spawn Y
if (Math.abs(obs.y - coin.y) < (obs.height + coin.height) / 2 + 40) {
// Check X overlap
if (Math.abs(obs.x - coin.x) < (obs.width + coin.width) / 2 + 10) {
validCoinPos = false;
break;
}
}
}
tryCount++;
}
if (validCoinPos) {
coins.push(coin);
game.addChild(coin);
} else {
coin.destroy();
}
}
}
// Zorluk arttırma: zamanla hız ve engel sıklığı artar
if (ticksSinceStart % 300 === 0 && gameSpeed < 38) {
gameSpeed += 2;
if (spawnInterval > 28) spawnInterval -= 4;
}
// Vites ve pedal kontrolleri
// Fren butonu basılıysa araba tamamen dursun
if (brakePressed) {
// Arabayı tamamen durdur
// Hiçbir hareket yok, gaz/fren/vites etkisiz
// (car.y değişmez)
// Ayrıca gaz/fren/vites etkisizleştirildiği için başka bir şey yapılmaz
} else if (currentGear === 'D') {
if (gazPressed) {
car.y -= 10;
if (car.y < GAME_HEIGHT / 2) car.y = GAME_HEIGHT / 2;
} else if (frenPressed) {
car.y += 8;
if (car.y > GAME_HEIGHT - 500) car.y = GAME_HEIGHT - 500;
}
} else if (currentGear === 'R') {
if (gazPressed) {
car.y += 10;
if (car.y > GAME_HEIGHT - 500) car.y = GAME_HEIGHT - 500;
} else if (frenPressed) {
car.y -= 8;
if (car.y < GAME_HEIGHT / 2) car.y = GAME_HEIGHT / 2;
}
}
// Skor güncellemesi (her frame değil, engel geçince artıyor)
};
// Sürükleme işlemleri ve UI butonları
game.down = function (x, y, obj) {
// Vites butonuna tıklandı mı?
var gearBtnBounds = LK.gui.right.toLocal(gearBtn.toGlobal({
x: 0,
y: 0
}));
if (x > GAME_WIDTH - 300 && y > 100 && y < 300) {
// Vites değiştir
if (currentGear === 'D') {
currentGear = 'R';
gearBtn.setGear('R');
} else {
currentGear = 'D';
gearBtn.setGear('D');
}
return;
}
// Gaz pedalı
if (x > GAME_WIDTH - 300 && y > 400 && y < 600) {
gazPressed = true;
return;
}
// Fren pedalı
if (x > GAME_WIDTH - 300 && y > 600 && y < 800) {
frenPressed = true;
return;
}
// Fren butonu (sağ altta)
if (x > brakeBtnArea.x && x < brakeBtnArea.x + brakeBtnArea.width && y > brakeBtnArea.y && y < brakeBtnArea.y + brakeBtnArea.height) {
brakePressed = true;
return;
}
// Dükkan açma butonu (duraklatma butonunun altında)
// GUI overlay koordinatlarını oyun koordinatına çevir
var shopBtnGlobal = LK.gui.topRight.toGlobal({
x: shopBtn.x,
y: shopBtn.y
});
if (x > shopBtnGlobal.x - shopBtn.width / 2 && x < shopBtnGlobal.x + shopBtn.width / 2 && y > shopBtnGlobal.y - shopBtn.height / 2 && y < shopBtnGlobal.y + shopBtn.height / 2) {
LK.effects.flashScreen(0x00e676, 400);
if (typeof LK.showShopMenu === "function") LK.showShopMenu();
return;
}
// Duraklatma butonu (sağ üstte)
if (x > pauseBtnArea.x && x < pauseBtnArea.x + pauseBtnArea.width && y > pauseBtnArea.y && y < pauseBtnArea.y + pauseBtnArea.height) {
LK.showPauseMenu();
return;
}
// Direksiyon simidi (sol alt)
if (x < 400 && y > GAME_HEIGHT - 600) {
// Direksiyon simidiyle sürükleme başlat
if (steering && steering.down) steering.down(x, y, obj);
// Arabayı da sürüklemeye başlat
dragNode = car;
lastGameX = x;
return;
}
// Arabaya dokunulmuşsa veya ekrana dokunulmuşsa sürüklemeye başla
if (x > car.x - car.width / 2 && x < car.x + car.width / 2 && y > car.y - car.height / 2 && y < car.y + car.height / 2) {
dragNode = car;
lastGameX = x;
} else if (y > GAME_HEIGHT / 2 // Sadece alt yarıda sürüklemeye izin ver
) {
dragNode = car;
lastGameX = x;
}
};
game.move = function (x, y, obj) {
if (dragNode === car) {
// Eğer direksiyon simidi aktifse, onun move fonksiyonunu çağır
if (steering && steering.isDown && steering.move) {
steering.move(x, y, obj);
}
// Sürükleme ile araba hareketi devre dışı (direksiyon ile kontrol edilecek)
// car.x değişimi steering.onSteer ile yapılacak
}
};
game.up = function (x, y, obj) {
dragNode = null;
gazPressed = false;
frenPressed = false;
brakePressed = false;
if (steering && steering.isDown && steering.up) {
steering.up(0, 0, null);
}
};
// Oyun başında skor ve para sıfırla
score = 0;
scoreTxt.setText(score);
money = 0;
moneyTxt.setText('₺' + money);
currentGear = 'D';
gearBtn.setGear('D');
gazPressed = false;
frenPressed = false; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Oyuncu arabası
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;
return self;
});
// Para (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 = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Vites butonu (D/R)
var GearButton = Container.expand(function () {
var self = Container.call(this);
self.txt = new Text2('D', {
size: 80,
fill: "#fff"
});
self.txt.anchor.set(0.5, 0.5);
self.addChild(self.txt);
self.gear = 'D'; // 'D' or 'R'
self.setGear = function (gear) {
self.gear = gear;
self.txt.setText(gear);
};
return self;
});
// Engel
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsAsset = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = obsAsset.width;
self.height = obsAsset.height;
self.speed = 18; // Başlangıç hızı, oyun ilerledikçe artacak
self.update = function () {
self.y += self.speed;
};
return self;
});
// Pedal butonu (gaz/fren)
var PedalButton = Container.expand(function () {
var self = Container.call(this);
self.txt = new Text2('Gaz', {
size: 70,
fill: "#fff"
});
self.txt.anchor.set(0.5, 0.5);
self.addChild(self.txt);
self.type = 'gaz'; // 'gaz' or 'fren'
self.setType = function (type) {
self.type = type;
self.txt.setText(type === 'gaz' ? 'Gaz' : 'Fren');
};
return self;
});
// Yol kenarı dekoru
var RoadEdge = Container.expand(function () {
var self = Container.call(this);
var edgeAsset = self.attachAsset('roadEdge', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = edgeAsset.width;
self.height = edgeAsset.height;
self.speed = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Yol çizgisi
var RoadLine = Container.expand(function () {
var self = Container.call(this);
var lineAsset = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = lineAsset.width;
self.height = lineAsset.height;
self.speed = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Dükkan simgesi
var ShopIcon = Container.expand(function () {
var self = Container.call(this);
var shopAsset = self.attachAsset('shopIcon', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = shopAsset.width;
self.height = shopAsset.height;
return self;
});
// Direksiyon simidi
var SteeringWheel = Container.expand(function () {
var self = Container.call(this);
self.txt = new Text2('🕹️', {
size: 200,
fill: "#fff"
});
self.txt.anchor.set(0.5, 0.5);
self.addChild(self.txt);
// Görsel büyüklüğü ve alanı
self.width = 260;
self.height = 260;
// Döndürme efekti için açı
self.angle = 0;
// Yana kaydırma için callback
self.onSteer = null;
// Basılı mı
self.isDown = false;
// Son X
self.lastX = 0;
// Sürükleme başlat
self.down = function (x, y, obj) {
self.isDown = true;
self.lastX = x;
};
// Sürükleme devam
self.move = function (x, y, obj) {
if (!self.isDown) return;
var dx = x - self.lastX;
self.lastX = x;
self.angle += dx * 0.2;
self.txt.rotation = self.angle * Math.PI / 180;
if (self.onSteer) self.onSteer(dx);
};
// Sürükleme bırak
self.up = function (x, y, obj) {
self.isDown = false;
// Direksiyon açısını sıfırla (animasyonla)
tween(self.txt, {
rotation: 0
}, 200, {
easing: 'easeOutQuad'
});
self.angle = 0;
};
return self;
});
// Ağaç dekoru
var Tree = Container.expand(function () {
var self = Container.call(this);
// Gövde
var trunk = self.attachAsset('treeTrunk', {
anchorX: 0.5,
anchorY: 1.0,
y: 180
});
// Yapraklar
var leaves = self.attachAsset('treeLeaves', {
anchorX: 0.5,
anchorY: 0.5,
y: 0,
scaleX: 4.5,
scaleY: 4.5
});
self.width = 600;
self.height = 700;
self.speed = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Arka plan dekorları
// Oyun alanı boyutları
// Araba (oyuncu) için kutu şeklinde bir asset
// Yol çizgisi için ince uzun kutu
// Engel için kırmızı kutu
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Yolun genişliği (ekranın ortasında)
var ROAD_WIDTH = 900;
var ROAD_X = (GAME_WIDTH - ROAD_WIDTH) / 2;
// Arabayı ve engelleri tutan değişkenler
var car;
var obstacles = [];
var roadLines = [];
var coins = [];
var score = 0;
var scoreTxt;
var money = 0;
var moneyTxt;
var dragNode = null;
var lastGameX = 0;
var gameSpeed = 18;
var ticksSinceStart = 0;
var spawnInterval = 60; // Engel oluşturma aralığı (frame cinsinden)
var minObstacleGap = 400; // Engeller arası minimum mesafe
// Skor gösterimi (üstte, ortada)
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Para gösterimi (sağ üstte)
moneyTxt = new Text2('₺0', {
size: 90,
fill: 0xFFD600
});
moneyTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(moneyTxt);
// Duraklatma butonu (oyunu durdurmak için, sağ üstte)
var pauseBtn = new Text2('⏸', {
size: 120,
fill: "#fff"
});
pauseBtn.anchor.set(1, 0);
pauseBtn.x = 0;
pauseBtn.y = 340;
LK.gui.topRight.addChild(pauseBtn);
// Pause butonuna tıklama kontrolü için koordinatları sakla
var pauseBtnArea = {
x: GAME_WIDTH - 180,
y: 340,
width: 160,
height: 160
};
// Dükkan açma butonu (duraklatma butonunun hemen altında)
var shopBtn = new ShopIcon();
// Shop iconu yeşil yap
if (shopBtn.children && shopBtn.children[0]) {
shopBtn.children[0].tint = 0x00e676;
}
shopBtn.x = -320; // Daha sola kaydır (daha kolay tıklansın)
shopBtn.y = pauseBtn.y + 180;
LK.gui.topRight.addChild(shopBtn);
// Shop butonuna tıklama kontrolü için koordinatları sakla
var shopBtnArea = {
x: GAME_WIDTH - 400,
// daha sola kaydırıldı
y: shopBtn.y,
width: 160,
height: 160
};
// Arka plan dekorları: yol kenarı ve ağaçlar
var leftEdges = [];
var rightEdges = [];
var leftTrees = [];
var rightTrees = [];
var edgeCount = 8;
var treeCount = 8;
for (var i = 0; i < edgeCount; i++) {
var lEdge = new RoadEdge();
lEdge.x = ROAD_X + 20;
lEdge.y = i * 400 + 200;
leftEdges.push(lEdge);
game.addChild(lEdge);
var rEdge = new RoadEdge();
rEdge.x = ROAD_X + ROAD_WIDTH - 20;
rEdge.y = i * 400 + 200;
rightEdges.push(rEdge);
game.addChild(rEdge);
}
for (var i = 0; i < treeCount; i++) {
var lTree = new Tree();
lTree.x = ROAD_X - 80;
lTree.y = i * 400 + 100;
leftTrees.push(lTree);
game.addChild(lTree);
var rTree = new Tree();
rTree.x = ROAD_X + ROAD_WIDTH + 80;
rTree.y = i * 400 + 300;
rightTrees.push(rTree);
game.addChild(rTree);
}
// Arabayı oluştur ve konumlandır
car = new Car();
game.addChild(car);
car.x = GAME_WIDTH / 2;
car.y = GAME_HEIGHT - 500;
// Yol çizgilerini oluştur
for (var i = 0; i < 7; i++) {
var line = new RoadLine();
line.x = GAME_WIDTH / 2;
line.y = i * 400 + 200;
roadLines.push(line);
game.addChild(line);
}
// Yol ayrımları için parametreler
var forkActive = false;
var forkXLeft = ROAD_X + ROAD_WIDTH * 0.25;
var forkXRight = ROAD_X + ROAD_WIDTH * 0.75;
var forkY = 900;
var forkTimer = 0;
var forkInterval = 900; // Her 900 frame'de bir yol ayrımı gelsin
var forkChoice = null; // 'left' veya 'right'
var forkVisuals = [];
// Yol ayrımı görseli (çatalı)
function showFork() {
forkActive = true;
forkChoice = null;
// Sol ve sağ oklar
var leftArrow = new Text2('⬅', {
size: 180,
fill: "#fff"
});
leftArrow.anchor.set(0.5, 0.5);
leftArrow.x = forkXLeft;
leftArrow.y = forkY - 100;
var rightArrow = new Text2('➡', {
size: 180,
fill: "#fff"
});
rightArrow.anchor.set(0.5, 0.5);
rightArrow.x = forkXRight;
rightArrow.y = forkY - 100;
forkVisuals.push(leftArrow, rightArrow);
game.addChild(leftArrow);
game.addChild(rightArrow);
// Çatal çizgisi (görsel için iki yol çizgisi)
for (var i = 0; i < 2; i++) {
var forkLine = new RoadLine();
forkLine.x = i === 0 ? forkXLeft : forkXRight;
forkLine.y = forkY;
forkLine.speed = 0;
forkVisuals.push(forkLine);
game.addChild(forkLine);
}
}
// Yol ayrımı görsellerini temizle
function clearFork() {
for (var i = 0; i < forkVisuals.length; i++) {
forkVisuals[i].destroy();
}
forkVisuals = [];
forkActive = false;
forkChoice = null;
}
// Vites butonları (D/R), gaz ve fren, direksiyon simidi
var gearBtn = new GearButton();
gearBtn.x = 0;
gearBtn.y = 0;
gearBtn.setGear('D');
LK.gui.right.addChild(gearBtn);
var pedalGaz = new PedalButton();
pedalGaz.setType('gaz');
pedalGaz.x = 0;
pedalGaz.y = 180;
LK.gui.right.addChild(pedalGaz);
var pedalFren = new PedalButton();
pedalFren.setType('fren');
pedalFren.x = 0;
pedalFren.y = 340;
LK.gui.right.addChild(pedalFren);
var steering = new SteeringWheel();
// Ekranın alt orta kısmına yerleştir (GUI overlay koordinatları ile)
steering.x = LK.gui.center.width / 2;
steering.y = LK.gui.bottom.height - 180;
LK.gui.bottom.addChild(steering);
// --- Fren butonu (sağ altta) ---
var brakeBtn = new Text2('🛑', {
size: 140,
fill: "#fff"
});
brakeBtn.anchor.set(1, 1);
brakeBtn.x = LK.gui.bottomRight.width - 40;
brakeBtn.y = LK.gui.bottomRight.height - 40;
LK.gui.bottomRight.addChild(brakeBtn);
// Brake button area for touch detection
var brakeBtnArea = {
x: GAME_WIDTH - 320,
y: GAME_HEIGHT - 320,
width: 260,
height: 260
};
var brakePressed = false;
// Oyun durumu için vites, gaz, fren
var currentGear = 'D'; // 'D' veya 'R'
var gazPressed = false;
var frenPressed = false;
// Direksiyon simidi ile araba kontrolü
steering.onSteer = function (dx) {
// dx: sağa/sola kaydırma miktarı
if (!car) return;
car.x += dx * 2.2; // Hassasiyet ayarı
// Yol dışına çıkmasın
var minX = ROAD_X + car.width / 2 + 10;
var maxX = ROAD_X + ROAD_WIDTH - car.width / 2 - 10;
if (car.x < minX) car.x = minX;
if (car.x > maxX) car.x = maxX;
};
// Oyun güncelleme fonksiyonu
game.update = function () {
ticksSinceStart++;
// Yol kenarı ve ağaçları hareket ettir ve döngüsel olarak tekrar yukarıya al
for (var i = 0; i < leftEdges.length; i++) {
var lEdge = leftEdges[i];
lEdge.speed = gameSpeed;
lEdge.update();
if (lEdge.y - lEdge.height / 2 > GAME_HEIGHT) {
lEdge.y -= edgeCount * 400;
}
var rEdge = rightEdges[i];
rEdge.speed = gameSpeed;
rEdge.update();
if (rEdge.y - rEdge.height / 2 > GAME_HEIGHT) {
rEdge.y -= edgeCount * 400;
}
}
for (var i = 0; i < leftTrees.length; i++) {
var lTree = leftTrees[i];
lTree.speed = gameSpeed;
lTree.update();
if (lTree.y - lTree.height / 2 > GAME_HEIGHT) {
lTree.y -= treeCount * 400;
}
var rTree = rightTrees[i];
rTree.speed = gameSpeed;
rTree.update();
if (rTree.y - rTree.height / 2 > GAME_HEIGHT) {
rTree.y -= treeCount * 400;
}
}
// Yol çizgilerini hareket ettir ve döngüsel olarak tekrar yukarıya al
for (var i = 0; i < roadLines.length; i++) {
var line = roadLines[i];
line.speed = gameSpeed;
line.update();
if (line.y - line.height / 2 > GAME_HEIGHT) {
line.y -= 7 * 400;
}
}
// Yol ayrımı (fork) oluşturma ve yönetimi
forkTimer++;
if (!forkActive && forkTimer > forkInterval) {
showFork();
forkTimer = 0;
}
// Eğer yol ayrımı aktifse, oyuncu seçim yapmalı
if (forkActive) {
// Araba çatal bölgesine geldi mi?
if (!forkChoice && car.y < forkY + 100 && car.y > forkY - 100) {
// Oyuncu sola veya sağa kayarsa seçim yap
if (car.x < GAME_WIDTH / 2) {
forkChoice = 'left';
} else if (car.x > GAME_WIDTH / 2) {
forkChoice = 'right';
}
if (forkChoice) {
// Arabayı seçilen yola kaydır
var targetX = forkChoice === 'left' ? forkXLeft : forkXRight;
tween(car, {
x: targetX
}, 300, {
easing: 'easeInOutQuad'
});
// Yol çizgilerini de kaydır
for (var i = 0; i < roadLines.length; i++) {
tween(roadLines[i], {
x: targetX
}, 300, {
easing: 'easeInOutQuad'
});
}
// 0.5 saniye sonra fork görsellerini kaldır
LK.setTimeout(clearFork, 500);
}
}
}
// Engelleri hareket ettir
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.speed = gameSpeed;
obs.update();
// Ekrandan çıktıysa sil
if (obs.y - obs.height / 2 > GAME_HEIGHT + 100) {
obs.destroy();
obstacles.splice(i, 1);
score++;
scoreTxt.setText(score);
continue;
}
// Çarpışma kontrolü
if (car.intersects(obs)) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
}
// Paraları hareket ettir
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
coin.speed = gameSpeed;
coin.update();
// Ekrandan çıktıysa sil
if (coin.y - coin.height / 2 > GAME_HEIGHT + 100) {
coin.destroy();
coins.splice(i, 1);
continue;
}
// Araba ile çarpışma (para toplama)
if (car.intersects(coin)) {
money += 10;
moneyTxt.setText('₺' + money);
coin.destroy();
coins.splice(i, 1);
continue;
}
}
// Engel oluşturma (aralıkla)
if (ticksSinceStart % spawnInterval === 0) {
var obs = new Obstacle();
// Rastgele x konumu, yolun dışına çıkmasın
var minX = ROAD_X + obs.width / 2 + 30;
var maxX = ROAD_X + ROAD_WIDTH - obs.width / 2 - 30;
obs.x = minX + Math.random() * (maxX - minX);
obs.y = -obs.height / 2;
obstacles.push(obs);
game.addChild(obs);
// %50 ihtimalle para da oluştur
if (Math.random() < 0.5) {
var coin = new Coin();
var minCoinX = ROAD_X + coin.width / 2 + 30;
var maxCoinX = ROAD_X + ROAD_WIDTH - coin.width / 2 - 30;
var tryCount = 0;
var maxTries = 8;
var validCoinPos = false;
while (!validCoinPos && tryCount < maxTries) {
coin.x = minCoinX + Math.random() * (maxCoinX - minCoinX);
coin.y = -coin.height / 2 - 120;
validCoinPos = true;
// Check if coin would overlap with any obstacle at spawn
for (var oi = 0; oi < obstacles.length; oi++) {
var obs = obstacles[oi];
// Only check obstacles that are close to spawn Y
if (Math.abs(obs.y - coin.y) < (obs.height + coin.height) / 2 + 40) {
// Check X overlap
if (Math.abs(obs.x - coin.x) < (obs.width + coin.width) / 2 + 10) {
validCoinPos = false;
break;
}
}
}
tryCount++;
}
if (validCoinPos) {
coins.push(coin);
game.addChild(coin);
} else {
coin.destroy();
}
}
}
// Zorluk arttırma: zamanla hız ve engel sıklığı artar
if (ticksSinceStart % 300 === 0 && gameSpeed < 38) {
gameSpeed += 2;
if (spawnInterval > 28) spawnInterval -= 4;
}
// Vites ve pedal kontrolleri
// Fren butonu basılıysa araba tamamen dursun
if (brakePressed) {
// Arabayı tamamen durdur
// Hiçbir hareket yok, gaz/fren/vites etkisiz
// (car.y değişmez)
// Ayrıca gaz/fren/vites etkisizleştirildiği için başka bir şey yapılmaz
} else if (currentGear === 'D') {
if (gazPressed) {
car.y -= 10;
if (car.y < GAME_HEIGHT / 2) car.y = GAME_HEIGHT / 2;
} else if (frenPressed) {
car.y += 8;
if (car.y > GAME_HEIGHT - 500) car.y = GAME_HEIGHT - 500;
}
} else if (currentGear === 'R') {
if (gazPressed) {
car.y += 10;
if (car.y > GAME_HEIGHT - 500) car.y = GAME_HEIGHT - 500;
} else if (frenPressed) {
car.y -= 8;
if (car.y < GAME_HEIGHT / 2) car.y = GAME_HEIGHT / 2;
}
}
// Skor güncellemesi (her frame değil, engel geçince artıyor)
};
// Sürükleme işlemleri ve UI butonları
game.down = function (x, y, obj) {
// Vites butonuna tıklandı mı?
var gearBtnBounds = LK.gui.right.toLocal(gearBtn.toGlobal({
x: 0,
y: 0
}));
if (x > GAME_WIDTH - 300 && y > 100 && y < 300) {
// Vites değiştir
if (currentGear === 'D') {
currentGear = 'R';
gearBtn.setGear('R');
} else {
currentGear = 'D';
gearBtn.setGear('D');
}
return;
}
// Gaz pedalı
if (x > GAME_WIDTH - 300 && y > 400 && y < 600) {
gazPressed = true;
return;
}
// Fren pedalı
if (x > GAME_WIDTH - 300 && y > 600 && y < 800) {
frenPressed = true;
return;
}
// Fren butonu (sağ altta)
if (x > brakeBtnArea.x && x < brakeBtnArea.x + brakeBtnArea.width && y > brakeBtnArea.y && y < brakeBtnArea.y + brakeBtnArea.height) {
brakePressed = true;
return;
}
// Dükkan açma butonu (duraklatma butonunun altında)
// GUI overlay koordinatlarını oyun koordinatına çevir
var shopBtnGlobal = LK.gui.topRight.toGlobal({
x: shopBtn.x,
y: shopBtn.y
});
if (x > shopBtnGlobal.x - shopBtn.width / 2 && x < shopBtnGlobal.x + shopBtn.width / 2 && y > shopBtnGlobal.y - shopBtn.height / 2 && y < shopBtnGlobal.y + shopBtn.height / 2) {
LK.effects.flashScreen(0x00e676, 400);
if (typeof LK.showShopMenu === "function") LK.showShopMenu();
return;
}
// Duraklatma butonu (sağ üstte)
if (x > pauseBtnArea.x && x < pauseBtnArea.x + pauseBtnArea.width && y > pauseBtnArea.y && y < pauseBtnArea.y + pauseBtnArea.height) {
LK.showPauseMenu();
return;
}
// Direksiyon simidi (sol alt)
if (x < 400 && y > GAME_HEIGHT - 600) {
// Direksiyon simidiyle sürükleme başlat
if (steering && steering.down) steering.down(x, y, obj);
// Arabayı da sürüklemeye başlat
dragNode = car;
lastGameX = x;
return;
}
// Arabaya dokunulmuşsa veya ekrana dokunulmuşsa sürüklemeye başla
if (x > car.x - car.width / 2 && x < car.x + car.width / 2 && y > car.y - car.height / 2 && y < car.y + car.height / 2) {
dragNode = car;
lastGameX = x;
} else if (y > GAME_HEIGHT / 2 // Sadece alt yarıda sürüklemeye izin ver
) {
dragNode = car;
lastGameX = x;
}
};
game.move = function (x, y, obj) {
if (dragNode === car) {
// Eğer direksiyon simidi aktifse, onun move fonksiyonunu çağır
if (steering && steering.isDown && steering.move) {
steering.move(x, y, obj);
}
// Sürükleme ile araba hareketi devre dışı (direksiyon ile kontrol edilecek)
// car.x değişimi steering.onSteer ile yapılacak
}
};
game.up = function (x, y, obj) {
dragNode = null;
gazPressed = false;
frenPressed = false;
brakePressed = false;
if (steering && steering.isDown && steering.up) {
steering.up(0, 0, null);
}
};
// Oyun başında skor ve para sıfırla
score = 0;
scoreTxt.setText(score);
money = 0;
moneyTxt.setText('₺' + money);
currentGear = 'D';
gearBtn.setGear('D');
gazPressed = false;
frenPressed = false;