User prompt
Nota basma yerleri daha büyük olsun.
User prompt
Oyunda misses 10 olunca kaybetme olmasın.
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: 1000
}
});
tween(self, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// 4 note lanes, each with a different color for clarity
// --- Game Constants ---
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 (Random Infinite Notes) ---
// Each note: {lane: 0-3, time: tick when note should reach target}
// We'll generate notes on the fly, at random lanes and random intervals
var bpm = 60;
var ticksPerBeat = 60 * 60 / bpm; // 60fps
var NOTE_TRAVEL_TICKS = 180; // 3 seconds at 60fps
// Infinite random note generator state
var nextNoteTick = 60; // When the next note should appear (in songTicks)
function getRandomLane() {
return Math.floor(Math.random() * NUM_LANES);
}
function getRandomInterval() {
// Random interval between notes: 0.5x to 1.5x of ticksPerBeat
return Math.floor(ticksPerBeat * (0.5 + Math.random()));
}
// --- 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();
// No win or game over, just stop music and mark as ended
}
// --- 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: 1000
}
});
// Flash lane red
LK.effects.flashObject(targets[i], 0xff0000, 200);
if (misses >= maxMisses) {
// No game over, just keep going
}
}
break;
}
}
};
// --- Main Game Loop ---
game.update = function () {
if (!songStarted || songEnded) return;
songTicks += 1;
// Spawn notes as needed (random, infinite)
while (songTicks >= nextNoteTick - NOTE_TRAVEL_TICKS) {
var lane = getRandomLane();
var noteTime = nextNoteTick;
var note = new Note();
note.setLane(lane);
note.x = getLaneX(lane);
note.y = -NOTE_HEIGHT / 2;
note.speed = (TARGET_Y + NOTE_HEIGHT / 2) / NOTE_TRAVEL_TICKS;
note.time = noteTime;
note.spawned = true;
notes.push(note);
game.addChild(note);
// Schedule next note
nextNoteTick += getRandomInterval();
}
// 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: 1000
}
});
LK.effects.flashObject(targets[note.lane], 0xff0000, 200);
if (misses >= maxMisses) {
// No game over, just keep going
}
}
// Remove destroyed notes
if (note.destroyed) {
notes.splice(i, 1);
}
}
// No win condition, keep game running
};
// --- Start the game ---
startSong(); ===================================================================
--- original.js
+++ change.js
@@ -245,9 +245,9 @@
});
// Flash lane red
LK.effects.flashObject(targets[i], 0xff0000, 200);
if (misses >= maxMisses) {
- endSong(false);
+ // No game over, just keep going
}
}
break;
}