Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
when bypassTracking also set scales to 1 but take into account the var trollFaceOffsets
Code edit (4 edits merged)
Please save this source code
User prompt
when bypassTracking, update all elements position but with fixed positions
User prompt
when bypassTracking, face should be placed at the center
Code edit (1 edits merged)
Please save this source code
User prompt
add a new global bypassTracking = false;
Code edit (1 edits merged)
Please save this source code
User prompt
if lastNosePosition is the same after trackingStoppedDelay ticks set isTrackingFace to false;
User prompt
Please fix the bug: 'TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 485
User prompt
if lastNosePosition is the same after trackingStoppedDelay ms set isTrackingFace to false;
Code edit (12 edits merged)
Please save this source code
User prompt
add a global variable lastNosePosition to store last facekit.noseTip.x;
Code edit (8 edits merged)
Please save this source code
User prompt
add a red screen flash when face is centered āŖš” Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
When face is no more detected return the face to the center with tween āŖš” Consider importing and using the following plugins: @upit/tween.v1
User prompt
When no face is detected return the face to the center
Code edit (12 edits merged)
Please save this source code
User prompt
in nextStyle use self.currentOffsets instead of full trollFaceOffsets[self.currentStyle - 1]
Code edit (1 edits merged)
Please save this source code
Code edit (4 edits merged)
Please save this source code
User prompt
use currentOffsets instead of trollFaceOffsets[self.currentStyle - 1] for positions updates
/****
* 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 SwitchButton = Container.expand(function () {
var self = Container.call(this);
// Create button
var buttonBackground = self.attachAsset('trollFaceButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Add text
var buttonText = new Text2('Switch', {
size: 50,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Handle press event
self.down = function (x, y, obj) {
// Scale down for press effect
tween(buttonBackground, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
};
// Handle release event
self.up = function (x, y, obj) {
// Scale back up on release
tween(buttonBackground, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
onFinish: function onFinish() {
// Trigger switch event
if (self.onSwitch) {
self.onSwitch();
}
}
});
};
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();
// 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);
// Apply position with clamping
var elementOffset = self.currentOffsets[elementName];
element.x = self.clampPosition(x, elementOffset.minX, elementOffset.maxX);
element.y = self.clampPosition(y, elementOffset.minY, elementOffset.maxY);
// 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 = {};
// 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
positions[name] = {
x: kitElement.x - self.x + self.currentOffsets[name].x,
y: kitElement.y - self.y + self.currentOffsets[name].y,
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;
}
if (bypassTracking) {
self.x = 2048 / 2;
self.y = 2732 / 2;
// Create a bypassKit object with fixed positions (similar to facekit)
var bypassKit = {
leftEye: {
x: self.x + 100,
y: self.y - 50
},
rightEye: {
x: self.x - 100,
y: self.y - 50
},
upperLip: {
x: self.x,
y: self.y + 50
},
lowerLip: {
x: self.x,
y: self.y + 100
},
mouthOpen: false
};
// Update all elements with bypassKit
self.updateAllFaceElements(bypassKit, true, true);
return;
}
// Update all elements with facekit
self.updateAllFaceElements(facekit, true, false);
};
// Calculate scale based on eye distance
self.calculateFaceScale = function () {
if (!bypassTracking && facekit && facekit.leftEye && facekit.rightEye) {
var eyeDistance = Math.sqrt(Math.pow(facekit.leftEye.x - facekit.rightEye.x, 2) + Math.pow(facekit.leftEye.y - facekit.rightEye.y, 2));
return eyeDistance / 200;
}
return 1;
};
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 = true; // Global variable to bypass face tracking
var trollFaceOffsets = [{
head: {
x: 0,
y: 0,
sx: 1,
sy: 1
},
leftEye: {
x: 150,
y: 200,
sx: 0.6,
sy: 0.6,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
rightEye: {
x: -0,
y: 200,
sx: 0.6,
sy: 0.6,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
upperLip: {
x: 0,
y: 30,
sx: 1,
sy: 1,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
lowerLip: {
x: 0,
y: 130,
sx: 1,
sy: 1,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
}
}, {
head: {
x: 0,
y: 0,
sx: 1,
sy: 1
},
leftEye: {
x: 60,
y: -18,
sx: 0.7,
sy: 0.7,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
rightEye: {
x: -60,
y: -18,
sx: 0.7,
sy: 0.7,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
upperLip: {
x: -50,
y: 80,
sx: 0.8,
sy: 0.8,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
lowerLip: {
x: 0,
y: 50,
sx: 1,
sy: 1,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
}
}, {
head: {
x: 0,
y: 0,
sx: 1,
sy: 1
},
leftEye: {
x: -55,
y: -200,
sx: 1,
sy: 1,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
rightEye: {
x: -155,
y: -200,
sx: 1,
sy: 1,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
upperLip: {
x: 0,
y: 32,
sx: 1,
sy: 1.5,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
},
lowerLip: {
x: 0,
y: 52,
sx: 1,
sy: 1.5,
minX: -200,
maxX: 200,
minY: -200,
maxY: 200
}
}]; // Global array to store offsets for each element of each trollface
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: true
});
backgroundContainer.addChild(background);
// Setup UI text
instructionText = new Text2('Tap anywhere to change troll face', {
size: 60,
fill: 0x0000FF
});
instructionText.anchor.set(0.5, 0);
LK.gui.top.addChild(instructionText);
instructionText.y = 50;
// 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);
}
}
// Initialize the game
initializeGame(); ===================================================================
--- original.js
+++ change.js
@@ -220,88 +220,127 @@
}
};
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);
+ // Apply position with clamping
+ var elementOffset = self.currentOffsets[elementName];
+ element.x = self.clampPosition(x, elementOffset.minX, elementOffset.maxX);
+ element.y = self.clampPosition(y, elementOffset.minY, elementOffset.maxY);
+ // 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 = {};
+ // 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
+ positions[name] = {
+ x: kitElement.x - self.x + self.currentOffsets[name].x,
+ y: kitElement.y - self.y + self.currentOffsets[name].y,
+ 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;
}
if (bypassTracking) {
self.x = 2048 / 2;
self.y = 2732 / 2;
- if (self.elements.head) {
- self.elements.head.x = 0;
- self.elements.head.y = 0;
- self.elements.head.scale.x = 1;
- self.elements.head.scale.y = 1;
- }
- if (self.elements.leftEye) {
- self.elements.leftEye.x = 100;
- self.elements.leftEye.y = -50;
- self.elements.leftEye.scale.x = 1 * self.currentOffsets.leftEye.sx;
- self.elements.leftEye.scale.y = 1 * self.currentOffsets.leftEye.sy;
- }
- if (self.elements.rightEye) {
- self.elements.rightEye.x = -100;
- self.elements.rightEye.y = -50;
- self.elements.rightEye.scale.x = 1 * self.currentOffsets.rightEye.sx;
- self.elements.rightEye.scale.y = 1 * self.currentOffsets.rightEye.sy;
- }
- if (self.elements.upperLip) {
- self.elements.upperLip.x = 0;
- self.elements.upperLip.y = 50;
- self.elements.upperLip.scale.x = 1 * self.currentOffsets.upperLip.sx;
- self.elements.upperLip.scale.y = 1 * self.currentOffsets.upperLip.sy;
- }
- if (self.elements.lowerLip) {
- self.elements.lowerLip.x = 0;
- self.elements.lowerLip.y = 100;
- self.elements.lowerLip.scale.x = 1 * self.currentOffsets.lowerLip.sx;
- self.elements.lowerLip.scale.y = 1 * self.currentOffsets.lowerLip.sy;
- }
+ // Create a bypassKit object with fixed positions (similar to facekit)
+ var bypassKit = {
+ leftEye: {
+ x: self.x + 100,
+ y: self.y - 50
+ },
+ rightEye: {
+ x: self.x - 100,
+ y: self.y - 50
+ },
+ upperLip: {
+ x: self.x,
+ y: self.y + 50
+ },
+ lowerLip: {
+ x: self.x,
+ y: self.y + 100
+ },
+ mouthOpen: false
+ };
+ // Update all elements with bypassKit
+ self.updateAllFaceElements(bypassKit, true, true);
return;
}
- // Use a variable for trollFaceOffsets[self.currentStyle - 1]
- // Position the head at the center of the face
- if (self.elements.head) {
- // Ensure scale is an object with x and y properties
- if (_typeof(self.elements.head.scale) !== 'object') {
- self.elements.head.scale = {
- x: 1,
- y: 1
- };
- }
- self.elements.head.scale.x = self.scales.head.x;
- self.elements.head.scale.y = self.scales.head.y;
- }
- // Position the eyes to match real eyes
- if (self.elements.leftEye && facekit.leftEye) {
- self.elements.leftEye.x = facekit.leftEye.x - self.x + self.currentOffsets.leftEye.x;
- self.elements.leftEye.y = facekit.leftEye.y - self.y + self.currentOffsets.leftEye.y;
- self.elements.leftEye.scale = self.scales.eye;
- }
- if (self.elements.rightEye && facekit.rightEye) {
- self.elements.rightEye.x = facekit.rightEye.x - self.x + self.currentOffsets.rightEye.x;
- self.elements.rightEye.y = facekit.rightEye.y - self.y + self.currentOffsets.rightEye.y;
- self.elements.rightEye.scale = self.scales.eye;
- }
- // Position the upper lip to match real upper lip
- if (self.elements.upperLip && facekit.upperLip) {
- self.elements.upperLip.x = facekit.upperLip.x - self.x + self.currentOffsets.upperLip.x;
- self.elements.upperLip.y = facekit.upperLip.y - self.y + self.currentOffsets.upperLip.y;
- self.elements.upperLip.scale = self.scales.lip;
- }
- // Position the lower lip to match real lower lip
- if (self.elements.lowerLip && facekit.lowerLip) {
- self.elements.lowerLip.x = facekit.lowerLip.x - self.x + self.currentOffsets.lowerLip.x;
- self.elements.lowerLip.y = facekit.lowerLip.y - self.y + self.currentOffsets.lowerLip.y;
- self.elements.lowerLip.scale = self.scales.lip;
- // Adjust lower lip height based on whether mouth is open
- if (facekit.mouthOpen) {
- //self.elements.lowerLip.scale.y = self.scales.lip.y * 1.5;
- }
- }
+ // Update all elements with facekit
+ self.updateAllFaceElements(facekit, true, false);
};
// Calculate scale based on eye distance
self.calculateFaceScale = function () {
if (!bypassTracking && facekit && facekit.leftEye && facekit.rightEye) {
@@ -338,27 +377,43 @@
leftEye: {
x: 150,
y: 200,
sx: 0.6,
- sy: 0.6
+ sy: 0.6,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
rightEye: {
x: -0,
y: 200,
sx: 0.6,
- sy: 0.6
+ sy: 0.6,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
upperLip: {
x: 0,
y: 30,
sx: 1,
- sy: 1
+ sy: 1,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
lowerLip: {
x: 0,
y: 130,
sx: 1,
- sy: 1
+ sy: 1,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
}
}, {
head: {
x: 0,
@@ -369,27 +424,43 @@
leftEye: {
x: 60,
y: -18,
sx: 0.7,
- sy: 0.7
+ sy: 0.7,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
rightEye: {
x: -60,
y: -18,
sx: 0.7,
- sy: 0.7
+ sy: 0.7,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
upperLip: {
- x: -150,
- y: 28 + 200,
+ x: -50,
+ y: 80,
sx: 0.8,
- sy: 0.8
+ sy: 0.8,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
lowerLip: {
- x: -150,
- y: 48 + 200,
+ x: 0,
+ y: 50,
sx: 1,
- sy: 1
+ sy: 1,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
}
}, {
head: {
x: 0,
@@ -400,27 +471,43 @@
leftEye: {
x: -55,
y: -200,
sx: 1,
- sy: 1
+ sy: 1,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
rightEye: {
x: -155,
y: -200,
sx: 1,
- sy: 1
+ sy: 1,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
upperLip: {
x: 0,
y: 32,
sx: 1,
- sy: 1.5
+ sy: 1.5,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
},
lowerLip: {
x: 0,
y: 52,
sx: 1,
- sy: 1.5
+ sy: 1.5,
+ minX: -200,
+ maxX: 200,
+ minY: -200,
+ maxY: 200
}
}]; // Global array to store offsets for each element of each trollface
var background;
var instructionText;
@@ -458,8 +545,13 @@
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
@@ -561,9 +653,9 @@
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
- visible: false
+ visible: true
});
backgroundContainer.addChild(background);
// Setup UI text
instructionText = new Text2('Tap anywhere to change troll face', {