/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
unlockedFilters: ["normal", "grayscale"],
coins: 0,
highestRating: 0
});
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Button = Container.expand(function (text, width, height) {
var self = Container.call(this);
var background = self.attachAsset('button', {
width: width || 300,
height: height || 100,
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2(text, {
size: 50,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.setEnabled = function (enabled) {
self.interactive = enabled;
background.alpha = enabled ? 1.0 : 0.5;
};
self.down = function (x, y, obj) {
tween(background, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(background, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
};
self.setText = function (newText) {
label.setText(newText);
};
return self;
});
var EffectIndicator = Container.expand(function () {
var self = Container.call(this);
var circle = self.attachAsset('effectIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2("π΅", {
size: 50,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.pulse = function (strength) {
var targetScale = 0.8 + strength * 0.5;
tween(self, {
scaleX: targetScale,
scaleY: targetScale
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
};
return self;
});
var FilterPreview = Container.expand(function (filterId, filterName) {
var self = Container.call(this);
self.filterId = filterId;
var background = self.attachAsset('filterPreview', {
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2(filterName, {
size: 30,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
label.y = 90;
self.addChild(label);
self.setSelected = function (selected) {
background.tint = selected ? 0x3498db : 0xcccccc;
};
self.setLocked = function (locked) {
self.interactive = !locked;
self.alpha = locked ? 0.5 : 1.0;
if (locked) {
var lockIcon = new Text2("π", {
size: 60,
fill: 0xFFFFFF
});
lockIcon.anchor.set(0.5, 0.5);
self.addChild(lockIcon);
} else {
// Remove lock icon if it exists
for (var i = self.children.length - 1; i >= 0; i--) {
if (self.children[i] instanceof Text2 && self.children[i].text === "π") {
self.removeChild(self.children[i]);
break;
}
}
}
};
self.down = function (x, y, obj) {
tween(background, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(background, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
};
return self;
});
var Judge = Container.expand(function (judgeName) {
var self = Container.call(this);
var background = self.attachAsset('judgeBackground', {
anchorX: 0.5,
anchorY: 0.5
});
var nameLabel = new Text2(judgeName, {
size: 40,
fill: 0xFFFFFF
});
nameLabel.anchor.set(0.5, 0);
nameLabel.y = -120;
self.addChild(nameLabel);
var commentLabel = new Text2("", {
size: 35,
fill: 0xFFFFFF
});
commentLabel.anchor.set(0.5, 0);
commentLabel.y = -60;
self.addChild(commentLabel);
// Create stars
self.stars = [];
for (var i = 0; i < 5; i++) {
var star = new RatingStar();
star.x = (i - 2) * 90;
star.y = 60;
self.addChild(star);
self.stars.push(star);
}
self.setRating = function (rating) {
for (var i = 0; i < 5; i++) {
self.stars[i].setFilled(i < rating);
if (i < rating) {
// Delay the animation for each star
(function (index) {
LK.setTimeout(function () {
self.stars[index].animateStar();
}, 200 * index);
})(i);
}
}
};
self.setComment = function (comment) {
commentLabel.setText(comment);
};
self.animateEntrance = function (delay) {
self.alpha = 0;
self.y = 100;
LK.setTimeout(function () {
tween(self, {
alpha: 1,
y: 0
}, {
duration: 500,
easing: tween.easeOut
});
}, delay);
};
return self;
});
var RatingStar = Container.expand(function () {
var self = Container.call(this);
var emptyStarGraphic = self.attachAsset('ratingStarEmpty', {
anchorX: 0.5,
anchorY: 0.5
});
var filledStarGraphic = self.attachAsset('ratingStarFilled', {
anchorX: 0.5,
anchorY: 0.5
});
filledStarGraphic.alpha = 0;
self.setFilled = function (filled) {
emptyStarGraphic.alpha = filled ? 0 : 1;
filledStarGraphic.alpha = filled ? 1 : 0;
};
self.animateStar = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Game states
var STATE_CAMERA = "camera";
var STATE_REVIEW = "review";
var currentState = STATE_CAMERA;
// Current filter settings
var currentFilter = "normal";
var availableFilters = [{
id: "normal",
name: "Normal",
unlockRating: 0
}, {
id: "grayscale",
name: "Grayscale",
unlockRating: 0
}, {
id: "sepia",
name: "Sepia",
unlockRating: 2
}, {
id: "vibrant",
name: "Vibrant",
unlockRating: 3
}, {
id: "blur",
name: "Blur",
unlockRating: 3.5
}, {
id: "pixelate",
name: "Pixelate",
unlockRating: 4
}, {
id: "rainbow",
name: "Rainbow",
unlockRating: 4.5
}];
// Judge configurations
var judges = [{
name: "Alex",
comments: {
1: "Not feeling it...",
2: "Has potential.",
3: "Pretty good!",
4: "Very creative!",
5: "Absolute perfection!"
}
}, {
name: "Taylor",
comments: {
1: "Needs work...",
2: "Getting better!",
3: "Nice effort!",
4: "Love the style!",
5: "Outstanding!"
}
}, {
name: "Jordan",
comments: {
1: "Try again...",
2: "Almost there.",
3: "Good composition!",
4: "Excellent work!",
5: "Masterpiece!"
}
}];
// Last detected voice volume for effects
var lastVoiceVolume = 0;
var voiceEffectThreshold = 0.3;
var voiceEffectActive = false;
// Create coin display
var coinText = new Text2("Coins: " + storage.coins, {
size: 60,
fill: 0xFFFFFF
});
coinText.anchor.set(0.5, 0.5);
coinText.x = 2048 - 150;
coinText.y = 100;
game.addChild(coinText);
// Create UI elements
var cameraFrame = game.addChild(LK.getAsset('cameraFrame', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0.2
}));
// Create filter selector container
var filterContainer = new Container();
filterContainer.y = 2732 - 200;
game.addChild(filterContainer);
// Create filter previews
var filterPreviews = {};
var filterPreviewWidth = 170;
var totalFiltersWidth = availableFilters.length * filterPreviewWidth;
var startX = (2048 - totalFiltersWidth) / 2 + filterPreviewWidth / 2;
availableFilters.forEach(function (filter, index) {
var preview = new FilterPreview(filter.id, filter.name);
preview.x = startX + index * filterPreviewWidth;
preview.y = 0;
var isUnlocked = storage.unlockedFilters.indexOf(filter.id) !== -1;
preview.setLocked(!isUnlocked);
preview.setSelected(filter.id === currentFilter);
filterContainer.addChild(preview);
filterPreviews[filter.id] = preview;
});
// Create capture button
var captureButton = new Button("Take Selfie", 400, 100);
captureButton.x = 2048 / 2;
captureButton.y = 2732 - 400;
game.addChild(captureButton);
// Create effect indicator
var effectIndicator = new EffectIndicator();
effectIndicator.x = 2048 - 150;
effectIndicator.y = 150;
effectIndicator.alpha = 0.7;
game.addChild(effectIndicator);
// Create judge container for ratings
var judgeContainer = new Container();
judgeContainer.x = 2048 / 2;
judgeContainer.y = 2732 / 2;
judgeContainer.visible = false;
game.addChild(judgeContainer);
// Create judges
var judgeObjects = [];
judges.forEach(function (judgeData, index) {
var judge = new Judge(judgeData.name);
judge.y = index * 350 - 350;
judgeContainer.addChild(judge);
judgeObjects.push(judge);
});
// Create return button for after ratings
var returnButton = new Button("New Selfie", 400, 100);
returnButton.x = 2048 / 2;
returnButton.y = 2732 - 200;
returnButton.visible = false;
game.addChild(returnButton);
// Current ratings info
var currentRatings = [];
var averageRatingText = new Text2("", {
size: 80,
fill: 0xFFFFFF
});
averageRatingText.anchor.set(0.5, 0.5);
averageRatingText.x = 2048 / 2;
averageRatingText.y = 200;
averageRatingText.visible = false;
game.addChild(averageRatingText);
// Function to switch between camera and review states
function switchToState(newState) {
currentState = newState;
if (newState === STATE_CAMERA) {
cameraFrame.visible = true;
filterContainer.visible = true;
captureButton.visible = true;
judgeContainer.visible = false;
returnButton.visible = false;
averageRatingText.visible = false;
// Reset any effects
voiceEffectActive = false;
// Start background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
} else if (newState === STATE_REVIEW) {
cameraFrame.visible = false;
filterContainer.visible = false;
captureButton.visible = false;
judgeContainer.visible = true;
returnButton.visible = true;
averageRatingText.visible = true;
// Generate random ratings from judges
generateRatings();
// Stop background music
LK.stopMusic();
// Play applause sound
LK.getSound('applause').play();
}
}
// Function to handle filter selection
function selectFilter(filterId) {
if (currentFilter === filterId) {
return;
}
// Deselect current filter
filterPreviews[currentFilter].setSelected(false);
// Set and select new filter
currentFilter = filterId;
filterPreviews[currentFilter].setSelected(true);
// Apply the selected filter using facekit
switch (filterId) {
case "normal":
facekit.applyFilter("normal");
break;
case "grayscale":
facekit.applyFilter("grayscale");
break;
case "sepia":
facekit.applyFilter("sepia");
break;
case "vibrant":
facekit.applyFilter("vibrant");
break;
case "blur":
facekit.applyFilter("blur");
break;
case "pixelate":
facekit.applyFilter("pixelate");
break;
case "rainbow":
facekit.applyFilter("rainbow");
break;
}
}
// Generate ratings from judges
function generateRatings() {
currentRatings = [];
var totalRating = 0;
// Reset judges and prepare for animation
judgeObjects.forEach(function (judge) {
judge.setRating(0);
judge.setComment("");
});
// Generate a rating for each judge
judges.forEach(function (judgeData, index) {
// Base rating is random but weighted toward the middle
var baseRating = Math.floor(Math.random() * 3) + 2; // 2-4
// Use coins to increase the chance of getting a higher rating
if (storage.coins >= 10) {
var chanceBoost = Math.random();
if (chanceBoost > 0.5) {
baseRating += 1; // Increase base rating by 1
storage.coins -= 10; // Deduct 10 coins for the boost
console.log("Used 10 coins for a rating boost. Remaining coins: " + storage.coins);
}
}
// Adjust based on current filter (bonus for using advanced filters)
var filterIndex = availableFilters.findIndex(function (f) {
return f.id === currentFilter;
});
var filterBonus = filterIndex / 10; // Small bonus for advanced filters
// Calculate final rating (1-5)
var finalRating = Math.min(5, Math.max(1, Math.round(baseRating + filterBonus)));
currentRatings.push(finalRating);
totalRating += finalRating;
// Set rating and comment with delay
(function (judgeObj, rating, comments) {
var delay = 1000 + index * 1000; // Stagger judges' responses
LK.setTimeout(function () {
judgeObj.animateEntrance(0);
judgeObj.setRating(rating);
judgeObj.setComment(comments[rating]);
LK.getSound('judgeComment').play();
}, delay);
})(judgeObjects[index], finalRating, judgeData.comments);
});
// Calculate and display average rating
var averageRating = totalRating / judges.length;
// Award coins based on average rating
var coinsEarned = Math.round(averageRating * 10); // Earn 10 coins per star
storage.coins = (storage.coins || 0) + coinsEarned;
console.log("Coins earned: " + coinsEarned + ", Total coins: " + storage.coins);
coinText.setText("Coins: " + storage.coins); // Update coin display
// Update the highest rating if this is better
if (averageRating > storage.highestRating) {
storage.highestRating = averageRating;
// Unlock new filters based on rating
availableFilters.forEach(function (filter) {
if (filter.unlockRating <= averageRating && storage.unlockedFilters.indexOf(filter.id) === -1) {
storage.unlockedFilters.push(filter.id);
}
});
}
// Display average rating
LK.setTimeout(function () {
averageRatingText.setText("Rating: " + averageRating.toFixed(1) + " / 5.0");
averageRatingText.alpha = 0;
averageRatingText.visible = true;
tween(averageRatingText, {
alpha: 1
}, {
duration: 500
});
}, 4000);
}
// Handle touch events for game elements
game.down = function (x, y, obj) {
// Handle filter selection
if (currentState === STATE_CAMERA) {
for (var filterId in filterPreviews) {
var preview = filterPreviews[filterId];
if (preview.interactive && preview.getBounds().contains(x, y)) {
selectFilter(filterId);
return;
}
}
}
};
// Capture button event handler
captureButton.down = function (x, y, obj) {
if (currentState !== STATE_CAMERA) {
return;
}
// Play camera click sound
LK.getSound('cameraClick').play();
// Flash screen effect
LK.effects.flashScreen(0xffffff, 500);
// Switch to review mode after a short delay
LK.setTimeout(function () {
switchToState(STATE_REVIEW);
}, 600);
};
// Return button event handler
returnButton.down = function (x, y, obj) {
if (currentState !== STATE_REVIEW) {
return;
}
// Deduct 10 coins if player has 10 or more coins
if (storage.coins >= 10) {
storage.coins -= 10;
console.log("Spent 10 coins for a new selfie. Remaining coins: " + storage.coins);
coinText.setText("Coins: " + storage.coins); // Update coin display
}
// Update filter previews to show newly unlocked filters
availableFilters.forEach(function (filter) {
var preview = filterPreviews[filter.id];
var isUnlocked = storage.unlockedFilters.indexOf(filter.id) !== -1;
preview.setLocked(!isUnlocked);
});
// Switch back to camera mode
switchToState(STATE_CAMERA);
};
// Game update function
game.update = function () {
// Handle voice-activated effects in camera mode
if (currentState === STATE_CAMERA) {
// Detect voice volume changes
var volume = facekit.volume;
// Update effect indicator based on current volume
if (volume > lastVoiceVolume && volume > voiceEffectThreshold) {
effectIndicator.pulse(volume);
// Activate voice effect if over threshold
if (volume > voiceEffectThreshold && !voiceEffectActive) {
voiceEffectActive = true;
// Apply random effect when voice detected
var effect = Math.floor(Math.random() * 3);
// Effects could include:
// 1. Temporary color flash
// 2. Scale animation
// 3. Rotation effect
switch (effect) {
case 0:
// Temporary color tint
var randomColor = Math.random() * 0xFFFFFF;
cameraFrame.tint = randomColor;
LK.setTimeout(function () {
tween(cameraFrame, {
tint: 0xFFFFFF
}, {
duration: 500
});
}, 500);
break;
case 1:
// Scale animation
tween(cameraFrame, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 300,
onFinish: function onFinish() {
tween(cameraFrame, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 400
});
}
});
break;
case 2:
// Rotation effect
var startRotation = cameraFrame.rotation;
var targetRotation = startRotation + Math.PI * 0.1;
tween(cameraFrame, {
rotation: targetRotation
}, {
duration: 300,
onFinish: function onFinish() {
tween(cameraFrame, {
rotation: startRotation
}, {
duration: 400
});
}
});
break;
}
}
} else if (volume < voiceEffectThreshold && voiceEffectActive) {
// Reset voice effect flag when volume drops
voiceEffectActive = false;
}
lastVoiceVolume = volume;
}
};
// Start with camera state
switchToState(STATE_CAMERA); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
unlockedFilters: ["normal", "grayscale"],
coins: 0,
highestRating: 0
});
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Button = Container.expand(function (text, width, height) {
var self = Container.call(this);
var background = self.attachAsset('button', {
width: width || 300,
height: height || 100,
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2(text, {
size: 50,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.setEnabled = function (enabled) {
self.interactive = enabled;
background.alpha = enabled ? 1.0 : 0.5;
};
self.down = function (x, y, obj) {
tween(background, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(background, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
};
self.setText = function (newText) {
label.setText(newText);
};
return self;
});
var EffectIndicator = Container.expand(function () {
var self = Container.call(this);
var circle = self.attachAsset('effectIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2("π΅", {
size: 50,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.pulse = function (strength) {
var targetScale = 0.8 + strength * 0.5;
tween(self, {
scaleX: targetScale,
scaleY: targetScale
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
};
return self;
});
var FilterPreview = Container.expand(function (filterId, filterName) {
var self = Container.call(this);
self.filterId = filterId;
var background = self.attachAsset('filterPreview', {
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2(filterName, {
size: 30,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
label.y = 90;
self.addChild(label);
self.setSelected = function (selected) {
background.tint = selected ? 0x3498db : 0xcccccc;
};
self.setLocked = function (locked) {
self.interactive = !locked;
self.alpha = locked ? 0.5 : 1.0;
if (locked) {
var lockIcon = new Text2("π", {
size: 60,
fill: 0xFFFFFF
});
lockIcon.anchor.set(0.5, 0.5);
self.addChild(lockIcon);
} else {
// Remove lock icon if it exists
for (var i = self.children.length - 1; i >= 0; i--) {
if (self.children[i] instanceof Text2 && self.children[i].text === "π") {
self.removeChild(self.children[i]);
break;
}
}
}
};
self.down = function (x, y, obj) {
tween(background, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
};
self.up = function (x, y, obj) {
tween(background, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
};
return self;
});
var Judge = Container.expand(function (judgeName) {
var self = Container.call(this);
var background = self.attachAsset('judgeBackground', {
anchorX: 0.5,
anchorY: 0.5
});
var nameLabel = new Text2(judgeName, {
size: 40,
fill: 0xFFFFFF
});
nameLabel.anchor.set(0.5, 0);
nameLabel.y = -120;
self.addChild(nameLabel);
var commentLabel = new Text2("", {
size: 35,
fill: 0xFFFFFF
});
commentLabel.anchor.set(0.5, 0);
commentLabel.y = -60;
self.addChild(commentLabel);
// Create stars
self.stars = [];
for (var i = 0; i < 5; i++) {
var star = new RatingStar();
star.x = (i - 2) * 90;
star.y = 60;
self.addChild(star);
self.stars.push(star);
}
self.setRating = function (rating) {
for (var i = 0; i < 5; i++) {
self.stars[i].setFilled(i < rating);
if (i < rating) {
// Delay the animation for each star
(function (index) {
LK.setTimeout(function () {
self.stars[index].animateStar();
}, 200 * index);
})(i);
}
}
};
self.setComment = function (comment) {
commentLabel.setText(comment);
};
self.animateEntrance = function (delay) {
self.alpha = 0;
self.y = 100;
LK.setTimeout(function () {
tween(self, {
alpha: 1,
y: 0
}, {
duration: 500,
easing: tween.easeOut
});
}, delay);
};
return self;
});
var RatingStar = Container.expand(function () {
var self = Container.call(this);
var emptyStarGraphic = self.attachAsset('ratingStarEmpty', {
anchorX: 0.5,
anchorY: 0.5
});
var filledStarGraphic = self.attachAsset('ratingStarFilled', {
anchorX: 0.5,
anchorY: 0.5
});
filledStarGraphic.alpha = 0;
self.setFilled = function (filled) {
emptyStarGraphic.alpha = filled ? 0 : 1;
filledStarGraphic.alpha = filled ? 1 : 0;
};
self.animateStar = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Game states
var STATE_CAMERA = "camera";
var STATE_REVIEW = "review";
var currentState = STATE_CAMERA;
// Current filter settings
var currentFilter = "normal";
var availableFilters = [{
id: "normal",
name: "Normal",
unlockRating: 0
}, {
id: "grayscale",
name: "Grayscale",
unlockRating: 0
}, {
id: "sepia",
name: "Sepia",
unlockRating: 2
}, {
id: "vibrant",
name: "Vibrant",
unlockRating: 3
}, {
id: "blur",
name: "Blur",
unlockRating: 3.5
}, {
id: "pixelate",
name: "Pixelate",
unlockRating: 4
}, {
id: "rainbow",
name: "Rainbow",
unlockRating: 4.5
}];
// Judge configurations
var judges = [{
name: "Alex",
comments: {
1: "Not feeling it...",
2: "Has potential.",
3: "Pretty good!",
4: "Very creative!",
5: "Absolute perfection!"
}
}, {
name: "Taylor",
comments: {
1: "Needs work...",
2: "Getting better!",
3: "Nice effort!",
4: "Love the style!",
5: "Outstanding!"
}
}, {
name: "Jordan",
comments: {
1: "Try again...",
2: "Almost there.",
3: "Good composition!",
4: "Excellent work!",
5: "Masterpiece!"
}
}];
// Last detected voice volume for effects
var lastVoiceVolume = 0;
var voiceEffectThreshold = 0.3;
var voiceEffectActive = false;
// Create coin display
var coinText = new Text2("Coins: " + storage.coins, {
size: 60,
fill: 0xFFFFFF
});
coinText.anchor.set(0.5, 0.5);
coinText.x = 2048 - 150;
coinText.y = 100;
game.addChild(coinText);
// Create UI elements
var cameraFrame = game.addChild(LK.getAsset('cameraFrame', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0.2
}));
// Create filter selector container
var filterContainer = new Container();
filterContainer.y = 2732 - 200;
game.addChild(filterContainer);
// Create filter previews
var filterPreviews = {};
var filterPreviewWidth = 170;
var totalFiltersWidth = availableFilters.length * filterPreviewWidth;
var startX = (2048 - totalFiltersWidth) / 2 + filterPreviewWidth / 2;
availableFilters.forEach(function (filter, index) {
var preview = new FilterPreview(filter.id, filter.name);
preview.x = startX + index * filterPreviewWidth;
preview.y = 0;
var isUnlocked = storage.unlockedFilters.indexOf(filter.id) !== -1;
preview.setLocked(!isUnlocked);
preview.setSelected(filter.id === currentFilter);
filterContainer.addChild(preview);
filterPreviews[filter.id] = preview;
});
// Create capture button
var captureButton = new Button("Take Selfie", 400, 100);
captureButton.x = 2048 / 2;
captureButton.y = 2732 - 400;
game.addChild(captureButton);
// Create effect indicator
var effectIndicator = new EffectIndicator();
effectIndicator.x = 2048 - 150;
effectIndicator.y = 150;
effectIndicator.alpha = 0.7;
game.addChild(effectIndicator);
// Create judge container for ratings
var judgeContainer = new Container();
judgeContainer.x = 2048 / 2;
judgeContainer.y = 2732 / 2;
judgeContainer.visible = false;
game.addChild(judgeContainer);
// Create judges
var judgeObjects = [];
judges.forEach(function (judgeData, index) {
var judge = new Judge(judgeData.name);
judge.y = index * 350 - 350;
judgeContainer.addChild(judge);
judgeObjects.push(judge);
});
// Create return button for after ratings
var returnButton = new Button("New Selfie", 400, 100);
returnButton.x = 2048 / 2;
returnButton.y = 2732 - 200;
returnButton.visible = false;
game.addChild(returnButton);
// Current ratings info
var currentRatings = [];
var averageRatingText = new Text2("", {
size: 80,
fill: 0xFFFFFF
});
averageRatingText.anchor.set(0.5, 0.5);
averageRatingText.x = 2048 / 2;
averageRatingText.y = 200;
averageRatingText.visible = false;
game.addChild(averageRatingText);
// Function to switch between camera and review states
function switchToState(newState) {
currentState = newState;
if (newState === STATE_CAMERA) {
cameraFrame.visible = true;
filterContainer.visible = true;
captureButton.visible = true;
judgeContainer.visible = false;
returnButton.visible = false;
averageRatingText.visible = false;
// Reset any effects
voiceEffectActive = false;
// Start background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});
} else if (newState === STATE_REVIEW) {
cameraFrame.visible = false;
filterContainer.visible = false;
captureButton.visible = false;
judgeContainer.visible = true;
returnButton.visible = true;
averageRatingText.visible = true;
// Generate random ratings from judges
generateRatings();
// Stop background music
LK.stopMusic();
// Play applause sound
LK.getSound('applause').play();
}
}
// Function to handle filter selection
function selectFilter(filterId) {
if (currentFilter === filterId) {
return;
}
// Deselect current filter
filterPreviews[currentFilter].setSelected(false);
// Set and select new filter
currentFilter = filterId;
filterPreviews[currentFilter].setSelected(true);
// Apply the selected filter using facekit
switch (filterId) {
case "normal":
facekit.applyFilter("normal");
break;
case "grayscale":
facekit.applyFilter("grayscale");
break;
case "sepia":
facekit.applyFilter("sepia");
break;
case "vibrant":
facekit.applyFilter("vibrant");
break;
case "blur":
facekit.applyFilter("blur");
break;
case "pixelate":
facekit.applyFilter("pixelate");
break;
case "rainbow":
facekit.applyFilter("rainbow");
break;
}
}
// Generate ratings from judges
function generateRatings() {
currentRatings = [];
var totalRating = 0;
// Reset judges and prepare for animation
judgeObjects.forEach(function (judge) {
judge.setRating(0);
judge.setComment("");
});
// Generate a rating for each judge
judges.forEach(function (judgeData, index) {
// Base rating is random but weighted toward the middle
var baseRating = Math.floor(Math.random() * 3) + 2; // 2-4
// Use coins to increase the chance of getting a higher rating
if (storage.coins >= 10) {
var chanceBoost = Math.random();
if (chanceBoost > 0.5) {
baseRating += 1; // Increase base rating by 1
storage.coins -= 10; // Deduct 10 coins for the boost
console.log("Used 10 coins for a rating boost. Remaining coins: " + storage.coins);
}
}
// Adjust based on current filter (bonus for using advanced filters)
var filterIndex = availableFilters.findIndex(function (f) {
return f.id === currentFilter;
});
var filterBonus = filterIndex / 10; // Small bonus for advanced filters
// Calculate final rating (1-5)
var finalRating = Math.min(5, Math.max(1, Math.round(baseRating + filterBonus)));
currentRatings.push(finalRating);
totalRating += finalRating;
// Set rating and comment with delay
(function (judgeObj, rating, comments) {
var delay = 1000 + index * 1000; // Stagger judges' responses
LK.setTimeout(function () {
judgeObj.animateEntrance(0);
judgeObj.setRating(rating);
judgeObj.setComment(comments[rating]);
LK.getSound('judgeComment').play();
}, delay);
})(judgeObjects[index], finalRating, judgeData.comments);
});
// Calculate and display average rating
var averageRating = totalRating / judges.length;
// Award coins based on average rating
var coinsEarned = Math.round(averageRating * 10); // Earn 10 coins per star
storage.coins = (storage.coins || 0) + coinsEarned;
console.log("Coins earned: " + coinsEarned + ", Total coins: " + storage.coins);
coinText.setText("Coins: " + storage.coins); // Update coin display
// Update the highest rating if this is better
if (averageRating > storage.highestRating) {
storage.highestRating = averageRating;
// Unlock new filters based on rating
availableFilters.forEach(function (filter) {
if (filter.unlockRating <= averageRating && storage.unlockedFilters.indexOf(filter.id) === -1) {
storage.unlockedFilters.push(filter.id);
}
});
}
// Display average rating
LK.setTimeout(function () {
averageRatingText.setText("Rating: " + averageRating.toFixed(1) + " / 5.0");
averageRatingText.alpha = 0;
averageRatingText.visible = true;
tween(averageRatingText, {
alpha: 1
}, {
duration: 500
});
}, 4000);
}
// Handle touch events for game elements
game.down = function (x, y, obj) {
// Handle filter selection
if (currentState === STATE_CAMERA) {
for (var filterId in filterPreviews) {
var preview = filterPreviews[filterId];
if (preview.interactive && preview.getBounds().contains(x, y)) {
selectFilter(filterId);
return;
}
}
}
};
// Capture button event handler
captureButton.down = function (x, y, obj) {
if (currentState !== STATE_CAMERA) {
return;
}
// Play camera click sound
LK.getSound('cameraClick').play();
// Flash screen effect
LK.effects.flashScreen(0xffffff, 500);
// Switch to review mode after a short delay
LK.setTimeout(function () {
switchToState(STATE_REVIEW);
}, 600);
};
// Return button event handler
returnButton.down = function (x, y, obj) {
if (currentState !== STATE_REVIEW) {
return;
}
// Deduct 10 coins if player has 10 or more coins
if (storage.coins >= 10) {
storage.coins -= 10;
console.log("Spent 10 coins for a new selfie. Remaining coins: " + storage.coins);
coinText.setText("Coins: " + storage.coins); // Update coin display
}
// Update filter previews to show newly unlocked filters
availableFilters.forEach(function (filter) {
var preview = filterPreviews[filter.id];
var isUnlocked = storage.unlockedFilters.indexOf(filter.id) !== -1;
preview.setLocked(!isUnlocked);
});
// Switch back to camera mode
switchToState(STATE_CAMERA);
};
// Game update function
game.update = function () {
// Handle voice-activated effects in camera mode
if (currentState === STATE_CAMERA) {
// Detect voice volume changes
var volume = facekit.volume;
// Update effect indicator based on current volume
if (volume > lastVoiceVolume && volume > voiceEffectThreshold) {
effectIndicator.pulse(volume);
// Activate voice effect if over threshold
if (volume > voiceEffectThreshold && !voiceEffectActive) {
voiceEffectActive = true;
// Apply random effect when voice detected
var effect = Math.floor(Math.random() * 3);
// Effects could include:
// 1. Temporary color flash
// 2. Scale animation
// 3. Rotation effect
switch (effect) {
case 0:
// Temporary color tint
var randomColor = Math.random() * 0xFFFFFF;
cameraFrame.tint = randomColor;
LK.setTimeout(function () {
tween(cameraFrame, {
tint: 0xFFFFFF
}, {
duration: 500
});
}, 500);
break;
case 1:
// Scale animation
tween(cameraFrame, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 300,
onFinish: function onFinish() {
tween(cameraFrame, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 400
});
}
});
break;
case 2:
// Rotation effect
var startRotation = cameraFrame.rotation;
var targetRotation = startRotation + Math.PI * 0.1;
tween(cameraFrame, {
rotation: targetRotation
}, {
duration: 300,
onFinish: function onFinish() {
tween(cameraFrame, {
rotation: startRotation
}, {
duration: 400
});
}
});
break;
}
}
} else if (volume < voiceEffectThreshold && voiceEffectActive) {
// Reset voice effect flag when volume drops
voiceEffectActive = false;
}
lastVoiceVolume = volume;
}
};
// Start with camera state
switchToState(STATE_CAMERA);