Code edit (2 edits merged)
Please save this source code
User prompt
Ok, now make final orb scale twice bigger
User prompt
now orb have the correct orientation, but they don't move and grow like gates. Please step back and analyse then fix orbs behaviour to match gate's one
User prompt
adjust orbs spawning and update so that they look like gates in term of position and movement
Code edit (1 edits merged)
Please save this source code
User prompt
Now make orbs behave like gates after they are spawned, orbs should follow a similar trajectory
User prompt
in GateManager.spawnGateAtTime(), call in OrbManager to spawn an Orb at the 'free angle' when spawning 2 gates.
User prompt
in OrbManager and Orb, use the same technique as GateManager.spawnGateAtTime() and Gate.updateScale() to spawn orbs and make them move ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
enhance orbs move : clone the system used for gates
User prompt
add an obrManager to spawn orbs; they should spanw from center with small scale and increase scale like the system used for gates ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'scaleX')' in or related to this line: 'var currentScale = orb.orbAsset.scaleX;' Line Number: 622
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'rotation')' in or related to this line: 'orb.orbAsset.rotation = orbAngle; // Assuming orbAsset exists and needs rotation' Line Number: 589
User prompt
Please fix the bug: 'TypeError: orb.setColor is not a function' in or related to this line: 'orb.setColor(orbColor); // Assuming Orb class has a setColor method' Line Number: 562
User prompt
Please fix the bug: 'ReferenceError: orbManager is not defined' in or related to this line: 'lastTick = now;' Line Number: 3174
User prompt
Please fix the bug: 'ReferenceError: orbManager is not defined' in or related to this line: 'if (orbManager) {' Line Number: 3176
User prompt
add an obrManager to spawn orbs like gates
User prompt
Ok now add and orb class but don't use it. add an anim using assets orb0,orb1,orb2,orb3,orb4 and orb5 as frames and changing their alpha in sequence ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
ok, add some randomness in WorldManager target's selection : don't only go to left border of left BG then right border of right BG but selected a random target between the two and animate to it then choose another random target ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
ok, add some randomness in WorldManager target's selection
Code edit (1 edits merged)
Please save this source code
User prompt
in WorldManager make BGs shift very slowly during song play to left the right ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add a new worldManager to display 2 worldBackground side by side (one with scaleX = -1)
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BackgroundManager = Container.expand(function () { var self = Container.call(this); self.bg0 = self.attachAsset('background01', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 2.4, scaleY: 2.4, alpha: 1 }); self.bg1 = self.attachAsset('background01', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 1.1, scaleY: 1.1, alpha: 1 }); self.bg2 = self.attachAsset('background01', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 0.5, scaleY: 0.5, alpha: 1 }); self.bg3 = self.attachAsset('background01', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 0.22, scaleY: 0.22, alpha: 1 }); self.bg4 = self.attachAsset('background01', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 0.11, scaleY: 0.11, alpha: 1 }); self.tore0 = self.attachAsset('tore', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 1.2, scaleY: 1.2, alpha: 0 }); self.tore1 = self.attachAsset('tore', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 0.6, scaleY: 0.6, alpha: 0 }); self.tore2 = self.attachAsset('tore', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 0.26, scaleY: 0.26, alpha: 0 }); self.tore3 = self.attachAsset('tore', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 0.12, scaleY: 0.12, alpha: 0 }); if (isDebug) { self.bg1.tint = 0xFF0000; self.tore1.tint = 0x00FF00; self.bg2.tint = 0x00FFFF; self.tore2.tint = 0xFF00FF; self.bg3.tint = 0xfff200; } self.bgAnimationSpeed = globalSpeed / 1000; self.bgAnimationAcceleration = 2; self.backgrounds = [self.bg0, self.tore0, self.bg1, self.tore1, self.bg2, self.tore2, self.bg3, self.tore3, self.bg4]; self.bgAnimStartTime = Date.now(); self.update = function () { if (!songStarted) { return; } var now = Date.now(); var elapsed = now - self.bgAnimStartTime; var resetTriggered = false; for (var i = 0; i < self.backgrounds.length; i++) { var bg = self.backgrounds[i]; bg.scaleX += self.bgAnimationSpeed * bg.scaleX; bg.scaleY = bg.scaleX; if (bg.scaleX > 3.0) { bg.scaleX = 0.12; bg.scaleY = bg.scaleX; } bg.tint = 0x1697b8; } }; return self; }); var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5, tint: currentColor, alpha: 1 }); self.speedX = 0; self.speedY = 0; self.lastIntersectingGates = {}; self.update = function () { if (!songStarted) { return; } if (runner) { self.x = runner.x; self.y = runner.y; } if (gateManager && gateManager.gates) { for (var i = gateManager.gates.length - 1; i >= 0; i--) { var gate = gateManager.gates[i]; var gateId = gate.gateId; if (self.lastIntersectingGates[gateId] === undefined) { self.lastIntersectingGates[gateId] = false; } var currentIntersecting = gate.gateAsset.scaleX >= minDetectionScale && gate.gateAsset.scaleX <= maxDetectionScale && self.intersects(gate.boundingBox); if (!self.lastIntersectingGates[gateId] && currentIntersecting) { playHitSound(); if (!gate.isDestroying) { gate.isDestroying = true; tween(gate, { scaleX: 0, scaleY: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { gateManager.destroyGate(gate); } }); } } self.lastIntersectingGates[gateId] = currentIntersecting; } } }; return self; }); var Gate = Container.expand(function () { var self = Container.call(this); self.gateAsset = self.attachAsset('gate', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 0.26, scaleY: 0.26, alpha: 1, visible: false }); self.directionAngle = 0; self.boundingBox = self.attachAsset('boundingBox', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2450, alpha: 1 }); /* width: 200, heigh: 100, */ self.gateColor = 0xFFFFFF; self.gateId = null; self.setColor = function (color) { self.gateColor = color; self.gateAsset.tint = color; { self.boundingBox.alpha = 0.8; } }; self.updateScale = function (newScale) { /* self.scaleX = newScale; self.scaleY = newScale; self.alpha = Math.min(1, newScale + 0.66); */ self.gateAsset.scaleX = newScale; self.gateAsset.scaleY = newScale; self.gateAsset.alpha = Math.min(1, newScale + 0.66); self.boundingBox.scaleX = newScale; self.boundingBox.scaleY = newScale; var distance = (2450 - 1366) * newScale; self.boundingBox.x = centerX + distance * Math.cos(self.directionAngle + Math.PI * 0.5); self.boundingBox.y = centerY + distance * Math.sin(self.directionAngle + Math.PI * 0.5); self.boundingBox.rotation = self.directionAngle; }; return self; }); var GateManager = Container.expand(function () { var self = Container.call(this); self.gates = []; self.gateAnimStartTime = Date.now(); self.gateAnimationSpeed = globalSpeed / 1000; self.currentSong = songListV3[0]; self.songStartTime = Date.now(); self.currentNoteIndex = 0; self.noteSpawnScale = 0.12; self.lastGateAngle = null; self.lastProcessedBeat = -1; self.spawnGateAtTime = function () { var beatValue = null; if (self.currentNoteIndex < self.currentSong.songBeats.length) { beatValue = self.currentSong.songBeats[self.currentNoteIndex].beat; } var keyNumber = parseInt(beatValue, 10) || 1; var noteKey = 'Key' + keyNumber; var keyColor = keyColorMap[noteKey] || currentColor; var startScale = self.noteSpawnScale; var endScale = 1.0; var speed = self.gateAnimationSpeed; var timeToReachPlayer = Math.log(endScale / startScale) / speed; var beatAngle = centerAngle; if (beatValue === "1") { beatAngle = rightAngle; } else if (beatValue === "2") { beatAngle = leftAngle; } else { beatAngle = centerAngle; } self.lastGateAngle = beatAngle; var allAngles = [leftAngle, centerAngle, rightAngle]; var gateAngles = []; for (var i = 0; i < allAngles.length; i++) { if (allAngles[i] !== beatAngle) { gateAngles.push(allAngles[i]); } } var beatTime = self.currentSong.songBeats[self.currentNoteIndex].time; var now = Date.now(); var songElapsed = now - self.songStartTime; var spawnTime = beatTime - timeToReachPlayer; for (var j = 0; j < gateAngles.length; j++) { var gate = new Gate(); gate.setColor(keyColor); gate.updateScale(self.noteSpawnScale); gate.spawnTime = Date.now() + 200 / globalSpeed; gate.colorIndex = 0; gate.gateId = getNextGateId(); gate.noteKey = noteKey; gate.directionAngle = gateAngles[j]; gate.gateAsset.rotation = gateAngles[j]; if (songElapsed >= spawnTime) { self.gates.push(gate); self.addChild(gate); } else { (function (g) { LK.setTimeout(function () { self.gates.push(g); self.addChild(g); }, spawnTime - songElapsed); })(gate); } } }; self.update = function () { if (!songStarted) { return; } var now = Date.now(); var songElapsed = now - self.songStartTime; if (self.currentNoteIndex < self.currentSong.songBeats.length) { var nextBeat = self.currentSong.songBeats[self.currentNoteIndex]; if (songElapsed >= nextBeat.time) { if (now - lastBeatTime >= skipBeatDelay) { self.spawnGateAtTime(); lastBeatTime = now; } self.currentNoteIndex++; } } for (var i = self.gates.length - 1; i >= 0; i--) { var gate = self.gates[i]; var currentScale = gate.gateAsset.scaleX; var newScale = currentScale + self.gateAnimationSpeed * currentScale; if (newScale > 3.0) { gate.destroy(); self.gates.splice(i, 1); } else { gate.updateScale(newScale); } } self.checkSongEnd(); }; self.resetSong = function () { self.songStartTime = Date.now(); self.currentNoteIndex = 0; self.lastGateAngle = null; }; self.checkSongEnd = function () { if (self.currentNoteIndex >= self.currentSong.songBeats.length) { var lastBeatTime = self.currentSong.songBeats[self.currentSong.songBeats.length - 1].time; var songElapsed = Date.now() - self.songStartTime; if (songElapsed > lastBeatTime + 5000) { self.resetSong(); } } }; self.destroyGate = function (gate) { var index = self.gates.indexOf(gate); if (index > -1) { self.gates.splice(index, 1); gate.destroy(); } }; return self; }); var Note = Container.expand(function () { var self = Container.call(this); var noteGraphics = self.attachAsset('note', { anchorX: 0.5, anchorY: 0.5, alpha: 1 }); self.velocity = { x: 0, y: -5 }; self.lifetime = 500; self.spawnTime = Date.now(); self.noteType = 'note'; self.noteColor = 0xFFFFFF; self.setNoteType = function (type) { self.noteType = type; noteGraphics.destroy(); noteGraphics = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5, alpha: 1 }); noteGraphics.tint = self.noteColor; }; self.setColor = function (color) { self.noteColor = color; noteGraphics.tint = color; }; self.setVelocity = function (vx, vy) { self.velocity.x = vx; self.velocity.y = vy; }; self.update = function () { self.x += self.velocity.x; self.y += self.velocity.y; var elapsed = Date.now() - self.spawnTime; if (elapsed > self.lifetime) { self.alpha = Math.max(0, 1 - (elapsed - self.lifetime) / 500); } if (elapsed > self.lifetime + 500 || self.y < -100 || self.y > 2832 || self.x < -100 || self.x > 2148) { self.shouldDestroy = true; } }; return self; }); var NoteSparks = Container.expand(function () { var self = Container.call(this); self.notes = []; self.spawnRate = 500; self.lastSpawnTime = 0; self.spawnEnabled = false; self.spawnX = 1024; self.spawnY = 1366; self.spawnVelocityRange = { x: { min: -2, max: 2 }, y: { min: -8, max: -4 } }; self.noteColors = [0xFF073A, 0x39FF14, 0x00FFFF, 0xF3F315, 0xFF61F6]; self.setSpawnPosition = function (x, y) { self.spawnX = x; self.spawnY = y; }; self.setSpawnEnabled = function (enabled) { self.spawnEnabled = enabled; }; self.setSpawnRate = function (rate) { self.spawnRate = rate; }; self.spawnNote = function () { var note = new Note(); note.x = self.spawnX + (Math.random() - 0.5) * 50; note.y = self.spawnY; var vx = self.spawnVelocityRange.x.min + Math.random() * (self.spawnVelocityRange.x.max - self.spawnVelocityRange.x.min); var vy = self.spawnVelocityRange.y.min + Math.random() * (self.spawnVelocityRange.y.max - self.spawnVelocityRange.y.min); note.setVelocity(vx, vy); note.setNoteType(Math.random() > 0.5 ? 'note' : 'note2'); var color = self.noteColors[Math.floor(Math.random() * self.noteColors.length)]; note.setColor(color); note.rotation = (Math.random() - 0.5) * 0.5; self.notes.push(note); self.addChild(note); }; self.spawnBurst = function (count) { for (var i = 0; i < count; i++) { self.spawnNote(); } }; self.update = function () { var now = Date.now(); if (self.spawnEnabled && now - self.lastSpawnTime >= self.spawnRate) { self.spawnNote(); self.lastSpawnTime = now; } for (var i = self.notes.length - 1; i >= 0; i--) { var note = self.notes[i]; if (note.shouldDestroy) { note.destroy(); self.notes.splice(i, 1); } } }; return self; }); var Runner = Container.expand(function () { var self = Container.call(this); var runnerGraphics = self.attachAsset('runnerDir4_001', { anchorX: 0.5, anchorY: 0.5, tint: 0xFFFFFF, alpha: 1 }); self.speedX = 0; self.speedY = 0; self.lastIntersectingGates = {}; self.tickCounter = 0; self.update = function () { if (!songStarted) { return; } var angle = Math.atan2(self.y - centerY, self.x - centerX); self.rotation = angle - Math.PI * 0.5; self.tickCounter++; if (self.tickCounter >= 5) { self.scaleX *= -1; self.tickCounter = 0; } }; return self; }); var Speaker = Container.expand(function () { var self = Container.call(this); var speakerGraphics = self.attachAsset('speaker', { anchorX: 0.5, anchorY: 0.5, alpha: 1 }); self.volume = 1.0; self.isPlaying = false; self.setVolume = function (vol) { self.volume = Math.max(0, Math.min(1, vol)); }; self.toggleState = function () { self.isPlaying = !self.isPlaying; speakerGraphics.alpha = self.isPlaying ? 1.0 : 0.5; }; return self; }); var SpeakerManager = Container.expand(function () { var self = Container.call(this); self.speakers = []; self.lastBeatTime = 0; self.beatCooldown = 200; self.speakerSongData = speakersBeat[0]; self.currentBeatIndex = 0; self.songStartTime = 0; self.initializeSpeakers = function () { var speakerPositions = [{ x: 1024 - 400, y: 512 }, { x: 1024, y: 512 }, { x: 1024 + 400, y: 512 }]; for (var i = 0; i < 3; i++) { var speaker = new Speaker(); speaker.x = speakerPositions[i].x; speaker.y = speakerPositions[i].y; speaker.scaleX = 0.8; speaker.scaleY = 0.8; speaker.isBigBumping = false; self.speakers.push(speaker); self.addChild(speaker); } }; self.onBeat = function (beatValue) { var now = Date.now(); if (now - self.lastBeatTime >= self.beatCooldown) { var speakerIndex = -1; if (beatValue === "1") { speakerIndex = 0; } else if (beatValue === "2") { speakerIndex = 2; } else { speakerIndex = 1; } if (speakerIndex >= 0 && speakerIndex < self.speakers.length) { var mainSpeaker = self.speakers[speakerIndex]; mainSpeaker.isBigBumping = true; self.spawnNoteSparks(mainSpeaker); tween(mainSpeaker, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(mainSpeaker, { scaleX: 0.8, scaleY: 0.8 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { mainSpeaker.isBigBumping = false; } }); } }); } self.lastBeatTime = now; } }; self.update = function () { if (songStarted) { for (var i = 0; i < self.speakers.length; i++) { var speaker = self.speakers[i]; var time = Date.now() * 0.003; var twistAngle = Math.sin(time + i * 0.5) * 0.15; speaker.rotation = twistAngle; if (!speaker.isBigBumping) { var scaleValue = 0.8 + Math.sin(time * 2 + i * 0.3) * 0.05; speaker.scaleX = scaleValue; speaker.scaleY = scaleValue; } } } if (!songStarted) { return; } var now = Date.now(); var songElapsed = now - self.songStartTime; if (self.currentBeatIndex < self.speakerSongData.songBeats.length) { var nextBeat = self.speakerSongData.songBeats[self.currentBeatIndex]; if (songElapsed >= nextBeat.time) { self.onBeat(nextBeat.beat); self.currentBeatIndex++; } } else { var lastBeatTime = self.speakerSongData.songBeats[self.speakerSongData.songBeats.length - 1].time; if (songElapsed > lastBeatTime + 5000) { self.songStartTime = Date.now(); self.currentBeatIndex = 0; } } }; self.spawnNoteSparks = function (speaker) { var noteCount = 3 + Math.floor(Math.random() * 3); for (var i = 0; i < noteCount; i++) { var note = new Note(); var angle = Math.random() * Math.PI * 2; var distance = 50 + Math.random() * 100; note.x = speaker.x + Math.cos(angle) * distance; note.y = speaker.y + Math.sin(angle) * distance; var speed = 3 + Math.random() * 5; note.setVelocity(Math.cos(angle) * speed, Math.sin(angle) * speed - 2); note.setNoteType(Math.random() > 0.5 ? 'note' : 'note2'); var futuristicColors = [0x32cbec]; var color = futuristicColors[Math.floor(Math.random() * futuristicColors.length)]; note.setColor(color); note.rotation = (Math.random() - 0.5) * 0.5; note.scaleX = 0.5; note.scaleY = 0.5; if (noteSparks) { noteSparks.notes.push(note); noteSparks.addChild(note); } } }; self.initializeSpeakers(); return self; }); /* var testGate = new Gate(); var newScale = 1; testGate.scaleX = newScale; testGate.scaleY = newScale; testGate.gateAsset.scaleX = newScale; testGate.gateAsset.scaleY = newScale; testGate.boundingBox.scaleX = newScale; testGate.boundingBox.scaleY = newScale; testGate.boundingBox.alpha = 0.3; game.addChild(testGate); */ var StartButton = Container.expand(function () { var self = Container.call(this); self.buttonBg = self.attachAsset('start', { anchorX: 0.5, anchorY: 0.5 }); self.x = centerX; self.y = centerY; self.down = function () { if (songStarted) { return; } songStarted = true; LK.playMusic('track_01'); if (gateManager) { gateManager.songStartTime = Date.now(); gateManager.currentNoteIndex = 0; } if (speakerManager) { speakerManager.songStartTime = Date.now(); speakerManager.currentBeatIndex = 0; } if (noteSparks) {} tween(self, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var WorldManager = Container.expand(function () { var self = Container.call(this); var assetWidth = 2732; var screenWidth = 2048; var totalContentWidth = assetWidth * 2; self.x_center_view = -(totalContentWidth / 2 - screenWidth / 2); self.shiftAmplitude = 1024; self.shiftDurationOneWay = 15000; self._isShifting = false; self._animateToRandomTarget = function () { if (!songStarted || !self._isShifting) { self._isShifting = false; tween.stop(self, { x: true }); return; } var minTargetX = self.x_center_view - self.shiftAmplitude; var maxTargetX = self.x_center_view + self.shiftAmplitude; var randomTargetX = minTargetX + Math.random() * (maxTargetX - minTargetX); var currentX = self.x; var distanceToTravel = Math.abs(currentX - randomTargetX); if (distanceToTravel < 50) { LK.setTimeout(self._animateToRandomTarget, 0); return; } var speed = self.shiftAmplitude / self.shiftDurationOneWay; if (speed <= 0) { speed = (self.shiftAmplitude > 0 ? self.shiftAmplitude : 1024) / 15000; if (speed <= 0) { speed = 0.05; } } var dynamicDuration = distanceToTravel / speed; dynamicDuration = Math.max(500, Math.min(dynamicDuration, self.shiftDurationOneWay * 2)); tween(self, { x: randomTargetX }, { duration: dynamicDuration, easing: tween.easeInOut, onFinish: self._animateToRandomTarget }); }; self._initiateShift = function () { if (self._isShifting) { return; } self._isShifting = true; self._animateToRandomTarget(); }; self.update = function () { if (songStarted && !self._isShifting) { self._initiateShift(); } else if (!songStarted && self._isShifting) { self._isShifting = false; tween.stop(self, { x: true }); tween(self, { x: self.x_center_view }, { duration: 1000, easing: tween.easeOut }); } }; self.x = self.x_center_view; self.y = 0; self.bgLeft = self.attachAsset('world01', { anchorX: 0.5, anchorY: 0.5, x: assetWidth / 2, y: centerY, scaleX: 1.0, scaleY: 1.0 }); self.bgRight = self.attachAsset('world01', { anchorX: 0.5, anchorY: 0.5, x: assetWidth / 2 + assetWidth, y: centerY, scaleX: -1.0, scaleY: 1.0 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000c33 }); /**** * Game Code ****/ var centerX = 1024; var centerY = 1366; var neonColors = [0x39FF14, 0xFF073A, 0x00FFFF, 0xF3F315, 0xFF61F6, 0xFF9900]; var keyColorMap = { 'Key0': 0x39FF14, 'Key1': 0xFF073A, 'Key2': 0x00FFFF, 'Key3': 0xF3F315, 'Key4': 0xFF61F6, 'Key5': 0xFF9900, 'Key6': 0x39FF14, 'Key7': 0xFF073A, 'Key8': 0x00FFFF, 'Key9': 0xF3F315, 'Key10': 0xFF61F6, 'Key11': 0xFF9900, 'Key12': 0x39FF14, 'Key13': 0xFF073A, 'Key14': 0x00FFFF }; var currentColor = neonColors[Math.floor(Math.random() * neonColors.length)]; function drawPolygon(coordinates, tint) { log("drawPolygon ", coordinates); var lines = []; for (var i = 0; i < coordinates.length; i++) { var startPoint = coordinates[i]; var endPoint = coordinates[(i + 1) % coordinates.length]; var line = drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, tint); lines.push(line); } return lines; } function updatePolygon(lines, newCoordinates, scale) { log("updatePolygon ", lines, scale); if (lines.length !== newCoordinates.length) { error("updatePolygon error: lines and newCoordinates length mismatch"); return lines; } for (var i = 0; i < lines.length; i++) { var startPoint = newCoordinates[i]; var endPoint = newCoordinates[(i + 1) % newCoordinates.length]; updateLine(lines[i], startPoint.x, startPoint.y, endPoint.x, endPoint.y, scale); } return lines; } function drawLine(x1, y1, x2, y2, tint) { log("drawLine ", x1, y1); var line = LK.getAsset('line', { anchorX: 0.0, anchorY: 0.0, x: x1, y: y1, tint: tint }); line.startX = x1; line.startY = y1; line.endX = x2; line.endY = y2; var distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); line.width = distance; var angle = Math.atan2(y2 - y1, x2 - x1); line.rotation = angle; return line; } function updateLine(line, newX1, newY1, newX2, newY2, scale) { log("updateLine ", line); scale = scale === undefined ? 1 : scale; var midX = (newX1 + newX2) / 2; var midY = (newY1 + newY2) / 2; newX1 = midX + (newX1 - midX) * scale; newY1 = midY + (newY1 - midY) * scale; newX2 = midX + (newX2 - midX) * scale; newY2 = midY + (newY2 - midY) * scale; line.x = newX1; line.y = newY1; line.startX = newX1; line.startY = newY1; line.endX = newX2; line.endY = newY2; var distance = Math.sqrt(Math.pow(newX2 - newX1, 2) + Math.pow(newY2 - newY1, 2)); line.width = distance; var angle = Math.atan2(newY2 - newY1, newX2 - newX1); line.rotation = angle; return line; } function log() { if (isDebug) { console.log(arguments); } } var songListV3 = [{ "name": "Words Fly Fast", "songBeats": [{ "time": 651, "beat": "1" }, { "time": 1256, "beat": "1" }, { "time": 1800, "beat": "1" }, { "time": 2364, "beat": "1" }, { "time": 2828, "beat": "1" }, { "time": 3324, "beat": "1" }, { "time": 3708, "beat": "1" }, { "time": 4192, "beat": "2" }, { "time": 4804, "beat": "2" }, { "time": 5320, "beat": "2" }, { "time": 5796, "beat": "2" }, { "time": 6240, "beat": "2" }, { "time": 6692, "beat": "2" }, { "time": 7176, "beat": "2" }, { "time": 7640, "beat": "2" }, { "time": 8092, "beat": "1" }, { "time": 8576, "beat": "2" }, { "time": 9124, "beat": "1" }, { "time": 9580, "beat": "2" }, { "time": 10084, "beat": "1" }, { "time": 10548, "beat": "2" }, { "time": 11072, "beat": "1" }, { "time": 11556, "beat": "2" }, { "time": 12092, "beat": "1" }, { "time": 12564, "beat": "2" }, { "time": 13008, "beat": "1" }, { "time": 13400, "beat": "2" }, { "time": 13916, "beat": "1" }, { "time": 14460, "beat": "2" }, { "time": 14944, "beat": "1" }, { "time": 15360, "beat": "2" }, { "time": 17340, "beat": "1" }, { "time": 18260, "beat": "2" }, { "time": 19196, "beat": "1" }, { "time": 20064, "beat": "2" }, { "time": 21092, "beat": "1" }, { "time": 22072, "beat": "2" }, { "time": 23100, "beat": "1" }, { "time": 24040, "beat": "2" }, { "time": 24988, "beat": "1" }, { "time": 25884, "beat": "2" }, { "time": 26876, "beat": "1" }, { "time": 27892, "beat": "2" }, { "time": 28820, "beat": "1" }, { "time": 29688, "beat": "2" }, { "time": 30728, "beat": "1" }, { "time": 31696, "beat": "2" }, { "time": 32656, "beat": "1" }, { "time": 33624, "beat": "2" }, { "time": 34673, "beat": "1" }, { "time": 35692, "beat": "2" }, { "time": 36628, "beat": "1" }, { "time": 37536, "beat": "2" }, { "time": 38516, "beat": "1" }, { "time": 39372, "beat": "2" }, { "time": 40524, "beat": "1" }, { "time": 41028, "beat": "1" }, { "time": 43080, "beat": "2" }, { "time": 43564, "beat": "2" }, { "time": 44400, "beat": "1" }, { "time": 44948, "beat": "1" }, { "time": 46888, "beat": "2" }, { "time": 47412, "beat": "2" }, { "time": 48260, "beat": "1" }, { "time": 48818, "beat": "1" }, { "time": 50816, "beat": "2" }, { "time": 51524, "beat": "2" }, { "time": 52168, "beat": "1" }, { "time": 52684, "beat": "1" }, { "time": 54540, "beat": "3" }, { "time": 55488, "beat": "3" }, { "time": 56448, "beat": "3" }, { "time": 57436, "beat": "3" }, { "time": 58412, "beat": "1" }, { "time": 59240, "beat": "2" }, { "time": 59988, "beat": "1" }, { "time": 60808, "beat": "2" }, { "time": 61636, "beat": "1" }, { "time": 63800, "beat": "1" }, { "time": 64688, "beat": "2" }, { "time": 65656, "beat": "1" }, { "time": 66544, "beat": "2" }, { "time": 67492, "beat": "1" }, { "time": 68432, "beat": "2" }, { "time": 69369, "beat": "1" }, { "time": 70336, "beat": "2" }, { "time": 71416, "beat": "1" }, { "time": 72324, "beat": "2" }, { "time": 73408, "beat": "1" }, { "time": 74316, "beat": "2" }, { "time": 75276, "beat": "1" }, { "time": 76204, "beat": "2" }, { "time": 77248, "beat": "2" }, { "time": 78232, "beat": "1" }, { "time": 79168, "beat": "2" }, { "time": 81048, "beat": "1" }, { "time": 81996, "beat": "2" }, { "time": 83096, "beat": "1" }, { "time": 84064, "beat": "2" }, { "time": 85040, "beat": "1" }, { "time": 86008, "beat": "2" }, { "time": 86956, "beat": "1" }, { "time": 87976, "beat": "2" }, { "time": 88832, "beat": "1" }, { "time": 89844, "beat": "2" }, { "time": 90832, "beat": "1" }, { "time": 92672, "beat": "3" }, { "time": 93156, "beat": "3" }, { "time": 93720, "beat": "3" }, { "time": 94329, "beat": "3" }, { "time": 94812, "beat": "3" }, { "time": 95256, "beat": "3" }, { "time": 95720, "beat": "1" }, { "time": 96496, "beat": "2" }, { "time": 97556, "beat": "3" }, { "time": 98112, "beat": "3" }, { "time": 98624, "beat": "3" }, { "time": 99100, "beat": "3" }, { "time": 99604, "beat": "1" }, { "time": 100440, "beat": "2" }, { "time": 101420, "beat": "1" }, { "time": 102388, "beat": "2" }, { "time": 103336, "beat": "1" }, { "time": 104324, "beat": "2" }, { "time": 105172, "beat": "1" }, { "time": 106260, "beat": "3" }, { "time": 106836, "beat": "3" }, { "time": 107392, "beat": "3" }, { "time": 108028, "beat": "2" }, { "time": 108692, "beat": "1" }, { "time": 109540, "beat": "2" }, { "time": 110488, "beat": "1" }, { "time": 111932, "beat": "2" }, { "time": 112888, "beat": "1" }, { "time": 113796, "beat": "2" }, { "time": 114864, "beat": "1" }, { "time": 115904, "beat": "2" }, { "time": 116864, "beat": "2" }, { "time": 117792, "beat": "1" }, { "time": 119184, "beat": "2" }, { "time": 120244, "beat": "1" }, { "time": 121112, "beat": "2" }, { "time": 122121, "beat": "3" }, { "time": 122744, "beat": "3" }, { "time": 123260, "beat": "3" }, { "time": 123784, "beat": "3" }, { "time": 124217, "beat": "3" }, { "time": 125620, "beat": "1" }, { "time": 126668, "beat": "2" }, { "time": 127788, "beat": "1" }, { "time": 128796, "beat": "2" }, { "time": 129716, "beat": "1" }, { "time": 130884, "beat": "2" }, { "time": 131936, "beat": "1" }, { "time": 132932, "beat": "2" }, { "time": 134092, "beat": "1" }, { "time": 135124, "beat": "2" }, { "time": 136160, "beat": "1" }, { "time": 137128, "beat": "2" }, { "time": 139693, "beat": "3" }, { "time": 140208, "beat": "3" }, { "time": 140712, "beat": "3" }, { "time": 141216, "beat": "3" }, { "time": 141700, "beat": "3" }, { "time": 142164, "beat": "3" }, { "time": 142668, "beat": "3" }, { "time": 143164, "beat": "3" }, { "time": 143668, "beat": "1" }, { "time": 144484, "beat": "2" }, { "time": 145412, "beat": "1" }, { "time": 146340, "beat": "2" }, { "time": 147708, "beat": "3" }, { "time": 148304, "beat": "3" }, { "time": 148820, "beat": "3" }, { "time": 149312, "beat": "3" }, { "time": 149908, "beat": "1" }, { "time": 150804, "beat": "2" }, { "time": 151784, "beat": "3" }, { "time": 152328, "beat": "3" }, { "time": 152832, "beat": "3" }, { "time": 153236, "beat": "3" }, { "time": 153680, "beat": "1" }, { "time": 154518, "beat": "2" }] }]; var speakersBeat = [{ "name": "Words Fly Fast", "songBeats": [{ "time": 128, "beat": "1" }, { "time": 443, "beat": "1" }, { "time": 747, "beat": "1" }, { "time": 1232, "beat": "1" }, { "time": 1579, "beat": "1" }, { "time": 1893, "beat": "1" }, { "time": 2224, "beat": "1" }, { "time": 2549, "beat": "1" }, { "time": 2853, "beat": "1" }, { "time": 3269, "beat": "1" }, { "time": 3712, "beat": "1" }, { "time": 4037, "beat": "1" }, { "time": 4352, "beat": "1" }, { "time": 4661, "beat": "1" }, { "time": 5072, "beat": "1" }, { "time": 5392, "beat": "1" }, { "time": 5728, "beat": "1" }, { "time": 6176, "beat": "1" }, { "time": 6587, "beat": "1" }, { "time": 7141, "beat": "1" }, { "time": 7541, "beat": "1" }, { "time": 7856, "beat": "1" }, { "time": 8171, "beat": "3" }, { "time": 8501, "beat": "2" }, { "time": 8816, "beat": "2" }, { "time": 9120, "beat": "3" }, { "time": 9424, "beat": "2" }, { "time": 9728, "beat": "2" }, { "time": 10032, "beat": "3" }, { "time": 10347, "beat": "2" }, { "time": 10651, "beat": "1" }, { "time": 10971, "beat": "2" }, { "time": 11275, "beat": "2" }, { "time": 11600, "beat": "2" }, { "time": 11915, "beat": "1" }, { "time": 12240, "beat": "2" }, { "time": 12560, "beat": "3" }, { "time": 12875, "beat": "2" }, { "time": 13184, "beat": "3" }, { "time": 13493, "beat": "2" }, { "time": 13813, "beat": "3" }, { "time": 14176, "beat": "3" }, { "time": 14517, "beat": "1" }, { "time": 14843, "beat": "2" }, { "time": 15147, "beat": "2" }, { "time": 15472, "beat": "3" }, { "time": 15781, "beat": "2" }, { "time": 16112, "beat": "2" }, { "time": 16432, "beat": "2" }, { "time": 16741, "beat": "2" }, { "time": 17056, "beat": "3" }, { "time": 17360, "beat": "3" }, { "time": 17685, "beat": "2" }, { "time": 17995, "beat": "3" }, { "time": 18299, "beat": "3" }, { "time": 18608, "beat": "3" }, { "time": 18917, "beat": "3" }, { "time": 19232, "beat": "1" }, { "time": 19547, "beat": "2" }, { "time": 19851, "beat": "3" }, { "time": 20171, "beat": "1" }, { "time": 20475, "beat": "3" }, { "time": 20805, "beat": "3" }, { "time": 21120, "beat": "1" }, { "time": 21435, "beat": "2" }, { "time": 21749, "beat": "2" }, { "time": 22059, "beat": "2" }, { "time": 22373, "beat": "2" }, { "time": 22699, "beat": "2" }, { "time": 23019, "beat": "1" }, { "time": 23323, "beat": "3" }, { "time": 23627, "beat": "3" }, { "time": 23931, "beat": "2" }, { "time": 24240, "beat": "2" }, { "time": 24549, "beat": "2" }, { "time": 24869, "beat": "2" }, { "time": 25189, "beat": "3" }, { "time": 25493, "beat": "2" }, { "time": 25819, "beat": "2" }, { "time": 26133, "beat": "1" }, { "time": 26437, "beat": "2" }, { "time": 26757, "beat": "2" }, { "time": 27061, "beat": "2" }, { "time": 27365, "beat": "2" }, { "time": 27669, "beat": "3" }, { "time": 27973, "beat": "3" }, { "time": 28277, "beat": "3" }, { "time": 28581, "beat": "3" }, { "time": 28885, "beat": "3" }, { "time": 29221, "beat": "2" }, { "time": 29557, "beat": "3" }, { "time": 29861, "beat": "2" }, { "time": 30197, "beat": "2" }, { "time": 30507, "beat": "2" }, { "time": 30827, "beat": "2" }, { "time": 31141, "beat": "2" }, { "time": 31483, "beat": "2" }, { "time": 31787, "beat": "2" }, { "time": 32091, "beat": "3" }, { "time": 32395, "beat": "3" }, { "time": 32731, "beat": "1" }, { "time": 33045, "beat": "2" }, { "time": 33349, "beat": "3" }, { "time": 33653, "beat": "2" }, { "time": 33957, "beat": "3" }, { "time": 34261, "beat": "2" }, { "time": 34576, "beat": "2" }, { "time": 34901, "beat": "2" }, { "time": 35211, "beat": "3" }, { "time": 35520, "beat": "2" }, { "time": 35829, "beat": "3" }, { "time": 36149, "beat": "3" }, { "time": 36464, "beat": "2" }, { "time": 36779, "beat": "3" }, { "time": 37083, "beat": "2" }, { "time": 37403, "beat": "2" }, { "time": 37707, "beat": "2" }, { "time": 38037, "beat": "2" }, { "time": 38341, "beat": "3" }, { "time": 38661, "beat": "2" }, { "time": 38976, "beat": "1" }, { "time": 39301, "beat": "1" }, { "time": 39611, "beat": "2" }, { "time": 39941, "beat": "2" }, { "time": 40256, "beat": "1" }, { "time": 40565, "beat": "2" }, { "time": 40885, "beat": "1" }, { "time": 41189, "beat": "1" }, { "time": 41499, "beat": "1" }, { "time": 41851, "beat": "1" }, { "time": 42155, "beat": "1" }, { "time": 42459, "beat": "1" }, { "time": 42976, "beat": "1" }, { "time": 43429, "beat": "1" }, { "time": 43733, "beat": "1" }, { "time": 44043, "beat": "1" }, { "time": 44357, "beat": "2" }, { "time": 44672, "beat": "2" }, { "time": 44987, "beat": "1" }, { "time": 45312, "beat": "1" }, { "time": 45744, "beat": "1" }, { "time": 46059, "beat": "1" }, { "time": 46373, "beat": "1" }, { "time": 46683, "beat": "2" }, { "time": 46992, "beat": "2" }, { "time": 47301, "beat": "1" }, { "time": 47605, "beat": "2" }, { "time": 47920, "beat": "2" }, { "time": 48229, "beat": "1" }, { "time": 48544, "beat": "2" }, { "time": 48859, "beat": "1" }, { "time": 49168, "beat": "1" }, { "time": 49477, "beat": "2" }, { "time": 49845, "beat": "1" }, { "time": 50160, "beat": "1" }, { "time": 50496, "beat": "2" }, { "time": 50805, "beat": "1" }, { "time": 51173, "beat": "1" }, { "time": 51477, "beat": "2" }, { "time": 51792, "beat": "2" }, { "time": 52107, "beat": "2" }, { "time": 52421, "beat": "1" }, { "time": 52869, "beat": "1" }, { "time": 53189, "beat": "1" }, { "time": 53595, "beat": "1" }, { "time": 53979, "beat": "1" }, { "time": 54288, "beat": "1" }, { "time": 54597, "beat": "3" }, { "time": 54907, "beat": "2" }, { "time": 55227, "beat": "3" }, { "time": 55531, "beat": "3" }, { "time": 55851, "beat": "2" }, { "time": 56165, "beat": "3" }, { "time": 56475, "beat": "3" }, { "time": 56789, "beat": "2" }, { "time": 57104, "beat": "2" }, { "time": 57408, "beat": "1" }, { "time": 57728, "beat": "3" }, { "time": 58053, "beat": "2" }, { "time": 58363, "beat": "1" }, { "time": 58667, "beat": "3" }, { "time": 58976, "beat": "3" }, { "time": 59307, "beat": "1" }, { "time": 59621, "beat": "3" }, { "time": 59947, "beat": "3" }, { "time": 60304, "beat": "2" }, { "time": 60608, "beat": "3" }, { "time": 60971, "beat": "1" }, { "time": 61339, "beat": "2" }, { "time": 61701, "beat": "1" }, { "time": 62032, "beat": "1" }, { "time": 62336, "beat": "3" }, { "time": 62640, "beat": "3" }, { "time": 62955, "beat": "3" }, { "time": 63269, "beat": "3" }, { "time": 63584, "beat": "2" }, { "time": 63904, "beat": "3" }, { "time": 64213, "beat": "3" }, { "time": 64555, "beat": "2" }, { "time": 64864, "beat": "3" }, { "time": 65179, "beat": "2" }, { "time": 65499, "beat": "2" }, { "time": 65824, "beat": "3" }, { "time": 66144, "beat": "2" }, { "time": 66464, "beat": "2" }, { "time": 66768, "beat": "3" }, { "time": 67093, "beat": "1" }, { "time": 67403, "beat": "3" }, { "time": 67707, "beat": "3" }, { "time": 68053, "beat": "2" }, { "time": 68368, "beat": "2" }, { "time": 68709, "beat": "1" }, { "time": 69024, "beat": "1" }, { "time": 69333, "beat": "2" }, { "time": 69648, "beat": "3" }, { "time": 69968, "beat": "2" }, { "time": 70283, "beat": "2" }, { "time": 70587, "beat": "3" }, { "time": 70896, "beat": "3" }, { "time": 71205, "beat": "3" }, { "time": 71525, "beat": "3" }, { "time": 71835, "beat": "3" }, { "time": 72139, "beat": "3" }, { "time": 72448, "beat": "3" }, { "time": 72779, "beat": "3" }, { "time": 73083, "beat": "2" }, { "time": 73387, "beat": "3" }, { "time": 73691, "beat": "1" }, { "time": 74016, "beat": "3" }, { "time": 74336, "beat": "2" }, { "time": 74667, "beat": "3" }, { "time": 74987, "beat": "3" }, { "time": 75296, "beat": "1" }, { "time": 75605, "beat": "3" }, { "time": 75915, "beat": "3" }, { "time": 76224, "beat": "3" }, { "time": 76549, "beat": "3" }, { "time": 76853, "beat": "3" }, { "time": 77157, "beat": "3" }, { "time": 77461, "beat": "3" }, { "time": 77776, "beat": "1" }, { "time": 78107, "beat": "2" }, { "time": 78421, "beat": "2" }, { "time": 78731, "beat": "2" }, { "time": 79045, "beat": "2" }, { "time": 79365, "beat": "2" }, { "time": 79669, "beat": "1" }, { "time": 79995, "beat": "1" }, { "time": 80309, "beat": "1" }, { "time": 80640, "beat": "1" }, { "time": 80965, "beat": "1" }, { "time": 81296, "beat": "1" }, { "time": 81856, "beat": "1" }, { "time": 82165, "beat": "2" }, { "time": 82491, "beat": "2" }, { "time": 82827, "beat": "2" }, { "time": 83136, "beat": "2" }, { "time": 83451, "beat": "2" }, { "time": 83765, "beat": "1" }, { "time": 84080, "beat": "1" }, { "time": 84389, "beat": "1" }, { "time": 84704, "beat": "1" }, { "time": 85040, "beat": "1" }, { "time": 85392, "beat": "2" }, { "time": 85696, "beat": "1" }, { "time": 86016, "beat": "1" }, { "time": 86325, "beat": "1" }, { "time": 86688, "beat": "1" }, { "time": 87019, "beat": "2" }, { "time": 87323, "beat": "2" }, { "time": 87643, "beat": "1" }, { "time": 87947, "beat": "1" }, { "time": 88272, "beat": "1" }, { "time": 88587, "beat": "1" }, { "time": 88901, "beat": "1" }, { "time": 89216, "beat": "1" }, { "time": 89520, "beat": "1" }, { "time": 89872, "beat": "1" }, { "time": 90176, "beat": "2" }, { "time": 90485, "beat": "2" }, { "time": 90800, "beat": "2" }, { "time": 91115, "beat": "1" }, { "time": 91424, "beat": "1" }, { "time": 91819, "beat": "1" }, { "time": 92304, "beat": "1" }, { "time": 92667, "beat": "1" }, { "time": 92992, "beat": "2" }, { "time": 93301, "beat": "3" }, { "time": 93659, "beat": "1" }, { "time": 93968, "beat": "3" }, { "time": 94272, "beat": "3" }, { "time": 94581, "beat": "2" }, { "time": 94885, "beat": "3" }, { "time": 95205, "beat": "3" }, { "time": 95525, "beat": "2" }, { "time": 95845, "beat": "3" }, { "time": 96155, "beat": "1" }, { "time": 96485, "beat": "2" }, { "time": 96811, "beat": "3" }, { "time": 97125, "beat": "3" }, { "time": 97451, "beat": "2" }, { "time": 97755, "beat": "3" }, { "time": 98069, "beat": "3" }, { "time": 98411, "beat": "2" }, { "time": 98725, "beat": "3" }, { "time": 99035, "beat": "3" }, { "time": 99349, "beat": "3" }, { "time": 99680, "beat": "1" }, { "time": 100000, "beat": "2" }, { "time": 100304, "beat": "3" }, { "time": 100624, "beat": "3" }, { "time": 100928, "beat": "3" }, { "time": 101232, "beat": "3" }, { "time": 101557, "beat": "3" }, { "time": 101888, "beat": "2" }, { "time": 102192, "beat": "3" }, { "time": 102507, "beat": "3" }, { "time": 102853, "beat": "3" }, { "time": 103157, "beat": "3" }, { "time": 103461, "beat": "3" }, { "time": 103765, "beat": "2" }, { "time": 104085, "beat": "1" }, { "time": 104395, "beat": "1" }, { "time": 104709, "beat": "2" }, { "time": 105013, "beat": "3" }, { "time": 105317, "beat": "2" }, { "time": 105627, "beat": "1" }, { "time": 105931, "beat": "3" }, { "time": 106240, "beat": "2" }, { "time": 106555, "beat": "3" }, { "time": 106864, "beat": "3" }, { "time": 107168, "beat": "3" }, { "time": 107472, "beat": "1" }, { "time": 107781, "beat": "2" }, { "time": 108091, "beat": "3" }, { "time": 108416, "beat": "2" }, { "time": 108731, "beat": "2" }, { "time": 109045, "beat": "2" }, { "time": 109349, "beat": "3" }, { "time": 109669, "beat": "2" }, { "time": 109979, "beat": "2" }, { "time": 110293, "beat": "3" }, { "time": 110597, "beat": "3" }, { "time": 110917, "beat": "3" }, { "time": 111221, "beat": "3" }, { "time": 111525, "beat": "3" }, { "time": 111840, "beat": "2" }, { "time": 112144, "beat": "3" }, { "time": 112459, "beat": "3" }, { "time": 112773, "beat": "3" }, { "time": 113093, "beat": "3" }, { "time": 113419, "beat": "3" }, { "time": 113723, "beat": "3" }, { "time": 114032, "beat": "2" }, { "time": 114336, "beat": "2" }, { "time": 114651, "beat": "3" }, { "time": 114965, "beat": "1" }, { "time": 115280, "beat": "2" }, { "time": 115584, "beat": "3" }, { "time": 115888, "beat": "3" }, { "time": 116208, "beat": "2" }, { "time": 116523, "beat": "3" }, { "time": 116837, "beat": "2" }, { "time": 117147, "beat": "3" }, { "time": 117451, "beat": "3" }, { "time": 117787, "beat": "3" }, { "time": 118101, "beat": "3" }, { "time": 118405, "beat": "3" }, { "time": 118741, "beat": "2" }, { "time": 119051, "beat": "2" }, { "time": 119360, "beat": "1" }, { "time": 119664, "beat": "2" }, { "time": 119973, "beat": "3" }, { "time": 120283, "beat": "2" }, { "time": 120603, "beat": "3" }, { "time": 120912, "beat": "3" }, { "time": 121216, "beat": "3" }, { "time": 121525, "beat": "3" }, { "time": 121829, "beat": "3" }, { "time": 122293, "beat": "1" }, { "time": 122779, "beat": "1" }, { "time": 123099, "beat": "1" }, { "time": 123504, "beat": "1" }, { "time": 123845, "beat": "1" }, { "time": 124352, "beat": "1" }, { "time": 124699, "beat": "1" }, { "time": 125024, "beat": "1" }, { "time": 125333, "beat": "1" }, { "time": 125648, "beat": "1" }, { "time": 125979, "beat": "1" }, { "time": 126325, "beat": "1" }, { "time": 126635, "beat": "1" }, { "time": 126960, "beat": "1" }, { "time": 127275, "beat": "1" }, { "time": 127589, "beat": "1" }, { "time": 128059, "beat": "1" }, { "time": 128523, "beat": "1" }, { "time": 128837, "beat": "2" }, { "time": 129173, "beat": "1" }, { "time": 129483, "beat": "2" }, { "time": 129813, "beat": "2" }, { "time": 130133, "beat": "1" }, { "time": 130437, "beat": "1" }, { "time": 130741, "beat": "1" }, { "time": 131109, "beat": "1" }, { "time": 131413, "beat": "1" }, { "time": 131739, "beat": "2" }, { "time": 132080, "beat": "2" }, { "time": 132384, "beat": "2" }, { "time": 132784, "beat": "1" }, { "time": 133093, "beat": "1" }, { "time": 133408, "beat": "2" }, { "time": 133739, "beat": "1" }, { "time": 134069, "beat": "1" }, { "time": 134389, "beat": "1" }, { "time": 134709, "beat": "1" }, { "time": 135019, "beat": "1" }, { "time": 135355, "beat": "1" }, { "time": 135733, "beat": "1" }, { "time": 136064, "beat": "2" }, { "time": 136384, "beat": "3" }, { "time": 136693, "beat": "1" }, { "time": 137024, "beat": "2" }, { "time": 137339, "beat": "2" }, { "time": 137776, "beat": "1" }, { "time": 138261, "beat": "1" }, { "time": 138741, "beat": "1" }, { "time": 139109, "beat": "1" }, { "time": 139435, "beat": "1" }, { "time": 139744, "beat": "2" }, { "time": 140048, "beat": "2" }, { "time": 140352, "beat": "3" }, { "time": 140656, "beat": "3" }, { "time": 140987, "beat": "2" }, { "time": 141291, "beat": "3" }, { "time": 141605, "beat": "3" }, { "time": 141909, "beat": "3" }, { "time": 142251, "beat": "1" }, { "time": 142555, "beat": "1" }, { "time": 142859, "beat": "3" }, { "time": 143184, "beat": "3" }, { "time": 143504, "beat": "3" }, { "time": 143813, "beat": "2" }, { "time": 144123, "beat": "3" }, { "time": 144427, "beat": "2" }, { "time": 144741, "beat": "3" }, { "time": 145061, "beat": "3" }, { "time": 145365, "beat": "3" }, { "time": 145685, "beat": "3" }, { "time": 146000, "beat": "3" }, { "time": 146309, "beat": "2" }, { "time": 146624, "beat": "3" }, { "time": 146928, "beat": "2" }, { "time": 147237, "beat": "2" }, { "time": 147547, "beat": "3" }, { "time": 147851, "beat": "2" }, { "time": 148165, "beat": "3" }, { "time": 148480, "beat": "3" }, { "time": 148784, "beat": "2" }, { "time": 149104, "beat": "3" }, { "time": 149413, "beat": "3" }, { "time": 149717, "beat": "3" }, { "time": 150032, "beat": "2" }, { "time": 150336, "beat": "2" }, { "time": 150651, "beat": "2" }, { "time": 150971, "beat": "3" }, { "time": 151285, "beat": "2" }, { "time": 151600, "beat": "3" }, { "time": 151904, "beat": "3" }, { "time": 152208, "beat": "3" }, { "time": 152517, "beat": "3" }, { "time": 152821, "beat": "3" }, { "time": 153248, "beat": "1" }, { "time": 153728, "beat": "1" }, { "time": 154208, "beat": "1" }, { "time": 154576, "beat": "1" }] }]; var isDebug = false; var globalSpeed = 20; var currentRotationAngle = 0; var fullLog = []; var fpsText; var lastTick; var frameCount; var debugText; var worldManager; var backgroundManager; var gateManager; var targetManager; var ball; var runner; var speakerManager; var noteSparks; var minDetectionScale = 0.4; var maxDetectionScale = 0.6; var borderLimitAngle = Math.PI * 0.08; var gateLimitAngle = Math.PI * 0.2; var gateUniqueId = 0; var songStarted = false; var leftAngle = -Math.PI * 0.5 + gateLimitAngle; var centerAngle = -Math.PI * 0.5 + Math.PI / 2; var rightAngle = -Math.PI * 0.5 + Math.PI - gateLimitAngle; function getNextGateId() { return gateUniqueId++; } var lastHitSoundTime = 0; var hitSoundCooldown = 100; var skipBeatDelay = 900; var lastBeatTime = 0; function playHitSound() { var now = Date.now(); if (now - lastHitSoundTime >= hitSoundCooldown) { LK.getSound('hit').play(); lastHitSoundTime = now; } } function gameInitialize() { worldManager = new WorldManager(); game.addChild(worldManager); backgroundManager = new BackgroundManager(); game.addChild(backgroundManager); gateManager = new GateManager(); game.addChild(gateManager); speakerManager = new SpeakerManager(); game.addChild(speakerManager); noteSparks = new NoteSparks(); game.addChild(noteSparks); ball = new Ball(); ball.x = 1024; ball.y = 2000; ball.alpha = true; game.addChild(ball); runner = new Runner(); runner.x = 1024; runner.y = 2000; game.addChild(runner); if (!songStarted) { var startButton = new StartButton(); game.addChild(startButton); } if (isDebug) { var debugMarker = LK.getAsset('debugMarker', { anchorX: 0.5, anchorY: 0.5, x: 2048 * 0.5, y: 2732 / 2 }); game.addChild(debugMarker); fpsText = new Text2('FPS: 0', { size: 50, fill: 0xFFFFFF }); fpsText.anchor.set(1, 1); LK.gui.bottomRight.addChild(fpsText); lastTick = Date.now(); frameCount = 0; debugText = new Text2('Debug Info', { size: 50, fill: 0xFFFFFF }); debugText.anchor.set(0.5, 0); LK.gui.top.addChild(debugText); var soundTestButton = new Container(); var buttonBg = LK.getAsset('line', { anchorX: 0.5, anchorY: 0.5, scaleX: 50, scaleY: 15, tint: 0x333333 }); soundTestButton.addChild(buttonBg); var buttonText = new Text2('SOUND TEST', { size: 40, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); soundTestButton.addChild(buttonText); soundTestButton.x = -100; soundTestButton.y = 50; LK.gui.topRight.addChild(soundTestButton); soundTestButton.down = function () { for (var i = 0; i <= 14; i++) { (function (index) { LK.setTimeout(function () { LK.getSound('key' + index).play(); }, index * 600); })(i); } }; } } game.update = function () { if (isDebug) { var now = Date.now(); frameCount++; if (now - lastTick >= 1000) { fpsText.setText('FPS: ' + frameCount); frameCount = 0; lastTick = now; } } }; var snapPositions = { left: 0, center: 1, right: 2 }; var currentSnapPosition = snapPositions.center; var lastMouseZone = 1; function updateSnapPosition(snapPos) { currentSnapPosition = snapPos; var targetAngle = centerAngle; if (snapPos === snapPositions.left) { targetAngle = leftAngle; } else if (snapPos === snapPositions.center) { targetAngle = centerAngle; } else if (snapPos === snapPositions.right) { targetAngle = rightAngle; } var radiusX = 924; var radiusY = 634; runner.x = centerX + radiusX * Math.cos(targetAngle + Math.PI * 0.5); runner.y = centerY + radiusY * Math.sin(targetAngle + Math.PI * 0.5); var rotationMap = { 0: -0.5, 1: 0, 2: 0.5 }; currentRotationAngle = rotationMap[snapPos] * Math.PI * 0.5; } function animateToSnapPosition(snapPos, jump) { var needsIntermediateStep = false; if (currentSnapPosition === snapPositions.left && snapPos === snapPositions.right || currentSnapPosition === snapPositions.right && snapPos === snapPositions.left) { needsIntermediateStep = true; } if (needsIntermediateStep && !jump) { var radiusX = 924; var radiusY = 634; var centerPosX = centerX + radiusX * Math.cos(centerAngle + Math.PI * 0.5); var centerPosY = centerY + radiusY * Math.sin(centerAngle + Math.PI * 0.5); tween(runner, { x: centerPosX, y: centerPosY }, { duration: 100, easing: tween.easeInOut, onFinish: function onFinish() { performSnapAnimation(snapPos, jump); } }); currentRotationAngle = 0; } else { performSnapAnimation(snapPos, jump); } } function performSnapAnimation(snapPos, jump) { currentSnapPosition = snapPos; var targetAngle = centerAngle; if (snapPos === snapPositions.left) { targetAngle = rightAngle; } else if (snapPos === snapPositions.center) { targetAngle = centerAngle; } else if (snapPos === snapPositions.right) { targetAngle = leftAngle; } var radiusX = 924; var radiusY = 634; var targetX = centerX + radiusX * Math.cos(targetAngle + Math.PI * 0.5); var targetY = centerY + radiusY * Math.sin(targetAngle + Math.PI * 0.5); var rotationMap = { 0: -0.5, 1: 0, 2: 0.5 }; var targetRotation = rotationMap[snapPos] * Math.PI * 0.5; if (jump) { tween(runner, { y: 1200 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(runner, { x: targetX, y: targetY }, { duration: 200, easing: tween.easeIn }); } }); } else { tween(runner, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeInOut }); } currentRotationAngle = targetRotation; } game.down = function (x, y, obj) { if (!songStarted) { return; } var screenWidth = 2048; var thirdWidth = screenWidth / 3; var tapZone; if (x < thirdWidth) { tapZone = 0; } else if (x < thirdWidth * 2) { tapZone = 1; } else { tapZone = 2; } if (tapZone === 0) { animateToSnapPosition(snapPositions.left); } else if (tapZone === 1) { animateToSnapPosition(snapPositions.center); } else { animateToSnapPosition(snapPositions.right); } lastMouseZone = tapZone; }; game.move = function (x, y, obj) { if (!songStarted) { return; } var screenWidth = 2048; var thirdWidth = screenWidth / 3; var currentZone; if (x < thirdWidth) { currentZone = 0; } else if (x < thirdWidth * 2) { currentZone = 1; } else { currentZone = 2; } if (currentZone !== lastMouseZone) { if (currentZone === 0) { animateToSnapPosition(snapPositions.left); } else if (currentZone === 1) { animateToSnapPosition(snapPositions.center); } else { animateToSnapPosition(snapPositions.right); } lastMouseZone = currentZone; } }; game.up = function (x, y, obj) {}; gameInitialize();
===================================================================
--- original.js
+++ change.js
@@ -5,12 +5,10 @@
/****
* Classes
****/
-/***********************************************************************************/
var BackgroundManager = Container.expand(function () {
var self = Container.call(this);
- // Create three background instances for smoother tunnel effect
self.bg0 = self.attachAsset('background01', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
@@ -90,171 +88,121 @@
scaleX: 0.12,
scaleY: 0.12,
alpha: 0
});
- // Apply different tints in debug mode
if (isDebug) {
- self.bg1.tint = 0xFF0000; // Red tint for first background
- self.tore1.tint = 0x00FF00; // Green tint for first tore
- self.bg2.tint = 0x00FFFF; // Cyan tint for second background
- self.tore2.tint = 0xFF00FF; // Magenta tint for second tore
- self.bg3.tint = 0xfff200; // Yellow tint for third background
+ self.bg1.tint = 0xFF0000;
+ self.tore1.tint = 0x00FF00;
+ self.bg2.tint = 0x00FFFF;
+ self.tore2.tint = 0xFF00FF;
+ self.bg3.tint = 0xfff200;
}
- // Animation properties
- self.bgAnimationSpeed = globalSpeed / 1000; //0.002;
+ self.bgAnimationSpeed = globalSpeed / 1000;
self.bgAnimationAcceleration = 2;
- // Add tore assets between backgrounds for animation
self.backgrounds = [self.bg0, self.tore0, self.bg1, self.tore1, self.bg2, self.tore2, self.bg3, self.tore3, self.bg4];
- //self.backgrounds = [self.bg0, self.bg1, self.bg2, self.bg3];
- // Define initial scale for each background/torus (tore: 0.26, bg: 0.22)
- //self.bgInitialScales = [0.22, 0.22, 0.22, 0.22, 0.22];
- //self.bgInitialScales = [0, 0, 0, 0, 0];
- //self.bgInitialScales = [0, 0, 0, 0, 0, 0, 0, 0, 0];
- // Animation state: single startTime for all backgrounds/torus
self.bgAnimStartTime = Date.now();
- // Update method - handle background/torus scale animation
self.update = function () {
- // Don't update if song hasn't started
if (!songStarted) {
return;
}
var now = Date.now();
var elapsed = now - self.bgAnimStartTime;
var resetTriggered = false;
for (var i = 0; i < self.backgrounds.length; i++) {
var bg = self.backgrounds[i];
- // Make the scale speed increase as the scale increases (e.g. exponential or quadratic growth)
- //var scaleMultiplier = bg.scaleX * self.bgAnimationAcceleration;
- //bg.scaleX += self.bgAnimationSpeed * scaleMultiplier;
bg.scaleX += self.bgAnimationSpeed * bg.scaleX;
bg.scaleY = bg.scaleX;
if (bg.scaleX > 3.0) {
- bg.scaleX = 0.12; //self.bgInitialScales[i];
+ bg.scaleX = 0.12;
bg.scaleY = bg.scaleX;
}
- //bg.alpha = Math.min(1, bg.scaleX + 0.66);
- bg.tint = 0x1697b8; // 0x33FF33;
+ bg.tint = 0x1697b8;
}
};
return self;
});
-// Initialize the game;
-/***********************************************************************************/
-/********************************** BALL CLASS *************************************/
-/***********************************************************************************/
var Ball = Container.expand(function () {
var self = Container.call(this);
- // Create and attach ball asset
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5,
tint: currentColor,
alpha: 1
});
- // Initialize ball properties
self.speedX = 0;
self.speedY = 0;
- // Track last intersecting state for each gate
self.lastIntersectingGates = {};
- // Update method to follow runner's position
self.update = function () {
- // Don't process gates until song has started
if (!songStarted) {
return;
}
- // Make ball follow runner's exact position
if (runner) {
self.x = runner.x;
self.y = runner.y;
}
- // Check for collisions with gates
if (gateManager && gateManager.gates) {
- // Iterate backwards to avoid index shifting issues when removing gates
for (var i = gateManager.gates.length - 1; i >= 0; i--) {
var gate = gateManager.gates[i];
var gateId = gate.gateId;
- // Initialize tracking if needed
if (self.lastIntersectingGates[gateId] === undefined) {
self.lastIntersectingGates[gateId] = false;
}
- // Check intersection with bounding box instead of gate asset, but ignore if gate scale > 1.0
var currentIntersecting = gate.gateAsset.scaleX >= minDetectionScale && gate.gateAsset.scaleX <= maxDetectionScale && self.intersects(gate.boundingBox);
- // Detect transition from not intersecting to intersecting
if (!self.lastIntersectingGates[gateId] && currentIntersecting) {
- // Play hit sound
playHitSound();
- // Mark gate as being destroyed to prevent multiple triggers
if (!gate.isDestroying) {
gate.isDestroying = true;
- // Animate scale down
tween(gate, {
scaleX: 0,
scaleY: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
- // Request destruction from gate manager
gateManager.destroyGate(gate);
}
});
}
}
- // Update last intersecting state
self.lastIntersectingGates[gateId] = currentIntersecting;
}
- // No cleanup needed - gate IDs are unique and won't be reused
}
};
return self;
});
-/***********************************************************************************/
-/********************************** GATE CLASS *************************************/
-/***********************************************************************************/
var Gate = Container.expand(function () {
var self = Container.call(this);
- // Create gate asset with initial properties
self.gateAsset = self.attachAsset('gate', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 0.26,
- // Start at same scale as tore2
scaleY: 0.26,
alpha: 1,
visible: false
});
- // Store direction angle for this gate
self.directionAngle = 0;
- // Add bounding box for collision detection
self.boundingBox = self.attachAsset('boundingBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2450,
- alpha: 1 // Invisible by default
+ alpha: 1
});
/*
width: 200,
heigh: 100,
*/
- // Store the color for this gate
- self.gateColor = 0xFFFFFF; // Default white, will be set by manager
- // Store unique ID for this gate
- self.gateId = null; // Will be set by manager
- // Set the tint to match the gate color
+ self.gateColor = 0xFFFFFF;
+ self.gateId = null;
self.setColor = function (color) {
self.gateColor = color;
self.gateAsset.tint = color;
- // Show bounding box in debug mode
- //if (isDebug)
{
self.boundingBox.alpha = 0.8;
- //self.boundingBox.tint = color;
}
};
- // Update scale to match background animation
self.updateScale = function (newScale) {
/*
self.scaleX = newScale;
self.scaleY = newScale;
@@ -262,103 +210,74 @@
*/
self.gateAsset.scaleX = newScale;
self.gateAsset.scaleY = newScale;
self.gateAsset.alpha = Math.min(1, newScale + 0.66);
- // Scale bounding box proportionally
- self.boundingBox.scaleX = newScale; // 3 * newScale / 0.26; // Maintain 300px width relative to gate scale
- self.boundingBox.scaleY = newScale; //0.3 * newScale / 0.26; // Maintain 30px height relative to gate scale
- // Calculate boundingBox position using directionAngle and scale
- // Calculate distance from center based on scale
+ self.boundingBox.scaleX = newScale;
+ self.boundingBox.scaleY = newScale;
var distance = (2450 - 1366) * newScale;
- // Use directionAngle to position boundingBox
self.boundingBox.x = centerX + distance * Math.cos(self.directionAngle + Math.PI * 0.5);
self.boundingBox.y = centerY + distance * Math.sin(self.directionAngle + Math.PI * 0.5);
self.boundingBox.rotation = self.directionAngle;
};
return self;
});
-/***********************************************************************************/
-/********************************** GATE MANAGER CLASS *****************************/
-/***********************************************************************************/
var GateManager = Container.expand(function () {
var self = Container.call(this);
- // Array to hold gates
self.gates = [];
- // Animation timing
self.gateAnimStartTime = Date.now();
- self.gateAnimationSpeed = globalSpeed / 1000; // Same as background
- // Song timing properties
+ self.gateAnimationSpeed = globalSpeed / 1000;
self.currentSong = songListV3[0];
self.songStartTime = Date.now();
self.currentNoteIndex = 0;
- self.noteSpawnScale = 0.12; // Initial scale for new gates matching smallest tore
- self.lastGateAngle = null; // Track last gate angle for path continuity
- self.lastProcessedBeat = -1; // Track last processed beat for speaker synchronization
- // Spawn a single gate at current time
+ self.noteSpawnScale = 0.12;
+ self.lastGateAngle = null;
+ self.lastProcessedBeat = -1;
self.spawnGateAtTime = function () {
- // Get the current beat value
var beatValue = null;
if (self.currentNoteIndex < self.currentSong.songBeats.length) {
beatValue = self.currentSong.songBeats[self.currentNoteIndex].beat;
}
- // Map beat to key for color selection
- var keyNumber = parseInt(beatValue, 10) || 1; // Default to 1 if parse fails
+ var keyNumber = parseInt(beatValue, 10) || 1;
var noteKey = 'Key' + keyNumber;
- var keyColor = keyColorMap[noteKey] || currentColor; // Default to currentColor if key not found
- // --- Calculate gate travel time so it reaches the player at the correct beat time ---
+ var keyColor = keyColorMap[noteKey] || currentColor;
var startScale = self.noteSpawnScale;
- var endScale = 1.0; // The scale at which the gate should reach the player (runner)
- var speed = self.gateAnimationSpeed; // This is the per-tick scale growth factor
- var timeToReachPlayer = Math.log(endScale / startScale) / speed; // ms
- // Determine beat angle (where the safe path is)
+ var endScale = 1.0;
+ var speed = self.gateAnimationSpeed;
+ var timeToReachPlayer = Math.log(endScale / startScale) / speed;
var beatAngle = centerAngle;
if (beatValue === "1") {
beatAngle = rightAngle;
} else if (beatValue === "2") {
beatAngle = leftAngle;
} else {
- // Beat values 0 and 3 go to center
beatAngle = centerAngle;
}
- // Store this angle for the next gate
self.lastGateAngle = beatAngle;
- // Create array of all possible angles
var allAngles = [leftAngle, centerAngle, rightAngle];
var gateAngles = [];
- // Filter out the beat angle to get the non-beat angles
for (var i = 0; i < allAngles.length; i++) {
if (allAngles[i] !== beatAngle) {
gateAngles.push(allAngles[i]);
}
}
- // Calculate timing
var beatTime = self.currentSong.songBeats[self.currentNoteIndex].time;
var now = Date.now();
var songElapsed = now - self.songStartTime;
var spawnTime = beatTime - timeToReachPlayer;
- // Create gates at non-beat positions
for (var j = 0; j < gateAngles.length; j++) {
var gate = new Gate();
gate.setColor(keyColor);
gate.updateScale(self.noteSpawnScale);
- // Store spawn time for tracking
gate.spawnTime = Date.now() + 200 / globalSpeed;
gate.colorIndex = 0;
- // Assign unique ID to gate
gate.gateId = getNextGateId();
- // Store the note key for this gate
gate.noteKey = noteKey;
- // Set the direction angle for this gate
gate.directionAngle = gateAngles[j];
- // Apply rotation to gate asset
gate.gateAsset.rotation = gateAngles[j];
- // Spawn or schedule the gate
if (songElapsed >= spawnTime) {
- // Spawn now
self.gates.push(gate);
self.addChild(gate);
} else {
- // Schedule spawn for later
(function (g) {
LK.setTimeout(function () {
self.gates.push(g);
self.addChild(g);
@@ -366,65 +285,51 @@
})(gate);
}
}
};
- // Update gates animation
self.update = function () {
- // Don't update if song hasn't started
if (!songStarted) {
return;
}
var now = Date.now();
var songElapsed = now - self.songStartTime;
- // Check if we need to spawn a new gate based on song timing
if (self.currentNoteIndex < self.currentSong.songBeats.length) {
var nextBeat = self.currentSong.songBeats[self.currentNoteIndex];
if (songElapsed >= nextBeat.time) {
- // Check if enough time has passed since last beat
if (now - lastBeatTime >= skipBeatDelay) {
- // Spawn a new gate for this beat
self.spawnGateAtTime();
lastBeatTime = now;
}
self.currentNoteIndex++;
}
}
- // Animate existing gates
for (var i = self.gates.length - 1; i >= 0; i--) {
var gate = self.gates[i];
var currentScale = gate.gateAsset.scaleX;
- // Increase scale with acceleration
var newScale = currentScale + self.gateAnimationSpeed * currentScale;
- // Remove gate when too large
if (newScale > 3.0) {
gate.destroy();
self.gates.splice(i, 1);
} else {
gate.updateScale(newScale);
}
}
- // Check if song has ended and needs restart
self.checkSongEnd();
};
- // Reset song when it ends
self.resetSong = function () {
self.songStartTime = Date.now();
self.currentNoteIndex = 0;
- self.lastGateAngle = null; // Reset angle tracking for new song
+ self.lastGateAngle = null;
};
- // Check if song has ended and restart
self.checkSongEnd = function () {
if (self.currentNoteIndex >= self.currentSong.songBeats.length) {
- // All beats have been spawned, check if we should restart
var lastBeatTime = self.currentSong.songBeats[self.currentSong.songBeats.length - 1].time;
var songElapsed = Date.now() - self.songStartTime;
- // Wait a bit after the last beat before restarting
if (songElapsed > lastBeatTime + 5000) {
self.resetSong();
}
}
};
- // Destroy a specific gate
self.destroyGate = function (gate) {
var index = self.gates.indexOf(gate);
if (index > -1) {
self.gates.splice(index, 1);
@@ -434,72 +339,58 @@
return self;
});
var Note = Container.expand(function () {
var self = Container.call(this);
- // Create and attach note asset
var noteGraphics = self.attachAsset('note', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
});
- // Note properties
self.velocity = {
x: 0,
y: -5
- }; // Default upward movement
- self.lifetime = 500; // 1.5 seconds (reduced from 3 seconds)
+ };
+ self.lifetime = 500;
self.spawnTime = Date.now();
- self.noteType = 'note'; // Can be 'note' or 'note2'
- self.noteColor = 0xFFFFFF; // Default white
- // Set note type and appearance
+ self.noteType = 'note';
+ self.noteColor = 0xFFFFFF;
self.setNoteType = function (type) {
self.noteType = type;
- // Remove current graphics
noteGraphics.destroy();
- // Create new graphics with appropriate asset
noteGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
});
noteGraphics.tint = self.noteColor;
};
- // Set note color
self.setColor = function (color) {
self.noteColor = color;
noteGraphics.tint = color;
};
- // Set velocity
self.setVelocity = function (vx, vy) {
self.velocity.x = vx;
self.velocity.y = vy;
};
- // Update method
self.update = function () {
- // Move based on velocity
self.x += self.velocity.x;
self.y += self.velocity.y;
- // Check lifetime
var elapsed = Date.now() - self.spawnTime;
if (elapsed > self.lifetime) {
- self.alpha = Math.max(0, 1 - (elapsed - self.lifetime) / 500); // Fade out over 500ms
+ self.alpha = Math.max(0, 1 - (elapsed - self.lifetime) / 500);
}
- // Destroy if too old or out of bounds
if (elapsed > self.lifetime + 500 || self.y < -100 || self.y > 2832 || self.x < -100 || self.x > 2148) {
self.shouldDestroy = true;
}
};
return self;
});
var NoteSparks = Container.expand(function () {
var self = Container.call(this);
- // Array to track active notes
self.notes = [];
- // Spawn configuration
- self.spawnRate = 500; // Milliseconds between spawns
+ self.spawnRate = 500;
self.lastSpawnTime = 0;
self.spawnEnabled = false;
- // Default spawn properties
self.spawnX = 1024;
self.spawnY = 1366;
self.spawnVelocityRange = {
x: {
@@ -511,57 +402,43 @@
max: -4
}
};
self.noteColors = [0xFF073A, 0x39FF14, 0x00FFFF, 0xF3F315, 0xFF61F6];
- // Set spawn position
self.setSpawnPosition = function (x, y) {
self.spawnX = x;
self.spawnY = y;
};
- // Enable/disable spawning
self.setSpawnEnabled = function (enabled) {
self.spawnEnabled = enabled;
};
- // Set spawn rate
self.setSpawnRate = function (rate) {
self.spawnRate = rate;
};
- // Spawn a single note
self.spawnNote = function () {
var note = new Note();
- // Set random position around spawn point
note.x = self.spawnX + (Math.random() - 0.5) * 50;
note.y = self.spawnY;
- // Set random velocity
var vx = self.spawnVelocityRange.x.min + Math.random() * (self.spawnVelocityRange.x.max - self.spawnVelocityRange.x.min);
var vy = self.spawnVelocityRange.y.min + Math.random() * (self.spawnVelocityRange.y.max - self.spawnVelocityRange.y.min);
note.setVelocity(vx, vy);
- // Set random note type
note.setNoteType(Math.random() > 0.5 ? 'note' : 'note2');
- // Set random color
var color = self.noteColors[Math.floor(Math.random() * self.noteColors.length)];
note.setColor(color);
- // Add slight rotation
note.rotation = (Math.random() - 0.5) * 0.5;
- // Add to arrays and stage
self.notes.push(note);
self.addChild(note);
};
- // Spawn multiple notes at once (burst)
self.spawnBurst = function (count) {
for (var i = 0; i < count; i++) {
self.spawnNote();
}
};
- // Update method
self.update = function () {
var now = Date.now();
- // Spawn new notes if enabled
if (self.spawnEnabled && now - self.lastSpawnTime >= self.spawnRate) {
self.spawnNote();
self.lastSpawnTime = now;
}
- // Update and clean up notes
for (var i = self.notes.length - 1; i >= 0; i--) {
var note = self.notes[i];
if (note.shouldDestroy) {
note.destroy();
@@ -570,143 +447,111 @@
}
};
return self;
});
-/***********************************************************************************/
-/********************************** RUNNER CLASS ***********************************/
-/***********************************************************************************/
var Runner = Container.expand(function () {
var self = Container.call(this);
- // Create and attach runner asset
var runnerGraphics = self.attachAsset('runnerDir4_001', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFFFF,
- //currentColor,
alpha: 1
});
- // Initialize runner properties
self.speedX = 0;
self.speedY = 0;
- // Track last intersecting state for each gate
self.lastIntersectingGates = {};
- // Add tick counter for scale flipping
self.tickCounter = 0;
self.update = function () {
- // Don't update if song hasn't started
if (!songStarted) {
return;
}
- // Calculate angle based on runner's position relative to center
var angle = Math.atan2(self.y - centerY, self.x - centerX);
- // Apply rotation to runner
- self.rotation = angle - Math.PI * 0.5; // Add PI/2 to orient correctly
- // Increment tick counter and flip scale only every 60 ticks
+ self.rotation = angle - Math.PI * 0.5;
self.tickCounter++;
if (self.tickCounter >= 5) {
self.scaleX *= -1;
- self.tickCounter = 0; // Reset counter
+ self.tickCounter = 0;
}
};
return self;
});
var Speaker = Container.expand(function () {
var self = Container.call(this);
- // Create and attach speaker asset
var speakerGraphics = self.attachAsset('speaker', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1
});
- // Initialize speaker properties
self.volume = 1.0;
self.isPlaying = false;
- // Method to set speaker volume
self.setVolume = function (vol) {
self.volume = Math.max(0, Math.min(1, vol));
};
- // Method to toggle speaker state
self.toggleState = function () {
self.isPlaying = !self.isPlaying;
speakerGraphics.alpha = self.isPlaying ? 1.0 : 0.5;
};
return self;
});
var SpeakerManager = Container.expand(function () {
var self = Container.call(this);
- // Array to hold 3 speakers
self.speakers = [];
self.lastBeatTime = 0;
- self.beatCooldown = 200; // Minimum time between beat animations
- // Properties for tracking speakersBeat data
- self.speakerSongData = speakersBeat[0]; // Use first song from speakersBeat
+ self.beatCooldown = 200;
+ self.speakerSongData = speakersBeat[0];
self.currentBeatIndex = 0;
- self.songStartTime = 0; // Will be set when song starts
- // Initialize 3 speakers
+ self.songStartTime = 0;
self.initializeSpeakers = function () {
var speakerPositions = [{
x: 1024 - 400,
y: 512
- },
- // Left speaker
- {
+ }, {
x: 1024,
y: 512
- },
- // Center speaker
- {
+ }, {
x: 1024 + 400,
y: 512
- } // Right speaker
- ];
+ }];
for (var i = 0; i < 3; i++) {
var speaker = new Speaker();
speaker.x = speakerPositions[i].x;
speaker.y = speakerPositions[i].y;
speaker.scaleX = 0.8;
speaker.scaleY = 0.8;
- speaker.isBigBumping = false; // Track if big bump animation is running
+ speaker.isBigBumping = false;
self.speakers.push(speaker);
self.addChild(speaker);
}
};
- // Animate specific speaker based on beat value
self.onBeat = function (beatValue) {
var now = Date.now();
if (now - self.lastBeatTime >= self.beatCooldown) {
- // Determine which speaker to animate based on beat value
var speakerIndex = -1;
if (beatValue === "1") {
- speakerIndex = 0; // Left speaker
+ speakerIndex = 0;
} else if (beatValue === "2") {
- speakerIndex = 2; // Right speaker
+ speakerIndex = 2;
} else {
- speakerIndex = 1; // Center speaker for beats 0 and 3
+ speakerIndex = 1;
}
- // Animate speaker based on whether it's the main speaker for this beat
if (speakerIndex >= 0 && speakerIndex < self.speakers.length) {
var mainSpeaker = self.speakers[speakerIndex];
- // Set flag to indicate big bump is running
mainSpeaker.isBigBumping = true;
- // Spawn note sparks around the speaker
self.spawnNoteSparks(mainSpeaker);
- // Big bump for the main speaker
tween(mainSpeaker, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
- // Return to base scale (will be overridden by continuous animation)
tween(mainSpeaker, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
- // Clear flag when big bump is complete
mainSpeaker.isBigBumping = false;
}
});
}
@@ -714,89 +559,67 @@
}
self.lastBeatTime = now;
}
};
- // Update method to check for beats and add swing animation
self.update = function () {
- // Add continuous twist (rotation) and small bump (scale) animations when song is playing
if (songStarted) {
for (var i = 0; i < self.speakers.length; i++) {
var speaker = self.speakers[i];
- var time = Date.now() * 0.003; // Time scale for animations
- // Twist animation (rotation) - always apply
- var twistAngle = Math.sin(time + i * 0.5) * 0.15; // Rotation with phase offset
+ var time = Date.now() * 0.003;
+ var twistAngle = Math.sin(time + i * 0.5) * 0.15;
speaker.rotation = twistAngle;
- // Small bump animation (scale) - only apply if big bump is not running
if (!speaker.isBigBumping) {
- var scaleValue = 0.8 + Math.sin(time * 2 + i * 0.3) * 0.05; // Small scale oscillation
+ var scaleValue = 0.8 + Math.sin(time * 2 + i * 0.3) * 0.05;
speaker.scaleX = scaleValue;
speaker.scaleY = scaleValue;
}
}
}
- // Check for beat events
if (!songStarted) {
return;
}
- // Check if a new beat has occurred using speakersBeat data
var now = Date.now();
var songElapsed = now - self.songStartTime;
- // Process beats from speakersBeat data
if (self.currentBeatIndex < self.speakerSongData.songBeats.length) {
var nextBeat = self.speakerSongData.songBeats[self.currentBeatIndex];
if (songElapsed >= nextBeat.time) {
- // Trigger beat
self.onBeat(nextBeat.beat);
self.currentBeatIndex++;
}
} else {
- // Check if song has ended and needs restart
var lastBeatTime = self.speakerSongData.songBeats[self.speakerSongData.songBeats.length - 1].time;
- // Wait a bit after the last beat before restarting
if (songElapsed > lastBeatTime + 5000) {
self.songStartTime = Date.now();
self.currentBeatIndex = 0;
}
}
};
- // Method to spawn note sparks around a speaker
self.spawnNoteSparks = function (speaker) {
- // Spawn 3-5 notes around the speaker
var noteCount = 3 + Math.floor(Math.random() * 3);
for (var i = 0; i < noteCount; i++) {
var note = new Note();
- // Position notes randomly around the speaker
var angle = Math.random() * Math.PI * 2;
var distance = 50 + Math.random() * 100;
note.x = speaker.x + Math.cos(angle) * distance;
note.y = speaker.y + Math.sin(angle) * distance;
- // Set random velocity outward from speaker
var speed = 3 + Math.random() * 5;
note.setVelocity(Math.cos(angle) * speed, Math.sin(angle) * speed - 2);
- // Randomly choose note or note2
note.setNoteType(Math.random() > 0.5 ? 'note' : 'note2');
- // Use only futuristic violet and blue colors
- var futuristicColors = [0x32cbec]; //[0xe77d82, 0x48dae9, 0x0b4aa4, 0x9d2c44]; // Violet and Blue
+ var futuristicColors = [0x32cbec];
var color = futuristicColors[Math.floor(Math.random() * futuristicColors.length)];
note.setColor(color);
- // Add slight rotation
note.rotation = (Math.random() - 0.5) * 0.5;
note.scaleX = 0.5;
note.scaleY = 0.5;
- // Add to noteSparks manager if it exists
if (noteSparks) {
noteSparks.notes.push(note);
noteSparks.addChild(note);
}
}
};
- // Initialize speakers when created
self.initializeSpeakers();
return self;
});
-// Music will be started by start button
-// LK.playMusic('track_02');
-// test gate
/*
var testGate = new Gate();
var newScale = 1;
testGate.scaleX = newScale;
@@ -809,41 +632,29 @@
game.addChild(testGate);
*/
var StartButton = Container.expand(function () {
var self = Container.call(this);
- // Create button background
self.buttonBg = self.attachAsset('start', {
anchorX: 0.5,
anchorY: 0.5
});
- // Position at center of screen
self.x = centerX;
self.y = centerY;
- // Handle button press
self.down = function () {
- // Prevent multiple presses
if (songStarted) {
return;
}
- // Mark song as started
songStarted = true;
- // Start the music
LK.playMusic('track_01');
- // Reset gate manager timing
if (gateManager) {
gateManager.songStartTime = Date.now();
gateManager.currentNoteIndex = 0;
}
- // Reset speaker manager timing
if (speakerManager) {
speakerManager.songStartTime = Date.now();
speakerManager.currentBeatIndex = 0;
}
- // Enable note sparks spawning
- if (noteSparks) {
- //noteSparks.setSpawnEnabled(true);
- }
- // Fade out and remove button
+ if (noteSparks) {}
tween(self, {
alpha: 0
}, {
duration: 500,
@@ -854,217 +665,150 @@
});
};
return self;
});
-/***********************************************************************************/
-/******************************* UTILITY FUNCTIONS *********************************/
-/***********************************************************************************/
-/******************************* WORLD MANAGER CLASS *******************************/
-/***********************************************************************************/
var WorldManager = Container.expand(function () {
var self = Container.call(this);
- // Constants for calculation
- var assetWidth = 2732; // Width of 'world01' asset
- var screenWidth = 2048; // Virtual screen width
+ var assetWidth = 2732;
+ var screenWidth = 2048;
var totalContentWidth = assetWidth * 2;
- // Properties for shifting
self.x_center_view = -(totalContentWidth / 2 - screenWidth / 2);
- self.shiftAmplitude = 1024; // How many pixels to shift left/right from center view
- self.shiftDurationOneWay = 15000; // 15 seconds for one leg of the shift (very slow)
- self._isShifting = false; // Internal state to track if shifting sequence is active
- // --- Shift methods (defined first as per guidelines) ---
+ self.shiftAmplitude = 1024;
+ self.shiftDurationOneWay = 15000;
+ self._isShifting = false;
self._animateToRandomTarget = function () {
- // Check if we should continue (song playing and shifting enabled)
if (!songStarted || !self._isShifting) {
- self._isShifting = false; // Ensure flag is clear
+ self._isShifting = false;
tween.stop(self, {
x: true
- }); // Stop any x-tween on self
+ });
return;
}
var minTargetX = self.x_center_view - self.shiftAmplitude;
var maxTargetX = self.x_center_view + self.shiftAmplitude;
var randomTargetX = minTargetX + Math.random() * (maxTargetX - minTargetX);
var currentX = self.x;
var distanceToTravel = Math.abs(currentX - randomTargetX);
- // If the target is too close, re-trigger to find a new target to ensure visible movement.
- // A minimum travel distance of 50px.
if (distanceToTravel < 50) {
- LK.setTimeout(self._animateToRandomTarget, 0); // Try again asynchronously to avoid stack overflow
+ LK.setTimeout(self._animateToRandomTarget, 0);
return;
}
- // Calculate duration based on a constant speed.
- // Speed: cover a distance equal to shiftAmplitude in shiftDurationOneWay.
- var speed = self.shiftAmplitude / self.shiftDurationOneWay; // pixels per millisecond
- // Defensive check for speed
+ var speed = self.shiftAmplitude / self.shiftDurationOneWay;
if (speed <= 0) {
- speed = (self.shiftAmplitude > 0 ? self.shiftAmplitude : 1024) / 15000; // Default speed if params are weird
- if (speed <= 0) speed = 0.05; // Absolute fallback speed
+ speed = (self.shiftAmplitude > 0 ? self.shiftAmplitude : 1024) / 15000;
+ if (speed <= 0) {
+ speed = 0.05;
+ }
}
var dynamicDuration = distanceToTravel / speed;
- // Clamp duration to reasonable min/max values.
- // Min duration 500ms, max duration can be up to 2x shiftDurationOneWay (e.g., if traversing full range).
dynamicDuration = Math.max(500, Math.min(dynamicDuration, self.shiftDurationOneWay * 2));
tween(self, {
x: randomTargetX
}, {
duration: dynamicDuration,
easing: tween.easeInOut,
- // Smooth easing
- onFinish: self._animateToRandomTarget // Chain to pick a new random target
+ onFinish: self._animateToRandomTarget
});
};
self._initiateShift = function () {
- // This function is called once when shifting should start.
if (self._isShifting) {
return;
}
self._isShifting = true;
- // Start the animation by moving towards a random target.
self._animateToRandomTarget();
};
- // Update method: Called by the engine every frame
self.update = function () {
if (songStarted && !self._isShifting) {
- // Song is playing, and we are not currently in a shift sequence. Start one.
self._initiateShift();
} else if (!songStarted && self._isShifting) {
- // Song has stopped, but we were in a shift sequence. Stop it.
- self._isShifting = false; // This flag will be checked by onFinish callbacks.
+ self._isShifting = false;
tween.stop(self, {
x: true
- }); // Immediately stop any ongoing x-tween.
- // Smoothly tween back to the default centered position.
+ });
tween(self, {
x: self.x_center_view
}, {
duration: 1000,
- // 1 second to return
- easing: tween.easeOut // Use easeOut for a gentle stop
+ easing: tween.easeOut
});
}
};
- // --- Constructor Logic (runs after method definitions) ---
- // Set initial position for WorldManager itself. This affects where its children are seen.
self.x = self.x_center_view;
- self.y = 0; // WorldManager is typically at y=0.
- // Attach background assets. Their x,y are relative to WorldManager's origin.
+ self.y = 0;
self.bgLeft = self.attachAsset('world01', {
anchorX: 0.5,
anchorY: 0.5,
x: assetWidth / 2,
- // Center of bgLeft is at assetWidth/2 from WM origin
y: centerY,
- // Vertically center on game screen using global centerY
scaleX: 1.0,
- // Normal orientation
scaleY: 1.0
});
self.bgRight = self.attachAsset('world01', {
anchorX: 0.5,
anchorY: 0.5,
x: assetWidth / 2 + assetWidth,
- // Center of bgRight is next to bgLeft
y: centerY,
- // Vertically centered using global centerY
scaleX: -1.0,
- // Mirrored horizontally
scaleY: 1.0
});
return self;
});
/****
* Initialize Game
****/
-// Utility function to draw a polygon using drawLine
var game = new LK.Game({
- backgroundColor: 0x000c33 // Initialize game with a black background
+ backgroundColor: 0x000c33
});
/****
* Game Code
****/
-// Global center coordinates
var centerX = 1024;
var centerY = 1366;
-// Global array of 6 neon colors
-var neonColors = [0x39FF14,
-// Neon Green
-0xFF073A,
-// Neon Red
-0x00FFFF,
-// Neon Cyan
-0xF3F315,
-// Neon Yellow
-0xFF61F6,
-// Neon Pink
-0xFF9900 // Neon Orange
-];
-// Map keys to colors - 15 keys (0-14) mapped to neon colors
+var neonColors = [0x39FF14, 0xFF073A, 0x00FFFF, 0xF3F315, 0xFF61F6, 0xFF9900];
var keyColorMap = {
'Key0': 0x39FF14,
- // Neon Green
'Key1': 0xFF073A,
- // Neon Red
'Key2': 0x00FFFF,
- // Neon Cyan
'Key3': 0xF3F315,
- // Neon Yellow
'Key4': 0xFF61F6,
- // Neon Pink
'Key5': 0xFF9900,
- // Neon Orange
'Key6': 0x39FF14,
- // Neon Green (repeat)
'Key7': 0xFF073A,
- // Neon Red (repeat)
'Key8': 0x00FFFF,
- // Neon Cyan (repeat)
'Key9': 0xF3F315,
- // Neon Yellow (repeat)
'Key10': 0xFF61F6,
- // Neon Pink (repeat)
'Key11': 0xFF9900,
- // Neon Orange (repeat)
'Key12': 0x39FF14,
- // Neon Green (repeat)
'Key13': 0xFF073A,
- // Neon Red (repeat)
- 'Key14': 0x00FFFF // Neon Cyan (repeat)
+ 'Key14': 0x00FFFF
};
-// Global currentColor, set to a random neon color
var currentColor = neonColors[Math.floor(Math.random() * neonColors.length)];
-/***********************************************************************************/
-/******************************* UTILITY FUNCTIONS *********************************/
-/***********************************************************************************/
function drawPolygon(coordinates, tint) {
log("drawPolygon ", coordinates);
var lines = [];
for (var i = 0; i < coordinates.length; i++) {
var startPoint = coordinates[i];
- var endPoint = coordinates[(i + 1) % coordinates.length]; // Loop back to the first point
+ var endPoint = coordinates[(i + 1) % coordinates.length];
var line = drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, tint);
lines.push(line);
}
return lines;
}
function updatePolygon(lines, newCoordinates, scale) {
log("updatePolygon ", lines, scale);
- // Ensure lines and newCoordinates have the same length
if (lines.length !== newCoordinates.length) {
error("updatePolygon error: lines and newCoordinates length mismatch");
return lines;
}
- // Update each line with new coordinates
for (var i = 0; i < lines.length; i++) {
var startPoint = newCoordinates[i];
- var endPoint = newCoordinates[(i + 1) % newCoordinates.length]; // Loop back to the first point for the last line
+ var endPoint = newCoordinates[(i + 1) % newCoordinates.length];
updateLine(lines[i], startPoint.x, startPoint.y, endPoint.x, endPoint.y, scale);
}
return lines;
}
-// Utility function to draw lines between two points
function drawLine(x1, y1, x2, y2, tint) {
log("drawLine ", x1, y1);
var line = LK.getAsset('line', {
anchorX: 0.0,
@@ -1076,55 +820,40 @@
line.startX = x1;
line.startY = y1;
line.endX = x2;
line.endY = y2;
- // Calculate the distance between the two points
var distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
- // Set the width of the line to the distance between the points
line.width = distance;
- // Calculate the angle between the two points
var angle = Math.atan2(y2 - y1, x2 - x1);
- // Correct angle calculation for all quadrants
line.rotation = angle;
return line;
}
-// Utility function to draw lines between two points
function updateLine(line, newX1, newY1, newX2, newY2, scale) {
log("updateLine ", line);
scale = scale === undefined ? 1 : scale;
- // Calculate midpoint of the original line
var midX = (newX1 + newX2) / 2;
var midY = (newY1 + newY2) / 2;
- // Adjust start and end points based on scale
newX1 = midX + (newX1 - midX) * scale;
newY1 = midY + (newY1 - midY) * scale;
newX2 = midX + (newX2 - midX) * scale;
newY2 = midY + (newY2 - midY) * scale;
- // Update line start and end coordinates after scaling
line.x = newX1;
line.y = newY1;
line.startX = newX1;
line.startY = newY1;
line.endX = newX2;
line.endY = newY2;
- // Recalculate the distance between the new scaled points
var distance = Math.sqrt(Math.pow(newX2 - newX1, 2) + Math.pow(newY2 - newY1, 2));
- // Update the width of the line to the new distance
line.width = distance;
- // Recalculate the angle between the new points
var angle = Math.atan2(newY2 - newY1, newX2 - newX1);
- // Update the rotation of the line to the new angle
line.rotation = angle;
return line;
}
function log() {
if (isDebug) {
console.log(arguments);
}
}
-/***********************************************************************************/
-/******************************* GAME VARIABLES*********************************/
-/***********************************************************************************/
var songListV3 = [{
"name": "Words Fly Fast",
"songBeats": [{
"time": 651,
@@ -3116,9 +2845,8 @@
var fpsText;
var lastTick;
var frameCount;
var debugText;
-// Removed drag-related variables - using tap controls now
var worldManager;
var backgroundManager;
var gateManager;
var targetManager;
@@ -3131,19 +2859,16 @@
var borderLimitAngle = Math.PI * 0.08;
var gateLimitAngle = Math.PI * 0.2;
var gateUniqueId = 0;
var songStarted = false;
-// Define three fixed positions: left, center, right
var leftAngle = -Math.PI * 0.5 + gateLimitAngle;
var centerAngle = -Math.PI * 0.5 + Math.PI / 2;
var rightAngle = -Math.PI * 0.5 + Math.PI - gateLimitAngle;
-// Function to get next gate ID
function getNextGateId() {
return gateUniqueId++;
}
-// Function to play hit sound with protection against multiple simultaneous plays
var lastHitSoundTime = 0;
-var hitSoundCooldown = 100; // Minimum time between hit sounds in milliseconds
+var hitSoundCooldown = 100;
var skipBeatDelay = 900;
var lastBeatTime = 0;
function playHitSound() {
var now = Date.now();
@@ -3151,30 +2876,19 @@
LK.getSound('hit').play();
lastHitSoundTime = now;
}
}
-/***********************************************************************************/
-/***************************** GAME INITIALIZATION *********************************/
-/***********************************************************************************/
function gameInitialize() {
- // Initialize WorldManager for the furthest background layer (behind tunnel effect)
worldManager = new WorldManager();
game.addChild(worldManager);
- // Initialize background manager for tunnel effect
backgroundManager = new BackgroundManager();
game.addChild(backgroundManager);
- // Initialize runner at center position
- //updateSnapPosition(snapPositions.center);
- // Initialize gate manager
gateManager = new GateManager();
game.addChild(gateManager);
- // Initialize speaker manager
speakerManager = new SpeakerManager();
game.addChild(speakerManager);
- // Initialize note sparks (but don't enable spawning yet)
noteSparks = new NoteSparks();
game.addChild(noteSparks);
- // Create and position ball
ball = new Ball();
ball.x = 1024;
ball.y = 2000;
ball.alpha = true;
@@ -3182,9 +2896,8 @@
runner = new Runner();
runner.x = 1024;
runner.y = 2000;
game.addChild(runner);
- // Create start button if song hasn't started
if (!songStarted) {
var startButton = new StartButton();
game.addChild(startButton);
}
@@ -3199,21 +2912,18 @@
fpsText = new Text2('FPS: 0', {
size: 50,
fill: 0xFFFFFF
});
- // Position FPS text at the bottom-right corner
- fpsText.anchor.set(1, 1); // Anchor to the bottom-right
+ fpsText.anchor.set(1, 1);
LK.gui.bottomRight.addChild(fpsText);
- // Update FPS display every second
lastTick = Date.now();
frameCount = 0;
debugText = new Text2('Debug Info', {
size: 50,
fill: 0xFFFFFF
});
- debugText.anchor.set(0.5, 0); // Anchor to the bottom-right
+ debugText.anchor.set(0.5, 0);
LK.gui.top.addChild(debugText);
- // Create sound test button
var soundTestButton = new Container();
var buttonBg = LK.getAsset('line', {
anchorX: 0.5,
anchorY: 0.5,
@@ -3227,15 +2937,12 @@
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
soundTestButton.addChild(buttonText);
- // Position at top right
soundTestButton.x = -100;
soundTestButton.y = 50;
LK.gui.topRight.addChild(soundTestButton);
- // Add click handler
soundTestButton.down = function () {
- // Play all key sounds with 600ms delay
for (var i = 0; i <= 14; i++) {
(function (index) {
LK.setTimeout(function () {
LK.getSound('key' + index).play();
@@ -3244,134 +2951,99 @@
}
};
}
}
-/***********************************************************************************/
-/******************************** MAIN GAME LOOP ***********************************/
-/***********************************************************************************/
game.update = function () {
if (isDebug) {
- // FPS
var now = Date.now();
frameCount++;
if (now - lastTick >= 1000) {
- // Update every second
fpsText.setText('FPS: ' + frameCount);
frameCount = 0;
lastTick = now;
}
}
};
-// Define magnetic snap positions
var snapPositions = {
left: 0,
center: 1,
right: 2
};
-// Current snap position (start at center)
var currentSnapPosition = snapPositions.center;
-// Track last mouse position to detect transitions
-var lastMouseZone = 1; // Start at center zone
-// Function to update runner position based on snap
+var lastMouseZone = 1;
function updateSnapPosition(snapPos) {
currentSnapPosition = snapPos;
- // Use global angle definitions
var targetAngle = centerAngle;
if (snapPos === snapPositions.left) {
targetAngle = leftAngle;
} else if (snapPos === snapPositions.center) {
targetAngle = centerAngle;
} else if (snapPos === snapPositions.right) {
targetAngle = rightAngle;
}
- // Calculate position on the ellipse path
var radiusX = 924;
var radiusY = 634;
- // Calculate new position
runner.x = centerX + radiusX * Math.cos(targetAngle + Math.PI * 0.5);
runner.y = centerY + radiusY * Math.sin(targetAngle + Math.PI * 0.5);
- // Apply rotation based on position
var rotationMap = {
0: -0.5,
- // left
1: 0,
- // center
- 2: 0.5 // right
+ 2: 0.5
};
currentRotationAngle = rotationMap[snapPos] * Math.PI * 0.5;
}
-// Function to animate runner to new snap position
function animateToSnapPosition(snapPos, jump) {
- // Check if we need to pass through center (moving from left to right or right to left)
var needsIntermediateStep = false;
if (currentSnapPosition === snapPositions.left && snapPos === snapPositions.right || currentSnapPosition === snapPositions.right && snapPos === snapPositions.left) {
needsIntermediateStep = true;
}
- // If we need intermediate step, first move to center
if (needsIntermediateStep && !jump) {
- // Use global angle definitions
- // Calculate position on the ellipse path
var radiusX = 924;
var radiusY = 634;
- // Calculate center position (intermediate step)
var centerPosX = centerX + radiusX * Math.cos(centerAngle + Math.PI * 0.5);
var centerPosY = centerY + radiusY * Math.sin(centerAngle + Math.PI * 0.5);
- // Animate to center first
tween(runner, {
x: centerPosX,
y: centerPosY
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
- // After reaching center, continue to final destination
performSnapAnimation(snapPos, jump);
}
});
- // Update rotation for center position
currentRotationAngle = 0;
} else {
- // Direct movement (no intermediate step needed)
performSnapAnimation(snapPos, jump);
}
}
-// Helper function to perform the actual snap animation
function performSnapAnimation(snapPos, jump) {
currentSnapPosition = snapPos;
- // Use global angle definitions
var targetAngle = centerAngle;
if (snapPos === snapPositions.left) {
targetAngle = rightAngle;
} else if (snapPos === snapPositions.center) {
targetAngle = centerAngle;
} else if (snapPos === snapPositions.right) {
targetAngle = leftAngle;
}
- // Calculate position on the ellipse path
var radiusX = 924;
var radiusY = 634;
- // Calculate target position
var targetX = centerX + radiusX * Math.cos(targetAngle + Math.PI * 0.5);
var targetY = centerY + radiusY * Math.sin(targetAngle + Math.PI * 0.5);
- // Apply rotation based on position
var rotationMap = {
0: -0.5,
- // left
1: 0,
- // center
- 2: 0.5 // right
+ 2: 0.5
};
var targetRotation = rotationMap[snapPos] * Math.PI * 0.5;
- // Check if jump is requested
if (jump) {
- // Jump to y=1200 first, then return to normal position
tween(runner, {
y: 1200
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
- // After jump, animate back to target position
tween(runner, {
x: targetX,
y: targetY
}, {
@@ -3380,69 +3052,56 @@
});
}
});
} else {
- // Normal animation without jump
tween(runner, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeInOut
});
}
- // Update rotation angle for continuous rotation
currentRotationAngle = targetRotation;
}
-// Add game event handlers for runner control
game.down = function (x, y, obj) {
- // Don't process input if song hasn't started
if (!songStarted) {
return;
}
- // Divide screen into thirds
var screenWidth = 2048;
var thirdWidth = screenWidth / 3;
- // Determine which zone was tapped
var tapZone;
if (x < thirdWidth) {
- tapZone = 0; // Left third
+ tapZone = 0;
} else if (x < thirdWidth * 2) {
- tapZone = 1; // Center third
+ tapZone = 1;
} else {
- tapZone = 2; // Right third
+ tapZone = 2;
}
- // Animate to the corresponding snap position based on tap
if (tapZone === 0) {
animateToSnapPosition(snapPositions.left);
} else if (tapZone === 1) {
animateToSnapPosition(snapPositions.center);
} else {
animateToSnapPosition(snapPositions.right);
}
- // Update lastMouseZone to match the tapped zone
lastMouseZone = tapZone;
};
game.move = function (x, y, obj) {
- // Don't process input if song hasn't started
if (!songStarted) {
return;
}
- // Divide screen into thirds
var screenWidth = 2048;
var thirdWidth = screenWidth / 3;
- // Determine which zone the mouse is in
var currentZone;
if (x < thirdWidth) {
- currentZone = 0; // Left third
+ currentZone = 0;
} else if (x < thirdWidth * 2) {
- currentZone = 1; // Center third
+ currentZone = 1;
} else {
- currentZone = 2; // Right third
+ currentZone = 2;
}
- // Only update position if we've moved to a different zone
if (currentZone !== lastMouseZone) {
- // Animate to the corresponding snap position
if (currentZone === 0) {
animateToSnapPosition(snapPositions.left);
} else if (currentZone === 1) {
animateToSnapPosition(snapPositions.center);
@@ -3451,8 +3110,6 @@
}
lastMouseZone = currentZone;
}
};
-game.up = function (x, y, obj) {
- // Empty - no longer needed for mouse-based controls
-};
+game.up = function (x, y, obj) {};
gameInitialize();
\ No newline at end of file
remove background
remove background
Futuristic speaker in the shape of a white orb. Face view
white video camera icon
landscape of a furturistic world by night
a white music note
white sparkles emiting from the center. back background
clean red-violet beam from above
button in the shape of a protorealistic holographic futuristc Rectangle . Front view.
above the clouds by a bright night, no visible moon Photorealistic
White Clef de sol
A 20 nodes straight metalic lock chain. High definition. In-Game asset. 2d. High contrast. No shadows
a closed metalic padlock. No visible key hole.
white menu icon
in white