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
User prompt
use a variable for trollFaceOffsets[self.currentStyle - 1] in updateFacePosition
Code edit (3 edits merged)
Please save this source code
User prompt
call nextStyle with argument after loading lastStyle
User prompt
add and optional aargument in nextStyle to force the style
Code edit (4 edits merged)
Please save this source code
User prompt
use trollFaceOffsets scale information in nextStyle to multiply with baseScale
User prompt
use trollFaceOffsets scale information in updateFacePosition to multiply with baseScale
User prompt
add scale informations in trollFaceOffsets
User prompt
move baseScale and scales update into nextStyle function
Code edit (1 edits merged)
Please save this source code
Code edit (3 edits merged)
Please save this source code
User prompt
apply trollFaceOffsets to elements positions
Code edit (2 edits merged)
Please save this source code
User prompt
in trollFaceOffsets, initialize objects for each face with offset properties for each face element
User prompt
add a global array to store offsets for each element of each trollface
Code edit (4 edits merged)
Please save this source code
User prompt
remove tween animation of head scale
/**** * 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); // Properties 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 }); // 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 () { self.currentStyle = self.currentStyle % 3 + 1; self.initialize(); return self.currentStyle; }; // Update face elements to match real face self.updateFacePosition = function () { if (!facekit) { return; } // Calculate face scale once and reuse var baseScale = self.calculateFaceScale(); // Calculate all scales upfront var scales = { head: { x: baseScale * 1.25, y: baseScale * 1.25 }, eye: { x: baseScale * 1.25 * 0.5, y: baseScale * 1.25 * 0.5 }, lip: { x: baseScale * 1.25 * 0.7, y: baseScale * 1.25 * 0.35 } }; // Position the head at the center of the face if (self.elements.head) { // Head follows overall face position self.elements.head.x = 0; self.elements.head.y = 0; // Scale head based on distance between eyes if (facekit.leftEye && facekit.rightEye) { // 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 = scales.head.x; self.elements.head.scale.y = 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.elements.leftEye.y = facekit.leftEye.y - self.y; // Scale eyes based on face scale if (self.elements.head && self.elements.head.scale) { self.elements.leftEye.scale = { x: scales.eye.x, y: scales.eye.y }; // Ensure scale is an object with x and y properties } } if (self.elements.rightEye && facekit.rightEye) { self.elements.rightEye.x = facekit.rightEye.x - self.x; self.elements.rightEye.y = facekit.rightEye.y - self.y; // Scale eyes based on face scale if (self.elements.head && self.elements.head.scale) { self.elements.rightEye.scale = { x: scales.eye.x, y: scales.eye.y }; // Ensure scale is an object with x and y properties } } // 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.elements.upperLip.y = facekit.upperLip.y - self.y; // Scale upper lip based on face scale if (self.elements.head && self.elements.head.scale) { self.elements.upperLip.scale = { x: scales.lip.x, y: scales.lip.y }; // Ensure scale is an object with x and y properties } } // 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.elements.lowerLip.y = facekit.lowerLip.y - self.y; // Scale lower lip based on face scale if (self.elements.head && self.elements.head.scale) { self.elements.lowerLip.scale = { x: scales.lip.x, y: scales.lip.y }; // Ensure scale is an object with x and y properties } // Adjust lower lip height based on whether mouth is open if (facekit.mouthOpen) { self.elements.lowerLip.scale.y = scales.lip.y * 1.5; } } }; // Calculate scale based on eye distance self.calculateFaceScale = function () { if (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 targetPosition; var background; var instructionText; var styleText; var trollFace; var debugMode; var debugPoints; var backgroundContainer; var middlegroundContainer; var foregroundContainer; 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 () { // Update troll face position to match real face if (facekit && facekit.noseTip) { // Use the nose tip position for the face with easing targetPosition.x = facekit.noseTip.x; targetPosition.y = facekit.noseTip.y; // 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(); } }; 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 }); backgroundContainer.addChild(background); // Setup UI text instructionText = new Text2('Tap anywhere to change troll face', { size: 60, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0); LK.gui.top.addChild(instructionText); instructionText.y = 50; // Add style text styleText = new Text2('Style: 1/3', { size: 50, fill: 0xFFFFFF }); styleText.anchor.set(0.5, 0); LK.gui.top.addChild(styleText); styleText.y = 120; // Load the last used style from storage var lastStyle = storage.lastTrollStyle || 1; // Create the troll face trollFace = new TrollFace(); trollFace.currentStyle = lastStyle; trollFace.initialize(); middlegroundContainer.addChild(trollFace); // Set the troll face position to the center of the screen trollFace.x = 2048 / 2; trollFace.y = 2732 / 2; // Debug mode (turn on for development, off for production) debugMode = false; debugPoints = null; if (debugMode) { debugPoints = new DebugPoints(); foregroundContainer.addChild(debugPoints); } } // Initialize the game initializeGame();
/****
* 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);
// Properties
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
});
// 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 () {
self.currentStyle = self.currentStyle % 3 + 1;
self.initialize();
return self.currentStyle;
};
// Update face elements to match real face
self.updateFacePosition = function () {
if (!facekit) {
return;
}
// Calculate face scale once and reuse
var baseScale = self.calculateFaceScale();
// Calculate all scales upfront
var scales = {
head: {
x: baseScale * 1.25,
y: baseScale * 1.25
},
eye: {
x: baseScale * 1.25 * 0.5,
y: baseScale * 1.25 * 0.5
},
lip: {
x: baseScale * 1.25 * 0.7,
y: baseScale * 1.25 * 0.35
}
};
// Position the head at the center of the face
if (self.elements.head) {
// Head follows overall face position
self.elements.head.x = 0;
self.elements.head.y = 0;
// Scale head based on distance between eyes
if (facekit.leftEye && facekit.rightEye) {
// 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 = scales.head.x;
self.elements.head.scale.y = 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.elements.leftEye.y = facekit.leftEye.y - self.y;
// Scale eyes based on face scale
if (self.elements.head && self.elements.head.scale) {
self.elements.leftEye.scale = {
x: scales.eye.x,
y: scales.eye.y
}; // Ensure scale is an object with x and y properties
}
}
if (self.elements.rightEye && facekit.rightEye) {
self.elements.rightEye.x = facekit.rightEye.x - self.x;
self.elements.rightEye.y = facekit.rightEye.y - self.y;
// Scale eyes based on face scale
if (self.elements.head && self.elements.head.scale) {
self.elements.rightEye.scale = {
x: scales.eye.x,
y: scales.eye.y
}; // Ensure scale is an object with x and y properties
}
}
// 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.elements.upperLip.y = facekit.upperLip.y - self.y;
// Scale upper lip based on face scale
if (self.elements.head && self.elements.head.scale) {
self.elements.upperLip.scale = {
x: scales.lip.x,
y: scales.lip.y
}; // Ensure scale is an object with x and y properties
}
}
// 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.elements.lowerLip.y = facekit.lowerLip.y - self.y;
// Scale lower lip based on face scale
if (self.elements.head && self.elements.head.scale) {
self.elements.lowerLip.scale = {
x: scales.lip.x,
y: scales.lip.y
}; // Ensure scale is an object with x and y properties
}
// Adjust lower lip height based on whether mouth is open
if (facekit.mouthOpen) {
self.elements.lowerLip.scale.y = scales.lip.y * 1.5;
}
}
};
// Calculate scale based on eye distance
self.calculateFaceScale = function () {
if (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 targetPosition;
var background;
var instructionText;
var styleText;
var trollFace;
var debugMode;
var debugPoints;
var backgroundContainer;
var middlegroundContainer;
var foregroundContainer;
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 () {
// Update troll face position to match real face
if (facekit && facekit.noseTip) {
// Use the nose tip position for the face with easing
targetPosition.x = facekit.noseTip.x;
targetPosition.y = facekit.noseTip.y;
// 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();
}
};
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
});
backgroundContainer.addChild(background);
// Setup UI text
instructionText = new Text2('Tap anywhere to change troll face', {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
LK.gui.top.addChild(instructionText);
instructionText.y = 50;
// Add style text
styleText = new Text2('Style: 1/3', {
size: 50,
fill: 0xFFFFFF
});
styleText.anchor.set(0.5, 0);
LK.gui.top.addChild(styleText);
styleText.y = 120;
// Load the last used style from storage
var lastStyle = storage.lastTrollStyle || 1;
// Create the troll face
trollFace = new TrollFace();
trollFace.currentStyle = lastStyle;
trollFace.initialize();
middlegroundContainer.addChild(trollFace);
// Set the troll face position to the center of the screen
trollFace.x = 2048 / 2;
trollFace.y = 2732 / 2;
// Debug mode (turn on for development, off for production)
debugMode = false;
debugPoints = null;
if (debugMode) {
debugPoints = new DebugPoints();
foregroundContainer.addChild(debugPoints);
}
}
// Initialize the game
initializeGame();