/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
// Character controlled by voice
var Character = Container.expand(function () {
var self = Container.call(this);
var charAsset = self.attachAsset('character', {
anchorX: 0.5,
anchorY: 0.5
});
self.setIdle = function () {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
};
self.setActive = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
};
return self;
});
// Word bubble above character
var WordBubble = Container.expand(function () {
var self = Container.call(this);
self.textObj = new Text2('', {
size: 90,
fill: 0xFFF700
});
self.textObj.anchor.set(0.5, 1);
self.addChild(self.textObj);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Word lists for Turkish and English
var wordListTR = ["elma", "araba", "kitap", "masa", "kedi", "köpek", "okul", "çanta", "kalem", "telefon", "beyaz", "mavi", "yeşil", "sarı", "kırmızı", "güneş", "ay", "yıldız", "bulut", "deniz", "uçak", "balık", "çiçek", "dağ", "orman", "şehir", "yol", "ev", "kapı", "pencere", "sandalye", "tabak", "kaşık", "çatal", "bardak", "su", "ekmek", "peynir", "zeytin", "domates", "salatalık"];
var wordListEN = ["apple", "car", "book", "table", "cat", "dog", "school", "bag", "pen", "phone", "white", "blue", "green", "yellow", "red", "sun", "moon", "star", "cloud", "sea", "plane", "fish", "flower", "mountain", "forest", "city", "road", "house", "door", "window", "chair", "plate", "spoon", "fork", "glass", "water", "bread", "cheese", "olive", "tomato", "cucumber"];
// Language state
var supportedLanguages = [{
code: "tr",
label: "Türkçe"
}, {
code: "en",
label: "English"
}];
var currentLanguage = "tr"; // default
var wordList = wordListTR;
// Language selection UI
var langTxt = new Text2("Dil: Türkçe | Language: English", {
size: 60,
fill: 0x00E0FF
});
langTxt.anchor.set(0.5, 0);
langTxt.y = 200;
langTxt.x = 2048 / 2;
LK.gui.top.addChild(langTxt);
// Allow user to tap to switch language
langTxt.interactive = true;
langTxt.buttonMode = true;
langTxt.down = function (x, y, obj) {
// Toggle language
if (currentLanguage === "tr") {
currentLanguage = "en";
wordList = wordListEN;
langTxt.setText("Dil: Türkçe | Language: English");
levelTxt.setText("Level 1");
} else {
currentLanguage = "tr";
wordList = wordListTR;
langTxt.setText("Dil: Türkçe | Language: English");
levelTxt.setText("Seviye 1");
}
// Reset game state for new language
currentWordIndex = 0;
score = 0;
level = 1;
LK.setScore(0);
scoreTxt.setText(0);
// Shuffle new word list
gameWords = shuffle(wordList.slice());
setNewWord();
};
// Shuffle helper
function shuffle(arr) {
for (var i = arr.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
}
// Game state
var currentWordIndex = 0;
var currentWord = '';
var score = 0;
var level = 1;
var wordsPerLevel = 5;
var isListening = false;
var lastHeard = '';
var wordTimeout = null;
var feedbackTimeout = null;
var gameActive = true;
// Shuffle word list for each game
var gameWords = shuffle(wordList.slice());
// Camera and microphone selection UI
var camMicTxt = new Text2("Kamera & Mikrofon: Açmak için dokunun\nTap to enable Camera & Microphone", {
size: 60,
fill: 0x00E0FF
});
camMicTxt.anchor.set(0.5, 0);
camMicTxt.x = 2048 / 2;
camMicTxt.y = 320;
LK.gui.top.addChild(camMicTxt);
var camMicEnabled = false;
camMicTxt.interactive = true;
camMicTxt.buttonMode = true;
camMicTxt.down = function (x, y, obj) {
if (!camMicEnabled) {
// Try to enable camera and microphone using facekit.start()
try {
facekit.start();
camMicEnabled = true;
camMicTxt.setText(currentLanguage === "tr" ? "Kamera & Mikrofon açık" : "Camera & Microphone enabled");
LK.effects.flashObject(camMicTxt, 0x00ff00, 600);
} catch (e) {
camMicTxt.setText(currentLanguage === "tr" ? "Erişim reddedildi!" : "Access denied!");
LK.effects.flashObject(camMicTxt, 0xff0000, 600);
}
}
};
// Character
var character = new Character();
character.x = 2048 / 2;
character.y = 2732 - 400;
game.addChild(character);
// Word bubble
var wordBubble = new WordBubble();
wordBubble.x = character.x;
wordBubble.y = character.y - 180;
game.addChild(wordBubble);
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Level text
var levelTxt = new Text2('Seviye 1', {
size: 70,
fill: 0x00E0FF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 120;
// Feedback text (centered)
var feedbackTxt = new Text2('', {
size: 120,
fill: 0x00FF00
});
feedbackTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(feedbackTxt);
// Helper: Set new word
function setNewWord() {
if (currentWordIndex >= gameWords.length) {
LK.showYouWin();
return;
}
currentWord = gameWords[currentWordIndex];
wordBubble.textObj.setText(currentWord);
wordBubble.textObj.setStyle({
fill: 0xFFF700
});
lastHeard = '';
isListening = true;
character.setIdle();
feedbackTxt.setText('');
// Set timeout for word (5 seconds)
if (wordTimeout) LK.clearTimeout(wordTimeout);
wordTimeout = LK.setTimeout(function () {
if (!gameActive) return;
isListening = false;
if (currentLanguage === "tr") {
feedbackTxt.setText('Süre doldu!');
} else {
feedbackTxt.setText('Time is up!');
}
feedbackTxt.setStyle({
fill: 0xFF3333
});
character.setIdle();
LK.effects.flashObject(character, 0xff0000, 600);
LK.setTimeout(function () {
LK.showGameOver();
}, 1200);
}, 5000);
}
// Helper: Show feedback
function showFeedback(text, color) {
feedbackTxt.setText(text);
feedbackTxt.setStyle({
fill: color
});
if (feedbackTimeout) LK.clearTimeout(feedbackTimeout);
feedbackTimeout = LK.setTimeout(function () {
feedbackTxt.setText('');
}, 1000);
}
// Helper: Next word
function nextWord() {
currentWordIndex++;
if (currentWordIndex % wordsPerLevel === 0) {
level++;
if (currentLanguage === "tr") {
levelTxt.setText('Seviye ' + level);
} else {
levelTxt.setText('Level ' + level);
}
// Increase difficulty: reduce time per word
}
setNewWord();
}
// Helper: Normalize string (lowercase, Turkish chars)
function normalize(str) {
return (str || '').toLocaleLowerCase('tr-TR').replace(/[^a-zçğıöşü]/g, '');
}
// Main voice check loop
game.update = function () {
if (!gameActive) return;
// Only check if listening for word
if (!isListening) return;
// Use facekit.volume as a proxy for "speaking"
if (facekit.volume > 0.2) {
// Simulate "heard" word by using pitch as a randomizer (since we can't do real speech-to-text)
// In a real implementation, here would be the speech recognition result
// For MVP, we simulate: if user makes sound, we "accept" as correct with 70% chance
if (lastHeard !== currentWord) {
var correct = Math.random() < 0.7;
if (correct) {
lastHeard = currentWord;
isListening = false;
LK.clearTimeout(wordTimeout);
score++;
LK.setScore(score);
scoreTxt.setText(score);
wordBubble.textObj.setStyle({
fill: 0x00FF00
});
character.setActive();
LK.effects.flashObject(character, 0x00ff00, 400);
showFeedback(currentLanguage === "tr" ? 'Doğru!' : 'Correct!', "#00ff00");
LK.setTimeout(function () {
character.setIdle();
nextWord();
}, 800);
} else {
lastHeard = 'wrong';
isListening = false;
LK.clearTimeout(wordTimeout);
wordBubble.textObj.setStyle({
fill: 0xFF3333
});
character.setIdle();
LK.effects.flashObject(character, 0xff0000, 400);
showFeedback(currentLanguage === "tr" ? 'Yanlış!' : 'Wrong!', "#ff3333");
LK.setTimeout(function () {
LK.showGameOver();
}, 900);
}
}
}
};
// Start game
setNewWord();
// Play background music in a loop
LK.playMusic('turkce_tellafuz_edebilir_misin', {
loop: true
}); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
// Character controlled by voice
var Character = Container.expand(function () {
var self = Container.call(this);
var charAsset = self.attachAsset('character', {
anchorX: 0.5,
anchorY: 0.5
});
self.setIdle = function () {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
};
self.setActive = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
};
return self;
});
// Word bubble above character
var WordBubble = Container.expand(function () {
var self = Container.call(this);
self.textObj = new Text2('', {
size: 90,
fill: 0xFFF700
});
self.textObj.anchor.set(0.5, 1);
self.addChild(self.textObj);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Word lists for Turkish and English
var wordListTR = ["elma", "araba", "kitap", "masa", "kedi", "köpek", "okul", "çanta", "kalem", "telefon", "beyaz", "mavi", "yeşil", "sarı", "kırmızı", "güneş", "ay", "yıldız", "bulut", "deniz", "uçak", "balık", "çiçek", "dağ", "orman", "şehir", "yol", "ev", "kapı", "pencere", "sandalye", "tabak", "kaşık", "çatal", "bardak", "su", "ekmek", "peynir", "zeytin", "domates", "salatalık"];
var wordListEN = ["apple", "car", "book", "table", "cat", "dog", "school", "bag", "pen", "phone", "white", "blue", "green", "yellow", "red", "sun", "moon", "star", "cloud", "sea", "plane", "fish", "flower", "mountain", "forest", "city", "road", "house", "door", "window", "chair", "plate", "spoon", "fork", "glass", "water", "bread", "cheese", "olive", "tomato", "cucumber"];
// Language state
var supportedLanguages = [{
code: "tr",
label: "Türkçe"
}, {
code: "en",
label: "English"
}];
var currentLanguage = "tr"; // default
var wordList = wordListTR;
// Language selection UI
var langTxt = new Text2("Dil: Türkçe | Language: English", {
size: 60,
fill: 0x00E0FF
});
langTxt.anchor.set(0.5, 0);
langTxt.y = 200;
langTxt.x = 2048 / 2;
LK.gui.top.addChild(langTxt);
// Allow user to tap to switch language
langTxt.interactive = true;
langTxt.buttonMode = true;
langTxt.down = function (x, y, obj) {
// Toggle language
if (currentLanguage === "tr") {
currentLanguage = "en";
wordList = wordListEN;
langTxt.setText("Dil: Türkçe | Language: English");
levelTxt.setText("Level 1");
} else {
currentLanguage = "tr";
wordList = wordListTR;
langTxt.setText("Dil: Türkçe | Language: English");
levelTxt.setText("Seviye 1");
}
// Reset game state for new language
currentWordIndex = 0;
score = 0;
level = 1;
LK.setScore(0);
scoreTxt.setText(0);
// Shuffle new word list
gameWords = shuffle(wordList.slice());
setNewWord();
};
// Shuffle helper
function shuffle(arr) {
for (var i = arr.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
}
// Game state
var currentWordIndex = 0;
var currentWord = '';
var score = 0;
var level = 1;
var wordsPerLevel = 5;
var isListening = false;
var lastHeard = '';
var wordTimeout = null;
var feedbackTimeout = null;
var gameActive = true;
// Shuffle word list for each game
var gameWords = shuffle(wordList.slice());
// Camera and microphone selection UI
var camMicTxt = new Text2("Kamera & Mikrofon: Açmak için dokunun\nTap to enable Camera & Microphone", {
size: 60,
fill: 0x00E0FF
});
camMicTxt.anchor.set(0.5, 0);
camMicTxt.x = 2048 / 2;
camMicTxt.y = 320;
LK.gui.top.addChild(camMicTxt);
var camMicEnabled = false;
camMicTxt.interactive = true;
camMicTxt.buttonMode = true;
camMicTxt.down = function (x, y, obj) {
if (!camMicEnabled) {
// Try to enable camera and microphone using facekit.start()
try {
facekit.start();
camMicEnabled = true;
camMicTxt.setText(currentLanguage === "tr" ? "Kamera & Mikrofon açık" : "Camera & Microphone enabled");
LK.effects.flashObject(camMicTxt, 0x00ff00, 600);
} catch (e) {
camMicTxt.setText(currentLanguage === "tr" ? "Erişim reddedildi!" : "Access denied!");
LK.effects.flashObject(camMicTxt, 0xff0000, 600);
}
}
};
// Character
var character = new Character();
character.x = 2048 / 2;
character.y = 2732 - 400;
game.addChild(character);
// Word bubble
var wordBubble = new WordBubble();
wordBubble.x = character.x;
wordBubble.y = character.y - 180;
game.addChild(wordBubble);
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Level text
var levelTxt = new Text2('Seviye 1', {
size: 70,
fill: 0x00E0FF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 120;
// Feedback text (centered)
var feedbackTxt = new Text2('', {
size: 120,
fill: 0x00FF00
});
feedbackTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(feedbackTxt);
// Helper: Set new word
function setNewWord() {
if (currentWordIndex >= gameWords.length) {
LK.showYouWin();
return;
}
currentWord = gameWords[currentWordIndex];
wordBubble.textObj.setText(currentWord);
wordBubble.textObj.setStyle({
fill: 0xFFF700
});
lastHeard = '';
isListening = true;
character.setIdle();
feedbackTxt.setText('');
// Set timeout for word (5 seconds)
if (wordTimeout) LK.clearTimeout(wordTimeout);
wordTimeout = LK.setTimeout(function () {
if (!gameActive) return;
isListening = false;
if (currentLanguage === "tr") {
feedbackTxt.setText('Süre doldu!');
} else {
feedbackTxt.setText('Time is up!');
}
feedbackTxt.setStyle({
fill: 0xFF3333
});
character.setIdle();
LK.effects.flashObject(character, 0xff0000, 600);
LK.setTimeout(function () {
LK.showGameOver();
}, 1200);
}, 5000);
}
// Helper: Show feedback
function showFeedback(text, color) {
feedbackTxt.setText(text);
feedbackTxt.setStyle({
fill: color
});
if (feedbackTimeout) LK.clearTimeout(feedbackTimeout);
feedbackTimeout = LK.setTimeout(function () {
feedbackTxt.setText('');
}, 1000);
}
// Helper: Next word
function nextWord() {
currentWordIndex++;
if (currentWordIndex % wordsPerLevel === 0) {
level++;
if (currentLanguage === "tr") {
levelTxt.setText('Seviye ' + level);
} else {
levelTxt.setText('Level ' + level);
}
// Increase difficulty: reduce time per word
}
setNewWord();
}
// Helper: Normalize string (lowercase, Turkish chars)
function normalize(str) {
return (str || '').toLocaleLowerCase('tr-TR').replace(/[^a-zçğıöşü]/g, '');
}
// Main voice check loop
game.update = function () {
if (!gameActive) return;
// Only check if listening for word
if (!isListening) return;
// Use facekit.volume as a proxy for "speaking"
if (facekit.volume > 0.2) {
// Simulate "heard" word by using pitch as a randomizer (since we can't do real speech-to-text)
// In a real implementation, here would be the speech recognition result
// For MVP, we simulate: if user makes sound, we "accept" as correct with 70% chance
if (lastHeard !== currentWord) {
var correct = Math.random() < 0.7;
if (correct) {
lastHeard = currentWord;
isListening = false;
LK.clearTimeout(wordTimeout);
score++;
LK.setScore(score);
scoreTxt.setText(score);
wordBubble.textObj.setStyle({
fill: 0x00FF00
});
character.setActive();
LK.effects.flashObject(character, 0x00ff00, 400);
showFeedback(currentLanguage === "tr" ? 'Doğru!' : 'Correct!', "#00ff00");
LK.setTimeout(function () {
character.setIdle();
nextWord();
}, 800);
} else {
lastHeard = 'wrong';
isListening = false;
LK.clearTimeout(wordTimeout);
wordBubble.textObj.setStyle({
fill: 0xFF3333
});
character.setIdle();
LK.effects.flashObject(character, 0xff0000, 400);
showFeedback(currentLanguage === "tr" ? 'Yanlış!' : 'Wrong!', "#ff3333");
LK.setTimeout(function () {
LK.showGameOver();
}, 900);
}
}
}
};
// Start game
setNewWord();
// Play background music in a loop
LK.playMusic('turkce_tellafuz_edebilir_misin', {
loop: true
});