User prompt
As the mask scale grows above base scale, raise Y position very slightly to compensate.
User prompt
As the mask scale grows above base scale, raise Y position to compensate.
User prompt
As the mask scale is reduced below standard scale, lower it on the face the compensate to keep proper orientation.
User prompt
As the mask scale is reduced as the face get smaller, lower it on the face to compensate.
User prompt
Remove the scale limits from the mask and mouth animator so they can continue to shrink and grow based on face size.
User prompt
Update as needed with: // In Mask class, replace the scale tracking section: // Scale tracking variables - MADE MORE RESPONSIVE var scaleHistory = new Array(3).fill(1); // Reduced from 5 to 3 for faster response var scaleIndex = 0; var currentScale = 1; // In the update function, replace the scale section: if (facekit.leftEye && facekit.rightEye) { var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x); var newScale = eyeDistance / 280; // Reduced from 300 for more sensitivity // Update rolling average for scale smoothing scaleHistory[scaleIndex] = newScale; scaleIndex = (scaleIndex + 1) % scaleHistory.length; // Calculate average scale var avgScale = scaleHistory.reduce(function (a, b) { return a + b; }, 0) / scaleHistory.length; // Apply with MORE RESPONSIVE smoothing and WIDER range var targetScale = Math.max(0.4, Math.min(2.0, avgScale)); // Expanded from 0.7-1.3 to 0.4-2.0 currentScale = currentScale * 0.7 + targetScale * 0.3; // Increased from 0.15 to 0.3 for faster response // Apply scale to mask self.maskGraphics.scaleX = currentScale; self.maskGraphics.scaleY = currentScale; } ``` **For the MouthAnimator:** ```javascript // In MouthAnimator class, replace the scale tracking section: // Scale tracking variables - MADE MORE RESPONSIVE var scaleHistory = new Array(3).fill(1); // Reduced from 5 to 3 var scaleIndex = 0; var currentScale = 1; // In the update function, replace the scale section: if (facekit.leftEye && facekit.rightEye) { var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x); var newScale = eyeDistance / 230; // Reduced from 250 for more sensitivity scaleHistory[scaleIndex] = newScale; scaleIndex = (scaleIndex + 1) % scaleHistory.length; var avgScale = scaleHistory.reduce(function (a, b) { return a + b; }, 0) / scaleHistory.length; // WIDER range and MORE RESPONSIVE smoothing var targetScale = Math.max(0.3, Math.min(2.5, avgScale)); // Expanded from 0.6-1.4 to 0.3-2.5 currentScale = currentScale * 0.65 + targetScale * 0.35; // Increased from 0.15 to 0.35 // Apply to all visemes Object.keys(self.visemes).forEach(function (key) { self.visemes[key].scaleX = currentScale; self.visemes[key].scaleY = currentScale; }); } ``` ### **2. Add Distance-Based Scaling Enhancement** Add this additional scale factor based on overall face size: ```javascript // Add this function to both Mask and MouthAnimator classes: function calculateFaceSize() { if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) { // Calculate face height (eye to mouth distance) var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2; var faceHeight = Math.abs(facekit.mouthCenter.y - eyeMidY); // Calculate face width (eye distance) var faceWidth = Math.abs(facekit.rightEye.x - facekit.leftEye.x); // Use both dimensions for more accurate scaling return (faceWidth + faceHeight * 0.7) / 2; // Weight face width more than height } return 150; // Default size } // Then in your scale update section, replace the eyeDistance calculation: var faceSize = calculateFaceSize(); var newScale = faceSize / 200; // Adjust this divisor to fine-tune sensitivity ``` ### **3. Optimize Smoothing for Responsiveness** For even more responsive tracking, you can reduce the position smoothing as well: ```javascript // In both classes, update the smoothing factors: var smoothingFactor = 0.25; // Increased from 0.15/0.18 for faster position response // And for the scale smoothing, make it even more responsive: currentScale = currentScale * 0.6 + targetScale * 0.4; // Even more responsive ``` ### **4. Optional: Add Velocity-Based Scaling** For the most responsive experience, add velocity detection: ```javascript // Add these variables to both classes: var previousFaceSize = null; var sizeVelocity = 0; // In the update function: var currentFaceSize = calculateFaceSize(); if (previousFaceSize !== null) { sizeVelocity = (currentFaceSize - previousFaceSize) * 0.1; // Damping factor newScale += sizeVelocity; // Add velocity component } previousFaceSize = currentFaceSize; ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
Code edit (6 edits merged)
Please save this source code
User prompt
Start the first subtitles slightly sooner.
Code edit (1 edits merged)
Please save this source code
User prompt
After the song is completed, do not restart it. Stop the music.
Code edit (2 edits merged)
Please save this source code
User prompt
Update with: self.subtitleData = [ {start: 5.5, end: 7.5, text: "From the ashes of tragedy"}, {start: 10.0, end: 12.5, text: "A guardian rises"}, {start: 14.0, end: 16.0, text: "Not the hero they deserve"}, {start: 17.5, end: 19.5, text: "But the one they need"}, {start: 22.5, end: 24.5, text: "Parents fallen in an alley cold"}, {start: 25.0, end: 29.0, text: "A boy's heart turned to stone"}, {start: 33.0, end: 35.0, text: "Fortune built on others' pain"}, {start: 36.0, end: 40.0, text: "Now I claim the night as my own"}, {start: 43.5, end: 46.0, text: "Gotham calls to me in whispers dire"}, {start: 47.0, end: 51.0, text: "Criminals scatter at my arrival"}, {start: 53.5, end: 56.0, text: "The cape becomes my second skin"}, {start: 57.0, end: 62.0, text: "This mask - my true survival"}, // Chorus {start: 63.5, end: 69.0, text: "From the darkness I emerge"}, {start: 75.0, end: 79.0, text: "Justice is what I serve"}, {start: 85.5, end: 90.0, text: "When evil plagues these streets"}, {start: 90.5, end: 92.0, text: "I'll be there"}, {start: 93.5, end: 94.5, text: "I'll be there"}, {start: 96.0, end: 97.0, text: "I'm Batman"}, {start: 98.5, end: 100.0, text: "I'm Batman"}, {start: 101.5, end: 102.5, text: "I'm Batman"}, {start: 103.0, end: 105.0, text: "I'm Batman"}, // Verse 2 {start: 109.0, end: 112.5, text: "A gallery of madness I've faced"}, {start: 114.0, end: 116.5, text: "The Joker with his twisted grin"}, {start: 120.0, end: 123.8, text: "Riddler's puzzles, Penguin's schemes"}, {start: 124.0, end: 128.5, text: "Two-Face's coin, the battle within"}, {start: 130.0, end: 132.0, text: "My allies few, my burden great"}, {start: 133.0, end: 137.0, text: "The cave below, my sanctuary"}, {start: 140.5, end: 144.5, text: "Alfred's wisdom guides my path"}, {start: 145.0, end: 150.5, text: "Through this life so solitary"}, // Chorus repeat {start: 151.5, end: 157.0, text: "From the darkness I emerge"}, {start: 163.5, end: 167.5, text: "Justice is what I serve"}, {start: 173.5, end: 178.0, text: "When evil plagues these streets"}, {start: 178.5, end: 180.0, text: "I'll be there"}, {start: 181.0, end: 182.5, text: "I'll be there"}, {start: 184.0, end: 185.0, text: "I'm Batman"}, {start: 186.5, end: 188.0, text: "I'm Batman"}, {start: 189.0, end: 190.5, text: "I'm Batman"}, {start: 191.5, end: 193.0, text: "I'm Batman"}, // Outro {start: 194.0, end: 197.0, text: "Na na na na na na na na"}, {start: 197.0, end: 200.0, text: "Na na na na na na na na"}, {start: 198.0, end: 198.5, text: "Batman"}, {start: 199.0, end: 202.0, text: "Na na na na na na na na"}, {start: 202.0, end: 205.0, text: "Na na na na na na na na"}, {start: 203.0, end: 204.5, text: "Batman!"} ];
User prompt
Move the subtitle Y position up 10%
User prompt
Make the subtitles twice the size and adjust positioning to compensate.
User prompt
Update with: var SubtitleDisplay = Container.expand(function () { var self = Container.call(this); // Create text display properties self.currentText = ""; self.textDisplay = null; self.subtitleData = [ {start: 5.5, end: 7.5, text: "From the ashes of tragedy"}, {start: 10.0, end: 12.5, text: "A guardian rises"}, {start: 14.0, end: 16.0, text: "Not the hero they deserve"}, {start: 17.5, end: 19.5, text: "But the one they need"}, {start: 22.5, end: 24.5, text: "Parents fallen in an alley cold"}, {start: 25.0, end: 29.0, text: "A boy's heart turned to stone"}, {start: 33.0, end: 35.0, text: "Fortune built on others' pain"}, {start: 36.0, end: 40.0, text: "Now I claim the night as my own"}, {start: 43.5, end: 46.0, text: "Gotham calls to me in whispers dire"}, {start: 47.0, end: 51.0, text: "Criminals scatter at my arrival"}, {start: 53.5, end: 56.0, text: "The cape becomes my second skin"}, {start: 57.0, end: 62.0, text: "This mask - my true survival"}, // Add chorus sections {start: 63.5, end: 69.0, text: "From the darkness I emerge"}, {start: 75.0, end: 79.0, text: "Justice is what I serve"}, {start: 85.5, end: 90.0, text: "When evil plagues these streets"}, {start: 90.5, end: 92.0, text: "I'll be there"}, {start: 93.5, end: 94.5, text: "I'll be there"}, {start: 96.0, end: 97.0, text: "I'm Batman"}, {start: 98.5, end: 100.0, text: "I'm Batman"}, {start: 101.5, end: 102.5, text: "I'm Batman"}, {start: 103.0, end: 105.0, text: "I'm Batman"} // Continue with remaining lyrics... ]; self.songStartTime = null; self.isActive = false; self.currentSubtitleIndex = 0; // Text styling properties self.textStyle = { fontFamily: 'Arial, sans-serif', fontSize: 48, fontWeight: 'bold', color: '#FFFFFF', stroke: '#000000', strokeWidth: 3, textAlign: 'center', textBaseline: 'middle', shadowColor: '#000000', shadowBlur: 8, shadowOffsetX: 2, shadowOffsetY: 2 }; // Create text graphics using canvas text self.createTextGraphics = function(text) { if (self.textDisplay) { self.removeChild(self.textDisplay); } if (!text || text.trim() === "") { self.textDisplay = null; return; } // Create a canvas-based text display var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); // Set canvas size canvas.width = GAME_WIDTH; canvas.height = 120; // Apply text styling ctx.font = `${self.textStyle.fontWeight} ${self.textStyle.fontSize}px ${self.textStyle.fontFamily}`; ctx.textAlign = self.textStyle.textAlign; ctx.textBaseline = self.textStyle.textBaseline; // Add shadow ctx.shadowColor = self.textStyle.shadowColor; ctx.shadowBlur = self.textStyle.shadowBlur; ctx.shadowOffsetX = self.textStyle.shadowOffsetX; ctx.shadowOffsetY = self.textStyle.shadowOffsetY; // Draw stroke ctx.strokeStyle = self.textStyle.stroke; ctx.lineWidth = self.textStyle.strokeWidth; ctx.strokeText(text, canvas.width / 2, canvas.height / 2); // Draw fill ctx.fillStyle = self.textStyle.color; ctx.fillText(text, canvas.width / 2, canvas.height / 2); // Convert to texture and create sprite var texture = PIXI.Texture.from(canvas); self.textDisplay = new PIXI.Sprite(texture); self.textDisplay.anchor.set(0.5, 0.5); self.addChild(self.textDisplay); }; self.startSubtitles = function() { self.songStartTime = Date.now(); self.isActive = true; self.currentSubtitleIndex = 0; console.log("Subtitles started"); }; self.updateSubtitles = function() { if (!self.isActive || !self.songStartTime || self.subtitleData.length === 0) { return; } var currentTimeSeconds = (Date.now() - self.songStartTime) / 1000.0; var newText = ""; // Find current subtitle for (var i = self.currentSubtitleIndex; i < self.subtitleData.length; i++) { var subtitle = self.subtitleData[i]; if (currentTimeSeconds >= subtitle.start && currentTimeSeconds < subtitle.end) { newText = subtitle.text; self.currentSubtitleIndex = i; break; } if (currentTimeSeconds < subtitle.start) { break; } } // Update display if text changed if (newText !== self.currentText) { self.currentText = newText; self.createTextGraphics(newText); } }; self.setPosition = function(x, y) { self.x = x; self.y = y; }; self.update = function() { self.updateSubtitles(); }; return self; }); ``` ## Integration with Your Existing Code Add this to your game initialization in the `handleStartButtonPressed` function: ```javascript function handleStartButtonPressed() { if (isGameActive) { return; } isGameActive = true; // ... existing code ... // Create subtitle display subtitleInstance = new SubtitleDisplay(); subtitleInstance.setPosition(GAME_WIDTH / 2, GAME_HEIGHT - 150); // Position at bottom game.addChild(subtitleInstance); // ... existing mask and mouth animator code ... // Start music, lip-sync, and subtitles LK.setTimeout(function () { LK.playMusic('batmansong'); if (mouthAnimatorInstance) { mouthAnimatorInstance.startLipSync(); } if (subtitleInstance) { subtitleInstance.startSubtitles(); } }, 1200); } ``` ## Add to Game Update Loop Update your game update function: ```javascript game.update = function () { if (isGameActive) { if (mouthAnimatorInstance) { mouthAnimatorInstance.update(); } if (maskInstance) { maskInstance.update(); } if (subtitleInstance) { subtitleInstance.update(); } } }; ``` ## Add Global Variable Add this at the top with your other game state variables: ```javascript var subtitleInstance;
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var Mask = Container.expand(function () { var self = Container.call(this); // Store maskGraphics on self to access its properties like height if needed later self.maskGraphics = self.attachAsset('maskImage', { anchorX: 0.5, anchorY: 0.4 }); self.animationFinished = false; // Flag to track if the intro animation is done // Position tracking variables (from dragon example) var targetX = GAME_WIDTH / 2; var targetY = GAME_HEIGHT / 3; var smoothingFactor = 0.15; // Higher value for more responsive tracking var prevX = null; var prevY = null; // Scale tracking variables (from dragon example) var scaleHistory = new Array(5).fill(1); // Start with default scale of 1 var scaleIndex = 0; var currentScale = 1; // Rotation variables - EXACTLY from working example var targetTilt = 0; var tiltSmoothingFactor = 0.11; var tiltScaleFactor = 0.09; self.show = function (targetX, targetY, duration) { self.x = targetX; self.y = -self.maskGraphics.height / 2 - 50; tween(self, { y: targetY }, { duration: duration, easing: tween.easeOutSine, onFinish: function onFinish() { self.animationFinished = true; } }); }; // Function copied EXACTLY from working DragonHead example function calculateFaceTilt() { if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) { // Calculate midpoint between eyes var eyeMidX = (facekit.leftEye.x + facekit.rightEye.x) / 2; var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2; // Calculate angle between eye midpoint and mouth, negated to fix direction var dx = facekit.mouthCenter.x - eyeMidX; var dy = facekit.mouthCenter.y - eyeMidY; var angle = -(Math.atan2(dx, dy) * (180 / Math.PI)); // Reduced angle impact return Math.max(-15, Math.min(15, angle * 0.15)); } return 0; // Default to straight when face points aren't available } // Enhanced update method with smooth position tracking and dynamic scaling self.update = function () { if (!self.animationFinished) { return; } // Smooth position tracking (from dragon example) if (facekit.leftEye && facekit.rightEye) { // Use midpoint between eyes for X, and slightly above for Y targetX = (facekit.leftEye.x + facekit.rightEye.x) / 2; targetY = (facekit.leftEye.y + facekit.rightEye.y) / 2 - self.maskGraphics.height * 0.20 - 50; // Initialize previous positions if not set if (prevX === null) { prevX = targetX; prevY = targetY; } // Weighted average between previous and target position for smooth tracking var newX = prevX * (1 - smoothingFactor) + targetX * smoothingFactor; var newY = prevY * (1 - smoothingFactor) + targetY * smoothingFactor; self.x = newX; self.y = newY; // Update previous positions prevX = newX; prevY = newY; } // Dynamic scale adjustment based on face size (from dragon example) if (facekit.leftEye && facekit.rightEye) { var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x); var newScale = eyeDistance / 300; // Adjust divisor for mask size // Update rolling average for scale smoothing scaleHistory[scaleIndex] = newScale; scaleIndex = (scaleIndex + 1) % scaleHistory.length; // Calculate average scale var avgScale = scaleHistory.reduce(function (a, b) { return a + b; }, 0) / scaleHistory.length; // Apply with gentle smoothing (limited range) var targetScale = Math.max(0.7, Math.min(1.3, avgScale)); currentScale = currentScale * 0.85 + targetScale * 0.15; // Apply scale to mask self.maskGraphics.scaleX = currentScale; self.maskGraphics.scaleY = currentScale; } // Rotation tracking - COPIED EXACTLY from working example if (facekit.leftEye && facekit.rightEye) { targetTilt = calculateFaceTilt() * tiltScaleFactor; // Limit rotation to ±15 degrees - DON'T convert to radians here targetTilt = Math.max(-15, Math.min(15, targetTilt)); self.rotation += (targetTilt - self.rotation) * tiltSmoothingFactor; } }; return self; }); var MouthAnimator = Container.expand(function () { var self = Container.call(this); // Load all viseme assets (keeping your existing setup) self.visemes = { closed: self.attachAsset('visemeClosed', { anchorX: 0.5, anchorY: 0.5, visible: false }), AEI: self.attachAsset('visemeAEI', { anchorX: 0.5, anchorY: 0.5, visible: false }), BMP: self.attachAsset('visemeBMP', { anchorX: 0.5, anchorY: 0.5, visible: false }), CDGKNRSTXYZ: self.attachAsset('visemeCDGKNRSTXYZ', { anchorX: 0.5, anchorY: 0.5, visible: false }), CHJSH: self.attachAsset('visemeCHJSH', { anchorX: 0.5, anchorY: 0.5, visible: false }), EE: self.attachAsset('visemeEE', { anchorX: 0.5, anchorY: 0.5, visible: false }), FV: self.attachAsset('visemeFV', { anchorX: 0.5, anchorY: 0.5, visible: false }), L: self.attachAsset('visemeL', { anchorX: 0.5, anchorY: 0.5, visible: false }), N: self.attachAsset('visemeN', { anchorX: 0.5, anchorY: 0.5, visible: false }), O: self.attachAsset('visemeO', { anchorX: 0.5, anchorY: 0.5, visible: false }), TH: self.attachAsset('visemeTH', { anchorX: 0.5, anchorY: 0.5, visible: false }), U: self.attachAsset('visemeU', { anchorX: 0.5, anchorY: 0.5, visible: false }), QW: self.attachAsset('visimeQW', { anchorX: 0.5, anchorY: 0.5, visible: false }) }; self.currentViseme = 'closed'; self.visemes.closed.visible = true; // Automated lip sync data (converted from your JSON) self.automatedLipSync = [{ start: 0.00, end: 5.03, value: "X" }, { start: 5.03, end: 5.16, value: "F" }, // "Fr" - changed B to F { start: 5.16, end: 5.23, value: "O" }, // "o" - changed E to O { start: 5.23, end: 5.30, value: "B" }, // "m" - changed F to B (BMP) { start: 5.30, end: 5.40, value: "C" }, // "th" - A to C { start: 5.40, end: 5.54, value: "E" }, // "e" - C to E { start: 5.54, end: 5.61, value: "A" }, // "a" - B to A { start: 5.61, end: 5.82, value: "C" }, // "sh" - keep C { start: 5.82, end: 5.96, value: "A" }, // "e" - B to A { start: 5.96, end: 6.03, value: "C" }, // "s" - keep C { start: 6.03, end: 6.31, value: "O" }, // "o" - B to O { start: 6.31, end: 6.52, value: "F" }, // "f" - keep F { start: 6.52, end: 6.73, value: "C" }, // "tr" - E to C { start: 6.73, end: 7.43, value: "A" }, // "agedy" - B to A { start: 7.43, end: 9.85, value: "X" }, { start: 9.85, end: 10.03, value: "A" }, // "A" - E to A { start: 10.03, end: 10.24, value: "C" }, // "g" - keep C { start: 10.24, end: 10.38, value: "A" }, // "ar" - E to A { start: 10.38, end: 10.52, value: "C" }, // "d" - F to C { start: 10.52, end: 10.59, value: "A" }, // "i" - D to A { start: 10.59, end: 11.15, value: "A" }, // "an" - C to A { start: 11.15, end: 11.23, value: "C" }, // "r" - A to C { start: 11.23, end: 11.54, value: "A" }, // "i" - D to A { start: 11.54, end: 11.62, value: "C" }, // "s" - keep C { start: 11.62, end: 12.77, value: "A" }, // "es" - B to A { start: 12.77, end: 13.77, value: "X" }, { start: 13.77, end: 13.83, value: "N" }, // "N" - C to N { start: 13.83, end: 14.44, value: "O" }, // "ot" - F to O { start: 14.44, end: 14.79, value: "C" }, // "th" - E to C { start: 14.79, end: 15.01, value: "E" }, // "e" - F to E { start: 15.01, end: 15.09, value: "E" }, // "he" - A to E { start: 15.09, end: 15.13, value: "C" }, // "r" - B to C { start: 15.13, end: 15.38, value: "O" }, // "o" - F to O { start: 15.38, end: 15.45, value: "C" }, // "th" - B to C { start: 15.45, end: 16.08, value: "A" }, // "ey" - E to A { start: 16.08, end: 16.29, value: "C" }, // "deserve" - B to C { start: 16.29, end: 17.16, value: "X" }, { start: 17.16, end: 17.23, value: "B" }, // "B" - C to B { start: 17.23, end: 17.29, value: "U" }, // "u" - B to U { start: 17.29, end: 17.99, value: "C" }, // "t the" - H to C { start: 17.99, end: 19.53, value: "U" }, // "one they need" - B to U { start: 19.53, end: 19.86, value: "X" }, { start: 19.86, end: 20.09, value: "E" }, // "e" - B to E { start: 20.09, end: 22.08, value: "X" }, { start: 22.08, end: 22.42, value: "B" }, // "P" - E to B (BMP) { start: 22.42, end: 22.77, value: "A" }, // "ar" - B to A { start: 22.77, end: 22.85, value: "A" }, // "e" - keep A { start: 22.85, end: 23.02, value: "N" }, // "n" - E to N { start: 23.02, end: 23.30, value: "C" }, // "ts" - B to C { start: 23.30, end: 23.65, value: "F" }, // "f" - C to F { start: 23.65, end: 23.86, value: "A" }, // "a" - B to A { start: 23.86, end: 24.49, value: "L" }, // "ll" - F to L { start: 24.49, end: 24.91, value: "A" }, // "en" - B to A { start: 24.91, end: 24.98, value: "N" }, // "n" - E to N { start: 24.98, end: 25.05, value: "A" }, // "a" - keep A { start: 25.05, end: 25.33, value: "N" }, // "n" - E to N { start: 25.33, end: 25.75, value: "A" }, // "a" - B to A { start: 25.75, end: 25.82, value: "L" }, // "l" - D to L { start: 25.82, end: 25.96, value: "L" }, // "l" - B to L { start: 25.96, end: 26.17, value: "E" }, // "ey" - F to E { start: 26.17, end: 26.45, value: "C" }, // "c" - E to C { start: 26.45, end: 27.08, value: "O" }, // "o" - B to O { start: 27.08, end: 27.43, value: "L" }, // "l" - E to L { start: 27.43, end: 27.57, value: "C" }, // "d" - F to C { start: 27.57, end: 27.71, value: "C" }, // keep C { start: 27.71, end: 28.48, value: "B" }, // B stays { start: 28.48, end: 32.70, value: "X" }, { start: 32.70, end: 32.82, value: "A" }, // "A" - B to A { start: 32.82, end: 33.03, value: "B" }, // "boy" - E to B { start: 33.03, end: 33.45, value: "O" }, // "oy" - B to O { start: 33.45, end: 33.66, value: "C" }, // "s" - E to C { start: 33.66, end: 33.73, value: "C" }, // "h" - F to C { start: 33.73, end: 33.87, value: "A" }, // "ar" - B to A { start: 33.87, end: 34.01, value: "C" }, // "t" - E to C { start: 34.01, end: 34.29, value: "C" }, // keep C { start: 34.29, end: 34.36, value: "U" }, // "ur" - B to U { start: 34.36, end: 34.50, value: "N" }, // "n" - E to N { start: 34.50, end: 34.71, value: "C" }, // "d" - B to C { start: 34.71, end: 34.85, value: "C" }, // "t" - E to C { start: 34.85, end: 35.13, value: "U" }, // "o" - C to U { start: 35.13, end: 35.20, value: "C" }, // "st" - F to C { start: 35.20, end: 35.48, value: "O" }, // "o" - B to O { start: 35.48, end: 35.55, value: "N" }, // "n" - C to N { start: 35.55, end: 35.76, value: "E" }, // "e" - keep E { start: 35.76, end: 35.90, value: "F" }, // keep F { start: 35.90, end: 36.60, value: "N" }, // "Now" - B to N { start: 36.60, end: 36.71, value: "A" }, // "I" - keep A { start: 36.71, end: 36.89, value: "C" }, // "cl" - D to C { start: 36.89, end: 36.94, value: "A" }, // "ai" - C to A { start: 36.94, end: 37.47, value: "B" }, // "m" - keep B { start: 37.47, end: 37.55, value: "C" }, // "th" - A to C { start: 37.55, end: 37.65, value: "E" }, // "e" - D to E { start: 37.65, end: 37.72, value: "N" }, // "n" - B to N { start: 37.72, end: 37.92, value: "A" }, // "ight" - F to A { start: 37.92, end: 38.00, value: "A" }, // "as" - E to A { start: 38.00, end: 40.10, value: "O" }, // "my own" - H to O { start: 40.10, end: 43.42, value: "X" }, // Continue with the rest, keeping ALL original timing and X placements... // I'll just show the pattern - every entry needs the same treatment { start: 43.42, end: 43.67, value: "C" }, // "G" - B to C { start: 43.67, end: 43.74, value: "O" }, // "o" - G to O { start: 43.74, end: 43.88, value: "C" }, // "th" - F to C { start: 43.88, end: 44.23, value: "A" }, // "am" - E to A { start: 44.23, end: 44.44, value: "C" }, // "c" - F to C { start: 44.44, end: 44.58, value: "A" }, // "a" - B to A { start: 44.58, end: 44.79, value: "L" }, // "ll" - F to L { start: 44.79, end: 45.07, value: "C" }, // "s" - B to C { start: 45.07, end: 45.35, value: "C" }, // "t" - F to C { start: 45.35, end: 45.63, value: "U" }, // "o" - E to U { start: 45.63, end: 45.70, value: "B" }, // "m" - keep B { start: 45.70, end: 46.12, value: "E" }, // "e" - keep E { start: 46.12, end: 46.40, value: "N" }, // "in" - C to N { start: 46.40, end: 46.45, value: "QW" }, // "wh" - B to QW { start: 46.45, end: 47.13, value: "C" }, // "whispers" - F to C { start: 47.13, end: 47.27, value: "C" }, // "d" - keep C { start: 47.27, end: 47.34, value: "A" }, // "ire" - B to A { start: 47.34, end: 47.55, value: "C" }, // "Cr" - E to C { start: 47.55, end: 47.76, value: "A" }, // "i" - C to A { start: 47.76, end: 47.83, value: "B" }, // "m" - keep B { start: 47.83, end: 48.04, value: "A" }, // "i" - D to A { start: 48.04, end: 48.11, value: "N" }, // "n" - B to N { start: 48.11, end: 48.81, value: "A" }, // "als" - F to A { start: 48.81, end: 48.88, value: "C" }, // "sc" - keep C { start: 48.88, end: 48.95, value: "A" }, // "a" - B to A { start: 48.95, end: 49.02, value: "C" }, // "tt" - E to C { start: 49.02, end: 50.28, value: "A" }, // "er at my" - B to A { start: 50.28, end: 50.61, value: "A" }, // "arrival" - keep A { start: 50.61, end: 53.74, value: "X" }, { start: 53.74, end: 54.23, value: "C" }, // "The c" - B to C { start: 54.23, end: 54.31, value: "A" }, // "a" - keep A { start: 54.31, end: 54.51, value: "B" }, // "pe" - keep B { start: 54.51, end: 54.79, value: "C" }, // keep C { start: 54.79, end: 54.90, value: "A" }, // keep A { start: 54.90, end: 55.01, value: "B" }, // keep B { start: 55.01, end: 55.12, value: "A" }, // keep A { start: 55.12, end: 55.18, value: "C" }, // keep C { start: 55.18, end: 55.52, value: "B" }, // keep B { start: 55.52, end: 55.59, value: "C" }, // keep C { start: 55.59, end: 55.87, value: "B" }, // keep B { start: 55.87, end: 56.22, value: "F" }, // keep F { start: 56.22, end: 56.36, value: "B" }, // keep B { start: 56.36, end: 56.66, value: "F" }, // keep F { start: 56.66, end: 56.74, value: "E" }, // keep E { start: 56.74, end: 56.89, value: "C" }, // "sk" - H to C { start: 56.89, end: 57.17, value: "C" }, // keep C { start: 57.17, end: 57.69, value: "B" }, // keep B { start: 57.69, end: 57.92, value: "C" }, // keep C { start: 57.92, end: 58.20, value: "B" }, // keep B { start: 58.20, end: 59.04, value: "C" }, // "mask" - F to C { start: 59.04, end: 59.18, value: "B" }, // "m" - keep B { start: 59.18, end: 59.39, value: "A" }, // "y" - E to A { start: 59.39, end: 59.53, value: "C" }, // "tr" - G to C { start: 59.53, end: 59.98, value: "U" }, // "ue" - D to U { start: 59.98, end: 60.06, value: "C" }, // keep C { start: 60.06, end: 60.37, value: "C" }, // "surv" - B to C { start: 60.37, end: 60.51, value: "A" }, // "iv" - G to A { start: 60.51, end: 60.65, value: "A" }, // "al" - E to A { start: 60.65, end: 62.19, value: "L" }, // "l" - H to L { start: 62.19, end: 62.33, value: "X" }, { start: 62.33, end: 62.55, value: "B" }, // keep B { start: 62.55, end: 63.24, value: "X" }, { start: 63.24, end: 63.38, value: "F" }, // "Fr" - B to F { start: 63.38, end: 63.73, value: "O" }, // "om" - E to O { start: 63.73, end: 63.87, value: "C" }, // "th" - F to C { start: 63.87, end: 63.99, value: "E" }, // "e" - A to E { start: 63.99, end: 64.11, value: "C" }, // "d" - B to C { start: 64.11, end: 64.46, value: "A" }, // "ar" - E to A { start: 64.46, end: 64.60, value: "C" }, // "k" - F to C { start: 64.60, end: 64.67, value: "N" }, // "n" - B to N { start: 64.67, end: 64.88, value: "A" }, // "e" - F to A { start: 64.88, end: 64.95, value: "C" }, // "ss" - keep C { start: 64.95, end: 65.88, value: "A" }, // "I" - B to A { start: 65.88, end: 66.43, value: "X" }, { start: 66.43, end: 66.62, value: "A" }, // "e" - D to A { start: 66.62, end: 66.81, value: "B" }, // "m" - C to B { start: 66.81, end: 66.86, value: "A" }, // "er" - E to A { start: 66.86, end: 67.11, value: "C" }, // "ge" - F to C { start: 67.11, end: 68.93, value: "E" }, // long vowel - B to E { start: 68.93, end: 69.14, value: "X" }, { start: 69.14, end: 70.99, value: "A" }, // vowel sounds - B to A { start: 70.99, end: 71.13, value: "C" }, // consonant - F to C { start: 71.13, end: 72.63, value: "A" }, // vowel - D to A { start: 72.63, end: 72.71, value: "C" }, // consonant - keep C { start: 72.71, end: 73.16, value: "E" }, // vowel - B to E { start: 73.16, end: 75.30, value: "X" }, { start: 75.30, end: 75.57, value: "C" }, // "J" - B to C { start: 75.57, end: 75.71, value: "U" }, // "u" - E to U { start: 75.71, end: 75.99, value: "C" }, // "st" - B to C { start: 75.99, end: 76.27, value: "A" }, // "i" - C to A { start: 76.27, end: 76.34, value: "C" }, // "s" - B to C { start: 76.34, end: 76.83, value: "E" }, // "e" - F to E { start: 76.83, end: 77.04, value: "A" }, // "i" - E to A { start: 77.04, end: 77.11, value: "C" }, // "s" - keep C { start: 77.11, end: 77.18, value: "QW" }, // "wh" - H to QW { start: 77.18, end: 77.37, value: "A" }, // "a" - D to A { start: 77.37, end: 77.42, value: "C" }, // "t" - keep C { start: 77.42, end: 77.81, value: "A" }, // "I" - B to A { start: 77.81, end: 79.14, value: "C" }, // "serve" - F to C { start: 79.14, end: 79.48, value: "F" }, // "v" - B to F { start: 79.48, end: 80.18, value: "E" }, // "e" - D to E { start: 80.18, end: 80.46, value: "C" }, // end consonant - keep C { start: 80.46, end: 83.12, value: "B" }, // keep B { start: 83.12, end: 84.24, value: "E" }, // keep E { start: 84.24, end: 84.45, value: "B" }, // keep B { start: 84.45, end: 85.37, value: "X" }, { start: 85.37, end: 85.55, value: "QW" }, // "Wh" - F to QW { start: 85.55, end: 86.08, value: "A" }, // "en" - B to A { start: 86.08, end: 86.62, value: "E" }, // "e" - F to E { start: 86.62, end: 86.67, value: "F" }, // "v" - C to F { start: 86.67, end: 87.00, value: "A" }, // "i" - E to A { start: 87.00, end: 87.28, value: "L" }, // "l" - F to L { start: 87.28, end: 87.42, value: "B" }, // "p" - D to B { start: 87.42, end: 87.70, value: "A" }, // "la" - C to A { start: 87.70, end: 88.54, value: "C" }, // "gues" - B to C { start: 88.54, end: 89.42, value: "E" }, // "these" - D to E { start: 89.42, end: 89.49, value: "C" }, // "s" - keep C { start: 89.49, end: 89.73, value: "C" }, // "tr" - B to C { start: 89.73, end: 90.46, value: "X" }, { start: 90.46, end: 90.81, value: "A" }, // "I'll" - E to A { start: 90.81, end: 91.27, value: "B" }, // "be" - F to B { start: 91.27, end: 91.34, value: "C" }, // "th" - E to C { start: 91.34, end: 91.41, value: "A" }, // "ere" - F to A { start: 91.41, end: 92.11, value: "E" }, // "e" - B to E { start: 92.11, end: 93.07, value: "X" }, { start: 93.07, end: 93.33, value: "A" }, // "I'll" - C to A { start: 93.33, end: 93.40, value: "L" }, // "l" - E to L { start: 93.40, end: 93.78, value: "B" }, // "be" - F to B { start: 93.78, end: 93.85, value: "C" }, // "th" - B to C { start: 93.85, end: 94.16, value: "A" }, // "ere" - D to A { start: 94.16, end: 94.24, value: "E" }, // "e" - C to E { start: 94.24, end: 95.04, value: "B" }, // keep B { start: 95.04, end: 95.79, value: "X" }, { start: 95.79, end: 95.89, value: "A" }, // "I'm" - C to A { start: 95.89, end: 95.96, value: "B" }, // "m" - keep B { start: 95.96, end: 96.05, value: "B" }, // "B" - A to B { start: 96.05, end: 96.31, value: "A" }, // "a" - C to A { start: 96.31, end: 96.49, value: "C" }, // "t" - B to C { start: 96.49, end: 97.18, value: "B" }, // "m" - D to B { start: 97.18, end: 97.26, value: "A" }, // "an" - C to A { start: 97.26, end: 98.43, value: "X" }, { start: 98.43, end: 98.54, value: "A" }, // "I'm" - E to A { start: 98.54, end: 98.61, value: "B" }, // "m" - F to B { start: 98.61, end: 98.68, value: "B" }, // "B" - C to B { start: 98.68, end: 98.75, value: "A" }, // "a" - B to A { start: 98.75, end: 98.82, value: "C" }, // "t" - F to C { start: 98.82, end: 99.10, value: "B" }, // "m" - C to B { start: 99.10, end: 99.18, value: "A" }, // "a" - keep A { start: 99.18, end: 99.64, value: "N" }, // "n" - C to N { start: 99.64, end: 99.85, value: "B" }, // keep B { start: 99.85, end: 101.13, value: "X" }, { start: 101.13, end: 101.26, value: "A" }, // "I'm" - D to A { start: 101.26, end: 101.33, value: "B" }, // "m" - keep B { start: 101.33, end: 101.45, value: "B" }, // "B" - A to B { start: 101.45, end: 101.86, value: "A" }, // "a" - B to A { start: 101.86, end: 102.38, value: "C" }, // "t" - D to C { start: 102.38, end: 102.46, value: "B" }, // "m" - C to B { start: 102.46, end: 103.19, value: "A" }, // "an" - B to A { start: 103.19, end: 103.47, value: "A" }, // "I'm" - H to A { start: 103.47, end: 104.52, value: "B" }, // "m B" - keep B { start: 104.52, end: 105.15, value: "A" }, // "a" - D to A { start: 105.15, end: 105.57, value: "C" }, // "tman" - keep C { start: 105.57, end: 108.41, value: "X" }, { start: 108.41, end: 108.56, value: "A" }, // "A" - B to A { start: 108.56, end: 108.63, value: "C" }, // "g" - D to C { start: 108.63, end: 108.84, value: "A" }, // "a" - B to A { start: 108.84, end: 108.98, value: "L" }, // "ll" - C to L { start: 108.98, end: 109.05, value: "A" }, // "e" - E to A { start: 109.05, end: 109.33, value: "C" }, // "ry" - F to C { start: 109.33, end: 109.68, value: "O" }, // "of" - B to O { start: 109.68, end: 109.82, value: "F" }, // "f" - keep F { start: 109.82, end: 109.89, value: "B" }, // "m" - C to B { start: 109.89, end: 110.03, value: "A" }, // "a" - B to A { start: 110.03, end: 110.17, value: "C" }, // "d" - keep C { start: 110.17, end: 110.24, value: "N" }, // "n" - D to N { start: 110.24, end: 110.52, value: "A" }, // "e" - B to A { start: 110.52, end: 110.59, value: "C" }, // "ss" - keep C { start: 110.59, end: 111.01, value: "A" }, // "I've" - B to A { start: 111.01, end: 111.08, value: "F" }, // "v" - C to F { start: 111.08, end: 111.57, value: "A" }, // "e" - B to A { start: 111.57, end: 111.64, value: "F" }, // "f" - C to F { start: 111.64, end: 111.99, value: "A" }, // "aced" - B to A { start: 111.99, end: 113.77, value: "X" }, { start: 113.77, end: 114.16, value: "C" }, // "The" - B to C { start: 114.16, end: 114.65, value: "C" }, // "J" - E to C { start: 114.65, end: 114.93, value: "O" }, // "o" - F to O { start: 114.93, end: 115.00, value: "C" }, // "k" - D to C { start: 115.00, end: 115.24, value: "A" }, // "er" - C to A { start: 115.24, end: 115.46, value: "QW" }, // "w" - B to QW { start: 115.46, end: 115.60, value: "A" }, // "i" - C to A { start: 115.60, end: 115.74, value: "C" }, // "th" - B to C { start: 115.74, end: 115.88, value: "A" }, // "his" - C to A { start: 115.88, end: 116.09, value: "C" }, // "tw" - B to C { start: 116.09, end: 116.17, value: "A" }, // "i" - keep A { start: 116.17, end: 116.24, value: "C" }, // "st" - E to C { start: 116.24, end: 116.73, value: "A" }, // "ed grin" - B to A { start: 116.73, end: 117.57, value: "X" }, { start: 117.57, end: 117.80, value: "B" }, // keep B { start: 117.80, end: 118.81, value: "X" }, { start: 118.81, end: 119.28, value: "C" }, // "R" - B to C { start: 119.28, end: 119.35, value: "A" }, // "i" - F to A { start: 119.35, end: 119.49, value: "C" }, // "dd" - E to C { start: 119.49, end: 119.65, value: "L" }, // "l" - A to L { start: 119.65, end: 119.88, value: "A" }, // "er's" - H to A { start: 119.88, end: 119.95, value: "B" }, // "p" - E to B { start: 119.95, end: 120.16, value: "U" }, // "u" - B to U { start: 120.16, end: 120.30, value: "C" }, // "zz" - E to C { start: 120.30, end: 120.37, value: "L" }, // "l" - B to L { start: 120.37, end: 120.65, value: "A" }, // "es" - E to A { start: 120.65, end: 120.79, value: "B" }, // "P" - F to B { start: 120.79, end: 120.93, value: "A" }, // "e" - B to A { start: 120.93, end: 121.00, value: "N" }, // "n" - C to N { start: 121.00, end: 121.28, value: "C" }, // "g" - B to C { start: 121.28, end: 121.49, value: "QW" }, // "w" - E to QW { start: 121.49, end: 121.56, value: "A" }, // "i" - F to A { start: 121.56, end: 121.70, value: "N" }, // "n's" - B to N { start: 121.70, end: 121.98, value: "C" }, // "sch" - F to C { start: 121.98, end: 122.19, value: "E" }, // "ee" - B to E { start: 122.19, end: 122.61, value: "B" }, // "m" - C to B { start: 122.61, end: 123.56, value: "C" }, // "s" - B to C { start: 123.56, end: 123.77, value: "X" }, { start: 123.77, end: 123.87, value: "C" }, // "T" - B to C { start: 123.87, end: 124.02, value: "U" }, // "wo" - A to U { start: 124.02, end: 124.16, value: "F" }, // "F" - G to F { start: 124.16, end: 124.30, value: "A" }, // "a" - C to A { start: 124.30, end: 124.72, value: "C" }, // "ce's" - B to C { start: 124.72, end: 125.00, value: "C" }, // "c" - E to C { start: 125.00, end: 125.99, value: "O" }, // "oi" - B to O { start: 125.99, end: 126.06, value: "N" }, // "n" - C to N { start: 126.06, end: 126.34, value: "C" }, // "th" - D to C { start: 126.34, end: 126.48, value: "E" }, // "e" - B to E { start: 126.48, end: 126.62, value: "B" }, // "b" - E to B { start: 126.62, end: 126.69, value: "A" }, // "a" - F to A { start: 126.69, end: 126.83, value: "C" }, // "tt" - H to C { start: 126.83, end: 128.26, value: "L" }, // "le" - B to L { start: 128.26, end: 128.43, value: "A" }, // "within" - E to A { start: 128.43, end: 129.70, value: "X" }, { start: 129.70, end: 129.85, value: "B" }, // "M" - A to B { start: 129.85, end: 129.96, value: "A" }, // "y" - D to A { start: 129.96, end: 130.03, value: "A" }, // "a" - B to A { start: 130.03, end: 130.17, value: "L" }, // "ll" - C to L { start: 130.17, end: 130.38, value: "A" }, // "ies" - B to A { start: 130.38, end: 130.52, value: "F" }, // "f" - D to F { start: 130.52, end: 130.59, value: "U" }, // "ew" - B to U { start: 130.59, end: 130.87, value: "B" }, // "m" - F to B { start: 130.87, end: 131.08, value: "A" }, // "y" - B to A { start: 131.08, end: 131.15, value: "B" }, // "b" - H to B { start: 131.15, end: 131.29, value: "U" }, // "ur" - D to U { start: 131.29, end: 131.36, value: "C" }, // "d" - keep C { start: 131.36, end: 131.50, value: "A" }, // "en" - B to A { start: 131.50, end: 131.81, value: "C" }, // "gr" - D to C { start: 131.81, end: 131.89, value: "A" }, // "ea" - E to A { start: 131.89, end: 132.20, value: "C" }, // "t" - F to C { start: 132.20, end: 132.48, value: "B" }, // keep B { start: 132.48, end: 132.62, value: "X" }, { start: 132.62, end: 132.69, value: "C" }, // "Th" - B to C { start: 132.69, end: 132.90, value: "E" }, // "e" - C to E { start: 132.90, end: 133.25, value: "C" }, // "c" - B to C { start: 133.25, end: 133.45, value: "A" }, // "a" - F to A { start: 133.45, end: 133.53, value: "F" }, // "v" - E to F { start: 133.53, end: 133.88, value: "E" }, // "e" - H to E { start: 133.88, end: 134.02, value: "B" }, // "b" - keep B { start: 134.02, end: 134.14, value: "X" }, { start: 134.14, end: 134.29, value: "L" }, // "l" - B to L { start: 134.29, end: 134.36, value: "O" }, // "o" - E to O { start: 134.36, end: 134.50, value: "QW" }, // "w" - B to QW { start: 134.50, end: 134.71, value: "B" }, // "m" - E to B { start: 134.71, end: 134.85, value: "A" }, // "y" - F to A { start: 134.85, end: 135.06, value: "C" }, // "s" - D to C { start: 135.06, end: 135.20, value: "A" }, // "a" - E to A { start: 135.20, end: 135.27, value: "N" }, // "n" - B to N { start: 135.27, end: 135.69, value: "C" }, // "ct" - keep C { start: 135.69, end: 135.83, value: "U" }, // "u" - B to U { start: 135.83, end: 136.53, value: "A" }, // "ary" - C to A { start: 136.53, end: 136.67, value: "E" }, // "y" - B to E { start: 136.67, end: 140.08, value: "X" }, { start: 140.08, end: 140.22, value: "A" }, // "Al" - D to A { start: 140.22, end: 140.29, value: "F" }, // "f" - B to F { start: 140.29, end: 140.57, value: "C" }, // "red's" - E to C { start: 140.57, end: 141.20, value: "QW" }, // "w" - F to QW { start: 141.20, end: 141.41, value: "A" }, // "is" - B to A { start: 141.41, end: 141.76, value: "C" }, // "dom" - E to C { start: 141.76, end: 142.11, value: "C" }, // "g" - F to C { start: 142.11, end: 142.18, value: "A" }, // "ui" - C to A { start: 142.18, end: 142.25, value: "C" }, // "d" - E to C { start: 142.25, end: 142.74, value: "A" }, // "es" - F to A { start: 142.74, end: 142.93, value: "B" }, // "m" - D to B { start: 142.93, end: 142.98, value: "A" }, // "y" - C to A { start: 142.98, end: 143.21, value: "B" }, // "p" - B to B { start: 143.21, end: 143.97, value: "A" }, // "ath" - D to A { start: 143.97, end: 144.11, value: "C" }, // "th" - B to C { start: 144.11, end: 144.27, value: "X" }, { start: 144.27, end: 144.40, value: "C" }, // "Thr" - B to C { start: 144.40, end: 145.11, value: "U" }, // "ough" - X to U { start: 145.11, end: 145.58, value: "C" }, // "th" - B to C { start: 145.58, end: 145.72, value: "A" }, // "is" - F to A { start: 145.72, end: 145.80, value: "L" }, // "l" - A to L { start: 145.80, end: 145.87, value: "A" }, // "i" - F to A { start: 145.87, end: 146.18, value: "F" }, // "f" - D to F { start: 146.18, end: 146.25, value: "E" }, // "e" - C to E { start: 146.25, end: 146.49, value: "C" }, // "s" - B to C { start: 146.49, end: 146.56, value: "O" }, // "o" - G to O { start: 146.56, end: 146.77, value: "C" }, // "s" - B to C { start: 146.77, end: 146.85, value: "O" }, // "o" - A to O { start: 146.85, end: 147.26, value: "L" }, // "l" - E to L { start: 147.26, end: 147.47, value: "A" }, // "i" - B to A { start: 147.47, end: 147.75, value: "C" }, // "t" - F to C { start: 147.75, end: 147.82, value: "A" }, // "a" - E to A { start: 147.82, end: 148.15, value: "C" }, // "r" - D to C { start: 148.15, end: 148.20, value: "E" }, // "y" - C to E { start: 148.20, end: 148.38, value: "B" }, // keep B { start: 148.38, end: 148.45, value: "F" }, // keep F { start: 148.45, end: 150.48, value: "E" }, // keep E { start: 150.48, end: 150.90, value: "B" }, // keep B { start: 150.90, end: 151.41, value: "X" }, { start: 151.41, end: 151.76, value: "F" }, // "Fr" - E to F { start: 151.76, end: 151.90, value: "O" }, // "o" - F to O { start: 151.90, end: 152.15, value: "B" }, // "m" - A to B { start: 152.15, end: 152.40, value: "C" }, // "th" - E to C { start: 152.40, end: 152.54, value: "E" }, // "e" - F to E { start: 152.54, end: 152.61, value: "C" }, // "d" - B to C { start: 152.61, end: 152.89, value: "A" }, // "ar" - E to A { start: 152.89, end: 153.13, value: "C" }, // "k" - F to C { start: 153.13, end: 153.19, value: "N" }, // "n" - C to N { start: 153.19, end: 153.38, value: "A" }, // "e" - E to A { start: 153.38, end: 153.45, value: "C" }, // "ss" - F to C { start: 153.45, end: 154.69, value: "A" }, // "I" - X to A { start: 154.69, end: 154.96, value: "A" }, // "e" - C to A { start: 154.96, end: 155.16, value: "B" }, // "m" - A to B { start: 155.16, end: 155.54, value: "A" }, // "er" - D to A { start: 155.54, end: 155.62, value: "C" }, // "g" - C to C { start: 155.62, end: 156.49, value: "E" }, // "e" - B to E { start: 156.49, end: 156.63, value: "E" }, // keep E { start: 156.63, end: 157.19, value: "B" }, // keep B { start: 157.19, end: 157.47, value: "E" }, // keep E { start: 157.47, end: 157.68, value: "C" }, // keep C { start: 157.68, end: 158.18, value: "B" }, // keep B { start: 158.18, end: 158.22, value: "F" }, // keep F { start: 158.22, end: 159.21, value: "B" }, // keep B { start: 159.21, end: 159.83, value: "E" }, // keep E { start: 159.83, end: 160.25, value: "F" }, // keep F { start: 160.25, end: 160.81, value: "B" }, // keep B { start: 160.81, end: 163.32, value: "X" }, { start: 163.32, end: 163.41, value: "C" }, // "J" - B to C { start: 163.41, end: 163.49, value: "U" }, // "u" - A to U { start: 163.49, end: 163.68, value: "C" }, // "st" - D to C { start: 163.68, end: 163.73, value: "A" }, // "i" - C to A { start: 163.73, end: 163.91, value: "C" }, // "s" - B to C { start: 163.91, end: 164.12, value: "E" }, // "e" - C to E { start: 164.12, end: 164.71, value: "A" }, // "i" - B to A { start: 164.71, end: 164.92, value: "C" }, // "s" - E to C { start: 164.92, end: 165.13, value: "QW" }, // "wh" - F to QW { start: 165.13, end: 165.48, value: "A" }, // "a" - D to A { start: 165.48, end: 165.62, value: "C" }, // "t" - C to C { start: 165.62, end: 165.90, value: "A" }, // "I" - B to A { start: 165.90, end: 165.97, value: "C" }, // "s" - C to C { start: 165.97, end: 167.23, value: "A" }, // "erve" - A to A { start: 167.23, end: 167.68, value: "X" }, { start: 167.68, end: 168.61, value: "A" }, // keep A { start: 168.61, end: 168.91, value: "B" }, // keep B { start: 168.91, end: 168.98, value: "C" }, // keep C { start: 168.98, end: 169.40, value: "E" }, // keep E { start: 169.40, end: 169.73, value: "F" }, // keep F { start: 169.73, end: 172.56, value: "D" }, // keep D { start: 172.56, end: 172.64, value: "C" }, // keep C { start: 172.64, end: 173.40, value: "X" }, { start: 173.40, end: 173.53, value: "QW" }, // "Wh" - F to QW { start: 173.53, end: 174.56, value: "A" }, // "en" - B to A { start: 174.56, end: 174.63, value: "E" }, // "e" - F to E { start: 174.63, end: 174.70, value: "F" }, // "v" - G to F { start: 174.70, end: 174.98, value: "A" }, // "i" - E to A { start: 174.98, end: 175.26, value: "L" }, // "l" - H to L { start: 175.26, end: 175.68, value: "B" }, // "p" - C to B { start: 175.68, end: 176.10, value: "A" }, // "la" - B to A { start: 176.10, end: 176.24, value: "C" }, // "gues" - C to C { start: 176.24, end: 176.45, value: "E" }, // "these" - B to E { start: 176.45, end: 176.52, value: "C" }, // "s" - E to C { start: 176.52, end: 177.64, value: "C" }, // "treets" - B to C { start: 177.64, end: 177.85, value: "X" }, { start: 177.85, end: 177.97, value: "B" }, // keep B { start: 177.97, end: 178.27, value: "X" }, { start: 178.27, end: 178.40, value: "A" }, // "I'll" - B to A { start: 178.40, end: 178.54, value: "L" }, // "l" - D to L { start: 178.54, end: 178.68, value: "B" }, // "be" - B to B { start: 178.68, end: 179.17, value: "C" }, // "th" - F to C { start: 179.17, end: 179.94, value: "A" }, // "ere" - B to A { start: 179.94, end: 181.13, value: "X" }, { start: 181.13, end: 181.25, value: "A" }, // "I'll" - D to A { start: 181.25, end: 181.39, value: "L" }, // "l" - B to L { start: 181.39, end: 181.94, value: "B" }, // "be" - F to B { start: 181.94, end: 182.33, value: "C" }, // "th" - D to C { start: 182.33, end: 182.41, value: "A" }, // "ere" - C to A { start: 182.41, end: 182.86, value: "E" }, // "e" - B to E { start: 182.86, end: 182.98, value: "X" }, { start: 182.98, end: 183.17, value: "B" }, // keep B { start: 183.17, end: 183.81, value: "X" }, { start: 183.81, end: 183.96, value: "A" }, // "I'm" - C to A { start: 183.96, end: 184.18, value: "B" }, // "m" - A to B { start: 184.18, end: 184.63, value: "B" }, // "B" - D to B { start: 184.63, end: 184.71, value: "A" }, // "a" - C to A { start: 184.71, end: 185.44, value: "C" }, // "tman" - B to C { start: 185.44, end: 186.32, value: "X" }, { start: 186.32, end: 186.49, value: "A" }, // "I'm" - B to A { start: 186.49, end: 186.56, value: "B" }, // "m" - C to B { start: 186.56, end: 186.63, value: "B" }, // "B" - B to B { start: 186.63, end: 186.78, value: "A" }, // "a" - A to A { start: 186.78, end: 187.00, value: "C" }, // "t" - C to C { start: 187.00, end: 188.12, value: "B" }, // "man" - B to B { start: 188.12, end: 189.10, value: "X" }, { start: 189.10, end: 189.33, value: "A" }, // "I'm" - C to A { start: 189.33, end: 189.47, value: "B" }, // "m" - B to B { start: 189.47, end: 189.66, value: "B" }, // "B" - D to B { start: 189.66, end: 189.71, value: "A" }, // "a" - C to A { start: 189.71, end: 190.80, value: "C" }, // "t" - B to C { start: 190.80, end: 191.22, value: "B" }, // "m" - D to B { start: 191.22, end: 191.46, value: "A" }, // "a" - C to A { start: 191.46, end: 191.50, value: "N" }, // "n" - H to N { start: 191.50, end: 191.54, value: "C" }, // keep C { start: 191.54, end: 192.52, value: "A" }, // "I'm" - G to A { start: 192.52, end: 192.69, value: "B" }, // "B" - A to B { start: 192.69, end: 192.83, value: "A" }, // "a" - C to A { start: 192.83, end: 193.25, value: "C" }, // "t" - B to C { start: 193.25, end: 193.50, value: "B" }, // "M" - G to B { start: 193.50, end: 193.71, value: "A" }, // "a" - E to A { start: 193.71, end: 193.82, value: "N" }, // "n" - A to N { start: 193.82, end: 194.03, value: "C" }, // "d" - D to C { start: 194.03, end: 194.09, value: "C" }, // keep C { start: 194.09, end: 195.53, value: "B" }, // keep B { start: 195.53, end: 195.77, value: "X" }, { start: 195.77, end: 195.95, value: "N" }, // "Na" - B to N { start: 195.95, end: 196.65, value: "A" }, // "a" - C to A { start: 196.65, end: 198.41, value: "N" }, // "na na na" - B to N { start: 198.41, end: 198.66, value: "B" }, // "B" - C to B { start: 198.66, end: 198.80, value: "A" }, // "a" - B to A { start: 198.80, end: 199.08, value: "C" }, // "t" - C to C { start: 199.08, end: 199.15, value: "B" }, // "m" - B to B { start: 199.15, end: 199.43, value: "A" }, // "a" - C to A { start: 199.43, end: 199.85, value: "N" }, // "n" - B to N { start: 199.85, end: 199.99, value: "C" }, // keep C { start: 199.99, end: 200.20, value: "B" }, // keep B { start: 200.20, end: 200.41, value: "G" }, // keep G { start: 200.41, end: 201.15, value: "N" }, // "Na" - B to N { start: 201.15, end: 202.25, value: "A" }, // "na na na" - D to A { start: 202.25, end: 202.33, value: "N" }, // "na" - C to N { start: 202.33, end: 203.09, value: "A" }, // "na na" - B to A { start: 203.09, end: 203.19, value: "B" }, // "B" - C to B { start: 203.19, end: 203.26, value: "A" }, // "a" - E to A { start: 203.26, end: 203.33, value: "C" }, // "t" - F to C { start: 203.33, end: 203.89, value: "B" }, // "man!" - B to B { start: 203.89, end: 206.72, value: "X" }]; // Viseme mapping self.visemeMapping = { 'X': 'closed', 'A': 'AEI', 'B': 'BMP', 'C': 'CDGKNRSTXYZ', 'D': 'AEI', 'E': 'EE', 'F': 'FV', 'G': 'CDGKNRSTXYZ', 'H': 'CHJSH' }; self.songStartTime = null; self.isLipSyncActive = false; self.currentLipSyncIndex = 0; // Position tracking variables (keeping your existing setup) var targetX = GAME_WIDTH / 2; var targetY = GAME_HEIGHT / 2 + 200; var smoothingFactor = 0.18; var prevX = null; var prevY = null; // Scale tracking variables (keeping your existing setup) var scaleHistory = new Array(5).fill(1); var scaleIndex = 0; var currentScale = 1; // Rotation variables (keeping your existing setup) var targetTilt = 0; var tiltSmoothingFactor = 0.11; var tiltScaleFactor = 0.09; function calculateFaceTilt() { if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) { var eyeMidX = (facekit.leftEye.x + facekit.rightEye.x) / 2; var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2; var dx = facekit.mouthCenter.x - eyeMidX; var dy = facekit.mouthCenter.y - eyeMidY; var angle = -(Math.atan2(dx, dy) * (180 / Math.PI)); return Math.max(-15, Math.min(15, angle * 0.15)); } return 0; } self.startLipSync = function () { self.songStartTime = Date.now(); self.isLipSyncActive = true; self.currentLipSyncIndex = 0; }; self.setViseme = function (visemeName) { if (self.currentViseme !== visemeName && self.visemes[visemeName]) { if (self.visemes[self.currentViseme]) { self.visemes[self.currentViseme].visible = false; } self.visemes[visemeName].visible = true; self.currentViseme = visemeName; } }; self.updateAutomatedLipSync = function () { if (!self.isLipSyncActive || !self.songStartTime || self.automatedLipSync.length === 0) { return; } var currentTimeSeconds = (Date.now() - self.songStartTime) / 1000.0; var targetVisemeKey = 'closed'; // Start searching from currentLipSyncIndex for optimization for (var i = self.currentLipSyncIndex; i < self.automatedLipSync.length; i++) { var cue = self.automatedLipSync[i]; if (currentTimeSeconds >= cue.start && currentTimeSeconds < cue.end) { var automatedCode = cue.value; targetVisemeKey = self.visemeMapping[automatedCode] || 'closed'; self.currentLipSyncIndex = i; break; } if (currentTimeSeconds >= cue.end) { if (i === self.automatedLipSync.length - 1) { var automatedCode = cue.value; targetVisemeKey = self.visemeMapping[automatedCode] || 'closed'; } } else if (currentTimeSeconds < cue.start) { break; } } if (self.currentLipSyncIndex === self.automatedLipSync.length - 1 && currentTimeSeconds >= self.automatedLipSync[self.automatedLipSync.length - 1].end) { targetVisemeKey = 'closed'; } self.setViseme(targetVisemeKey); }; self.update = function () { // Update automated lip sync self.updateAutomatedLipSync(); // Smooth position tracking if (facekit.mouthCenter) { targetX = facekit.mouthCenter.x; targetY = facekit.mouthCenter.y; if (prevX === null) { prevX = targetX; prevY = targetY; } var newX = prevX * (1 - smoothingFactor) + targetX * smoothingFactor; var newY = prevY * (1 - smoothingFactor) + targetY * smoothingFactor; self.x = newX; self.y = newY; prevX = newX; prevY = newY; } // Dynamic scale adjustment if (facekit.leftEye && facekit.rightEye) { var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x); var newScale = eyeDistance / 250; scaleHistory[scaleIndex] = newScale; scaleIndex = (scaleIndex + 1) % scaleHistory.length; var avgScale = scaleHistory.reduce(function (a, b) { return a + b; }, 0) / scaleHistory.length; var targetScale = Math.max(0.6, Math.min(1.4, avgScale)); currentScale = currentScale * 0.85 + targetScale * 0.15; Object.keys(self.visemes).forEach(function (key) { self.visemes[key].scaleX = currentScale; self.visemes[key].scaleY = currentScale; }); } // Rotation tracking if (facekit.leftEye && facekit.rightEye) { targetTilt = calculateFaceTilt() * tiltScaleFactor; targetTilt = Math.max(-15, Math.min(15, targetTilt)); self.rotation += (targetTilt - self.rotation) * tiltSmoothingFactor; } }; return self; }); var StartButton = Container.expand(function () { var self = Container.call(this); self.buttonGraphics = self.attachAsset('startButtonImage', { anchorX: 0.5, anchorY: 0.5 }); self.down = function () { // This will call the globally defined startGame function // when the button is pressed. if (typeof handleStartButtonPressed === 'function') { handleStartButtonPressed(); } }; return self; }); /**** * Initialize Game ****/ // Facekit provides the camera feed as background, so no explicit backgroundColor needed. var game = new LK.Game({}); /**** * Game Code ****/ // Game state variables var isGameActive = false; var startButtonInstance; var maskInstance; var mouthAnimatorInstance; // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var AUTOMATED_VISEME_MAPPING = { 'X': 'closed', // Silence/rest position 'A': 'AEI', // Open vowels (father, palm) 'B': 'BMP', // Lip closure (b, m, p) 'C': 'CDGKNRSTXYZ', // Consonants (c, d, g, k, n, r, s, t, x, y, z) 'D': 'AEI', // Mid vowels (day, face) 'E': 'EE', // High front vowels (see, fleece) 'F': 'FV', // Lip-teeth contact (f, v) 'G': 'CDGKNRSTXYZ', // Back consonants (g, ng) 'H': 'CHJSH' // Fricatives (h, ch, j, sh) }; function handleStartButtonPressed() { if (isGameActive) { return; } isGameActive = true; // Remove start button if (startButtonInstance && startButtonInstance.parent) { startButtonInstance.destroy(); startButtonInstance = null; } // Create and show mask maskInstance = new Mask(); game.addChild(maskInstance); var maskGraphicHeight = maskInstance.maskGraphics.height; var yOffset = -50; var maskTargetX, maskTargetY; if (facekit.leftEye && facekit.rightEye && facekit.leftEye.x !== 0 && facekit.rightEye.x !== 0) { maskTargetX = (facekit.leftEye.x + facekit.rightEye.x) / 2; maskTargetY = (facekit.leftEye.y + facekit.rightEye.y) / 2 - maskGraphicHeight * 0.20 + yOffset; } else { maskTargetX = GAME_WIDTH / 2; maskTargetY = GAME_HEIGHT / 3 + yOffset; } // Create mouth animator mouthAnimatorInstance = new MouthAnimator(); var mouthInitialX = facekit.mouthCenter && facekit.mouthCenter.x !== 0 ? facekit.mouthCenter.x : GAME_WIDTH / 2; var mouthInitialY = facekit.mouthCenter && facekit.mouthCenter.y !== 0 ? facekit.mouthCenter.y : GAME_HEIGHT / 2 + 200; mouthAnimatorInstance.x = mouthInitialX; mouthAnimatorInstance.y = mouthInitialY; game.addChild(mouthAnimatorInstance); // Show mask with callback to start music and lip-sync when animation completes maskInstance.show(maskTargetX, maskTargetY, 1200); // Start music and lip-sync after mask animation completes (1.2 seconds) LK.setTimeout(function () { LK.playMusic('batmansong'); if (mouthAnimatorInstance) { // Ensure mouthAnimatorInstance still exists mouthAnimatorInstance.startLipSync(); } }, 1200); } // Initial game setup function initializeGameScreen() { isGameActive = false; // Reset game state // Create and position the start button startButtonInstance = new StartButton(); // Center the button horizontally startButtonInstance.x = GAME_WIDTH / 2; // Position it towards the bottom of the screen var buttonHeight = startButtonInstance.buttonGraphics.height; startButtonInstance.y = GAME_HEIGHT - buttonHeight / 2 - 100; // 100px padding from bottom game.addChild(startButtonInstance); } // Call initial setup initializeGameScreen(); // Game update loop game.update = function () { if (isGameActive) { // Update mouth animator with enhanced tracking if (mouthAnimatorInstance) { // mouthAnimatorInstance.updateViseme(facekit.volume); // Viseme update is now handled by updateLipSync within MouthAnimator's update mouthAnimatorInstance.update(); // This now includes smooth position tracking, scaling, and lip-sync } // Update mask with enhanced tracking if (maskInstance) { maskInstance.update(); // This now includes smooth position tracking and scaling } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Mask = Container.expand(function () {
var self = Container.call(this);
// Store maskGraphics on self to access its properties like height if needed later
self.maskGraphics = self.attachAsset('maskImage', {
anchorX: 0.5,
anchorY: 0.4
});
self.animationFinished = false; // Flag to track if the intro animation is done
// Position tracking variables (from dragon example)
var targetX = GAME_WIDTH / 2;
var targetY = GAME_HEIGHT / 3;
var smoothingFactor = 0.15; // Higher value for more responsive tracking
var prevX = null;
var prevY = null;
// Scale tracking variables (from dragon example)
var scaleHistory = new Array(5).fill(1); // Start with default scale of 1
var scaleIndex = 0;
var currentScale = 1;
// Rotation variables - EXACTLY from working example
var targetTilt = 0;
var tiltSmoothingFactor = 0.11;
var tiltScaleFactor = 0.09;
self.show = function (targetX, targetY, duration) {
self.x = targetX;
self.y = -self.maskGraphics.height / 2 - 50;
tween(self, {
y: targetY
}, {
duration: duration,
easing: tween.easeOutSine,
onFinish: function onFinish() {
self.animationFinished = true;
}
});
};
// Function copied EXACTLY from working DragonHead example
function calculateFaceTilt() {
if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) {
// Calculate midpoint between eyes
var eyeMidX = (facekit.leftEye.x + facekit.rightEye.x) / 2;
var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2;
// Calculate angle between eye midpoint and mouth, negated to fix direction
var dx = facekit.mouthCenter.x - eyeMidX;
var dy = facekit.mouthCenter.y - eyeMidY;
var angle = -(Math.atan2(dx, dy) * (180 / Math.PI));
// Reduced angle impact
return Math.max(-15, Math.min(15, angle * 0.15));
}
return 0; // Default to straight when face points aren't available
}
// Enhanced update method with smooth position tracking and dynamic scaling
self.update = function () {
if (!self.animationFinished) {
return;
}
// Smooth position tracking (from dragon example)
if (facekit.leftEye && facekit.rightEye) {
// Use midpoint between eyes for X, and slightly above for Y
targetX = (facekit.leftEye.x + facekit.rightEye.x) / 2;
targetY = (facekit.leftEye.y + facekit.rightEye.y) / 2 - self.maskGraphics.height * 0.20 - 50;
// Initialize previous positions if not set
if (prevX === null) {
prevX = targetX;
prevY = targetY;
}
// Weighted average between previous and target position for smooth tracking
var newX = prevX * (1 - smoothingFactor) + targetX * smoothingFactor;
var newY = prevY * (1 - smoothingFactor) + targetY * smoothingFactor;
self.x = newX;
self.y = newY;
// Update previous positions
prevX = newX;
prevY = newY;
}
// Dynamic scale adjustment based on face size (from dragon example)
if (facekit.leftEye && facekit.rightEye) {
var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x);
var newScale = eyeDistance / 300; // Adjust divisor for mask size
// Update rolling average for scale smoothing
scaleHistory[scaleIndex] = newScale;
scaleIndex = (scaleIndex + 1) % scaleHistory.length;
// Calculate average scale
var avgScale = scaleHistory.reduce(function (a, b) {
return a + b;
}, 0) / scaleHistory.length;
// Apply with gentle smoothing (limited range)
var targetScale = Math.max(0.7, Math.min(1.3, avgScale));
currentScale = currentScale * 0.85 + targetScale * 0.15;
// Apply scale to mask
self.maskGraphics.scaleX = currentScale;
self.maskGraphics.scaleY = currentScale;
}
// Rotation tracking - COPIED EXACTLY from working example
if (facekit.leftEye && facekit.rightEye) {
targetTilt = calculateFaceTilt() * tiltScaleFactor;
// Limit rotation to ±15 degrees - DON'T convert to radians here
targetTilt = Math.max(-15, Math.min(15, targetTilt));
self.rotation += (targetTilt - self.rotation) * tiltSmoothingFactor;
}
};
return self;
});
var MouthAnimator = Container.expand(function () {
var self = Container.call(this);
// Load all viseme assets (keeping your existing setup)
self.visemes = {
closed: self.attachAsset('visemeClosed', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
AEI: self.attachAsset('visemeAEI', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
BMP: self.attachAsset('visemeBMP', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
CDGKNRSTXYZ: self.attachAsset('visemeCDGKNRSTXYZ', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
CHJSH: self.attachAsset('visemeCHJSH', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
EE: self.attachAsset('visemeEE', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
FV: self.attachAsset('visemeFV', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
L: self.attachAsset('visemeL', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
N: self.attachAsset('visemeN', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
O: self.attachAsset('visemeO', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
TH: self.attachAsset('visemeTH', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
U: self.attachAsset('visemeU', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
}),
QW: self.attachAsset('visimeQW', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
})
};
self.currentViseme = 'closed';
self.visemes.closed.visible = true;
// Automated lip sync data (converted from your JSON)
self.automatedLipSync = [{
start: 0.00,
end: 5.03,
value: "X"
}, {
start: 5.03,
end: 5.16,
value: "F"
},
// "Fr" - changed B to F
{
start: 5.16,
end: 5.23,
value: "O"
},
// "o" - changed E to O
{
start: 5.23,
end: 5.30,
value: "B"
},
// "m" - changed F to B (BMP)
{
start: 5.30,
end: 5.40,
value: "C"
},
// "th" - A to C
{
start: 5.40,
end: 5.54,
value: "E"
},
// "e" - C to E
{
start: 5.54,
end: 5.61,
value: "A"
},
// "a" - B to A
{
start: 5.61,
end: 5.82,
value: "C"
},
// "sh" - keep C
{
start: 5.82,
end: 5.96,
value: "A"
},
// "e" - B to A
{
start: 5.96,
end: 6.03,
value: "C"
},
// "s" - keep C
{
start: 6.03,
end: 6.31,
value: "O"
},
// "o" - B to O
{
start: 6.31,
end: 6.52,
value: "F"
},
// "f" - keep F
{
start: 6.52,
end: 6.73,
value: "C"
},
// "tr" - E to C
{
start: 6.73,
end: 7.43,
value: "A"
},
// "agedy" - B to A
{
start: 7.43,
end: 9.85,
value: "X"
}, {
start: 9.85,
end: 10.03,
value: "A"
},
// "A" - E to A
{
start: 10.03,
end: 10.24,
value: "C"
},
// "g" - keep C
{
start: 10.24,
end: 10.38,
value: "A"
},
// "ar" - E to A
{
start: 10.38,
end: 10.52,
value: "C"
},
// "d" - F to C
{
start: 10.52,
end: 10.59,
value: "A"
},
// "i" - D to A
{
start: 10.59,
end: 11.15,
value: "A"
},
// "an" - C to A
{
start: 11.15,
end: 11.23,
value: "C"
},
// "r" - A to C
{
start: 11.23,
end: 11.54,
value: "A"
},
// "i" - D to A
{
start: 11.54,
end: 11.62,
value: "C"
},
// "s" - keep C
{
start: 11.62,
end: 12.77,
value: "A"
},
// "es" - B to A
{
start: 12.77,
end: 13.77,
value: "X"
}, {
start: 13.77,
end: 13.83,
value: "N"
},
// "N" - C to N
{
start: 13.83,
end: 14.44,
value: "O"
},
// "ot" - F to O
{
start: 14.44,
end: 14.79,
value: "C"
},
// "th" - E to C
{
start: 14.79,
end: 15.01,
value: "E"
},
// "e" - F to E
{
start: 15.01,
end: 15.09,
value: "E"
},
// "he" - A to E
{
start: 15.09,
end: 15.13,
value: "C"
},
// "r" - B to C
{
start: 15.13,
end: 15.38,
value: "O"
},
// "o" - F to O
{
start: 15.38,
end: 15.45,
value: "C"
},
// "th" - B to C
{
start: 15.45,
end: 16.08,
value: "A"
},
// "ey" - E to A
{
start: 16.08,
end: 16.29,
value: "C"
},
// "deserve" - B to C
{
start: 16.29,
end: 17.16,
value: "X"
}, {
start: 17.16,
end: 17.23,
value: "B"
},
// "B" - C to B
{
start: 17.23,
end: 17.29,
value: "U"
},
// "u" - B to U
{
start: 17.29,
end: 17.99,
value: "C"
},
// "t the" - H to C
{
start: 17.99,
end: 19.53,
value: "U"
},
// "one they need" - B to U
{
start: 19.53,
end: 19.86,
value: "X"
}, {
start: 19.86,
end: 20.09,
value: "E"
},
// "e" - B to E
{
start: 20.09,
end: 22.08,
value: "X"
}, {
start: 22.08,
end: 22.42,
value: "B"
},
// "P" - E to B (BMP)
{
start: 22.42,
end: 22.77,
value: "A"
},
// "ar" - B to A
{
start: 22.77,
end: 22.85,
value: "A"
},
// "e" - keep A
{
start: 22.85,
end: 23.02,
value: "N"
},
// "n" - E to N
{
start: 23.02,
end: 23.30,
value: "C"
},
// "ts" - B to C
{
start: 23.30,
end: 23.65,
value: "F"
},
// "f" - C to F
{
start: 23.65,
end: 23.86,
value: "A"
},
// "a" - B to A
{
start: 23.86,
end: 24.49,
value: "L"
},
// "ll" - F to L
{
start: 24.49,
end: 24.91,
value: "A"
},
// "en" - B to A
{
start: 24.91,
end: 24.98,
value: "N"
},
// "n" - E to N
{
start: 24.98,
end: 25.05,
value: "A"
},
// "a" - keep A
{
start: 25.05,
end: 25.33,
value: "N"
},
// "n" - E to N
{
start: 25.33,
end: 25.75,
value: "A"
},
// "a" - B to A
{
start: 25.75,
end: 25.82,
value: "L"
},
// "l" - D to L
{
start: 25.82,
end: 25.96,
value: "L"
},
// "l" - B to L
{
start: 25.96,
end: 26.17,
value: "E"
},
// "ey" - F to E
{
start: 26.17,
end: 26.45,
value: "C"
},
// "c" - E to C
{
start: 26.45,
end: 27.08,
value: "O"
},
// "o" - B to O
{
start: 27.08,
end: 27.43,
value: "L"
},
// "l" - E to L
{
start: 27.43,
end: 27.57,
value: "C"
},
// "d" - F to C
{
start: 27.57,
end: 27.71,
value: "C"
},
// keep C
{
start: 27.71,
end: 28.48,
value: "B"
},
// B stays
{
start: 28.48,
end: 32.70,
value: "X"
}, {
start: 32.70,
end: 32.82,
value: "A"
},
// "A" - B to A
{
start: 32.82,
end: 33.03,
value: "B"
},
// "boy" - E to B
{
start: 33.03,
end: 33.45,
value: "O"
},
// "oy" - B to O
{
start: 33.45,
end: 33.66,
value: "C"
},
// "s" - E to C
{
start: 33.66,
end: 33.73,
value: "C"
},
// "h" - F to C
{
start: 33.73,
end: 33.87,
value: "A"
},
// "ar" - B to A
{
start: 33.87,
end: 34.01,
value: "C"
},
// "t" - E to C
{
start: 34.01,
end: 34.29,
value: "C"
},
// keep C
{
start: 34.29,
end: 34.36,
value: "U"
},
// "ur" - B to U
{
start: 34.36,
end: 34.50,
value: "N"
},
// "n" - E to N
{
start: 34.50,
end: 34.71,
value: "C"
},
// "d" - B to C
{
start: 34.71,
end: 34.85,
value: "C"
},
// "t" - E to C
{
start: 34.85,
end: 35.13,
value: "U"
},
// "o" - C to U
{
start: 35.13,
end: 35.20,
value: "C"
},
// "st" - F to C
{
start: 35.20,
end: 35.48,
value: "O"
},
// "o" - B to O
{
start: 35.48,
end: 35.55,
value: "N"
},
// "n" - C to N
{
start: 35.55,
end: 35.76,
value: "E"
},
// "e" - keep E
{
start: 35.76,
end: 35.90,
value: "F"
},
// keep F
{
start: 35.90,
end: 36.60,
value: "N"
},
// "Now" - B to N
{
start: 36.60,
end: 36.71,
value: "A"
},
// "I" - keep A
{
start: 36.71,
end: 36.89,
value: "C"
},
// "cl" - D to C
{
start: 36.89,
end: 36.94,
value: "A"
},
// "ai" - C to A
{
start: 36.94,
end: 37.47,
value: "B"
},
// "m" - keep B
{
start: 37.47,
end: 37.55,
value: "C"
},
// "th" - A to C
{
start: 37.55,
end: 37.65,
value: "E"
},
// "e" - D to E
{
start: 37.65,
end: 37.72,
value: "N"
},
// "n" - B to N
{
start: 37.72,
end: 37.92,
value: "A"
},
// "ight" - F to A
{
start: 37.92,
end: 38.00,
value: "A"
},
// "as" - E to A
{
start: 38.00,
end: 40.10,
value: "O"
},
// "my own" - H to O
{
start: 40.10,
end: 43.42,
value: "X"
},
// Continue with the rest, keeping ALL original timing and X placements...
// I'll just show the pattern - every entry needs the same treatment
{
start: 43.42,
end: 43.67,
value: "C"
},
// "G" - B to C
{
start: 43.67,
end: 43.74,
value: "O"
},
// "o" - G to O
{
start: 43.74,
end: 43.88,
value: "C"
},
// "th" - F to C
{
start: 43.88,
end: 44.23,
value: "A"
},
// "am" - E to A
{
start: 44.23,
end: 44.44,
value: "C"
},
// "c" - F to C
{
start: 44.44,
end: 44.58,
value: "A"
},
// "a" - B to A
{
start: 44.58,
end: 44.79,
value: "L"
},
// "ll" - F to L
{
start: 44.79,
end: 45.07,
value: "C"
},
// "s" - B to C
{
start: 45.07,
end: 45.35,
value: "C"
},
// "t" - F to C
{
start: 45.35,
end: 45.63,
value: "U"
},
// "o" - E to U
{
start: 45.63,
end: 45.70,
value: "B"
},
// "m" - keep B
{
start: 45.70,
end: 46.12,
value: "E"
},
// "e" - keep E
{
start: 46.12,
end: 46.40,
value: "N"
},
// "in" - C to N
{
start: 46.40,
end: 46.45,
value: "QW"
},
// "wh" - B to QW
{
start: 46.45,
end: 47.13,
value: "C"
},
// "whispers" - F to C
{
start: 47.13,
end: 47.27,
value: "C"
},
// "d" - keep C
{
start: 47.27,
end: 47.34,
value: "A"
},
// "ire" - B to A
{
start: 47.34,
end: 47.55,
value: "C"
},
// "Cr" - E to C
{
start: 47.55,
end: 47.76,
value: "A"
},
// "i" - C to A
{
start: 47.76,
end: 47.83,
value: "B"
},
// "m" - keep B
{
start: 47.83,
end: 48.04,
value: "A"
},
// "i" - D to A
{
start: 48.04,
end: 48.11,
value: "N"
},
// "n" - B to N
{
start: 48.11,
end: 48.81,
value: "A"
},
// "als" - F to A
{
start: 48.81,
end: 48.88,
value: "C"
},
// "sc" - keep C
{
start: 48.88,
end: 48.95,
value: "A"
},
// "a" - B to A
{
start: 48.95,
end: 49.02,
value: "C"
},
// "tt" - E to C
{
start: 49.02,
end: 50.28,
value: "A"
},
// "er at my" - B to A
{
start: 50.28,
end: 50.61,
value: "A"
},
// "arrival" - keep A
{
start: 50.61,
end: 53.74,
value: "X"
}, {
start: 53.74,
end: 54.23,
value: "C"
},
// "The c" - B to C
{
start: 54.23,
end: 54.31,
value: "A"
},
// "a" - keep A
{
start: 54.31,
end: 54.51,
value: "B"
},
// "pe" - keep B
{
start: 54.51,
end: 54.79,
value: "C"
},
// keep C
{
start: 54.79,
end: 54.90,
value: "A"
},
// keep A
{
start: 54.90,
end: 55.01,
value: "B"
},
// keep B
{
start: 55.01,
end: 55.12,
value: "A"
},
// keep A
{
start: 55.12,
end: 55.18,
value: "C"
},
// keep C
{
start: 55.18,
end: 55.52,
value: "B"
},
// keep B
{
start: 55.52,
end: 55.59,
value: "C"
},
// keep C
{
start: 55.59,
end: 55.87,
value: "B"
},
// keep B
{
start: 55.87,
end: 56.22,
value: "F"
},
// keep F
{
start: 56.22,
end: 56.36,
value: "B"
},
// keep B
{
start: 56.36,
end: 56.66,
value: "F"
},
// keep F
{
start: 56.66,
end: 56.74,
value: "E"
},
// keep E
{
start: 56.74,
end: 56.89,
value: "C"
},
// "sk" - H to C
{
start: 56.89,
end: 57.17,
value: "C"
},
// keep C
{
start: 57.17,
end: 57.69,
value: "B"
},
// keep B
{
start: 57.69,
end: 57.92,
value: "C"
},
// keep C
{
start: 57.92,
end: 58.20,
value: "B"
},
// keep B
{
start: 58.20,
end: 59.04,
value: "C"
},
// "mask" - F to C
{
start: 59.04,
end: 59.18,
value: "B"
},
// "m" - keep B
{
start: 59.18,
end: 59.39,
value: "A"
},
// "y" - E to A
{
start: 59.39,
end: 59.53,
value: "C"
},
// "tr" - G to C
{
start: 59.53,
end: 59.98,
value: "U"
},
// "ue" - D to U
{
start: 59.98,
end: 60.06,
value: "C"
},
// keep C
{
start: 60.06,
end: 60.37,
value: "C"
},
// "surv" - B to C
{
start: 60.37,
end: 60.51,
value: "A"
},
// "iv" - G to A
{
start: 60.51,
end: 60.65,
value: "A"
},
// "al" - E to A
{
start: 60.65,
end: 62.19,
value: "L"
},
// "l" - H to L
{
start: 62.19,
end: 62.33,
value: "X"
}, {
start: 62.33,
end: 62.55,
value: "B"
},
// keep B
{
start: 62.55,
end: 63.24,
value: "X"
}, {
start: 63.24,
end: 63.38,
value: "F"
},
// "Fr" - B to F
{
start: 63.38,
end: 63.73,
value: "O"
},
// "om" - E to O
{
start: 63.73,
end: 63.87,
value: "C"
},
// "th" - F to C
{
start: 63.87,
end: 63.99,
value: "E"
},
// "e" - A to E
{
start: 63.99,
end: 64.11,
value: "C"
},
// "d" - B to C
{
start: 64.11,
end: 64.46,
value: "A"
},
// "ar" - E to A
{
start: 64.46,
end: 64.60,
value: "C"
},
// "k" - F to C
{
start: 64.60,
end: 64.67,
value: "N"
},
// "n" - B to N
{
start: 64.67,
end: 64.88,
value: "A"
},
// "e" - F to A
{
start: 64.88,
end: 64.95,
value: "C"
},
// "ss" - keep C
{
start: 64.95,
end: 65.88,
value: "A"
},
// "I" - B to A
{
start: 65.88,
end: 66.43,
value: "X"
}, {
start: 66.43,
end: 66.62,
value: "A"
},
// "e" - D to A
{
start: 66.62,
end: 66.81,
value: "B"
},
// "m" - C to B
{
start: 66.81,
end: 66.86,
value: "A"
},
// "er" - E to A
{
start: 66.86,
end: 67.11,
value: "C"
},
// "ge" - F to C
{
start: 67.11,
end: 68.93,
value: "E"
},
// long vowel - B to E
{
start: 68.93,
end: 69.14,
value: "X"
}, {
start: 69.14,
end: 70.99,
value: "A"
},
// vowel sounds - B to A
{
start: 70.99,
end: 71.13,
value: "C"
},
// consonant - F to C
{
start: 71.13,
end: 72.63,
value: "A"
},
// vowel - D to A
{
start: 72.63,
end: 72.71,
value: "C"
},
// consonant - keep C
{
start: 72.71,
end: 73.16,
value: "E"
},
// vowel - B to E
{
start: 73.16,
end: 75.30,
value: "X"
}, {
start: 75.30,
end: 75.57,
value: "C"
},
// "J" - B to C
{
start: 75.57,
end: 75.71,
value: "U"
},
// "u" - E to U
{
start: 75.71,
end: 75.99,
value: "C"
},
// "st" - B to C
{
start: 75.99,
end: 76.27,
value: "A"
},
// "i" - C to A
{
start: 76.27,
end: 76.34,
value: "C"
},
// "s" - B to C
{
start: 76.34,
end: 76.83,
value: "E"
},
// "e" - F to E
{
start: 76.83,
end: 77.04,
value: "A"
},
// "i" - E to A
{
start: 77.04,
end: 77.11,
value: "C"
},
// "s" - keep C
{
start: 77.11,
end: 77.18,
value: "QW"
},
// "wh" - H to QW
{
start: 77.18,
end: 77.37,
value: "A"
},
// "a" - D to A
{
start: 77.37,
end: 77.42,
value: "C"
},
// "t" - keep C
{
start: 77.42,
end: 77.81,
value: "A"
},
// "I" - B to A
{
start: 77.81,
end: 79.14,
value: "C"
},
// "serve" - F to C
{
start: 79.14,
end: 79.48,
value: "F"
},
// "v" - B to F
{
start: 79.48,
end: 80.18,
value: "E"
},
// "e" - D to E
{
start: 80.18,
end: 80.46,
value: "C"
},
// end consonant - keep C
{
start: 80.46,
end: 83.12,
value: "B"
},
// keep B
{
start: 83.12,
end: 84.24,
value: "E"
},
// keep E
{
start: 84.24,
end: 84.45,
value: "B"
},
// keep B
{
start: 84.45,
end: 85.37,
value: "X"
}, {
start: 85.37,
end: 85.55,
value: "QW"
},
// "Wh" - F to QW
{
start: 85.55,
end: 86.08,
value: "A"
},
// "en" - B to A
{
start: 86.08,
end: 86.62,
value: "E"
},
// "e" - F to E
{
start: 86.62,
end: 86.67,
value: "F"
},
// "v" - C to F
{
start: 86.67,
end: 87.00,
value: "A"
},
// "i" - E to A
{
start: 87.00,
end: 87.28,
value: "L"
},
// "l" - F to L
{
start: 87.28,
end: 87.42,
value: "B"
},
// "p" - D to B
{
start: 87.42,
end: 87.70,
value: "A"
},
// "la" - C to A
{
start: 87.70,
end: 88.54,
value: "C"
},
// "gues" - B to C
{
start: 88.54,
end: 89.42,
value: "E"
},
// "these" - D to E
{
start: 89.42,
end: 89.49,
value: "C"
},
// "s" - keep C
{
start: 89.49,
end: 89.73,
value: "C"
},
// "tr" - B to C
{
start: 89.73,
end: 90.46,
value: "X"
}, {
start: 90.46,
end: 90.81,
value: "A"
},
// "I'll" - E to A
{
start: 90.81,
end: 91.27,
value: "B"
},
// "be" - F to B
{
start: 91.27,
end: 91.34,
value: "C"
},
// "th" - E to C
{
start: 91.34,
end: 91.41,
value: "A"
},
// "ere" - F to A
{
start: 91.41,
end: 92.11,
value: "E"
},
// "e" - B to E
{
start: 92.11,
end: 93.07,
value: "X"
}, {
start: 93.07,
end: 93.33,
value: "A"
},
// "I'll" - C to A
{
start: 93.33,
end: 93.40,
value: "L"
},
// "l" - E to L
{
start: 93.40,
end: 93.78,
value: "B"
},
// "be" - F to B
{
start: 93.78,
end: 93.85,
value: "C"
},
// "th" - B to C
{
start: 93.85,
end: 94.16,
value: "A"
},
// "ere" - D to A
{
start: 94.16,
end: 94.24,
value: "E"
},
// "e" - C to E
{
start: 94.24,
end: 95.04,
value: "B"
},
// keep B
{
start: 95.04,
end: 95.79,
value: "X"
}, {
start: 95.79,
end: 95.89,
value: "A"
},
// "I'm" - C to A
{
start: 95.89,
end: 95.96,
value: "B"
},
// "m" - keep B
{
start: 95.96,
end: 96.05,
value: "B"
},
// "B" - A to B
{
start: 96.05,
end: 96.31,
value: "A"
},
// "a" - C to A
{
start: 96.31,
end: 96.49,
value: "C"
},
// "t" - B to C
{
start: 96.49,
end: 97.18,
value: "B"
},
// "m" - D to B
{
start: 97.18,
end: 97.26,
value: "A"
},
// "an" - C to A
{
start: 97.26,
end: 98.43,
value: "X"
}, {
start: 98.43,
end: 98.54,
value: "A"
},
// "I'm" - E to A
{
start: 98.54,
end: 98.61,
value: "B"
},
// "m" - F to B
{
start: 98.61,
end: 98.68,
value: "B"
},
// "B" - C to B
{
start: 98.68,
end: 98.75,
value: "A"
},
// "a" - B to A
{
start: 98.75,
end: 98.82,
value: "C"
},
// "t" - F to C
{
start: 98.82,
end: 99.10,
value: "B"
},
// "m" - C to B
{
start: 99.10,
end: 99.18,
value: "A"
},
// "a" - keep A
{
start: 99.18,
end: 99.64,
value: "N"
},
// "n" - C to N
{
start: 99.64,
end: 99.85,
value: "B"
},
// keep B
{
start: 99.85,
end: 101.13,
value: "X"
}, {
start: 101.13,
end: 101.26,
value: "A"
},
// "I'm" - D to A
{
start: 101.26,
end: 101.33,
value: "B"
},
// "m" - keep B
{
start: 101.33,
end: 101.45,
value: "B"
},
// "B" - A to B
{
start: 101.45,
end: 101.86,
value: "A"
},
// "a" - B to A
{
start: 101.86,
end: 102.38,
value: "C"
},
// "t" - D to C
{
start: 102.38,
end: 102.46,
value: "B"
},
// "m" - C to B
{
start: 102.46,
end: 103.19,
value: "A"
},
// "an" - B to A
{
start: 103.19,
end: 103.47,
value: "A"
},
// "I'm" - H to A
{
start: 103.47,
end: 104.52,
value: "B"
},
// "m B" - keep B
{
start: 104.52,
end: 105.15,
value: "A"
},
// "a" - D to A
{
start: 105.15,
end: 105.57,
value: "C"
},
// "tman" - keep C
{
start: 105.57,
end: 108.41,
value: "X"
}, {
start: 108.41,
end: 108.56,
value: "A"
},
// "A" - B to A
{
start: 108.56,
end: 108.63,
value: "C"
},
// "g" - D to C
{
start: 108.63,
end: 108.84,
value: "A"
},
// "a" - B to A
{
start: 108.84,
end: 108.98,
value: "L"
},
// "ll" - C to L
{
start: 108.98,
end: 109.05,
value: "A"
},
// "e" - E to A
{
start: 109.05,
end: 109.33,
value: "C"
},
// "ry" - F to C
{
start: 109.33,
end: 109.68,
value: "O"
},
// "of" - B to O
{
start: 109.68,
end: 109.82,
value: "F"
},
// "f" - keep F
{
start: 109.82,
end: 109.89,
value: "B"
},
// "m" - C to B
{
start: 109.89,
end: 110.03,
value: "A"
},
// "a" - B to A
{
start: 110.03,
end: 110.17,
value: "C"
},
// "d" - keep C
{
start: 110.17,
end: 110.24,
value: "N"
},
// "n" - D to N
{
start: 110.24,
end: 110.52,
value: "A"
},
// "e" - B to A
{
start: 110.52,
end: 110.59,
value: "C"
},
// "ss" - keep C
{
start: 110.59,
end: 111.01,
value: "A"
},
// "I've" - B to A
{
start: 111.01,
end: 111.08,
value: "F"
},
// "v" - C to F
{
start: 111.08,
end: 111.57,
value: "A"
},
// "e" - B to A
{
start: 111.57,
end: 111.64,
value: "F"
},
// "f" - C to F
{
start: 111.64,
end: 111.99,
value: "A"
},
// "aced" - B to A
{
start: 111.99,
end: 113.77,
value: "X"
}, {
start: 113.77,
end: 114.16,
value: "C"
},
// "The" - B to C
{
start: 114.16,
end: 114.65,
value: "C"
},
// "J" - E to C
{
start: 114.65,
end: 114.93,
value: "O"
},
// "o" - F to O
{
start: 114.93,
end: 115.00,
value: "C"
},
// "k" - D to C
{
start: 115.00,
end: 115.24,
value: "A"
},
// "er" - C to A
{
start: 115.24,
end: 115.46,
value: "QW"
},
// "w" - B to QW
{
start: 115.46,
end: 115.60,
value: "A"
},
// "i" - C to A
{
start: 115.60,
end: 115.74,
value: "C"
},
// "th" - B to C
{
start: 115.74,
end: 115.88,
value: "A"
},
// "his" - C to A
{
start: 115.88,
end: 116.09,
value: "C"
},
// "tw" - B to C
{
start: 116.09,
end: 116.17,
value: "A"
},
// "i" - keep A
{
start: 116.17,
end: 116.24,
value: "C"
},
// "st" - E to C
{
start: 116.24,
end: 116.73,
value: "A"
},
// "ed grin" - B to A
{
start: 116.73,
end: 117.57,
value: "X"
}, {
start: 117.57,
end: 117.80,
value: "B"
},
// keep B
{
start: 117.80,
end: 118.81,
value: "X"
}, {
start: 118.81,
end: 119.28,
value: "C"
},
// "R" - B to C
{
start: 119.28,
end: 119.35,
value: "A"
},
// "i" - F to A
{
start: 119.35,
end: 119.49,
value: "C"
},
// "dd" - E to C
{
start: 119.49,
end: 119.65,
value: "L"
},
// "l" - A to L
{
start: 119.65,
end: 119.88,
value: "A"
},
// "er's" - H to A
{
start: 119.88,
end: 119.95,
value: "B"
},
// "p" - E to B
{
start: 119.95,
end: 120.16,
value: "U"
},
// "u" - B to U
{
start: 120.16,
end: 120.30,
value: "C"
},
// "zz" - E to C
{
start: 120.30,
end: 120.37,
value: "L"
},
// "l" - B to L
{
start: 120.37,
end: 120.65,
value: "A"
},
// "es" - E to A
{
start: 120.65,
end: 120.79,
value: "B"
},
// "P" - F to B
{
start: 120.79,
end: 120.93,
value: "A"
},
// "e" - B to A
{
start: 120.93,
end: 121.00,
value: "N"
},
// "n" - C to N
{
start: 121.00,
end: 121.28,
value: "C"
},
// "g" - B to C
{
start: 121.28,
end: 121.49,
value: "QW"
},
// "w" - E to QW
{
start: 121.49,
end: 121.56,
value: "A"
},
// "i" - F to A
{
start: 121.56,
end: 121.70,
value: "N"
},
// "n's" - B to N
{
start: 121.70,
end: 121.98,
value: "C"
},
// "sch" - F to C
{
start: 121.98,
end: 122.19,
value: "E"
},
// "ee" - B to E
{
start: 122.19,
end: 122.61,
value: "B"
},
// "m" - C to B
{
start: 122.61,
end: 123.56,
value: "C"
},
// "s" - B to C
{
start: 123.56,
end: 123.77,
value: "X"
}, {
start: 123.77,
end: 123.87,
value: "C"
},
// "T" - B to C
{
start: 123.87,
end: 124.02,
value: "U"
},
// "wo" - A to U
{
start: 124.02,
end: 124.16,
value: "F"
},
// "F" - G to F
{
start: 124.16,
end: 124.30,
value: "A"
},
// "a" - C to A
{
start: 124.30,
end: 124.72,
value: "C"
},
// "ce's" - B to C
{
start: 124.72,
end: 125.00,
value: "C"
},
// "c" - E to C
{
start: 125.00,
end: 125.99,
value: "O"
},
// "oi" - B to O
{
start: 125.99,
end: 126.06,
value: "N"
},
// "n" - C to N
{
start: 126.06,
end: 126.34,
value: "C"
},
// "th" - D to C
{
start: 126.34,
end: 126.48,
value: "E"
},
// "e" - B to E
{
start: 126.48,
end: 126.62,
value: "B"
},
// "b" - E to B
{
start: 126.62,
end: 126.69,
value: "A"
},
// "a" - F to A
{
start: 126.69,
end: 126.83,
value: "C"
},
// "tt" - H to C
{
start: 126.83,
end: 128.26,
value: "L"
},
// "le" - B to L
{
start: 128.26,
end: 128.43,
value: "A"
},
// "within" - E to A
{
start: 128.43,
end: 129.70,
value: "X"
}, {
start: 129.70,
end: 129.85,
value: "B"
},
// "M" - A to B
{
start: 129.85,
end: 129.96,
value: "A"
},
// "y" - D to A
{
start: 129.96,
end: 130.03,
value: "A"
},
// "a" - B to A
{
start: 130.03,
end: 130.17,
value: "L"
},
// "ll" - C to L
{
start: 130.17,
end: 130.38,
value: "A"
},
// "ies" - B to A
{
start: 130.38,
end: 130.52,
value: "F"
},
// "f" - D to F
{
start: 130.52,
end: 130.59,
value: "U"
},
// "ew" - B to U
{
start: 130.59,
end: 130.87,
value: "B"
},
// "m" - F to B
{
start: 130.87,
end: 131.08,
value: "A"
},
// "y" - B to A
{
start: 131.08,
end: 131.15,
value: "B"
},
// "b" - H to B
{
start: 131.15,
end: 131.29,
value: "U"
},
// "ur" - D to U
{
start: 131.29,
end: 131.36,
value: "C"
},
// "d" - keep C
{
start: 131.36,
end: 131.50,
value: "A"
},
// "en" - B to A
{
start: 131.50,
end: 131.81,
value: "C"
},
// "gr" - D to C
{
start: 131.81,
end: 131.89,
value: "A"
},
// "ea" - E to A
{
start: 131.89,
end: 132.20,
value: "C"
},
// "t" - F to C
{
start: 132.20,
end: 132.48,
value: "B"
},
// keep B
{
start: 132.48,
end: 132.62,
value: "X"
}, {
start: 132.62,
end: 132.69,
value: "C"
},
// "Th" - B to C
{
start: 132.69,
end: 132.90,
value: "E"
},
// "e" - C to E
{
start: 132.90,
end: 133.25,
value: "C"
},
// "c" - B to C
{
start: 133.25,
end: 133.45,
value: "A"
},
// "a" - F to A
{
start: 133.45,
end: 133.53,
value: "F"
},
// "v" - E to F
{
start: 133.53,
end: 133.88,
value: "E"
},
// "e" - H to E
{
start: 133.88,
end: 134.02,
value: "B"
},
// "b" - keep B
{
start: 134.02,
end: 134.14,
value: "X"
}, {
start: 134.14,
end: 134.29,
value: "L"
},
// "l" - B to L
{
start: 134.29,
end: 134.36,
value: "O"
},
// "o" - E to O
{
start: 134.36,
end: 134.50,
value: "QW"
},
// "w" - B to QW
{
start: 134.50,
end: 134.71,
value: "B"
},
// "m" - E to B
{
start: 134.71,
end: 134.85,
value: "A"
},
// "y" - F to A
{
start: 134.85,
end: 135.06,
value: "C"
},
// "s" - D to C
{
start: 135.06,
end: 135.20,
value: "A"
},
// "a" - E to A
{
start: 135.20,
end: 135.27,
value: "N"
},
// "n" - B to N
{
start: 135.27,
end: 135.69,
value: "C"
},
// "ct" - keep C
{
start: 135.69,
end: 135.83,
value: "U"
},
// "u" - B to U
{
start: 135.83,
end: 136.53,
value: "A"
},
// "ary" - C to A
{
start: 136.53,
end: 136.67,
value: "E"
},
// "y" - B to E
{
start: 136.67,
end: 140.08,
value: "X"
}, {
start: 140.08,
end: 140.22,
value: "A"
},
// "Al" - D to A
{
start: 140.22,
end: 140.29,
value: "F"
},
// "f" - B to F
{
start: 140.29,
end: 140.57,
value: "C"
},
// "red's" - E to C
{
start: 140.57,
end: 141.20,
value: "QW"
},
// "w" - F to QW
{
start: 141.20,
end: 141.41,
value: "A"
},
// "is" - B to A
{
start: 141.41,
end: 141.76,
value: "C"
},
// "dom" - E to C
{
start: 141.76,
end: 142.11,
value: "C"
},
// "g" - F to C
{
start: 142.11,
end: 142.18,
value: "A"
},
// "ui" - C to A
{
start: 142.18,
end: 142.25,
value: "C"
},
// "d" - E to C
{
start: 142.25,
end: 142.74,
value: "A"
},
// "es" - F to A
{
start: 142.74,
end: 142.93,
value: "B"
},
// "m" - D to B
{
start: 142.93,
end: 142.98,
value: "A"
},
// "y" - C to A
{
start: 142.98,
end: 143.21,
value: "B"
},
// "p" - B to B
{
start: 143.21,
end: 143.97,
value: "A"
},
// "ath" - D to A
{
start: 143.97,
end: 144.11,
value: "C"
},
// "th" - B to C
{
start: 144.11,
end: 144.27,
value: "X"
}, {
start: 144.27,
end: 144.40,
value: "C"
},
// "Thr" - B to C
{
start: 144.40,
end: 145.11,
value: "U"
},
// "ough" - X to U
{
start: 145.11,
end: 145.58,
value: "C"
},
// "th" - B to C
{
start: 145.58,
end: 145.72,
value: "A"
},
// "is" - F to A
{
start: 145.72,
end: 145.80,
value: "L"
},
// "l" - A to L
{
start: 145.80,
end: 145.87,
value: "A"
},
// "i" - F to A
{
start: 145.87,
end: 146.18,
value: "F"
},
// "f" - D to F
{
start: 146.18,
end: 146.25,
value: "E"
},
// "e" - C to E
{
start: 146.25,
end: 146.49,
value: "C"
},
// "s" - B to C
{
start: 146.49,
end: 146.56,
value: "O"
},
// "o" - G to O
{
start: 146.56,
end: 146.77,
value: "C"
},
// "s" - B to C
{
start: 146.77,
end: 146.85,
value: "O"
},
// "o" - A to O
{
start: 146.85,
end: 147.26,
value: "L"
},
// "l" - E to L
{
start: 147.26,
end: 147.47,
value: "A"
},
// "i" - B to A
{
start: 147.47,
end: 147.75,
value: "C"
},
// "t" - F to C
{
start: 147.75,
end: 147.82,
value: "A"
},
// "a" - E to A
{
start: 147.82,
end: 148.15,
value: "C"
},
// "r" - D to C
{
start: 148.15,
end: 148.20,
value: "E"
},
// "y" - C to E
{
start: 148.20,
end: 148.38,
value: "B"
},
// keep B
{
start: 148.38,
end: 148.45,
value: "F"
},
// keep F
{
start: 148.45,
end: 150.48,
value: "E"
},
// keep E
{
start: 150.48,
end: 150.90,
value: "B"
},
// keep B
{
start: 150.90,
end: 151.41,
value: "X"
}, {
start: 151.41,
end: 151.76,
value: "F"
},
// "Fr" - E to F
{
start: 151.76,
end: 151.90,
value: "O"
},
// "o" - F to O
{
start: 151.90,
end: 152.15,
value: "B"
},
// "m" - A to B
{
start: 152.15,
end: 152.40,
value: "C"
},
// "th" - E to C
{
start: 152.40,
end: 152.54,
value: "E"
},
// "e" - F to E
{
start: 152.54,
end: 152.61,
value: "C"
},
// "d" - B to C
{
start: 152.61,
end: 152.89,
value: "A"
},
// "ar" - E to A
{
start: 152.89,
end: 153.13,
value: "C"
},
// "k" - F to C
{
start: 153.13,
end: 153.19,
value: "N"
},
// "n" - C to N
{
start: 153.19,
end: 153.38,
value: "A"
},
// "e" - E to A
{
start: 153.38,
end: 153.45,
value: "C"
},
// "ss" - F to C
{
start: 153.45,
end: 154.69,
value: "A"
},
// "I" - X to A
{
start: 154.69,
end: 154.96,
value: "A"
},
// "e" - C to A
{
start: 154.96,
end: 155.16,
value: "B"
},
// "m" - A to B
{
start: 155.16,
end: 155.54,
value: "A"
},
// "er" - D to A
{
start: 155.54,
end: 155.62,
value: "C"
},
// "g" - C to C
{
start: 155.62,
end: 156.49,
value: "E"
},
// "e" - B to E
{
start: 156.49,
end: 156.63,
value: "E"
},
// keep E
{
start: 156.63,
end: 157.19,
value: "B"
},
// keep B
{
start: 157.19,
end: 157.47,
value: "E"
},
// keep E
{
start: 157.47,
end: 157.68,
value: "C"
},
// keep C
{
start: 157.68,
end: 158.18,
value: "B"
},
// keep B
{
start: 158.18,
end: 158.22,
value: "F"
},
// keep F
{
start: 158.22,
end: 159.21,
value: "B"
},
// keep B
{
start: 159.21,
end: 159.83,
value: "E"
},
// keep E
{
start: 159.83,
end: 160.25,
value: "F"
},
// keep F
{
start: 160.25,
end: 160.81,
value: "B"
},
// keep B
{
start: 160.81,
end: 163.32,
value: "X"
}, {
start: 163.32,
end: 163.41,
value: "C"
},
// "J" - B to C
{
start: 163.41,
end: 163.49,
value: "U"
},
// "u" - A to U
{
start: 163.49,
end: 163.68,
value: "C"
},
// "st" - D to C
{
start: 163.68,
end: 163.73,
value: "A"
},
// "i" - C to A
{
start: 163.73,
end: 163.91,
value: "C"
},
// "s" - B to C
{
start: 163.91,
end: 164.12,
value: "E"
},
// "e" - C to E
{
start: 164.12,
end: 164.71,
value: "A"
},
// "i" - B to A
{
start: 164.71,
end: 164.92,
value: "C"
},
// "s" - E to C
{
start: 164.92,
end: 165.13,
value: "QW"
},
// "wh" - F to QW
{
start: 165.13,
end: 165.48,
value: "A"
},
// "a" - D to A
{
start: 165.48,
end: 165.62,
value: "C"
},
// "t" - C to C
{
start: 165.62,
end: 165.90,
value: "A"
},
// "I" - B to A
{
start: 165.90,
end: 165.97,
value: "C"
},
// "s" - C to C
{
start: 165.97,
end: 167.23,
value: "A"
},
// "erve" - A to A
{
start: 167.23,
end: 167.68,
value: "X"
}, {
start: 167.68,
end: 168.61,
value: "A"
},
// keep A
{
start: 168.61,
end: 168.91,
value: "B"
},
// keep B
{
start: 168.91,
end: 168.98,
value: "C"
},
// keep C
{
start: 168.98,
end: 169.40,
value: "E"
},
// keep E
{
start: 169.40,
end: 169.73,
value: "F"
},
// keep F
{
start: 169.73,
end: 172.56,
value: "D"
},
// keep D
{
start: 172.56,
end: 172.64,
value: "C"
},
// keep C
{
start: 172.64,
end: 173.40,
value: "X"
}, {
start: 173.40,
end: 173.53,
value: "QW"
},
// "Wh" - F to QW
{
start: 173.53,
end: 174.56,
value: "A"
},
// "en" - B to A
{
start: 174.56,
end: 174.63,
value: "E"
},
// "e" - F to E
{
start: 174.63,
end: 174.70,
value: "F"
},
// "v" - G to F
{
start: 174.70,
end: 174.98,
value: "A"
},
// "i" - E to A
{
start: 174.98,
end: 175.26,
value: "L"
},
// "l" - H to L
{
start: 175.26,
end: 175.68,
value: "B"
},
// "p" - C to B
{
start: 175.68,
end: 176.10,
value: "A"
},
// "la" - B to A
{
start: 176.10,
end: 176.24,
value: "C"
},
// "gues" - C to C
{
start: 176.24,
end: 176.45,
value: "E"
},
// "these" - B to E
{
start: 176.45,
end: 176.52,
value: "C"
},
// "s" - E to C
{
start: 176.52,
end: 177.64,
value: "C"
},
// "treets" - B to C
{
start: 177.64,
end: 177.85,
value: "X"
}, {
start: 177.85,
end: 177.97,
value: "B"
},
// keep B
{
start: 177.97,
end: 178.27,
value: "X"
}, {
start: 178.27,
end: 178.40,
value: "A"
},
// "I'll" - B to A
{
start: 178.40,
end: 178.54,
value: "L"
},
// "l" - D to L
{
start: 178.54,
end: 178.68,
value: "B"
},
// "be" - B to B
{
start: 178.68,
end: 179.17,
value: "C"
},
// "th" - F to C
{
start: 179.17,
end: 179.94,
value: "A"
},
// "ere" - B to A
{
start: 179.94,
end: 181.13,
value: "X"
}, {
start: 181.13,
end: 181.25,
value: "A"
},
// "I'll" - D to A
{
start: 181.25,
end: 181.39,
value: "L"
},
// "l" - B to L
{
start: 181.39,
end: 181.94,
value: "B"
},
// "be" - F to B
{
start: 181.94,
end: 182.33,
value: "C"
},
// "th" - D to C
{
start: 182.33,
end: 182.41,
value: "A"
},
// "ere" - C to A
{
start: 182.41,
end: 182.86,
value: "E"
},
// "e" - B to E
{
start: 182.86,
end: 182.98,
value: "X"
}, {
start: 182.98,
end: 183.17,
value: "B"
},
// keep B
{
start: 183.17,
end: 183.81,
value: "X"
}, {
start: 183.81,
end: 183.96,
value: "A"
},
// "I'm" - C to A
{
start: 183.96,
end: 184.18,
value: "B"
},
// "m" - A to B
{
start: 184.18,
end: 184.63,
value: "B"
},
// "B" - D to B
{
start: 184.63,
end: 184.71,
value: "A"
},
// "a" - C to A
{
start: 184.71,
end: 185.44,
value: "C"
},
// "tman" - B to C
{
start: 185.44,
end: 186.32,
value: "X"
}, {
start: 186.32,
end: 186.49,
value: "A"
},
// "I'm" - B to A
{
start: 186.49,
end: 186.56,
value: "B"
},
// "m" - C to B
{
start: 186.56,
end: 186.63,
value: "B"
},
// "B" - B to B
{
start: 186.63,
end: 186.78,
value: "A"
},
// "a" - A to A
{
start: 186.78,
end: 187.00,
value: "C"
},
// "t" - C to C
{
start: 187.00,
end: 188.12,
value: "B"
},
// "man" - B to B
{
start: 188.12,
end: 189.10,
value: "X"
}, {
start: 189.10,
end: 189.33,
value: "A"
},
// "I'm" - C to A
{
start: 189.33,
end: 189.47,
value: "B"
},
// "m" - B to B
{
start: 189.47,
end: 189.66,
value: "B"
},
// "B" - D to B
{
start: 189.66,
end: 189.71,
value: "A"
},
// "a" - C to A
{
start: 189.71,
end: 190.80,
value: "C"
},
// "t" - B to C
{
start: 190.80,
end: 191.22,
value: "B"
},
// "m" - D to B
{
start: 191.22,
end: 191.46,
value: "A"
},
// "a" - C to A
{
start: 191.46,
end: 191.50,
value: "N"
},
// "n" - H to N
{
start: 191.50,
end: 191.54,
value: "C"
},
// keep C
{
start: 191.54,
end: 192.52,
value: "A"
},
// "I'm" - G to A
{
start: 192.52,
end: 192.69,
value: "B"
},
// "B" - A to B
{
start: 192.69,
end: 192.83,
value: "A"
},
// "a" - C to A
{
start: 192.83,
end: 193.25,
value: "C"
},
// "t" - B to C
{
start: 193.25,
end: 193.50,
value: "B"
},
// "M" - G to B
{
start: 193.50,
end: 193.71,
value: "A"
},
// "a" - E to A
{
start: 193.71,
end: 193.82,
value: "N"
},
// "n" - A to N
{
start: 193.82,
end: 194.03,
value: "C"
},
// "d" - D to C
{
start: 194.03,
end: 194.09,
value: "C"
},
// keep C
{
start: 194.09,
end: 195.53,
value: "B"
},
// keep B
{
start: 195.53,
end: 195.77,
value: "X"
}, {
start: 195.77,
end: 195.95,
value: "N"
},
// "Na" - B to N
{
start: 195.95,
end: 196.65,
value: "A"
},
// "a" - C to A
{
start: 196.65,
end: 198.41,
value: "N"
},
// "na na na" - B to N
{
start: 198.41,
end: 198.66,
value: "B"
},
// "B" - C to B
{
start: 198.66,
end: 198.80,
value: "A"
},
// "a" - B to A
{
start: 198.80,
end: 199.08,
value: "C"
},
// "t" - C to C
{
start: 199.08,
end: 199.15,
value: "B"
},
// "m" - B to B
{
start: 199.15,
end: 199.43,
value: "A"
},
// "a" - C to A
{
start: 199.43,
end: 199.85,
value: "N"
},
// "n" - B to N
{
start: 199.85,
end: 199.99,
value: "C"
},
// keep C
{
start: 199.99,
end: 200.20,
value: "B"
},
// keep B
{
start: 200.20,
end: 200.41,
value: "G"
},
// keep G
{
start: 200.41,
end: 201.15,
value: "N"
},
// "Na" - B to N
{
start: 201.15,
end: 202.25,
value: "A"
},
// "na na na" - D to A
{
start: 202.25,
end: 202.33,
value: "N"
},
// "na" - C to N
{
start: 202.33,
end: 203.09,
value: "A"
},
// "na na" - B to A
{
start: 203.09,
end: 203.19,
value: "B"
},
// "B" - C to B
{
start: 203.19,
end: 203.26,
value: "A"
},
// "a" - E to A
{
start: 203.26,
end: 203.33,
value: "C"
},
// "t" - F to C
{
start: 203.33,
end: 203.89,
value: "B"
},
// "man!" - B to B
{
start: 203.89,
end: 206.72,
value: "X"
}];
// Viseme mapping
self.visemeMapping = {
'X': 'closed',
'A': 'AEI',
'B': 'BMP',
'C': 'CDGKNRSTXYZ',
'D': 'AEI',
'E': 'EE',
'F': 'FV',
'G': 'CDGKNRSTXYZ',
'H': 'CHJSH'
};
self.songStartTime = null;
self.isLipSyncActive = false;
self.currentLipSyncIndex = 0;
// Position tracking variables (keeping your existing setup)
var targetX = GAME_WIDTH / 2;
var targetY = GAME_HEIGHT / 2 + 200;
var smoothingFactor = 0.18;
var prevX = null;
var prevY = null;
// Scale tracking variables (keeping your existing setup)
var scaleHistory = new Array(5).fill(1);
var scaleIndex = 0;
var currentScale = 1;
// Rotation variables (keeping your existing setup)
var targetTilt = 0;
var tiltSmoothingFactor = 0.11;
var tiltScaleFactor = 0.09;
function calculateFaceTilt() {
if (facekit.leftEye && facekit.rightEye && facekit.mouthCenter) {
var eyeMidX = (facekit.leftEye.x + facekit.rightEye.x) / 2;
var eyeMidY = (facekit.leftEye.y + facekit.rightEye.y) / 2;
var dx = facekit.mouthCenter.x - eyeMidX;
var dy = facekit.mouthCenter.y - eyeMidY;
var angle = -(Math.atan2(dx, dy) * (180 / Math.PI));
return Math.max(-15, Math.min(15, angle * 0.15));
}
return 0;
}
self.startLipSync = function () {
self.songStartTime = Date.now();
self.isLipSyncActive = true;
self.currentLipSyncIndex = 0;
};
self.setViseme = function (visemeName) {
if (self.currentViseme !== visemeName && self.visemes[visemeName]) {
if (self.visemes[self.currentViseme]) {
self.visemes[self.currentViseme].visible = false;
}
self.visemes[visemeName].visible = true;
self.currentViseme = visemeName;
}
};
self.updateAutomatedLipSync = function () {
if (!self.isLipSyncActive || !self.songStartTime || self.automatedLipSync.length === 0) {
return;
}
var currentTimeSeconds = (Date.now() - self.songStartTime) / 1000.0;
var targetVisemeKey = 'closed';
// Start searching from currentLipSyncIndex for optimization
for (var i = self.currentLipSyncIndex; i < self.automatedLipSync.length; i++) {
var cue = self.automatedLipSync[i];
if (currentTimeSeconds >= cue.start && currentTimeSeconds < cue.end) {
var automatedCode = cue.value;
targetVisemeKey = self.visemeMapping[automatedCode] || 'closed';
self.currentLipSyncIndex = i;
break;
}
if (currentTimeSeconds >= cue.end) {
if (i === self.automatedLipSync.length - 1) {
var automatedCode = cue.value;
targetVisemeKey = self.visemeMapping[automatedCode] || 'closed';
}
} else if (currentTimeSeconds < cue.start) {
break;
}
}
if (self.currentLipSyncIndex === self.automatedLipSync.length - 1 && currentTimeSeconds >= self.automatedLipSync[self.automatedLipSync.length - 1].end) {
targetVisemeKey = 'closed';
}
self.setViseme(targetVisemeKey);
};
self.update = function () {
// Update automated lip sync
self.updateAutomatedLipSync();
// Smooth position tracking
if (facekit.mouthCenter) {
targetX = facekit.mouthCenter.x;
targetY = facekit.mouthCenter.y;
if (prevX === null) {
prevX = targetX;
prevY = targetY;
}
var newX = prevX * (1 - smoothingFactor) + targetX * smoothingFactor;
var newY = prevY * (1 - smoothingFactor) + targetY * smoothingFactor;
self.x = newX;
self.y = newY;
prevX = newX;
prevY = newY;
}
// Dynamic scale adjustment
if (facekit.leftEye && facekit.rightEye) {
var eyeDistance = Math.abs(facekit.rightEye.x - facekit.leftEye.x);
var newScale = eyeDistance / 250;
scaleHistory[scaleIndex] = newScale;
scaleIndex = (scaleIndex + 1) % scaleHistory.length;
var avgScale = scaleHistory.reduce(function (a, b) {
return a + b;
}, 0) / scaleHistory.length;
var targetScale = Math.max(0.6, Math.min(1.4, avgScale));
currentScale = currentScale * 0.85 + targetScale * 0.15;
Object.keys(self.visemes).forEach(function (key) {
self.visemes[key].scaleX = currentScale;
self.visemes[key].scaleY = currentScale;
});
}
// Rotation tracking
if (facekit.leftEye && facekit.rightEye) {
targetTilt = calculateFaceTilt() * tiltScaleFactor;
targetTilt = Math.max(-15, Math.min(15, targetTilt));
self.rotation += (targetTilt - self.rotation) * tiltSmoothingFactor;
}
};
return self;
});
var StartButton = Container.expand(function () {
var self = Container.call(this);
self.buttonGraphics = self.attachAsset('startButtonImage', {
anchorX: 0.5,
anchorY: 0.5
});
self.down = function () {
// This will call the globally defined startGame function
// when the button is pressed.
if (typeof handleStartButtonPressed === 'function') {
handleStartButtonPressed();
}
};
return self;
});
/****
* Initialize Game
****/
// Facekit provides the camera feed as background, so no explicit backgroundColor needed.
var game = new LK.Game({});
/****
* Game Code
****/
// Game state variables
var isGameActive = false;
var startButtonInstance;
var maskInstance;
var mouthAnimatorInstance;
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var AUTOMATED_VISEME_MAPPING = {
'X': 'closed',
// Silence/rest position
'A': 'AEI',
// Open vowels (father, palm)
'B': 'BMP',
// Lip closure (b, m, p)
'C': 'CDGKNRSTXYZ',
// Consonants (c, d, g, k, n, r, s, t, x, y, z)
'D': 'AEI',
// Mid vowels (day, face)
'E': 'EE',
// High front vowels (see, fleece)
'F': 'FV',
// Lip-teeth contact (f, v)
'G': 'CDGKNRSTXYZ',
// Back consonants (g, ng)
'H': 'CHJSH' // Fricatives (h, ch, j, sh)
};
function handleStartButtonPressed() {
if (isGameActive) {
return;
}
isGameActive = true;
// Remove start button
if (startButtonInstance && startButtonInstance.parent) {
startButtonInstance.destroy();
startButtonInstance = null;
}
// Create and show mask
maskInstance = new Mask();
game.addChild(maskInstance);
var maskGraphicHeight = maskInstance.maskGraphics.height;
var yOffset = -50;
var maskTargetX, maskTargetY;
if (facekit.leftEye && facekit.rightEye && facekit.leftEye.x !== 0 && facekit.rightEye.x !== 0) {
maskTargetX = (facekit.leftEye.x + facekit.rightEye.x) / 2;
maskTargetY = (facekit.leftEye.y + facekit.rightEye.y) / 2 - maskGraphicHeight * 0.20 + yOffset;
} else {
maskTargetX = GAME_WIDTH / 2;
maskTargetY = GAME_HEIGHT / 3 + yOffset;
}
// Create mouth animator
mouthAnimatorInstance = new MouthAnimator();
var mouthInitialX = facekit.mouthCenter && facekit.mouthCenter.x !== 0 ? facekit.mouthCenter.x : GAME_WIDTH / 2;
var mouthInitialY = facekit.mouthCenter && facekit.mouthCenter.y !== 0 ? facekit.mouthCenter.y : GAME_HEIGHT / 2 + 200;
mouthAnimatorInstance.x = mouthInitialX;
mouthAnimatorInstance.y = mouthInitialY;
game.addChild(mouthAnimatorInstance);
// Show mask with callback to start music and lip-sync when animation completes
maskInstance.show(maskTargetX, maskTargetY, 1200);
// Start music and lip-sync after mask animation completes (1.2 seconds)
LK.setTimeout(function () {
LK.playMusic('batmansong');
if (mouthAnimatorInstance) {
// Ensure mouthAnimatorInstance still exists
mouthAnimatorInstance.startLipSync();
}
}, 1200);
}
// Initial game setup
function initializeGameScreen() {
isGameActive = false; // Reset game state
// Create and position the start button
startButtonInstance = new StartButton();
// Center the button horizontally
startButtonInstance.x = GAME_WIDTH / 2;
// Position it towards the bottom of the screen
var buttonHeight = startButtonInstance.buttonGraphics.height;
startButtonInstance.y = GAME_HEIGHT - buttonHeight / 2 - 100; // 100px padding from bottom
game.addChild(startButtonInstance);
}
// Call initial setup
initializeGameScreen();
// Game update loop
game.update = function () {
if (isGameActive) {
// Update mouth animator with enhanced tracking
if (mouthAnimatorInstance) {
// mouthAnimatorInstance.updateViseme(facekit.volume); // Viseme update is now handled by updateLipSync within MouthAnimator's update
mouthAnimatorInstance.update(); // This now includes smooth position tracking, scaling, and lip-sync
}
// Update mask with enhanced tracking
if (maskInstance) {
maskInstance.update(); // This now includes smooth position tracking and scaling
}
}
};