User prompt
Let the obstacles go in the same direction as my bike
User prompt
Increase the speed of obstacles
User prompt
No vehicles should be driving backwards
User prompt
Apply the obstacle skin to the obstacle vehicles
User prompt
Remove changing colors
User prompt
Make speed bar horizontal
User prompt
Adapt speed bar to speed skin
User prompt
Make the skin of gear- and gear+ into gear skin
User prompt
Set brakeide throttle skin
User prompt
Remove gas from car skin and add it to gas skin
User prompt
Block vehicles
User prompt
Gaz brake Gear+ Gear - Make Speed skins square
User prompt
Vites Gaz Yavaşlama hız imlecini kare yap
User prompt
Add individual skins to buttons
User prompt
Restore buttons
User prompt
Add moving vehicles instead of obstacles
User prompt
Let the vehicle stay in the middle for a while longer, then slow down after shifting gears and step on the gas to increase speed.
User prompt
Add skins store
User prompt
Make Speed Cursor
User prompt
Add drift system
User prompt
Increase traffic and add gear
User prompt
Add gas and brake
User prompt
Speed up the game by 1% per 2000 scores
User prompt
Slow down score growth by 75%
User prompt
Remove tokens and instead make a score system based on distance
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
bestScore: 0
});
/****
* Classes
****/
// Player Car
var Car = Container.expand(function () {
var self = Container.call(this);
// Use selected skin color
var skin = typeof getCurrentSkin === "function" ? getCurrentSkin() : {
id: 'car',
color: 0x2196f3
};
var carAsset = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
// width/height default
});
carAsset.tint = skin.color;
// For collision box, use the car asset's size
self.width = carAsset.width;
self.height = carAsset.height;
return self;
});
// Obstacle (legacy, not used anymore)
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;
// For collision
return self;
});
// Road Stripe
var Stripe = Container.expand(function () {
var self = Container.call(this);
var stripeAsset = self.attachAsset('stripe', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = stripeAsset.width;
self.height = stripeAsset.height;
return self;
});
// Coin class removed (no longer needed)
// Vehicle (moving obstacle)
var Vehicle = Container.expand(function () {
var self = Container.call(this);
// Use car asset for vehicles, random color for variety
var vehicleColors = [0xd32f2f, 0x2196f3, 0xfbc02d, 0x43a047, 0x8e24aa, 0x00897b];
var color = vehicleColors[Math.floor(Math.random() * vehicleColors.length)];
var vehicleAsset = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
color: color
});
vehicleAsset.tint = color;
self.width = vehicleAsset.width;
self.height = vehicleAsset.height;
// Vehicle speed (relative to road speed, can be positive or negative for overtaking/slow cars)
self.relativeSpeed = (Math.random() < 0.5 ? 1 : -1) * (6 + Math.random() * 8); // -14 to +14
// Track lastY for event triggers
self.lastY = self.y;
// Track if already collided
self.lastWasIntersecting = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// LK.init.shape('coin', {width:100, height:100, color:0xffeb3b, shape:'ellipse'})
// Game area
// Car (player)
// Obstacle
// Coin
// Road stripes
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var ROAD_WIDTH = 1200;
var ROAD_X = (GAME_WIDTH - ROAD_WIDTH) / 2;
var ROAD_Y = 0;
var ROAD_HEIGHT = GAME_HEIGHT;
// --- Skins Store System ---
// Skins data
var carSkins = [{
id: 'car',
name: 'Blue',
color: 0x2196f3,
unlocked: true,
price: 0
}, {
id: 'car_red',
name: 'Red',
color: 0xd32f2f,
unlocked: false,
price: 5000
}, {
id: 'car_green',
name: 'Green',
color: 0x43a047,
unlocked: false,
price: 10000
}, {
id: 'car_gold',
name: 'Gold',
color: 0xfbc02d,
unlocked: false,
price: 20000
}];
// Load unlocked skins from storage
if (typeof storage.unlockedSkins === "undefined") {
storage.unlockedSkins = {
car: true
};
}
for (var i = 0; i < carSkins.length; i++) {
if (storage.unlockedSkins[carSkins[i].id]) carSkins[i].unlocked = true;
}
// Selected skin
var selectedSkinIdx = 0;
if (typeof storage.selectedSkinIdx !== "undefined") {
selectedSkinIdx = storage.selectedSkinIdx;
}
// Helper to get current skin
function getCurrentSkin() {
return carSkins[selectedSkinIdx];
}
// --- Skins Store UI ---
var storeOpen = false;
var storePanel = new Container();
storePanel.visible = false;
storePanel.x = GAME_WIDTH / 2;
storePanel.y = GAME_HEIGHT / 2;
game.addChild(storePanel);
// Store background
var storeBg = storePanel.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
width: 900,
height: 1200,
color: 0x222222
});
storeBg.alpha = 0.98;
// Store title
var storeTitle = new Text2('SKINS STORE', {
size: 90,
fill: "#fff"
});
storeTitle.anchor.set(0.5, 0);
storeTitle.y = -520;
storePanel.addChild(storeTitle);
// Skin preview
var skinPreview = new Container();
skinPreview.x = 0;
skinPreview.y = -120;
storePanel.addChild(skinPreview);
var skinPreviewAsset = null;
function updateSkinPreview() {
if (skinPreviewAsset) {
skinPreviewAsset.destroy();
skinPreviewAsset = null;
}
var skin = carSkins[selectedSkinIdx];
skinPreviewAsset = skinPreview.attachAsset(skin.id === 'car' ? 'car' : 'car', {
anchorX: 0.5,
anchorY: 0.5,
width: 320,
height: 520,
color: skin.color
});
}
updateSkinPreview();
// Skin name
var skinNameTxt = new Text2('', {
size: 70,
fill: "#fff"
});
skinNameTxt.anchor.set(0.5, 0.5);
skinNameTxt.y = 220;
storePanel.addChild(skinNameTxt);
// Unlock/buy/select button
var skinActionBtn = new Container();
skinActionBtn.x = 0;
skinActionBtn.y = 400;
storePanel.addChild(skinActionBtn);
var skinActionAsset = skinActionBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 120,
color: 0x43a047
});
skinActionAsset.alpha = 0.9;
var skinActionTxt = new Text2('', {
size: 60,
fill: "#fff"
});
skinActionTxt.anchor.set(0.5, 0.5);
skinActionBtn.addChild(skinActionTxt);
// Left/right arrows
var leftArrowBtn = new Container();
var leftArrowAsset = leftArrowBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: 120,
height: 120,
color: 0x90caf9
});
leftArrowBtn.x = -320;
leftArrowBtn.y = 0;
storePanel.addChild(leftArrowBtn);
var leftArrowTxt = new Text2('<', {
size: 90,
fill: "#fff"
});
leftArrowTxt.anchor.set(0.5, 0.5);
leftArrowBtn.addChild(leftArrowTxt);
var rightArrowBtn = new Container();
var rightArrowAsset = rightArrowBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: 120,
height: 120,
color: 0x90caf9
});
rightArrowBtn.x = 320;
rightArrowBtn.y = 0;
storePanel.addChild(rightArrowBtn);
var rightArrowTxt = new Text2('>', {
size: 90,
fill: "#fff"
});
rightArrowTxt.anchor.set(0.5, 0.5);
rightArrowBtn.addChild(rightArrowTxt);
// Close button
var closeBtn = new Container();
var closeAsset = closeBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: 120,
height: 120,
color: 0xd32f2f
});
closeBtn.x = 0;
closeBtn.y = 540;
storePanel.addChild(closeBtn);
var closeTxt = new Text2('CLOSE', {
size: 48,
fill: "#fff"
});
closeTxt.anchor.set(0.5, 0.5);
closeBtn.addChild(closeTxt);
// Coins display
var coinsTxt = new Text2('', {
size: 60,
fill: "#fff"
});
coinsTxt.anchor.set(0.5, 0.5);
coinsTxt.y = -400;
storePanel.addChild(coinsTxt);
// Helper to update store UI
function updateStoreUI() {
var skin = carSkins[selectedSkinIdx];
skinNameTxt.setText(skin.name);
updateSkinPreview();
// Show coins
coinsTxt.setText('Coins: ' + (score || 0));
if (skin.unlocked) {
if (selectedSkinIdx === storage.selectedSkinIdx) {
skinActionTxt.setText('SELECTED');
skinActionAsset.tint = 0x90caf9;
} else {
skinActionTxt.setText('SELECT');
skinActionAsset.tint = 0x43a047;
}
} else {
skinActionTxt.setText('BUY (' + skin.price + ')');
skinActionAsset.tint = 0xfbc02d;
}
}
updateStoreUI();
// Store open button (top right)
var storeBtn = new Container();
var storeBtnAsset = storeBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: 120,
height: 120,
color: 0x90caf9
});
storeBtn.x = GAME_WIDTH - 160;
storeBtn.y = 160;
game.addChild(storeBtn);
var storeBtnTxt = new Text2('SKINS', {
size: 40,
fill: "#fff"
});
storeBtnTxt.anchor.set(0.5, 0.5);
storeBtn.addChild(storeBtnTxt);
// --- End Skins Store System ---
// Player car
var car = new Car();
car.x = GAME_WIDTH / 2;
car.y = GAME_HEIGHT - 500;
game.addChild(car);
// Road stripes
var stripes = [];
var stripeSpacing = 400;
for (var i = 0; i < 8; i++) {
var stripe = new Stripe();
stripe.x = GAME_WIDTH / 2;
stripe.y = i * stripeSpacing + 200;
stripes.push(stripe);
game.addChild(stripe);
}
// Vehicles and coins
var vehicles = [];
var coins = [];
// Score
var score = 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Best score
var bestScore = storage.bestScore || 0;
var bestScoreTxt = new Text2('Best: ' + bestScore, {
size: 60,
fill: "#fff"
});
bestScoreTxt.anchor.set(0.5, 0);
bestScoreTxt.y = 120;
LK.gui.top.addChild(bestScoreTxt);
// Game speed
var baseSpeed = 18;
var speed = baseSpeed;
var speedIncreaseEvery = 600; // ticks
var maxSpeed = 48;
// Gear system
var gear = 1;
var maxGear = 5;
var minGear = 1;
var gearSpeeds = [0, 18, 26, 34, 42, 48]; // index 0 unused, gear 1-5
// Dragging
var dragCar = false;
var dragOffsetX = 0;
// Drift system state
var isDrifting = false;
var driftDirection = 0; // -1 for left, 1 for right, 0 for none
var driftTimer = 0;
var driftMaxTime = 60; // frames (1 second)
var driftCooldown = 0;
var driftCooldownTime = 40; // frames
var driftAngle = 0; // in radians, for visual tilt
var driftAngleMax = Math.PI / 7; // max tilt angle
var driftSpeedBonus = 1.18; // 18% speed boost during drift
// Gas and brake button state
var gasPressed = false;
var brakePressed = false;
// Touch controls
function clamp(val, min, max) {
return val < min ? min : val > max ? max : val;
}
function handleMove(x, y, obj) {
if (storeOpen) return;
if (dragCar) {
// Clamp car within road
var minX = ROAD_X + car.width / 2 + 20;
var maxX = ROAD_X + ROAD_WIDTH - car.width / 2 - 20;
var prevX = car.x;
car.x = clamp(x - dragOffsetX, minX, maxX);
// Drift trigger: if swipe is fast and not already drifting or on cooldown
var dx = car.x - prevX;
if (!isDrifting && driftCooldown === 0 && Math.abs(dx) > 32) {
isDrifting = true;
driftDirection = dx > 0 ? 1 : -1;
driftTimer = 0;
}
}
}
game.move = handleMove;
// --- Gas and Brake Buttons ---
var buttonSize = 260;
var buttonMargin = 80;
// Assign unique skin colors to each button based on carSkins
var gasBtn = new Container();
var gasBtnSkin = carSkins[1] || carSkins[0]; // Red or fallback to blue
var gasAsset = gasBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: buttonSize,
height: buttonSize,
color: gasBtnSkin.color
});
gasAsset.tint = gasBtnSkin.color;
gasBtn.x = GAME_WIDTH - buttonSize / 2 - buttonMargin;
gasBtn.y = GAME_HEIGHT - buttonSize / 2 - buttonMargin;
game.addChild(gasBtn);
var gasTxt = new Text2('GAS', {
size: 70,
fill: "#fff"
});
gasTxt.anchor.set(0.5, 0.5);
gasBtn.addChild(gasTxt);
// Brake button (bottom left)
var brakeBtn = new Container();
var brakeBtnSkin = carSkins[3] || carSkins[0]; // Gold or fallback to blue
var brakeAsset = brakeBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: buttonSize,
height: buttonSize,
color: brakeBtnSkin.color
});
brakeAsset.tint = brakeBtnSkin.color;
brakeBtn.x = buttonSize / 2 + buttonMargin;
brakeBtn.y = GAME_HEIGHT - buttonSize / 2 - buttonMargin;
game.addChild(brakeBtn);
var brakeTxt = new Text2('BRAKE', {
size: 70,
fill: "#fff"
});
brakeTxt.anchor.set(0.5, 0.5);
brakeBtn.addChild(brakeTxt);
// Gear Up button (bottom center right)
var gearUpBtn = new Container();
var gearUpBtnSkin = carSkins[2] || carSkins[0]; // Green or fallback to blue
var gearUpAsset = gearUpBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: buttonSize,
height: buttonSize,
color: gearUpBtnSkin.color
});
gearUpAsset.tint = gearUpBtnSkin.color;
gearUpBtn.x = GAME_WIDTH / 2 + buttonSize + buttonMargin;
gearUpBtn.y = GAME_HEIGHT - buttonSize / 2 - buttonMargin;
game.addChild(gearUpBtn);
var gearUpTxt = new Text2('GEAR+', {
size: 60,
fill: "#fff"
});
gearUpTxt.anchor.set(0.5, 0.5);
gearUpBtn.addChild(gearUpTxt);
// Gear Down button (bottom center left)
var gearDownBtn = new Container();
var gearDownBtnSkin = carSkins[0]; // Blue
var gearDownAsset = gearDownBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
width: buttonSize,
height: buttonSize,
color: gearDownBtnSkin.color
});
gearDownAsset.tint = gearDownBtnSkin.color;
gearDownBtn.x = GAME_WIDTH / 2 - buttonSize - buttonMargin;
gearDownBtn.y = GAME_HEIGHT - buttonSize / 2 - buttonMargin;
game.addChild(gearDownBtn);
var gearDownTxt = new Text2('GEAR-', {
size: 60,
fill: "#fff"
});
gearDownTxt.anchor.set(0.5, 0.5);
gearDownBtn.addChild(gearDownTxt);
// Gear display (center bottom)
var gearTxt = new Text2('GEAR: 1', {
size: 80,
fill: "#fff"
});
gearTxt.anchor.set(0.5, 0.5);
gearTxt.x = GAME_WIDTH / 2;
gearTxt.y = GAME_HEIGHT - buttonSize - buttonMargin - 60;
game.addChild(gearTxt);
// --- Speed Cursor UI ---
// Speed cursor background bar
var speedCursorBg = new Container();
var speedCursorBgAsset = speedCursorBg.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0,
width: 80,
height: 600,
color: 0x333333
});
speedCursorBgAsset.alpha = 0.5;
speedCursorBg.x = GAME_WIDTH - 120;
speedCursorBg.y = 320;
game.addChild(speedCursorBg);
// Speed cursor fill (shows current speed) - now a square
var speedCursorFill = new Container();
var speedCursorFillAsset = speedCursorFill.attachAsset('car', {
anchorX: 0.5,
anchorY: 1,
width: 120,
height: 120,
color: 0x43a047
});
speedCursorFill.x = speedCursorBg.x;
speedCursorFill.y = speedCursorBg.y + speedCursorBgAsset.height - 10;
game.addChild(speedCursorFill);
// Speed cursor text
var speedCursorTxt = new Text2('SPEED', {
size: 48,
fill: "#fff"
});
speedCursorTxt.anchor.set(0.5, 1);
speedCursorTxt.x = speedCursorBg.x;
speedCursorTxt.y = speedCursorBg.y - 12;
game.addChild(speedCursorTxt);
// Helper to check if a point is inside a button
function isInsideBtn(btn, x, y) {
var bx = btn.x,
by = btn.y;
var hw = buttonSize / 2,
hh = buttonSize / 2;
return x >= bx - hw && x <= bx + hw && y >= by - hh && y <= by + hh;
}
// Down event
game.down = function (x, y, obj) {
// --- Skins Store UI events ---
if (storeOpen) {
// Convert to storePanel local
var local = {
x: x - storePanel.x,
y: y - storePanel.y
};
// Close
if (local.y > closeBtn.y - 60 && local.y < closeBtn.y + 60 && local.x > closeBtn.x - 60 && local.x < closeBtn.x + 60) {
storePanel.visible = false;
storeOpen = false;
return;
}
// Left arrow
if (local.y > leftArrowBtn.y - 60 && local.y < leftArrowBtn.y + 60 && local.x > leftArrowBtn.x - 60 && local.x < leftArrowBtn.x + 60) {
selectedSkinIdx = (selectedSkinIdx - 1 + carSkins.length) % carSkins.length;
updateStoreUI();
return;
}
// Right arrow
if (local.y > rightArrowBtn.y - 60 && local.y < rightArrowBtn.y + 60 && local.x > rightArrowBtn.x - 60 && local.x < rightArrowBtn.x + 60) {
selectedSkinIdx = (selectedSkinIdx + 1) % carSkins.length;
updateStoreUI();
return;
}
// Action button
if (local.y > skinActionBtn.y - 60 && local.y < skinActionBtn.y + 60 && local.x > skinActionBtn.x - 200 && local.x < skinActionBtn.x + 200) {
var skin = carSkins[selectedSkinIdx];
if (skin.unlocked) {
storage.selectedSkinIdx = selectedSkinIdx;
updateStoreUI();
// Recreate car with new skin
car.destroy();
car = new Car();
car.x = GAME_WIDTH / 2;
car.y = GAME_HEIGHT - 500;
game.addChild(car);
} else if ((score || 0) >= skin.price) {
// Unlock skin
skin.unlocked = true;
storage.unlockedSkins[skin.id] = true;
// Deduct coins (score)
score -= skin.price;
scoreTxt.setText(score);
updateStoreUI();
}
return;
}
return;
}
// Open store button
if (x > storeBtn.x - 60 && x < storeBtn.x + 60 && y > storeBtn.y - 60 && y < storeBtn.y + 60) {
storePanel.visible = true;
storeOpen = true;
updateStoreUI();
return;
}
// Only start drag if touch is on car
var local = car.toLocal(game.toGlobal({
x: x,
y: y
}));
if (local.x >= -car.width / 2 && local.x <= car.width / 2 && local.y >= -car.height / 2 && local.y <= car.height / 2) {
dragCar = true;
dragOffsetX = x - car.x;
}
// Gas/brake buttons
if (isInsideBtn(gasBtn, x, y)) {
gasPressed = true;
gasAsset.alpha = 0.7;
}
if (isInsideBtn(brakeBtn, x, y)) {
brakePressed = true;
brakeAsset.alpha = 0.7;
}
// Gear up button
if (isInsideBtn(gearUpBtn, x, y)) {
if (gear < maxGear) {
gear++;
gearTxt.setText('GEAR: ' + gear);
// Snap speed to new gear's minimum if below
if (speed < gearSpeeds[gear]) speed = gearSpeeds[gear];
}
gearUpAsset.alpha = 0.7;
}
// Gear down button
if (isInsideBtn(gearDownBtn, x, y)) {
if (gear > minGear) {
gear--;
gearTxt.setText('GEAR: ' + gear);
// Snap speed to new gear's max if above
if (speed > gearSpeeds[gear]) speed = gearSpeeds[gear];
}
gearDownAsset.alpha = 0.7;
}
};
// Up event
game.up = function (x, y, obj) {
if (storeOpen) return;
dragCar = false;
gasPressed = false;
brakePressed = false;
gasAsset.alpha = 1;
brakeAsset.alpha = 1;
gearUpAsset.alpha = 1;
gearDownAsset.alpha = 1;
};
// Spawning
var obstacleTimer = 0;
var coinTimer = 0;
function spawnVehicle() {
var lanes = 4;
var laneWidth = ROAD_WIDTH / lanes;
var lane = Math.floor(Math.random() * lanes);
var vehicle = new Vehicle();
vehicle.x = ROAD_X + laneWidth * (lane + 0.5);
vehicle.y = -vehicle.height;
vehicle.lane = lane;
vehicles.push(vehicle);
game.addChild(vehicle);
}
// function spawnCoin removed (no longer needed)
// Main update loop
game.update = function () {
// --- Car stay in middle at start, slow after gear shift, require gas to accelerate ---
// State: 0 = normal, 1 = holding in middle, 2 = slowing after gear shift, 3 = waiting for gas
if (typeof carStartState === "undefined") {
carStartState = 1; // 1 = holding in middle
carStartTicks = 0;
carSlowed = false;
carWaitGas = false;
}
if (carStartState === 1) {
// Hold car in middle for 1.2 seconds (72 ticks)
car.x = GAME_WIDTH / 2;
carStartTicks++;
if (carStartTicks > 72) {
carStartState = 2;
carStartTicks = 0;
}
} else if (carStartState === 2) {
// Wait for gear shift, then slow down
if (gear > 1 && !carSlowed) {
speed = Math.max(gearSpeeds[gear] * 0.55, gearSpeeds[1]);
carSlowed = true;
carStartTicks = 0;
carStartState = 3;
}
} else if (carStartState === 3) {
// Wait for gas press to allow acceleration
if (gasPressed) {
carStartState = 0;
} else {
// Gradually slow down if not pressing gas
speed = Math.max(speed - 0.7, gearSpeeds[1]);
}
}
// Drift update logic
if (isDrifting) {
driftTimer++;
// Smoothly tilt car in drift direction
driftAngle += (driftDirection * driftAngleMax - driftAngle) * 0.25;
// Give speed bonus during drift
speed = Math.min(speed * driftSpeedBonus, gearSpeeds[gear]);
// End drift after max time or if drag stops
if (driftTimer > driftMaxTime || !dragCar) {
isDrifting = false;
driftCooldown = driftCooldownTime;
}
} else {
// Return car to upright
driftAngle += (0 - driftAngle) * 0.18;
if (driftCooldown > 0) driftCooldown--;
}
// Gas/brake logic
if (carStartState === 0) {
if (gasPressed) {
speed = Math.min(speed + 0.5, gearSpeeds[gear]);
} else if (brakePressed) {
speed = Math.max(speed - 1.2, gearSpeeds[gear - 1] ? gearSpeeds[gear - 1] : baseSpeed * 0.5);
} else {
// Speed up over time
if (LK.ticks % speedIncreaseEvery === 0 && speed < gearSpeeds[gear]) {
speed += 2;
}
}
}
// Clamp speed to current gear range
if (speed > gearSpeeds[gear]) speed = gearSpeeds[gear];
if (speed < (gearSpeeds[gear - 1] ? gearSpeeds[gear - 1] : baseSpeed * 0.5)) speed = gearSpeeds[gear - 1] ? gearSpeeds[gear - 1] : baseSpeed * 0.5;
gearTxt.setText('GEAR: ' + gear);
// Apply drift visual tilt to car
car.rotation = driftAngle;
// --- Update Speed Cursor ---
// Calculate speed percent (0 to 1) relative to min/max
var minSpeed = gearSpeeds[1];
var maxSpeedCursor = gearSpeeds[maxGear];
var speedPercent = (speed - minSpeed) / (maxSpeedCursor - minSpeed);
if (speedPercent < 0) speedPercent = 0;
if (speedPercent > 1) speedPercent = 1;
// Move square block (speed cursor) from bottom up
var fillMaxHeight = 580;
var blockSize = 120;
var minY = speedCursorBg.y + speedCursorBgAsset.height - 10;
var maxY = speedCursorBg.y + 10 + blockSize / 2;
speedCursorFill.y = minY - (fillMaxHeight - blockSize) * speedPercent;
// Set fill color (green to yellow to red)
var fillColor;
if (speedPercent < 0.5) {
// Green to yellow
var t = speedPercent * 2;
var r = Math.round(0x43 * (1 - t) + 0xfb * t);
var g = Math.round(0xa0 * (1 - t) + 0xc0 * t);
var b = Math.round(0x47 * (1 - t) + 0x2d * t);
fillColor = r << 16 | g << 8 | b;
} else {
// Yellow to red
var t = (speedPercent - 0.5) * 2;
var r = Math.round(0xfb * (1 - t) + 0xd3 * t);
var g = Math.round(0xc0 * (1 - t) + 0x2f * t);
var b = Math.round(0x2d * (1 - t) + 0x2f * t);
fillColor = r << 16 | g << 8 | b;
}
speedCursorFillAsset.tint = fillColor;
// Move stripes
for (var i = 0; i < stripes.length; i++) {
stripes[i].y += speed;
if (stripes[i].y > GAME_HEIGHT + stripes[i].height / 2) {
stripes[i].y -= stripeSpacing * stripes.length;
}
}
// Spawn vehicles
obstacleTimer += 1;
if (obstacleTimer > 32 + Math.floor(40 * baseSpeed / speed)) {
// Spawn 1-2 vehicles per spawn, never in the same lane
var lanes = 4;
var usedLanes = [];
var numVehicles = 1 + (Math.random() < 0.5 ? 1 : 0); // 1 or 2
for (var i = 0; i < numVehicles; i++) {
var lane;
do {
lane = Math.floor(Math.random() * lanes);
} while (usedLanes.indexOf(lane) !== -1 && usedLanes.length < lanes);
usedLanes.push(lane);
var vehicle = new Vehicle();
var laneWidth = ROAD_WIDTH / lanes;
vehicle.x = ROAD_X + laneWidth * (lane + 0.5);
vehicle.y = -vehicle.height;
vehicle.lane = lane;
vehicles.push(vehicle);
game.addChild(vehicle);
}
obstacleTimer = 0;
}
// Move vehicles
for (var i = vehicles.length - 1; i >= 0; i--) {
var vehicle = vehicles[i];
// Move vehicle at road speed + its relative speed
vehicle.lastY = vehicle.y;
vehicle.y += speed + vehicle.relativeSpeed;
// Remove if off screen
if (vehicle.y - vehicle.height / 2 > GAME_HEIGHT + 100 || vehicle.y + vehicle.height / 2 < -200) {
vehicle.destroy();
vehicles.splice(i, 1);
continue;
}
// Collision with car (only if visible)
var isIntersecting = car.intersects(vehicle);
if (!vehicle.lastWasIntersecting && isIntersecting) {
// Flash and game over
LK.effects.flashScreen(0xff0000, 800);
if (score > bestScore) {
storage.bestScore = score;
}
LK.showGameOver();
return;
}
vehicle.lastWasIntersecting = isIntersecting;
}
// Move coins
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
coin.y += speed;
// Remove if off screen
if (coin.y - coin.height / 2 > GAME_HEIGHT + 100) {
coin.destroy();
coins.splice(i, 1);
continue;
}
}
score += Math.floor(speed / 4); // Slow down score growth by 75%
scoreTxt.setText(score);
// Update store coins display if open
if (storeOpen && typeof coinsTxt !== "undefined") {
coinsTxt.setText('Coins: ' + (score || 0));
}
// Speed up by 1% for every 2000 score points
if (typeof lastScoreForSpeed === "undefined") {
lastScoreForSpeed = 0;
}
while (score - lastScoreForSpeed >= 2000) {
speed = Math.min(Math.round(speed * 1.01), maxSpeed);
lastScoreForSpeed += 2000;
}
if (score > bestScore) {
bestScore = score;
bestScoreTxt.setText('Best: ' + bestScore);
storage.bestScore = bestScore;
}
// Persist selected skin
if (typeof storage.selectedSkinIdx === "undefined") storage.selectedSkinIdx = selectedSkinIdx;else storage.selectedSkinIdx = selectedSkinIdx;
};
// Reset score on new game
score = 0;
scoreTxt.setText(score);
bestScore = storage.bestScore || 0;
bestScoreTxt.setText('Best: ' + bestScore);
// Reset vehicles
for (var i = vehicles.length - 1; i >= 0; i--) {
if (vehicles[i] && vehicles[i].destroy) vehicles[i].destroy();
}
vehicles = [];
// Reset drift state
isDrifting = false;
driftDirection = 0;
driftTimer = 0;
driftCooldown = 0;
driftAngle = 0;
car.rotation = 0;
// Reset store state
storePanel.visible = false;
storeOpen = false;
// Recreate car with selected skin
if (typeof car !== "undefined" && car.destroy) car.destroy();
car = new Car();
car.x = GAME_WIDTH / 2;
car.y = GAME_HEIGHT - 500;
game.addChild(car); ===================================================================
--- original.js
+++ change.js
@@ -446,10 +446,10 @@
var gearUpBtnSkin = carSkins[2] || carSkins[0]; // Green or fallback to blue
var gearUpAsset = gearUpBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
- width: buttonSize * 0.7,
- height: buttonSize * 0.7,
+ width: buttonSize,
+ height: buttonSize,
color: gearUpBtnSkin.color
});
gearUpAsset.tint = gearUpBtnSkin.color;
gearUpBtn.x = GAME_WIDTH / 2 + buttonSize + buttonMargin;
@@ -466,10 +466,10 @@
var gearDownBtnSkin = carSkins[0]; // Blue
var gearDownAsset = gearDownBtn.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5,
- width: buttonSize * 0.7,
- height: buttonSize * 0.7,
+ width: buttonSize,
+ height: buttonSize,
color: gearDownBtnSkin.color
});
gearDownAsset.tint = gearDownBtnSkin.color;
gearDownBtn.x = GAME_WIDTH / 2 - buttonSize - buttonMargin;
Vertical sports car. In-Game asset. 2d. High contrast. No shadows
Accelerator pedal vertical. In-Game asset. 2d. High contrast. No shadows
Car gear-. In-Game asset. 2d. High contrast. No shadows
Standart Car vertical. In-Game asset. 2d. High contrast. No shadows
Token. In-Game asset. 2d. High contrast. No shadows