User prompt
Her puan alındığında oyunun hızı 1.5 artsın
User prompt
Her puan alındığında oyunun hızı 3 artsın
User prompt
Her puan alındığında oyunun hızı 5 artsın
User prompt
Her puan alındığında oyunun hızı 100 artsın
User prompt
Her puan alındığında oyunun hızı 0.4 artsın
User prompt
Notalar alındığında arabanın hızı 0.4 artsın
User prompt
Engelleri saniyede 0.75 olarak ayarla
User prompt
Oyunun zorluğunu ilk 20 puan kolay, her 20 puan kazandıkça zorlaşacak şekilde düzenle
User prompt
Arabanın yanına tıkladığımda gitmiyor bu tür bugları düzelt
User prompt
Oyunun zorluğunu başlarda kolay puan kazandıkça zorlaşacak şekilde düzenle
User prompt
Engelleri müziğin ritmine göre çıkart
User prompt
9 Farklı Note assetini random olarak gönder
User prompt
Engeller her 0.65 saniyede bir belirsin
User prompt
Engeller her 0.7 saniyede bir belirsin
User prompt
8 farklı nota asseti oluştur
Code edit (1 edits merged)
Please save this source code
User prompt
Neon Rhythm Road
User prompt
- Oyun başladığında araba yolun ortasında başlar ve otomatik olarak ileri gider. - Ekranın soluna dokunmak arabayı sola, sağına dokunmak sağa hareket ettirir. - Yol üzerinde rastgele engeller ve müzik notaları belirir. - Engellere çarpılırsa oyun biter. - Toplanan her müzik notası puan kazandırır. - Oyun, oyuncu engellere çarpana kadar devam eder. - Oyun müzikle senkronize çalışacak. - Engeller ve notalar müziğin BPM değerine göre belirli aralıklarla belirecek. - Basit bir BPM senkronizasyonu kullanılabilir: örneğin, her 0.5 saniyede bir engel/nokta belirsin. - Müzik dosyası .mp3 olarak sahneye eklenecek. Arka plan bir otoyol manzarası, gece ya da neon stil tercih edilebilir. - Araba yukarıdan görünüyor (top-down). - Notalar parlayan semboller olarak görünmeli. - Engeller basit dikdörtgen bloklar olabilir. - Oyun retro ya da synthwave estetiğinde olabilir (istersen görsel AI ile üretim için ayrıca belirtirim).
Initial prompt
Oyuncu bir arabayı ekranın sol ve sağ tarafına dokunarak kontrol eder (sol dokunuş: sola git, sağ dokunuş: sağa git). - Araba sabit hızla ileri gider (otomatik ilerleme). - Yol üzerinde engeller belirir; oyuncu sağ veya sola kaçarak çarpmamaya çalışır. - Oyuncu ayrıca yol üzerindeki müzik notalarını toplayarak puan kazanır. - Engellere çarpılırsa oyun biter.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Car class var Car = Container.expand(function () { var self = Container.call(this); var carSprite = self.attachAsset('car', { anchorX: 0.5, anchorY: 0.5 }); // For possible future effects self.flash = function () { LK.effects.flashObject(self, 0xffffff, 200); }; return self; }); // LaneLine class (for visual effect) var LaneLine = Container.expand(function () { var self = Container.call(this); var lineSprite = self.attachAsset('laneLine', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Note class var Note = Container.expand(function (assetId) { var self = Container.call(this); var noteAssetId = assetId || 'note1'; var noteSprite = self.attachAsset(noteAssetId, { anchorX: 0.5, anchorY: 0.5 }); // Lane index (0,1,2) self.lane = 1; // For state tracking self.lastY = undefined; self.lastIntersecting = false; self.assetId = noteAssetId; return self; }); // Obstacle class var Obstacle = Container.expand(function () { var self = Container.call(this); var obsSprite = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); // Lane index (0,1,2) self.lane = 1; // For state tracking self.lastY = undefined; self.lastIntersecting = false; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0a0020 // Deep synthwave night }); /**** * Game Code ****/ // --- Game constants --- // Neon synthwave colors // Sounds and music (IDs are placeholders, engine will load as used) var NUM_LANES = 3; var LANE_WIDTH = 410; // 2048 / 3 ≈ 682, but leave margins for neon effect var ROAD_TOP = 400; var ROAD_BOTTOM = 2732 - 200; var CAR_Y = 2200; var BASE_OBSTACLE_SPEED = 22; // px per frame var BASE_NOTE_SPEED = 22; var speedMultiplier = 1.0; var OBSTACLE_SPEED = BASE_OBSTACLE_SPEED * speedMultiplier; var NOTE_SPEED = BASE_NOTE_SPEED * speedMultiplier; var LANE_X = [410, // left 1024, // center 1638 // right ]; // --- Music BPM and spawn sync --- var BPM = 120; // Example BPM, can be changed if music changes // Spawn interval: 0.75 seconds = 45 frames at 60fps var BEAT_INTERVAL = 45; var lastBeatTick = 0; // --- Game state --- var car = null; var carLane = 1; // 0: left, 1: center, 2: right var obstacles = []; var notes = []; var laneLines = []; var score = 0; var scoreTxt = null; var dragSide = null; // 'left' or 'right' for touch controls // --- Note sequence control --- var noteSequence = ['note1', 'note2', 'note3', 'note4', 'note5', 'note6', 'note7', 'note8', 'note9', 'note10', 'note11', 'note12', 'note13', 'note14', 'note15', 'note16', 'note17', 'note18', 'note19', 'note20', 'note21', 'note22', 'note23', 'note24', 'note25', 'note26', 'note27', 'note28', 'note29', 'note30', 'note31', 'note32', 'note33', 'note34', 'note35', 'note36', 'note37', 'note38']; var noteSequenceIndex = 0; // --- Entry Screen --- var entryScreen = new Container(); var playBtn = new Text2('Play', { size: 180, fill: 0x00fff2, font: "Impact" }); playBtn.anchor.set(0.5, 0.5); playBtn.x = 2048 / 2; playBtn.y = 2732 / 2; entryScreen.addChild(playBtn); game.addChild(entryScreen); // Hide game UI until play is pressed LK.gui.top.visible = false; // Play button interaction playBtn.interactive = true; playBtn.buttonMode = true; playBtn.down = function (x, y, obj) { gameStarted = false; // Prevent game logic from running immediately // Play applause sound LK.getSound('ApplauseSound').play(); // Remove entry screen entryScreen.destroy(); // Show game UI LK.gui.top.visible = true; // --- Background music --- LK.playMusic('neonTrack'); // --- Draw neon road lanes --- createLaneLines(); // --- Create car --- car = new Car(); car.x = LANE_X[carLane]; car.y = CAR_Y; game.addChild(car); // --- Score display --- scoreTxt = new Text2('0', { size: 120, fill: 0xFFF200, font: "Impact" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // --- Speed multiplier display --- speedTxt = new Text2('x1', { size: 80, fill: 0x00fff2, font: "Impact" }); speedTxt.anchor.set(0.5, 0); // Position speedTxt just below scoreTxt (scoreTxt is anchored at top center) speedTxt.y = scoreTxt.height + 10; LK.gui.top.addChild(speedTxt); // --- Fastest! text (hidden by default) --- fastestTxt = new Text2('Fastest!', { size: 80, fill: 0xFF2A6D, font: "Impact" }); fastestTxt.anchor.set(0.5, 0); fastestTxt.visible = false; // Both Fastest! and Too Slow! will be positioned at the same distance below speedTxt fastestTxt.y = speedTxt.y + speedTxt.height + 20; LK.gui.top.addChild(fastestTxt); // --- Too Slow! text (hidden by default) --- tooSlowTxt = new Text2('Too Slow!', { size: 80, fill: 0xFFFFFF, font: "Impact" }); tooSlowTxt.anchor.set(0.5, 0); tooSlowTxt.visible = false; // Position Too Slow! at the same y as Fastest! so they overlap and are always at the same distance below speed counter tooSlowTxt.y = speedTxt.y + speedTxt.height + 20; LK.gui.top.addChild(tooSlowTxt); // --- Touch controls --- game.down = handleDown; game.up = handleUp; game.move = handleMove; // --- Set initial score --- LK.setScore(0); scoreTxt.setText('0'); // Delay game start by 2 seconds before enabling obstacles/notes LK.setTimeout(function () { gameStarted = true; lastBeatTick = LK.ticks; // Reset beat tick so spawn syncs after delay }, 2000); }; // --- Draw neon road lanes --- function createLaneLines() { for (var i = 0; i < laneLines.length; i++) { laneLines[i].destroy(); } laneLines = []; // Draw vertical lines between lanes for (var i = 1; i < NUM_LANES; i++) { var x = (LANE_X[i - 1] + LANE_X[i]) / 2; for (var y = ROAD_TOP; y < ROAD_BOTTOM; y += 400) { var line = new LaneLine(); line.x = x; line.y = y; line.alpha = 0.25; game.addChild(line); laneLines.push(line); } } } // --- Touch controls --- // Touch/click left or right half of screen to move car function handleDown(x, y, obj) { // Only respond to touches below the top 200px (avoid menu) if (y < 200) return; if (x < 1024) { dragSide = 'left'; moveCar(-1); } else { dragSide = 'right'; moveCar(1); } } function handleUp(x, y, obj) { dragSide = null; } function handleMove(x, y, obj) { // Optional: swipe to move, but for now, tap only } // --- Move car between lanes --- function moveCar(dir) { var newLane = carLane + dir; if (newLane < 0) newLane = 0; if (newLane > 2) newLane = 2; if (newLane !== carLane) { carLane = newLane; // Animate car to new lane tween(car, { x: LANE_X[carLane] }, { duration: 120, easing: tween.cubicOut }); } } // --- Spawn obstacles and notes in sync with music --- function spawnBeatObjects() { // Always place exactly 1 obstacle per beat var availableLanes = [0, 1, 2]; // Place exactly 1 obstacle var idx = Math.floor(Math.random() * availableLanes.length); var lane = availableLanes[idx]; availableLanes.splice(idx, 1); var obs = new Obstacle(); obs.lane = lane; obs.x = LANE_X[lane]; obs.y = ROAD_TOP - 100; obs.lastY = obs.y; obs.lastIntersecting = false; obstacles.push(obs); game.addChild(obs); // Place a note in the next free lane in sequence (always spawn a note if a lane is available) if (availableLanes.length > 0) { var idx = Math.floor(Math.random() * availableLanes.length); var lane = availableLanes[idx]; var nextNoteAssetId = noteSequence[noteSequenceIndex]; noteSequenceIndex = (noteSequenceIndex + 1) % noteSequence.length; var note = new Note(nextNoteAssetId); note.lane = lane; note.x = LANE_X[lane]; note.y = ROAD_TOP - 100; note.lastY = note.y; note.lastIntersecting = false; notes.push(note); game.addChild(note); } } // --- Main game update loop --- var gameStarted = false; game.update = function () { if (!gameStarted) return; // Animate lane lines for neon effect for (var i = 0; i < laneLines.length; i++) { laneLines[i].y += OBSTACLE_SPEED; if (laneLines[i].y > ROAD_BOTTOM + 200) { laneLines[i].y = ROAD_TOP - 200; } } // Spawn obstacles/notes on beat if (LK.ticks - lastBeatTick >= BEAT_INTERVAL) { spawnBeatObjects(); lastBeatTick = LK.ticks; } // Move obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.y += OBSTACLE_SPEED; // Off-screen removal if (obs.lastY < 2800 && obs.y >= 2800) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision detection var isIntersecting = obs.intersects(car); if (!obs.lastIntersecting && isIntersecting) { // Crash! LK.effects.flashScreen(0xff2a6d, 800); car.flash(); // Pause neonTrack music LK.stopMusic(); // Delay game over by 2 seconds LK.getSound('GameOver').play(); LK.setTimeout(function () { LK.showGameOver(); }, 2000); // Prevent further updates during delay gameStarted = false; return; } obs.lastY = obs.y; obs.lastIntersecting = isIntersecting; } // Move notes for (var i = notes.length - 1; i >= 0; i--) { var note = notes[i]; note.y += NOTE_SPEED; // Off-screen removal if (note.lastY < 2800 && note.y >= 2800) { // Decrease speed multiplier by 0.3 if note is missed speedMultiplier -= 0.3; if (speedMultiplier < 0.1) speedMultiplier = 0.1; // Prevent negative or zero speed OBSTACLE_SPEED = BASE_OBSTACLE_SPEED * speedMultiplier; NOTE_SPEED = BASE_NOTE_SPEED * speedMultiplier; // Update speed multiplier display if (typeof speedTxt !== "undefined") { speedTxt.setText('x' + speedMultiplier.toFixed(2).replace(/\.00$/, '')); } // End the game if speedMultiplier drops below 1 if (speedMultiplier < 1) { LK.showGameOver(); return; } note.destroy(); notes.splice(i, 1); continue; } // Collect note var isIntersecting = note.intersects(car); if (!note.lastIntersecting && isIntersecting) { // Collect! LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); // Increase speed multiplier by 0.05 each time score increases speedMultiplier += 0.05; OBSTACLE_SPEED = BASE_OBSTACLE_SPEED * speedMultiplier; NOTE_SPEED = BASE_NOTE_SPEED * speedMultiplier; // Update speed multiplier display if (typeof speedTxt !== "undefined") { speedTxt.setText('x' + speedMultiplier.toFixed(2).replace(/\.00$/, '')); if (typeof fastestTxt !== "undefined") { // Show Fastest! if speedMultiplier just crossed above 2 if (speedMultiplier > 2 && !fastestTxt.visible) { fastestTxt.visible = true; } else if (speedMultiplier <= 2 && fastestTxt.visible) { fastestTxt.visible = false; } } if (typeof tooSlowTxt !== "undefined") { // Show Too Slow! if speedMultiplier just dropped below 1.5 if (speedMultiplier < 1.5 && !tooSlowTxt.visible) { tooSlowTxt.visible = true; } else if (speedMultiplier >= 1.5 && tooSlowTxt.visible) { tooSlowTxt.visible = false; } } } // Only play NoteDo sound if this is note1 asset if (note.assetId === 'note1') { LK.getSound('NoteDo').play(); } // Only play NoteRe sound if this is note2 asset if (note.assetId === 'note2') { LK.getSound('NoteRe').play(); } // Only play NoteMi sound if this is note3 asset if (note.assetId === 'note3') { LK.getSound('NoteMi').play(); } // Only play NoteFa sound if this is note4 asset if (note.assetId === 'note4') { LK.getSound('NoteFa').play(); } // Only play NoteSol sound if this is note5 asset if (note.assetId === 'note5') { LK.getSound('NoteSol').play(); } // Only play NoteLa sound if this is note6 asset if (note.assetId === 'note6') { LK.getSound('NoteLa').play(); } // Only play NoteSi sound if this is note7 asset if (note.assetId === 'note7') { LK.getSound('NoteSi').play(); } // Only play NoteThickDo sound if this is note8 asset if (note.assetId === 'note8') { LK.getSound('NoteThickDo').play(); } // Only play DOKUZ sound if this is note9 asset if (note.assetId === 'note9') { LK.getSound('DOKUZ').play(); } // Only play ONNN sound if this is note10 asset if (note.assetId === 'note10') { LK.getSound('ONNN').play(); } // Only play ONBIR sound if this is note11 asset if (note.assetId === 'note11') { LK.getSound('ONBIR').play(); } // Only play ONIKI sound if this is note12 asset if (note.assetId === 'note12') { LK.getSound('ONIKI').play(); } // Only play ONUC sound if this is note13 asset if (note.assetId === 'note13') { LK.getSound('ONUC').play(); } // Only play ONDORT sound if this is note14 asset if (note.assetId === 'note14') { LK.getSound('ONDORT').play(); } // Only play ONBES sound if this is note15 asset if (note.assetId === 'note15') { LK.getSound('ONBES').play(); } // Only play ONALTI sound if this is note16 asset if (note.assetId === 'note16') { LK.getSound('ONALTI').play(); } // Only play ONYEDI sound if this is note17 asset if (note.assetId === 'note17') { LK.getSound('ONYEDI').play(); } // Only play ONSEKIZ sound if this is note18 asset if (note.assetId === 'note18') { LK.getSound('ONSEKIZ').play(); } // Only play ONDOKUZ sound if this is note19 asset if (note.assetId === 'note19') { LK.getSound('ONDOKUZ').play(); } // Only play YIRMI sound if this is note20 asset if (note.assetId === 'note20') { LK.getSound('YIRMI').play(); } // Only play YIRMIBIR sound if this is note21 asset if (note.assetId === 'note21') { LK.getSound('YIRMIBIR').play(); } // Only play YIRMIIKI sound if this is note22 asset if (note.assetId === 'note22') { LK.getSound('YIRMIIKI').play(); } // Only play YIRMIUC sound if this is note23 asset if (note.assetId === 'note23') { LK.getSound('YIRMIUC').play(); } // Only play YIRMIDORT sound if this is note24 asset if (note.assetId === 'note24') { LK.getSound('YIRMIDORT').play(); } // Only play YIRMIBES sound if this is note25 asset if (note.assetId === 'note25') { LK.getSound('YIRMIBES').play(); } // Only play YIRMIALTI sound if this is note26 asset if (note.assetId === 'note26') { LK.getSound('YIRMIALTI').play(); } // Only play YIRMIYEDI sound if this is note27 asset if (note.assetId === 'note27') { LK.getSound('YIRMIYEDI').play(); } // Only play YIRMISEKIZ sound if this is note28 asset if (note.assetId === 'note28') { LK.getSound('YIRMISEKIZ').play(); } // Only play YIRMIDOKUZ sound if this is note29 asset if (note.assetId === 'note29') { LK.getSound('YIRMIDOKUZ').play(); } // Only play OTUZ sound if this is note30 asset if (note.assetId === 'note30') { LK.getSound('OTUZ').play(); } // Only play OTUZBIR sound if this is note31 asset if (note.assetId === 'note31') { LK.getSound('OTUZBIR').play(); } // Only play OTUZIKI sound if this is note32 asset if (note.assetId === 'note32') { LK.getSound('OTUZIKI').play(); } // Only play OTUZUC sound if this is note33 asset if (note.assetId === 'note33') { LK.getSound('OTUZUC').play(); } // Only play OTUZDORT sound if this is note34 asset if (note.assetId === 'note34') { LK.getSound('OTUZDORT').play(); } // Only play OTUZBES sound if this is note35 asset if (note.assetId === 'note35') { LK.getSound('OTUZBES').play(); } // Only play OTUZALTI sound if this is note36 asset if (note.assetId === 'note36') { LK.getSound('OTUZALTI').play(); } // Only play OTUZYEDI sound if this is note37 asset if (note.assetId === 'note37') { LK.getSound('OTUZYEDI').play(); } // Only play OTUZSEKIZ sound if this is note38 asset if (note.assetId === 'note38') { LK.getSound('OTUZSEKIZ').play(); } // Neon flash LK.effects.flashObject(car, 0xfff200, 200); note.destroy(); notes.splice(i, 1); continue; } note.lastY = note.y; note.lastIntersecting = isIntersecting; } }; // --- Set initial score --- LK.setScore(0); if (scoreTxt !== null) { scoreTxt.setText('0'); }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Car class
var Car = Container.expand(function () {
var self = Container.call(this);
var carSprite = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
// For possible future effects
self.flash = function () {
LK.effects.flashObject(self, 0xffffff, 200);
};
return self;
});
// LaneLine class (for visual effect)
var LaneLine = Container.expand(function () {
var self = Container.call(this);
var lineSprite = self.attachAsset('laneLine', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Note class
var Note = Container.expand(function (assetId) {
var self = Container.call(this);
var noteAssetId = assetId || 'note1';
var noteSprite = self.attachAsset(noteAssetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Lane index (0,1,2)
self.lane = 1;
// For state tracking
self.lastY = undefined;
self.lastIntersecting = false;
self.assetId = noteAssetId;
return self;
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsSprite = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Lane index (0,1,2)
self.lane = 1;
// For state tracking
self.lastY = undefined;
self.lastIntersecting = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0020 // Deep synthwave night
});
/****
* Game Code
****/
// --- Game constants ---
// Neon synthwave colors
// Sounds and music (IDs are placeholders, engine will load as used)
var NUM_LANES = 3;
var LANE_WIDTH = 410; // 2048 / 3 ≈ 682, but leave margins for neon effect
var ROAD_TOP = 400;
var ROAD_BOTTOM = 2732 - 200;
var CAR_Y = 2200;
var BASE_OBSTACLE_SPEED = 22; // px per frame
var BASE_NOTE_SPEED = 22;
var speedMultiplier = 1.0;
var OBSTACLE_SPEED = BASE_OBSTACLE_SPEED * speedMultiplier;
var NOTE_SPEED = BASE_NOTE_SPEED * speedMultiplier;
var LANE_X = [410,
// left
1024,
// center
1638 // right
];
// --- Music BPM and spawn sync ---
var BPM = 120; // Example BPM, can be changed if music changes
// Spawn interval: 0.75 seconds = 45 frames at 60fps
var BEAT_INTERVAL = 45;
var lastBeatTick = 0;
// --- Game state ---
var car = null;
var carLane = 1; // 0: left, 1: center, 2: right
var obstacles = [];
var notes = [];
var laneLines = [];
var score = 0;
var scoreTxt = null;
var dragSide = null; // 'left' or 'right' for touch controls
// --- Note sequence control ---
var noteSequence = ['note1', 'note2', 'note3', 'note4', 'note5', 'note6', 'note7', 'note8', 'note9', 'note10', 'note11', 'note12', 'note13', 'note14', 'note15', 'note16', 'note17', 'note18', 'note19', 'note20', 'note21', 'note22', 'note23', 'note24', 'note25', 'note26', 'note27', 'note28', 'note29', 'note30', 'note31', 'note32', 'note33', 'note34', 'note35', 'note36', 'note37', 'note38'];
var noteSequenceIndex = 0;
// --- Entry Screen ---
var entryScreen = new Container();
var playBtn = new Text2('Play', {
size: 180,
fill: 0x00fff2,
font: "Impact"
});
playBtn.anchor.set(0.5, 0.5);
playBtn.x = 2048 / 2;
playBtn.y = 2732 / 2;
entryScreen.addChild(playBtn);
game.addChild(entryScreen);
// Hide game UI until play is pressed
LK.gui.top.visible = false;
// Play button interaction
playBtn.interactive = true;
playBtn.buttonMode = true;
playBtn.down = function (x, y, obj) {
gameStarted = false; // Prevent game logic from running immediately
// Play applause sound
LK.getSound('ApplauseSound').play();
// Remove entry screen
entryScreen.destroy();
// Show game UI
LK.gui.top.visible = true;
// --- Background music ---
LK.playMusic('neonTrack');
// --- Draw neon road lanes ---
createLaneLines();
// --- Create car ---
car = new Car();
car.x = LANE_X[carLane];
car.y = CAR_Y;
game.addChild(car);
// --- Score display ---
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFF200,
font: "Impact"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// --- Speed multiplier display ---
speedTxt = new Text2('x1', {
size: 80,
fill: 0x00fff2,
font: "Impact"
});
speedTxt.anchor.set(0.5, 0);
// Position speedTxt just below scoreTxt (scoreTxt is anchored at top center)
speedTxt.y = scoreTxt.height + 10;
LK.gui.top.addChild(speedTxt);
// --- Fastest! text (hidden by default) ---
fastestTxt = new Text2('Fastest!', {
size: 80,
fill: 0xFF2A6D,
font: "Impact"
});
fastestTxt.anchor.set(0.5, 0);
fastestTxt.visible = false;
// Both Fastest! and Too Slow! will be positioned at the same distance below speedTxt
fastestTxt.y = speedTxt.y + speedTxt.height + 20;
LK.gui.top.addChild(fastestTxt);
// --- Too Slow! text (hidden by default) ---
tooSlowTxt = new Text2('Too Slow!', {
size: 80,
fill: 0xFFFFFF,
font: "Impact"
});
tooSlowTxt.anchor.set(0.5, 0);
tooSlowTxt.visible = false;
// Position Too Slow! at the same y as Fastest! so they overlap and are always at the same distance below speed counter
tooSlowTxt.y = speedTxt.y + speedTxt.height + 20;
LK.gui.top.addChild(tooSlowTxt);
// --- Touch controls ---
game.down = handleDown;
game.up = handleUp;
game.move = handleMove;
// --- Set initial score ---
LK.setScore(0);
scoreTxt.setText('0');
// Delay game start by 2 seconds before enabling obstacles/notes
LK.setTimeout(function () {
gameStarted = true;
lastBeatTick = LK.ticks; // Reset beat tick so spawn syncs after delay
}, 2000);
};
// --- Draw neon road lanes ---
function createLaneLines() {
for (var i = 0; i < laneLines.length; i++) {
laneLines[i].destroy();
}
laneLines = [];
// Draw vertical lines between lanes
for (var i = 1; i < NUM_LANES; i++) {
var x = (LANE_X[i - 1] + LANE_X[i]) / 2;
for (var y = ROAD_TOP; y < ROAD_BOTTOM; y += 400) {
var line = new LaneLine();
line.x = x;
line.y = y;
line.alpha = 0.25;
game.addChild(line);
laneLines.push(line);
}
}
}
// --- Touch controls ---
// Touch/click left or right half of screen to move car
function handleDown(x, y, obj) {
// Only respond to touches below the top 200px (avoid menu)
if (y < 200) return;
if (x < 1024) {
dragSide = 'left';
moveCar(-1);
} else {
dragSide = 'right';
moveCar(1);
}
}
function handleUp(x, y, obj) {
dragSide = null;
}
function handleMove(x, y, obj) {
// Optional: swipe to move, but for now, tap only
}
// --- Move car between lanes ---
function moveCar(dir) {
var newLane = carLane + dir;
if (newLane < 0) newLane = 0;
if (newLane > 2) newLane = 2;
if (newLane !== carLane) {
carLane = newLane;
// Animate car to new lane
tween(car, {
x: LANE_X[carLane]
}, {
duration: 120,
easing: tween.cubicOut
});
}
}
// --- Spawn obstacles and notes in sync with music ---
function spawnBeatObjects() {
// Always place exactly 1 obstacle per beat
var availableLanes = [0, 1, 2];
// Place exactly 1 obstacle
var idx = Math.floor(Math.random() * availableLanes.length);
var lane = availableLanes[idx];
availableLanes.splice(idx, 1);
var obs = new Obstacle();
obs.lane = lane;
obs.x = LANE_X[lane];
obs.y = ROAD_TOP - 100;
obs.lastY = obs.y;
obs.lastIntersecting = false;
obstacles.push(obs);
game.addChild(obs);
// Place a note in the next free lane in sequence (always spawn a note if a lane is available)
if (availableLanes.length > 0) {
var idx = Math.floor(Math.random() * availableLanes.length);
var lane = availableLanes[idx];
var nextNoteAssetId = noteSequence[noteSequenceIndex];
noteSequenceIndex = (noteSequenceIndex + 1) % noteSequence.length;
var note = new Note(nextNoteAssetId);
note.lane = lane;
note.x = LANE_X[lane];
note.y = ROAD_TOP - 100;
note.lastY = note.y;
note.lastIntersecting = false;
notes.push(note);
game.addChild(note);
}
}
// --- Main game update loop ---
var gameStarted = false;
game.update = function () {
if (!gameStarted) return;
// Animate lane lines for neon effect
for (var i = 0; i < laneLines.length; i++) {
laneLines[i].y += OBSTACLE_SPEED;
if (laneLines[i].y > ROAD_BOTTOM + 200) {
laneLines[i].y = ROAD_TOP - 200;
}
}
// Spawn obstacles/notes on beat
if (LK.ticks - lastBeatTick >= BEAT_INTERVAL) {
spawnBeatObjects();
lastBeatTick = LK.ticks;
}
// Move obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.y += OBSTACLE_SPEED;
// Off-screen removal
if (obs.lastY < 2800 && obs.y >= 2800) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision detection
var isIntersecting = obs.intersects(car);
if (!obs.lastIntersecting && isIntersecting) {
// Crash!
LK.effects.flashScreen(0xff2a6d, 800);
car.flash();
// Pause neonTrack music
LK.stopMusic();
// Delay game over by 2 seconds
LK.getSound('GameOver').play();
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
// Prevent further updates during delay
gameStarted = false;
return;
}
obs.lastY = obs.y;
obs.lastIntersecting = isIntersecting;
}
// Move notes
for (var i = notes.length - 1; i >= 0; i--) {
var note = notes[i];
note.y += NOTE_SPEED;
// Off-screen removal
if (note.lastY < 2800 && note.y >= 2800) {
// Decrease speed multiplier by 0.3 if note is missed
speedMultiplier -= 0.3;
if (speedMultiplier < 0.1) speedMultiplier = 0.1; // Prevent negative or zero speed
OBSTACLE_SPEED = BASE_OBSTACLE_SPEED * speedMultiplier;
NOTE_SPEED = BASE_NOTE_SPEED * speedMultiplier;
// Update speed multiplier display
if (typeof speedTxt !== "undefined") {
speedTxt.setText('x' + speedMultiplier.toFixed(2).replace(/\.00$/, ''));
}
// End the game if speedMultiplier drops below 1
if (speedMultiplier < 1) {
LK.showGameOver();
return;
}
note.destroy();
notes.splice(i, 1);
continue;
}
// Collect note
var isIntersecting = note.intersects(car);
if (!note.lastIntersecting && isIntersecting) {
// Collect!
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Increase speed multiplier by 0.05 each time score increases
speedMultiplier += 0.05;
OBSTACLE_SPEED = BASE_OBSTACLE_SPEED * speedMultiplier;
NOTE_SPEED = BASE_NOTE_SPEED * speedMultiplier;
// Update speed multiplier display
if (typeof speedTxt !== "undefined") {
speedTxt.setText('x' + speedMultiplier.toFixed(2).replace(/\.00$/, ''));
if (typeof fastestTxt !== "undefined") {
// Show Fastest! if speedMultiplier just crossed above 2
if (speedMultiplier > 2 && !fastestTxt.visible) {
fastestTxt.visible = true;
} else if (speedMultiplier <= 2 && fastestTxt.visible) {
fastestTxt.visible = false;
}
}
if (typeof tooSlowTxt !== "undefined") {
// Show Too Slow! if speedMultiplier just dropped below 1.5
if (speedMultiplier < 1.5 && !tooSlowTxt.visible) {
tooSlowTxt.visible = true;
} else if (speedMultiplier >= 1.5 && tooSlowTxt.visible) {
tooSlowTxt.visible = false;
}
}
}
// Only play NoteDo sound if this is note1 asset
if (note.assetId === 'note1') {
LK.getSound('NoteDo').play();
}
// Only play NoteRe sound if this is note2 asset
if (note.assetId === 'note2') {
LK.getSound('NoteRe').play();
}
// Only play NoteMi sound if this is note3 asset
if (note.assetId === 'note3') {
LK.getSound('NoteMi').play();
}
// Only play NoteFa sound if this is note4 asset
if (note.assetId === 'note4') {
LK.getSound('NoteFa').play();
}
// Only play NoteSol sound if this is note5 asset
if (note.assetId === 'note5') {
LK.getSound('NoteSol').play();
}
// Only play NoteLa sound if this is note6 asset
if (note.assetId === 'note6') {
LK.getSound('NoteLa').play();
}
// Only play NoteSi sound if this is note7 asset
if (note.assetId === 'note7') {
LK.getSound('NoteSi').play();
}
// Only play NoteThickDo sound if this is note8 asset
if (note.assetId === 'note8') {
LK.getSound('NoteThickDo').play();
}
// Only play DOKUZ sound if this is note9 asset
if (note.assetId === 'note9') {
LK.getSound('DOKUZ').play();
}
// Only play ONNN sound if this is note10 asset
if (note.assetId === 'note10') {
LK.getSound('ONNN').play();
}
// Only play ONBIR sound if this is note11 asset
if (note.assetId === 'note11') {
LK.getSound('ONBIR').play();
}
// Only play ONIKI sound if this is note12 asset
if (note.assetId === 'note12') {
LK.getSound('ONIKI').play();
}
// Only play ONUC sound if this is note13 asset
if (note.assetId === 'note13') {
LK.getSound('ONUC').play();
}
// Only play ONDORT sound if this is note14 asset
if (note.assetId === 'note14') {
LK.getSound('ONDORT').play();
}
// Only play ONBES sound if this is note15 asset
if (note.assetId === 'note15') {
LK.getSound('ONBES').play();
}
// Only play ONALTI sound if this is note16 asset
if (note.assetId === 'note16') {
LK.getSound('ONALTI').play();
}
// Only play ONYEDI sound if this is note17 asset
if (note.assetId === 'note17') {
LK.getSound('ONYEDI').play();
}
// Only play ONSEKIZ sound if this is note18 asset
if (note.assetId === 'note18') {
LK.getSound('ONSEKIZ').play();
}
// Only play ONDOKUZ sound if this is note19 asset
if (note.assetId === 'note19') {
LK.getSound('ONDOKUZ').play();
}
// Only play YIRMI sound if this is note20 asset
if (note.assetId === 'note20') {
LK.getSound('YIRMI').play();
}
// Only play YIRMIBIR sound if this is note21 asset
if (note.assetId === 'note21') {
LK.getSound('YIRMIBIR').play();
}
// Only play YIRMIIKI sound if this is note22 asset
if (note.assetId === 'note22') {
LK.getSound('YIRMIIKI').play();
}
// Only play YIRMIUC sound if this is note23 asset
if (note.assetId === 'note23') {
LK.getSound('YIRMIUC').play();
}
// Only play YIRMIDORT sound if this is note24 asset
if (note.assetId === 'note24') {
LK.getSound('YIRMIDORT').play();
}
// Only play YIRMIBES sound if this is note25 asset
if (note.assetId === 'note25') {
LK.getSound('YIRMIBES').play();
}
// Only play YIRMIALTI sound if this is note26 asset
if (note.assetId === 'note26') {
LK.getSound('YIRMIALTI').play();
}
// Only play YIRMIYEDI sound if this is note27 asset
if (note.assetId === 'note27') {
LK.getSound('YIRMIYEDI').play();
}
// Only play YIRMISEKIZ sound if this is note28 asset
if (note.assetId === 'note28') {
LK.getSound('YIRMISEKIZ').play();
}
// Only play YIRMIDOKUZ sound if this is note29 asset
if (note.assetId === 'note29') {
LK.getSound('YIRMIDOKUZ').play();
}
// Only play OTUZ sound if this is note30 asset
if (note.assetId === 'note30') {
LK.getSound('OTUZ').play();
}
// Only play OTUZBIR sound if this is note31 asset
if (note.assetId === 'note31') {
LK.getSound('OTUZBIR').play();
}
// Only play OTUZIKI sound if this is note32 asset
if (note.assetId === 'note32') {
LK.getSound('OTUZIKI').play();
}
// Only play OTUZUC sound if this is note33 asset
if (note.assetId === 'note33') {
LK.getSound('OTUZUC').play();
}
// Only play OTUZDORT sound if this is note34 asset
if (note.assetId === 'note34') {
LK.getSound('OTUZDORT').play();
}
// Only play OTUZBES sound if this is note35 asset
if (note.assetId === 'note35') {
LK.getSound('OTUZBES').play();
}
// Only play OTUZALTI sound if this is note36 asset
if (note.assetId === 'note36') {
LK.getSound('OTUZALTI').play();
}
// Only play OTUZYEDI sound if this is note37 asset
if (note.assetId === 'note37') {
LK.getSound('OTUZYEDI').play();
}
// Only play OTUZSEKIZ sound if this is note38 asset
if (note.assetId === 'note38') {
LK.getSound('OTUZSEKIZ').play();
}
// Neon flash
LK.effects.flashObject(car, 0xfff200, 200);
note.destroy();
notes.splice(i, 1);
continue;
}
note.lastY = note.y;
note.lastIntersecting = isIntersecting;
}
};
// --- Set initial score ---
LK.setScore(0);
if (scoreTxt !== null) {
scoreTxt.setText('0');
}
NoteRe
Sound effect
NoteMi
Sound effect
NoteFa
Sound effect
NoteSol
Sound effect
NoteLa
Sound effect
NoteSi
Sound effect
NoteThickDo
Sound effect
ApplauseSound
Sound effect
neonTrack
Music
GameOver
Sound effect
NoteDo
Sound effect
DOKUZ
Sound effect
ONNN
Sound effect
ONBIR
Sound effect
ONIKI
Sound effect
ONUC
Sound effect
ONDORT
Sound effect
ONBES
Sound effect
ONALTI
Sound effect
ONYEDI
Sound effect
ONSEKIZ
Sound effect
ONDOKUZ
Sound effect
YIRMI
Sound effect
YIRMIBIR
Sound effect
YIRMIIKI
Sound effect
YIRMIUC
Sound effect
YIRMIDORT
Sound effect
YIRMIBES
Sound effect
YIRMIALTI
Sound effect
YIRMIYEDI
Sound effect
YIRMISEKIZ
Sound effect
YIRMIDOKUZ
Sound effect
OTUZ
Sound effect
OTUZBIR
Sound effect
OTUZIKI
Sound effect
OTUZUC
Sound effect
OTUZDORT
Sound effect
OTUZBES
Sound effect
OTUZALTI
Sound effect
OTUZYEDI
Sound effect
OTUZSEKIZ
Sound effect