/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Obstacle class var Obstacle = Container.expand(function () { var self = Container.call(this); var obs = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 22; // px per frame, will be adjusted by game speed self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222a38 }); /**** * Game Code ****/ // Game constants LK.playMusic('musicId'); // Not: Araba görseli yok, sadece kokpitten (dashboard ve direksiyon) görünüm var. // Direksiyon (steering wheel) - ellipse, dark gray // Direksiyon merkezi (center) - small ellipse, lighter gray // Yol (road) - tall box, dark // Şerit çizgisi (lane line) - thin box, white // Araç kaputu (dashboard/hood) - wide box, blue // Engel (obstacle) - red box // yandaki yerler için ayrı asset var ROAD_WIDTH = 1200; var ROAD_X = (2048 - ROAD_WIDTH) / 2; var ROAD_Y = 0; var ROAD_HEIGHT = 2732; var STEERING_RADIUS = 200; var STEERING_X = 2048 / 2; var STEERING_Y = 2732 - 350; var DASHBOARD_Y = 2732 - 180; // Move dashboard further back (higher up on the screen) var CAR_WIDTH = 140; var CAR_HEIGHT = 240; var LANE_LINE_COUNT = 7; var LANE_LINE_SPACING = 350; var OBSTACLE_MIN_X = ROAD_X + 80; var OBSTACLE_MAX_X = ROAD_X + ROAD_WIDTH - 80; var OBSTACLE_SPAWN_INTERVAL = 90; // frames var OBSTACLE_SPEED = 22; var ROAD_SPEED = 22; // Side areas (left and right of the road) var sideAreaLeft = LK.getAsset('sideArea', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(sideAreaLeft); var sideAreaRight = LK.getAsset('sideArea', { anchorX: 0, anchorY: 0, x: ROAD_X + ROAD_WIDTH, y: 0 }); game.addChild(sideAreaRight); // Road var road = LK.getAsset('road', { anchorX: 0, anchorY: 0, x: ROAD_X, y: ROAD_Y }); game.addChild(road); // Lane lines var laneLines = []; for (var i = 0; i < LANE_LINE_COUNT; i++) { var line = LK.getAsset('laneLine', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: i * LANE_LINE_SPACING + 200 }); game.addChild(line); laneLines.push(line); } // Dashboard (hood) var dashboard = LK.getAsset('dashboard', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: DASHBOARD_Y }); game.addChild(dashboard); // Steering wheel var steeringWheel = LK.getAsset('steeringWheel', { anchorX: 0.5, anchorY: 0.5, x: STEERING_X, y: STEERING_Y }); game.addChild(steeringWheel); // Steering center var steeringCenter = LK.getAsset('steeringCenter', { anchorX: 0.5, anchorY: 0.5, x: STEERING_X, y: STEERING_Y }); game.addChild(steeringCenter); // Play horn sound when steeringCenter is pressed steeringCenter.down = function (x, y, obj) { LK.getSound('horn').play(); }; // Car position (virtual, not visible, but used for collision) // In cockpit view, the car is not drawn, only dashboard and steering wheel are visible. // The car's position is still tracked for collision, but not rendered. var car = { x: 2048 / 2, y: DASHBOARD_Y - CAR_HEIGHT / 2, width: CAR_WIDTH, height: CAR_HEIGHT }; // Obstacles var obstacles = []; // Steering state var steeringDragging = false; var steeringStartAngle = 0; var steeringCurrentAngle = 0; var steeringMaxAngle = Math.PI / 2; // 90 degrees left/right var steeringValue = 0; // -1 (left) to 1 (right) var lastSteeringPointerAngle = 0; // Score var distance = 0; var scoreTxt = new Text2('0 m', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Helper: get angle between center and pointer function getPointerAngle(x, y) { var dx = x - steeringWheel.x; var dy = y - steeringWheel.y; return Math.atan2(dy, dx); } // Helper: clamp function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); } // Steering wheel drag logic steeringWheel.down = function (x, y, obj) { // Only start drag if inside steering wheel var dx = x - steeringWheel.x; var dy = y - steeringWheel.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist <= STEERING_RADIUS) { steeringDragging = true; steeringStartAngle = getPointerAngle(x, y) - steeringCurrentAngle; lastSteeringPointerAngle = getPointerAngle(x, y); } }; steeringWheel.up = function (x, y, obj) { steeringDragging = false; // Tween steering back to center tween(steeringWheel, { rotation: 0 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { steeringCurrentAngle = 0; steeringValue = 0; } }); }; // Global move handler for steering function handleMove(x, y, obj) { if (steeringDragging) { var pointerAngle = getPointerAngle(x, y); var angle = pointerAngle - steeringStartAngle; // Clamp angle angle = clamp(angle, -steeringMaxAngle, steeringMaxAngle); steeringCurrentAngle = angle; steeringWheel.rotation = angle; steeringValue = angle / steeringMaxAngle; } } game.move = handleMove; // Also allow steering wheel to be dragged from anywhere on the wheel game.down = function (x, y, obj) { // Only start drag if inside steering wheel var dx = x - steeringWheel.x; var dy = y - steeringWheel.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist <= STEERING_RADIUS) { steeringDragging = true; steeringStartAngle = getPointerAngle(x, y) - steeringCurrentAngle; lastSteeringPointerAngle = getPointerAngle(x, y); } }; game.up = function (x, y, obj) { steeringDragging = false; // Tween steering back to center tween(steeringWheel, { rotation: 0 }, { duration: 400, easing: tween.easeOut, onFinish: function onFinish() { steeringCurrentAngle = 0; steeringValue = 0; } }); }; // Main game update var ticks = 0; game.update = function () { ticks++; // Move lane lines to simulate road movement from cockpit for (var i = 0; i < laneLines.length; i++) { laneLines[i].y += ROAD_SPEED; // Lane lines should disappear under the dashboard (cockpit) if (laneLines[i].y > DASHBOARD_Y + 100) { laneLines[i].y -= LANE_LINE_COUNT * LANE_LINE_SPACING; } } // Move obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.y += OBSTACLE_SPEED; // In cockpit view, obstacles disappear under the dashboard if (obs.y > DASHBOARD_Y + 100) { obs.destroy(); obstacles.splice(i, 1); continue; } // Dashboard collision check (AABB) var obsLeft = obs.x - 60; var obsRight = obs.x + 60; var obsTop = obs.y - 60; var obsBottom = obs.y + 60; var dashLeft = dashboard.x - dashboard.width / 2; var dashRight = dashboard.x + dashboard.width / 2; var dashTop = dashboard.y; var dashBottom = dashboard.y + dashboard.height; // Track last dashboard collision state for each obstacle if (typeof obs.lastWasDashColliding === "undefined") { obs.lastWasDashColliding = false; } var isDashColliding = !(dashRight < obsLeft || dashLeft > obsRight || dashBottom < obsTop || dashTop > obsBottom); // Only trigger game over on the exact frame dashboard collision starts if (!obs.lastWasDashColliding && isDashColliding) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } obs.lastWasDashColliding = isDashColliding; // (Retain car collision code for future extensibility, but now only dashboard triggers game over) } // Car movement: steeringValue -1..1, move car.x accordingly, clamp to road var steerSpeed = 22; // px per frame at full turn car.x += steeringValue * steerSpeed; // Clamp car to road var minCarX = ROAD_X + CAR_WIDTH / 2 + 20; var maxCarX = ROAD_X + ROAD_WIDTH - CAR_WIDTH / 2 - 20; car.x = clamp(car.x, minCarX, maxCarX); // Dashboard/hood follows car.x dashboard.x = car.x; // Spawn obstacles if (ticks % OBSTACLE_SPAWN_INTERVAL === 0) { var obs = new Obstacle(); // Random x within road var obsX = Math.floor(Math.random() * (OBSTACLE_MAX_X - OBSTACLE_MIN_X)) + OBSTACLE_MIN_X; obs.x = obsX; obs.y = -80; obstacles.push(obs); game.addChild(obs); } // Update distance/score distance += ROAD_SPEED; var meters = Math.floor(distance / 10); scoreTxt.setText(meters + " m"); LK.setScore(meters); }; /* End of file */
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obs = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 22; // px per frame, will be adjusted by game speed
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222a38
});
/****
* Game Code
****/
// Game constants
LK.playMusic('musicId');
// Not: Araba görseli yok, sadece kokpitten (dashboard ve direksiyon) görünüm var.
// Direksiyon (steering wheel) - ellipse, dark gray
// Direksiyon merkezi (center) - small ellipse, lighter gray
// Yol (road) - tall box, dark
// Şerit çizgisi (lane line) - thin box, white
// Araç kaputu (dashboard/hood) - wide box, blue
// Engel (obstacle) - red box
// yandaki yerler için ayrı asset
var ROAD_WIDTH = 1200;
var ROAD_X = (2048 - ROAD_WIDTH) / 2;
var ROAD_Y = 0;
var ROAD_HEIGHT = 2732;
var STEERING_RADIUS = 200;
var STEERING_X = 2048 / 2;
var STEERING_Y = 2732 - 350;
var DASHBOARD_Y = 2732 - 180; // Move dashboard further back (higher up on the screen)
var CAR_WIDTH = 140;
var CAR_HEIGHT = 240;
var LANE_LINE_COUNT = 7;
var LANE_LINE_SPACING = 350;
var OBSTACLE_MIN_X = ROAD_X + 80;
var OBSTACLE_MAX_X = ROAD_X + ROAD_WIDTH - 80;
var OBSTACLE_SPAWN_INTERVAL = 90; // frames
var OBSTACLE_SPEED = 22;
var ROAD_SPEED = 22;
// Side areas (left and right of the road)
var sideAreaLeft = LK.getAsset('sideArea', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(sideAreaLeft);
var sideAreaRight = LK.getAsset('sideArea', {
anchorX: 0,
anchorY: 0,
x: ROAD_X + ROAD_WIDTH,
y: 0
});
game.addChild(sideAreaRight);
// Road
var road = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
x: ROAD_X,
y: ROAD_Y
});
game.addChild(road);
// Lane lines
var laneLines = [];
for (var i = 0; i < LANE_LINE_COUNT; i++) {
var line = LK.getAsset('laneLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: i * LANE_LINE_SPACING + 200
});
game.addChild(line);
laneLines.push(line);
}
// Dashboard (hood)
var dashboard = LK.getAsset('dashboard', {
anchorX: 0.5,
anchorY: 0,
x: 2048 / 2,
y: DASHBOARD_Y
});
game.addChild(dashboard);
// Steering wheel
var steeringWheel = LK.getAsset('steeringWheel', {
anchorX: 0.5,
anchorY: 0.5,
x: STEERING_X,
y: STEERING_Y
});
game.addChild(steeringWheel);
// Steering center
var steeringCenter = LK.getAsset('steeringCenter', {
anchorX: 0.5,
anchorY: 0.5,
x: STEERING_X,
y: STEERING_Y
});
game.addChild(steeringCenter);
// Play horn sound when steeringCenter is pressed
steeringCenter.down = function (x, y, obj) {
LK.getSound('horn').play();
};
// Car position (virtual, not visible, but used for collision)
// In cockpit view, the car is not drawn, only dashboard and steering wheel are visible.
// The car's position is still tracked for collision, but not rendered.
var car = {
x: 2048 / 2,
y: DASHBOARD_Y - CAR_HEIGHT / 2,
width: CAR_WIDTH,
height: CAR_HEIGHT
};
// Obstacles
var obstacles = [];
// Steering state
var steeringDragging = false;
var steeringStartAngle = 0;
var steeringCurrentAngle = 0;
var steeringMaxAngle = Math.PI / 2; // 90 degrees left/right
var steeringValue = 0; // -1 (left) to 1 (right)
var lastSteeringPointerAngle = 0;
// Score
var distance = 0;
var scoreTxt = new Text2('0 m', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: get angle between center and pointer
function getPointerAngle(x, y) {
var dx = x - steeringWheel.x;
var dy = y - steeringWheel.y;
return Math.atan2(dy, dx);
}
// Helper: clamp
function clamp(val, min, max) {
return Math.max(min, Math.min(max, val));
}
// Steering wheel drag logic
steeringWheel.down = function (x, y, obj) {
// Only start drag if inside steering wheel
var dx = x - steeringWheel.x;
var dy = y - steeringWheel.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist <= STEERING_RADIUS) {
steeringDragging = true;
steeringStartAngle = getPointerAngle(x, y) - steeringCurrentAngle;
lastSteeringPointerAngle = getPointerAngle(x, y);
}
};
steeringWheel.up = function (x, y, obj) {
steeringDragging = false;
// Tween steering back to center
tween(steeringWheel, {
rotation: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
steeringCurrentAngle = 0;
steeringValue = 0;
}
});
};
// Global move handler for steering
function handleMove(x, y, obj) {
if (steeringDragging) {
var pointerAngle = getPointerAngle(x, y);
var angle = pointerAngle - steeringStartAngle;
// Clamp angle
angle = clamp(angle, -steeringMaxAngle, steeringMaxAngle);
steeringCurrentAngle = angle;
steeringWheel.rotation = angle;
steeringValue = angle / steeringMaxAngle;
}
}
game.move = handleMove;
// Also allow steering wheel to be dragged from anywhere on the wheel
game.down = function (x, y, obj) {
// Only start drag if inside steering wheel
var dx = x - steeringWheel.x;
var dy = y - steeringWheel.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist <= STEERING_RADIUS) {
steeringDragging = true;
steeringStartAngle = getPointerAngle(x, y) - steeringCurrentAngle;
lastSteeringPointerAngle = getPointerAngle(x, y);
}
};
game.up = function (x, y, obj) {
steeringDragging = false;
// Tween steering back to center
tween(steeringWheel, {
rotation: 0
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
steeringCurrentAngle = 0;
steeringValue = 0;
}
});
};
// Main game update
var ticks = 0;
game.update = function () {
ticks++;
// Move lane lines to simulate road movement from cockpit
for (var i = 0; i < laneLines.length; i++) {
laneLines[i].y += ROAD_SPEED;
// Lane lines should disappear under the dashboard (cockpit)
if (laneLines[i].y > DASHBOARD_Y + 100) {
laneLines[i].y -= LANE_LINE_COUNT * LANE_LINE_SPACING;
}
}
// Move obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.y += OBSTACLE_SPEED;
// In cockpit view, obstacles disappear under the dashboard
if (obs.y > DASHBOARD_Y + 100) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Dashboard collision check (AABB)
var obsLeft = obs.x - 60;
var obsRight = obs.x + 60;
var obsTop = obs.y - 60;
var obsBottom = obs.y + 60;
var dashLeft = dashboard.x - dashboard.width / 2;
var dashRight = dashboard.x + dashboard.width / 2;
var dashTop = dashboard.y;
var dashBottom = dashboard.y + dashboard.height;
// Track last dashboard collision state for each obstacle
if (typeof obs.lastWasDashColliding === "undefined") {
obs.lastWasDashColliding = false;
}
var isDashColliding = !(dashRight < obsLeft || dashLeft > obsRight || dashBottom < obsTop || dashTop > obsBottom);
// Only trigger game over on the exact frame dashboard collision starts
if (!obs.lastWasDashColliding && isDashColliding) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
obs.lastWasDashColliding = isDashColliding;
// (Retain car collision code for future extensibility, but now only dashboard triggers game over)
}
// Car movement: steeringValue -1..1, move car.x accordingly, clamp to road
var steerSpeed = 22; // px per frame at full turn
car.x += steeringValue * steerSpeed;
// Clamp car to road
var minCarX = ROAD_X + CAR_WIDTH / 2 + 20;
var maxCarX = ROAD_X + ROAD_WIDTH - CAR_WIDTH / 2 - 20;
car.x = clamp(car.x, minCarX, maxCarX);
// Dashboard/hood follows car.x
dashboard.x = car.x;
// Spawn obstacles
if (ticks % OBSTACLE_SPAWN_INTERVAL === 0) {
var obs = new Obstacle();
// Random x within road
var obsX = Math.floor(Math.random() * (OBSTACLE_MAX_X - OBSTACLE_MIN_X)) + OBSTACLE_MIN_X;
obs.x = obsX;
obs.y = -80;
obstacles.push(obs);
game.addChild(obs);
}
// Update distance/score
distance += ROAD_SPEED;
var meters = Math.floor(distance / 10);
scoreTxt.setText(meters + " m");
LK.setScore(meters);
};
/* End of file */