User prompt
Oyun notaları her seferinde rastgele yerlerde oluşsun ve sonsuza kadar notalar rastgele gelsin.
User prompt
Oyun 1000 puandan sonrada devam etsin
User prompt
Oyun sonsuza kadar devam etsin
User prompt
Miss çalma süresini 1 yap
User prompt
Her nota geçtiğinde misses bir sayılsın
User prompt
Miss çalma süresini 2 saniye yap
User prompt
Kaybedince miss sesi çıksın
User prompt
Oyun başladığında müzikte başlasın
User prompt
Nota tıklama yerlerini büyüt
User prompt
Notalar daha yavaş ve teker teker gelsin
Code edit (1 edits merged)
Please save this source code
User prompt
Beat Tapper
Initial prompt
Bana bir müzik oyunu tasarla
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Note class for falling notes var Note = Container.expand(function () { var self = Container.call(this); // Lane index (0-3) self.lane = 0; self.hit = false; self.missed = false; self.speed = 0; // pixels per tick self.time = 0; // time (in ticks) when note should reach the target self.spawned = false; // Attach correct note asset based on lane self.setLane = function (laneIdx) { self.lane = laneIdx; var assetId = 'note' + (laneIdx + 1); var noteAsset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; // Called every tick self.update = function () { if (!self.spawned) return; self.y += self.speed; }; // Called when note is hit self.onHit = function () { if (self.hit || self.missed) return; self.hit = true; // Animate note tween(self, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); }; // Called when note is missed self.onMiss = function () { if (self.hit || self.missed) return; self.missed = true; LK.getSound('miss').play({ fade: { start: 1, end: 0, duration: 2000 } }); tween(self, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // --- Game Constants --- // 4 note lanes, each with a different color for clarity var NUM_LANES = 4; var LANE_WIDTH = 200; var LANE_SPACING = 40; var NOTE_WIDTH = 180; var NOTE_HEIGHT = 80; var TARGET_HEIGHT = 120; // Increased from 40 to 120 for larger tap area var LANE_HEIGHT = 2200; var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var LANE_TOTAL_WIDTH = NUM_LANES * LANE_WIDTH + (NUM_LANES - 1) * LANE_SPACING; var LANE_START_X = (GAME_WIDTH - LANE_TOTAL_WIDTH) / 2 + LANE_WIDTH / 2; var TARGET_Y = GAME_HEIGHT - 220; // Target zone Y position // --- Game State --- var notes = []; // All active notes var noteIndex = 0; // Index of next note to spawn var songTicks = 0; // Ticks since song start var score = 0; var combo = 0; var maxCombo = 0; var misses = 0; var maxMisses = 10; var songEnded = false; var songStarted = false; var lastTick = 0; // --- UI Elements --- var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var comboTxt = new Text2('', { size: 70, fill: 0xFFE066 }); comboTxt.anchor.set(0.5, 0); LK.gui.top.addChild(comboTxt); comboTxt.y = 130; var missTxt = new Text2('', { size: 70, fill: 0xFF6666 }); missTxt.anchor.set(0.5, 0); LK.gui.top.addChild(missTxt); missTxt.y = 210; // --- Lanes and Targets --- var lanes = []; var targets = []; for (var i = 0; i < NUM_LANES; i++) { // Lane background var laneX = LANE_START_X + i * (LANE_WIDTH + LANE_SPACING); var lane = LK.getAsset('lane', { anchorX: 0.5, anchorY: 0, x: laneX, y: 0, width: LANE_WIDTH, height: LANE_HEIGHT }); game.addChild(lane); lanes.push(lane); // Target zone var target = LK.getAsset('target', { anchorX: 0.5, anchorY: 0.5, x: laneX, y: TARGET_Y, width: LANE_WIDTH, height: TARGET_HEIGHT // Now uses the updated, larger TARGET_HEIGHT }); game.addChild(target); targets.push(target); } // --- Song Data (Slower, Single Note Demo Song) --- // Each note: {lane: 0-3, time: tick when note should reach target} // Lower BPM for slower note frequency var bpm = 60; var ticksPerBeat = 60 * 60 / bpm; // 60fps // Notes come one by one, spaced far apart, alternating lanes var songNotes = [{ lane: 0, time: 60 }, { lane: 1, time: 180 }, { lane: 2, time: 300 }, { lane: 3, time: 420 }, { lane: 0, time: 540 }, { lane: 1, time: 660 }, { lane: 2, time: 780 }, { lane: 3, time: 900 }, { lane: 0, time: 1020 }, { lane: 1, time: 1140 }, { lane: 2, time: 1260 }, { lane: 3, time: 1380 }]; // How many ticks before target to spawn note (so it falls from top to target in time) // Increase travel time for slower falling notes var NOTE_TRAVEL_TICKS = 180; // 3 seconds at 60fps // --- Helper Functions --- function getLaneX(laneIdx) { return LANE_START_X + laneIdx * (LANE_WIDTH + LANE_SPACING); } // --- Game Logic --- // Start song/music function startSong() { if (songStarted) return; songStarted = true; LK.playMusic('song1'); songTicks = 0; noteIndex = 0; score = 0; combo = 0; maxCombo = 0; misses = 0; songEnded = false; scoreTxt.setText('0'); comboTxt.setText(''); missTxt.setText(''); notes.length = 0; } // End song/game function endSong(win) { if (songEnded) return; songEnded = true; LK.stopMusic(); if (win) { LK.showYouWin(); } else { LK.showGameOver(); } } // --- Input Handling --- game.down = function (x, y, obj) { // Only allow input if song is running if (!songStarted || songEnded) return; // Find which lane was tapped for (var i = 0; i < NUM_LANES; i++) { var laneX = getLaneX(i); var minX = laneX - LANE_WIDTH / 2; var maxX = laneX + LANE_WIDTH / 2; if (x >= minX && x <= maxX) { // Check for a hittable note in this lane var hit = false; for (var j = 0; j < notes.length; j++) { var note = notes[j]; if (note.lane !== i || note.hit || note.missed) continue; // If note is within hit window (±TARGET_HEIGHT/2) var dy = Math.abs(note.y - TARGET_Y); // Make the hit window slightly more generous to match the larger target if (dy <= TARGET_HEIGHT / 2 + NOTE_HEIGHT / 2) { // Hit! note.onHit(); hit = true; score += 100; combo += 1; if (combo > maxCombo) maxCombo = combo; scoreTxt.setText(score + ''); comboTxt.setText(combo > 1 ? combo + ' Combo!' : ''); LK.getSound('tap').play(); break; } } if (!hit) { // Missed tap (no note in window) combo = 0; misses += 1; comboTxt.setText(''); missTxt.setText('Misses: ' + misses); LK.getSound('miss').play({ fade: { start: 1, end: 0, duration: 2000 } }); // Flash lane red LK.effects.flashObject(targets[i], 0xff0000, 200); if (misses >= maxMisses) { endSong(false); } } break; } } }; // --- Main Game Loop --- game.update = function () { if (!songStarted || songEnded) return; songTicks += 1; // Spawn notes as needed while (noteIndex < songNotes.length) { var noteData = songNotes[noteIndex]; if (noteData.time - NOTE_TRAVEL_TICKS <= songTicks) { // Spawn note var note = new Note(); note.setLane(noteData.lane); note.x = getLaneX(noteData.lane); note.y = -NOTE_HEIGHT / 2; note.speed = (TARGET_Y + NOTE_HEIGHT / 2) / NOTE_TRAVEL_TICKS; note.time = noteData.time; note.spawned = true; notes.push(note); game.addChild(note); noteIndex += 1; } else { break; } } // Update notes for (var i = notes.length - 1; i >= 0; i--) { var note = notes[i]; note.update(); // If note reached target zone and not hit, mark as missed if (!note.hit && !note.missed && note.y >= TARGET_Y + TARGET_HEIGHT / 2) { note.onMiss(); combo = 0; misses += 1; comboTxt.setText(''); missTxt.setText('Misses: ' + misses); LK.getSound('miss').play({ fade: { start: 1, end: 0, duration: 2000 } }); LK.effects.flashObject(targets[note.lane], 0xff0000, 200); if (misses >= maxMisses) { endSong(false); } } // Remove destroyed notes if (note.destroyed) { notes.splice(i, 1); } } // End song if all notes are done and no more on screen if (noteIndex >= songNotes.length && notes.length === 0) { endSong(true); } }; // --- Start the game --- startSong();
===================================================================
--- original.js
+++ change.js
@@ -50,9 +50,15 @@
// Called when note is missed
self.onMiss = function () {
if (self.hit || self.missed) return;
self.missed = true;
- LK.getSound('miss').play();
+ LK.getSound('miss').play({
+ fade: {
+ start: 1,
+ end: 0,
+ duration: 2000
+ }
+ });
tween(self, {
alpha: 0
}, {
duration: 200,
@@ -264,9 +270,15 @@
combo = 0;
misses += 1;
comboTxt.setText('');
missTxt.setText('Misses: ' + misses);
- LK.getSound('miss').play();
+ LK.getSound('miss').play({
+ fade: {
+ start: 1,
+ end: 0,
+ duration: 2000
+ }
+ });
// Flash lane red
LK.effects.flashObject(targets[i], 0xff0000, 200);
if (misses >= maxMisses) {
endSong(false);
@@ -309,9 +321,15 @@
combo = 0;
misses += 1;
comboTxt.setText('');
missTxt.setText('Misses: ' + misses);
- LK.getSound('miss').play();
+ LK.getSound('miss').play({
+ fade: {
+ start: 1,
+ end: 0,
+ duration: 2000
+ }
+ });
LK.effects.flashObject(targets[note.lane], 0xff0000, 200);
if (misses >= maxMisses) {
endSong(false);
}