Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;' Line Number: 359
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;' Line Number: 359
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
Code edit (18 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ggame is not defined' in or related to this line: 'ggame.update = function () {' Line Number: 1468
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (4 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'height')' in or related to this line: 'LK.gui.top.add(new Text2('SONG ENDED', {' Line Number: 920
Code edit (11 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'height')' in or related to this line: 'playerHpBarContainer.y = LK.data.height - 80; // Pozycja Y na dole (LK.data.height to wysokość ekranu)' Line Number: 698
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 (6 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'stringify')' in or related to this line: 'console.log("Swipe BBox:", JSON.stringify(swipeBoundingBox));' Line Number: 497
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Graphics is not a constructor' in or related to this line: 'var hitZoneLine = new Graphics();' Line Number: 242
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: LK.getTime is not a function' in or related to this line: 'var now = LK.getTime();' Line Number: 535
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Visual width of swipeNote asset
var Note = Container.expand(function (noteType, swipeDir, targetHitTimeFull, centerXVal) {
var self = Container.call(this);
self.noteType = noteType || 'tap';
self.swipeDir = swipeDir || null;
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;
if (self.noteType === 'tap') {
self.noteAsset = self.attachAsset('tapNote', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.noteType === 'swipe') {
self.noteAsset = self.attachAsset('swipeNote', {
anchorX: 0.5,
anchorY: 0.5
});
if (self.swipeDir) {
var arrow = new Text2('', {
size: 80,
fill: 0xFFFFFF
});
arrow.anchor.set(0.5, 0.5);
if (self.swipeDir === 'left') {
arrow.setText('←');
} else if (self.swipeDir === 'right') {
arrow.setText('→');
} else if (self.swipeDir === 'up') {
arrow.setText('↑');
} else if (self.swipeDir === 'down') {
arrow.setText('↓');
}
self.addChild(arrow);
self.arrow = arrow;
}
} else if (self.noteType === 'trap') {
self.noteAsset = self.attachAsset('trapNote', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.alpha = 0;
self.showHitFeedback = function (result) {
var feedback = LK.getAsset('hitFeedback', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 0.7,
scaleY: 0.7,
alpha: 0.7
});
if (result === 'perfect') {
feedback.tint = 0xffff00;
} else if (result === 'good') {
feedback.tint = 0x00ff00;
} else {
feedback.tint = 0xff0000;
}
// Ensure feedback is added to the note itself, so its position is relative
self.addChild(feedback);
tween(feedback, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 350,
easing: tween.easeOut,
onFinish: function onFinish() {
if (feedback.parent) {
feedback.destroy();
}
}
});
};
self.update = function () {
var now = Date.now();
if (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;
if (progress < 0) {
progress = 0;
}
if (progress > 1) {
progress = 1;
}
var currentScale = self.scaleStart + (self.scaleEnd - self.scaleStart) * progress;
// Ensure scale doesn't go to 0 or negative if times are weird
self.scale.x = Math.max(0.01, currentScale);
self.scale.y = Math.max(0.01, currentScale);
self.x = self.centerX;
self.y = self.startY + (self.centerY - self.startY) * progress;
if (!self.judged && now > self.targetHitTime + hitWindowGood) {
self.judged = true;
if (self.noteType !== 'trap') {
game.onNoteMiss(self);
}
}
};
self.isInHitWindow = function () {
var now = Date.now();
var dt = Math.abs(now - self.targetHitTime);
return dt <= hitWindowGood;
};
self.getHitAccuracy = function () {
var now = Date.now();
var dt = Math.abs(now - self.targetHitTime);
if (dt <= hitWindowPerfect) {
return 'perfect';
}
if (dt <= hitWindowGood) {
return 'good';
}
return 'miss';
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181828
});
/****
* Game Code
****/
var gameScreenWidth = 2048;
var NUM_COLUMNS = 4;
var columnWidth = gameScreenWidth / NUM_COLUMNS; // 512
var columnCenterXs = [];
for (var i = 0; i < NUM_COLUMNS; i++) {
columnCenterXs.push(i * columnWidth + columnWidth / 2);
}
// columnCenterXs will be [256, 768, 1280, 1792]
var SWIPE_NOTE_WIDTH = 160;
var rhythmMap = [{
time: 1000,
type: 'tap',
columnIndex: 0
}, {
time: 1800,
type: 'tap',
columnIndex: 1
}, {
time: 2600,
type: 'swipe',
swipeDir: 'left',
columnIndex: 2
}, {
time: 3400,
type: 'tap',
columnIndex: 3
}, {
time: 4200,
type: 'swipe',
swipeDir: 'right',
columnIndex: 0
}, {
time: 5000,
type: 'trap',
columnIndex: 1
}, {
time: 5800,
type: 'tap',
columnIndex: 2
}, {
// Example of a "wider swipe" (horizontal right)
time: 6600,
type: 'swipe',
swipeDir: 'right',
partOfWiderSwipe: 'leftHalf',
widerSwipePairCenterX: (columnCenterXs[1] + columnCenterXs[2]) / 2
}, {
time: 6600,
type: 'swipe',
swipeDir: 'right',
partOfWiderSwipe: 'rightHalf',
widerSwipePairCenterX: (columnCenterXs[1] + columnCenterXs[2]) / 2
}, {
time: 7400,
type: 'tap',
columnIndex: 0
}, {
time: 8200,
type: 'trap',
columnIndex: 3
}, {
time: 9000,
type: 'swipe',
swipeDir: 'down',
columnIndex: 1
}, {
// Example of another "wider swipe" (horizontal left)
time: 9800,
type: 'swipe',
swipeDir: 'left',
partOfWiderSwipe: 'leftHalf',
widerSwipePairCenterX: (columnCenterXs[0] + columnCenterXs[1]) / 2
}, {
time: 9800,
type: 'swipe',
swipeDir: 'left',
partOfWiderSwipe: 'rightHalf',
widerSwipePairCenterX: (columnCenterXs[0] + columnCenterXs[1]) / 2
}, {
time: 10600,
type: 'tap',
columnIndex: 3
}, {
time: 11400,
type: 'swipe',
swipeDir: 'up',
columnIndex: 0
}, {
time: 12200,
type: 'trap',
columnIndex: 1
}, {
time: 13000,
type: 'tap',
columnIndex: 2
}];
var noteTravelTime = 1200;
var hitWindowPerfect = 120;
var hitWindowGood = 260;
var MIN_SWIPE_DISTANCE = 60;
var notes = [];
var nextNoteIdx = 0;
var gameStartTime = 0;
var score = 0;
var combo = 0;
var maxCombo = 0;
var swipeStart = null;
var inputLocked = false;
var scoreTxt = new Text2('Score: 0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.x = gameScreenWidth / 2;
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
var comboTxt = new Text2('Combo: 0', {
size: 80,
fill: 0xFFFF00
});
comboTxt.anchor.set(0.5, 0);
comboTxt.x = gameScreenWidth / 2;
comboTxt.y = 130;
LK.gui.top.addChild(comboTxt);
var hitZoneY = 1800;
var hitZoneWidth = gameScreenWidth * 0.95;
var hitZoneLine = LK.getAsset('lineAsset', {
anchorX: 0.5,
anchorY: 0.5,
x: gameScreenWidth / 2,
y: hitZoneY,
width: hitZoneWidth,
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 spawnNotes() {
var now = Date.now();
while (nextNoteIdx < rhythmMap.length) {
var noteData = rhythmMap[nextNoteIdx];
var noteTargetHitTime = gameStartTime + noteData.time;
var noteVisualSpawnTime = noteTargetHitTime - noteTravelTime;
if (noteVisualSpawnTime <= now) {
var targetCenterX;
if (noteData.partOfWiderSwipe && noteData.widerSwipePairCenterX !== undefined) {
if (noteData.partOfWiderSwipe === 'leftHalf') {
targetCenterX = noteData.widerSwipePairCenterX - SWIPE_NOTE_WIDTH / 2;
} else if (noteData.partOfWiderSwipe === 'rightHalf') {
targetCenterX = noteData.widerSwipePairCenterX + SWIPE_NOTE_WIDTH / 2;
} else {
// Fallback if partOfWiderSwipe has unexpected value
targetCenterX = columnCenterXs[noteData.columnIndex !== undefined ? noteData.columnIndex : Math.floor(NUM_COLUMNS / 2)];
}
} else if (noteData.columnIndex !== undefined && noteData.columnIndex >= 0 && noteData.columnIndex < NUM_COLUMNS) {
targetCenterX = columnCenterXs[noteData.columnIndex];
} else {
targetCenterX = gameScreenWidth / 2; // Fallback for notes without proper column/widerSwipe info
}
var n = new Note(noteData.type, noteData.swipeDir, noteTargetHitTime, targetCenterX);
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];
if (n.judged && now > n.targetHitTime + hitWindowGood + 400) {
if (n.parent) {
n.destroy();
}
notes.splice(i, 1);
} else if (!n.judged && now > n.targetHitTime + noteTravelTime + 500) {
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 currentNoteWidth = (n.noteType === 'swipe' ? SWIPE_NOTE_WIDTH : n.noteAsset.width) * n.scale.x;
var currentNoteHeight = (n.noteType === 'swipe' ? SWIPE_NOTE_WIDTH : n.noteAsset.height) * n.scale.y; // Assuming swipe notes are square
var dx = x - n.x;
var dy = y - n.y;
if (Math.abs(dx) <= currentNoteWidth / 2 && Math.abs(dy) <= currentNoteHeight / 2) {
if (timeDiff < smallestTimeDiff) {
bestNote = n;
smallestTimeDiff = timeDiff;
}
}
}
return bestNote;
}
function addScore(result) {
if (result === 'perfect') {
score += 100;
} else if (result === 'good') {
score += 50;
}
scoreTxt.setText('Score: ' + score);
}
function addCombo() {
combo += 1;
if (combo > maxCombo) {
maxCombo = combo;
}
comboTxt.setText('Combo: ' + combo);
}
function resetCombo() {
combo = 0;
comboTxt.setText('Combo: ' + combo);
}
function checkGameEnd() {
if (nextNoteIdx >= rhythmMap.length && notes.length === 0) {
LK.setTimeout(function () {
if (nextNoteIdx >= rhythmMap.length && notes.length === 0) {
LK.showYouWin();
}
}, 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 End: X=" + swipeEndX + " Y=" + swipeEndY + " Dist=" + 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 + ", width=" + swipeBoundingBox.width + ", height=" + swipeBoundingBox.height);
var notesHitThisSwipe = [];
for (var i = 0; i < notes.length; i++) {
var n = notes[i];
// console.log("Checking Note " + i + ": Type=" + n.noteType + " Judged=" + n.judged + " TargetX=" + n.centerX + " TargetY=" + n.centerY + " CurrentY=" + n.y);
if (n.judged || n.noteType !== 'swipe') {
continue;
}
// console.log("Note " + i + " is a potential swipe target.");
var overallSwipeTimeMatchesNote = false;
if (swipeStart.time <= n.targetHitTime + hitWindowGood && swipeEndTime >= n.targetHitTime - hitWindowGood) {
overallSwipeTimeMatchesNote = true;
}
if (!overallSwipeTimeMatchesNote) {
// Secondary check
if (swipeStart.time <= n.targetHitTime + hitWindowGood && swipeEndTime >= n.targetHitTime - hitWindowGood) {
overallSwipeTimeMatchesNote = true;
}
}
// console.log("Note " + i + " - overallSwipeTimeMatchesNote: " + overallSwipeTimeMatchesNote + " (SwipeStart: " + swipeStart.time + ", SwipeEnd: " + swipeEndTime + ", NoteTarget: " + n.targetHitTime + ", Window: " + hitWindowGood + ")");
if (!overallSwipeTimeMatchesNote) {
// console.log("Note " + i + " rejected: Swipe time does not match note time window.");
continue;
}
if (n.alpha === 0) {
// console.log("Note " + i + " rejected: Note alpha is 0 (not visible/active).");
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:", JSON.stringify(noteBoundingBox));
if (rectsIntersect(swipeBoundingBox, noteBoundingBox)) {
console.log("Note " + i + " INTERSECTS with swipe BBox.");
if (detectedDir === n.swipeDir) {
console.log("Note " + i + " Direction MATCH. Detected: " + detectedDir + ", Expected: " + n.swipeDir);
var verticalCheckTolerance = noteCurrentHeight / 1.5;
// console.log("Note " + i + " Vertical Check: |" + n.y + " - " + n.centerY + "| < " + verticalCheckTolerance + " ? Result: " + (Math.abs(n.y - n.centerY) < verticalCheckTolerance));
if (Math.abs(n.y - n.centerY) < verticalCheckTolerance) {
console.log("Note " + i + " PASSED vertical proximity check. Adding to hits.");
notesHitThisSwipe.push(n);
} else {
// console.log("Note " + i + " FAILED vertical proximity check.");
}
} else {
// console.log("Note " + i + " Direction MISMATCH. Detected: " + detectedDir + ", Expected: " + n.swipeDir);
}
} else {
// console.log("Note " + i + " does NOT intersect with swipe BBox.");
}
}
if (notesHitThisSwipe.length > 0) {
console.log("Processing " + notesHitThisSwipe.length + " notes hit by this swipe.");
notesHitThisSwipe.sort(function (a, b) {
var da = Math.abs(swipeEndTime - a.targetHitTime);
var db = Math.abs(swipeEndTime - b.targetHitTime);
return da - db;
});
var maxNotesToHitPerSwipe = 2;
var notesActuallyHitCount = 0;
for (var k = 0; k < notesHitThisSwipe.length && k < maxNotesToHitPerSwipe; k++) {
var noteToJudge = notesHitThisSwipe[k];
if (noteToJudge.judged) {
// console.log("Note " + noteToJudge.idx_in_notes_array_for_debug + " already judged, skipping."); // Potrzebowalibyśmy jakiegoś ID notatki
continue;
}
var result = noteToJudge.getHitAccuracy();
console.log("Judging Note Hit! Result: " + result);
noteToJudge.judged = true;
noteToJudge.showHitFeedback(result);
if (result !== 'miss') {
addScore(result);
addCombo();
} else {
resetCombo();
}
swipedNoteSuccessfully = true;
notesActuallyHitCount++;
}
} else {
console.log("No notes were successfully hit by this swipe action.");
}
} else {
console.log("Swipe too short or not considered potential.");
}
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();
};
resetGameState();
gameStartTime = Date.now(); ===================================================================
--- original.js
+++ change.js
@@ -5,9 +5,10 @@
/****
* Classes
****/
-var Note = Container.expand(function (noteType, swipeDir, targetHitTimeFull) {
+// Visual width of swipeNote asset
+var Note = Container.expand(function (noteType, swipeDir, targetHitTimeFull, centerXVal) {
var self = Container.call(this);
self.noteType = noteType || 'tap';
self.swipeDir = swipeDir || null;
self.targetHitTime = targetHitTimeFull;
@@ -15,9 +16,9 @@
self.hit = false;
self.judged = false;
self.scaleStart = 0.3;
self.scaleEnd = 1.2;
- self.centerX = 2048 / 2;
+ self.centerX = centerXVal;
self.centerY = 1800;
self.startY = 600;
self.noteAsset = null;
if (self.noteType === 'tap') {
@@ -26,16 +27,14 @@
anchorY: 0.5
});
} else if (self.noteType === 'swipe') {
self.noteAsset = self.attachAsset('swipeNote', {
- // Will use the square definition
anchorX: 0.5,
anchorY: 0.5
});
if (self.swipeDir) {
var arrow = new Text2('', {
size: 80,
- // Arrow size
fill: 0xFFFFFF
});
arrow.anchor.set(0.5, 0.5);
if (self.swipeDir === 'left') {
@@ -73,8 +72,9 @@
feedback.tint = 0x00ff00;
} else {
feedback.tint = 0xff0000;
}
+ // Ensure feedback is added to the note itself, so its position is relative
self.addChild(feedback);
tween(feedback, {
alpha: 0,
scaleX: 1.5,
@@ -105,11 +105,12 @@
}
if (progress > 1) {
progress = 1;
}
- var scale = self.scaleStart + (self.scaleEnd - self.scaleStart) * progress;
- self.scale.x = scale;
- self.scale.y = scale;
+ var currentScale = self.scaleStart + (self.scaleEnd - self.scaleStart) * progress;
+ // Ensure scale doesn't go to 0 or negative if times are weird
+ self.scale.x = Math.max(0.01, currentScale);
+ self.scale.y = Math.max(0.01, currentScale);
self.x = self.centerX;
self.y = self.startY + (self.centerY - self.startY) * progress;
if (!self.judged && now > self.targetHitTime + hitWindowGood) {
self.judged = true;
@@ -146,67 +147,108 @@
/****
* Game Code
****/
-// Changed to square
+var gameScreenWidth = 2048;
+var NUM_COLUMNS = 4;
+var columnWidth = gameScreenWidth / NUM_COLUMNS; // 512
+var columnCenterXs = [];
+for (var i = 0; i < NUM_COLUMNS; i++) {
+ columnCenterXs.push(i * columnWidth + columnWidth / 2);
+}
+// columnCenterXs will be [256, 768, 1280, 1792]
+var SWIPE_NOTE_WIDTH = 160;
var rhythmMap = [{
time: 1000,
- type: 'tap'
+ type: 'tap',
+ columnIndex: 0
}, {
time: 1800,
- type: 'tap'
+ type: 'tap',
+ columnIndex: 1
}, {
time: 2600,
type: 'swipe',
- swipeDir: 'left'
+ swipeDir: 'left',
+ columnIndex: 2
}, {
time: 3400,
- type: 'tap'
+ type: 'tap',
+ columnIndex: 3
}, {
time: 4200,
type: 'swipe',
- swipeDir: 'right'
+ swipeDir: 'right',
+ columnIndex: 0
}, {
time: 5000,
- type: 'trap'
+ type: 'trap',
+ columnIndex: 1
}, {
time: 5800,
- type: 'tap'
+ type: 'tap',
+ columnIndex: 2
}, {
+ // Example of a "wider swipe" (horizontal right)
time: 6600,
type: 'swipe',
- swipeDir: 'up'
+ 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'
+ type: 'tap',
+ columnIndex: 0
}, {
time: 8200,
- type: 'trap'
+ type: 'trap',
+ columnIndex: 3
}, {
time: 9000,
type: 'swipe',
- swipeDir: 'down'
+ swipeDir: 'down',
+ columnIndex: 1
}, {
+ // Example of another "wider swipe" (horizontal left)
time: 9800,
- type: 'tap'
+ 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'
+ type: 'tap',
+ columnIndex: 3
}, {
time: 11400,
type: 'swipe',
- swipeDir: 'left'
+ swipeDir: 'up',
+ columnIndex: 0
}, {
time: 12200,
- type: 'trap'
+ type: 'trap',
+ columnIndex: 1
}, {
time: 13000,
- type: 'tap'
+ type: 'tap',
+ columnIndex: 2
}];
var noteTravelTime = 1200;
var hitWindowPerfect = 120;
var hitWindowGood = 260;
-var MIN_SWIPE_DISTANCE = 60; // Minimum distance for a swipe to be registered
+var MIN_SWIPE_DISTANCE = 60;
var notes = [];
var nextNoteIdx = 0;
var gameStartTime = 0;
var score = 0;
@@ -218,32 +260,39 @@
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
-scoreTxt.x = 2048 / 2;
+scoreTxt.x = gameScreenWidth / 2;
scoreTxt.y = 20;
LK.gui.top.addChild(scoreTxt);
var comboTxt = new Text2('Combo: 0', {
size: 80,
fill: 0xFFFF00
});
comboTxt.anchor.set(0.5, 0);
-comboTxt.x = 2048 / 2;
+comboTxt.x = gameScreenWidth / 2;
comboTxt.y = 130;
LK.gui.top.addChild(comboTxt);
-var hitZoneY = 1800; // Matches Note's centerY
-var hitZoneLine = new Graphics();
-hitZoneLine.lineStyle(4, 0xAAAAAA, 0.6);
-var hitZoneWidth = 400; // Visual width of the hit zone line
-hitZoneLine.moveTo(2048 / 2 - hitZoneWidth / 2, hitZoneY);
-hitZoneLine.lineTo(2048 / 2 + hitZoneWidth / 2, hitZoneY);
+var hitZoneY = 1800;
+var hitZoneWidth = gameScreenWidth * 0.95;
+var hitZoneLine = LK.getAsset('lineAsset', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: gameScreenWidth / 2,
+ y: hitZoneY,
+ width: hitZoneWidth,
+ 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();
+ if (n && n.parent) {
+ n.destroy();
+ }
});
notes = [];
nextNoteIdx = 0;
score = 0;
@@ -260,13 +309,24 @@
var noteData = rhythmMap[nextNoteIdx];
var noteTargetHitTime = gameStartTime + noteData.time;
var noteVisualSpawnTime = noteTargetHitTime - noteTravelTime;
if (noteVisualSpawnTime <= now) {
- var n = new Note(noteData.type, noteData.swipeDir, noteTargetHitTime);
- n.x = n.centerX;
- n.y = n.startY;
- n.scale.x = n.scaleStart;
- n.scale.y = n.scaleStart;
+ var targetCenterX;
+ if (noteData.partOfWiderSwipe && noteData.widerSwipePairCenterX !== undefined) {
+ if (noteData.partOfWiderSwipe === 'leftHalf') {
+ targetCenterX = noteData.widerSwipePairCenterX - SWIPE_NOTE_WIDTH / 2;
+ } else if (noteData.partOfWiderSwipe === 'rightHalf') {
+ targetCenterX = noteData.widerSwipePairCenterX + SWIPE_NOTE_WIDTH / 2;
+ } else {
+ // Fallback if partOfWiderSwipe has unexpected value
+ targetCenterX = columnCenterXs[noteData.columnIndex !== undefined ? noteData.columnIndex : Math.floor(NUM_COLUMNS / 2)];
+ }
+ } else if (noteData.columnIndex !== undefined && noteData.columnIndex >= 0 && noteData.columnIndex < NUM_COLUMNS) {
+ targetCenterX = columnCenterXs[noteData.columnIndex];
+ } else {
+ targetCenterX = gameScreenWidth / 2; // Fallback for notes without proper column/widerSwipe info
+ }
+ var n = new Note(noteData.type, noteData.swipeDir, noteTargetHitTime, targetCenterX);
n.alpha = 0;
notes.push(n);
game.addChild(n);
nextNoteIdx++;
@@ -304,13 +364,12 @@
var timeDiff = Math.abs(now - n.targetHitTime);
if (timeDiff > hitWindowGood) {
continue;
}
- var currentNoteWidth = n.noteAsset.width * n.scale.x;
- var currentNoteHeight = n.noteAsset.height * n.scale.y;
- var dx = x - n.x; // Distance from input to note's center
+ var currentNoteWidth = (n.noteType === 'swipe' ? SWIPE_NOTE_WIDTH : n.noteAsset.width) * n.scale.x;
+ var currentNoteHeight = (n.noteType === 'swipe' ? SWIPE_NOTE_WIDTH : n.noteAsset.height) * n.scale.y; // Assuming swipe notes are square
+ var dx = x - n.x;
var dy = y - n.y;
- // Check for point within note's bounding box
if (Math.abs(dx) <= currentNoteWidth / 2 && Math.abs(dy) <= currentNoteHeight / 2) {
if (timeDiff < smallestTimeDiff) {
bestNote = n;
smallestTimeDiff = timeDiff;
@@ -347,14 +406,15 @@
}, 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) {
- // Check if note still exists before flashing
LK.effects.flashObject(note, 0xff0000, 300);
}
};
game.down = function (x, y, obj) {
@@ -365,25 +425,25 @@
x: x,
y: y,
time: Date.now()
};
- var trap = findNoteAt(x, y, 'trap');
- if (trap && !trap.judged && trap.isInHitWindow()) {
- trap.judged = true;
- trap.showHitFeedback('miss');
+ 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;
}
- var tap = findNoteAt(x, y, 'tap');
- if (tap && !tap.judged && tap.isInHitWindow()) {
- var result = tap.getHitAccuracy();
- tap.judged = true;
- tap.showHitFeedback(result);
+ 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 {
@@ -397,8 +457,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;
@@ -406,8 +467,9 @@
var swipeEndTime = Date.now();
var dx = swipeEndX - swipeStart.x;
var dy = swipeEndY - swipeStart.y;
var dist = Math.sqrt(dx * dx + dy * dy);
+ console.log("Swipe End: X=" + swipeEndX + " Y=" + swipeEndY + " Dist=" + dist);
var potentialSwipe = dist >= MIN_SWIPE_DISTANCE;
var swipedNoteSuccessfully = false;
if (potentialSwipe) {
var detectedDir = null;
@@ -415,81 +477,112 @@
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)
};
- var bestSwipedNote = null;
- var bestSwipedNoteTimeDiff = hitWindowGood + 1;
+ console.log("Swipe BBox: x=" + swipeBoundingBox.x + ", y=" + swipeBoundingBox.y + ", width=" + swipeBoundingBox.width + ", height=" + swipeBoundingBox.height);
+ var notesHitThisSwipe = [];
for (var i = 0; i < notes.length; i++) {
var n = notes[i];
+ // console.log("Checking Note " + i + ": Type=" + n.noteType + " Judged=" + n.judged + " TargetX=" + n.centerX + " TargetY=" + n.centerY + " CurrentY=" + n.y);
if (n.judged || n.noteType !== 'swipe') {
continue;
}
- // Check if the swipe *action time* is within the note's hit window
- var timeDiffWithSwipeEnd = Math.abs(swipeEndTime - n.targetHitTime);
- if (timeDiffWithSwipeEnd > hitWindowGood) {
- // Check also with swipe start time for very fast notes / slow swipes
- var timeDiffWithSwipeStart = Math.abs(swipeStart.time - n.targetHitTime);
- if (timeDiffWithSwipeStart > hitWindowGood && (swipeStart.time > n.targetHitTime + hitWindowGood || swipeEndTime < n.targetHitTime - hitWindowGood)) {
- continue;
+ // console.log("Note " + i + " is a potential swipe target.");
+ var overallSwipeTimeMatchesNote = false;
+ if (swipeStart.time <= n.targetHitTime + hitWindowGood && swipeEndTime >= n.targetHitTime - hitWindowGood) {
+ overallSwipeTimeMatchesNote = true;
+ }
+ if (!overallSwipeTimeMatchesNote) {
+ // Secondary check
+ if (swipeStart.time <= n.targetHitTime + hitWindowGood && swipeEndTime >= n.targetHitTime - hitWindowGood) {
+ overallSwipeTimeMatchesNote = true;
}
}
- // Check if the note itself is visually near the hit line at the moment of swipe evaluation
- // This can be tricky because the note is moving. We rely more on its targetHitTime.
- // However, we should only consider notes that are "active" (alpha=1)
- if (n.alpha === 0) continue;
- var noteCurrentWidth = n.noteAsset.width * n.scale.x;
- var noteCurrentHeight = n.noteAsset.height * n.scale.y;
+ // console.log("Note " + i + " - overallSwipeTimeMatchesNote: " + overallSwipeTimeMatchesNote + " (SwipeStart: " + swipeStart.time + ", SwipeEnd: " + swipeEndTime + ", NoteTarget: " + n.targetHitTime + ", Window: " + hitWindowGood + ")");
+ if (!overallSwipeTimeMatchesNote) {
+ // console.log("Note " + i + " rejected: Swipe time does not match note time window.");
+ continue;
+ }
+ if (n.alpha === 0) {
+ // console.log("Note " + i + " rejected: Note alpha is 0 (not visible/active).");
+ 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:", JSON.stringify(noteBoundingBox));
if (rectsIntersect(swipeBoundingBox, noteBoundingBox)) {
+ console.log("Note " + i + " INTERSECTS with swipe BBox.");
if (detectedDir === n.swipeDir) {
- // If multiple notes intersect, prefer the one closest to its targetHitTime
- var currentNoteTimeDiff = Math.abs(swipeEndTime - n.targetHitTime); // Or average swipe time
- if (bestSwipedNote === null || currentNoteTimeDiff < bestSwipedNoteTimeDiff) {
- bestSwipedNote = n;
- bestSwipedNoteTimeDiff = currentNoteTimeDiff;
+ console.log("Note " + i + " Direction MATCH. Detected: " + detectedDir + ", Expected: " + n.swipeDir);
+ var verticalCheckTolerance = noteCurrentHeight / 1.5;
+ // console.log("Note " + i + " Vertical Check: |" + n.y + " - " + n.centerY + "| < " + verticalCheckTolerance + " ? Result: " + (Math.abs(n.y - n.centerY) < verticalCheckTolerance));
+ if (Math.abs(n.y - n.centerY) < verticalCheckTolerance) {
+ console.log("Note " + i + " PASSED vertical proximity check. Adding to hits.");
+ notesHitThisSwipe.push(n);
+ } else {
+ // console.log("Note " + i + " FAILED vertical proximity check.");
}
+ } else {
+ // console.log("Note " + i + " Direction MISMATCH. Detected: " + detectedDir + ", Expected: " + n.swipeDir);
}
+ } else {
+ // console.log("Note " + i + " does NOT intersect with swipe BBox.");
}
}
- if (bestSwipedNote) {
- var noteToJudge = bestSwipedNote;
- var result = noteToJudge.getHitAccuracy(); // Uses note's targetHitTime vs now (swipeEndTime)
- noteToJudge.judged = true;
- noteToJudge.showHitFeedback(result);
- if (result !== 'miss') {
- addScore(result);
- addCombo();
- } else {
- resetCombo();
+ if (notesHitThisSwipe.length > 0) {
+ console.log("Processing " + notesHitThisSwipe.length + " notes hit by this swipe.");
+ notesHitThisSwipe.sort(function (a, b) {
+ var da = Math.abs(swipeEndTime - a.targetHitTime);
+ var db = Math.abs(swipeEndTime - b.targetHitTime);
+ return da - db;
+ });
+ var maxNotesToHitPerSwipe = 2;
+ var notesActuallyHitCount = 0;
+ for (var k = 0; k < notesHitThisSwipe.length && k < maxNotesToHitPerSwipe; k++) {
+ var noteToJudge = notesHitThisSwipe[k];
+ if (noteToJudge.judged) {
+ // console.log("Note " + noteToJudge.idx_in_notes_array_for_debug + " already judged, skipping."); // Potrzebowalibyśmy jakiegoś ID notatki
+ continue;
+ }
+ var result = noteToJudge.getHitAccuracy();
+ console.log("Judging Note Hit! Result: " + result);
+ noteToJudge.judged = true;
+ noteToJudge.showHitFeedback(result);
+ if (result !== 'miss') {
+ addScore(result);
+ addCombo();
+ } else {
+ resetCombo();
+ }
+ swipedNoteSuccessfully = true;
+ notesActuallyHitCount++;
}
- swipedNoteSuccessfully = true;
+ } else {
+ console.log("No notes were successfully hit by this swipe action.");
}
+ } else {
+ console.log("Swipe too short or not considered potential.");
}
- if (potentialSwipe && !swipedNoteSuccessfully) {
- // Optional: If it was a swipe but didn't hit anything relevant,
- // one might still want to reset combo if that's the desired game feel.
- // For now, only a judged miss on a note resets combo.
- }
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
- }, 120); // Short lock to prevent accidental double inputs from one action
+ }, 80);
swipeStart = null;
};
-game.move = function (x, y, obj) {
- // Not used for now
-};
+game.move = function (x, y, obj) {};
game.update = function () {
spawnNotes();
for (var i = 0; i < notes.length; i++) {
if (notes[i] && notes[i].update) {