Code edit (6 edits merged)
Please save this source code
User prompt
switch bypassTracking to true
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (17 edits merged)
Please save this source code
User prompt
switch bypassTracking to false
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
switch bypassTracking to true
Code edit (11 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'head')' in or related to this line: 'self.scales = {' Line Number: 238
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'head')' in or related to this line: 'self.scales = {' Line Number: 224
Code edit (1 edits merged)
Please save this source code
Code edit (8 edits merged)
Please save this source code
User prompt
switch bypassTracking to false
User prompt
switch bypassTracking to true
Code edit (1 edits merged)
Please save this source code
Code edit (18 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'parse')' in or related to this line: 'previousFacekit = JSON.parse(JSON.stringify(currentKit));' Line Number: 609
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'parse')' in or related to this line: 'previousFacekit = JSON.parse(JSON.stringify(currentKit));' Line Number: 600
Code edit (1 edits merged)
Please save this source code
Code edit (18 edits merged)
Please save this source code
User prompt
in debugMode, console log y, elementOffset.minY * eyeDistance, elementOffset.maxY * eyeDistance when element is lowerLip every second
User prompt
in debugMode, console log y, elementOffset.minY * eyeDistance, elementOffset.maxY * eyeDistance when element is lowerLip
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var DebugPoints = Container.expand(function () { var self = Container.call(this); // Create points for face tracking debugging self.points = { leftEye: self.attachAsset('debugFacePoints', { anchorX: 0.5, anchorY: 0.5 }), rightEye: self.attachAsset('debugFacePoints', { anchorX: 0.5, anchorY: 0.5 }), noseTip: self.attachAsset('debugFacePoints', { anchorX: 0.5, anchorY: 0.5 }), mouthCenter: self.attachAsset('debugFacePoints', { anchorX: 0.5, anchorY: 0.5 }), upperLip: self.attachAsset('debugFacePoints', { anchorX: 0.5, anchorY: 0.5 }), lowerLip: self.attachAsset('debugFacePoints', { anchorX: 0.5, anchorY: 0.5 }), chin: self.attachAsset('debugFacePoints', { anchorX: 0.5, anchorY: 0.5 }) }; // Update debug points to match face points self.update = function () { if (!facekit) { return; } if (facekit.leftEye) { self.points.leftEye.x = facekit.leftEye.x; self.points.leftEye.y = facekit.leftEye.y; } if (facekit.rightEye) { self.points.rightEye.x = facekit.rightEye.x; self.points.rightEye.y = facekit.rightEye.y; } if (facekit.noseTip) { self.points.noseTip.x = facekit.noseTip.x; self.points.noseTip.y = facekit.noseTip.y; } if (facekit.mouthCenter) { self.points.mouthCenter.x = facekit.mouthCenter.x; self.points.mouthCenter.y = facekit.mouthCenter.y; } if (facekit.upperLip) { self.points.upperLip.x = facekit.upperLip.x; self.points.upperLip.y = facekit.upperLip.y; } if (facekit.lowerLip) { self.points.lowerLip.x = facekit.lowerLip.x; self.points.lowerLip.y = facekit.lowerLip.y; } if (facekit.chin) { self.points.chin.x = facekit.chin.x; self.points.chin.y = facekit.chin.y; } }; return self; }); var TrollFace = Container.expand(function () { var self = Container.call(this); self.scales = { head: { x: 1, y: 1 }, eye: { x: 1, y: 1 }, lip: { x: 1, y: 1 } }; // Properties self.currentStyle = 1; self.currentOffsets = trollFaceOffsets[self.currentStyle - 1]; self.elements = {}; // Initialize the troll face elements self.initialize = function (style) { // Clear previous elements self.removeAllElements(); // Create new elements for the selected style self.createFaceElements(style || self.currentStyle); }; // Create face elements for a specific style self.createFaceElements = function (style) { // Create head self.elements.head = self.attachAsset('trollHead' + style, { anchorX: 0.5, anchorY: 0.5, scale: 1, alpha: 1 // DEBUG }); // Create eyes self.elements.leftEye = self.attachAsset('trollLeftEye' + style, { anchorX: 0.5, anchorY: 0.5, scale: 1 }); self.elements.rightEye = self.attachAsset('trollRightEye' + style, { anchorX: 0.5, anchorY: 0.5, scale: 1 }); // Create upper lip self.elements.upperLip = self.attachAsset('trollUpperLip' + style, { anchorX: 0.5, anchorY: 0.5, scale: 1 }); // Create lower lip self.elements.lowerLip = self.attachAsset('trollLowerLip' + style, { anchorX: 0.5, anchorY: 0.5, scale: 1 }); }; // Remove all face elements self.removeAllElements = function () { if (self.elements.head) { self.removeChild(self.elements.head); } if (self.elements.leftEye) { self.removeChild(self.elements.leftEye); } if (self.elements.rightEye) { self.removeChild(self.elements.rightEye); } if (self.elements.upperLip) { self.removeChild(self.elements.upperLip); } if (self.elements.lowerLip) { self.removeChild(self.elements.lowerLip); } }; // Change to the next troll face style self.nextStyle = function (forcedStyle) { self.currentStyle = forcedStyle || self.currentStyle % 3 + 1; self.initialize(); self.currentOffsets = trollFaceOffsets[self.currentStyle - 1]; // Calculate face scale once and reuse var baseScale = self.calculateFaceScale(facekit); // Calculate all scales upfront self.scales = { head: { x: baseScale * self.currentOffsets.head.sx, y: baseScale * self.currentOffsets.head.sy }, eye: { x: baseScale * self.currentOffsets.leftEye.sx, y: baseScale * self.currentOffsets.leftEye.sy }, lip: { x: baseScale * self.currentOffsets.upperLip.sx, y: baseScale * self.currentOffsets.upperLip.sy } }; return self.currentStyle; }; // Helper function to clamp a value between min and max self.clampPosition = function (value, min, max) { return Math.min(Math.max(value, min), max); }; // Helper function to ensure scale is an object self.ensureScaleIsObject = function (element) { if (_typeof(element.scale) !== 'object') { element.scale = { x: 1, y: 1 }; } }; // Helper function to update a face element self.updateFaceElement = function (elementName, x, y, scaleX, scaleY, makeVisible) { var element = self.elements[elementName]; if (!element) { return; } // Ensure scale is an object self.ensureScaleIsObject(element); // Get eye distance for relative positioning var kit = bypassTracking ? fakeCamera : facekit; var eyeDistance = self.getEyeDistance(kit); // Apply position with clamping using scaled boundaries var elementOffset = self.currentOffsets[elementName]; element.x = self.clampPosition(x, elementOffset.minX * eyeDistance, elementOffset.maxX * eyeDistance); element.y = self.clampPosition(y, elementOffset.minY * eyeDistance, elementOffset.maxY * eyeDistance); // Apply scale element.scale.x = scaleX; element.scale.y = scaleY; // Set visibility if needed if (makeVisible) { element.visible = true; } }; // Helper function to update all face elements self.updateAllFaceElements = function (kit, makeVisible, useDefaultScales) { var elementNames = ['head', 'leftEye', 'rightEye', 'upperLip', 'lowerLip']; var positions = {}; // Get eye distance for relative positioning var eyeDistance = self.getEyeDistance(kit); // Calculate positions for all elements positions.head = { x: 0, y: 0, scaleX: useDefaultScales ? 1 : self.scales.head.x, scaleY: useDefaultScales ? 1 : self.scales.head.y }; // For other elements, calculate based on kit positions for (var i = 1; i < elementNames.length; i++) { var name = elementNames[i]; var kitElement = kit[name]; if (kitElement) { var scaleX, scaleY; // Determine which scale to use based on element type and useDefaultScales flag if (useDefaultScales) { scaleX = 1 * self.currentOffsets[name].sx; scaleY = 1 * self.currentOffsets[name].sy; } else { if (name === 'leftEye' || name === 'rightEye') { scaleX = self.scales.eye.x; scaleY = self.scales.eye.y; } else { scaleX = self.scales.lip.x; scaleY = self.scales.lip.y; } } // Calculate position using relative offsets scaled by eye distance positions[name] = { x: kitElement.x - self.x + self.currentOffsets[name].x * eyeDistance, y: kitElement.y - self.y + self.currentOffsets[name].y * eyeDistance, scaleX: scaleX, scaleY: scaleY }; } } // Update each element with calculated positions for (var j = 0; j < elementNames.length; j++) { var elemName = elementNames[j]; if (self.elements[elemName] && positions[elemName]) { var pos = positions[elemName]; self.updateFaceElement(elemName, pos.x, pos.y, pos.scaleX, pos.scaleY, makeVisible); } } // Handle mouth open adjustment if (kit.mouthOpen && self.elements.lowerLip) { //self.elements.lowerLip.scale.y = self.scales.lip.y * 1.5; } }; // Update face elements to match real face self.updateFacePosition = function () { if (!facekit) { return; } // Recalculate scales based on the current kit var kit = bypassTracking ? fakeCamera : facekit; var baseScale = self.calculateFaceScale(kit); // Update scales self.scales = { head: { x: baseScale * self.currentOffsets.head.sx, y: baseScale * self.currentOffsets.head.sy }, eye: { x: baseScale * self.currentOffsets.leftEye.sx, y: baseScale * self.currentOffsets.leftEye.sy }, lip: { x: baseScale * self.currentOffsets.upperLip.sx, y: baseScale * self.currentOffsets.upperLip.sy } }; if (bypassTracking) { self.x = 2048 / 2; self.y = 2732 / 2; // Use the global fakeCamera with dynamic scales self.updateAllFaceElements(fakeCamera, true, false); return; } // Update all elements with facekit self.updateAllFaceElements(facekit, true, false); }; // Calculate scale based on eye distance self.calculateFaceScale = function (kit) { var eyeDistance = self.getEyeDistance(kit); return eyeDistance / 200; }; // Get eye distance from kit self.getEyeDistance = function (kit) { if (kit && kit.leftEye && kit.rightEye) { return Math.sqrt(Math.pow(kit.leftEye.x - kit.rightEye.x, 2) + Math.pow(kit.leftEye.y - kit.rightEye.y, 2)); } return 200; // Default eye distance }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xFFFFFF }); /**** * Game Code ****/ /**** * Global Variables ****/ var debugMode = true; // DEBUG MODE DEBUG MODE DEBUG MODE var bypassTracking = false; // Global variable to bypass face tracking var trollFaceOffsets = [{ head: { x: 0, y: 0, sx: 1, sy: 1 }, leftEye: { x: 0.75, // 150/200 = 0.75 y: 1.0, // 200/200 = 1.0 sx: 0.6, sy: 0.6, minX: -1.0, // -200/200 = -1.0 maxX: 1.0, // 200/200 = 1.0 minY: -1.0, maxY: 1.0 }, rightEye: { x: 0, // 0/200 = 0 y: 1.0, // 200/200 = 1.0 sx: 0.6, sy: 0.6, minX: -1.0, maxX: 1.0, minY: -1.0, maxY: 1.0 }, upperLip: { x: 0, // 0/200 = 0 y: 0.15, // 30/200 = 0.15 sx: 1, sy: 1, minX: -1.0, maxX: 1.0, minY: -1.0, maxY: 1.0 }, lowerLip: { x: 0, // 0/200 = 0 y: 0.65, // 130/200 = 0.65 sx: 1, sy: 1, minX: -1.0, maxX: 1.0, minY: -1.0, maxY: 1.0 } }, { head: { x: 0, y: 0, sx: 1, sy: 1 }, leftEye: { x: 0, y: 0.5, sx: 0.6, sy: 0.6, minX: 0.2, maxX: 0.7, minY: 0, maxY: 0.6 }, rightEye: { x: 0.1, y: 0.3, sx: 0.6, sy: 0.6, minX: -0.7, maxX: 0, minY: 0, maxY: 0.4 }, upperLip: { x: -0.2, y: 0.25, sx: 0.5, sy: 0.5, minX: -0.3, maxX: -0.1, minY: -1, maxY: 1 }, lowerLip: { x: -0.10, y: 0.27, sx: 0.2, sy: 0.2, minX: -0.2, maxX: 0, minY: -1, maxY: 1 } }, { head: { x: 0, y: 0, sx: 1, sy: 1 }, leftEye: { x: -0.275, // -55/200 = -0.275 y: -1.0, // -200/200 = -1.0 sx: 1, sy: 1, minX: -1.0, maxX: 1.0, minY: -1.0, maxY: 1.0 }, rightEye: { x: -0.775, // -155/200 = -0.775 y: -1.0, // -200/200 = -1.0 sx: 1, sy: 1, minX: -1.0, maxX: 1.0, minY: -1.0, maxY: 1.0 }, upperLip: { x: 0, // 0/200 = 0 y: 0.16, // 32/200 = 0.16 sx: 1, sy: 1.5, minX: -1.0, maxX: 1.0, minY: -1.0, maxY: 1.0 }, lowerLip: { x: 0, // 0/200 = 0 y: 0.26, // 52/200 = 0.26 sx: 1, sy: 1.5, minX: -1.0, maxX: 1.0, minY: -1.0, maxY: 1.0 } }]; // Define fakeCamera globally with fixed positions for testing var fakeCamera = { leftEye: { x: 1380, y: 958 }, rightEye: { x: 673, y: 970 }, upperLip: { x: 1027, y: 1610 }, lowerLip: { x: 1030, y: 1613 }, mouthOpen: false }; // Global object for bypass tracking mode var background; var instructionText; var styleText; var trollFace; var debugPoints; var backgroundContainer; var middlegroundContainer; var foregroundContainer; var isTrackingFace = false; // Global flag to track face detection state var targetPosition; var lastNosePosition = null; // Global variable to store last facekit.noseTip.x var trackingStoppedDelay = 100; var trackingStoppedCounter = trackingStoppedDelay; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } /**** * Game Functions ****/ // Handle tap anywhere on the screen to change face game.down = function (x, y, obj) { // Switch to the next troll face style var newStyle = trollFace.nextStyle(); // Save the current style to storage storage.lastTrollStyle = newStyle; // Update the style text styleText.setText('Style: ' + newStyle + '/3'); // Play switch sound LK.getSound('switchTroll').play(); }; // Update function called every frame game.update = function () { if (bypassTracking) { // When bypassing tracking, position the troll face at the center and update its elements trollFace.updateFacePosition(); return; } if (!facekit || !facekit.noseTip) { return; } // Check if lastNosePosition is the same after trackingStoppedDelay ticks if (lastNosePosition === facekit.noseTip.x) { trackingStoppedCounter--; if (trackingStoppedCounter <= 0) { isTrackingFace = false; instructionText.setText("Stopped tracking"); trackingStoppedCounter = trackingStoppedDelay; // Reset delay } } else { isTrackingFace = true; lastNosePosition = facekit.noseTip.x; instructionText.setText("Tracking..."); trackingStoppedCounter = trackingStoppedDelay; // Reset delay } // Update troll face position to match real face if (isTrackingFace) { // Use the nose tip position for the face with easing targetPosition.x = facekit.noseTip.x; targetPosition.y = facekit.noseTip.y; trollFace.x = targetPosition.x; trollFace.y = targetPosition.y; trollFace.isTweening = true; // TEMP DEBUG // Apply tweening for smooth movement and wait for it to finish before starting the next // if (!trollFace.isTweening) { // trollFace.isTweening = true; // tween(trollFace, { // x: targetPosition.x, // y: targetPosition.y // }, { // duration: 300, // easing: tween.easeInOut, // onFinish: function onFinish() { // trollFace.isTweening = false; // } // }); // } // Update face elements to match real face features trollFace.updateFacePosition(); trollFace.isCentered = false; trollFace.isCentering = false; // Update face tracking state if (!isTrackingFace) { isTrackingFace = true; instructionText.setText("Tracking..." + new Date()); console.log("facekit", facekit); } //console.log("noseTip x=", facekit.noseTip.x); } else { // If face is not detected, return the face to the center if (!trollFace.isCentered) { if (trollFace.isCentering) { // Don't exit the update function, just skip starting a new tween // This allows other updates to continue // Continue updating face elements during centering trollFace.updateFacePosition(); } else { trollFace.isCentering = true; LK.effects.flashScreen(0xFFFFFF, 1000); // Flash screen tween(trollFace, { x: 2048 / 2, y: 2732 / 2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { trollFace.isCentered = true; trollFace.isCentering = false; trollFace.updateFacePosition(); } }); } } // Update face tracking state if (isTrackingFace) { isTrackingFace = false; instructionText.setText("No Face found"); } } }; function initializeGame() { // Initialize game // Create containers for layering backgroundContainer = new Container(); middlegroundContainer = new Container(); foregroundContainer = new Container(); // Add containers to game game.addChild(backgroundContainer); game.addChild(middlegroundContainer); game.addChild(foregroundContainer); // Global target position for the troll face targetPosition = { x: 2048 / 2, y: 2732 / 2 }; // Setup background background = LK.getAsset('whiteBackground', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, visible: false }); backgroundContainer.addChild(background); // Setup UI text instructionText = new Text2('Tap anywhere to change troll face', { size: 50, fill: 0xFF0000 }); instructionText.anchor.set(0.5, 0); LK.gui.top.addChild(instructionText); instructionText.y = 1700; // Load the last used style from storage var lastStyle = storage.lastTrollStyle || 1; // Create the troll face trollFace = new TrollFace(); trollFace.currentStyle = lastStyle; trollFace.initialize(); trollFace.nextStyle(lastStyle); middlegroundContainer.addChild(trollFace); // Set the troll face position to the center of the screen trollFace.x = 2048 / 2; trollFace.y = 2732 / 2; // Initialize tracking state isTrackingFace = false; // Add style text styleText = new Text2('Style: ' + lastStyle + '/3', { size: 50, fill: 0xFF0000 }); styleText.anchor.set(0.5, 0); LK.gui.top.addChild(styleText); styleText.y = 120; // Debug mode (turn on for development, off for production) debugPoints = null; if (debugMode) { debugPoints = new DebugPoints(); foregroundContainer.addChild(debugPoints); // Log facekit to console every second LK.setInterval(function () { console.log(facekit); if (facekit.lowerLip) { var elementOffset = trollFace.currentOffsets.lowerLip; var eyeDistance = trollFace.getEyeDistance(facekit); console.log("lowerLip y:", facekit.lowerLip.y, "minY:", elementOffset.minY * eyeDistance, "maxY:", elementOffset.maxY * eyeDistance); } instructionText.setText("le:".concat(Math.round(facekit.leftEye.x), ",").concat(Math.round(facekit.leftEye.y), " / ") + "re:".concat(Math.round(facekit.rightEye.x), ",").concat(Math.round(facekit.rightEye.y), " / ") + "ul:".concat(Math.round(facekit.upperLip.x), ",").concat(Math.round(facekit.upperLip.y), " / ") + "ll:".concat(Math.round(facekit.lowerLip.x), ",").concat(Math.round(facekit.lowerLip.y))); }, 1000); } } // Initialize the game initializeGame();
===================================================================
--- original.js
+++ change.js
@@ -400,40 +400,40 @@
x: 0,
y: 0.5,
sx: 0.6,
sy: 0.6,
- minX: -1.0,
- maxX: 1.0,
- minY: -1.0,
- maxY: 1.0
+ minX: 0.2,
+ maxX: 0.7,
+ minY: 0,
+ maxY: 0.6
},
rightEye: {
x: 0.1,
y: 0.3,
sx: 0.6,
sy: 0.6,
- minX: -1.0,
- maxX: 1.0,
- minY: -1.0,
- maxY: 1.0
+ minX: -0.7,
+ maxX: 0,
+ minY: 0,
+ maxY: 0.4
},
upperLip: {
x: -0.2,
y: 0.25,
sx: 0.5,
sy: 0.5,
- minX: -1,
- maxX: 1,
+ minX: -0.3,
+ maxX: -0.1,
minY: -1,
maxY: 1
},
lowerLip: {
x: -0.10,
y: 0.27,
sx: 0.2,
sy: 0.2,
- minX: -10.0,
- maxX: 10.0,
+ minX: -0.2,
+ maxX: 0,
minY: -1,
maxY: 1
}
}, {