Code edit (1 edits merged)
Please save this source code
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 (7 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 (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) { // Existing circular feedback var feedbackCircle = LK.getAsset('hitFeedback', { anchorX: 0.5, anchorY: 0.5, x: 0, // Relative to the note's center y: 0, // Relative to the note's center scaleX: 0.7, scaleY: 0.7, alpha: 0.7 }); var feedbackTextContent = ""; var feedbackTextColor = 0xFFFFFF; // Default white if (result === 'perfect') { feedbackCircle.tint = 0xffff00; // Yellow feedbackTextContent = "Perfect!"; // Or "+100" feedbackTextColor = 0xffff00; } else if (result === 'good') { feedbackCircle.tint = 0x00ff00; // Green feedbackTextContent = "Good!"; // Or "+50" feedbackTextColor = 0x00ff00; } else { // 'miss' feedbackCircle.tint = 0xff0000; // Red feedbackTextContent = "Miss"; feedbackTextColor = 0xff0000; } self.addChild(feedbackCircle); // Add circle to the note container tween(feedbackCircle, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 350, easing: tween.easeOut, onFinish: function onFinish() { if (feedbackCircle.parent) { feedbackCircle.destroy(); } } }); // New text feedback if (feedbackTextContent) { var scorePopup = new Text2(feedbackTextContent, { size: 60, // Możemy dostosować rozmiar fill: feedbackTextColor, stroke: 0x000000, // Czarny kontur dla lepszej czytelności strokeThickness: 3 }); scorePopup.anchor.set(0.5, 0.5); scorePopup.x = 0; // W centrum notatki (tam gdzie feedbackCircle) scorePopup.y = -SWIPE_NOTE_WIDTH / 2 - 30; // Trochę nad notatką (zakładając, że notatka ma środek w 0,0) // Możemy potrzebować dostosować Y, jeśli anchor notatki jest inny // Add to the main game layer (or LK.gui.top) so it's not affected by note's alpha/scale changes later // If added to self (note), it would disappear if note is quickly destroyed. // Let's add it to the note's parent (which should be 'game') if (self.parent) { // Ensure note has a parent // Position needs to be absolute if added to game layer scorePopup.x = self.x + 0; // (self.x (Note's absolute X) + relative X (0)) scorePopup.y = self.y - SWIPE_NOTE_WIDTH * self.scale.y / 2 - 30; // (self.y (Note's absolute Y) + relative Y) self.parent.addChild(scorePopup); // Add to the same layer as the note } tween(scorePopup, { y: scorePopup.y - 80, // Animacja w górę alpha: 0 }, { duration: 700, // Dłuższy czas trwania animacji easing: tween.easeOut, onFinish: function onFinish() { if (scorePopup.parent) { scorePopup.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 testGuiShape; // Bright green box var testGuiElement = LK.getAsset('testTopGui', { x: 100, y: 100, anchorX: 0, anchorY: 0 }); LK.gui.top.addChild(testGuiElement); console.log("Attempted to add testGuiElement to LK.gui.top", testGuiElement); 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 = 190; 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, // Możemy dostosować, jeśli za duże/małe fill: 0xFFFFFF, // Biały alpha: 1 }); scoreTxt.anchor.set(1, 1); // Kotwiczenie na środku obiektu Tekstowego scoreTxt.x = gameScreenWidth / 2; scoreTxt.y = 80; // Trochę niżej niż pierwotne 20, aby dać więcej miejsca od góry LK.gui.top.addChild(scoreTxt); console.log("Restored scoreTxt: X=" + scoreTxt.x + " Y=" + scoreTxt.y + " Visible:" + scoreTxt.visible); var comboTxt = new Text2('Combo: 0', { size: 80, fill: 0xFFFF00, // Żółty alpha: 1 }); comboTxt.anchor.set(0.5, 0.5); // Kotwiczenie na środku obiektu Tekstowego comboTxt.x = gameScreenWidth / 2; comboTxt.y = scoreTxt.y + scoreTxt.height / 2 + 60; // Pozycjonowanie poniżej scoreTxt, uwzględniając jego wysokość LK.gui.top.addChild(comboTxt); console.log("Restored comboTxt: X=" + comboTxt.x + " Y=" + comboTxt.y + " Visible:" + comboTxt.visible); 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) { console.log("Error: Song data or rawRhythmMap not found for key: " + songKey); if (allSongData["defaultTestTrack"] && allSongData["defaultTestTrack"].rawRhythmMap) { songData = allSongData["defaultTestTrack"]; } else { currentActiveRhythmMap = []; return; } } // Zatrzymanie poprzedniej muzyki, jeśli grała if (currentMusic && typeof currentMusic.stop === 'function') { currentMusic.stop(); } currentMusic = null; resetGameState(); nextNoteIdx = 0; // Przetwarzamy mapę PRZED ustawieniem gameStartTime i startem muzyki currentActiveRhythmMap = processRawRhythmMap(songData.rawRhythmMap, songKey); // Ustawiamy gameStartTime BEZPOŚREDNIO PRZED próbą startu muzyki gameStartTime = Date.now(); if (songData.musicAsset) { currentMusic = LK.getSound(songData.musicAsset); if (currentMusic && typeof currentMusic.play === 'function') { currentMusic.play(); console.log("Music asset for " + songKey + " PLAYING. gameStartTime: " + gameStartTime); } else { console.log("Warning: Music asset '" + songData.musicAsset + "' not found or not playable."); } } else { console.log("No musicAsset defined for " + songKey + ". Map will run on system time only."); } 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); // Animacja dla comboTxt if (combo > 1) { // Mała animacja tylko jeśli combo jest większe niż 1 var originalScale = comboTxt.scale.x; // Zakładamy, że skala X i Y jest taka sama tween(comboTxt.scale, { x: originalScale * 1.3, y: originalScale * 1.3 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(comboTxt.scale, { x: originalScale, y: originalScale }, { duration: 100, easing: tween.easeIn }); } }); } } 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
@@ -19,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
@@ -55,41 +60,118 @@
});
}
self.alpha = 0;
self.showHitFeedback = function (result) {
- var feedback = LK.getAsset('hitFeedback', {
+ // Existing circular feedback
+ var feedbackCircle = LK.getAsset('hitFeedback', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
+ // Relative to the note's center
y: 0,
+ // Relative to the note's center
scaleX: 0.7,
scaleY: 0.7,
alpha: 0.7
});
+ var feedbackTextContent = "";
+ var feedbackTextColor = 0xFFFFFF; // Default white
if (result === 'perfect') {
- feedback.tint = 0xffff00;
+ feedbackCircle.tint = 0xffff00; // Yellow
+ feedbackTextContent = "Perfect!"; // Or "+100"
+ feedbackTextColor = 0xffff00;
} else if (result === 'good') {
- feedback.tint = 0x00ff00;
+ feedbackCircle.tint = 0x00ff00; // Green
+ feedbackTextContent = "Good!"; // Or "+50"
+ feedbackTextColor = 0x00ff00;
} else {
- feedback.tint = 0xff0000;
+ // 'miss'
+ feedbackCircle.tint = 0xff0000; // Red
+ feedbackTextContent = "Miss";
+ feedbackTextColor = 0xff0000;
}
- self.addChild(feedback);
- tween(feedback, {
+ self.addChild(feedbackCircle); // Add circle to the note container
+ tween(feedbackCircle, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 350,
easing: tween.easeOut,
onFinish: function onFinish() {
- if (feedback.parent) {
- feedback.destroy();
+ if (feedbackCircle.parent) {
+ feedbackCircle.destroy();
}
}
});
+ // New text feedback
+ if (feedbackTextContent) {
+ var scorePopup = new Text2(feedbackTextContent, {
+ size: 60,
+ // Możemy dostosować rozmiar
+ fill: feedbackTextColor,
+ stroke: 0x000000,
+ // Czarny kontur dla lepszej czytelności
+ strokeThickness: 3
+ });
+ scorePopup.anchor.set(0.5, 0.5);
+ scorePopup.x = 0; // W centrum notatki (tam gdzie feedbackCircle)
+ scorePopup.y = -SWIPE_NOTE_WIDTH / 2 - 30; // Trochę nad notatką (zakładając, że notatka ma środek w 0,0)
+ // Możemy potrzebować dostosować Y, jeśli anchor notatki jest inny
+ // Add to the main game layer (or LK.gui.top) so it's not affected by note's alpha/scale changes later
+ // If added to self (note), it would disappear if note is quickly destroyed.
+ // Let's add it to the note's parent (which should be 'game')
+ if (self.parent) {
+ // Ensure note has a parent
+ // Position needs to be absolute if added to game layer
+ scorePopup.x = self.x + 0; // (self.x (Note's absolute X) + relative X (0))
+ scorePopup.y = self.y - SWIPE_NOTE_WIDTH * self.scale.y / 2 - 30; // (self.y (Note's absolute Y) + relative Y)
+ self.parent.addChild(scorePopup); // Add to the same layer as the note
+ }
+ tween(scorePopup, {
+ y: scorePopup.y - 80,
+ // Animacja w górę
+ alpha: 0
+ }, {
+ duration: 700,
+ // Dłuższy czas trwania animacji
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ if (scorePopup.parent) {
+ scorePopup.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;
}
@@ -97,24 +179,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;
- 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();
@@ -144,114 +234,1621 @@
/****
* Game Code
****/
+var testGuiShape; // Bright green box
+var testGuiElement = LK.getAsset('testTopGui', {
+ x: 100,
+ y: 100,
+ anchorX: 0,
+ anchorY: 0
+});
+LK.gui.top.addChild(testGuiElement);
+console.log("Attempted to add testGuiElement to LK.gui.top", testGuiElement);
var gameScreenWidth = 2048;
-var playfieldWidth = 1408; // Narrower playfield
-var playfieldStartX = (gameScreenWidth - playfieldWidth) / 2; // 320
+var playfieldWidth = 1408;
+var playfieldStartX = (gameScreenWidth - playfieldWidth) / 2;
var NUM_COLUMNS = 4;
-var columnWidth = playfieldWidth / NUM_COLUMNS; // 352
+var columnWidth = playfieldWidth / NUM_COLUMNS;
var columnCenterXs = [];
for (var i = 0; i < NUM_COLUMNS; i++) {
columnCenterXs.push(playfieldStartX + i * columnWidth + columnWidth / 2);
}
-// New columnCenterXs for playfieldWidth = 1408, starting at X = 320:
-// columnCenterXs[0] = 320 + 176 = 496
-// columnCenterXs[1] = 496 + 352 = 848
-// columnCenterXs[2] = 848 + 352 = 1200
-// columnCenterXs[3] = 1200 + 352 = 1552
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
-}, {
- // Wider swipe between new col 1 and col 2 (centers 848 and 1200)
- // Midpoint is (848 + 1200) / 2 = 1024
- 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
-}, {
- // Wider swipe between new col 0 and col 1 (centers 496 and 848)
- // Midpoint is (496 + 848) / 2 = 672
- 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;
-var hitWindowPerfect = 120;
+// 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 = 190;
var hitWindowGood = 260;
var MIN_SWIPE_DISTANCE = 60;
var notes = [];
var nextNoteIdx = 0;
@@ -262,29 +1859,35 @@
var swipeStart = null;
var inputLocked = false;
var scoreTxt = new Text2('Score: 0', {
size: 100,
- fill: 0xFFFFFF
+ // Możemy dostosować, jeśli za duże/małe
+ fill: 0xFFFFFF,
+ // Biały
+ alpha: 1
});
-scoreTxt.anchor.set(0.5, 0);
+scoreTxt.anchor.set(1, 1); // Kotwiczenie na środku obiektu Tekstowego
scoreTxt.x = gameScreenWidth / 2;
-scoreTxt.y = 20;
+scoreTxt.y = 80; // Trochę niżej niż pierwotne 20, aby dać więcej miejsca od góry
LK.gui.top.addChild(scoreTxt);
+console.log("Restored scoreTxt: X=" + scoreTxt.x + " Y=" + scoreTxt.y + " Visible:" + scoreTxt.visible);
var comboTxt = new Text2('Combo: 0', {
size: 80,
- fill: 0xFFFF00
+ fill: 0xFFFF00,
+ // Żółty
+ alpha: 1
});
-comboTxt.anchor.set(0.5, 0);
+comboTxt.anchor.set(0.5, 0.5); // Kotwiczenie na środku obiektu Tekstowego
comboTxt.x = gameScreenWidth / 2;
-comboTxt.y = 130;
+comboTxt.y = scoreTxt.y + scoreTxt.height / 2 + 60; // Pozycjonowanie poniżej scoreTxt, uwzględniając jego wysokość
LK.gui.top.addChild(comboTxt);
+console.log("Restored comboTxt: X=" + comboTxt.x + " Y=" + comboTxt.y + " Visible:" + comboTxt.visible);
var hitZoneY = 1800;
-var hitZoneVisualWidth = playfieldWidth; // Line width matches the new playfield width
+var hitZoneVisualWidth = playfieldWidth;
var hitZoneLine = LK.getAsset('lineAsset', {
anchorX: 0.5,
anchorY: 0.5,
x: gameScreenWidth / 2,
- // Centered on the whole screen, but visual width is playfieldWidth
y: hitZoneY,
width: hitZoneVisualWidth,
height: 4,
alpha: 0.6
@@ -294,9 +1897,11 @@
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();
+ if (n && n.parent) {
+ n.destroy();
+ }
});
notes = [];
nextNoteIdx = 0;
score = 0;
@@ -306,34 +1911,73 @@
inputLocked = false;
scoreTxt.setText('Score: 0');
comboTxt.setText('Combo: 0');
}
+function loadSong(songKey) {
+ var songData = allSongData[songKey];
+ if (!songData || !songData.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;
+ }
+ }
+ // Zatrzymanie poprzedniej muzyki, jeśli grała
+ if (currentMusic && typeof currentMusic.stop === 'function') {
+ currentMusic.stop();
+ }
+ currentMusic = null;
+ resetGameState();
+ nextNoteIdx = 0;
+ // Przetwarzamy mapę PRZED ustawieniem gameStartTime i startem muzyki
+ currentActiveRhythmMap = processRawRhythmMap(songData.rawRhythmMap, songKey);
+ // Ustawiamy gameStartTime BEZPOŚREDNIO PRZED próbą startu muzyki
+ gameStartTime = Date.now();
+ if (songData.musicAsset) {
+ currentMusic = LK.getSound(songData.musicAsset);
+ if (currentMusic && typeof currentMusic.play === 'function') {
+ currentMusic.play();
+ console.log("Music asset for " + songKey + " PLAYING. gameStartTime: " + gameStartTime);
+ } else {
+ console.log("Warning: Music asset '" + songData.musicAsset + "' not found or not playable.");
+ }
+ } else {
+ console.log("No musicAsset defined for " + songKey + ". Map will run on system time only.");
+ }
+ 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) {
- // Ensure the noteAsset (specifically swipeNote) is defined for SWIPE_NOTE_WIDTH
- // For wider swipes, their visual representation is two standard swipe notes
if (noteData.partOfWiderSwipe === 'leftHalf') {
targetCenterX = noteData.widerSwipePairCenterX - SWIPE_NOTE_WIDTH / 2;
} else if (noteData.partOfWiderSwipe === 'rightHalf') {
targetCenterX = noteData.widerSwipePairCenterX + SWIPE_NOTE_WIDTH / 2;
} else {
- 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 {
- // Fallback for notes without proper column/widerSwipe info (e.g. old map format)
- // Place in the center of the new, narrower playfield
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++;
@@ -345,14 +1989,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);
@@ -372,12 +2019,13 @@
if (timeDiff > hitWindowGood) {
continue;
}
var currentNoteAsset = n.noteAsset;
- if (!currentNoteAsset) continue; // Should not happen if note is properly initialized
+ if (!currentNoteAsset) {
+ continue;
+ }
var currentNoteWidth = currentNoteAsset.width * n.scale.x;
var currentNoteHeight = currentNoteAsset.height * n.scale.y;
- // If swipeNote, use SWIPE_NOTE_WIDTH for consistency, as its asset is square
if (n.noteType === 'swipe') {
currentNoteWidth = SWIPE_NOTE_WIDTH * n.scale.x;
currentNoteHeight = SWIPE_NOTE_WIDTH * n.scale.y;
}
@@ -405,24 +2053,47 @@
if (combo > maxCombo) {
maxCombo = combo;
}
comboTxt.setText('Combo: ' + combo);
+ // Animacja dla comboTxt
+ if (combo > 1) {
+ // Mała animacja tylko jeśli combo jest większe niż 1
+ var originalScale = comboTxt.scale.x; // Zakładamy, że skala X i Y jest taka sama
+ tween(comboTxt.scale, {
+ x: originalScale * 1.3,
+ y: originalScale * 1.3
+ }, {
+ duration: 100,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(comboTxt.scale, {
+ x: originalScale,
+ y: originalScale
+ }, {
+ duration: 100,
+ easing: tween.easeIn
+ });
+ }
+ });
+ }
}
function resetCombo() {
combo = 0;
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);
}
}
game.onNoteMiss = function (note) {
- if (!note || note.judged) return;
+ if (!note || note.judged) {
+ return;
+ }
note.judged = true;
note.showHitFeedback('miss');
resetCombo();
if (note.parent) {
@@ -469,8 +2140,9 @@
}
};
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;
@@ -478,8 +2150,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 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;
@@ -487,59 +2163,97 @@
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) 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
};
- if (rectsIntersect(swipeBoundingBox, noteBoundingBox)) {
+ 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) {
- if (Math.abs(n.y - n.centerY) < noteCurrentHeight / 1.5) {
+ 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); // Or use n.y proximity to centerY
+ var da = Math.abs(swipeEndTime - a.targetHitTime);
var db = Math.abs(swipeEndTime - b.targetHitTime);
return da - db;
});
- var maxNotesToHitPerSwipe = notesHitThisSwipe.length > 1 && notesHitThisSwipe[0].widerSwipePairCenterX !== undefined ? 2 : 1;
- // If it's a wider swipe candidate, allow hitting up to 2, otherwise just 1.
- // This check is a bit simplistic, assumes wider swipe notes are sorted first if both are hit.
- // A more robust way would be to check if the hit notes form a valid wider swipe pair.
+ 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 (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);
@@ -549,9 +2263,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 candidates after iterating.");
}
+ } else {
+ console.log("Swipe too short (Dist: " + dist + ", Min: " + MIN_SWIPE_DISTANCE + ")");
}
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
@@ -568,6 +2289,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