User prompt
make stars at the same position as targets (x aligned with lanes and y = hitLineY)
Code edit (17 edits merged)
Please save this source code
User prompt
Set speedMultiplier to 1.0
Code edit (1 edits merged)
Please save this source code
User prompt
Add a rating system: 0 or 1 miss/too early => 3 stars <=50% miss/too early => 2 stars >50% miss/too early => 1 star 100% miss/too early => 0 stars
User prompt
pop (destroy) notes that are taped too early
User prompt
reset combo if note is tapped too early or missed
Code edit (3 edits merged)
Please save this source code
User prompt
play click sound only on menu tile selection, not on menu drag
User prompt
Currently when we drag the menu list and then release, the menu tile is clicked/selected; => diferentiate between drag and click/selection
User prompt
Now there are many songs and many menu tiles, Implement scroll in menu tile list
Code edit (6 edits merged)
Please save this source code
User prompt
change the startbutton anim from a small rotation back and forth to a full continuous rotation ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (4 edits merged)
Please save this source code
User prompt
when a note is tapped too early animate comboTxt with "Too early!" (like for "Missed!") ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
In Note down, if the note is tapped before reaching hitlineY -320 then play tapMiss instead of the note sound
User prompt
for `var delta = Math.abs(songElapsed - note.hitTime);` use a calculation with note y and hitLineY instead
User prompt
when a note is tapped before reaching a target then play tapMiss instead of the note sound
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
use the LK score system too
Code edit (1 edits merged)
Please save this source code
User prompt
play menuSpawn when spawning a menu tile
Code edit (3 edits merged)
Please save this source code
User prompt
in pulse anim, replace tween on scale by a tween on rotation (small rotation left then small rotation right)
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BackgroundManager = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('background00', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); return self; }); var ComboText = Container.expand(function () { var self = Container.call(this); self.textObj = new Text2('', { size: 80, fill: 0xFFFFFF, dropShadow: true }); self.textObj.anchor.set(0.5, 0); self.addChild(self.textObj); self.setText = function (txt) { self.textObj.setText(txt); tween.stop(self.textObj, { scaleX: true, scaleY: true, alpha: true }); if (txt && txt.length > 0) { self.textObj.alpha = 1; self.textObj.scaleX = 1.0; self.textObj.scaleY = 1.0; tween(self.textObj, { scaleX: 1.25, scaleY: 1.25 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { tween(self.textObj, { scaleX: 1.0, scaleY: 1.0 }, { duration: 120, easing: tween.cubicIn }); } }); } else { tween(self.textObj, { alpha: 0 }, { duration: 180 }); } }; return self; }); var MenuButton = Container.expand(function () { var self = Container.call(this); var icon = self.attachAsset('menuIcon', { anchorX: 0.5, anchorY: 0.5 }); self.down = function (x, y, obj) { tween(self, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicOut }); }; self.up = function (x, y, obj) { tween(self, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { LK.stopMusic(); gameActive = false; if (noteManager) { noteManager.reset(); } if (scoreTxt) { scoreTxt.visible = false; } if (comboTxt) { comboTxt.setText(''); } if (laneHighlights) { for (var i = 0; i < laneHighlights.length; i++) { laneHighlights[i].visible = false; } } if (targets) { for (var i = 0; i < targets.length; i++) { targets[i].visible = false; } } if (restartBtn) { restartBtn.visible = false; } self.visible = false; if (menuManager) { menuManager.show(); } } }); }; return self; }); var MenuManager = Container.expand(function () { var self = Container.call(this); self.menuTiles = []; self.scrollContainer = new Container(); self.addChild(self.scrollContainer); self.scrollY = 0; self.targetScrollY = 0; self.lastTouchY = 0; self.isDragging = false; self.dragVelocity = 0; self.lastDragTime = 0; self.minScrollY = 0; self.maxScrollY = 0; self.dragStartY = 0; self.dragDistance = 0; self.dragThreshold = 10; self.createMenuTiles = function (songs) { for (var i = 0; i < self.menuTiles.length; i++) { self.menuTiles[i].destroy(); } self.menuTiles = []; var tileHeight = 300; var tileSpacing = 260; var startY = 500; for (var i = 0; i < songs.length; i++) { var tile = new MenuTile(); tile.x = 2048 / 2; tile.y = startY + i * (tileHeight + tileSpacing); tile.setText(songs[i].name); tile.songIndex = i; tile.down = function () { var index = this.songIndex; self.dragDistance = 0; if (Math.abs(self.dragVelocity) < 5) { tween(this, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.cubicOut }); } }; tile.up = function () { var index = this.songIndex; if (self.dragDistance < self.dragThreshold && Math.abs(self.dragVelocity) < 5) { LK.getSound('click').play(); tween(this, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { if (self.onSongSelected) { self.onSongSelected(index); } } }); } else { tween(this, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.cubicIn }); } }; self.scrollContainer.addChild(tile); self.menuTiles.push(tile); } var lastTileY = startY + (songs.length - 1) * (tileHeight + tileSpacing); self.maxScrollY = 0; self.minScrollY = Math.min(0, 2732 - lastTileY - 400); }; self.down = function (x, y, obj) { self.isDragging = true; self.lastTouchY = y; self.dragStartY = y; self.dragDistance = 0; self.dragVelocity = 0; self.lastDragTime = Date.now(); tween.stop(self, { targetScrollY: true }); }; self.move = function (x, y, obj) { if (!self.isDragging) { return; } var deltaY = y - self.lastTouchY; self.targetScrollY += deltaY; self.dragDistance = Math.abs(y - self.dragStartY); if (self.targetScrollY > self.maxScrollY) { self.targetScrollY = self.maxScrollY + (self.targetScrollY - self.maxScrollY) * 0.3; } else if (self.targetScrollY < self.minScrollY) { self.targetScrollY = self.minScrollY + (self.targetScrollY - self.minScrollY) * 0.3; } var now = Date.now(); var deltaTime = now - self.lastDragTime; if (deltaTime > 0) { self.dragVelocity = deltaY / deltaTime * 16; } self.lastTouchY = y; self.lastDragTime = now; }; self.up = function (x, y, obj) { self.isDragging = false; if (Math.abs(self.dragVelocity) > 2) { var momentum = self.dragVelocity * 20; var newTarget = self.targetScrollY + momentum; newTarget = Math.max(self.minScrollY, Math.min(self.maxScrollY, newTarget)); tween(self, { targetScrollY: newTarget }, { duration: 800, easing: tween.cubicOut }); } else { if (self.targetScrollY > self.maxScrollY) { tween(self, { targetScrollY: self.maxScrollY }, { duration: 300, easing: tween.cubicOut }); } else if (self.targetScrollY < self.minScrollY) { tween(self, { targetScrollY: self.minScrollY }, { duration: 300, easing: tween.cubicOut }); } } self.dragVelocity = 0; }; self.update = function () { self.scrollY += (self.targetScrollY - self.scrollY) * 0.2; self.scrollContainer.y = self.scrollY; if (!self.isDragging) { self.dragVelocity *= 0.95; } }; self.onSongSelected = null; self.show = function () { self.visible = true; self.alpha = 0; self.scrollY = 0; self.targetScrollY = 0; self.scrollContainer.y = 0; tween(self, { alpha: 1 }, { duration: 300, easing: tween.cubicOut }); for (var i = 0; i < self.menuTiles.length; i++) { (function (tile, delay) { tile.scaleX = 0.8; tile.scaleY = 0.8; tile.alpha = 0; LK.setTimeout(function () { LK.getSound('menuSpawn').play(); }, delay); tween(tile, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 400, delay: delay, easing: tween.cubicOut, onFinish: function onFinish() {} }); })(self.menuTiles[i], i * 100); } }; self.hide = function () { tween(self, { alpha: 0 }, { duration: 300, easing: tween.cubicIn, onFinish: function onFinish() { self.visible = false; } }); }; return self; }); var MenuTile = Container.expand(function () { var self = Container.call(this); self.tileImg = self.attachAsset('menuTile', { anchorX: 0.5, anchorY: 0.5 }); self.textObj = new Text2('', { size: 100, fill: 0x222222, dropShadow: true }); self.textObj.anchor.set(0, 0.5); self.textObj.x = -self.tileImg.width / 2 + 100; self.textObj.y = 0; self.addChild(self.textObj); self.playBtn = self.attachAsset('playButton', { anchorX: 0.5, anchorY: 0.5, x: self.tileImg.width / 2 - 150, y: 0 }); self.setText = function (txt) { self.textObj.setText(txt); }; return self; }); var Note = Container.expand(function () { var self = Container.call(this); self.noteBall = self.attachAsset('noteDot', { anchorX: 0.5, anchorY: 0.5, alpha: 0.6 }); self.noteSign = self.attachAsset('noteSign', { anchorX: 0.5, anchorY: 0.5 }); self.lane = 0; self.hitTime = 0; self.tapped = false; self.missed = false; self.showTapFeedback = function () { var feedback = self.attachAsset('tapFeedback', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); var sparkles = new Sparkles(); sparkles.x = self.x; sparkles.y = self.y; if (self.parent) { self.parent.addChild(sparkles); } self.noteSign.scaleX = 1; self.noteSign.scaleY = 1; tween(self.noteSign, { scaleX: 3, scaleY: 3 }, { duration: 120, easing: tween.cubicOut, onFinish: function onFinish() {} }); tween(feedback, { alpha: 0 }, { duration: 250, onFinish: function onFinish() { feedback.destroy(); } }); }; self.update = function () { if (!gameActive) { return; } var now = Date.now(); var songElapsed = now - songStartTime; var adjustedTravelTime = noteTravelTime * speedMultiplier; var t = (songElapsed - (self.hitTime - adjustedTravelTime)) / adjustedTravelTime; self.y = noteStartY + (hitLineY - noteStartY) * t + (t > 1 ? (t - 1) * (2732 - hitLineY) : 0); if (!self.tapped && !self.missed && songElapsed > self.hitTime + 220) { self.missed = true; self.alpha = 0.3; combo = 0; failedNotes++; comboTxt.tint = 0xff2222; comboTxt.setText('Missed!'); tween.stop(comboTxt, { scaleX: true, scaleY: true, alpha: true }); comboTxt.scaleX = 1.0; comboTxt.scaleY = 1.0; comboTxt.alpha = 1.0; tween(comboTxt, { scaleX: 2.0, scaleY: 2.0, alpha: 0.0 }, { duration: 600, easing: tween.cubicOut, onFinish: function onFinish() { comboTxt.setText(''); comboTxt.tint = 0x3A8EE6; comboTxt.scaleX = 1.0; comboTxt.scaleY = 1.0; comboTxt.alpha = 1.0; } }); tween(self.noteSign, { tint: 0xff0000 }, { duration: 60, onFinish: function onFinish() { tween(self.noteSign, { tint: 0xffffff }, { duration: 180 }); } }); LK.getSound('tapMiss').play(); } }; self.down = function () { if (self.y < hitLineY - 320) { self.tapped = true; LK.getSound('tapMiss').play(); combo = 0; failedNotes++; comboTxt.tint = 0xff2222; comboTxt.setText('Too early!'); tween.stop(comboTxt, { scaleX: true, scaleY: true, alpha: true }); comboTxt.scaleX = 1.0; comboTxt.scaleY = 1.0; comboTxt.alpha = 1.0; tween(comboTxt, { scaleX: 2.0, scaleY: 2.0, alpha: 0.0 }, { duration: 600, easing: tween.cubicOut, onFinish: function onFinish() { comboTxt.setText(''); comboTxt.tint = 0x3A8EE6; comboTxt.scaleX = 1.0; comboTxt.scaleY = 1.0; comboTxt.alpha = 1.0; } }); tween(self, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 300, easing: tween.cubicOut, onFinish: function onFinish() { self.destroy(); if (noteManager) { noteManager.removeNote(self); } } }); return; } for (var i = 0; i < songNotesRaw.length; i++) { var sn = songNotesRaw[i]; var lane = 0; if (keyToLane.hasOwnProperty(sn.key)) { lane = keyToLane[sn.key]; } else { lane = i % 3; } if (lane === self.lane && sn.time / speedMultiplier === self.hitTime) { if (typeof sn.key === "string") { var keySoundName = sn.key.toLowerCase(); var keySound = LK.getSound(keySoundName); if (keySound) { keySound.play(); } } break; } } }; return self; }); var NoteManager = Container.expand(function () { var self = Container.call(this); self.notes = []; self.nextNoteIdx = 0; self.reset = function () { for (var i = 0; i < self.notes.length; i++) { self.notes[i].destroy(); } self.notes = []; self.nextNoteIdx = 0; }; self.spawnNotes = function (songNotes, songElapsed, noteTravelTime, laneX, noteStartY) { while (self.nextNoteIdx < songNotes.length && songNotes[self.nextNoteIdx].time / speedMultiplier - noteTravelTime <= songElapsed) { var noteData = songNotes[self.nextNoteIdx]; var note = new Note(); note.lane = noteData.lane; note.hitTime = noteData.time / speedMultiplier; note.x = laneX[note.lane]; note.y = noteStartY; self.notes.push(note); game.addChild(note); self.nextNoteIdx++; } }; self.cleanupNotes = function (songElapsed) { for (var i = self.notes.length - 1; i >= 0; i--) { var note = self.notes[i]; if (note.y > 2732 + 100) { note.destroy(); self.notes.splice(i, 1); } } }; self.removeNote = function (note) { for (var i = 0; i < self.notes.length; i++) { if (self.notes[i] === note) { self.notes.splice(i, 1); break; } } }; self.getNotes = function () { return self.notes; }; self.getNextNoteIdx = function () { return self.nextNoteIdx; }; self.setNextNoteIdx = function (idx) { self.nextNoteIdx = idx; }; return self; }); var RestartButton = Container.expand(function () { var self = Container.call(this); var btn = self.attachAsset('restartButton', { anchorX: 0.5, anchorY: 0.5 }); self.down = function (x, y, obj) { tween(self, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, easing: tween.cubicOut }); }; self.up = function (x, y, obj) { tween(self, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.cubicIn, onFinish: function onFinish() { LK.stopMusic(); gameActive = false; if (noteManager) { noteManager.reset(); } startGame(); } }); }; return self; }); var ScoreText = Container.expand(function () { var self = Container.call(this); self.textObj = new Text2('', { size: 120, fill: 0xFFFFFF, dropShadow: true }); self.textObj.anchor.set(0.5, 0); self.addChild(self.textObj); self.setText = function (txt) { self.textObj.setText(txt); tween.stop(self.textObj, { scaleX: true, scaleY: true, alpha: true }); if (txt && txt.length > 0) { self.textObj.alpha = 1; self.textObj.scaleX = 1.0; self.textObj.scaleY = 1.0; tween(self.textObj, { scaleX: 1.25, scaleY: 1.25 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { tween(self.textObj, { scaleX: 1.0, scaleY: 1.0 }, { duration: 120, easing: tween.cubicIn }); } }); } else { tween(self.textObj, { alpha: 0 }, { duration: 180 }); } }; return self; }); var Sparkles = Container.expand(function () { var self = Container.call(this); var particleCount = 12; var minSpeed = 160; var maxSpeed = 360; var minScale = 0.5; var maxScale = 1.2; var minAlpha = 0.7; var maxAlpha = 1.0; var minDuration = 320; var maxDuration = 1520; var colors = [0xffffff, 0xe0f7fa, 0xb3e5fc, 0x81d4fa, 0x4fc3f7, 0x29b6f6, 0x039be5, 0x0288d1, 0x0277bd, 0x01579b, 0x3a8ee6]; for (var i = 0; i < particleCount; i++) { var angle = Math.PI * 2 * (i / particleCount); var speed = minSpeed + Math.random() * (maxSpeed - minSpeed); var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; var scale = minScale + Math.random() * (maxScale - minScale); var alpha = minAlpha + Math.random() * (maxAlpha - minAlpha); var color = colors[Math.floor(Math.random() * colors.length)]; var duration = minDuration + Math.random() * (maxDuration - minDuration); var targetAngle = Math.PI * 2 * Math.random(); var sparkle = self.attachAsset('sparkle', { anchorX: 0.5, anchorY: 0.5, scaleX: scale, scaleY: scale, alpha: alpha, tint: color }); (function (sparkle, vx, vy, duration) { var startX = 0, startY = 0; var seconds = duration / 1000; var finalX = startX + vx * seconds; var finalY = startY + vy * seconds; tween(sparkle, { x: finalX, y: finalY, alpha: 0, scaleX: 0.1, scaleY: 0.1, rotation: targetAngle }, { duration: duration, easing: tween.cubicOut, onFinish: function onFinish() { sparkle.destroy(); } }); })(sparkle, vx, vy, duration); } LK.setTimeout(function () { self.destroy(); }, maxDuration + 40); return self; }); var StartButton = Container.expand(function () { var self = Container.call(this); self.isTapped = false; var dot = self.attachAsset('noteDot', { anchorX: 0.5, anchorY: 0.5, scaleX: 5, scaleY: 5, alpha: 0.85 }); var btn = self.attachAsset('startText', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1, alpha: 1 }); self.animationComplete = false; var pulseTween; function startPulse() { function animateLeft() { pulseTween = tween(self, { rotation: -0.1 }, { duration: 1000, easing: tween.cubicInOut, onFinish: function onFinish() { animateRight(); } }); } function animateRight() { pulseTween = tween(self, { rotation: 0.1 }, { duration: 1000, easing: tween.cubicInOut, onFinish: function onFinish() { animateLeft(); } }); } self.rotation = 0; animateLeft(); } self.scaleX = 0.1; self.scaleY = 0.1; tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 600, easing: tween.cubicOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 240, easing: tween.cubicIn, onFinish: function onFinish() { self.animationComplete = true; startPulse(); } }); } }); self.onTap = null; self.down = function (x, y, obj) { if (!self.animationComplete) { return; } self.isTapped = true; tween.stop(self, { scaleX: true, scaleY: true }); self.scaleX = 1.0; self.scaleY = 1.0; LK.getSound('startSound').play(); tween(self, { scaleX: 10, scaleY: 10, alpha: 0 }, { duration: 1200, easing: tween.cubicIn, onFinish: function onFinish() { self.destroy(); self = null; startGame(); } }); }; var origDestroy = self.destroy; self.destroy = function () { if (pulseTween) { tween.stop(self, { scaleX: true, scaleY: true }); } origDestroy.call(self); }; return self; }); var Target = Container.expand(function () { var self = Container.call(this); var targetAsset = self.attachAsset('target', { anchorX: 0.5, anchorY: 0.5, tint: 0x3a8ee6, alpha: 0.8 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ var SONGS = [{ "name": "Ode to Joy\r\nBeethoven", "bpm": 220, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": false, "songNotes": [{ "time": 1432, "key": "Key6" }, { "time": 1855, "key": "Key6" }, { "time": 2305, "key": "Key7" }, { "time": 2788, "key": "Key8" }, { "time": 3216, "key": "Key8" }, { "time": 3666, "key": "Key7" }, { "time": 4122, "key": "Key6" }, { "time": 4567, "key": "Key5" }, { "time": 5027, "key": "Key4" }, { "time": 5479, "key": "Key4" }, { "time": 5937, "key": "Key5" }, { "time": 6397, "key": "Key6" }, { "time": 6864, "key": "Key6" }, { "time": 7583, "key": "Key5" }, { "time": 7820, "key": "Key5" }, { "time": 8816, "key": "Key6" }, { "time": 9289, "key": "Key6" }, { "time": 9778, "key": "Key7" }, { "time": 10205, "key": "Key8" }, { "time": 10672, "key": "Key8" }, { "time": 11108, "key": "Key7" }, { "time": 11564, "key": "Key6" }, { "time": 12000, "key": "Key5" }, { "time": 12455, "key": "Key4" }, { "time": 12911, "key": "Key4" }, { "time": 13339, "key": "Key5" }, { "time": 13785, "key": "Key6" }, { "time": 14370, "key": "Key5" }, { "time": 15131, "key": "Key4" }, { "time": 15341, "key": "Key4" }, { "time": 16318, "key": "Key5" }, { "time": 16760, "key": "Key5" }, { "time": 17243, "key": "Key6" }, { "time": 17711, "key": "Key4" }, { "time": 18164, "key": "Key5" }, { "time": 18607, "key": "Key6" }, { "time": 18840, "key": "Key7" }, { "time": 19107, "key": "Key6" }, { "time": 19556, "key": "Key4" }, { "time": 20007, "key": "Key5" }, { "time": 20428, "key": "Key6" }, { "time": 20634, "key": "Key7" }, { "time": 20915, "key": "Key6" }, { "time": 21375, "key": "Key5" }, { "time": 21859, "key": "Key4" }, { "time": 22325, "key": "Key5" }, { "time": 22818, "key": "Key1" }, { "time": 23809, "key": "Key6" }, { "time": 24259, "key": "Key6" }, { "time": 24725, "key": "Key7" }, { "time": 25156, "key": "Key8" }, { "time": 25597, "key": "Key8" }, { "time": 26039, "key": "Key7" }, { "time": 26496, "key": "Key6" }, { "time": 26950, "key": "Key5" }, { "time": 27413, "key": "Key4" }, { "time": 27882, "key": "Key4" }, { "time": 28309, "key": "Key5" }, { "time": 28830, "key": "Key6" }, { "time": 29319, "key": "Key5" }, { "time": 30092, "key": "Key4" }, { "time": 30343, "key": "Key4" }], "fromLibrary": true }, { "name": "Spring\r\nVivaldi", "bpm": 200, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": false, "songNotes": [{ "time": 696, "key": "Key7" }, { "time": 1001, "key": "Key9" }, { "time": 1314, "key": "Key9" }, { "time": 1661, "key": "Key9" }, { "time": 1998, "key": "Key8" }, { "time": 2170, "key": "Key7" }, { "time": 2313, "key": "Key11" }, { "time": 3064, "key": "Key11" }, { "time": 3212, "key": "Key10" }, { "time": 3379, "key": "Key9" }, { "time": 3736, "key": "Key9" }, { "time": 4097, "key": "Key9" }, { "time": 4430, "key": "Key8" }, { "time": 4630, "key": "Key7" }, { "time": 4785, "key": "Key11" }, { "time": 5585, "key": "Key11" }, { "time": 5740, "key": "Key10" }, { "time": 5949, "key": "Key9" }, { "time": 6348, "key": "Key10" }, { "time": 6488, "key": "Key11" }, { "time": 6693, "key": "Key10" }, { "time": 7154, "key": "Key9" }, { "time": 7555, "key": "Key8" }, { "time": 8743, "key": "Key7" }, { "time": 9102, "key": "Key11" }, { "time": 9440, "key": "Key10" }, { "time": 9598, "key": "Key9" }, { "time": 9768, "key": "Key10" }, { "time": 10160, "key": "Key11" }, { "time": 10516, "key": "Key12" }, { "time": 10900, "key": "Key11" }, { "time": 11764, "key": "Key7" }, { "time": 12109, "key": "Key11" }, { "time": 12415, "key": "Key10" }, { "time": 12590, "key": "Key9" }, { "time": 12771, "key": "Key10" }, { "time": 13206, "key": "Key11" }, { "time": 13567, "key": "Key12" }, { "time": 13952, "key": "Key11" }, { "time": 14782, "key": "Key7" }, { "time": 15151, "key": "Key12" }, { "time": 15522, "key": "Key11" }, { "time": 16353, "key": "Key10" }, { "time": 16689, "key": "Key9" }, { "time": 17020, "key": "Key8" }, { "time": 17247, "key": "Key7" }, { "time": 17365, "key": "Key8" }, { "time": 17906, "key": "Key7" }, { "time": 18079, "key": "Key7" }, { "time": 19261, "key": "Key9" }, { "time": 19621, "key": "Key9" }, { "time": 19967, "key": "Key9" }, { "time": 20309, "key": "Key8" }, { "time": 20483, "key": "Key9" }, { "time": 20708, "key": "Key10" }, { "time": 21486, "key": "Key10" }, { "time": 21630, "key": "Key9" }, { "time": 21845, "key": "Key8" }, { "time": 22216, "key": "Key8" }, { "time": 22583, "key": "Key8" }, { "time": 22938, "key": "Key7" }, { "time": 23125, "key": "Key8" }, { "time": 23316, "key": "Key9" }, { "time": 24195, "key": "Key9" }, { "time": 24431, "key": "Key10" }, { "time": 24592, "key": "Key11" }, { "time": 24964, "key": "Key11" }, { "time": 25332, "key": "Key11" }, { "time": 25685, "key": "Key11" }, { "time": 25863, "key": "Key10" }, { "time": 26056, "key": "Key9" }, { "time": 26456, "key": "Key9" }, { "time": 26832, "key": "Key9" }, { "time": 27188, "key": "Key9" }, { "time": 27392, "key": "Key10" }, { "time": 27572, "key": "Key11" }, { "time": 27936, "key": "Key11" }, { "time": 28318, "key": "Key11" }, { "time": 28689, "key": "Key11" }, { "time": 28887, "key": "Key10" }, { "time": 29068, "key": "Key9" }, { "time": 29451, "key": "Key9" }, { "time": 29839, "key": "Key9" }, { "time": 30226, "key": "Key9" }, { "time": 30420, "key": "Key10" }, { "time": 30586, "key": "Key11" }, { "time": 30994, "key": "Key11" }, { "time": 31369, "key": "Key11" }, { "time": 31742, "key": "Key10" }, { "time": 31949, "key": "Key9" }, { "time": 32115, "key": "Key8" }, { "time": 33283, "key": "Key7" }, { "time": 33628, "key": "Key11" }, { "time": 33991, "key": "Key10" }, { "time": 34165, "key": "Key9" }, { "time": 34357, "key": "Key10" }, { "time": 34778, "key": "Key11" }, { "time": 35152, "key": "Key12" }, { "time": 35574, "key": "Key11" }, { "time": 36394, "key": "Key7" }, { "time": 36768, "key": "Key11" }, { "time": 37125, "key": "Key10" }, { "time": 37292, "key": "Key9" }, { "time": 37452, "key": "Key10" }, { "time": 37855, "key": "Key11" }, { "time": 38194, "key": "Key12" }, { "time": 38651, "key": "Key11" }, { "time": 39420, "key": "Key7" }, { "time": 39781, "key": "Key12" }, { "time": 40199, "key": "Key11" }, { "time": 40964, "key": "Key10" }, { "time": 41328, "key": "Key9" }, { "time": 41660, "key": "Key8" }, { "time": 41890, "key": "Key7" }, { "time": 42048, "key": "Key8" }, { "time": 42718, "key": "Key7" }, { "time": 42899, "key": "Key2" }, { "time": 42905, "key": "Key7" }], "fromLibrary": true }, { "name": "San Francisco\r\nScott Mckenzie", "bpm": 240, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": false, "songNotes": [{ "time": 674, "key": "Key4" }, { "time": 1068, "key": "Key4" }, { "time": 1469, "key": "Key4" }, { "time": 1799, "key": "Key9" }, { "time": 2772, "key": "Key9" }, { "time": 3254, "key": "Key8" }, { "time": 4257, "key": "Key8" }, { "time": 5177, "key": "Key6" }, { "time": 5502, "key": "Key5" }, { "time": 7004, "key": "Key4" }, { "time": 7375, "key": "Key4" }, { "time": 7766, "key": "Key4" }, { "time": 8148, "key": "Key9" }, { "time": 9144, "key": "Key9" }, { "time": 9575, "key": "Key8" }, { "time": 9886, "key": "Key9" }, { "time": 10362, "key": "Key8" }, { "time": 10689, "key": "Key6" }, { "time": 11272, "key": "Key5" }, { "time": 13245, "key": "Key4" }, { "time": 13581, "key": "Key5" }, { "time": 14093, "key": "Key4" }, { "time": 14535, "key": "Key8" }, { "time": 14706, "key": "Key6" }, { "time": 15638, "key": "Key5" }, { "time": 16138, "key": "Key4" }, { "time": 16965, "key": "Key4" }, { "time": 17825, "key": "Key2" }, { "time": 18053, "key": "Key1" }, { "time": 19354, "key": "Key4" }, { "time": 19564, "key": "Key5" }, { "time": 19969, "key": "Key6" }, { "time": 21104, "key": "Key9" }, { "time": 21541, "key": "Key8" }, { "time": 21792, "key": "Key9" }, { "time": 22350, "key": "Key8" }, { "time": 22710, "key": "Key6" }, { "time": 22957, "key": "Key5" }], "fromLibrary": true }, { "name": "La Cucaracha", "bpm": 240, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": false, "songNotes": [{ "time": 1159, "key": "Key4" }, { "time": 1437, "key": "Key4" }, { "time": 1639, "key": "Key4" }, { "time": 1918, "key": "Key7" }, { "time": 2612, "key": "Key9" }, { "time": 3142, "key": "Key4" }, { "time": 3401, "key": "Key4" }, { "time": 3638, "key": "Key4" }, { "time": 3868, "key": "Key7" }, { "time": 4638, "key": "Key9" }, { "time": 5909, "key": "Key7" }, { "time": 6363, "key": "Key7" }, { "time": 6650, "key": "Key6" }, { "time": 6897, "key": "Key6" }, { "time": 7138, "key": "Key5" }, { "time": 7398, "key": "Key5" }, { "time": 7658, "key": "Key4" }, { "time": 9559, "key": "Key4" }, { "time": 9819, "key": "Key4" }, { "time": 10062, "key": "Key4" }, { "time": 10319, "key": "Key6" }, { "time": 11116, "key": "Key8" }, { "time": 11642, "key": "Key4" }, { "time": 11920, "key": "Key4" }, { "time": 12161, "key": "Key4" }, { "time": 12481, "key": "Key6" }, { "time": 13286, "key": "Key8" }, { "time": 14722, "key": "Key11" }, { "time": 15191, "key": "Key12" }, { "time": 15462, "key": "Key11" }, { "time": 15723, "key": "Key10" }, { "time": 15962, "key": "Key9" }, { "time": 16219, "key": "Key8" }, { "time": 16440, "key": "Key7" }, { "time": 17990, "key": "Key4" }, { "time": 18481, "key": "Key4" }, { "time": 18698, "key": "Key7" }, { "time": 18994, "key": "Key7" }, { "time": 19214, "key": "Key9" }, { "time": 19438, "key": "Key9" }, { "time": 19699, "key": "Key11" }, { "time": 20430, "key": "Key9" }, { "time": 21777, "key": "Key11" }, { "time": 22330, "key": "Key12" }, { "time": 22549, "key": "Key11" }, { "time": 22844, "key": "Key10" }, { "time": 23149, "key": "Key9" }, { "time": 23479, "key": "Key11" }, { "time": 23730, "key": "Key10" }, { "time": 24429, "key": "Key8" }, { "time": 25791, "key": "Key4" }, { "time": 26299, "key": "Key4" }, { "time": 26576, "key": "Key6" }, { "time": 26838, "key": "Key6" }, { "time": 27091, "key": "Key8" }, { "time": 27357, "key": "Key8" }, { "time": 28353, "key": "Key10" }, { "time": 29046, "key": "Key8" }, { "time": 30525, "key": "Key11" }, { "time": 31038, "key": "Key12" }, { "time": 31301, "key": "Key11" }, { "time": 31555, "key": "Key10" }, { "time": 31898, "key": "Key9" }, { "time": 32238, "key": "Key8" }, { "time": 32510, "key": "Key9" }, { "time": 33274, "key": "Key7" }, { "time": 34644, "key": "Key4" }, { "time": 34937, "key": "Key4" }, { "time": 35166, "key": "Key4" }, { "time": 35480, "key": "Key7" }, { "time": 36263, "key": "Key9" }, { "time": 36793, "key": "Key4" }, { "time": 37039, "key": "Key4" }, { "time": 37283, "key": "Key4" }, { "time": 37578, "key": "Key7" }, { "time": 38347, "key": "Key9" }, { "time": 39470, "key": "Key7" }, { "time": 39956, "key": "Key7" }, { "time": 40188, "key": "Key6" }, { "time": 40448, "key": "Key6" }, { "time": 40671, "key": "Key5" }, { "time": 40922, "key": "Key5" }, { "time": 41177, "key": "Key4" }, { "time": 42609, "key": "Key4" }, { "time": 42909, "key": "Key4" }, { "time": 43138, "key": "Key4" }, { "time": 43530, "key": "Key6" }, { "time": 44290, "key": "Key8" }, { "time": 44836, "key": "Key4" }, { "time": 45125, "key": "Key4" }, { "time": 45399, "key": "Key4" }, { "time": 45701, "key": "Key6" }, { "time": 46565, "key": "Key8" }, { "time": 48061, "key": "Key11" }, { "time": 48587, "key": "Key12" }, { "time": 48888, "key": "Key11" }, { "time": 49211, "key": "Key10" }, { "time": 49451, "key": "Key9" }, { "time": 49801, "key": "Key8" }, { "time": 50156, "key": "Key7" }], "fromLibrary": true }, { "name": "Tetris Theme", "bpm": 240, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": false, "songNotes": [{ "time": 909, "key": "Key9" }, { "time": 1403, "key": "Key6" }, { "time": 1660, "key": "Key7" }, { "time": 1902, "key": "Key8" }, { "time": 2432, "key": "Key7" }, { "time": 2669, "key": "Key6" }, { "time": 2938, "key": "Key5" }, { "time": 3441, "key": "Key5" }, { "time": 3674, "key": "Key7" }, { "time": 3976, "key": "Key9" }, { "time": 4552, "key": "Key8" }, { "time": 4753, "key": "Key7" }, { "time": 5051, "key": "Key6" }, { "time": 5857, "key": "Key7" }, { "time": 6114, "key": "Key8" }, { "time": 6620, "key": "Key9" }, { "time": 7094, "key": "Key7" }, { "time": 7548, "key": "Key5" }, { "time": 8054, "key": "Key5" }, { "time": 9415, "key": "Key8" }, { "time": 9921, "key": "Key10" }, { "time": 10204, "key": "Key12" }, { "time": 10707, "key": "Key11" }, { "time": 10972, "key": "Key10" }, { "time": 11261, "key": "Key9" }, { "time": 12098, "key": "Key7" }, { "time": 12387, "key": "Key9" }, { "time": 12890, "key": "Key8" }, { "time": 13094, "key": "Key7" }, { "time": 13387, "key": "Key6" }, { "time": 14284, "key": "Key7" }, { "time": 14585, "key": "Key8" }, { "time": 15119, "key": "Key9" }, { "time": 15688, "key": "Key7" }, { "time": 16160, "key": "Key5" }, { "time": 16662, "key": "Key5" }, { "time": 17737, "key": "Key7" }, { "time": 17766, "key": "Key9" }, { "time": 18826, "key": "Key5" }, { "time": 18858, "key": "Key7" }, { "time": 19848, "key": "Key8" }, { "time": 19878, "key": "Key6" }, { "time": 20900, "key": "Key6" }, { "time": 20907, "key": "Key4" }, { "time": 21933, "key": "Key5" }, { "time": 21941, "key": "Key7" }, { "time": 23005, "key": "Key2" }, { "time": 24027, "key": "Key2" }, { "time": 24034, "key": "Key4" }, { "time": 25100, "key": "Key6" }, { "time": 25137, "key": "Key4" }, { "time": 26128, "key": "Key7" }, { "time": 26158, "key": "Key9" }, { "time": 27219, "key": "Key5" }, { "time": 27235, "key": "Key7" }, { "time": 28252, "key": "Key6" }, { "time": 28269, "key": "Key8" }, { "time": 29309, "key": "Key6" }, { "time": 29314, "key": "Key4" }, { "time": 30313, "key": "Key5" }, { "time": 30369, "key": "Key7" }, { "time": 30841, "key": "Key7" }, { "time": 30894, "key": "Key9" }, { "time": 31418, "key": "Key9" }, { "time": 32371, "key": "Key11" }, { "time": 32402, "key": "Key9" }], "fromLibrary": true }, { "name": "Lost Woods\r\nLegend of Zelda", "bpm": 220, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": true, "songNotes": [{ "time": 400, "key": "Key3" }, { "time": 672, "key": "Key5" }, { "time": 944, "key": "Key6" }, { "time": 1488, "key": "Key3" }, { "time": 1760, "key": "Key5" }, { "time": 2032, "key": "Key6" }, { "time": 2576, "key": "Key3" }, { "time": 2848, "key": "Key5" }, { "time": 3120, "key": "Key6" }, { "time": 3392, "key": "Key9" }, { "time": 3664, "key": "Key8" }, { "time": 4208, "key": "Key6" }, { "time": 4480, "key": "Key7" }, { "time": 4752, "key": "Key6" }, { "time": 5024, "key": "Key4" }, { "time": 5296, "key": "Key2" }, { "time": 6656, "key": "Key1" }, { "time": 6928, "key": "Key2" }, { "time": 7200, "key": "Key4" }, { "time": 7472, "key": "Key2" }, { "time": 9104, "key": "Key3" }, { "time": 9376, "key": "Key5" }, { "time": 9648, "key": "Key6" }, { "time": 10192, "key": "Key3" }, { "time": 10464, "key": "Key5" }, { "time": 10736, "key": "Key6" }, { "time": 11280, "key": "Key3" }, { "time": 11552, "key": "Key5" }, { "time": 11824, "key": "Key6" }, { "time": 12096, "key": "Key9" }, { "time": 12368, "key": "Key8" }, { "time": 12912, "key": "Key6" }, { "time": 13184, "key": "Key7" }, { "time": 13456, "key": "Key9" }, { "time": 13728, "key": "Key7" }, { "time": 14000, "key": "Key4" }, { "time": 15360, "key": "Key1" }, { "time": 15632, "key": "Key2" }, { "time": 15904, "key": "Key4" }, { "time": 16176, "key": "Key2" }, { "time": 17808, "key": "Key1" }, { "time": 18080, "key": "Key2" }, { "time": 18352, "key": "Key3" }, { "time": 18896, "key": "Key4" }, { "time": 19168, "key": "Key5" }, { "time": 19440, "key": "Key6" }, { "time": 19984, "key": "Key7" }, { "time": 20256, "key": "Key6" }, { "time": 20528, "key": "Key2" }, { "time": 22160, "key": "Key1" }, { "time": 22432, "key": "Key2" }, { "time": 22704, "key": "Key3" }, { "time": 23248, "key": "Key4" }, { "time": 23520, "key": "Key5" }, { "time": 23792, "key": "Key6" }, { "time": 24336, "key": "Key7" }, { "time": 24608, "key": "Key8" }, { "time": 24880, "key": "Key9" }, { "time": 26512, "key": "Key1" }, { "time": 26784, "key": "Key2" }, { "time": 27056, "key": "Key3" }, { "time": 27600, "key": "Key4" }, { "time": 27872, "key": "Key5" }, { "time": 28144, "key": "Key6" }, { "time": 28688, "key": "Key7" }, { "time": 28960, "key": "Key6" }, { "time": 29232, "key": "Key2" }, { "time": 30864, "key": "Key1" }, { "time": 31136, "key": "Key2" }, { "time": 31408, "key": "Key4" }, { "time": 31680, "key": "Key3" }, { "time": 31952, "key": "Key6" }, { "time": 32224, "key": "Key5" }, { "time": 32496, "key": "Key8" }, { "time": 32768, "key": "Key7" }, { "time": 33040, "key": "Key5" }, { "time": 33312, "key": "Key6" }], "fromLibrary": true }, { "name": "Super Mario theme", "bpm": 200, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": false, "songNotes": [{ "time": 1194, "key": "Key9" }, { "time": 1333, "key": "Key9" }, { "time": 1622, "key": "Key9" }, { "time": 1896, "key": "Key7" }, { "time": 2076, "key": "Key9" }, { "time": 2423, "key": "Key11" }, { "time": 3066, "key": "Key4" }, { "time": 3718, "key": "Key7" }, { "time": 4235, "key": "Key4" }, { "time": 4719, "key": "Key2" }, { "time": 5254, "key": "Key5" }, { "time": 5547, "key": "Key6" }, { "time": 5857, "key": "Key5" }, { "time": 6017, "key": "Key5" }, { "time": 6340, "key": "Key4" }, { "time": 6543, "key": "Key9" }, { "time": 6834, "key": "Key11" }, { "time": 7025, "key": "Key12" }, { "time": 7311, "key": "Key10" }, { "time": 7502, "key": "Key11" }, { "time": 7777, "key": "Key9" }, { "time": 8087, "key": "Key7" }, { "time": 8379, "key": "Key8" }, { "time": 8515, "key": "Key6" }, { "time": 9492, "key": "Key7" }, { "time": 9992, "key": "Key4" }, { "time": 10477, "key": "Key2" }, { "time": 11034, "key": "Key5" }, { "time": 11355, "key": "Key6" }, { "time": 11663, "key": "Key5" }, { "time": 11850, "key": "Key5" }, { "time": 12173, "key": "Key4" }, { "time": 12385, "key": "Key9" }, { "time": 12640, "key": "Key11" }, { "time": 12859, "key": "Key12" }, { "time": 13157, "key": "Key10" }, { "time": 13350, "key": "Key11" }, { "time": 13601, "key": "Key9" }, { "time": 13928, "key": "Key7" }, { "time": 14227, "key": "Key8" }, { "time": 14362, "key": "Key6" }, { "time": 15781, "key": "Key11" }, { "time": 15993, "key": "Key10" }, { "time": 16116, "key": "Key10" }, { "time": 16398, "key": "Key8" }, { "time": 16758, "key": "Key9" }, { "time": 17133, "key": "Key2" }, { "time": 17369, "key": "Key5" }, { "time": 17520, "key": "Key7" }, { "time": 17884, "key": "Key5" }, { "time": 18051, "key": "Key7" }, { "time": 18234, "key": "Key8" }, { "time": 18865, "key": "Key11" }, { "time": 19065, "key": "Key10" }, { "time": 19225, "key": "Key10" }, { "time": 19448, "key": "Key8" }, { "time": 19757, "key": "Key9" }, { "time": 20117, "key": "Key14" }, { "time": 20409, "key": "Key14" }, { "time": 20578, "key": "Key14" }, { "time": 21671, "key": "Key11" }, { "time": 21872, "key": "Key10" }, { "time": 22013, "key": "Key10" }, { "time": 22230, "key": "Key8" }, { "time": 22523, "key": "Key9" }, { "time": 22848, "key": "Key2" }, { "time": 23067, "key": "Key5" }, { "time": 23192, "key": "Key7" }, { "time": 23559, "key": "Key5" }, { "time": 23699, "key": "Key7" }, { "time": 23879, "key": "Key8" }, { "time": 24572, "key": "Key8" }, { "time": 25062, "key": "Key7" }, { "time": 25537, "key": "Key7" }, { "time": 25947, "key": "Key3" }, { "time": 26239, "key": "Key3" }, { "time": 26391, "key": "Key3" }, { "time": 28555, "key": "Key11" }, { "time": 28758, "key": "Key10" }, { "time": 28907, "key": "Key10" }, { "time": 29105, "key": "Key8" }, { "time": 29421, "key": "Key9" }, { "time": 29749, "key": "Key2" }, { "time": 29942, "key": "Key5" }, { "time": 30064, "key": "Key7" }, { "time": 30817, "key": "Key5" }, { "time": 31011, "key": "Key7" }, { "time": 31171, "key": "Key8" }, { "time": 31828, "key": "Key11" }, { "time": 32039, "key": "Key10" }, { "time": 32188, "key": "Key10" }, { "time": 32480, "key": "Key8" }, { "time": 32813, "key": "Key9" }, { "time": 33147, "key": "Key14" }, { "time": 33425, "key": "Key14" }, { "time": 33592, "key": "Key14" }, { "time": 34794, "key": "Key11" }, { "time": 34993, "key": "Key10" }, { "time": 35144, "key": "Key10" }, { "time": 35404, "key": "Key8" }, { "time": 35746, "key": "Key9" }, { "time": 36155, "key": "Key2" }, { "time": 36314, "key": "Key5" }, { "time": 36499, "key": "Key7" }, { "time": 36974, "key": "Key5" }, { "time": 37132, "key": "Key7" }, { "time": 37316, "key": "Key8" }, { "time": 38229, "key": "Key8" }, { "time": 38728, "key": "Key7" }, { "time": 39213, "key": "Key7" }, { "time": 39697, "key": "Key14" }, { "time": 40031, "key": "Key14" }, { "time": 40183, "key": "Key14" }], "fromLibrary": true }, { "name": "Sonic - Marble Zone", "bpm": 200, "pitchLevel": 1, "bitsPerPage": 16, "isComposed": false, "songNotes": [{ "time": 809, "key": "Key6" }, { "time": 929, "key": "Key6" }, { "time": 1009, "key": "Key6" }, { "time": 1499, "key": "Key2" }, { "time": 1967, "key": "Key5" }, { "time": 2174, "key": "Key6" }, { "time": 2383, "key": "Key7" }, { "time": 2608, "key": "Key9" }, { "time": 2868, "key": "Key13" }, { "time": 3273, "key": "Key13" }, { "time": 3461, "key": "Key12" }, { "time": 3680, "key": "Key13" }, { "time": 4109, "key": "Key13" }, { "time": 4315, "key": "Key12" }, { "time": 4523, "key": "Key13" }, { "time": 4926, "key": "Key13" }, { "time": 5149, "key": "Key12" }, { "time": 5359, "key": "Key13" }, { "time": 5558, "key": "Key12" }, { "time": 5752, "key": "Key9" }, { "time": 5956, "key": "Key7" }, { "time": 6195, "key": "Key11" }, { "time": 6582, "key": "Key12" }, { "time": 6805, "key": "Key10" }, { "time": 9551, "key": "Key12" }, { "time": 9974, "key": "Key12" }, { "time": 10188, "key": "Key11" }, { "time": 10365, "key": "Key12" }, { "time": 10769, "key": "Key12" }, { "time": 10977, "key": "Key11" }, { "time": 11208, "key": "Key12" }, { "time": 11611, "key": "Key12" }, { "time": 11820, "key": "Key11" }, { "time": 12052, "key": "Key12" }, { "time": 12406, "key": "Key13" }, { "time": 12835, "key": "Key10" }, { "time": 13492, "key": "Key9" }, { "time": 15312, "key": "Key5" }, { "time": 15506, "key": "Key6" }, { "time": 15685, "key": "Key7" }, { "time": 15884, "key": "Key9" }, { "time": 16117, "key": "Key13" }, { "time": 16547, "key": "Key13" }, { "time": 16753, "key": "Key12" }, { "time": 16986, "key": "Key13" }, { "time": 17433, "key": "Key13" }, { "time": 17640, "key": "Key12" }, { "time": 17899, "key": "Key13" }, { "time": 18331, "key": "Key13" }, { "time": 18548, "key": "Key12" }, { "time": 18762, "key": "Key13" }, { "time": 18977, "key": "Key12" }, { "time": 19202, "key": "Key9" }, { "time": 19377, "key": "Key7" }, { "time": 19635, "key": "Key11" }, { "time": 20023, "key": "Key12" }, { "time": 20264, "key": "Key10" }, { "time": 22677, "key": "Key12" }, { "time": 23961, "key": "Key13" }, { "time": 24380, "key": "Key11" }, { "time": 25564, "key": "Key13" }, { "time": 26000, "key": "Key13" }, { "time": 26602, "key": "Key12" }, { "time": 27451, "key": "Key9" }, { "time": 27866, "key": "Key9" }, { "time": 28105, "key": "Key8" }, { "time": 28508, "key": "Key7" }, { "time": 28730, "key": "Key6" }, { "time": 29377, "key": "Key5" }, { "time": 29602, "key": "Key7" }, { "time": 29736, "key": "Key5" }, { "time": 29833, "key": "Key7" }, { "time": 30020, "key": "Key5" }, { "time": 30220, "key": "Key6" }, { "time": 30412, "key": "Key4" }, { "time": 30621, "key": "Key1" }, { "time": 30870, "key": "Key6" }, { "time": 31097, "key": "Key3" }, { "time": 31267, "key": "Key5" }, { "time": 31416, "key": "Key3" }, { "time": 31517, "key": "Key5" }, { "time": 31773, "key": "Key3" }, { "time": 32000, "key": "Key4" }, { "time": 32177, "key": "Key5" }, { "time": 32412, "key": "Key6" }, { "time": 32621, "key": "Key4" }, { "time": 32838, "key": "Key5" }, { "time": 33037, "key": "Key7" }, { "time": 33162, "key": "Key5" }, { "time": 33289, "key": "Key7" }, { "time": 33475, "key": "Key5" }, { "time": 33695, "key": "Key6" }, { "time": 33899, "key": "Key4" }, { "time": 34117, "key": "Key1" }, { "time": 34343, "key": "Key6" }, { "time": 34553, "key": "Key3" }, { "time": 34735, "key": "Key5" }, { "time": 34879, "key": "Key3" }, { "time": 34984, "key": "Key5" }, { "time": 35260, "key": "Key3" }, { "time": 35518, "key": "Key4" }, { "time": 35762, "key": "Key5" }, { "time": 36039, "key": "Key6" }, { "time": 36271, "key": "Key7" }, { "time": 37484, "key": "Key13" }], "fromLibrary": true }, { "name": "Crazy Frog", "bpm": 220, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": "true", "songNotes": [{ "time": 400, "key": "Key5" }, { "time": 944, "key": "Key7" }, { "time": 1352, "key": "Key5" }, { "time": 1624, "key": "Key5" }, { "time": 1760, "key": "Key8" }, { "time": 2032, "key": "Key5" }, { "time": 2304, "key": "Key4" }, { "time": 2576, "key": "Key5" }, { "time": 3120, "key": "Key9" }, { "time": 3528, "key": "Key5" }, { "time": 3800, "key": "Key5" }, { "time": 3936, "key": "Key10" }, { "time": 4208, "key": "Key9" }, { "time": 4480, "key": "Key7" }, { "time": 4752, "key": "Key5" }, { "time": 5024, "key": "Key9" }, { "time": 5296, "key": "Key12" }, { "time": 5568, "key": "Key5" }, { "time": 5704, "key": "Key4" }, { "time": 5976, "key": "Key4" }, { "time": 6112, "key": "Key2" }, { "time": 6384, "key": "Key6" }, { "time": 6656, "key": "Key5" }, { "time": 8560, "key": "Key5" }, { "time": 9104, "key": "Key7" }, { "time": 9512, "key": "Key5" }, { "time": 9784, "key": "Key5" }, { "time": 9920, "key": "Key8" }, { "time": 10192, "key": "Key5" }, { "time": 10464, "key": "Key4" }, { "time": 10736, "key": "Key5" }, { "time": 11280, "key": "Key9" }, { "time": 11688, "key": "Key5" }, { "time": 11960, "key": "Key5" }, { "time": 12096, "key": "Key10" }, { "time": 12368, "key": "Key9" }, { "time": 12640, "key": "Key7" }, { "time": 12912, "key": "Key5" }, { "time": 13184, "key": "Key9" }, { "time": 13456, "key": "Key12" }, { "time": 13728, "key": "Key5" }, { "time": 13864, "key": "Key4" }, { "time": 14136, "key": "Key4" }, { "time": 14272, "key": "Key2" }, { "time": 14544, "key": "Key6" }, { "time": 14816, "key": "Key5" }, { "time": 16448, "key": "Key5" }, { "time": 16992, "key": "Key7" }, { "time": 17400, "key": "Key5" }, { "time": 17672, "key": "Key5" }, { "time": 17808, "key": "Key8" }, { "time": 18080, "key": "Key5" }, { "time": 18352, "key": "Key4" }, { "time": 18624, "key": "Key5" }, { "time": 19168, "key": "Key9" }, { "time": 19576, "key": "Key5" }, { "time": 19848, "key": "Key5" }, { "time": 19984, "key": "Key10" }, { "time": 20256, "key": "Key9" }, { "time": 20528, "key": "Key7" }, { "time": 20800, "key": "Key5" }, { "time": 21072, "key": "Key9" }, { "time": 21344, "key": "Key12" }, { "time": 21616, "key": "Key5" }, { "time": 21752, "key": "Key4" }, { "time": 22024, "key": "Key4" }, { "time": 22160, "key": "Key2" }, { "time": 22432, "key": "Key6" }, { "time": 22704, "key": "Key5" }], "fromLibrary": true }, { "name": "Believer\r\nImagine Dragons", "bpm": 200, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": "false", "songNotes": [{ "time": 1266, "key": "Key1" }, { "time": 1773, "key": "Key5" }, { "time": 2237, "key": "Key4" }, { "time": 2745, "key": "Key4" }, { "time": 3091, "key": "Key3" }, { "time": 3275, "key": "Key4" }, { "time": 3707, "key": "Key4" }, { "time": 4037, "key": "Key5" }, { "time": 4212, "key": "Key4" }, { "time": 4545, "key": "Key3" }, { "time": 4787, "key": "Key1" }, { "time": 5162, "key": "Key0" }, { "time": 5399, "key": "Key1" }, { "time": 6060, "key": "Key5" }, { "time": 6529, "key": "Key4" }, { "time": 6993, "key": "Key4" }, { "time": 7338, "key": "Key3" }, { "time": 7521, "key": "Key4" }, { "time": 7971, "key": "Key4" }, { "time": 8264, "key": "Key5" }, { "time": 8432, "key": "Key4" }, { "time": 8760, "key": "Key3" }, { "time": 8940, "key": "Key1" }, { "time": 9281, "key": "Key0" }, { "time": 9458, "key": "Key1" }, { "time": 9961, "key": "Key3" }, { "time": 10433, "key": "Key8" }, { "time": 11387, "key": "Key5" }, { "time": 12115, "key": "Key5" }, { "time": 12314, "key": "Key4" }, { "time": 12650, "key": "Key3" }, { "time": 12818, "key": "Key1" }, { "time": 13129, "key": "Key0" }, { "time": 13336, "key": "Key1" }, { "time": 13833, "key": "Key3" }, { "time": 14329, "key": "Key8" }, { "time": 15243, "key": "Key7" }, { "time": 17091, "key": "Key1" }, { "time": 17394, "key": "Key1" }, { "time": 17587, "key": "Key5" }, { "time": 18033, "key": "Key4" }, { "time": 18329, "key": "Key4" }, { "time": 18521, "key": "Key4" }, { "time": 18844, "key": "Key3" }, { "time": 19026, "key": "Key4" }, { "time": 19484, "key": "Key4" }, { "time": 19745, "key": "Key5" }, { "time": 19940, "key": "Key4" }, { "time": 20249, "key": "Key3" }, { "time": 20402, "key": "Key1" }, { "time": 20714, "key": "Key0" }, { "time": 20890, "key": "Key1" }, { "time": 21338, "key": "Key4" }, { "time": 21642, "key": "Key5" }, { "time": 21813, "key": "Key4" }, { "time": 22289, "key": "Key4" }, { "time": 22586, "key": "Key3" }, { "time": 22786, "key": "Key4" }, { "time": 23225, "key": "Key4" }, { "time": 23554, "key": "Key5" }, { "time": 23722, "key": "Key4" }, { "time": 24021, "key": "Key3" }, { "time": 24153, "key": "Key1" }, { "time": 24427, "key": "Key0" }, { "time": 24642, "key": "Key1" }, { "time": 25073, "key": "Key3" }, { "time": 25541, "key": "Key8" }, { "time": 26547, "key": "Key5" }, { "time": 27282, "key": "Key5" }, { "time": 27474, "key": "Key4" }, { "time": 27787, "key": "Key3" }, { "time": 27923, "key": "Key1" }, { "time": 28221, "key": "Key0" }, { "time": 28422, "key": "Key1" }, { "time": 28906, "key": "Key3" }, { "time": 29379, "key": "Key8" }, { "time": 30386, "key": "Key7" }, { "time": 31794, "key": "Key1" }, { "time": 31930, "key": "Key0" }, { "time": 32126, "key": "Key1" }, { "time": 32419, "key": "Key1" }, { "time": 32739, "key": "Key1" }, { "time": 32907, "key": "Key1" }, { "time": 33055, "key": "Key1" }, { "time": 33490, "key": "Key1" }, { "time": 33778, "key": "Key1" }, { "time": 33897, "key": "Key0" }, { "time": 34047, "key": "Key1" }, { "time": 34396, "key": "Key1" }, { "time": 34681, "key": "Key1" }, { "time": 34836, "key": "Key1" }, { "time": 34996, "key": "Key1" }, { "time": 35396, "key": "Key1" }, { "time": 35852, "key": "Key3" }, { "time": 36187, "key": "Key3" }, { "time": 36507, "key": "Key3" }, { "time": 36658, "key": "Key2" }, { "time": 36796, "key": "Key3" }, { "time": 37212, "key": "Key3" }, { "time": 37667, "key": "Key2" }, { "time": 37988, "key": "Key2" }, { "time": 38306, "key": "Key2" }, { "time": 38437, "key": "Key1" }, { "time": 38596, "key": "Key2" }, { "time": 39020, "key": "Key2" }, { "time": 39443, "key": "Key1" }, { "time": 39794, "key": "Key1" }, { "time": 40098, "key": "Key1" }, { "time": 40234, "key": "Key0" }, { "time": 40394, "key": "Key1" }, { "time": 40860, "key": "Key1" }, { "time": 41282, "key": "Key1" }, { "time": 41626, "key": "Key1" }, { "time": 41955, "key": "Key1" }, { "time": 42114, "key": "Key0" }, { "time": 42274, "key": "Key1" }, { "time": 42674, "key": "Key1" }, { "time": 43108, "key": "Key3" }, { "time": 43436, "key": "Key3" }, { "time": 43762, "key": "Key3" }, { "time": 43925, "key": "Key2" }, { "time": 44075, "key": "Key3" }, { "time": 44539, "key": "Key3" }, { "time": 44988, "key": "Key2" }, { "time": 45325, "key": "Key2" }, { "time": 45676, "key": "Key2" }, { "time": 45821, "key": "Key1" }, { "time": 46037, "key": "Key2" }, { "time": 46523, "key": "Key2" }, { "time": 47924, "key": "Key8" }, { "time": 48636, "key": "Key7" }, { "time": 48845, "key": "Key10" }, { "time": 49155, "key": "Key9" }, { "time": 49347, "key": "Key8" }, { "time": 49669, "key": "Key7" }, { "time": 49914, "key": "Key10" }, { "time": 50239, "key": "Key9" }, { "time": 50414, "key": "Key8" }, { "time": 50741, "key": "Key7" }, { "time": 50900, "key": "Key8" }, { "time": 51411, "key": "Key10" }, { "time": 52468, "key": "Key10" }, { "time": 52659, "key": "Key9" }, { "time": 53156, "key": "Key7" }, { "time": 55582, "key": "Key8" }, { "time": 56259, "key": "Key7" }, { "time": 56459, "key": "Key10" }, { "time": 56747, "key": "Key9" }, { "time": 56923, "key": "Key8" }, { "time": 57238, "key": "Key7" }, { "time": 57423, "key": "Key10" }, { "time": 57715, "key": "Key9" }, { "time": 57898, "key": "Key8" }, { "time": 58211, "key": "Key7" }, { "time": 58411, "key": "Key8" }, { "time": 58915, "key": "Key10" }, { "time": 59989, "key": "Key10" }, { "time": 60161, "key": "Key9" }, { "time": 60659, "key": "Key7" }], "fromLibrary": true }, { "name": "Canon in C\r\nJohann Pachelbel", "bpm": 200, "pitchLevel": 1, "bitsPerPage": 16, "isComposed": false, "songNotes": [{ "time": 2046, "key": "Key11" }, { "time": 2055, "key": "Key7" }, { "time": 2062, "key": "Key9" }, { "time": 2527, "key": "Key9" }, { "time": 2702, "key": "Key10" }, { "time": 2949, "key": "Key11" }, { "time": 3410, "key": "Key9" }, { "time": 3568, "key": "Key10" }, { "time": 3827, "key": "Key11" }, { "time": 3834, "key": "Key6" }, { "time": 3851, "key": "Key4" }, { "time": 4038, "key": "Key6" }, { "time": 4263, "key": "Key5" }, { "time": 4477, "key": "Key6" }, { "time": 4699, "key": "Key7" }, { "time": 4917, "key": "Key8" }, { "time": 5149, "key": "Key9" }, { "time": 5360, "key": "Key10" }, { "time": 5601, "key": "Key5" }, { "time": 5609, "key": "Key7" }, { "time": 5618, "key": "Key9" }, { "time": 6027, "key": "Key7" }, { "time": 6262, "key": "Key8" }, { "time": 6503, "key": "Key9" }, { "time": 6930, "key": "Key2" }, { "time": 7139, "key": "Key3" }, { "time": 7363, "key": "Key2" }, { "time": 7377, "key": "Key0" }, { "time": 7385, "key": "Key4" }, { "time": 7611, "key": "Key5" }, { "time": 7819, "key": "Key4" }, { "time": 8029, "key": "Key3" }, { "time": 8270, "key": "Key4" }, { "time": 8470, "key": "Key7" }, { "time": 8680, "key": "Key6" }, { "time": 8872, "key": "Key7" }, { "time": 9113, "key": "Key5" }, { "time": 9116, "key": "Key0" }, { "time": 9126, "key": "Key3" }, { "time": 9539, "key": "Key7" }, { "time": 9750, "key": "Key6" }, { "time": 9999, "key": "Key5" }, { "time": 10424, "key": "Key4" }, { "time": 10616, "key": "Key3" }, { "time": 10839, "key": "Key0" }, { "time": 10845, "key": "Key2" }, { "time": 10849, "key": "Key4" }, { "time": 11060, "key": "Key3" }, { "time": 11274, "key": "Key2" }, { "time": 11484, "key": "Key3" }, { "time": 11727, "key": "Key4" }, { "time": 11933, "key": "Key5" }, { "time": 12140, "key": "Key6" }, { "time": 12345, "key": "Key7" }, { "time": 12575, "key": "Key0" }, { "time": 12583, "key": "Key3" }, { "time": 12588, "key": "Key5" }, { "time": 12994, "key": "Key7" }, { "time": 13193, "key": "Key6" }, { "time": 13437, "key": "Key7" }, { "time": 13864, "key": "Key6" }, { "time": 14060, "key": "Key7" }, { "time": 14269, "key": "Key6" }, { "time": 14282, "key": "Key1" }, { "time": 14299, "key": "Key4" }, { "time": 14497, "key": "Key5" }, { "time": 14728, "key": "Key6" }, { "time": 14938, "key": "Key7" }, { "time": 15132, "key": "Key8" }, { "time": 15322, "key": "Key9" }, { "time": 15536, "key": "Key10" }, { "time": 15722, "key": "Key11" }, { "time": 15965, "key": "Key2" }, { "time": 15969, "key": "Key9" }, { "time": 15979, "key": "Key0" }, { "time": 16390, "key": "Key7" }, { "time": 16607, "key": "Key8" }, { "time": 16863, "key": "Key9" }, { "time": 17276, "key": "Key8" }, { "time": 17415, "key": "Key7" }, { "time": 17649, "key": "Key6" }, { "time": 17667, "key": "Key8" }, { "time": 17675, "key": "Key4" }, { "time": 17853, "key": "Key6" }, { "time": 18077, "key": "Key7" }, { "time": 18286, "key": "Key8" }, { "time": 18516, "key": "Key9" }, { "time": 18715, "key": "Key8" }, { "time": 18942, "key": "Key7" }, { "time": 19140, "key": "Key6" }, { "time": 19366, "key": "Key5" }, { "time": 19384, "key": "Key7" }, { "time": 19397, "key": "Key2" }, { "time": 19834, "key": "Key5" }, { "time": 20024, "key": "Key6" }, { "time": 20257, "key": "Key7" }, { "time": 20670, "key": "Key0" }, { "time": 20864, "key": "Key1" }, { "time": 21087, "key": "Key0" }, { "time": 21094, "key": "Key2" }, { "time": 21285, "key": "Key3" }, { "time": 21494, "key": "Key2" }, { "time": 21712, "key": "Key1" }, { "time": 21922, "key": "Key2" }, { "time": 22131, "key": "Key7" }, { "time": 22354, "key": "Key6" }, { "time": 22553, "key": "Key7" }, { "time": 22770, "key": "Key3" }, { "time": 22778, "key": "Key5" }, { "time": 22791, "key": "Key0" }, { "time": 23214, "key": "Key7" }, { "time": 23424, "key": "Key6" }, { "time": 23662, "key": "Key5" }, { "time": 24091, "key": "Key4" }, { "time": 24275, "key": "Key3" }, { "time": 24471, "key": "Key0" }, { "time": 24475, "key": "Key4" }, { "time": 24483, "key": "Key2" }, { "time": 24705, "key": "Key3" }, { "time": 24921, "key": "Key2" }, { "time": 25139, "key": "Key3" }, { "time": 25372, "key": "Key4" }, { "time": 25601, "key": "Key5" }, { "time": 25809, "key": "Key6" }, { "time": 26006, "key": "Key7" }, { "time": 26240, "key": "Key5" }, { "time": 26243, "key": "Key0" }, { "time": 26252, "key": "Key3" }, { "time": 26676, "key": "Key7" }, { "time": 26891, "key": "Key6" }, { "time": 27134, "key": "Key7" }, { "time": 27543, "key": "Key6" }, { "time": 27763, "key": "Key7" }, { "time": 27976, "key": "Key1" }, { "time": 27982, "key": "Key6" }, { "time": 27986, "key": "Key4" }, { "time": 28196, "key": "Key7" }, { "time": 28434, "key": "Key8" }, { "time": 28653, "key": "Key7" }, { "time": 28904, "key": "Key6" }, { "time": 29158, "key": "Key7" }, { "time": 29412, "key": "Key5" }, { "time": 29669, "key": "Key6" }, { "time": 29937, "key": "Key7" }, { "time": 29942, "key": "Key2" }, { "time": 29950, "key": "Key0" }, { "time": 31841, "key": "Key7" }, { "time": 31852, "key": "Key9" }, { "time": 31858, "key": "Key14" }], "fromLibrary": true }, { "name": "Moonlight Sonata\r\nBeethoven", "bpm": 130, "pitchLevel": 0, "bitsPerPage": 16, "isComposed": "true", "songNotes": [{ "time": 400, "key": "Key0" }, { "time": 400, "key": "Key2" }, { "time": 861, "key": "Key5" }, { "time": 1322, "key": "Key7" }, { "time": 1783, "key": "Key2" }, { "time": 2244, "key": "Key5" }, { "time": 2705, "key": "Key7" }, { "time": 3166, "key": "Key2" }, { "time": 3627, "key": "Key5" }, { "time": 4088, "key": "Key7" }, { "time": 4549, "key": "Key2" }, { "time": 5010, "key": "Key5" }, { "time": 5471, "key": "Key7" }, { "time": 5932, "key": "Key1" }, { "time": 5932, "key": "Key2" }, { "time": 6393, "key": "Key5" }, { "time": 6854, "key": "Key7" }, { "time": 7315, "key": "Key2" }, { "time": 7776, "key": "Key5" }, { "time": 8237, "key": "Key7" }, { "time": 8698, "key": "Key2" }, { "time": 9159, "key": "Key5" }, { "time": 9620, "key": "Key7" }, { "time": 10081, "key": "Key2" }, { "time": 10542, "key": "Key5" }, { "time": 11003, "key": "Key7" }, { "time": 11464, "key": "Key0" }, { "time": 11464, "key": "Key3" }, { "time": 11925, "key": "Key5" }, { "time": 12386, "key": "Key7" }, { "time": 12847, "key": "Key3" }, { "time": 13308, "key": "Key5" }, { "time": 13769, "key": "Key7" }, { "time": 14230, "key": "Key1" }, { "time": 14230, "key": "Key3" }, { "time": 14691, "key": "Key6" }, { "time": 15152, "key": "Key8" }, { "time": 15613, "key": "Key3" }, { "time": 16074, "key": "Key6" }, { "time": 16535, "key": "Key8" }, { "time": 16996, "key": "Key0" }, { "time": 16996, "key": "Key2" }, { "time": 17457, "key": "Key5" }, { "time": 17918, "key": "Key7" }, { "time": 18379, "key": "Key2" }, { "time": 18840, "key": "Key5" }, { "time": 19301, "key": "Key7" }, { "time": 19762, "key": "Key1" }, { "time": 19762, "key": "Key2" }, { "time": 20223, "key": "Key5" }, { "time": 20684, "key": "Key6" }, { "time": 21145, "key": "Key2" }, { "time": 21606, "key": "Key5" }, { "time": 22067, "key": "Key6" }, { "time": 22528, "key": "Key0" }, { "time": 22528, "key": "Key2" }, { "time": 22528, "key": "Key5" }, { "time": 22989, "key": "Key2" }, { "time": 23450, "key": "Key5" }, { "time": 23911, "key": "Key7" }, { "time": 24372, "key": "Key5" }, { "time": 24833, "key": "Key7" }, { "time": 25294, "key": "Key9" }, { "time": 26216, "key": "Key7" }, { "time": 26446, "key": "Key9" }, { "time": 26676, "key": "Key4" }, { "time": 26676, "key": "Key6" }, { "time": 26676, "key": "Key9" }, { "time": 27136, "key": "Key8" }, { "time": 27597, "key": "Key3" }, { "time": 28058, "key": "Key6" }, { "time": 28519, "key": "Key8" }, { "time": 28980, "key": "Key3" }, { "time": 29441, "key": "Key6" }, { "time": 29902, "key": "Key8" }, { "time": 30363, "key": "Key9" }, { "time": 31285, "key": "Key8" }, { "time": 31515, "key": "Key9" }, { "time": 31745, "key": "Key5" }, { "time": 31745, "key": "Key9" }, { "time": 32205, "key": "Key7" }, { "time": 32666, "key": "Key9" }, { "time": 33127, "key": "Key5" }, { "time": 33588, "key": "Key7" }, { "time": 34049, "key": "Key9" }, { "time": 34510, "key": "Key5" }, { "time": 34510, "key": "Key10" }, { "time": 34971, "key": "Key7" }, { "time": 35432, "key": "Key10" }, { "time": 35893, "key": "Key5" }, { "time": 36354, "key": "Key7" }, { "time": 36815, "key": "Key10" }, { "time": 37276, "key": "Key0" }, { "time": 37276, "key": "Key4" }, { "time": 37276, "key": "Key9" }, { "time": 37737, "key": "Key7" }, { "time": 38198, "key": "Key9" }, { "time": 38659, "key": "Key4" }, { "time": 39120, "key": "Key7" }, { "time": 39581, "key": "Key9" }, { "time": 40042, "key": "Key1" }, { "time": 40042, "key": "Key4" }, { "time": 40042, "key": "Key8" }, { "time": 40964, "key": "Key9" }, { "time": 41425, "key": "Key11" }, { "time": 42347, "key": "Key6" }, { "time": 42808, "key": "Key0" }, { "time": 42808, "key": "Key2" }, { "time": 42808, "key": "Key7" }, { "time": 43269, "key": "Key2" }, { "time": 43730, "key": "Key5" }, { "time": 44191, "key": "Key7" }, { "time": 44652, "key": "Key5" }, { "time": 45113, "key": "Key7" }, { "time": 45574, "key": "Key9" }, { "time": 46496, "key": "Key7" }, { "time": 46726, "key": "Key9" }, { "time": 46956, "key": "Key4" }, { "time": 46956, "key": "Key6" }, { "time": 46956, "key": "Key9" }, { "time": 47416, "key": "Key8" }, { "time": 47877, "key": "Key3" }, { "time": 48338, "key": "Key6" }, { "time": 48799, "key": "Key8" }, { "time": 49260, "key": "Key3" }, { "time": 49721, "key": "Key6" }, { "time": 50182, "key": "Key8" }, { "time": 50643, "key": "Key9" }, { "time": 51565, "key": "Key8" }, { "time": 51795, "key": "Key9" }, { "time": 52025, "key": "Key5" }, { "time": 52025, "key": "Key9" }, { "time": 52485, "key": "Key7" }, { "time": 52946, "key": "Key9" }, { "time": 53407, "key": "Key5" }, { "time": 53868, "key": "Key7" }, { "time": 54329, "key": "Key9" }, { "time": 54790, "key": "Key5" }, { "time": 54790, "key": "Key10" }, { "time": 55251, "key": "Key7" }, { "time": 55712, "key": "Key10" }, { "time": 56173, "key": "Key5" }, { "time": 56634, "key": "Key7" }, { "time": 57095, "key": "Key10" }, { "time": 57556, "key": "Key0" }, { "time": 57556, "key": "Key4" }, { "time": 57556, "key": "Key9" }, { "time": 58017, "key": "Key7" }, { "time": 58478, "key": "Key9" }, { "time": 58939, "key": "Key4" }, { "time": 59400, "key": "Key7" }, { "time": 59861, "key": "Key9" }, { "time": 60322, "key": "Key1" }, { "time": 60322, "key": "Key4" }, { "time": 60322, "key": "Key8" }, { "time": 61244, "key": "Key9" }, { "time": 61705, "key": "Key11" }, { "time": 62627, "key": "Key6" }, { "time": 63088, "key": "Key0" }, { "time": 63088, "key": "Key2" }, { "time": 63088, "key": "Key5" }], "fromLibrary": true }, { "name": "Bella ciao", "bpm": 650, "pitchLevel": 4, "bitsPerPage": 16, "isComposed": true, "songNotes": [{ "time": 368, "key": "Key2" }, { "time": 552, "key": "Key5" }, { "time": 736, "key": "Key6" }, { "time": 1012, "key": "Key7" }, { "time": 1196, "key": "Key5" }, { "time": 1932, "key": "Key2" }, { "time": 2208, "key": "Key5" }, { "time": 2392, "key": "Key6" }, { "time": 2576, "key": "Key7" }, { "time": 2852, "key": "Key5" }, { "time": 3588, "key": "Key2" }, { "time": 3772, "key": "Key5" }, { "time": 3956, "key": "Key6" }, { "time": 4232, "key": "Key7" }, { "time": 4508, "key": "Key6" }, { "time": 4692, "key": "Key5" }, { "time": 4968, "key": "Key7" }, { "time": 5244, "key": "Key6" }, { "time": 5428, "key": "Key5" }, { "time": 5704, "key": "Key9" }, { "time": 5980, "key": "Key9" }, { "time": 6348, "key": "Key9" }, { "time": 6532, "key": "Key9" }, { "time": 6808, "key": "Key8" }, { "time": 6992, "key": "Key9" }, { "time": 7176, "key": "Key10" }, { "time": 7452, "key": "Key10" }, { "time": 7636, "key": "Key1" }, { "time": 7912, "key": "Key3" }, { "time": 8188, "key": "Key10" }, { "time": 8372, "key": "Key9" }, { "time": 8556, "key": "Key8" }, { "time": 8832, "key": "Key10" }, { "time": 9016, "key": "Key9" }, { "time": 9752, "key": "Key9" }, { "time": 9936, "key": "Key8" }, { "time": 10120, "key": "Key7" }, { "time": 10396, "key": "Key6" }, { "time": 10672, "key": "Key9" }, { "time": 11040, "key": "Key6" }, { "time": 11316, "key": "Key7" }, { "time": 11684, "key": "Key5" }, { "time": 11960, "key": "Key2" }, { "time": 12328, "key": "Key2" }, { "time": 12512, "key": "Key2" }, { "time": 12696, "key": "Key5" }, { "time": 12972, "key": "Key6" }, { "time": 13156, "key": "Key7" }, { "time": 13340, "key": "Key5" }, { "time": 14168, "key": "Key2" }, { "time": 14352, "key": "Key5" }, { "time": 14536, "key": "Key6" }, { "time": 14720, "key": "Key7" }, { "time": 14904, "key": "Key5" }, { "time": 15640, "key": "Key2" }, { "time": 15916, "key": "Key5" }, { "time": 16100, "key": "Key6" }, { "time": 16284, "key": "Key7" }, { "time": 16652, "key": "Key6" }, { "time": 16836, "key": "Key5" }, { "time": 17112, "key": "Key7" }, { "time": 17388, "key": "Key6" }, { "time": 17664, "key": "Key5" }, { "time": 17848, "key": "Key9" }, { "time": 18124, "key": "Key9" }, { "time": 18492, "key": "Key9" }, { "time": 18676, "key": "Key9" }, { "time": 18952, "key": "Key8" }, { "time": 19136, "key": "Key9" }, { "time": 19320, "key": "Key10" }, { "time": 19596, "key": "Key10" }, { "time": 19780, "key": "Key1" }, { "time": 20056, "key": "Key3" }, { "time": 20332, "key": "Key10" }, { "time": 20516, "key": "Key1" }, { "time": 20516, "key": "Key9" }, { "time": 20700, "key": "Key8" }, { "time": 20976, "key": "Key10" }, { "time": 21160, "key": "Key9" }, { "time": 21896, "key": "Key9" }, { "time": 22080, "key": "Key8" }, { "time": 22264, "key": "Key7" }, { "time": 22540, "key": "Key6" }, { "time": 22816, "key": "Key9" }, { "time": 23184, "key": "Key6" }, { "time": 23460, "key": "Key7" }, { "time": 23828, "key": "Key5" }, { "time": 24104, "key": "Key2" }, { "time": 24472, "key": "Key2" }, { "time": 24656, "key": "Key2" }, { "time": 24840, "key": "Key5" }, { "time": 25116, "key": "Key6" }, { "time": 25300, "key": "Key7" }, { "time": 25484, "key": "Key5" }, { "time": 26220, "key": "Key2" }, { "time": 26496, "key": "Key5" }, { "time": 26680, "key": "Key6" }, { "time": 26864, "key": "Key7" }, { "time": 27048, "key": "Key5" }, { "time": 27784, "key": "Key2" }, { "time": 27968, "key": "Key5" }, { "time": 28152, "key": "Key6" }, { "time": 28428, "key": "Key7" }, { "time": 28704, "key": "Key6" }, { "time": 28980, "key": "Key5" }, { "time": 29164, "key": "Key7" }, { "time": 29532, "key": "Key6" }, { "time": 29716, "key": "Key5" }, { "time": 29900, "key": "Key9" }, { "time": 30268, "key": "Key9" }, { "time": 30544, "key": "Key9" }, { "time": 30728, "key": "Key9" }, { "time": 31004, "key": "Key8" }, { "time": 31188, "key": "Key9" }, { "time": 31372, "key": "Key10" }, { "time": 31648, "key": "Key10" }, { "time": 31832, "key": "Key1" }, { "time": 32200, "key": "Key3" }, { "time": 32384, "key": "Key10" }, { "time": 32568, "key": "Key1" }, { "time": 32568, "key": "Key9" }, { "time": 32844, "key": "Key8" }, { "time": 33028, "key": "Key10" }, { "time": 33212, "key": "Key9" }, { "time": 33948, "key": "Key9" }, { "time": 34132, "key": "Key8" }, { "time": 34408, "key": "Key7" }, { "time": 34592, "key": "Key6" }, { "time": 34868, "key": "Key9" }, { "time": 35236, "key": "Key6" }, { "time": 35512, "key": "Key7" }, { "time": 35880, "key": "Key5" }, { "time": 36156, "key": "Key2" }, { "time": 36524, "key": "Key2" }, { "time": 36708, "key": "Key2" }, { "time": 36984, "key": "Key5" }, { "time": 37168, "key": "Key6" }, { "time": 37352, "key": "Key7" }, { "time": 37628, "key": "Key5" }, { "time": 38364, "key": "Key2" }, { "time": 38548, "key": "Key5" }, { "time": 38732, "key": "Key6" }, { "time": 39008, "key": "Key7" }, { "time": 39192, "key": "Key5" }, { "time": 39928, "key": "Key2" }, { "time": 40112, "key": "Key5" }, { "time": 40388, "key": "Key6" }, { "time": 40572, "key": "Key7" }, { "time": 40940, "key": "Key6" }, { "time": 41124, "key": "Key5" }, { "time": 41308, "key": "Key7" }, { "time": 41676, "key": "Key6" }, { "time": 41860, "key": "Key5" }, { "time": 42044, "key": "Key9" }, { "time": 42412, "key": "Key9" }, { "time": 42688, "key": "Key9" }, { "time": 42964, "key": "Key9" }, { "time": 43148, "key": "Key8" }, { "time": 43332, "key": "Key9" }, { "time": 43608, "key": "Key10" }, { "time": 43792, "key": "Key10" }, { "time": 43976, "key": "Key1" }, { "time": 44344, "key": "Key3" }, { "time": 44528, "key": "Key10" }, { "time": 44712, "key": "Key1" }, { "time": 44712, "key": "Key9" }, { "time": 44988, "key": "Key8" }, { "time": 45172, "key": "Key10" }, { "time": 45356, "key": "Key9" }, { "time": 46092, "key": "Key9" }, { "time": 46276, "key": "Key8" }, { "time": 46552, "key": "Key7" }, { "time": 46736, "key": "Key6" }, { "time": 47104, "key": "Key9" }, { "time": 47380, "key": "Key6" }, { "time": 47748, "key": "Key7" }, { "time": 48024, "key": "Key5" }, { "time": 48392, "key": "Key0" }, { "time": 48392, "key": "Key2" }, { "time": 48668, "key": "Key0" }, { "time": 48668, "key": "Key2" }], "fromLibrary": true }]; var songsRating = []; var songNotesRaw = SONGS[0].songNotes; var keyToLane = { "Key0": 0, "Key1": 1, "Key2": 2, "Key3": 0, "Key4": 1, "Key5": 2, "Key6": 0, "Key7": 1, "Key8": 2, "Key9": 0, "Key10": 1, "Key11": 2, "Key12": 0, "Key13": 1, "Key14": 2 }; var songNotes = []; var songDuration; var laneCount = 3; var laneWidth = 600; var laneOffset = 150; var laneSpacing = 2048 / laneCount; var laneX = [laneSpacing * 0.5 + laneOffset, laneSpacing * 1.5, laneSpacing * 2.5 - laneOffset]; var hitLine; var hitLineYDisplay; var targets = []; var speedMultiplier = 1.0; var baseNoteTravelTime = 4000; var noteTravelTime = baseNoteTravelTime / speedMultiplier; var hitLineY = 2000; var baseNoteStartY = -4000; var noteStartY = baseNoteStartY; var noteManager; var menuManager; var restartBtn; var songStartTime; var gameActive; var score; var combo; var maxCombo; var lastTapTime; var totalNotes; var failedNotes; var scoreTxt; var comboTxt; var menuButton; var bgManager; var laneHighlights; function startGame() { if (!noteManager) { noteManager = new NoteManager(); } noteManager.reset(); score = LK.getScore(); combo = 0; maxCombo = 0; totalNotes = songNotes.length; failedNotes = 0; if (!scoreTxt) { scoreTxt = new ScoreText(); scoreTxt.y = 0; LK.gui.top.addChild(scoreTxt); } scoreTxt.visible = true; scoreTxt.setText(LK.getScore() + ''); if (!comboTxt) { comboTxt = new ComboText(); comboTxt.y = 130; comboTxt.tint = 0x3A8EE6; LK.gui.top.addChild(comboTxt); } comboTxt.setText(''); lastTapTime = 0; if (laneHighlights) { for (var i = 0; i < laneHighlights.length; i++) { laneHighlights[i].visible = true; } } if (targets) { for (var i = 0; i < targets.length; i++) { targets[i].visible = true; } } if (restartBtn) { restartBtn.visible = true; } if (menuButton) { menuButton.visible = true; } LK.setTimeout(function () { gameActive = true; songStartTime = Date.now(); }, 1000); } game.update = function () { if (menuManager && menuManager.visible) { menuManager.update(); } noteTravelTime = baseNoteTravelTime / speedMultiplier; noteStartY = baseNoteStartY / speedMultiplier; if (!gameActive) { return; } var now = Date.now(); var songElapsed = now - songStartTime; noteManager.spawnNotes(songNotes, songElapsed, noteTravelTime, laneX, noteStartY); noteManager.cleanupNotes(songElapsed); if (songElapsed > songDuration + 600 && noteManager.getNotes().length === 0 && gameActive) { gameActive = false; var failureRate = totalNotes > 0 ? failedNotes / totalNotes : 0; var stars = 0; if (failedNotes === 0 || failedNotes === 1) { stars = 3; } else if (failureRate <= 0.5) { stars = 2; } else if (failureRate < 1.0) { stars = 1; } else { stars = 0; } var starContainer = new Container(); starContainer.x = 2048 / 2; starContainer.y = 800; game.addChild(starContainer); var starSpacing = 150; var starStartX = -(stars - 1) * starSpacing / 2; for (var i = 0; i < stars; i++) { (function (index) { var star = starContainer.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, x: starStartX + index * starSpacing, y: 0, scaleX: 0, scaleY: 0, tint: 0xFFD700 }); LK.setTimeout(function () { tween(star, { scaleX: 2, scaleY: 2 }, { duration: 400, easing: tween.elasticOut }); }, index * 200); })(i); } LK.getSound('cheers').play(); LK.setTimeout(function () { restartBtn.visible = false; menuButton.visible = false; LK.showYouWin(); }, 4400); } }; function getLaneFromX(x) { for (var i = 0; i < laneCount; i++) { var left = laneX[i] - laneWidth / 2; var right = laneX[i] + laneWidth / 2; if (x >= left && x <= right) { return i; } } return -1; } game.down = function (x, y, obj) { if (!gameActive) { return; } if (y < hitLineY - 220 || y > hitLineY + 220) { return; } var lane = getLaneFromX(x); if (lane < 0 || lane >= laneCount) { return; } var now = Date.now(); var songElapsed = now - songStartTime; var bestNote = null; var bestDelta = 9999; var notesInPlay = noteManager.getNotes(); for (var i = 0; i < notesInPlay.length; i++) { var note = notesInPlay[i]; if (note.lane !== lane) { continue; } if (note.tapped || note.missed) { continue; } var delta = Math.abs(songElapsed - note.hitTime); if (delta < 320 && delta < bestDelta) { bestNote = note; bestDelta = delta; } } if (bestNote) { bestNote.tapped = true; bestNote.showTapFeedback(); LK.getSound('tapGood').play(); if (typeof bestNote.down === "function") { bestNote.down(); } var distance = Math.abs(bestNote.y - hitLineY); var norm = distance / (bestNote.height / 2); var points = 1; if (norm <= 0.1) { points = 10; } else if (norm <= 0.2) { points = 9; } else if (norm <= 0.3) { points = 8; } else if (norm <= 0.4) { points = 7; } else if (norm <= 0.5) { points = 6; } else if (norm <= 0.6) { points = 5; } else if (norm <= 0.7) { points = 4; } else if (norm <= 0.8) { points = 3; } else if (norm <= 0.9) { points = 2; } else { points = 1; } combo += 1; score += combo * points; if (combo > maxCombo) { maxCombo = combo; } LK.setScore(score); scoreTxt.setText(score + ''); tween.stop(scoreTxt, { scaleX: true, scaleY: true }); scoreTxt.scaleX = 1.0; scoreTxt.scaleY = 1.0; tween(scoreTxt, { scaleX: 1.2, scaleY: 1.2 }, { duration: 160, easing: tween.cubicOut, onFinish: function onFinish() { tween(scoreTxt, { scaleX: 1.0, scaleY: 1.0 }, { duration: 120, easing: tween.cubicIn }); } }); if (combo > 1) { comboTxt.setText('Combo x' + combo + '!'); tween.stop(comboTxt, { scaleX: true, scaleY: true }); comboTxt.scaleX = 1.0; comboTxt.scaleY = 1.0; tween(comboTxt, { scaleX: 1.6, scaleY: 1.6 }, { duration: 160, easing: tween.cubicOut, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1.0, scaleY: 1.0 }, { duration: 120, easing: tween.cubicIn }); } }); } else { comboTxt.setText(''); } LK.effects.flashObject(laneHighlights[lane], 0x3a8ee6, 180); var tappedTarget = targets[lane]; if (tappedTarget) { tappedTarget.scaleX = 1; tappedTarget.scaleY = 1; tween(tappedTarget, { scaleX: 1.4, scaleY: 1.4 }, { duration: 90, easing: tween.cubicOut, onFinish: function onFinish() { tween(tappedTarget, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.cubicIn }); } }); } tween(bestNote, { alpha: 0 }, { duration: 180, onFinish: function onFinish() { bestNote.destroy(); } }); noteManager.removeNote(bestNote); } else { combo = 0; comboTxt.setText(''); LK.getSound('tapMiss').play(); LK.effects.flashObject(laneHighlights[lane], 0xff0000, 300); } }; LK.on('gameover', function () { LK.stopMusic(); startGame(); }); LK.on('youwin', function () { LK.stopMusic(); startGame(); }); function initializeGame() { for (var i = 0; i < SONGS.length; i++) { songsRating[i] = 0; } bgManager = new BackgroundManager(); game.addChild(bgManager); menuManager = new MenuManager(); menuManager.createMenuTiles(SONGS); menuManager.onSongSelected = function (songIndex) { menuManager.hide(); songNotesRaw = SONGS[songIndex].songNotes; songNotes = []; for (var i = 0; i < songNotesRaw.length; i++) { var note = songNotesRaw[i]; var lane = 0; if (keyToLane.hasOwnProperty(note.key)) { lane = keyToLane[note.key]; } else { lane = i % 3; } songNotes.push({ lane: lane, time: note.time }); } songDuration = songNotes.length > 0 ? songNotes[songNotes.length - 1].time / speedMultiplier + 1000 : 9000; startGame(); }; game.addChild(menuManager); menuManager.visible = false; for (var i = 0; i < songNotesRaw.length; i++) { var note = songNotesRaw[i]; var lane = 0; if (keyToLane.hasOwnProperty(note.key)) { lane = keyToLane[note.key]; } else { lane = i % 3; } songNotes.push({ lane: lane, time: note.time }); } songDuration = songNotes.length > 0 ? songNotes[songNotes.length - 1].time / speedMultiplier + 1000 : 9000; hitLine = LK.getAsset('laneHighlight', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 8, color: 0x3a8ee6, alpha: 0.18, x: 2048 / 2, y: hitLineY }); game.addChild(hitLine); for (var i = 0; i < laneCount; i++) { var target = new Target(); target.x = laneX[i]; target.y = hitLineY; target.visible = false; game.addChild(target); targets.push(target); } noteManager = new NoteManager(); songStartTime = 0; gameActive = false; score = 0; combo = 0; maxCombo = 0; lastTapTime = 0; totalNotes = 0; failedNotes = 0; scoreTxt = new ScoreText(); scoreTxt.setText(LK.getScore() + ''); scoreTxt.y = 0; scoreTxt.visible = false; LK.gui.top.addChild(scoreTxt); comboTxt = new ComboText(); comboTxt.y = 130; comboTxt.tint = 0x3A8EE6; LK.gui.top.addChild(comboTxt); if (!restartBtn) { restartBtn = new RestartButton(); restartBtn.visible = false; restartBtn.x = 1900; restartBtn.y = 150; game.addChild(restartBtn); } if (!menuButton) { menuButton = new MenuButton(); menuButton.visible = false; menuButton.x = 200; menuButton.y = 500; game.addChild(menuButton); } laneHighlights = []; for (var i = 0; i < laneCount; i++) { var laneHL = LK.getAsset('laneHighlight', { anchorX: 0.5, anchorY: 0, alpha: 0.07, x: laneX[i], y: 0, height: 2732, visible: false }); game.addChild(laneHL); laneHighlights.push(laneHL); } hitLineYDisplay = hitLineY; if (typeof startBtn !== "undefined" && startBtn) { startBtn.destroy(); startBtn = null; } startBtn = new StartButton(); startBtn.x = 2048 / 2; startBtn.y = 1200; startBtn.down = function (x, y, obj) { if (!startBtn.animationComplete) { return; } tween.stop(startBtn, { scaleX: true, scaleY: true }); startBtn.scaleX = 1.0; startBtn.scaleY = 1.0; LK.getSound('startSound').play(); tween(startBtn, { scaleX: 100, scaleY: 100, alpha: 0 }, { duration: 1200, easing: tween.cubicIn, onFinish: function onFinish() { startBtn.destroy(); startBtn = null; if (restartBtn) { restartBtn.visible = false; } if (menuButton) { menuButton.visible = false; } menuManager.show(); } }); }; game.addChild(startBtn); } initializeGame();
===================================================================
--- original.js
+++ change.js
@@ -5,35 +5,29 @@
/****
* Classes
****/
-// BackgroundManager class: manages the game background
var BackgroundManager = Container.expand(function () {
var self = Container.call(this);
- // Attach the background00 asset, anchored at top-left
var bg = self.attachAsset('background00', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
return self;
});
-// ComboText class: animated combo display
var ComboText = Container.expand(function () {
var self = Container.call(this);
- // Internal Text2 for display
self.textObj = new Text2('', {
size: 80,
fill: 0xFFFFFF,
dropShadow: true
});
self.textObj.anchor.set(0.5, 0);
self.addChild(self.textObj);
- // Set text and animate
self.setText = function (txt) {
self.textObj.setText(txt);
- // Animate: pop if not empty, fade out if empty
tween.stop(self.textObj, {
scaleX: true,
scaleY: true,
alpha: true
@@ -58,9 +52,8 @@
});
}
});
} else {
- // Fade out if empty
tween(self.textObj, {
alpha: 0
}, {
duration: 180
@@ -68,19 +61,15 @@
}
};
return self;
});
-// MenuButton class: a button to return to the menu during gameplay
var MenuButton = Container.expand(function () {
var self = Container.call(this);
- // Attach the menuIcon asset, centered
var icon = self.attachAsset('menuIcon', {
anchorX: 0.5,
anchorY: 0.5
});
- // Handle tap
self.down = function (x, y, obj) {
- // Animate press feedback
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
@@ -88,25 +77,20 @@
easing: tween.cubicOut
});
};
self.up = function (x, y, obj) {
- // Animate release
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.cubicIn,
onFinish: function onFinish() {
- // Stop music
LK.stopMusic();
- // Reset game state
gameActive = false;
- // Reset note manager
if (noteManager) {
noteManager.reset();
}
- // Hide game UI elements
if (scoreTxt) {
scoreTxt.visible = false;
}
if (comboTxt) {
@@ -124,68 +108,51 @@
}
if (restartBtn) {
restartBtn.visible = false;
}
- // Hide the menu button itself
self.visible = false;
- // Show the menu
if (menuManager) {
menuManager.show();
}
}
});
};
return self;
});
-// MenuManager class: manages the song selection menu
var MenuManager = Container.expand(function () {
var self = Container.call(this);
- // Array to hold menu tiles
self.menuTiles = [];
- // Scroll container for tiles
self.scrollContainer = new Container();
self.addChild(self.scrollContainer);
- // Scroll state
self.scrollY = 0;
self.targetScrollY = 0;
self.lastTouchY = 0;
self.isDragging = false;
self.dragVelocity = 0;
self.lastDragTime = 0;
- // Scroll bounds
self.minScrollY = 0;
self.maxScrollY = 0;
- // Drag detection
self.dragStartY = 0;
self.dragDistance = 0;
- self.dragThreshold = 10; // Minimum pixels to consider it a drag
- // Create menu tiles for each song
+ self.dragThreshold = 10;
self.createMenuTiles = function (songs) {
- // Clear existing tiles
for (var i = 0; i < self.menuTiles.length; i++) {
self.menuTiles[i].destroy();
}
self.menuTiles = [];
- // Create new tiles
var tileHeight = 300;
- var tileSpacing = 260; // Increased spacing for more vertical space
+ var tileSpacing = 260;
var startY = 500;
for (var i = 0; i < songs.length; i++) {
var tile = new MenuTile();
tile.x = 2048 / 2;
tile.y = startY + i * (tileHeight + tileSpacing);
tile.setText(songs[i].name);
- // Store song index for later use
tile.songIndex = i;
- // Make tile interactive
tile.down = function () {
var index = this.songIndex;
- // Reset drag distance when tile is pressed
self.dragDistance = 0;
- // Don't play sound or animate if we're already scrolling
if (Math.abs(self.dragVelocity) < 5) {
- // Don't play click sound here - wait for up handler to confirm it's not a drag
- // Animate press feedback
tween(this, {
scaleX: 0.95,
scaleY: 0.95
}, {
@@ -195,13 +162,10 @@
}
};
tile.up = function () {
var index = this.songIndex;
- // Only trigger selection if not dragging (check drag distance and velocity)
if (self.dragDistance < self.dragThreshold && Math.abs(self.dragVelocity) < 5) {
- // Play click sound only when actually selecting (not dragging)
LK.getSound('click').play();
- // Animate release and trigger song selection
tween(this, {
scaleX: 1.0,
scaleY: 1.0
}, {
@@ -213,9 +177,8 @@
}
}
});
} else {
- // Reset scale if scrolling
tween(this, {
scaleX: 1.0,
scaleY: 1.0
}, {
@@ -226,22 +189,19 @@
};
self.scrollContainer.addChild(tile);
self.menuTiles.push(tile);
}
- // Calculate scroll bounds
var lastTileY = startY + (songs.length - 1) * (tileHeight + tileSpacing);
self.maxScrollY = 0;
- self.minScrollY = Math.min(0, 2732 - lastTileY - 400); // Keep some padding at bottom
+ self.minScrollY = Math.min(0, 2732 - lastTileY - 400);
};
- // Handle touch/drag for scrolling
self.down = function (x, y, obj) {
self.isDragging = true;
self.lastTouchY = y;
- self.dragStartY = y; // Store initial position
- self.dragDistance = 0; // Reset drag distance
+ self.dragStartY = y;
+ self.dragDistance = 0;
self.dragVelocity = 0;
self.lastDragTime = Date.now();
- // Stop any ongoing scroll animation
tween.stop(self, {
targetScrollY: true
});
};
@@ -250,41 +210,35 @@
return;
}
var deltaY = y - self.lastTouchY;
self.targetScrollY += deltaY;
- // Track total drag distance
self.dragDistance = Math.abs(y - self.dragStartY);
- // Clamp to bounds with rubber band effect
if (self.targetScrollY > self.maxScrollY) {
self.targetScrollY = self.maxScrollY + (self.targetScrollY - self.maxScrollY) * 0.3;
} else if (self.targetScrollY < self.minScrollY) {
self.targetScrollY = self.minScrollY + (self.targetScrollY - self.minScrollY) * 0.3;
}
- // Calculate velocity
var now = Date.now();
var deltaTime = now - self.lastDragTime;
if (deltaTime > 0) {
- self.dragVelocity = deltaY / deltaTime * 16; // Convert to pixels per frame
+ self.dragVelocity = deltaY / deltaTime * 16;
}
self.lastTouchY = y;
self.lastDragTime = now;
};
self.up = function (x, y, obj) {
self.isDragging = false;
- // Apply momentum
if (Math.abs(self.dragVelocity) > 2) {
var momentum = self.dragVelocity * 20;
var newTarget = self.targetScrollY + momentum;
- // Clamp to bounds
newTarget = Math.max(self.minScrollY, Math.min(self.maxScrollY, newTarget));
tween(self, {
targetScrollY: newTarget
}, {
duration: 800,
easing: tween.cubicOut
});
} else {
- // Snap back to bounds if overscrolled
if (self.targetScrollY > self.maxScrollY) {
tween(self, {
targetScrollY: self.maxScrollY
}, {
@@ -301,25 +255,19 @@
}
}
self.dragVelocity = 0;
};
- // Update scroll position smoothly
self.update = function () {
- // Smooth scrolling
self.scrollY += (self.targetScrollY - self.scrollY) * 0.2;
self.scrollContainer.y = self.scrollY;
- // Decay velocity when not dragging
if (!self.isDragging) {
self.dragVelocity *= 0.95;
}
};
- // Callback for when a song is selected
self.onSongSelected = null;
- // Show menu with animation
self.show = function () {
self.visible = true;
self.alpha = 0;
- // Reset scroll position
self.scrollY = 0;
self.targetScrollY = 0;
self.scrollContainer.y = 0;
tween(self, {
@@ -327,16 +275,14 @@
}, {
duration: 300,
easing: tween.cubicOut
});
- // Animate tiles in sequence
for (var i = 0; i < self.menuTiles.length; i++) {
(function (tile, delay) {
tile.scaleX = 0.8;
tile.scaleY = 0.8;
tile.alpha = 0;
LK.setTimeout(function () {
- // Play menuSpawn sound when creating each tile
LK.getSound('menuSpawn').play();
}, delay);
tween(tile, {
scaleX: 1,
@@ -350,9 +296,8 @@
});
})(self.menuTiles[i], i * 100);
}
};
- // Hide menu with animation
self.hide = function () {
tween(self, {
alpha: 0
}, {
@@ -364,17 +309,14 @@
});
};
return self;
});
-// MenuTile class: a menu tile with an image and a text label
var MenuTile = Container.expand(function () {
var self = Container.call(this);
- // Attach the menuTile asset, centered
self.tileImg = self.attachAsset('menuTile', {
anchorX: 0.5,
anchorY: 0.5
});
- // Add a text label aligned to the left
self.textObj = new Text2('', {
size: 100,
fill: 0x222222,
dropShadow: true
@@ -382,25 +324,21 @@
self.textObj.anchor.set(0, 0.5);
self.textObj.x = -self.tileImg.width / 2 + 100;
self.textObj.y = 0;
self.addChild(self.textObj);
- // Add play button on the right
self.playBtn = self.attachAsset('playButton', {
anchorX: 0.5,
anchorY: 0.5,
x: self.tileImg.width / 2 - 150,
y: 0
});
- // Public method to set the text
self.setText = function (txt) {
self.textObj.setText(txt);
};
return self;
});
-// Note class: a falling dot in a lane, with timing and tap state
var Note = Container.expand(function () {
var self = Container.call(this);
- // Attach the note dot asset, centered
self.noteBall = self.attachAsset('noteDot', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.6
@@ -408,48 +346,33 @@
self.noteSign = self.attachAsset('noteSign', {
anchorX: 0.5,
anchorY: 0.5
});
- // Lane index (0,1,2)
self.lane = 0;
- // Time (in ms) when this note should be hit
self.hitTime = 0;
- // Whether this note has been tapped
self.tapped = false;
- // Whether this note has been missed
self.missed = false;
- // For tap feedback
self.showTapFeedback = function () {
var feedback = self.attachAsset('tapFeedback', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
- // Spawn sparkles at note position
var sparkles = new Sparkles();
sparkles.x = self.x;
sparkles.y = self.y;
if (self.parent) {
self.parent.addChild(sparkles);
}
- // Animate noteSign scale up to 4 and back to 1
self.noteSign.scaleX = 1;
self.noteSign.scaleY = 1;
tween(self.noteSign, {
scaleX: 3,
scaleY: 3
}, {
duration: 120,
easing: tween.cubicOut,
- onFinish: function onFinish() {
- // tween(self.noteSign, {
- // scaleX: 1,
- // scaleY: 1
- // }, {
- // duration: 180,
- // easing: tween.cubicIn
- // });
- }
+ onFinish: function onFinish() {}
});
tween(feedback, {
alpha: 0
}, {
@@ -458,31 +381,23 @@
feedback.destroy();
}
});
};
- // Called every tick
self.update = function () {
- // Calculate songElapsed and t for this note
if (!gameActive) {
return;
}
var now = Date.now();
var songElapsed = now - songStartTime;
- // Calculate progress: 0 (spawn) to 1 (at hit line), allow t > 1 for movement past hit line
- // Apply speedMultiplier to make notes move at the correct visual speed
var adjustedTravelTime = noteTravelTime * speedMultiplier;
var t = (songElapsed - (self.hitTime - adjustedTravelTime)) / adjustedTravelTime;
- // Don't clamp t to 0, allow negative values for proper positioning before note starts moving
- // Remove the clamp for t > 1, so notes keep moving past hit line
self.y = noteStartY + (hitLineY - noteStartY) * t + (t > 1 ? (t - 1) * (2732 - hitLineY) : 0);
- // Miss detection: if note passes hit line and not tapped
if (!self.tapped && !self.missed && songElapsed > self.hitTime + 220) {
self.missed = true;
self.alpha = 0.3;
combo = 0;
- failedNotes++; // Track missed note for rating
- // Show and animate 'Missed!' on comboTxt in red
- comboTxt.tint = 0xff2222; // set to red
+ failedNotes++;
+ comboTxt.tint = 0xff2222;
comboTxt.setText('Missed!');
tween.stop(comboTxt, {
scaleX: true,
scaleY: true,
@@ -499,15 +414,14 @@
duration: 600,
easing: tween.cubicOut,
onFinish: function onFinish() {
comboTxt.setText('');
- comboTxt.tint = 0x3A8EE6; // restore to blue after
+ comboTxt.tint = 0x3A8EE6;
comboTxt.scaleX = 1.0;
comboTxt.scaleY = 1.0;
comboTxt.alpha = 1.0;
}
});
- // Animate noteSign to flash red
tween(self.noteSign, {
tint: 0xff0000
}, {
duration: 60,
@@ -518,25 +432,18 @@
duration: 180
});
}
});
- // Play tapMiss sound when missed
LK.getSound('tapMiss').play();
}
};
- // Play the corresponding key sound for this note
self.down = function () {
- // Check if note is tapped too early (before hitLineY - 320)
if (self.y < hitLineY - 320) {
- // Mark as tapped so it can't be tapped again
self.tapped = true;
- // Play tapMiss sound for early tap
LK.getSound('tapMiss').play();
- // Reset combo
combo = 0;
- failedNotes++; // Track too early tap for rating
- // Show and animate 'Too early!' on comboTxt in red
- comboTxt.tint = 0xff2222; // set to red
+ failedNotes++;
+ comboTxt.tint = 0xff2222;
comboTxt.setText('Too early!');
tween.stop(comboTxt, {
scaleX: true,
scaleY: true,
@@ -553,15 +460,14 @@
duration: 600,
easing: tween.cubicOut,
onFinish: function onFinish() {
comboTxt.setText('');
- comboTxt.tint = 0x3A8EE6; // restore to blue after
+ comboTxt.tint = 0x3A8EE6;
comboTxt.scaleX = 1.0;
comboTxt.scaleY = 1.0;
comboTxt.alpha = 1.0;
}
});
- // Animate note destruction
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
@@ -569,27 +475,23 @@
duration: 300,
easing: tween.cubicOut,
onFinish: function onFinish() {
self.destroy();
- // Remove from note manager
if (noteManager) {
noteManager.removeNote(self);
}
}
});
return;
}
- // Find the original song note for this Note instance
- // We'll use the lane and hitTime to match to songNotesRaw
for (var i = 0; i < songNotesRaw.length; i++) {
var sn = songNotesRaw[i];
var lane = 0;
if (keyToLane.hasOwnProperty(sn.key)) {
lane = keyToLane[sn.key];
} else {
lane = i % 3;
}
- // Compare adjusted time (sn.time / speedMultiplier) with note's hitTime
if (lane === self.lane && sn.time / speedMultiplier === self.hitTime) {
if (typeof sn.key === "string") {
var keySoundName = sn.key.toLowerCase();
var keySound = LK.getSound(keySoundName);
@@ -602,106 +504,67 @@
}
};
return self;
});
-// NoteManager class: handles spawning and management of notes
var NoteManager = Container.expand(function () {
var self = Container.call(this);
- // Notes in play
self.notes = [];
- // Index of next note to spawn
self.nextNoteIdx = 0;
- // Reset all state
self.reset = function () {
for (var i = 0; i < self.notes.length; i++) {
self.notes[i].destroy();
}
self.notes = [];
self.nextNoteIdx = 0;
};
- // Spawn notes as their time approaches
self.spawnNotes = function (songNotes, songElapsed, noteTravelTime, laneX, noteStartY) {
- // This function spawns notes at the right time so they reach the hit line exactly when they should be tapped
- //
- // Parameters:
- // - songNotes: Array of all notes in the song, each with {lane: 0|1|2, time: ms}
- // - songElapsed: Current time elapsed since song started (in milliseconds)
- // - noteTravelTime: Time it takes for a note to travel from spawn point to hit line (in milliseconds)
- // - laneX: Array of x-coordinates for each lane [left, center, right]
- // - noteStartY: Y-coordinate where notes spawn (above the screen)
- // The key timing logic:
- // A note should spawn when: songElapsed >= (note.hitTime - noteTravelTime)
- // This ensures the note has exactly noteTravelTime milliseconds to travel to the hit line
- // Example: If a note should be hit at 5000ms and travel time is 4000ms, it spawns at 1000ms
- // Keep spawning notes while there are unspawned notes whose spawn time has arrived
- // Apply speedMultiplier to the note time to control music playback speed
while (self.nextNoteIdx < songNotes.length && songNotes[self.nextNoteIdx].time / speedMultiplier - noteTravelTime <= songElapsed) {
- // Get the data for the next note to spawn
var noteData = songNotes[self.nextNoteIdx];
- // Create a new Note instance
var note = new Note();
- // Set which lane (0=left, 1=center, 2=right)
note.lane = noteData.lane;
- // Set when this note should be hit (in ms from song start)
- // Apply speedMultiplier to sync with music speed
note.hitTime = noteData.time / speedMultiplier;
- // Position the note horizontally in its lane
note.x = laneX[note.lane];
- // Position the note vertically at the spawn point (above screen)
note.y = noteStartY;
- // Add note to our tracking array
self.notes.push(note);
- // Add note to the game display
game.addChild(note);
- // Move to the next note in the song
self.nextNoteIdx++;
}
};
- // Remove notes that are far past the hit line
self.cleanupNotes = function (songElapsed) {
for (var i = self.notes.length - 1; i >= 0; i--) {
var note = self.notes[i];
- // Remove note if it has moved past the bottom of the screen
if (note.y > 2732 + 100) {
note.destroy();
self.notes.splice(i, 1);
}
}
};
- // Remove a specific note from the manager
self.removeNote = function (note) {
for (var i = 0; i < self.notes.length; i++) {
if (self.notes[i] === note) {
self.notes.splice(i, 1);
break;
}
}
};
- // Get all notes in play
self.getNotes = function () {
return self.notes;
};
- // Get the index of the next note to spawn
self.getNextNoteIdx = function () {
return self.nextNoteIdx;
};
- // Set the index of the next note to spawn
self.setNextNoteIdx = function (idx) {
self.nextNoteIdx = idx;
};
return self;
});
-// RestartButton class: a restart button shown during gameplay
var RestartButton = Container.expand(function () {
var self = Container.call(this);
- // Attach the restartButton asset
var btn = self.attachAsset('restartButton', {
anchorX: 0.5,
anchorY: 0.5
});
- // Handle tap
self.down = function (x, y, obj) {
- // Animate press feedback
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
@@ -709,45 +572,37 @@
easing: tween.cubicOut
});
};
self.up = function (x, y, obj) {
- // Animate release and restart game
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.cubicIn,
onFinish: function onFinish() {
- // Stop music and restart current song
LK.stopMusic();
gameActive = false;
- // Reset note manager
if (noteManager) {
noteManager.reset();
}
- // Restart the current song (not the entire game)
startGame();
}
});
};
return self;
});
-// ScoreText class: animated score display (mirrors ComboText)
var ScoreText = Container.expand(function () {
var self = Container.call(this);
- // Internal Text2 for display
self.textObj = new Text2('', {
size: 120,
fill: 0xFFFFFF,
dropShadow: true
});
self.textObj.anchor.set(0.5, 0);
self.addChild(self.textObj);
- // Set text and animate
self.setText = function (txt) {
self.textObj.setText(txt);
- // Animate: pop if not empty, fade out if empty
tween.stop(self.textObj, {
scaleX: true,
scaleY: true,
alpha: true
@@ -772,9 +627,8 @@
});
}
});
} else {
- // Fade out if empty
tween(self.textObj, {
alpha: 0
}, {
duration: 180
@@ -782,12 +636,10 @@
}
};
return self;
});
-// Sparkles class: creates and animates a small particle explosion
var Sparkles = Container.expand(function () {
var self = Container.call(this);
- // Configurable parameters
var particleCount = 12;
var minSpeed = 160;
var maxSpeed = 360;
var minScale = 0.5;
@@ -795,56 +647,30 @@
var minAlpha = 0.7;
var maxAlpha = 1.0;
var minDuration = 320;
var maxDuration = 1520;
- // Particle colors: only white to blue shades
- var colors = [0xffffff,
- // white
- 0xe0f7fa,
- // very light blue
- 0xb3e5fc,
- // light blue
- 0x81d4fa,
- // sky blue
- 0x4fc3f7,
- // lighter blue
- 0x29b6f6,
- // blue
- 0x039be5,
- // vivid blue
- 0x0288d1,
- // deep blue
- 0x0277bd,
- // darker blue
- 0x01579b,
- // navy blue
- 0x3a8ee6 // main game blue
- ];
- // Create particles
+ var colors = [0xffffff, 0xe0f7fa, 0xb3e5fc, 0x81d4fa, 0x4fc3f7, 0x29b6f6, 0x039be5, 0x0288d1, 0x0277bd, 0x01579b, 0x3a8ee6];
for (var i = 0; i < particleCount; i++) {
- var angle = Math.PI * 2 * (i / particleCount); // + Math.random() * 0.3;
+ var angle = Math.PI * 2 * (i / particleCount);
var speed = minSpeed + Math.random() * (maxSpeed - minSpeed);
var vx = Math.cos(angle) * speed;
var vy = Math.sin(angle) * speed;
var scale = minScale + Math.random() * (maxScale - minScale);
var alpha = minAlpha + Math.random() * (maxAlpha - minAlpha);
var color = colors[Math.floor(Math.random() * colors.length)];
var duration = minDuration + Math.random() * (maxDuration - minDuration);
var targetAngle = Math.PI * 2 * Math.random();
- // Use a small circle as the sparkle
var sparkle = self.attachAsset('sparkle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: scale,
scaleY: scale,
alpha: alpha,
tint: color
});
- // Animate outward movement, fade and shrink
(function (sparkle, vx, vy, duration) {
var startX = 0,
startY = 0;
- // Calculate the final position based on velocity and duration (assuming 60fps, so duration/1000 seconds)
var seconds = duration / 1000;
var finalX = startX + vx * seconds;
var finalY = startY + vy * seconds;
tween(sparkle, {
@@ -862,43 +688,36 @@
}
});
})(sparkle, vx, vy, duration);
}
- // Destroy the container after all particles are done
LK.setTimeout(function () {
self.destroy();
}, maxDuration + 40);
return self;
});
-// StartButton class: a tappable start button with image and animation
var StartButton = Container.expand(function () {
var self = Container.call(this);
self.isTapped = false;
- // Attach a big noteDot asset, centered, before the startText asset
var dot = self.attachAsset('noteDot', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5,
scaleY: 5,
alpha: 0.85
});
- // Attach the startText asset, centered, above the dot
var btn = self.attachAsset('startText', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1,
alpha: 1
});
- // Track if animation is complete
self.animationComplete = false;
- // Optional: pulse animation
var pulseTween;
function startPulse() {
- // Manual pulse animation with rotation instead of scale
function animateLeft() {
pulseTween = tween(self, {
- rotation: -0.1 // Small rotation to the left (in radians)
+ rotation: -0.1
}, {
duration: 1000,
easing: tween.cubicInOut,
onFinish: function onFinish() {
@@ -907,22 +726,20 @@
});
}
function animateRight() {
pulseTween = tween(self, {
- rotation: 0.1 // Small rotation to the right (in radians)
+ rotation: 0.1
}, {
duration: 1000,
easing: tween.cubicInOut,
onFinish: function onFinish() {
animateLeft();
}
});
}
- // Start from neutral position
self.rotation = 0;
animateLeft();
}
- // Animate pop-in (longer duration)
self.scaleX = 0.1;
self.scaleY = 0.1;
tween(self, {
scaleX: 1.2,
@@ -943,29 +760,21 @@
}
});
}
});
- // Public: set callback for tap
self.onTap = null;
- // Handle tap
self.down = function (x, y, obj) {
- // Only allow tap if animation is complete
if (!self.animationComplete) {
return;
}
self.isTapped = true;
- // Stop pulse animation immediately
tween.stop(self, {
scaleX: true,
scaleY: true
});
- // Animate tap feedback
self.scaleX = 1.0;
self.scaleY = 1.0;
- // --- Moved start logic here ---
- // Play start sound when start is pressed
LK.getSound('startSound').play();
- // Animate exit: scale up and fade out, then destroy and start game (longer duration)
tween(self, {
scaleX: 10,
scaleY: 10,
alpha: 0
@@ -978,9 +787,8 @@
startGame();
}
});
};
- // Clean up pulse tween on destroy
var origDestroy = self.destroy;
self.destroy = function () {
if (pulseTween) {
tween.stop(self, {
@@ -991,12 +799,10 @@
origDestroy.call(self);
};
return self;
});
-// Target class: represents the target area for each lane
var Target = Container.expand(function () {
var self = Container.call(this);
- // Attach the target asset, centered, with blue tint
var targetAsset = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x3a8ee6,
@@ -1014,15 +820,8 @@
/****
* Game Code
****/
-// Sound assets for key0 to key14
-// Falling note (white dot)
-// Tap feedback (blue highlight)
-// Lane highlight (subtle gray)
-// Sound for correct tap
-// Sound for miss
-// Music track (Ode to Joy, assumed loaded as 'odeToJoy')
var SONGS = [{
"name": "Ode to Joy\r\nBeethoven",
"bpm": 220,
"pitchLevel": 0,
@@ -5321,12 +5120,8 @@
}],
"fromLibrary": true
}];
var songsRating = [];
-// --- Song Data: Use SONGS[0] ---
-// Each note: {lane: 0|1|2, time: ms from song start}
-// Lane 0: left, 1: center, 2: right
-// We'll map keys to lanes below.
var songNotesRaw = SONGS[0].songNotes;
var keyToLane = {
"Key0": 0,
"Key1": 1,
@@ -5344,36 +5139,23 @@
"Key13": 1,
"Key14": 2
};
var songNotes = [];
-// Song duration (ms)
var songDuration;
-// --- Lane positions (3 columns) ---
var laneCount = 3;
var laneWidth = 600;
var laneOffset = 150;
var laneSpacing = 2048 / laneCount;
-var laneX = [laneSpacing * 0.5 + laneOffset,
-// left
-laneSpacing * 1.5,
-// center
-laneSpacing * 2.5 - laneOffset // right
-];
-// --- Visual: show hit line (subtle, not interactive) ---
+var laneX = [laneSpacing * 0.5 + laneOffset, laneSpacing * 1.5, laneSpacing * 2.5 - laneOffset];
var hitLine;
-// --- Hit line (invisible, for reference) ---
var hitLineYDisplay;
-// --- Instantiate 3 targets, one in each column at hitLineY ---
var targets = [];
-// --- Note fall parameters ---
-var speedMultiplier = 1.0; // Global speed multiplier (1.0 = normal, >1 = faster, <1 = slower)
-var baseNoteTravelTime = 4000; //8000; // ms: base time from spawn (top) to hit line (bottom)
-var noteTravelTime = baseNoteTravelTime / speedMultiplier; // effective travel time, updated if speedMultiplier changes
-var hitLineY = 2000; // y position where notes should be tapped
-var baseNoteStartY = -4000; // base spawn position
-var noteStartY = baseNoteStartY; // actual spawn position (will be updated based on speedMultiplier)
-// --- State ---
-// Declare all global game objects as variables (no instantiation here)
+var speedMultiplier = 1.0;
+var baseNoteTravelTime = 4000;
+var noteTravelTime = baseNoteTravelTime / speedMultiplier;
+var hitLineY = 2000;
+var baseNoteStartY = -4000;
+var noteStartY = baseNoteStartY;
var noteManager;
var menuManager;
var restartBtn;
var songStartTime;
@@ -5383,26 +5165,21 @@
var maxCombo;
var lastTapTime;
var totalNotes;
var failedNotes;
-// --- GUI Elements ---
var scoreTxt;
var comboTxt;
var menuButton;
-// --- Instantiate and add background manager ---
var bgManager;
-// --- Lane highlights (for visual feedback) ---
var laneHighlights;
function startGame() {
- // Reset state
if (!noteManager) {
noteManager = new NoteManager();
}
noteManager.reset();
score = LK.getScore();
combo = 0;
maxCombo = 0;
- // Reset rating tracking
totalNotes = songNotes.length;
failedNotes = 0;
if (!scoreTxt) {
scoreTxt = new ScoreText();
@@ -5418,56 +5195,44 @@
LK.gui.top.addChild(comboTxt);
}
comboTxt.setText('');
lastTapTime = 0;
- // Show lane highlights when game starts
if (laneHighlights) {
for (var i = 0; i < laneHighlights.length; i++) {
laneHighlights[i].visible = true;
}
}
- // Show targets when game starts
if (targets) {
for (var i = 0; i < targets.length; i++) {
targets[i].visible = true;
}
}
- // Show restart button when game starts
if (restartBtn) {
restartBtn.visible = true;
}
- // Show menu button when game starts
if (menuButton) {
menuButton.visible = true;
}
LK.setTimeout(function () {
gameActive = true;
songStartTime = Date.now();
}, 1000);
}
-// --- Main game update loop ---
game.update = function () {
- // Update menu manager scrolling
if (menuManager && menuManager.visible) {
menuManager.update();
}
- // Update noteTravelTime in case speedMultiplier has changed
noteTravelTime = baseNoteTravelTime / speedMultiplier;
- // Update noteStartY to maintain visual spacing when speed changes
noteStartY = baseNoteStartY / speedMultiplier;
if (!gameActive) {
return;
}
var now = Date.now();
var songElapsed = now - songStartTime;
- // --- Spawn notes as their time approaches ---
noteManager.spawnNotes(songNotes, songElapsed, noteTravelTime, laneX, noteStartY);
- // --- Update notes: remove notes that are far past the hit line ---
noteManager.cleanupNotes(songElapsed);
- // --- Win condition: song finished and all notes handled ---
if (songElapsed > songDuration + 600 && noteManager.getNotes().length === 0 && gameActive) {
gameActive = false;
- // Calculate star rating
var failureRate = totalNotes > 0 ? failedNotes / totalNotes : 0;
var stars = 0;
if (failedNotes === 0 || failedNotes === 1) {
stars = 3;
@@ -5477,14 +5242,12 @@
stars = 1;
} else {
stars = 0;
}
- // Display stars
var starContainer = new Container();
starContainer.x = 2048 / 2;
starContainer.y = 800;
game.addChild(starContainer);
- // Create and animate stars
var starSpacing = 150;
var starStartX = -(stars - 1) * starSpacing / 2;
for (var i = 0; i < stars; i++) {
(function (index) {
@@ -5494,9 +5257,9 @@
x: starStartX + index * starSpacing,
y: 0,
scaleX: 0,
scaleY: 0,
- tint: 0xFFD700 // Gold color
+ tint: 0xFFD700
});
LK.setTimeout(function () {
tween(star, {
scaleX: 2,
@@ -5507,45 +5270,37 @@
});
}, index * 200);
})(i);
}
- // Play cheers sound before YouWin
LK.getSound('cheers').play();
LK.setTimeout(function () {
restartBtn.visible = false;
menuButton.visible = false;
LK.showYouWin();
}, 4400);
}
};
-// --- Tap input handling ---
-// Convert x to lane index (0,1,2)
function getLaneFromX(x) {
- // Each lane is laneSpacing wide, centered at laneX[i]
for (var i = 0; i < laneCount; i++) {
var left = laneX[i] - laneWidth / 2;
var right = laneX[i] + laneWidth / 2;
if (x >= left && x <= right) {
return i;
}
}
- // Out of bounds
return -1;
}
-// On tap (down) anywhere in game
game.down = function (x, y, obj) {
if (!gameActive) {
return;
}
- // Only accept taps near the hit line (±220px)
if (y < hitLineY - 220 || y > hitLineY + 220) {
return;
}
var lane = getLaneFromX(x);
if (lane < 0 || lane >= laneCount) {
return;
}
- // Find the earliest untapped note in this lane within hit window
var now = Date.now();
var songElapsed = now - songStartTime;
var bestNote = null;
var bestDelta = 9999;
@@ -5559,23 +5314,19 @@
continue;
}
var delta = Math.abs(songElapsed - note.hitTime);
if (delta < 320 && delta < bestDelta) {
- // 320ms window
bestNote = note;
bestDelta = delta;
}
}
if (bestNote) {
- // Correct tap!
bestNote.tapped = true;
bestNote.showTapFeedback();
LK.getSound('tapGood').play();
- // Play the corresponding key sound for this note (moved to Note.down)
if (typeof bestNote.down === "function") {
bestNote.down();
}
- // Calculate points based on the distance to the hitLineY
var distance = Math.abs(bestNote.y - hitLineY);
var norm = distance / (bestNote.height / 2);
var points = 1;
if (norm <= 0.1) {
@@ -5603,12 +5354,10 @@
score += combo * points;
if (combo > maxCombo) {
maxCombo = combo;
}
- // Update LK score system
LK.setScore(score);
scoreTxt.setText(score + '');
- // Animate scoreTxt scale pop
tween.stop(scoreTxt, {
scaleX: true,
scaleY: true
});
@@ -5631,9 +5380,8 @@
}
});
if (combo > 1) {
comboTxt.setText('Combo x' + combo + '!');
- // Animate comboTxt scale pop
tween.stop(comboTxt, {
scaleX: true,
scaleY: true
});
@@ -5657,11 +5405,9 @@
});
} else {
comboTxt.setText('');
}
- // Flash lane blue
LK.effects.flashObject(laneHighlights[lane], 0x3a8ee6, 180);
- // Animate corresponding target scale
var tappedTarget = targets[lane];
if (tappedTarget) {
tappedTarget.scaleX = 1;
tappedTarget.scaleY = 1;
@@ -5681,62 +5427,44 @@
});
}
});
}
- // Remove note visually
tween(bestNote, {
alpha: 0
}, {
duration: 180,
onFinish: function onFinish() {
bestNote.destroy();
}
});
- // Remove from notes array after fade
noteManager.removeNote(bestNote);
} else {
- // Miss! (Tapped with no note in window)
combo = 0;
comboTxt.setText('');
LK.getSound('tapMiss').play();
LK.effects.flashObject(laneHighlights[lane], 0xff0000, 300);
- //LK.effects.flashScreen(0xff0000, 100);
- /*
- gameActive = false;
- LK.setTimeout(function () {
- LK.showGameOver();
- }, 600);
- */
}
};
-// --- Reset game on game over or win ---
LK.on('gameover', function () {
LK.stopMusic();
startGame();
});
LK.on('youwin', function () {
LK.stopMusic();
startGame();
});
-// Game initialization
function initializeGame() {
- // Instantiate and initialize all global objects here
for (var i = 0; i < SONGS.length; i++) {
songsRating[i] = 0;
}
- // --- Instantiate and add background manager ---
bgManager = new BackgroundManager();
game.addChild(bgManager);
- // Create menu manager
menuManager = new MenuManager();
menuManager.createMenuTiles(SONGS);
menuManager.onSongSelected = function (songIndex) {
- // Hide menu
menuManager.hide();
- // Update current song data
songNotesRaw = SONGS[songIndex].songNotes;
songNotes = [];
- // Process notes for the selected song
for (var i = 0; i < songNotesRaw.length; i++) {
var note = songNotesRaw[i];
var lane = 0;
if (keyToLane.hasOwnProperty(note.key)) {
@@ -5748,16 +5476,13 @@
lane: lane,
time: note.time
});
}
- // Update song duration with speedMultiplier applied
songDuration = songNotes.length > 0 ? songNotes[songNotes.length - 1].time / speedMultiplier + 1000 : 9000;
- // Start the game
startGame();
};
game.addChild(menuManager);
- menuManager.visible = false; // Initially hidden
- // If the song uses only Key6/Key7/Key8, map them to 0/1/2, else fallback to a round-robin
+ menuManager.visible = false;
for (var i = 0; i < songNotesRaw.length; i++) {
var note = songNotesRaw[i];
var lane = 0;
if (keyToLane.hasOwnProperty(note.key)) {
@@ -5769,9 +5494,8 @@
lane: lane,
time: note.time
});
}
- // Song duration (ms) with speedMultiplier applied
songDuration = songNotes.length > 0 ? songNotes[songNotes.length - 1].time / speedMultiplier + 1000 : 9000;
hitLine = LK.getAsset('laneHighlight', {
anchorX: 0.5,
anchorY: 0.5,
@@ -5786,50 +5510,44 @@
for (var i = 0; i < laneCount; i++) {
var target = new Target();
target.x = laneX[i];
target.y = hitLineY;
- target.visible = false; // hide initially
+ target.visible = false;
game.addChild(target);
targets.push(target);
}
- // --- State ---
- noteManager = new NoteManager(); // Handles all notes and spawning
- songStartTime = 0; // Date.now() when song started
- gameActive = false; // True if game is running
+ noteManager = new NoteManager();
+ songStartTime = 0;
+ gameActive = false;
score = 0;
combo = 0;
maxCombo = 0;
lastTapTime = 0;
- // Rating system tracking
totalNotes = 0;
- failedNotes = 0; // Tracks misses and too early taps
- // --- GUI Elements ---
+ failedNotes = 0;
scoreTxt = new ScoreText();
scoreTxt.setText(LK.getScore() + '');
scoreTxt.y = 0;
- scoreTxt.visible = false; // hide initially
+ scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
comboTxt = new ComboText();
comboTxt.y = 130;
comboTxt.tint = 0x3A8EE6;
LK.gui.top.addChild(comboTxt);
- // Add restart button to bottom right
if (!restartBtn) {
restartBtn = new RestartButton();
- restartBtn.visible = false; // Initially hidden
- restartBtn.x = 1900; // Move left to ensure it's fully on screen
- restartBtn.y = 150; // Move left to ensure it's fully on screen
+ restartBtn.visible = false;
+ restartBtn.x = 1900;
+ restartBtn.y = 150;
game.addChild(restartBtn);
}
- // Add menu button
if (!menuButton) {
menuButton = new MenuButton();
- menuButton.visible = false; // Initially hidden
+ menuButton.visible = false;
menuButton.x = 200;
menuButton.y = 500;
game.addChild(menuButton);
}
- // --- Lane highlights (for visual feedback) ---
laneHighlights = [];
for (var i = 0; i < laneCount; i++) {
var laneHL = LK.getAsset('laneHighlight', {
anchorX: 0.5,
@@ -5837,39 +5555,32 @@
alpha: 0.07,
x: laneX[i],
y: 0,
height: 2732,
- visible: false // hide initially
+ visible: false
});
game.addChild(laneHL);
laneHighlights.push(laneHL);
}
- // --- Hit line (invisible, for reference) ---
hitLineYDisplay = hitLineY;
- // Show StartButton and call startGame only when tapped
if (typeof startBtn !== "undefined" && startBtn) {
startBtn.destroy();
startBtn = null;
}
startBtn = new StartButton();
startBtn.x = 2048 / 2;
startBtn.y = 1200;
- // Modify start button to show menu instead
startBtn.down = function (x, y, obj) {
- // Only allow tap if animation is complete
if (!startBtn.animationComplete) {
return;
}
- // Animate tap feedback
tween.stop(startBtn, {
scaleX: true,
scaleY: true
});
startBtn.scaleX = 1.0;
startBtn.scaleY = 1.0;
- // Play start sound
LK.getSound('startSound').play();
- // Animate exit and show menu
tween(startBtn, {
scaleX: 100,
scaleY: 100,
alpha: 0
@@ -5878,17 +5589,14 @@
easing: tween.cubicIn,
onFinish: function onFinish() {
startBtn.destroy();
startBtn = null;
- // Hide restart button when showing menu
if (restartBtn) {
restartBtn.visible = false;
}
- // Hide menu button when showing menu
if (menuButton) {
menuButton.visible = false;
}
- // Show menu manager
menuManager.show();
}
});
};
key0
Sound effect
key1
Sound effect
key2
Sound effect
key3
Sound effect
key4
Sound effect
key5
Sound effect
key6
Sound effect
key7
Sound effect
key8
Sound effect
key10
Sound effect
key11
Sound effect
key12
Sound effect
key13
Sound effect
key14
Sound effect
key9
Sound effect
tapMiss
Sound effect
cheers
Sound effect
startSound
Sound effect
click
Sound effect
menuSpawn
Sound effect
jeers
Sound effect