Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'stringify')' in or related to this line: 'console.log("Swipe BBox:", JSON.stringify(swipeBoundingBox));' Line Number: 497
Code edit (6 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'stringify')' in or related to this line: 'console.log("Swipe BBox:", JSON.stringify(swipeBoundingBox));' Line Number: 497
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Graphics is not a constructor' in or related to this line: 'var hitZoneLine = new Graphics();' Line Number: 242
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: LK.getTime is not a function' in or related to this line: 'var now = LK.getTime();' Line Number: 535
User prompt
Please fix the bug: 'LK.getTime is not a function' in or related to this line: 'gameStartTime = LK.getTime();' Line Number: 549
Code edit (1 edits merged)
Please save this source code
User prompt
Beat Swipe: Rhythm Saber
Initial prompt
Create a 2D rhythm game framework inspired by Beat Saber. Game mechanics: - Notes (circles or shapes) appear far away and grow in size as they "approach" the player, simulating a forward motion toward the screen. - There are 3 types of notes: 1. Tap notes — the player must click exactly when the note reaches maximum size. 2. Swipe notes — the player must perform a quick swipe with the mouse through the note in a given direction (left, right, up, down). 3. Trap notes — these must be avoided entirely. Clicking or swiping them results in a combo break. - Notes appear at specific times and types defined in an array. Controls: - Mouse only. Recognize: - Clicks (onMouseDown + release timing). - Swipes (track onMouseDown → onMouseUp direction and distance). Scoring: - Perfect timing (±0.1 sec) gives max points. - Good timing (±0.3 sec) gives half points. - Missed or incorrect interaction resets combo. - Trap interaction resets combo too. Other features: - Notes scale up as they approach to simulate perspective. - Show combo counter and score. - Simple placeholder graphics and dark background are fine. - Music and visuals will be added manually later. Code structure must clearly separate: - Note spawn logic. - Input detection (click + swipe). - Timing window checks. - Scoring and combo logic. Use simple assets for now (colored shapes). Add comments to explain functions.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Note = Container.expand(function (noteType, swipeDir, targetHitTimeFull, centerXVal) {
var self = Container.call(this);
self.noteType = noteType || 'tap';
self.swipeDir = swipeDir || null;
self.targetHitTime = targetHitTimeFull;
self.visualSpawnTime = self.targetHitTime - noteTravelTime;
self.hit = false;
self.judged = false;
self.scaleStart = 0.3;
self.scaleEnd = 1.2;
self.centerX = centerXVal;
self.centerY = 1800;
self.startY = 600;
self.noteAsset = null;
self.isWiderSwipePart = false; // Flag for wider swipe rendering if needed later
// Store original columnIndex if available, for potential debugging or advanced logic
if (this.mapData && this.mapData.originalColumnHint !== undefined) {
self.originalColumnHint = this.mapData.originalColumnHint;
}
if (self.noteType === 'tap') {
self.noteAsset = self.attachAsset('tapNote', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.noteType === 'swipe') {
self.noteAsset = self.attachAsset('swipeNote', {
anchorX: 0.5,
anchorY: 0.5
});
if (self.swipeDir) {
var arrow = new Text2('', {
size: 80,
fill: 0xFFFFFF
});
arrow.anchor.set(0.5, 0.5);
if (self.swipeDir === 'left') {
arrow.setText('←');
} else if (self.swipeDir === 'right') {
arrow.setText('→');
} else if (self.swipeDir === 'up') {
arrow.setText('↑');
} else if (self.swipeDir === 'down') {
arrow.setText('↓');
}
self.addChild(arrow);
self.arrow = arrow;
}
} else if (self.noteType === 'trap') {
self.noteAsset = self.attachAsset('trapNote', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.alpha = 0;
self.showHitFeedback = function (result) {
var feedback = LK.getAsset('hitFeedback', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 0.7,
scaleY: 0.7,
alpha: 0.7
});
if (result === 'perfect') {
feedback.tint = 0xffff00;
} else if (result === 'good') {
feedback.tint = 0x00ff00;
} else {
feedback.tint = 0xff0000;
}
self.addChild(feedback);
tween(feedback, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 350,
easing: tween.easeOut,
onFinish: function onFinish() {
if (feedback.parent) {
feedback.destroy();
}
}
});
};
self.update = function () {
var now = Date.now();
if (self.judged) {
// If judged (hit or missed), it might still be moving for a bit
if (now > self.targetHitTime + 500) {// Time after hit/miss to be fully removed by removeOldNotes
// This note is done, removeOldNotes will handle it.
// If it was hit, its alpha might be 0 from feedback animation.
// If it was missed and had flash, it's visible.
// We can explicitly hide it here if we want it to disappear sooner than removeOldNotes.
// self.alpha = 0; // Opcjonalnie, aby szybciej zniknęła po ocenie
}
// Allow it to continue moving based on original trajectory if needed for visual effect
// For simplicity, if judged, we mostly let removeOldNotes handle it.
// However, if we want it to continue moving PAST the hit line visibly:
if (this.alpha > 0) {
// Only update position if visible
var elapsedTimeSinceSpawn = now - self.visualSpawnTime;
var currentProgress = elapsedTimeSinceSpawn / noteTravelTime;
// No clamping progress to 1 here, so it can go beyond
self.x = self.centerX;
self.y = self.startY + (self.centerY - self.startY) * currentProgress;
// Keep scale at max after passing hit line
var currentScale = currentProgress >= 1 ? self.scaleEnd : self.scaleStart + (self.scaleEnd - self.scaleStart) * currentProgress;
self.scale.x = Math.max(0.01, currentScale);
self.scale.y = Math.max(0.01, currentScale);
}
return;
}
if (now < self.visualSpawnTime) {
self.alpha = 0;
return;
}
if (self.alpha === 0 && !self.judged) {
self.alpha = 1;
}
var elapsedTimeSinceSpawn = now - self.visualSpawnTime;
var progress = elapsedTimeSinceSpawn / noteTravelTime;
// Notatka leci dalej, więc progress może być > 1
// Nie ograniczamy już progress do 1 tutaj dla pozycji i skali
// Skala osiąga self.scaleEnd przy progress = 1 i tak pozostaje
var scale;
if (progress >= 1) {
scale = self.scaleEnd;
} else if (progress < 0) {
// Powinno być obsłużone przez visualSpawnTime check, ale dla pewności
scale = self.scaleStart;
progress = 0; // Clamp progress for position if it was somehow negative
} else {
scale = self.scaleStart + (self.scaleEnd - self.scaleStart) * progress;
}
self.scale.x = Math.max(0.01, scale);
self.scale.y = Math.max(0.01, scale);
self.x = self.centerX;
self.y = self.startY + (self.centerY - self.startY) * progress; // Pozwalamy Y iść dalej
// Oznacz jako miss, jeśli nie została oceniona i minął czas + okno tolerancji
if (!self.judged && now > self.targetHitTime + hitWindowGood) {
self.judged = true; // Oznaczona jako oceniona (w tym przypadku jako miss)
if (self.noteType !== 'trap') {
game.onNoteMiss(self); // Wywołaj logikę miss
}
// Notatka będzie dalej widoczna i usuwana przez removeOldNotes
}
};
self.isInHitWindow = function () {
var now = Date.now();
var dt = Math.abs(now - self.targetHitTime);
return dt <= hitWindowGood;
};
self.getHitAccuracy = function () {
var now = Date.now();
var dt = Math.abs(now - self.targetHitTime);
if (dt <= hitWindowPerfect) {
return 'perfect';
}
if (dt <= hitWindowGood) {
return 'good';
}
return 'miss';
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181828
});
/****
* Game Code
****/
var gameScreenWidth = 2048;
var playfieldWidth = 1408;
var playfieldStartX = (gameScreenWidth - playfieldWidth) / 2;
var NUM_COLUMNS = 4;
var columnWidth = playfieldWidth / NUM_COLUMNS;
var columnCenterXs = [];
for (var i = 0; i < NUM_COLUMNS; i++) {
columnCenterXs.push(playfieldStartX + i * columnWidth + columnWidth / 2);
}
var SWIPE_NOTE_WIDTH = 160;
// Function to process raw rhythm map data
function processRawRhythmMap(rawMapData, songKeyForLogging) {
console.log("Processing raw map for: " + songKeyForLogging + " with " + rawMapData.length + " initial notes.");
var processedMap = [];
// Manual deep copy for an array of simple objects
var tempMap = [];
for (var k = 0; k < rawMapData.length; k++) {
var originalNote = rawMapData[k];
var copiedNote = {};
for (var key in originalNote) {
if (originalNote.hasOwnProperty(key)) {
copiedNote[key] = originalNote[key];
}
}
tempMap.push(copiedNote);
}
// 1. Convert diagonal swipes and normalize directions
for (var i = 0; i < tempMap.length; i++) {
var note = tempMap[i];
if (note.type === 'swipe' && note.swipeDir) {
var dir = note.swipeDir.toLowerCase();
if (dir.includes('right')) {
note.swipeDir = 'right';
} else if (dir.includes('left')) {
note.swipeDir = 'left';
} else if (dir.includes('up')) {
note.swipeDir = 'up';
} else if (dir.includes('down')) {
note.swipeDir = 'down';
}
}
}
var timeGroupedNotes = {};
tempMap.forEach(function (note) {
if (!timeGroupedNotes[note.time]) {
timeGroupedNotes[note.time] = [];
}
timeGroupedNotes[note.time].push(note);
});
var finalMapNotes = [];
var sortedTimes = Object.keys(timeGroupedNotes).map(Number).sort(function (a, b) {
return a - b;
});
for (var tIdx = 0; tIdx < sortedTimes.length; tIdx++) {
var time = sortedTimes[tIdx];
var notesAtThisTime = timeGroupedNotes[time];
var notesToKeepAtThisTime = [];
var processedForWiderSwipeConversion = []; // Keep track of notes converted from vertical pairs
var colsWithVerticalSwipes = [null, null, null, null];
notesAtThisTime.forEach(function (note) {
if (note.type === 'swipe' && (note.swipeDir === 'up' || note.swipeDir === 'down')) {
if (note.columnIndex >= 0 && note.columnIndex < NUM_COLUMNS) {
// Only add if not already part of a wider swipe conversion that happened
var alreadyConverted = false;
for (var convIdx = 0; convIdx < processedForWiderSwipeConversion.length; convIdx++) {
if (processedForWiderSwipeConversion[convIdx].originalTime === note.time && processedForWiderSwipeConversion[convIdx].originalColumn === note.columnIndex) {
alreadyConverted = true;
break;
}
}
if (!alreadyConverted) {
colsWithVerticalSwipes[note.columnIndex] = note.swipeDir;
}
}
}
});
for (var c = 0; c < NUM_COLUMNS - 1; c++) {
if (colsWithVerticalSwipes[c] && colsWithVerticalSwipes[c + 1] && colsWithVerticalSwipes[c] === colsWithVerticalSwipes[c + 1]) {
var randomHorizontalDir = Math.random() < 0.5 ? 'left' : 'right';
var pairCenterX = (columnCenterXs[c] + columnCenterXs[c + 1]) / 2;
notesToKeepAtThisTime.push({
time: time,
type: 'swipe',
swipeDir: randomHorizontalDir,
partOfWiderSwipe: 'leftHalf',
widerSwipePairCenterX: pairCenterX,
originalColumnHint: c
});
notesToKeepAtThisTime.push({
time: time,
type: 'swipe',
swipeDir: randomHorizontalDir,
partOfWiderSwipe: 'rightHalf',
widerSwipePairCenterX: pairCenterX,
originalColumnHint: c + 1
});
// Add to a temporary list to mark them as "used" by this conversion
processedForWiderSwipeConversion.push({
originalTime: time,
originalColumn: c
});
processedForWiderSwipeConversion.push({
originalTime: time,
originalColumn: c + 1
});
colsWithVerticalSwipes[c] = null;
colsWithVerticalSwipes[c + 1] = null;
c++;
}
}
notesAtThisTime.forEach(function (note) {
var wasConverted = false;
for (var convIdx = 0; convIdx < processedForWiderSwipeConversion.length; convIdx++) {
if (processedForWiderSwipeConversion[convIdx].originalTime === note.time && processedForWiderSwipeConversion[convIdx].originalColumn === note.columnIndex && (note.swipeDir === 'up' || note.swipeDir === 'down')) {
// Check if it was one of the vertical notes
wasConverted = true;
break;
}
}
if (!wasConverted) {
notesToKeepAtThisTime.push(note);
}
});
var horizontalWiderSwipePairs = {};
var notesForFinalProcessing = [];
// Filter out duplicates before further processing this time slot's notes
var uniqueNotesAtThisTime = [];
var seenNotesKeysAtThisTime = {};
notesToKeepAtThisTime.forEach(function (note) {
var key = "" + note.type + "_" + (note.columnIndex !== undefined ? note.columnIndex : note.partOfWiderSwipe ? note.widerSwipePairCenterX + note.partOfWiderSwipe : '') + "_" + (note.swipeDir || '');
if (!seenNotesKeysAtThisTime[key]) {
uniqueNotesAtThisTime.push(note);
seenNotesKeysAtThisTime[key] = true;
}
});
uniqueNotesAtThisTime.sort(function (a, b) {
// Sort by original column hint if available, or column index, or widerSwipePairCenterX
var valA = a.originalColumnHint !== undefined ? a.originalColumnHint : a.columnIndex !== undefined ? a.columnIndex : a.widerSwipePairCenterX || 0;
var valB = b.originalColumnHint !== undefined ? b.originalColumnHint : b.columnIndex !== undefined ? b.columnIndex : b.widerSwipePairCenterX || 0;
return valA - valB;
});
for (var nIdx = 0; nIdx < uniqueNotesAtThisTime.length; nIdx++) {
var note = uniqueNotesAtThisTime[nIdx];
if (note.partOfWiderSwipe) {
notesForFinalProcessing.push(note);
continue;
}
var potentialPartner = null;
if (nIdx + 1 < uniqueNotesAtThisTime.length) {
potentialPartner = uniqueNotesAtThisTime[nIdx + 1];
}
if (note.type === 'swipe' && (note.swipeDir === 'left' || note.swipeDir === 'right') && potentialPartner && potentialPartner.type === 'swipe' && potentialPartner.time === note.time &&
// Ensure same time for partner
potentialPartner.swipeDir === note.swipeDir && potentialPartner.columnIndex === note.columnIndex + 1) {
var pairCenterX = (columnCenterXs[note.columnIndex] + columnCenterXs[potentialPartner.columnIndex]) / 2;
notesForFinalProcessing.push({
time: note.time,
type: 'swipe',
swipeDir: note.swipeDir,
partOfWiderSwipe: 'leftHalf',
widerSwipePairCenterX: pairCenterX,
originalColumnHint: note.columnIndex
});
notesForFinalProcessing.push({
time: potentialPartner.time,
type: 'swipe',
swipeDir: potentialPartner.swipeDir,
partOfWiderSwipe: 'rightHalf',
widerSwipePairCenterX: pairCenterX,
originalColumnHint: potentialPartner.columnIndex
});
nIdx++;
} else {
notesForFinalProcessing.push(note);
}
}
finalMapNotes.push.apply(finalMapNotes, notesForFinalProcessing);
}
var uniqueNotesOverall = [];
var seenNotesOverall = {};
finalMapNotes.sort(function (a, b) {
return a.time - b.time;
});
finalMapNotes.forEach(function (note) {
var cX;
var keyPartForColumn;
if (note.partOfWiderSwipe) {
// For wider swipe parts, their exact X is calculated, so use that for uniqueness.
// Also include which half it is to differentiate parts of the same pair.
cX = note.widerSwipePairCenterX + (note.partOfWiderSwipe === 'leftHalf' ? -(SWIPE_NOTE_WIDTH / 2) : SWIPE_NOTE_WIDTH / 2);
keyPartForColumn = "pC" + note.widerSwipePairCenterX + "h" + (note.partOfWiderSwipe === 'leftHalf' ? 'L' : 'R');
} else if (note.columnIndex !== undefined) {
cX = columnCenterXs[note.columnIndex]; // Should exist if columnIndex is valid
keyPartForColumn = "c" + note.columnIndex;
} else {
// Should not happen if map is well-formed by this stage
cX = gameScreenWidth / 2;
keyPartForColumn = "cX" + cX;
}
var key = "" + note.time + "_" + note.type + "_" + keyPartForColumn + "_" + (note.swipeDir || '');
if (!seenNotesOverall[key]) {
uniqueNotesOverall.push(note);
seenNotesOverall[key] = true;
} else {
// console.log("Filtered final duplicate note: " + key);
}
});
console.log("Processed map for: " + songKeyForLogging + " FINALLY contains " + uniqueNotesOverall.length + " notes.");
return uniqueNotesOverall;
}
var allSongData = {
"defaultTestTrack": {
// Kept for basic testing if needed
musicAsset: null,
rawRhythmMap: [
// Now stores raw map, will be processed by loadSong
{
time: 1000,
type: 'tap',
columnIndex: 0
}, {
time: 1800,
type: 'tap',
columnIndex: 1
}, {
time: 2600,
type: 'swipe',
swipeDir: 'left',
columnIndex: 2
}, {
time: 3400,
type: 'tap',
columnIndex: 3
}, {
time: 4200,
type: 'swipe',
swipeDir: 'right',
columnIndex: 0
}, {
time: 5000,
type: 'trap',
columnIndex: 1
}, {
time: 5800,
type: 'tap',
columnIndex: 2
}, {
time: 6600,
type: 'swipe',
swipeDir: 'right',
// This will become widerSwipe
columnIndex: 1 // Original column for left part of potential pair
}, {
time: 6600,
type: 'swipe',
swipeDir: 'right',
columnIndex: 2 // Original column for right part of potential pair
}, {
time: 7400,
type: 'tap',
columnIndex: 0
}]
},
"test3": {
// Your map for test3
musicAsset: "test3",
// Assuming this is the asset name in Upit
rawRhythmMap: [
// Paste the content of rhythmMap_Expert.js here
{
"time": 21558,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 21558,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted to horizontal wider
{
"time": 24959,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 24959,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
},
// Will be converted to horizontal wider
{
"time": 28480,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 30578,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 34620,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 36018,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 42161,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 42161,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 44799,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 46580,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 48340,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 48340,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
},
// Simultaneous, different dirs, adjacent - will remain separate swipes
{
"time": 50099,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 50099,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Simultaneous, different dirs, adjacent - will remain separate swipes
{
"time": 51879,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 51879,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
},
// Simultaneous, different dirs, different columns - separate
{
"time": 53621,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 53621,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 57139,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
},
// Removed duplicate: {"time": 57139, "type": "swipe", "swipeDir": "left", "columnIndex": 0},
{
"time": 58921,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 60699,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 62460,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
},
// Removed duplicate: {"time": 62460, "type": "swipe", "swipeDir": "right", "columnIndex": 3},
{
"time": 64219,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 65141,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 66000,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
},
// Removed duplicate: {"time": 66000, "type": "swipe", "swipeDir": "left", "columnIndex": 0},
{
"time": 67761,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 67761,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 71280,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 71280,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 72301,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 73039,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 73518,
"type": "swipe",
"swipeDir": "down-right",
"columnIndex": 3
},
// Becomes right
{
"time": 73939,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 74421,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 74421,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
},
// Will be converted (up -> random L/R wider)
{
"time": 80100,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 81861,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 83638,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 85399,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 87160,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 88920,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 88920,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 3
},
// Will be converted
{
"time": 90700,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 90700,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
},
// Will be converted
{
"time": 92460,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 92460,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
},
// Will be converted
{
"time": 94218,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 95978,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 97739,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 99521,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 101278,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 101278,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
},
// Will be converted
{
"time": 103041,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 103041,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
},
// Will be converted
{
"time": 104800,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 104800,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 106578,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 106578,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
},
// Will be converted
{
"time": 109858,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 109858,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 112201,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 112201,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
},
// Not adjacent, separate
{
"time": 113620,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 113620,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 116918,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 116918,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 118918,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 118918,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
},
// Will be converted
{
"time": 119798,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 119798,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
},
// Not adjacent
{
"time": 123359,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 123359,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 3
},
// Will be converted
{
"time": 124238,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 124238,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
},
// Will be converted
{
"time": 125138,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 125138,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
},
// Will be converted
{
"time": 126000,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 126000,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
},
// Will be converted
{
"time": 126320,
"type": "tap",
"columnIndex": 2
}, {
"time": 127158,
"type": "tap",
"columnIndex": 1
}, {
"time": 128200,
"type": "tap",
"columnIndex": 1
}, {
"time": 128200,
"type": "tap",
"columnIndex": 2
},
// Simultaneous taps in adjacent columns
{
"time": 130318,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 130318,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 136579,
"type": "tap",
"columnIndex": 1
}, {
"time": 136579,
"type": "tap",
"columnIndex": 2
}, {
"time": 137460,
"type": "tap",
"columnIndex": 1
}, {
"time": 137460,
"type": "tap",
"columnIndex": 2
}, {
"time": 137901,
"type": "tap",
"columnIndex": 1
}, {
"time": 137901,
"type": "tap",
"columnIndex": 2
}, {
"time": 138340,
"type": "tap",
"columnIndex": 1
}, {
"time": 138340,
"type": "tap",
"columnIndex": 2
}, {
"time": 138798,
"type": "tap",
"columnIndex": 1
}, {
"time": 138798,
"type": "tap",
"columnIndex": 2
}, {
"time": 139219,
"type": "tap",
"columnIndex": 1
}, {
"time": 139219,
"type": "tap",
"columnIndex": 2
}, {
"time": 139658,
"type": "tap",
"columnIndex": 1
}, {
"time": 139658,
"type": "tap",
"columnIndex": 2
}, {
"time": 140100,
"type": "tap",
"columnIndex": 1
}, {
"time": 140100,
"type": "tap",
"columnIndex": 2
}, {
"time": 140540,
"type": "tap",
"columnIndex": 1
}, {
"time": 140540,
"type": "tap",
"columnIndex": 2
}, {
"time": 140979,
"type": "tap",
"columnIndex": 1
}, {
"time": 140979,
"type": "tap",
"columnIndex": 2
}, {
"time": 141441,
"type": "tap",
"columnIndex": 1
}, {
"time": 141441,
"type": "tap",
"columnIndex": 2
}, {
"time": 141861,
"type": "tap",
"columnIndex": 1
}, {
"time": 141861,
"type": "tap",
"columnIndex": 2
}, {
"time": 143639,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 144081,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 144521,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 144959,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 145401,
"type": "swipe",
"swipeDir": "down-right",
"columnIndex": 2
},
// Becomes right
{
"time": 145839,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 3
}, {
"time": 146281,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 146281,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
},
// Will be converted
{
"time": 147160,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 147599,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 148039,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 148498,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 148921,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 149821,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 150681,
"type": "swipe",
"swipeDir": "down-right",
"columnIndex": 2
},
// Becomes right
{
"time": 150681,
"type": "swipe",
"swipeDir": "down-right",
"columnIndex": 3
},
// Becomes right, this will be a wider swipe right if they are adjacent after col mapping
{
"time": 151581,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 151581,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
},
// Will be converted
{
"time": 152459,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 3
}, {
"time": 152898,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 153339,
"type": "swipe",
"swipeDir": "up-left",
"columnIndex": 0
},
// Becomes left
{
"time": 153339,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 154221,
"type": "swipe",
"swipeDir": "down-right",
"columnIndex": 2
},
// Becomes right
{
"time": 154661,
"type": "swipe",
"swipeDir": "down-left",
"columnIndex": 1
},
// Becomes left
{
"time": 155099,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 155541,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 155979,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 155979,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
},
// Will be converted
{
"time": 156861,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 156861,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
},
// Will be converted
{
"time": 157739,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 158179,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 158640,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 159081,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 159518,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 3
}, {
"time": 159960,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 160400,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 160400,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
},
// Will be converted
{
"time": 163941,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 163941,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 1
},
// Wider swipe left
{
"time": 164800,
"type": "tap",
"columnIndex": 1
}, {
"time": 164800,
"type": "tap",
"columnIndex": 2
}, {
"time": 166139,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 3
}, {
"time": 166580,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 167001,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 167439,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 167920,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 168399,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 168780,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 169220,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 169660,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 170101,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 2
}, {
"time": 170980,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 171420,
"type": "swipe",
"swipeDir": "down-left",
"columnIndex": 1
},
// Becomes left
{
"time": 171860,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 171860,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
},
// Will be converted
{
"time": 173178,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 173639,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 174501,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 174981,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 175418,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 175839,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 176278,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 176278,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 177160,
"type": "tap",
"columnIndex": 1
}, {
"time": 177160,
"type": "tap",
"columnIndex": 2
}, {
"time": 178941,
"type": "tap",
"columnIndex": 1
}, {
"time": 179380,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 179798,
"type": "tap",
"columnIndex": 1
}, {
"time": 180239,
"type": "tap",
"columnIndex": 2
}, {
"time": 180699,
"type": "tap",
"columnIndex": 1
}, {
"time": 181580,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 2
}, {
"time": 182018,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
},
// Wider swipe right
{
"time": 182901,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 183341,
"type": "tap",
"columnIndex": 1
}, {
"time": 183341,
"type": "tap",
"columnIndex": 2
}, {
"time": 184220,
"type": "tap",
"columnIndex": 1
}, {
"time": 184220,
"type": "tap",
"columnIndex": 2
}, {
"time": 185558,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 185979,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 186439,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 186879,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 187299,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 187740,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 188620,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 188620,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 189540,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 189961,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 190401,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 191280,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 191280,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 192159,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 192718,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 193041,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 193938,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 193938,
"type": "swipe",
"swipeDir": "right",
"columnIndex": 3
}, {
"time": 194358,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 194818,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 195678,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 195678,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
},
// Will be converted
{
"time": 196139,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 3
}, {
"time": 196579,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 197018,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 197458,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 197458,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 198338,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 198781,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 199221,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 199221,
"type": "swipe",
"swipeDir": "down-left",
"columnIndex": 1
},
// Becomes left
{
"time": 200098,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 0
}, {
"time": 200098,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 201420,
"type": "swipe",
"swipeDir": "down-left",
"columnIndex": 1
},
// Becomes left
{
"time": 201858,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 0
}, {
"time": 202740,
"type": "swipe",
"swipeDir": "down-right",
"columnIndex": 3
},
// Becomes right
{
"time": 204058,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 204499,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 3
}, {
"time": 205401,
"type": "swipe",
"swipeDir": "up-left",
"columnIndex": 0
},
// Becomes left
{
"time": 205401,
"type": "swipe",
"swipeDir": "down-left",
"columnIndex": 2
},
// Becomes left
{
"time": 206279,
"type": "swipe",
"swipeDir": "down-right",
"columnIndex": 1
},
// Becomes right
{
"time": 206279,
"type": "swipe",
"swipeDir": "up-right",
"columnIndex": 3
},
// Becomes right
{
"time": 207160,
"type": "swipe",
"swipeDir": "left",
"columnIndex": 0
}, {
"time": 207620,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 2
}, {
"time": 208038,
"type": "swipe",
"swipeDir": "down",
"columnIndex": 1
}, {
"time": 208478,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 2
}, {
"time": 208919,
"type": "swipe",
"swipeDir": "up",
"columnIndex": 1
}, {
"time": 209799,
"type": "tap",
"columnIndex": 1
}, {
"time": 209799,
"type": "tap",
"columnIndex": 2
}, {
"time": 210698,
"type": "tap",
"columnIndex": 0
}, {
"time": 211140,
"type": "tap",
"columnIndex": 3
}, {
"time": 211578,
"type": "tap",
"columnIndex": 2
}, {
"time": 212018,
"type": "tap",
"columnIndex": 1
}, {
"time": 212459,
"type": "tap",
"columnIndex": 0
}, {
"time": 213341,
"type": "tap",
"columnIndex": 3
}, {
"time": 213778,
"type": "tap",
"columnIndex": 1
}, {
"time": 214221,
"type": "tap",
"columnIndex": 3
}, {
"time": 215121,
"type": "tap",
"columnIndex": 0
}, {
"time": 215541,
"type": "tap",
"columnIndex": 3
}, {
"time": 215978,
"type": "tap",
"columnIndex": 1
}, {
"time": 216861,
"type": "tap",
"columnIndex": 2
}, {
"time": 217758,
"type": "tap",
"columnIndex": 2
}, {
"time": 218179,
"type": "tap",
"columnIndex": 3
}, {
"time": 218639,
"type": "tap",
"columnIndex": 1
}, {
"time": 219518,
"type": "tap",
"columnIndex": 1
}, {
"time": 219518,
"type": "tap",
"columnIndex": 2
}, {
"time": 220400,
"type": "tap",
"columnIndex": 1
}]
}
// Placeholder for test1 and test2
// "test1_raw": { musicAsset: "test1", rawRhythmMap: [ /* ... map data ... */ ] },
// "test2_raw": { musicAsset: "test2", rawRhythmMap: [ /* ... map data ... */ ] }
};
var currentActiveRhythmMap = null;
var currentMusic = null;
var noteTravelTime = 2000;
var hitWindowPerfect = 120;
var hitWindowGood = 260;
var MIN_SWIPE_DISTANCE = 60;
var notes = [];
var nextNoteIdx = 0;
var gameStartTime = 0;
var score = 0;
var combo = 0;
var maxCombo = 0;
var swipeStart = null;
var inputLocked = false;
var scoreTxt = new Text2('Score: 0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = gameScreenWidth / 2;
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
var comboTxt = new Text2('Combo: 0', {
size: 80,
fill: 0xFFFF00
});
comboTxt.anchor.set(0.5, 0);
comboTxt.x = gameScreenWidth / 2;
comboTxt.y = 130;
LK.gui.top.addChild(comboTxt);
var hitZoneY = 1800;
var hitZoneVisualWidth = playfieldWidth;
var hitZoneLine = LK.getAsset('lineAsset', {
anchorX: 0.5,
anchorY: 0.5,
x: gameScreenWidth / 2,
y: hitZoneY,
width: hitZoneVisualWidth,
height: 4,
alpha: 0.6
});
game.addChild(hitZoneLine);
function rectsIntersect(r1, r2) {
return !(r2.x > r1.x + r1.width || r2.x + r2.width < r1.x || r2.y > r1.y + r1.height || r2.y + r2.height < r1.y);
}
function resetGameState() {
notes.forEach(function (n) {
if (n && n.parent) {
n.destroy();
}
});
notes = [];
nextNoteIdx = 0;
score = 0;
combo = 0;
maxCombo = 0;
swipeStart = null;
inputLocked = false;
scoreTxt.setText('Score: 0');
comboTxt.setText('Combo: 0');
}
function loadSong(songKey) {
var songData = allSongData[songKey];
if (!songData || !songData.rawRhythmMap) {
// Check for rawRhythmMap
console.log("Error: Song data or rawRhythmMap not found for key: " + songKey);
if (allSongData["defaultTestTrack"] && allSongData["defaultTestTrack"].rawRhythmMap) {
songData = allSongData["defaultTestTrack"];
} else {
currentActiveRhythmMap = [];
return;
}
}
currentActiveRhythmMap = processRawRhythmMap(songData.rawRhythmMap, songKey); // Process the raw map
if (currentMusic && typeof currentMusic.stop === 'function') {
currentMusic.stop();
}
currentMusic = null;
if (songData.musicAsset) {
currentMusic = LK.getSound(songData.musicAsset);
if (currentMusic && typeof currentMusic.play === 'function') {
currentMusic.play();
console.log("Music asset for " + songKey + " would play here.");
} else {
console.log("Warning: Music asset '" + songData.musicAsset + "' not found or not playable.");
}
}
resetGameState();
nextNoteIdx = 0;
gameStartTime = Date.now();
console.log("Loaded and processed song: " + songKey);
}
function spawnNotes() {
var now = Date.now();
if (!currentActiveRhythmMap) {
return;
}
while (nextNoteIdx < currentActiveRhythmMap.length) {
var noteData = currentActiveRhythmMap[nextNoteIdx]; // Use processed map
var noteTargetHitTime = gameStartTime + noteData.time;
if (noteTargetHitTime - noteTravelTime <= now) {
var targetCenterX;
if (noteData.partOfWiderSwipe && noteData.widerSwipePairCenterX !== undefined) {
if (noteData.partOfWiderSwipe === 'leftHalf') {
targetCenterX = noteData.widerSwipePairCenterX - SWIPE_NOTE_WIDTH / 2;
} else if (noteData.partOfWiderSwipe === 'rightHalf') {
targetCenterX = noteData.widerSwipePairCenterX + SWIPE_NOTE_WIDTH / 2;
} else {
// Fallback if partOfWiderSwipe has unexpected value, use original column if available
targetCenterX = columnCenterXs[noteData.originalColumnHint !== undefined ? noteData.originalColumnHint : Math.floor(NUM_COLUMNS / 2)];
}
} else if (noteData.columnIndex !== undefined && noteData.columnIndex >= 0 && noteData.columnIndex < NUM_COLUMNS) {
targetCenterX = columnCenterXs[noteData.columnIndex];
} else {
targetCenterX = playfieldStartX + playfieldWidth / 2;
}
// Pass original noteData to Note constructor for potential debugging/reference if needed
var n = new Note(noteData.type, noteData.swipeDir, noteTargetHitTime, targetCenterX);
n.mapData = noteData; // Attach original map data to the note instance
if (noteData.partOfWiderSwipe) {
n.isWiderSwipePart = true;
}
n.alpha = 0;
notes.push(n);
game.addChild(n);
nextNoteIdx++;
} else {
break;
}
}
}
function removeOldNotes() {
var now = Date.now();
for (var i = notes.length - 1; i >= 0; i--) {
var n = notes[i];
var timeToRemoveAfterJudged = 700; // ms po targetHitTime dla ocenionych notatek
var timeToRemoveIfNotJudged = noteTravelTime / 2 + hitWindowGood + 500; // Dłuższy czas, jeśli nieoceniona, liczony od targetHitTime
if (n.judged && now > n.targetHitTime + timeToRemoveAfterJudged) {
if (n.parent) {
n.destroy();
}
notes.splice(i, 1);
} else if (!n.judged && now > n.targetHitTime + timeToRemoveIfNotJudged) {
if (n.noteType !== 'trap') {}
if (n.parent) {
n.destroy();
}
notes.splice(i, 1);
}
}
}
function findNoteAt(x, y, typeToFind) {
var now = Date.now();
var bestNote = null;
var smallestTimeDiff = hitWindowGood + 1;
for (var i = 0; i < notes.length; i++) {
var n = notes[i];
if (n.judged || n.noteType !== typeToFind) {
continue;
}
var timeDiff = Math.abs(now - n.targetHitTime);
if (timeDiff > hitWindowGood) {
continue;
}
var currentNoteAsset = n.noteAsset;
if (!currentNoteAsset) {
continue;
}
var currentNoteWidth = currentNoteAsset.width * n.scale.x;
var currentNoteHeight = currentNoteAsset.height * n.scale.y;
if (n.noteType === 'swipe') {
currentNoteWidth = SWIPE_NOTE_WIDTH * n.scale.x;
currentNoteHeight = SWIPE_NOTE_WIDTH * n.scale.y;
}
var dx = x - n.x;
var dy = y - n.y;
if (Math.abs(dx) <= currentNoteWidth / 2 && Math.abs(dy) <= currentNoteHeight / 2) {
if (timeDiff < smallestTimeDiff) {
bestNote = n;
smallestTimeDiff = timeDiff;
}
}
}
return bestNote;
}
function addScore(result) {
if (result === 'perfect') {
score += 100;
} else if (result === 'good') {
score += 50;
}
scoreTxt.setText('Score: ' + score);
}
function addCombo() {
combo += 1;
if (combo > maxCombo) {
maxCombo = combo;
}
comboTxt.setText('Combo: ' + combo);
}
function resetCombo() {
combo = 0;
comboTxt.setText('Combo: 0');
}
function checkGameEnd() {
if (currentActiveRhythmMap && nextNoteIdx >= currentActiveRhythmMap.length && notes.length === 0) {
LK.setTimeout(function () {
if (currentActiveRhythmMap && nextNoteIdx >= currentActiveRhythmMap.length && notes.length === 0) {
LK.showYouWin(); // Consider a more advanced game end screen later
}
}, 1000);
}
}
game.onNoteMiss = function (note) {
if (!note || note.judged) {
return;
}
note.judged = true;
note.showHitFeedback('miss');
resetCombo();
if (note.parent) {
LK.effects.flashObject(note, 0xff0000, 300);
}
};
game.down = function (x, y, obj) {
if (inputLocked) {
return;
}
swipeStart = {
x: x,
y: y,
time: Date.now()
};
var noteUnderCursor = findNoteAt(x, y, 'trap');
if (noteUnderCursor && !noteUnderCursor.judged && noteUnderCursor.isInHitWindow()) {
noteUnderCursor.judged = true;
noteUnderCursor.showHitFeedback('miss');
resetCombo();
LK.effects.flashScreen(0xff0000, 400);
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
}, 200);
return;
}
noteUnderCursor = findNoteAt(x, y, 'tap');
if (noteUnderCursor && !noteUnderCursor.judged && noteUnderCursor.isInHitWindow()) {
var result = noteUnderCursor.getHitAccuracy();
noteUnderCursor.judged = true;
noteUnderCursor.showHitFeedback(result);
if (result !== 'miss') {
addScore(result);
addCombo();
} else {
resetCombo();
}
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
}, 120);
return;
}
};
game.up = function (x, y, obj) {
if (inputLocked || !swipeStart) {
// console.log("Swipe Rejected: Input locked or no swipe start");
swipeStart = null;
return;
}
var swipeEndX = x;
var swipeEndY = y;
var swipeEndTime = Date.now();
var dx = swipeEndX - swipeStart.x;
var dy = swipeEndY - swipeStart.y;
var dist = Math.sqrt(dx * dx + dy * dy);
console.log("--- Swipe Action END ---");
console.log("Swipe Start (X,Y,Time): " + swipeStart.x + "," + swipeStart.y + "," + swipeStart.time);
console.log("Swipe End (X,Y,Time): " + swipeEndX + "," + swipeEndY + "," + swipeEndTime);
console.log("Swipe Delta (dX,dY,Dist): " + dx + "," + dy + "," + dist);
var potentialSwipe = dist >= MIN_SWIPE_DISTANCE;
var swipedNoteSuccessfully = false;
if (potentialSwipe) {
var detectedDir = null;
if (Math.abs(dx) > Math.abs(dy)) {
detectedDir = dx > 0 ? 'right' : 'left';
} else {
detectedDir = dy > 0 ? 'down' : 'up';
}
console.log("Potential Swipe. Detected Dir: " + detectedDir);
var swipeBoundingBox = {
x: Math.min(swipeStart.x, swipeEndX),
y: Math.min(swipeStart.y, swipeEndY),
width: Math.abs(dx),
height: Math.abs(dy)
};
console.log("Swipe BBox: x=" + swipeBoundingBox.x + ", y=" + swipeBoundingBox.y + ", w=" + swipeBoundingBox.width + ", h=" + swipeBoundingBox.height);
var notesHitThisSwipe = [];
for (var i = 0; i < notes.length; i++) {
var n = notes[i];
if (n.judged || n.noteType !== 'swipe') {
continue;
}
console.log("Checking Note Idx " + i + " (TargetTime: " + n.targetHitTime + ", Dir: " + n.swipeDir + ", X: " + n.x + ", Y: " + n.y + ", Scale: " + n.scale.x + ", Alpha: " + n.alpha + ")");
var overallSwipeTimeMatchesNote = false;
// Check if the note's target hit time falls within the swipe's duration, with tolerance
if (n.targetHitTime >= swipeStart.time - hitWindowGood && n.targetHitTime <= swipeEndTime + hitWindowGood) {
overallSwipeTimeMatchesNote = true;
}
// Also consider if the swipe itself (its start or end) happens within the note's broader hit window
// This helps for notes that should be hit AT the start or AT the end of a swipe.
if (!overallSwipeTimeMatchesNote) {
if (swipeStart.time >= n.targetHitTime - hitWindowGood && swipeStart.time <= n.targetHitTime + hitWindowGood || swipeEndTime >= n.targetHitTime - hitWindowGood && swipeEndTime <= n.targetHitTime + hitWindowGood) {
overallSwipeTimeMatchesNote = true;
}
}
console.log(" Note " + i + " - overallSwipeTimeMatchesNote: " + overallSwipeTimeMatchesNote);
if (!overallSwipeTimeMatchesNote) {
continue;
}
if (n.alpha === 0) {
console.log(" Note " + i + " - REJECTED (alpha is 0)");
continue;
}
var noteCurrentWidth = SWIPE_NOTE_WIDTH * n.scale.x;
var noteCurrentHeight = SWIPE_NOTE_WIDTH * n.scale.y;
var noteBoundingBox = {
x: n.x - noteCurrentWidth / 2,
y: n.y - noteCurrentHeight / 2,
width: noteCurrentWidth,
height: noteCurrentHeight
};
console.log(" Note " + i + " BBox: x=" + noteBoundingBox.x + ", y=" + noteBoundingBox.y + ", w=" + noteBoundingBox.width + ", h=" + noteBoundingBox.height);
var intersects = rectsIntersect(swipeBoundingBox, noteBoundingBox);
console.log(" Note " + i + " - rectsIntersect: " + intersects);
if (intersects) {
console.log(" Note " + i + " - Detected Dir: " + detectedDir + ", Note Dir: " + n.swipeDir);
if (detectedDir === n.swipeDir) {
var verticalProximity = Math.abs(n.y - n.centerY);
var verticalTolerance = noteCurrentHeight / 1.5; // How close to hit line note should be
console.log(" Note " + i + " - Vertical Proximity: " + verticalProximity + " (Tolerance: " + verticalTolerance + ")");
if (verticalProximity < verticalTolerance) {
console.log(" Note " + i + " - PASSED ALL CHECKS. Added to potential hits.");
notesHitThisSwipe.push(n);
} else {
console.log(" Note " + i + " - FAILED Vertical Proximity Check.");
}
} else {
console.log(" Note " + i + " - FAILED Direction Check.");
}
}
}
if (notesHitThisSwipe.length > 0) {
console.log("Processing " + notesHitThisSwipe.length + " notes initially hit by this swipe.");
notesHitThisSwipe.sort(function (a, b) {
var da = Math.abs(swipeEndTime - a.targetHitTime);
var db = Math.abs(swipeEndTime - b.targetHitTime);
return da - db;
});
var maxNotesToHitPerSwipe = 1;
if (notesHitThisSwipe.length > 0 && notesHitThisSwipe[0].isWiderSwipePart) {
// Check the best candidate
maxNotesToHitPerSwipe = 2;
}
var notesActuallyHitCount = 0;
for (var k = 0; k < notesHitThisSwipe.length && notesActuallyHitCount < maxNotesToHitPerSwipe; k++) {
var noteToJudge = notesHitThisSwipe[k];
if (noteToJudge.judged) {
continue;
}
if (notesActuallyHitCount === 1 && notesHitThisSwipe[0].isWiderSwipePart) {
if (!noteToJudge.isWiderSwipePart || noteToJudge.mapData.widerSwipePairCenterX !== notesHitThisSwipe[0].mapData.widerSwipePairCenterX || noteToJudge.mapData.partOfWiderSwipe === notesHitThisSwipe[0].mapData.partOfWiderSwipe) {
console.log(" Skipping note in wider swipe check - not matching pair for first hit note.");
continue;
}
}
var result = noteToJudge.getHitAccuracy();
console.log(" JUDGING Note Hit! Result: " + result + " for note at X=" + noteToJudge.x + ", Y=" + noteToJudge.y);
noteToJudge.judged = true;
noteToJudge.showHitFeedback(result);
if (result !== 'miss') {
addScore(result);
addCombo();
} else {
resetCombo();
}
swipedNoteSuccessfully = true;
notesActuallyHitCount++;
}
if (notesActuallyHitCount === 0 && notesHitThisSwipe.length > 0) {
console.log(" Notes were candidates, but none met final hit criteria (e.g. wider swipe pair logic).");
}
} else {
console.log("No notes candidates after iterating.");
}
} else {
console.log("Swipe too short (Dist: " + dist + ", Min: " + MIN_SWIPE_DISTANCE + ")");
}
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
}, 80);
swipeStart = null;
};
game.move = function (x, y, obj) {};
game.update = function () {
spawnNotes();
for (var i = 0; i < notes.length; i++) {
if (notes[i] && notes[i].update) {
notes[i].update();
}
}
removeOldNotes();
checkGameEnd();
};
// Load the specific song for testing
loadSong("test3");
// loadSong("defaultTestTrack"); // Możesz to odkomentować, aby załadować starą mapę testową ===================================================================
--- original.js
+++ change.js
@@ -5,9 +5,8 @@
/****
* Classes
****/
-// Visual width of swipeNote asset
var Note = Container.expand(function (noteType, swipeDir, targetHitTimeFull, centerXVal) {
var self = Container.call(this);
self.noteType = noteType || 'tap';
self.swipeDir = swipeDir || null;
@@ -20,8 +19,13 @@
self.centerX = centerXVal;
self.centerY = 1800;
self.startY = 600;
self.noteAsset = null;
+ self.isWiderSwipePart = false; // Flag for wider swipe rendering if needed later
+ // Store original columnIndex if available, for potential debugging or advanced logic
+ if (this.mapData && this.mapData.originalColumnHint !== undefined) {
+ self.originalColumnHint = this.mapData.originalColumnHint;
+ }
if (self.noteType === 'tap') {
self.noteAsset = self.attachAsset('tapNote', {
anchorX: 0.5,
anchorY: 0.5
@@ -72,9 +76,8 @@
feedback.tint = 0x00ff00;
} else {
feedback.tint = 0xff0000;
}
- // Ensure feedback is added to the note itself, so its position is relative
self.addChild(feedback);
tween(feedback, {
alpha: 0,
scaleX: 1.5,
@@ -90,8 +93,34 @@
});
};
self.update = function () {
var now = Date.now();
+ if (self.judged) {
+ // If judged (hit or missed), it might still be moving for a bit
+ if (now > self.targetHitTime + 500) {// Time after hit/miss to be fully removed by removeOldNotes
+ // This note is done, removeOldNotes will handle it.
+ // If it was hit, its alpha might be 0 from feedback animation.
+ // If it was missed and had flash, it's visible.
+ // We can explicitly hide it here if we want it to disappear sooner than removeOldNotes.
+ // self.alpha = 0; // Opcjonalnie, aby szybciej zniknęła po ocenie
+ }
+ // Allow it to continue moving based on original trajectory if needed for visual effect
+ // For simplicity, if judged, we mostly let removeOldNotes handle it.
+ // However, if we want it to continue moving PAST the hit line visibly:
+ if (this.alpha > 0) {
+ // Only update position if visible
+ var elapsedTimeSinceSpawn = now - self.visualSpawnTime;
+ var currentProgress = elapsedTimeSinceSpawn / noteTravelTime;
+ // No clamping progress to 1 here, so it can go beyond
+ self.x = self.centerX;
+ self.y = self.startY + (self.centerY - self.startY) * currentProgress;
+ // Keep scale at max after passing hit line
+ var currentScale = currentProgress >= 1 ? self.scaleEnd : self.scaleStart + (self.scaleEnd - self.scaleStart) * currentProgress;
+ self.scale.x = Math.max(0.01, currentScale);
+ self.scale.y = Math.max(0.01, currentScale);
+ }
+ return;
+ }
if (now < self.visualSpawnTime) {
self.alpha = 0;
return;
}
@@ -99,25 +128,32 @@
self.alpha = 1;
}
var elapsedTimeSinceSpawn = now - self.visualSpawnTime;
var progress = elapsedTimeSinceSpawn / noteTravelTime;
- if (progress < 0) {
- progress = 0;
+ // Notatka leci dalej, więc progress może być > 1
+ // Nie ograniczamy już progress do 1 tutaj dla pozycji i skali
+ // Skala osiąga self.scaleEnd przy progress = 1 i tak pozostaje
+ var scale;
+ if (progress >= 1) {
+ scale = self.scaleEnd;
+ } else if (progress < 0) {
+ // Powinno być obsłużone przez visualSpawnTime check, ale dla pewności
+ scale = self.scaleStart;
+ progress = 0; // Clamp progress for position if it was somehow negative
+ } else {
+ scale = self.scaleStart + (self.scaleEnd - self.scaleStart) * progress;
}
- if (progress > 1) {
- progress = 1;
- }
- var currentScale = self.scaleStart + (self.scaleEnd - self.scaleStart) * progress;
- // Ensure scale doesn't go to 0 or negative if times are weird
- self.scale.x = Math.max(0.01, currentScale);
- self.scale.y = Math.max(0.01, currentScale);
+ self.scale.x = Math.max(0.01, scale);
+ self.scale.y = Math.max(0.01, scale);
self.x = self.centerX;
- self.y = self.startY + (self.centerY - self.startY) * progress;
+ self.y = self.startY + (self.centerY - self.startY) * progress; // Pozwalamy Y iść dalej
+ // Oznacz jako miss, jeśli nie została oceniona i minął czas + okno tolerancji
if (!self.judged && now > self.targetHitTime + hitWindowGood) {
- self.judged = true;
+ self.judged = true; // Oznaczona jako oceniona (w tym przypadku jako miss)
if (self.noteType !== 'trap') {
- game.onNoteMiss(self);
+ game.onNoteMiss(self); // Wywołaj logikę miss
}
+ // Notatka będzie dalej widoczna i usuwana przez removeOldNotes
}
};
self.isInHitWindow = function () {
var now = Date.now();
@@ -148,104 +184,1610 @@
/****
* Game Code
****/
var gameScreenWidth = 2048;
+var playfieldWidth = 1408;
+var playfieldStartX = (gameScreenWidth - playfieldWidth) / 2;
var NUM_COLUMNS = 4;
-var columnWidth = gameScreenWidth / NUM_COLUMNS; // 512
+var columnWidth = playfieldWidth / NUM_COLUMNS;
var columnCenterXs = [];
for (var i = 0; i < NUM_COLUMNS; i++) {
- columnCenterXs.push(i * columnWidth + columnWidth / 2);
+ columnCenterXs.push(playfieldStartX + i * columnWidth + columnWidth / 2);
}
-// columnCenterXs will be [256, 768, 1280, 1792]
var SWIPE_NOTE_WIDTH = 160;
-var rhythmMap = [{
- time: 1000,
- type: 'tap',
- columnIndex: 0
-}, {
- time: 1800,
- type: 'tap',
- columnIndex: 1
-}, {
- time: 2600,
- type: 'swipe',
- swipeDir: 'left',
- columnIndex: 2
-}, {
- time: 3400,
- type: 'tap',
- columnIndex: 3
-}, {
- time: 4200,
- type: 'swipe',
- swipeDir: 'right',
- columnIndex: 0
-}, {
- time: 5000,
- type: 'trap',
- columnIndex: 1
-}, {
- time: 5800,
- type: 'tap',
- columnIndex: 2
-}, {
- // Example of a "wider swipe" (horizontal right)
- time: 6600,
- type: 'swipe',
- swipeDir: 'right',
- partOfWiderSwipe: 'leftHalf',
- widerSwipePairCenterX: (columnCenterXs[1] + columnCenterXs[2]) / 2
-}, {
- time: 6600,
- type: 'swipe',
- swipeDir: 'right',
- partOfWiderSwipe: 'rightHalf',
- widerSwipePairCenterX: (columnCenterXs[1] + columnCenterXs[2]) / 2
-}, {
- time: 7400,
- type: 'tap',
- columnIndex: 0
-}, {
- time: 8200,
- type: 'trap',
- columnIndex: 3
-}, {
- time: 9000,
- type: 'swipe',
- swipeDir: 'down',
- columnIndex: 1
-}, {
- // Example of another "wider swipe" (horizontal left)
- time: 9800,
- type: 'swipe',
- swipeDir: 'left',
- partOfWiderSwipe: 'leftHalf',
- widerSwipePairCenterX: (columnCenterXs[0] + columnCenterXs[1]) / 2
-}, {
- time: 9800,
- type: 'swipe',
- swipeDir: 'left',
- partOfWiderSwipe: 'rightHalf',
- widerSwipePairCenterX: (columnCenterXs[0] + columnCenterXs[1]) / 2
-}, {
- time: 10600,
- type: 'tap',
- columnIndex: 3
-}, {
- time: 11400,
- type: 'swipe',
- swipeDir: 'up',
- columnIndex: 0
-}, {
- time: 12200,
- type: 'trap',
- columnIndex: 1
-}, {
- time: 13000,
- type: 'tap',
- columnIndex: 2
-}];
-var noteTravelTime = 1200;
+// Function to process raw rhythm map data
+function processRawRhythmMap(rawMapData, songKeyForLogging) {
+ console.log("Processing raw map for: " + songKeyForLogging + " with " + rawMapData.length + " initial notes.");
+ var processedMap = [];
+ // Manual deep copy for an array of simple objects
+ var tempMap = [];
+ for (var k = 0; k < rawMapData.length; k++) {
+ var originalNote = rawMapData[k];
+ var copiedNote = {};
+ for (var key in originalNote) {
+ if (originalNote.hasOwnProperty(key)) {
+ copiedNote[key] = originalNote[key];
+ }
+ }
+ tempMap.push(copiedNote);
+ }
+ // 1. Convert diagonal swipes and normalize directions
+ for (var i = 0; i < tempMap.length; i++) {
+ var note = tempMap[i];
+ if (note.type === 'swipe' && note.swipeDir) {
+ var dir = note.swipeDir.toLowerCase();
+ if (dir.includes('right')) {
+ note.swipeDir = 'right';
+ } else if (dir.includes('left')) {
+ note.swipeDir = 'left';
+ } else if (dir.includes('up')) {
+ note.swipeDir = 'up';
+ } else if (dir.includes('down')) {
+ note.swipeDir = 'down';
+ }
+ }
+ }
+ var timeGroupedNotes = {};
+ tempMap.forEach(function (note) {
+ if (!timeGroupedNotes[note.time]) {
+ timeGroupedNotes[note.time] = [];
+ }
+ timeGroupedNotes[note.time].push(note);
+ });
+ var finalMapNotes = [];
+ var sortedTimes = Object.keys(timeGroupedNotes).map(Number).sort(function (a, b) {
+ return a - b;
+ });
+ for (var tIdx = 0; tIdx < sortedTimes.length; tIdx++) {
+ var time = sortedTimes[tIdx];
+ var notesAtThisTime = timeGroupedNotes[time];
+ var notesToKeepAtThisTime = [];
+ var processedForWiderSwipeConversion = []; // Keep track of notes converted from vertical pairs
+ var colsWithVerticalSwipes = [null, null, null, null];
+ notesAtThisTime.forEach(function (note) {
+ if (note.type === 'swipe' && (note.swipeDir === 'up' || note.swipeDir === 'down')) {
+ if (note.columnIndex >= 0 && note.columnIndex < NUM_COLUMNS) {
+ // Only add if not already part of a wider swipe conversion that happened
+ var alreadyConverted = false;
+ for (var convIdx = 0; convIdx < processedForWiderSwipeConversion.length; convIdx++) {
+ if (processedForWiderSwipeConversion[convIdx].originalTime === note.time && processedForWiderSwipeConversion[convIdx].originalColumn === note.columnIndex) {
+ alreadyConverted = true;
+ break;
+ }
+ }
+ if (!alreadyConverted) {
+ colsWithVerticalSwipes[note.columnIndex] = note.swipeDir;
+ }
+ }
+ }
+ });
+ for (var c = 0; c < NUM_COLUMNS - 1; c++) {
+ if (colsWithVerticalSwipes[c] && colsWithVerticalSwipes[c + 1] && colsWithVerticalSwipes[c] === colsWithVerticalSwipes[c + 1]) {
+ var randomHorizontalDir = Math.random() < 0.5 ? 'left' : 'right';
+ var pairCenterX = (columnCenterXs[c] + columnCenterXs[c + 1]) / 2;
+ notesToKeepAtThisTime.push({
+ time: time,
+ type: 'swipe',
+ swipeDir: randomHorizontalDir,
+ partOfWiderSwipe: 'leftHalf',
+ widerSwipePairCenterX: pairCenterX,
+ originalColumnHint: c
+ });
+ notesToKeepAtThisTime.push({
+ time: time,
+ type: 'swipe',
+ swipeDir: randomHorizontalDir,
+ partOfWiderSwipe: 'rightHalf',
+ widerSwipePairCenterX: pairCenterX,
+ originalColumnHint: c + 1
+ });
+ // Add to a temporary list to mark them as "used" by this conversion
+ processedForWiderSwipeConversion.push({
+ originalTime: time,
+ originalColumn: c
+ });
+ processedForWiderSwipeConversion.push({
+ originalTime: time,
+ originalColumn: c + 1
+ });
+ colsWithVerticalSwipes[c] = null;
+ colsWithVerticalSwipes[c + 1] = null;
+ c++;
+ }
+ }
+ notesAtThisTime.forEach(function (note) {
+ var wasConverted = false;
+ for (var convIdx = 0; convIdx < processedForWiderSwipeConversion.length; convIdx++) {
+ if (processedForWiderSwipeConversion[convIdx].originalTime === note.time && processedForWiderSwipeConversion[convIdx].originalColumn === note.columnIndex && (note.swipeDir === 'up' || note.swipeDir === 'down')) {
+ // Check if it was one of the vertical notes
+ wasConverted = true;
+ break;
+ }
+ }
+ if (!wasConverted) {
+ notesToKeepAtThisTime.push(note);
+ }
+ });
+ var horizontalWiderSwipePairs = {};
+ var notesForFinalProcessing = [];
+ // Filter out duplicates before further processing this time slot's notes
+ var uniqueNotesAtThisTime = [];
+ var seenNotesKeysAtThisTime = {};
+ notesToKeepAtThisTime.forEach(function (note) {
+ var key = "" + note.type + "_" + (note.columnIndex !== undefined ? note.columnIndex : note.partOfWiderSwipe ? note.widerSwipePairCenterX + note.partOfWiderSwipe : '') + "_" + (note.swipeDir || '');
+ if (!seenNotesKeysAtThisTime[key]) {
+ uniqueNotesAtThisTime.push(note);
+ seenNotesKeysAtThisTime[key] = true;
+ }
+ });
+ uniqueNotesAtThisTime.sort(function (a, b) {
+ // Sort by original column hint if available, or column index, or widerSwipePairCenterX
+ var valA = a.originalColumnHint !== undefined ? a.originalColumnHint : a.columnIndex !== undefined ? a.columnIndex : a.widerSwipePairCenterX || 0;
+ var valB = b.originalColumnHint !== undefined ? b.originalColumnHint : b.columnIndex !== undefined ? b.columnIndex : b.widerSwipePairCenterX || 0;
+ return valA - valB;
+ });
+ for (var nIdx = 0; nIdx < uniqueNotesAtThisTime.length; nIdx++) {
+ var note = uniqueNotesAtThisTime[nIdx];
+ if (note.partOfWiderSwipe) {
+ notesForFinalProcessing.push(note);
+ continue;
+ }
+ var potentialPartner = null;
+ if (nIdx + 1 < uniqueNotesAtThisTime.length) {
+ potentialPartner = uniqueNotesAtThisTime[nIdx + 1];
+ }
+ if (note.type === 'swipe' && (note.swipeDir === 'left' || note.swipeDir === 'right') && potentialPartner && potentialPartner.type === 'swipe' && potentialPartner.time === note.time &&
+ // Ensure same time for partner
+ potentialPartner.swipeDir === note.swipeDir && potentialPartner.columnIndex === note.columnIndex + 1) {
+ var pairCenterX = (columnCenterXs[note.columnIndex] + columnCenterXs[potentialPartner.columnIndex]) / 2;
+ notesForFinalProcessing.push({
+ time: note.time,
+ type: 'swipe',
+ swipeDir: note.swipeDir,
+ partOfWiderSwipe: 'leftHalf',
+ widerSwipePairCenterX: pairCenterX,
+ originalColumnHint: note.columnIndex
+ });
+ notesForFinalProcessing.push({
+ time: potentialPartner.time,
+ type: 'swipe',
+ swipeDir: potentialPartner.swipeDir,
+ partOfWiderSwipe: 'rightHalf',
+ widerSwipePairCenterX: pairCenterX,
+ originalColumnHint: potentialPartner.columnIndex
+ });
+ nIdx++;
+ } else {
+ notesForFinalProcessing.push(note);
+ }
+ }
+ finalMapNotes.push.apply(finalMapNotes, notesForFinalProcessing);
+ }
+ var uniqueNotesOverall = [];
+ var seenNotesOverall = {};
+ finalMapNotes.sort(function (a, b) {
+ return a.time - b.time;
+ });
+ finalMapNotes.forEach(function (note) {
+ var cX;
+ var keyPartForColumn;
+ if (note.partOfWiderSwipe) {
+ // For wider swipe parts, their exact X is calculated, so use that for uniqueness.
+ // Also include which half it is to differentiate parts of the same pair.
+ cX = note.widerSwipePairCenterX + (note.partOfWiderSwipe === 'leftHalf' ? -(SWIPE_NOTE_WIDTH / 2) : SWIPE_NOTE_WIDTH / 2);
+ keyPartForColumn = "pC" + note.widerSwipePairCenterX + "h" + (note.partOfWiderSwipe === 'leftHalf' ? 'L' : 'R');
+ } else if (note.columnIndex !== undefined) {
+ cX = columnCenterXs[note.columnIndex]; // Should exist if columnIndex is valid
+ keyPartForColumn = "c" + note.columnIndex;
+ } else {
+ // Should not happen if map is well-formed by this stage
+ cX = gameScreenWidth / 2;
+ keyPartForColumn = "cX" + cX;
+ }
+ var key = "" + note.time + "_" + note.type + "_" + keyPartForColumn + "_" + (note.swipeDir || '');
+ if (!seenNotesOverall[key]) {
+ uniqueNotesOverall.push(note);
+ seenNotesOverall[key] = true;
+ } else {
+ // console.log("Filtered final duplicate note: " + key);
+ }
+ });
+ console.log("Processed map for: " + songKeyForLogging + " FINALLY contains " + uniqueNotesOverall.length + " notes.");
+ return uniqueNotesOverall;
+}
+var allSongData = {
+ "defaultTestTrack": {
+ // Kept for basic testing if needed
+ musicAsset: null,
+ rawRhythmMap: [
+ // Now stores raw map, will be processed by loadSong
+ {
+ time: 1000,
+ type: 'tap',
+ columnIndex: 0
+ }, {
+ time: 1800,
+ type: 'tap',
+ columnIndex: 1
+ }, {
+ time: 2600,
+ type: 'swipe',
+ swipeDir: 'left',
+ columnIndex: 2
+ }, {
+ time: 3400,
+ type: 'tap',
+ columnIndex: 3
+ }, {
+ time: 4200,
+ type: 'swipe',
+ swipeDir: 'right',
+ columnIndex: 0
+ }, {
+ time: 5000,
+ type: 'trap',
+ columnIndex: 1
+ }, {
+ time: 5800,
+ type: 'tap',
+ columnIndex: 2
+ }, {
+ time: 6600,
+ type: 'swipe',
+ swipeDir: 'right',
+ // This will become widerSwipe
+ columnIndex: 1 // Original column for left part of potential pair
+ }, {
+ time: 6600,
+ type: 'swipe',
+ swipeDir: 'right',
+ columnIndex: 2 // Original column for right part of potential pair
+ }, {
+ time: 7400,
+ type: 'tap',
+ columnIndex: 0
+ }]
+ },
+ "test3": {
+ // Your map for test3
+ musicAsset: "test3",
+ // Assuming this is the asset name in Upit
+ rawRhythmMap: [
+ // Paste the content of rhythmMap_Expert.js here
+ {
+ "time": 21558,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 21558,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted to horizontal wider
+ {
+ "time": 24959,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 24959,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ },
+ // Will be converted to horizontal wider
+ {
+ "time": 28480,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 30578,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 34620,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 36018,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 42161,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 42161,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 44799,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 46580,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 48340,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 48340,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ },
+ // Simultaneous, different dirs, adjacent - will remain separate swipes
+ {
+ "time": 50099,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 50099,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Simultaneous, different dirs, adjacent - will remain separate swipes
+ {
+ "time": 51879,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 51879,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ },
+ // Simultaneous, different dirs, different columns - separate
+ {
+ "time": 53621,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 53621,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 57139,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ },
+ // Removed duplicate: {"time": 57139, "type": "swipe", "swipeDir": "left", "columnIndex": 0},
+ {
+ "time": 58921,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 60699,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 62460,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ },
+ // Removed duplicate: {"time": 62460, "type": "swipe", "swipeDir": "right", "columnIndex": 3},
+ {
+ "time": 64219,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 65141,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 66000,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ },
+ // Removed duplicate: {"time": 66000, "type": "swipe", "swipeDir": "left", "columnIndex": 0},
+ {
+ "time": 67761,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 67761,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 71280,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 71280,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 72301,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 73039,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 73518,
+ "type": "swipe",
+ "swipeDir": "down-right",
+ "columnIndex": 3
+ },
+ // Becomes right
+ {
+ "time": 73939,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 74421,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 74421,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ },
+ // Will be converted (up -> random L/R wider)
+ {
+ "time": 80100,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 81861,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 83638,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 85399,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 87160,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 88920,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 88920,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 3
+ },
+ // Will be converted
+ {
+ "time": 90700,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 90700,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ },
+ // Will be converted
+ {
+ "time": 92460,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 92460,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ },
+ // Will be converted
+ {
+ "time": 94218,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 95978,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 97739,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 99521,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 101278,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 101278,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ },
+ // Will be converted
+ {
+ "time": 103041,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 103041,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ },
+ // Will be converted
+ {
+ "time": 104800,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 104800,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 106578,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 106578,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ },
+ // Will be converted
+ {
+ "time": 109858,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 109858,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 112201,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 112201,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ },
+ // Not adjacent, separate
+ {
+ "time": 113620,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 113620,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 116918,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 116918,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 118918,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 118918,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 119798,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 119798,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ },
+ // Not adjacent
+ {
+ "time": 123359,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 123359,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 3
+ },
+ // Will be converted
+ {
+ "time": 124238,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 124238,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ },
+ // Will be converted
+ {
+ "time": 125138,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 125138,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ },
+ // Will be converted
+ {
+ "time": 126000,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 126000,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ },
+ // Will be converted
+ {
+ "time": 126320,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 127158,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 128200,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 128200,
+ "type": "tap",
+ "columnIndex": 2
+ },
+ // Simultaneous taps in adjacent columns
+ {
+ "time": 130318,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 130318,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 136579,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 136579,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 137460,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 137460,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 137901,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 137901,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 138340,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 138340,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 138798,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 138798,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 139219,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 139219,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 139658,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 139658,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 140100,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 140100,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 140540,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 140540,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 140979,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 140979,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 141441,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 141441,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 141861,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 141861,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 143639,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 144081,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 144521,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 144959,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 145401,
+ "type": "swipe",
+ "swipeDir": "down-right",
+ "columnIndex": 2
+ },
+ // Becomes right
+ {
+ "time": 145839,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 3
+ }, {
+ "time": 146281,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 146281,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ },
+ // Will be converted
+ {
+ "time": 147160,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 147599,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 148039,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 148498,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 148921,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 149821,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 150681,
+ "type": "swipe",
+ "swipeDir": "down-right",
+ "columnIndex": 2
+ },
+ // Becomes right
+ {
+ "time": 150681,
+ "type": "swipe",
+ "swipeDir": "down-right",
+ "columnIndex": 3
+ },
+ // Becomes right, this will be a wider swipe right if they are adjacent after col mapping
+ {
+ "time": 151581,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 151581,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 152459,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 3
+ }, {
+ "time": 152898,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 153339,
+ "type": "swipe",
+ "swipeDir": "up-left",
+ "columnIndex": 0
+ },
+ // Becomes left
+ {
+ "time": 153339,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 154221,
+ "type": "swipe",
+ "swipeDir": "down-right",
+ "columnIndex": 2
+ },
+ // Becomes right
+ {
+ "time": 154661,
+ "type": "swipe",
+ "swipeDir": "down-left",
+ "columnIndex": 1
+ },
+ // Becomes left
+ {
+ "time": 155099,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 155541,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 155979,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 155979,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 156861,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 156861,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ },
+ // Will be converted
+ {
+ "time": 157739,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 158179,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 158640,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 159081,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 159518,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 3
+ }, {
+ "time": 159960,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 160400,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 160400,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ },
+ // Will be converted
+ {
+ "time": 163941,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 163941,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 1
+ },
+ // Wider swipe left
+ {
+ "time": 164800,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 164800,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 166139,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 3
+ }, {
+ "time": 166580,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 167001,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 167439,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 167920,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 168399,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 168780,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 169220,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 169660,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 170101,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 2
+ }, {
+ "time": 170980,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 171420,
+ "type": "swipe",
+ "swipeDir": "down-left",
+ "columnIndex": 1
+ },
+ // Becomes left
+ {
+ "time": 171860,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 171860,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ },
+ // Will be converted
+ {
+ "time": 173178,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 173639,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 174501,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 174981,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 175418,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 175839,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 176278,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 176278,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 177160,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 177160,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 178941,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 179380,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 179798,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 180239,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 180699,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 181580,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 2
+ }, {
+ "time": 182018,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ },
+ // Wider swipe right
+ {
+ "time": 182901,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 183341,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 183341,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 184220,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 184220,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 185558,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 185979,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 186439,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 186879,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 187299,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 187740,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 188620,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 188620,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 189540,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 189961,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 190401,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 191280,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 191280,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 192159,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 192718,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 193041,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 193938,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 193938,
+ "type": "swipe",
+ "swipeDir": "right",
+ "columnIndex": 3
+ }, {
+ "time": 194358,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 194818,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 195678,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 195678,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ },
+ // Will be converted
+ {
+ "time": 196139,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 3
+ }, {
+ "time": 196579,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 197018,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 197458,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 197458,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 198338,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 198781,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 199221,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 199221,
+ "type": "swipe",
+ "swipeDir": "down-left",
+ "columnIndex": 1
+ },
+ // Becomes left
+ {
+ "time": 200098,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 0
+ }, {
+ "time": 200098,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 201420,
+ "type": "swipe",
+ "swipeDir": "down-left",
+ "columnIndex": 1
+ },
+ // Becomes left
+ {
+ "time": 201858,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 0
+ }, {
+ "time": 202740,
+ "type": "swipe",
+ "swipeDir": "down-right",
+ "columnIndex": 3
+ },
+ // Becomes right
+ {
+ "time": 204058,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 204499,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 3
+ }, {
+ "time": 205401,
+ "type": "swipe",
+ "swipeDir": "up-left",
+ "columnIndex": 0
+ },
+ // Becomes left
+ {
+ "time": 205401,
+ "type": "swipe",
+ "swipeDir": "down-left",
+ "columnIndex": 2
+ },
+ // Becomes left
+ {
+ "time": 206279,
+ "type": "swipe",
+ "swipeDir": "down-right",
+ "columnIndex": 1
+ },
+ // Becomes right
+ {
+ "time": 206279,
+ "type": "swipe",
+ "swipeDir": "up-right",
+ "columnIndex": 3
+ },
+ // Becomes right
+ {
+ "time": 207160,
+ "type": "swipe",
+ "swipeDir": "left",
+ "columnIndex": 0
+ }, {
+ "time": 207620,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 2
+ }, {
+ "time": 208038,
+ "type": "swipe",
+ "swipeDir": "down",
+ "columnIndex": 1
+ }, {
+ "time": 208478,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 2
+ }, {
+ "time": 208919,
+ "type": "swipe",
+ "swipeDir": "up",
+ "columnIndex": 1
+ }, {
+ "time": 209799,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 209799,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 210698,
+ "type": "tap",
+ "columnIndex": 0
+ }, {
+ "time": 211140,
+ "type": "tap",
+ "columnIndex": 3
+ }, {
+ "time": 211578,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 212018,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 212459,
+ "type": "tap",
+ "columnIndex": 0
+ }, {
+ "time": 213341,
+ "type": "tap",
+ "columnIndex": 3
+ }, {
+ "time": 213778,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 214221,
+ "type": "tap",
+ "columnIndex": 3
+ }, {
+ "time": 215121,
+ "type": "tap",
+ "columnIndex": 0
+ }, {
+ "time": 215541,
+ "type": "tap",
+ "columnIndex": 3
+ }, {
+ "time": 215978,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 216861,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 217758,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 218179,
+ "type": "tap",
+ "columnIndex": 3
+ }, {
+ "time": 218639,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 219518,
+ "type": "tap",
+ "columnIndex": 1
+ }, {
+ "time": 219518,
+ "type": "tap",
+ "columnIndex": 2
+ }, {
+ "time": 220400,
+ "type": "tap",
+ "columnIndex": 1
+ }]
+ }
+ // Placeholder for test1 and test2
+ // "test1_raw": { musicAsset: "test1", rawRhythmMap: [ /* ... map data ... */ ] },
+ // "test2_raw": { musicAsset: "test2", rawRhythmMap: [ /* ... map data ... */ ] }
+};
+var currentActiveRhythmMap = null;
+var currentMusic = null;
+var noteTravelTime = 2000;
var hitWindowPerfect = 120;
var hitWindowGood = 260;
var MIN_SWIPE_DISTANCE = 60;
var notes = [];
@@ -272,15 +1814,15 @@
comboTxt.x = gameScreenWidth / 2;
comboTxt.y = 130;
LK.gui.top.addChild(comboTxt);
var hitZoneY = 1800;
-var hitZoneWidth = gameScreenWidth * 0.95;
+var hitZoneVisualWidth = playfieldWidth;
var hitZoneLine = LK.getAsset('lineAsset', {
anchorX: 0.5,
anchorY: 0.5,
x: gameScreenWidth / 2,
y: hitZoneY,
- width: hitZoneWidth,
+ width: hitZoneVisualWidth,
height: 4,
alpha: 0.6
});
game.addChild(hitZoneLine);
@@ -302,31 +1844,69 @@
inputLocked = false;
scoreTxt.setText('Score: 0');
comboTxt.setText('Combo: 0');
}
+function loadSong(songKey) {
+ var songData = allSongData[songKey];
+ if (!songData || !songData.rawRhythmMap) {
+ // Check for rawRhythmMap
+ console.log("Error: Song data or rawRhythmMap not found for key: " + songKey);
+ if (allSongData["defaultTestTrack"] && allSongData["defaultTestTrack"].rawRhythmMap) {
+ songData = allSongData["defaultTestTrack"];
+ } else {
+ currentActiveRhythmMap = [];
+ return;
+ }
+ }
+ currentActiveRhythmMap = processRawRhythmMap(songData.rawRhythmMap, songKey); // Process the raw map
+ if (currentMusic && typeof currentMusic.stop === 'function') {
+ currentMusic.stop();
+ }
+ currentMusic = null;
+ if (songData.musicAsset) {
+ currentMusic = LK.getSound(songData.musicAsset);
+ if (currentMusic && typeof currentMusic.play === 'function') {
+ currentMusic.play();
+ console.log("Music asset for " + songKey + " would play here.");
+ } else {
+ console.log("Warning: Music asset '" + songData.musicAsset + "' not found or not playable.");
+ }
+ }
+ resetGameState();
+ nextNoteIdx = 0;
+ gameStartTime = Date.now();
+ console.log("Loaded and processed song: " + songKey);
+}
function spawnNotes() {
var now = Date.now();
- while (nextNoteIdx < rhythmMap.length) {
- var noteData = rhythmMap[nextNoteIdx];
+ if (!currentActiveRhythmMap) {
+ return;
+ }
+ while (nextNoteIdx < currentActiveRhythmMap.length) {
+ var noteData = currentActiveRhythmMap[nextNoteIdx]; // Use processed map
var noteTargetHitTime = gameStartTime + noteData.time;
- var noteVisualSpawnTime = noteTargetHitTime - noteTravelTime;
- if (noteVisualSpawnTime <= now) {
+ if (noteTargetHitTime - noteTravelTime <= now) {
var targetCenterX;
if (noteData.partOfWiderSwipe && noteData.widerSwipePairCenterX !== undefined) {
if (noteData.partOfWiderSwipe === 'leftHalf') {
targetCenterX = noteData.widerSwipePairCenterX - SWIPE_NOTE_WIDTH / 2;
} else if (noteData.partOfWiderSwipe === 'rightHalf') {
targetCenterX = noteData.widerSwipePairCenterX + SWIPE_NOTE_WIDTH / 2;
} else {
- // Fallback if partOfWiderSwipe has unexpected value
- targetCenterX = columnCenterXs[noteData.columnIndex !== undefined ? noteData.columnIndex : Math.floor(NUM_COLUMNS / 2)];
+ // Fallback if partOfWiderSwipe has unexpected value, use original column if available
+ targetCenterX = columnCenterXs[noteData.originalColumnHint !== undefined ? noteData.originalColumnHint : Math.floor(NUM_COLUMNS / 2)];
}
} else if (noteData.columnIndex !== undefined && noteData.columnIndex >= 0 && noteData.columnIndex < NUM_COLUMNS) {
targetCenterX = columnCenterXs[noteData.columnIndex];
} else {
- targetCenterX = gameScreenWidth / 2; // Fallback for notes without proper column/widerSwipe info
+ targetCenterX = playfieldStartX + playfieldWidth / 2;
}
+ // Pass original noteData to Note constructor for potential debugging/reference if needed
var n = new Note(noteData.type, noteData.swipeDir, noteTargetHitTime, targetCenterX);
+ n.mapData = noteData; // Attach original map data to the note instance
+ if (noteData.partOfWiderSwipe) {
+ n.isWiderSwipePart = true;
+ }
n.alpha = 0;
notes.push(n);
game.addChild(n);
nextNoteIdx++;
@@ -338,14 +1918,17 @@
function removeOldNotes() {
var now = Date.now();
for (var i = notes.length - 1; i >= 0; i--) {
var n = notes[i];
- if (n.judged && now > n.targetHitTime + hitWindowGood + 400) {
+ var timeToRemoveAfterJudged = 700; // ms po targetHitTime dla ocenionych notatek
+ var timeToRemoveIfNotJudged = noteTravelTime / 2 + hitWindowGood + 500; // Dłuższy czas, jeśli nieoceniona, liczony od targetHitTime
+ if (n.judged && now > n.targetHitTime + timeToRemoveAfterJudged) {
if (n.parent) {
n.destroy();
}
notes.splice(i, 1);
- } else if (!n.judged && now > n.targetHitTime + noteTravelTime + 500) {
+ } else if (!n.judged && now > n.targetHitTime + timeToRemoveIfNotJudged) {
+ if (n.noteType !== 'trap') {}
if (n.parent) {
n.destroy();
}
notes.splice(i, 1);
@@ -364,10 +1947,18 @@
var timeDiff = Math.abs(now - n.targetHitTime);
if (timeDiff > hitWindowGood) {
continue;
}
- var currentNoteWidth = (n.noteType === 'swipe' ? SWIPE_NOTE_WIDTH : n.noteAsset.width) * n.scale.x;
- var currentNoteHeight = (n.noteType === 'swipe' ? SWIPE_NOTE_WIDTH : n.noteAsset.height) * n.scale.y; // Assuming swipe notes are square
+ var currentNoteAsset = n.noteAsset;
+ if (!currentNoteAsset) {
+ continue;
+ }
+ var currentNoteWidth = currentNoteAsset.width * n.scale.x;
+ var currentNoteHeight = currentNoteAsset.height * n.scale.y;
+ if (n.noteType === 'swipe') {
+ currentNoteWidth = SWIPE_NOTE_WIDTH * n.scale.x;
+ currentNoteHeight = SWIPE_NOTE_WIDTH * n.scale.y;
+ }
var dx = x - n.x;
var dy = y - n.y;
if (Math.abs(dx) <= currentNoteWidth / 2 && Math.abs(dy) <= currentNoteHeight / 2) {
if (timeDiff < smallestTimeDiff) {
@@ -394,15 +1985,15 @@
comboTxt.setText('Combo: ' + combo);
}
function resetCombo() {
combo = 0;
- comboTxt.setText('Combo: ' + combo);
+ comboTxt.setText('Combo: 0');
}
function checkGameEnd() {
- if (nextNoteIdx >= rhythmMap.length && notes.length === 0) {
+ if (currentActiveRhythmMap && nextNoteIdx >= currentActiveRhythmMap.length && notes.length === 0) {
LK.setTimeout(function () {
- if (nextNoteIdx >= rhythmMap.length && notes.length === 0) {
- LK.showYouWin();
+ if (currentActiveRhythmMap && nextNoteIdx >= currentActiveRhythmMap.length && notes.length === 0) {
+ LK.showYouWin(); // Consider a more advanced game end screen later
}
}, 1000);
}
}
@@ -457,9 +2048,9 @@
}
};
game.up = function (x, y, obj) {
if (inputLocked || !swipeStart) {
- console.log("Swipe Rejected: Input locked or no swipe start");
+ // console.log("Swipe Rejected: Input locked or no swipe start");
swipeStart = null;
return;
}
var swipeEndX = x;
@@ -467,9 +2058,12 @@
var swipeEndTime = Date.now();
var dx = swipeEndX - swipeStart.x;
var dy = swipeEndY - swipeStart.y;
var dist = Math.sqrt(dx * dx + dy * dy);
- console.log("Swipe End: X=" + swipeEndX + " Y=" + swipeEndY + " Dist=" + dist);
+ console.log("--- Swipe Action END ---");
+ console.log("Swipe Start (X,Y,Time): " + swipeStart.x + "," + swipeStart.y + "," + swipeStart.time);
+ console.log("Swipe End (X,Y,Time): " + swipeEndX + "," + swipeEndY + "," + swipeEndTime);
+ console.log("Swipe Delta (dX,dY,Dist): " + dx + "," + dy + "," + dist);
var potentialSwipe = dist >= MIN_SWIPE_DISTANCE;
var swipedNoteSuccessfully = false;
if (potentialSwipe) {
var detectedDir = null;
@@ -477,42 +2071,41 @@
detectedDir = dx > 0 ? 'right' : 'left';
} else {
detectedDir = dy > 0 ? 'down' : 'up';
}
- console.log("Potential Swipe Detected. Dir: " + detectedDir);
+ console.log("Potential Swipe. Detected Dir: " + detectedDir);
var swipeBoundingBox = {
x: Math.min(swipeStart.x, swipeEndX),
y: Math.min(swipeStart.y, swipeEndY),
width: Math.abs(dx),
height: Math.abs(dy)
};
- // Safer logging for swipeBoundingBox
console.log("Swipe BBox: x=" + swipeBoundingBox.x + ", y=" + swipeBoundingBox.y + ", w=" + swipeBoundingBox.width + ", h=" + swipeBoundingBox.height);
var notesHitThisSwipe = [];
for (var i = 0; i < notes.length; i++) {
var n = notes[i];
- // console.log("Checking Note " + i + ": Type=" + n.noteType + " Judged=" + n.judged + " TargetX=" + n.centerX + " TargetY=" + n.centerY + " CurrentY=" + n.y);
if (n.judged || n.noteType !== 'swipe') {
continue;
}
- // console.log("Note " + i + " is a potential swipe target.");
+ console.log("Checking Note Idx " + i + " (TargetTime: " + n.targetHitTime + ", Dir: " + n.swipeDir + ", X: " + n.x + ", Y: " + n.y + ", Scale: " + n.scale.x + ", Alpha: " + n.alpha + ")");
var overallSwipeTimeMatchesNote = false;
- if (swipeStart.time <= n.targetHitTime + hitWindowGood && swipeEndTime >= n.targetHitTime - hitWindowGood) {
+ // Check if the note's target hit time falls within the swipe's duration, with tolerance
+ if (n.targetHitTime >= swipeStart.time - hitWindowGood && n.targetHitTime <= swipeEndTime + hitWindowGood) {
overallSwipeTimeMatchesNote = true;
}
- // This secondary check is redundant if the first one is inclusive enough.
- // if (!overallSwipeTimeMatchesNote) {
- // if (swipeStart.time <= n.targetHitTime + hitWindowGood && swipeEndTime >= n.targetHitTime - hitWindowGood) {
- // overallSwipeTimeMatchesNote = true;
- // }
- // }
- // console.log("Note " + i + " - overallSwipeTimeMatchesNote: " + overallSwipeTimeMatchesNote + " (SwipeStart: " + swipeStart.time + ", SwipeEnd: " + swipeEndTime + ", NoteTarget: " + n.targetHitTime + ", Window: " + hitWindowGood + ")");
+ // Also consider if the swipe itself (its start or end) happens within the note's broader hit window
+ // This helps for notes that should be hit AT the start or AT the end of a swipe.
if (!overallSwipeTimeMatchesNote) {
- // console.log("Note " + i + " rejected: Swipe time does not match note time window.");
+ if (swipeStart.time >= n.targetHitTime - hitWindowGood && swipeStart.time <= n.targetHitTime + hitWindowGood || swipeEndTime >= n.targetHitTime - hitWindowGood && swipeEndTime <= n.targetHitTime + hitWindowGood) {
+ overallSwipeTimeMatchesNote = true;
+ }
+ }
+ console.log(" Note " + i + " - overallSwipeTimeMatchesNote: " + overallSwipeTimeMatchesNote);
+ if (!overallSwipeTimeMatchesNote) {
continue;
}
if (n.alpha === 0) {
- // console.log("Note " + i + " rejected: Note alpha is 0 (not visible/active).");
+ console.log(" Note " + i + " - REJECTED (alpha is 0)");
continue;
}
var noteCurrentWidth = SWIPE_NOTE_WIDTH * n.scale.x;
var noteCurrentHeight = SWIPE_NOTE_WIDTH * n.scale.y;
@@ -521,45 +2114,54 @@
y: n.y - noteCurrentHeight / 2,
width: noteCurrentWidth,
height: noteCurrentHeight
};
- // console.log("Note " + i + " BBox: x=" + noteBoundingBox.x + ", y=" + noteBoundingBox.y + ", w=" + noteBoundingBox.width + ", h=" + noteBoundingBox.height);
- if (rectsIntersect(swipeBoundingBox, noteBoundingBox)) {
- console.log("Note " + i + " INTERSECTS with swipe BBox.");
+ console.log(" Note " + i + " BBox: x=" + noteBoundingBox.x + ", y=" + noteBoundingBox.y + ", w=" + noteBoundingBox.width + ", h=" + noteBoundingBox.height);
+ var intersects = rectsIntersect(swipeBoundingBox, noteBoundingBox);
+ console.log(" Note " + i + " - rectsIntersect: " + intersects);
+ if (intersects) {
+ console.log(" Note " + i + " - Detected Dir: " + detectedDir + ", Note Dir: " + n.swipeDir);
if (detectedDir === n.swipeDir) {
- console.log("Note " + i + " Direction MATCH. Detected: " + detectedDir + ", Expected: " + n.swipeDir);
- var verticalCheckTolerance = noteCurrentHeight / 1.5; // Height of note plus some tolerance
- // console.log("Note " + i + " Vertical Check: |" + n.y + " - " + n.centerY + "| < " + verticalCheckTolerance + " ? Result: " + (Math.abs(n.y - n.centerY) < verticalCheckTolerance));
- if (Math.abs(n.y - n.centerY) < verticalCheckTolerance) {
- console.log("Note " + i + " PASSED vertical proximity check. Adding to hits.");
+ var verticalProximity = Math.abs(n.y - n.centerY);
+ var verticalTolerance = noteCurrentHeight / 1.5; // How close to hit line note should be
+ console.log(" Note " + i + " - Vertical Proximity: " + verticalProximity + " (Tolerance: " + verticalTolerance + ")");
+ if (verticalProximity < verticalTolerance) {
+ console.log(" Note " + i + " - PASSED ALL CHECKS. Added to potential hits.");
notesHitThisSwipe.push(n);
} else {
- // console.log("Note " + i + " FAILED vertical proximity check.");
+ console.log(" Note " + i + " - FAILED Vertical Proximity Check.");
}
} else {
- // console.log("Note " + i + " Direction MISMATCH. Detected: " + detectedDir + ", Expected: " + n.swipeDir);
+ console.log(" Note " + i + " - FAILED Direction Check.");
}
- } else {
- // console.log("Note " + i + " does NOT intersect with swipe BBox.");
}
}
if (notesHitThisSwipe.length > 0) {
- console.log("Processing " + notesHitThisSwipe.length + " notes hit by this swipe.");
+ console.log("Processing " + notesHitThisSwipe.length + " notes initially hit by this swipe.");
notesHitThisSwipe.sort(function (a, b) {
var da = Math.abs(swipeEndTime - a.targetHitTime);
var db = Math.abs(swipeEndTime - b.targetHitTime);
return da - db;
});
- var maxNotesToHitPerSwipe = 2;
+ var maxNotesToHitPerSwipe = 1;
+ if (notesHitThisSwipe.length > 0 && notesHitThisSwipe[0].isWiderSwipePart) {
+ // Check the best candidate
+ maxNotesToHitPerSwipe = 2;
+ }
var notesActuallyHitCount = 0;
- for (var k = 0; k < notesHitThisSwipe.length && k < maxNotesToHitPerSwipe; k++) {
+ for (var k = 0; k < notesHitThisSwipe.length && notesActuallyHitCount < maxNotesToHitPerSwipe; k++) {
var noteToJudge = notesHitThisSwipe[k];
if (noteToJudge.judged) {
- // console.log("Note (ID/Ref might be useful here) already judged, skipping.");
continue;
}
+ if (notesActuallyHitCount === 1 && notesHitThisSwipe[0].isWiderSwipePart) {
+ if (!noteToJudge.isWiderSwipePart || noteToJudge.mapData.widerSwipePairCenterX !== notesHitThisSwipe[0].mapData.widerSwipePairCenterX || noteToJudge.mapData.partOfWiderSwipe === notesHitThisSwipe[0].mapData.partOfWiderSwipe) {
+ console.log(" Skipping note in wider swipe check - not matching pair for first hit note.");
+ continue;
+ }
+ }
var result = noteToJudge.getHitAccuracy();
- console.log("Judging Note Hit! Result: " + result);
+ console.log(" JUDGING Note Hit! Result: " + result + " for note at X=" + noteToJudge.x + ", Y=" + noteToJudge.y);
noteToJudge.judged = true;
noteToJudge.showHitFeedback(result);
if (result !== 'miss') {
addScore(result);
@@ -569,13 +2171,16 @@
}
swipedNoteSuccessfully = true;
notesActuallyHitCount++;
}
+ if (notesActuallyHitCount === 0 && notesHitThisSwipe.length > 0) {
+ console.log(" Notes were candidates, but none met final hit criteria (e.g. wider swipe pair logic).");
+ }
} else {
- console.log("No notes were successfully hit by this swipe action.");
+ console.log("No notes candidates after iterating.");
}
} else {
- console.log("Swipe too short or not considered potential.");
+ console.log("Swipe too short (Dist: " + dist + ", Min: " + MIN_SWIPE_DISTANCE + ")");
}
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
@@ -592,6 +2197,7 @@
}
removeOldNotes();
checkGameEnd();
};
-resetGameState();
-gameStartTime = Date.now();
\ No newline at end of file
+// Load the specific song for testing
+loadSong("test3");
+// loadSong("defaultTestTrack"); // Możesz to odkomentować, aby załadować starą mapę testową
\ No newline at end of file