User prompt
kanka şu ipucu yazısı en sol üst köşede olsun en sağ üst değil
User prompt
kanka bir kere gelen kişi daha gelemesin eğer 2 kere aynı ismi görürsem anlıyayım doppleganger olduğunu ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
kanka tam iki kartın tam ortasında bir resim olsun
User prompt
kanka bazende kimlik kartıyla verdiği kartta faklılıklar olsun örenğin birinde daire 300 yazarken diğerinde 205 yazsın ve bu yüzden yanlış olduğunu anlayabilelim
User prompt
kanka ana menüdeyken tuşlara özel basma sesi oluştur
User prompt
kanka ana menüdeyeken tuşlara basma seside ekle
User prompt
kanka ipucu en sağ üst köşede yazsın
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'x')' in or related to this line: 'anomalyKiller.x = currentVisitor.x;' Line Number: 1188
User prompt
kanka ana menüdeyken şu approve deny yazan kısım gözükmesin birde approve buttonunu tıpkı deny gibi yap ama yeşil olsun
User prompt
kanka approve butonu yeşil renkte olsun birde ana menüdeyken ipucu metni gözükmesin
User prompt
kanka approve yazan buttonu düzelt birde şu yukarıda yazan ipucu metnini bir araya getir çok fazla yer kaplamasın birde oyun ilk ingilizce başlasın ayarlardan değiştirebilelim
User prompt
hayır yanlış yaptığım kişi anomaliye dönüşsün ve bana yaklaşıp öldürsün beni ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'destroy')' in or related to this line: 'currentVisitor.destroy();' Line Number: 1178
User prompt
kanka eğer 3 hata yaparsak anomali yanıma gelip beni öldürsün animasyonunu ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kanka şimdide adamın söylediği şey konuştuğu kutucuğa sığmıyor metine göre boyutu tam optimize edilsin konuşma kutucuğunun ve diğer kutucuklarda metinlere göre optimize edilsin metinler taşmasın
User prompt
kanka yazılar çok küçük okunmuyo isim kayıt yada adamın söylediği şeyler ipucu falan bunları büyüt ki okunsun
User prompt
kanka kayıt taki resimdede hata var ara sıra onuda düzelt ve daha çok şey ekle sadece kimliğe bakmayalım farklı ipuçlarıda olsun aynı That's Not My Neighbor! oyunundaki gibi ve adam bizle konuşsun şu yüzden geldim falan diye ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/storage.v1
User prompt
kanka hala hatalar var kimlikte gözüken adam hatalı oluyor bazen hiç hata kalmasın bütün hataları düzelt herşeyi ekle ve detaylandırıp düzelt
User prompt
kanka mesela örnek veriyorum zenci biri geliyo kimlikte adamın ten rengi beyaz o yüzden reddet diyorum hata yaptın diyo kanka düzelt şu hataları eğer doğru kişiyse kimliktede o kişinin aynısı gözüksün
User prompt
kanka kimlikte olan admın resmi hep aynı düzelt şunu hiçbirşey anlayamıyorum ve dili türkçe yapınca neden hala ingilizce oyun approve falan yazıyo bütün hataları düzelt ve detay ekle
User prompt
kanka kimlikteki resim hep aynı bune kanka düzelt şunu birde ana menü animasyonu butona basma animasyonu falan olsun sadelikten uzaklaşsın oyun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kanka isimler daha belirgin dursun birde bütün karakterler aynı hepsi birbirinden farklı gözüksün bazıları anomali olduğu belli olsun tipinden hatta çok detaylı olsun birde ana menü yap oyna ve ayarlar olsun ayarlardan dil değiştirebilelim ingilizce ve türkçe olsun ses ekle oyuna bide ↪💡 Consider importing and using the following plugins: @upit/storage.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Doppelganger Detective
Initial prompt
That's Not My Neighbor! oyununun aynısını yapabilirmisin
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { language: "en", soundEnabled: true }); /**** * Classes ****/ var AnomalyKiller = Container.expand(function () { var self = Container.call(this); // Create menacing appearance var body = self.attachAsset('visitor', { anchorX: 0.5, anchorY: 1.0 }); body.tint = 0x1a1a1a; // Dark body var head = self.attachAsset('visitorHead', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -200 }); head.tint = 0x2a2a2a; // Dark head var leftEye = self.attachAsset('visitorEye', { anchorX: 0.5, anchorY: 0.5, x: -25, y: -210 }); leftEye.tint = 0xff0000; // Red glowing eyes leftEye.scaleX = 1.5; leftEye.scaleY = 1.5; var rightEye = self.attachAsset('visitorEye', { anchorX: 0.5, anchorY: 0.5, x: 25, y: -210 }); rightEye.tint = 0xff0000; // Red glowing eyes rightEye.scaleX = 1.5; rightEye.scaleY = 1.5; var mouth = self.attachAsset('visitorMouth', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -170 }); mouth.tint = 0x8b0000; // Dark red mouth mouth.scaleX = 2.0; // Large menacing mouth // Start off-screen self.x = 1024; self.y = -500; self.alpha = 0; self.killPlayer = function () { // Dramatic entrance animation tween(self, { y: 1400, alpha: 1 }, { duration: 2000, easing: tween.easeOut, onFinish: function onFinish() { // Flash red eyes tween(leftEye, { scaleX: 2.0, scaleY: 2.0 }, { duration: 300, easing: tween.easeInOut }); tween(rightEye, { scaleX: 2.0, scaleY: 2.0 }, { duration: 300, easing: tween.easeInOut }); // Screen flash and kill LK.setTimeout(function () { LK.effects.flashScreen(0xff0000, 1500); LK.setTimeout(function () { LK.showGameOver(); }, 1500); }, 500); } }); }; return self; }); var ConversationBox = Container.expand(function () { var self = Container.call(this); var boxBackground = self.attachAsset('idCard', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 0.8 }); boxBackground.tint = 0xf0f0f0; self.messageText = new Text2('', { size: 42, fill: '#2c3e50' }); self.messageText.anchor.set(0.5, 0.5); self.messageText.x = 0; self.messageText.y = 0; self.addChild(self.messageText); self.showMessage = function (message) { self.messageText.setText(message); // Dynamically resize box based on text content var textBounds = self.messageText.getBounds(); var padding = 40; var minWidth = 400; var minHeight = 120; var maxWidth = 1600; // Calculate required dimensions var requiredWidth = Math.max(minWidth, Math.min(maxWidth, textBounds.width + padding * 2)); var requiredHeight = Math.max(minHeight, textBounds.height + padding * 2); var baseWidth = 400; var baseHeight = 250; boxBackground.scaleX = requiredWidth / baseWidth; boxBackground.scaleY = requiredHeight / baseHeight; self.alpha = 0; tween(self, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); }; self.hideMessage = function () { tween(self, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var IDCard = Container.expand(function () { var self = Container.call(this); var cardBackground = self.attachAsset('idCard', { anchorX: 0.5, anchorY: 0.5 }); // Create mini visitor face on ID var miniHead = self.attachAsset('visitorHead', { anchorX: 0.5, anchorY: 0.5, x: -120, y: -20, scaleX: 0.6, scaleY: 0.6 }); var miniHair = self.attachAsset('visitorHair', { anchorX: 0.5, anchorY: 0.5, x: -120, y: -40, scaleX: 0.6, scaleY: 0.6 }); var miniLeftEye = self.attachAsset('visitorEye', { anchorX: 0.5, anchorY: 0.5, x: -135, y: -25, scaleX: 0.6, scaleY: 0.6 }); var miniRightEye = self.attachAsset('visitorEye', { anchorX: 0.5, anchorY: 0.5, x: -105, y: -25, scaleX: 0.6, scaleY: 0.6 }); var miniNose = self.attachAsset('visitorNose', { anchorX: 0.5, anchorY: 0.5, x: -120, y: -10, scaleX: 0.6, scaleY: 0.6 }); var miniMouth = self.attachAsset('visitorMouth', { anchorX: 0.5, anchorY: 0.5, x: -120, y: 5, scaleX: 0.6, scaleY: 0.6 }); self.nameText = new Text2('', { size: 45, fill: '#000000' }); self.nameText.anchor.set(0, 0.5); self.nameText.x = 20; self.nameText.y = -60; self.addChild(self.nameText); self.apartmentText = new Text2('', { size: 40, fill: '#000000' }); self.apartmentText.anchor.set(0, 0.5); self.apartmentText.x = 20; self.apartmentText.y = -20; self.addChild(self.apartmentText); self.setInfo = function (name, apartment, features, isRandomized) { var language = storage.language || 'en'; var nameLabel = language === 'tr' ? 'Isim: ' : 'Name: '; var aptLabel = language === 'tr' ? 'Daire: ' : 'Apt: '; self.nameText.setText(nameLabel + name); // Create apartment discrepancy for doppelgangers var displayApartment = apartment; if (isRandomized && Math.random() < 0.6) { // 60% chance of apartment mismatch for doppelgangers var apartmentNumbers = [101, 102, 103, 201, 202, 203, 301, 302, 303, 401]; do { displayApartment = apartmentNumbers[Math.floor(Math.random() * apartmentNumbers.length)]; } while (displayApartment === apartment); } self.apartmentText.setText(aptLabel + displayApartment); // Dynamically resize card based on text content var nameBounds = self.nameText.getBounds(); var aptBounds = self.apartmentText.getBounds(); var maxTextWidth = Math.max(nameBounds.width, aptBounds.width); var padding = 40; var minWidth = 400; var requiredWidth = Math.max(minWidth, maxTextWidth + 160 + padding); var baseWidth = 400; if (requiredWidth > baseWidth) { cardBackground.scaleX = requiredWidth / baseWidth; } // ID card should always show the original resident features, not doppelganger features var idFeatures = features; miniHair.tint = idFeatures.hairColor; miniLeftEye.x = -120 - idFeatures.eyeSpacing * 0.3; miniRightEye.x = -120 + idFeatures.eyeSpacing * 0.3; miniNose.scaleX = idFeatures.noseSize * 0.6; miniNose.scaleY = idFeatures.noseSize * 0.6; miniMouth.scaleX = idFeatures.mouthWidth * 0.6; // Set skin tone if available if (idFeatures.skinTone) { miniHead.tint = idFeatures.skinTone; } }; return self; }); var MainMenu = Container.expand(function () { var self = Container.call(this); var language = storage.language || 'en'; var texts = { en: { title: 'DOPPELGANGER DETECTIVE', play: 'PLAY', settings: 'SETTINGS', back: 'BACK', language: 'LANGUAGE: ENGLISH', sound: 'SOUND: ON', soundOff: 'SOUND: OFF' }, tr: { title: 'DOPPELGANGER DEDEKTIFI', play: 'OYNA', settings: 'AYARLAR', back: 'GERI', language: 'DIL: TURKCE', sound: 'SES: ACIK', soundOff: 'SES: KAPALI' } }; self.currentTexts = texts[language]; // Title self.titleText = new Text2(self.currentTexts.title, { size: 80, fill: '#e74c3c' }); self.titleText.anchor.set(0.5, 0.5); self.titleText.x = 1024; self.titleText.y = 600; self.titleText.alpha = 0; self.addChild(self.titleText); // Animate title entrance tween(self.titleText, { alpha: 1, y: 800 }, { duration: 1500, easing: tween.easeOut }); // Play button self.playButtonBg = self.attachAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1400 }); self.playText = new Text2(self.currentTexts.play, { size: 50, fill: '#ffffff' }); self.playText.anchor.set(0.5, 0.5); self.playText.x = 1024; self.playText.y = 1400; self.playText.alpha = 0; self.playButtonBg.alpha = 0; self.addChild(self.playText); // Animate play button entrance LK.setTimeout(function () { tween(self.playButtonBg, { alpha: 1 }, { duration: 800, easing: tween.easeOut }); tween(self.playText, { alpha: 1 }, { duration: 800, easing: tween.easeOut }); }, 500); // Settings button self.settingsButtonBg = self.attachAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1550 }); self.settingsText = new Text2(self.currentTexts.settings, { size: 50, fill: '#ffffff' }); self.settingsText.anchor.set(0.5, 0.5); self.settingsText.x = 1024; self.settingsText.y = 1550; self.settingsText.alpha = 0; self.settingsButtonBg.alpha = 0; self.addChild(self.settingsText); // Animate settings button entrance LK.setTimeout(function () { tween(self.settingsButtonBg, { alpha: 1 }, { duration: 800, easing: tween.easeOut }); tween(self.settingsText, { alpha: 1 }, { duration: 800, easing: tween.easeOut }); }, 800); self.playButtonBg.down = function () { // Play button sound effect if (storage.soundEnabled !== false) { LK.getSound('menuButtonSound').play(); } // Animate button press tween(self.playButtonBg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(self.playButtonBg, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { self.destroy(); startGame(); } }); } }); }; self.settingsButtonBg.down = function () { // Play button sound effect if (storage.soundEnabled !== false) { LK.getSound('settingsButtonSound').play(); } // Animate button press tween(self.settingsButtonBg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(self.settingsButtonBg, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { self.destroy(); showSettings(); } }); } }); }; return self; }); var RecordCard = Container.expand(function () { var self = Container.call(this); var cardBackground = self.attachAsset('recordCard', { anchorX: 0.5, anchorY: 0.5 }); // Create mini resident face on record var miniHead = self.attachAsset('visitorHead', { anchorX: 0.5, anchorY: 0.5, x: -120, y: -20, scaleX: 0.6, scaleY: 0.6 }); var miniHair = self.attachAsset('visitorHair', { anchorX: 0.5, anchorY: 0.5, x: -120, y: -40, scaleX: 0.6, scaleY: 0.6 }); var miniLeftEye = self.attachAsset('visitorEye', { anchorX: 0.5, anchorY: 0.5, x: -135, y: -25, scaleX: 0.6, scaleY: 0.6 }); var miniRightEye = self.attachAsset('visitorEye', { anchorX: 0.5, anchorY: 0.5, x: -105, y: -25, scaleX: 0.6, scaleY: 0.6 }); var miniNose = self.attachAsset('visitorNose', { anchorX: 0.5, anchorY: 0.5, x: -120, y: -10, scaleX: 0.6, scaleY: 0.6 }); var miniMouth = self.attachAsset('visitorMouth', { anchorX: 0.5, anchorY: 0.5, x: -120, y: 5, scaleX: 0.6, scaleY: 0.6 }); self.nameText = new Text2('', { size: 45, fill: '#000000' }); self.nameText.anchor.set(0, 0.5); self.nameText.x = 20; self.nameText.y = -60; self.addChild(self.nameText); self.apartmentText = new Text2('', { size: 40, fill: '#000000' }); self.apartmentText.anchor.set(0, 0.5); self.apartmentText.x = 20; self.apartmentText.y = -20; self.addChild(self.apartmentText); self.setInfo = function (name, apartment, features) { var language = storage.language || 'en'; var recordLabel = language === 'tr' ? 'Kayit: ' : 'Record: '; var aptLabel = language === 'tr' ? 'Daire: ' : 'Apt: '; self.nameText.setText(recordLabel + name); self.apartmentText.setText(aptLabel + apartment); // Dynamically resize card based on text content var nameBounds = self.nameText.getBounds(); var aptBounds = self.apartmentText.getBounds(); var maxTextWidth = Math.max(nameBounds.width, aptBounds.width); var padding = 40; var minWidth = 400; var requiredWidth = Math.max(minWidth, maxTextWidth + 160 + padding); var baseWidth = 400; if (requiredWidth > baseWidth) { cardBackground.scaleX = requiredWidth / baseWidth; } miniHair.tint = features.hairColor; miniLeftEye.x = -120 - features.eyeSpacing * 0.3; miniRightEye.x = -120 + features.eyeSpacing * 0.3; miniNose.scaleX = features.noseSize * 0.6; miniNose.scaleY = features.noseSize * 0.6; miniMouth.scaleX = features.mouthWidth * 0.6; // Set skin tone if available if (features.skinTone) { miniHead.tint = features.skinTone; } }; return self; }); var SettingsMenu = Container.expand(function () { var self = Container.call(this); var language = storage.language || 'en'; var soundEnabled = storage.soundEnabled !== false; var texts = { en: { settings: 'SETTINGS', back: 'BACK', language: 'LANGUAGE: ENGLISH', languageTr: 'LANGUAGE: TURKISH', sound: 'SOUND: ON', soundOff: 'SOUND: OFF' }, tr: { settings: 'AYARLAR', back: 'GERI', language: 'DIL: TURKCE', languageEn: 'DIL: INGILIZCE', sound: 'SES: ACIK', soundOff: 'SES: KAPALI' } }; self.currentTexts = texts[language]; // Settings title self.titleText = new Text2(self.currentTexts.settings, { size: 70, fill: '#2c3e50' }); self.titleText.anchor.set(0.5, 0.5); self.titleText.x = 1024; self.titleText.y = 600; self.addChild(self.titleText); // Language button self.langButtonBg = self.attachAsset('languageButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1000 }); self.langText = new Text2(language === 'en' ? self.currentTexts.language : self.currentTexts.language, { size: 40, fill: '#ffffff' }); self.langText.anchor.set(0.5, 0.5); self.langText.x = 1024; self.langText.y = 1000; self.addChild(self.langText); // Sound button self.soundButtonBg = self.attachAsset('soundButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1150 }); self.soundText = new Text2(soundEnabled ? self.currentTexts.sound : self.currentTexts.soundOff, { size: 40, fill: '#ffffff' }); self.soundText.anchor.set(0.5, 0.5); self.soundText.x = 1024; self.soundText.y = 1150; self.addChild(self.soundText); // Back button self.backButtonBg = self.attachAsset('backButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1400 }); self.backText = new Text2(self.currentTexts.back, { size: 40, fill: '#ffffff' }); self.backText.anchor.set(0.5, 0.5); self.backText.x = 1024; self.backText.y = 1400; self.addChild(self.backText); self.langButtonBg.down = function () { // Play button sound effect if (storage.soundEnabled !== false) { LK.getSound('toggleButtonSound').play(); } // Animate button press tween(self.langButtonBg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(self.langButtonBg, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { storage.language = storage.language === 'en' ? 'tr' : 'en'; self.destroy(); showSettings(); } }); } }); }; self.soundButtonBg.down = function () { // Play button sound effect (before toggling sound) if (storage.soundEnabled !== false) { LK.getSound('toggleButtonSound').play(); } // Animate button press tween(self.soundButtonBg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(self.soundButtonBg, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { storage.soundEnabled = !storage.soundEnabled; self.destroy(); showSettings(); } }); } }); }; self.backButtonBg.down = function () { // Play button sound effect if (storage.soundEnabled !== false) { LK.getSound('backButtonSound').play(); } // Animate button press tween(self.backButtonBg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, onFinish: function onFinish() { tween(self.backButtonBg, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: function onFinish() { self.destroy(); showMainMenu(); } }); } }); }; return self; }); var Visitor = Container.expand(function () { var self = Container.call(this); // Create visitor appearance with more variety var body = self.attachAsset('visitor', { anchorX: 0.5, anchorY: 1.0 }); var head = self.attachAsset('visitorHead', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -200 }); var hair = self.attachAsset('visitorHair', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -240 }); var leftEye = self.attachAsset('visitorEye', { anchorX: 0.5, anchorY: 0.5, x: -25, y: -210 }); var rightEye = self.attachAsset('visitorEye', { anchorX: 0.5, anchorY: 0.5, x: 25, y: -210 }); var nose = self.attachAsset('visitorNose', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -190 }); var mouth = self.attachAsset('visitorMouth', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -170 }); // Visitor properties self.name = ''; self.apartmentNumber = 0; self.isDoppelganger = false; self.hairColor = 0x654321; self.eyeSpacing = 50; self.noseSize = 1.0; self.mouthWidth = 1.0; self.skinTone = 0xfdbcb4; self.eyeColor = 0x2c3e50; self.setFeatures = function (features) { hair.tint = features.hairColor; leftEye.x = -features.eyeSpacing / 2; rightEye.x = features.eyeSpacing / 2; nose.scaleX = features.noseSize; nose.scaleY = features.noseSize; mouth.scaleX = features.mouthWidth; self.hairColor = features.hairColor; self.eyeSpacing = features.eyeSpacing; self.noseSize = features.noseSize; self.mouthWidth = features.mouthWidth; // Use skin tone from features if available if (features.skinTone) { self.skinTone = features.skinTone; head.tint = self.skinTone; body.tint = self.skinTone; } // Make anomalies very obvious for doppelgangers if (features.isObviousAnomaly) { if (features.anomalyType === 'eye') { leftEye.tint = 0xff0000; // Red eye rightEye.scaleX = 1.5; // Different sized eyes } else if (features.anomalyType === 'mouth') { mouth.tint = 0x0000ff; // Blue mouth mouth.rotation = 0.2; // Tilted mouth } else if (features.anomalyType === 'nose') { nose.tint = 0x00ff00; // Green nose nose.scaleX = 2.0; // Very large nose } else if (features.anomalyType === 'hair') { hair.tint = 0xff00ff; // Bright magenta hair } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x34495e }); /**** * Game Code ****/ // Game state var currentVisitor = null; var currentIDCard = null; var currentRecord = null; var currentConversation = null; var middleImage = null; var gameActive = false; var score = 0; var mistakes = 0; var maxMistakes = 3; var visitorCount = 0; var gameStarted = false; var currentMenu = null; // Track visited names for doppelganger detection var visitedNames = storage.visitedNames || []; // Visitor reasons database var visitReasons = { en: ["I'm here to visit my friend in apartment 102.", "I need to deliver a package to my neighbor.", "I forgot my keys and need to get spare from building manager.", "I'm here for a dinner party tonight.", "I need to check on my elderly neighbor.", "I'm bringing groceries to my sick roommate.", "I have a repair appointment scheduled today.", "I'm here to pick up my mail from vacation.", "I need to return borrowed tools to my friend.", "I'm visiting my cousin who lives here."], tr: ["102 numaralı dairede arkadaşımı ziyarete geliyorum.", "Komşuma paket teslim etmem gerekiyor.", "Anahtarlarımı unuttum, yöneticiden yedek almam lazım.", "Bu akşam yemek partisi için geliyorum.", "Yaşlı komşumu kontrol etmem gerekiyor.", "Hasta ev arkadaşıma market alışverişi getiriyorum.", "Bugün tamirat randevum var.", "Tatilden postalarımı almaya geliyorum.", "Arkadaşımdan ödünç aldığım aletleri geri vermeye geliyorum.", "Burada yaşayan kuzenimle buluşmaya geliyorum."] }; // Additional clues system var additionalClues = { timeClues: ["Visitor arrived at unusual hour", "Claims to have appointment but building is closed", "Says visiting friend but it's very late"], behaviorClues: ["Visitor seems nervous and sweating", "Avoiding eye contact", "Fidgeting with hands constantly", "Speaking too quickly", "Can't remember apartment number clearly"], storyClues: ["Story doesn't match resident's schedule", "Claims relationship that doesn't exist", "Knows too much personal information", "Contradicts previous statements"] }; // Enhanced resident database with more variety var residents = [{ name: 'John Smith', apartment: 101, hairColor: 0x654321, eyeSpacing: 50, noseSize: 1.0, mouthWidth: 1.0, skinTone: 0xfdbcb4 }, { name: 'Mary Johnson', apartment: 102, hairColor: 0x8B4513, eyeSpacing: 45, noseSize: 0.8, mouthWidth: 1.2, skinTone: 0xf1c27d }, { name: 'Bob Wilson', apartment: 103, hairColor: 0x2F4F4F, eyeSpacing: 55, noseSize: 1.3, mouthWidth: 0.9, skinTone: 0x8d5524 }, { name: 'Lisa Brown', apartment: 201, hairColor: 0xFFD700, eyeSpacing: 48, noseSize: 0.9, mouthWidth: 1.1, skinTone: 0xdeb887 }, { name: 'Mike Davis', apartment: 202, hairColor: 0x8B0000, eyeSpacing: 52, noseSize: 1.1, mouthWidth: 0.8, skinTone: 0x654321 }, { name: 'Sarah Garcia', apartment: 203, hairColor: 0x2E8B57, eyeSpacing: 42, noseSize: 0.7, mouthWidth: 1.3, skinTone: 0xfdbcb4 }, { name: 'David Chen', apartment: 301, hairColor: 0x000000, eyeSpacing: 47, noseSize: 1.2, mouthWidth: 0.9, skinTone: 0xffdbac }, { name: 'Emma Williams', apartment: 302, hairColor: 0xDC143C, eyeSpacing: 53, noseSize: 0.9, mouthWidth: 1.0, skinTone: 0xf1c27d }, { name: 'Alex Rodriguez', apartment: 303, hairColor: 0x4B0082, eyeSpacing: 49, noseSize: 1.1, mouthWidth: 1.1, skinTone: 0xdeb887 }, { name: 'Nina Petrov', apartment: 401, hairColor: 0xFF1493, eyeSpacing: 44, noseSize: 0.8, mouthWidth: 1.4, skinTone: 0xfdbcb4 }]; function showMainMenu() { currentMenu = game.addChild(new MainMenu()); } function showSettings() { currentMenu = game.addChild(new SettingsMenu()); } function startGame() { gameActive = true; gameStarted = true; score = 0; mistakes = 0; visitorCount = 0; LK.setScore(0); // Clear visited names for new game visitedNames = []; storage.visitedNames = []; updateButtonTexts(); LK.setTimeout(spawnVisitor, 2000); } // Create background var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); // Create desk var desk = game.addChild(LK.getAsset('desk', { anchorX: 0.5, anchorY: 1.0, x: 1024, y: 2732 })); // Create buttons var approveButton = game.addChild(LK.getAsset('denyButton', { anchorX: 0.5, anchorY: 0.5, x: 700, y: 2500 })); approveButton.tint = 0x27ae60; var denyButton = game.addChild(LK.getAsset('denyButton', { anchorX: 0.5, anchorY: 0.5, x: 1348, y: 2500 })); // Button labels var approveText = new Text2('APPROVE', { size: 55, fill: '#ffffff' }); approveText.anchor.set(0.5, 0.5); approveText.x = 700; approveText.y = 2500; game.addChild(approveText); var denyText = new Text2('DENY', { size: 55, fill: '#ffffff' }); denyText.anchor.set(0.5, 0.5); denyText.x = 1348; denyText.y = 2500; game.addChild(denyText); function updateButtonTexts() { var language = storage.language || 'en'; if (language === 'tr') { approveText.setText('ONAYLA'); denyText.setText('REDDET'); scoreText.setText('Puan: ' + LK.getScore()); mistakesText.setText('Hatalar: ' + mistakes + '/' + maxMistakes); instructionText.setText('Ziyaretciyi kimligi ve kayitlariyla karsilastirin. Konusma, davranis ve gorsel ipuclarini kontrol edin!'); } else { approveText.setText('APPROVE'); denyText.setText('DENY'); scoreText.setText('Score: ' + LK.getScore()); mistakesText.setText('Mistakes: ' + mistakes + '/' + maxMistakes); instructionText.setText('Compare visitor to ID and records. Check conversation, behavior and visual clues!'); } } function showClueNotification(clueText) { var clueBox = game.addChild(new ConversationBox()); clueBox.x = 1024; clueBox.y = 400; clueBox.showMessage("🚨 " + clueText); clueBox.messageText.tint = 0xff6b6b; LK.setTimeout(function () { if (clueBox) { clueBox.hideMessage(); } }, 3000); } // Score display var scoreText = new Text2('Score: 0', { size: 75, fill: '#ffffff' }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Mistakes display var mistakesText = new Text2('Mistakes: 0/3', { size: 55, fill: '#ff6b6b' }); mistakesText.anchor.set(1, 0); mistakesText.x = 2048 - 50; mistakesText.y = 100; game.addChild(mistakesText); // Instructions var instructionText = new Text2('Compare visitor to ID and records. Check conversation, behavior and visual clues!', { size: 45, fill: '#ecf0f1', maxWidth: 600, wordWrap: true, align: 'left' }); instructionText.anchor.set(0, 0); instructionText.x = 150; instructionText.y = 150; game.addChild(instructionText); function getRandomResident() { return residents[Math.floor(Math.random() * residents.length)]; } function createDoppelgangerFeatures(originalFeatures) { var features = { hairColor: originalFeatures.hairColor, eyeSpacing: originalFeatures.eyeSpacing, noseSize: originalFeatures.noseSize, mouthWidth: originalFeatures.mouthWidth, isObviousAnomaly: false, anomalyType: '' }; // 60% chance for obvious anomaly, 40% for subtle var isObvious = Math.random() < 0.6; if (isObvious) { features.isObviousAnomaly = true; var anomalyTypes = ['eye', 'mouth', 'nose', 'hair']; features.anomalyType = anomalyTypes[Math.floor(Math.random() * anomalyTypes.length)]; } else { // Subtle changes var changeType = Math.floor(Math.random() * 4); switch (changeType) { case 0: // Hair color - more dramatic changes var colors = [0x654321, 0x8B4513, 0x2F4F4F, 0xFFD700, 0x8B0000, 0x2E8B57, 0x000000, 0xDC143C, 0x4B0082, 0xFF1493]; do { features.hairColor = colors[Math.floor(Math.random() * colors.length)]; } while (features.hairColor === originalFeatures.hairColor); break; case 1: // Eye spacing - more noticeable features.eyeSpacing = originalFeatures.eyeSpacing + (Math.random() > 0.5 ? 15 : -15); break; case 2: // Nose size - more dramatic features.noseSize = originalFeatures.noseSize + (Math.random() > 0.5 ? 0.6 : -0.5); break; case 3: // Mouth width - more noticeable features.mouthWidth = originalFeatures.mouthWidth + (Math.random() > 0.5 ? 0.7 : -0.6); break; } } return features; } function spawnVisitor() { if (!gameActive) return; visitorCount++; var resident = getRandomResident(); // Check if this name has been visited before var hasVisitedBefore = visitedNames.indexOf(resident.name) !== -1; // If name visited before, automatically make it a doppelganger // Otherwise use random chance var isDoppelganger = hasVisitedBefore || Math.random() < 0.4; // 40% chance of doppelganger // Add name to visited list if not already there if (!hasVisitedBefore) { visitedNames.push(resident.name); storage.visitedNames = visitedNames; } // Create visitor currentVisitor = game.addChild(new Visitor()); currentVisitor.x = 1024; currentVisitor.y = 1800; currentVisitor.name = resident.name; currentVisitor.apartmentNumber = resident.apartment; currentVisitor.isDoppelganger = isDoppelganger; var visitorFeatures = isDoppelganger ? createDoppelgangerFeatures(resident) : resident; currentVisitor.setFeatures(visitorFeatures); // Store additional clues for doppelgangers currentVisitor.hasTimeClue = isDoppelganger && Math.random() < 0.3; currentVisitor.hasBehaviorClue = isDoppelganger && Math.random() < 0.4; currentVisitor.hasStoryClue = isDoppelganger && Math.random() < 0.5; // Create ID card (ALWAYS shows original resident features, never doppelganger features) currentIDCard = game.addChild(new IDCard()); currentIDCard.x = 400; currentIDCard.y = 2300; currentIDCard.setInfo(resident.name, resident.apartment, resident, isDoppelganger); // Create building record (always shows correct resident info) currentRecord = game.addChild(new RecordCard()); currentRecord.x = 1648; currentRecord.y = 2300; currentRecord.setInfo(resident.name, resident.apartment, resident); // Create middle image between the two cards var middleImage = game.addChild(LK.getAsset('middleImage', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2300 })); // Create conversation box currentConversation = game.addChild(new ConversationBox()); currentConversation.x = 1024; currentConversation.y = 1000; // Show visitor's reason for visiting var language = storage.language || 'en'; var reasons = visitReasons[language]; var randomReason = reasons[Math.floor(Math.random() * reasons.length)]; // For doppelgangers, sometimes give suspicious reasons if (isDoppelganger && Math.random() < 0.6) { if (language === 'tr') { var suspiciousReasons = ["Sadece... arkadaşımı ziyarete geliyorum...", "Burada yaşadığımı unuttum mu? Tabii ki buraya aittim!", "Normal insan aktiviteleri için buradayım.", "Size neden söylemek zorundayım? Ben buralıyım!", "Daire numaramı mı? Şey... 20... 3? Evet, 203!"]; } else { var suspiciousReasons = ["I'm just... visiting my friend...", "Did I forget I live here? Of course I belong here!", "I'm here for normal human activities.", "Why should I tell you? I belong here!", "My apartment? Uh... 20... 3? Yes, 203!"]; } randomReason = suspiciousReasons[Math.floor(Math.random() * suspiciousReasons.length)]; } currentConversation.showMessage(randomReason); // Auto-hide conversation after 4 seconds LK.setTimeout(function () { if (currentConversation) { currentConversation.hideMessage(); currentConversation = null; } }, 4000); // Animate visitor entrance currentVisitor.y = 1200; tween(currentVisitor, { y: 1800 }, { duration: 1000 }); if (storage.soundEnabled !== false) { LK.getSound('doorbell').play(); } } function handleDecision(approved) { if (!gameActive || !currentVisitor) return; var correct = approved && !currentVisitor.isDoppelganger || !approved && currentVisitor.isDoppelganger; var language = storage.language || 'en'; if (correct) { score += 10; LK.setScore(score); var scoreLabel = language === 'tr' ? 'Puan: ' : 'Score: '; scoreText.setText(scoreLabel + score); if (storage.soundEnabled !== false) { LK.getSound('correct').play(); } if (currentVisitor.isDoppelganger) { LK.effects.flashObject(currentVisitor, 0xff0000, 500); // Check if this was a repeat visitor var wasRepeatVisitor = visitedNames.indexOf(currentVisitor.name) !== -1 && visitedNames.lastIndexOf(currentVisitor.name) !== visitedNames.length - 1; if (wasRepeatVisitor) { var repeatText = language === 'tr' ? "Doğru! Bu kişi daha önce gelmişti - Tekrar ziyaretçi tespit edildi!" : "Correct! This person visited before - Repeat visitor detected!"; showClueNotification(repeatText); } else { // Show what clues were available var cluesFound = []; if (currentVisitor.hasTimeClue) cluesFound.push(language === 'tr' ? "Zaman ipucu" : "Time clue"); if (currentVisitor.hasBehaviorClue) cluesFound.push(language === 'tr' ? "Davranış ipucu" : "Behavior clue"); if (currentVisitor.hasStoryClue) cluesFound.push(language === 'tr' ? "Hikaye ipucu" : "Story clue"); if (cluesFound.length > 0) { var clueText = language === 'tr' ? "Doğru! Bulduğunuz ipuçları: " + cluesFound.join(", ") : "Correct! Clues found: " + cluesFound.join(", "); showClueNotification(clueText); } } } else { LK.effects.flashObject(currentVisitor, 0x00ff00, 500); } } else { mistakes++; var mistakeLabel = language === 'tr' ? 'Hatalar: ' : 'Mistakes: '; mistakesText.setText(mistakeLabel + mistakes + '/' + maxMistakes); if (storage.soundEnabled !== false) { LK.getSound('wrong').play(); } LK.effects.flashScreen(0xff0000, 300); // Show missed clues if it was a doppelganger if (currentVisitor.isDoppelganger && !approved) { var missedClues = []; if (currentVisitor.hasTimeClue) missedClues.push(language === 'tr' ? "Zaman ipucu" : "Time clue"); if (currentVisitor.hasBehaviorClue) missedClues.push(language === 'tr' ? "Davranış ipucu" : "Behavior clue"); if (currentVisitor.hasStoryClue) missedClues.push(language === 'tr' ? "Hikaye ipucu" : "Story clue"); if (missedClues.length > 0) { var missedText = language === 'tr' ? "Kaçırdığınız ipuçları: " + missedClues.join(", ") : "Missed clues: " + missedClues.join(", "); showClueNotification(missedText); } } if (mistakes >= maxMistakes) { gameActive = false; gameStarted = false; // Transform current visitor into anomaly killer if (currentVisitor) { // Hide conversation and cards first if (currentConversation) { currentConversation.destroy(); currentConversation = null; } if (currentIDCard) { currentIDCard.destroy(); currentIDCard = null; } if (currentRecord) { currentRecord.destroy(); currentRecord = null; } if (middleImage) { middleImage.destroy(); middleImage = null; } // Transform the visitor into an anomaly killer tween(currentVisitor, { tint: 0x1a1a1a, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { // Create proper anomaly killer to replace visitor var anomalyKiller = game.addChild(new AnomalyKiller()); if (currentVisitor) { anomalyKiller.x = currentVisitor.x; anomalyKiller.y = currentVisitor.y; currentVisitor.destroy(); currentVisitor = null; } else { anomalyKiller.x = 1024; anomalyKiller.y = 1800; } anomalyKiller.killPlayer(); } }); } else { // Fallback: spawn new anomaly killer if no current visitor var anomalyKiller = game.addChild(new AnomalyKiller()); anomalyKiller.killPlayer(); } return; } } // Clean up conversation if still active if (currentConversation) { currentConversation.destroy(); currentConversation = null; } // Remove current visitor and cards tween(currentVisitor, { y: 1200 }, { duration: 800, onFinish: function onFinish() { if (currentVisitor) { currentVisitor.destroy(); } if (currentIDCard) { currentIDCard.destroy(); } if (currentRecord) { currentRecord.destroy(); } if (middleImage) { middleImage.destroy(); } currentVisitor = null; currentIDCard = null; currentRecord = null; // Spawn next visitor after a short delay if (gameActive) { LK.setTimeout(spawnVisitor, 1500); } } }); // Check win condition if (score >= 100) { gameActive = false; gameStarted = false; LK.setTimeout(function () { LK.showYouWin(); }, 1000); } } // Button event handlers approveButton.down = function (x, y, obj) { if (gameActive && currentVisitor) { // Enhanced button animation tween(approveButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, onFinish: function onFinish() { tween(approveButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.bounceOut }); } }); LK.effects.flashObject(approveButton, 0xffffff, 200); handleDecision(true); } }; denyButton.down = function (x, y, obj) { if (gameActive && currentVisitor) { // Enhanced button animation tween(denyButton, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100, onFinish: function onFinish() { tween(denyButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.bounceOut }); } }); LK.effects.flashObject(denyButton, 0xffffff, 200); handleDecision(false); } }; // Initialize main menu showMainMenu(); game.update = function () { // Game loop - update score display only when game is active if (gameStarted && gameActive) { var language = storage.language || 'en'; var scoreLabel = language === 'tr' ? 'Puan: ' : 'Score: '; scoreText.setText(scoreLabel + LK.getScore()); } // Hide instruction text and buttons when not in game if (gameStarted) { instructionText.alpha = 1; approveButton.alpha = 1; denyButton.alpha = 1; approveText.alpha = 1; denyText.alpha = 1; } else { instructionText.alpha = 0; approveButton.alpha = 0; denyButton.alpha = 0; approveText.alpha = 0; denyText.alpha = 0; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
language: "en",
soundEnabled: true
});
/****
* Classes
****/
var AnomalyKiller = Container.expand(function () {
var self = Container.call(this);
// Create menacing appearance
var body = self.attachAsset('visitor', {
anchorX: 0.5,
anchorY: 1.0
});
body.tint = 0x1a1a1a; // Dark body
var head = self.attachAsset('visitorHead', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -200
});
head.tint = 0x2a2a2a; // Dark head
var leftEye = self.attachAsset('visitorEye', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: -210
});
leftEye.tint = 0xff0000; // Red glowing eyes
leftEye.scaleX = 1.5;
leftEye.scaleY = 1.5;
var rightEye = self.attachAsset('visitorEye', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: -210
});
rightEye.tint = 0xff0000; // Red glowing eyes
rightEye.scaleX = 1.5;
rightEye.scaleY = 1.5;
var mouth = self.attachAsset('visitorMouth', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -170
});
mouth.tint = 0x8b0000; // Dark red mouth
mouth.scaleX = 2.0; // Large menacing mouth
// Start off-screen
self.x = 1024;
self.y = -500;
self.alpha = 0;
self.killPlayer = function () {
// Dramatic entrance animation
tween(self, {
y: 1400,
alpha: 1
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
// Flash red eyes
tween(leftEye, {
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 300,
easing: tween.easeInOut
});
tween(rightEye, {
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 300,
easing: tween.easeInOut
});
// Screen flash and kill
LK.setTimeout(function () {
LK.effects.flashScreen(0xff0000, 1500);
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}, 500);
}
});
};
return self;
});
var ConversationBox = Container.expand(function () {
var self = Container.call(this);
var boxBackground = self.attachAsset('idCard', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.8
});
boxBackground.tint = 0xf0f0f0;
self.messageText = new Text2('', {
size: 42,
fill: '#2c3e50'
});
self.messageText.anchor.set(0.5, 0.5);
self.messageText.x = 0;
self.messageText.y = 0;
self.addChild(self.messageText);
self.showMessage = function (message) {
self.messageText.setText(message);
// Dynamically resize box based on text content
var textBounds = self.messageText.getBounds();
var padding = 40;
var minWidth = 400;
var minHeight = 120;
var maxWidth = 1600;
// Calculate required dimensions
var requiredWidth = Math.max(minWidth, Math.min(maxWidth, textBounds.width + padding * 2));
var requiredHeight = Math.max(minHeight, textBounds.height + padding * 2);
var baseWidth = 400;
var baseHeight = 250;
boxBackground.scaleX = requiredWidth / baseWidth;
boxBackground.scaleY = requiredHeight / baseHeight;
self.alpha = 0;
tween(self, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
};
self.hideMessage = function () {
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var IDCard = Container.expand(function () {
var self = Container.call(this);
var cardBackground = self.attachAsset('idCard', {
anchorX: 0.5,
anchorY: 0.5
});
// Create mini visitor face on ID
var miniHead = self.attachAsset('visitorHead', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: -20,
scaleX: 0.6,
scaleY: 0.6
});
var miniHair = self.attachAsset('visitorHair', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: -40,
scaleX: 0.6,
scaleY: 0.6
});
var miniLeftEye = self.attachAsset('visitorEye', {
anchorX: 0.5,
anchorY: 0.5,
x: -135,
y: -25,
scaleX: 0.6,
scaleY: 0.6
});
var miniRightEye = self.attachAsset('visitorEye', {
anchorX: 0.5,
anchorY: 0.5,
x: -105,
y: -25,
scaleX: 0.6,
scaleY: 0.6
});
var miniNose = self.attachAsset('visitorNose', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: -10,
scaleX: 0.6,
scaleY: 0.6
});
var miniMouth = self.attachAsset('visitorMouth', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: 5,
scaleX: 0.6,
scaleY: 0.6
});
self.nameText = new Text2('', {
size: 45,
fill: '#000000'
});
self.nameText.anchor.set(0, 0.5);
self.nameText.x = 20;
self.nameText.y = -60;
self.addChild(self.nameText);
self.apartmentText = new Text2('', {
size: 40,
fill: '#000000'
});
self.apartmentText.anchor.set(0, 0.5);
self.apartmentText.x = 20;
self.apartmentText.y = -20;
self.addChild(self.apartmentText);
self.setInfo = function (name, apartment, features, isRandomized) {
var language = storage.language || 'en';
var nameLabel = language === 'tr' ? 'Isim: ' : 'Name: ';
var aptLabel = language === 'tr' ? 'Daire: ' : 'Apt: ';
self.nameText.setText(nameLabel + name);
// Create apartment discrepancy for doppelgangers
var displayApartment = apartment;
if (isRandomized && Math.random() < 0.6) {
// 60% chance of apartment mismatch for doppelgangers
var apartmentNumbers = [101, 102, 103, 201, 202, 203, 301, 302, 303, 401];
do {
displayApartment = apartmentNumbers[Math.floor(Math.random() * apartmentNumbers.length)];
} while (displayApartment === apartment);
}
self.apartmentText.setText(aptLabel + displayApartment);
// Dynamically resize card based on text content
var nameBounds = self.nameText.getBounds();
var aptBounds = self.apartmentText.getBounds();
var maxTextWidth = Math.max(nameBounds.width, aptBounds.width);
var padding = 40;
var minWidth = 400;
var requiredWidth = Math.max(minWidth, maxTextWidth + 160 + padding);
var baseWidth = 400;
if (requiredWidth > baseWidth) {
cardBackground.scaleX = requiredWidth / baseWidth;
}
// ID card should always show the original resident features, not doppelganger features
var idFeatures = features;
miniHair.tint = idFeatures.hairColor;
miniLeftEye.x = -120 - idFeatures.eyeSpacing * 0.3;
miniRightEye.x = -120 + idFeatures.eyeSpacing * 0.3;
miniNose.scaleX = idFeatures.noseSize * 0.6;
miniNose.scaleY = idFeatures.noseSize * 0.6;
miniMouth.scaleX = idFeatures.mouthWidth * 0.6;
// Set skin tone if available
if (idFeatures.skinTone) {
miniHead.tint = idFeatures.skinTone;
}
};
return self;
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
var language = storage.language || 'en';
var texts = {
en: {
title: 'DOPPELGANGER DETECTIVE',
play: 'PLAY',
settings: 'SETTINGS',
back: 'BACK',
language: 'LANGUAGE: ENGLISH',
sound: 'SOUND: ON',
soundOff: 'SOUND: OFF'
},
tr: {
title: 'DOPPELGANGER DEDEKTIFI',
play: 'OYNA',
settings: 'AYARLAR',
back: 'GERI',
language: 'DIL: TURKCE',
sound: 'SES: ACIK',
soundOff: 'SES: KAPALI'
}
};
self.currentTexts = texts[language];
// Title
self.titleText = new Text2(self.currentTexts.title, {
size: 80,
fill: '#e74c3c'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 600;
self.titleText.alpha = 0;
self.addChild(self.titleText);
// Animate title entrance
tween(self.titleText, {
alpha: 1,
y: 800
}, {
duration: 1500,
easing: tween.easeOut
});
// Play button
self.playButtonBg = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1400
});
self.playText = new Text2(self.currentTexts.play, {
size: 50,
fill: '#ffffff'
});
self.playText.anchor.set(0.5, 0.5);
self.playText.x = 1024;
self.playText.y = 1400;
self.playText.alpha = 0;
self.playButtonBg.alpha = 0;
self.addChild(self.playText);
// Animate play button entrance
LK.setTimeout(function () {
tween(self.playButtonBg, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
tween(self.playText, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
}, 500);
// Settings button
self.settingsButtonBg = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1550
});
self.settingsText = new Text2(self.currentTexts.settings, {
size: 50,
fill: '#ffffff'
});
self.settingsText.anchor.set(0.5, 0.5);
self.settingsText.x = 1024;
self.settingsText.y = 1550;
self.settingsText.alpha = 0;
self.settingsButtonBg.alpha = 0;
self.addChild(self.settingsText);
// Animate settings button entrance
LK.setTimeout(function () {
tween(self.settingsButtonBg, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
tween(self.settingsText, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
}, 800);
self.playButtonBg.down = function () {
// Play button sound effect
if (storage.soundEnabled !== false) {
LK.getSound('menuButtonSound').play();
}
// Animate button press
tween(self.playButtonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(self.playButtonBg, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
self.destroy();
startGame();
}
});
}
});
};
self.settingsButtonBg.down = function () {
// Play button sound effect
if (storage.soundEnabled !== false) {
LK.getSound('settingsButtonSound').play();
}
// Animate button press
tween(self.settingsButtonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(self.settingsButtonBg, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
self.destroy();
showSettings();
}
});
}
});
};
return self;
});
var RecordCard = Container.expand(function () {
var self = Container.call(this);
var cardBackground = self.attachAsset('recordCard', {
anchorX: 0.5,
anchorY: 0.5
});
// Create mini resident face on record
var miniHead = self.attachAsset('visitorHead', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: -20,
scaleX: 0.6,
scaleY: 0.6
});
var miniHair = self.attachAsset('visitorHair', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: -40,
scaleX: 0.6,
scaleY: 0.6
});
var miniLeftEye = self.attachAsset('visitorEye', {
anchorX: 0.5,
anchorY: 0.5,
x: -135,
y: -25,
scaleX: 0.6,
scaleY: 0.6
});
var miniRightEye = self.attachAsset('visitorEye', {
anchorX: 0.5,
anchorY: 0.5,
x: -105,
y: -25,
scaleX: 0.6,
scaleY: 0.6
});
var miniNose = self.attachAsset('visitorNose', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: -10,
scaleX: 0.6,
scaleY: 0.6
});
var miniMouth = self.attachAsset('visitorMouth', {
anchorX: 0.5,
anchorY: 0.5,
x: -120,
y: 5,
scaleX: 0.6,
scaleY: 0.6
});
self.nameText = new Text2('', {
size: 45,
fill: '#000000'
});
self.nameText.anchor.set(0, 0.5);
self.nameText.x = 20;
self.nameText.y = -60;
self.addChild(self.nameText);
self.apartmentText = new Text2('', {
size: 40,
fill: '#000000'
});
self.apartmentText.anchor.set(0, 0.5);
self.apartmentText.x = 20;
self.apartmentText.y = -20;
self.addChild(self.apartmentText);
self.setInfo = function (name, apartment, features) {
var language = storage.language || 'en';
var recordLabel = language === 'tr' ? 'Kayit: ' : 'Record: ';
var aptLabel = language === 'tr' ? 'Daire: ' : 'Apt: ';
self.nameText.setText(recordLabel + name);
self.apartmentText.setText(aptLabel + apartment);
// Dynamically resize card based on text content
var nameBounds = self.nameText.getBounds();
var aptBounds = self.apartmentText.getBounds();
var maxTextWidth = Math.max(nameBounds.width, aptBounds.width);
var padding = 40;
var minWidth = 400;
var requiredWidth = Math.max(minWidth, maxTextWidth + 160 + padding);
var baseWidth = 400;
if (requiredWidth > baseWidth) {
cardBackground.scaleX = requiredWidth / baseWidth;
}
miniHair.tint = features.hairColor;
miniLeftEye.x = -120 - features.eyeSpacing * 0.3;
miniRightEye.x = -120 + features.eyeSpacing * 0.3;
miniNose.scaleX = features.noseSize * 0.6;
miniNose.scaleY = features.noseSize * 0.6;
miniMouth.scaleX = features.mouthWidth * 0.6;
// Set skin tone if available
if (features.skinTone) {
miniHead.tint = features.skinTone;
}
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
var language = storage.language || 'en';
var soundEnabled = storage.soundEnabled !== false;
var texts = {
en: {
settings: 'SETTINGS',
back: 'BACK',
language: 'LANGUAGE: ENGLISH',
languageTr: 'LANGUAGE: TURKISH',
sound: 'SOUND: ON',
soundOff: 'SOUND: OFF'
},
tr: {
settings: 'AYARLAR',
back: 'GERI',
language: 'DIL: TURKCE',
languageEn: 'DIL: INGILIZCE',
sound: 'SES: ACIK',
soundOff: 'SES: KAPALI'
}
};
self.currentTexts = texts[language];
// Settings title
self.titleText = new Text2(self.currentTexts.settings, {
size: 70,
fill: '#2c3e50'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 600;
self.addChild(self.titleText);
// Language button
self.langButtonBg = self.attachAsset('languageButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1000
});
self.langText = new Text2(language === 'en' ? self.currentTexts.language : self.currentTexts.language, {
size: 40,
fill: '#ffffff'
});
self.langText.anchor.set(0.5, 0.5);
self.langText.x = 1024;
self.langText.y = 1000;
self.addChild(self.langText);
// Sound button
self.soundButtonBg = self.attachAsset('soundButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1150
});
self.soundText = new Text2(soundEnabled ? self.currentTexts.sound : self.currentTexts.soundOff, {
size: 40,
fill: '#ffffff'
});
self.soundText.anchor.set(0.5, 0.5);
self.soundText.x = 1024;
self.soundText.y = 1150;
self.addChild(self.soundText);
// Back button
self.backButtonBg = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1400
});
self.backText = new Text2(self.currentTexts.back, {
size: 40,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 1400;
self.addChild(self.backText);
self.langButtonBg.down = function () {
// Play button sound effect
if (storage.soundEnabled !== false) {
LK.getSound('toggleButtonSound').play();
}
// Animate button press
tween(self.langButtonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(self.langButtonBg, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
storage.language = storage.language === 'en' ? 'tr' : 'en';
self.destroy();
showSettings();
}
});
}
});
};
self.soundButtonBg.down = function () {
// Play button sound effect (before toggling sound)
if (storage.soundEnabled !== false) {
LK.getSound('toggleButtonSound').play();
}
// Animate button press
tween(self.soundButtonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(self.soundButtonBg, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
storage.soundEnabled = !storage.soundEnabled;
self.destroy();
showSettings();
}
});
}
});
};
self.backButtonBg.down = function () {
// Play button sound effect
if (storage.soundEnabled !== false) {
LK.getSound('backButtonSound').play();
}
// Animate button press
tween(self.backButtonBg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100,
onFinish: function onFinish() {
tween(self.backButtonBg, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
onFinish: function onFinish() {
self.destroy();
showMainMenu();
}
});
}
});
};
return self;
});
var Visitor = Container.expand(function () {
var self = Container.call(this);
// Create visitor appearance with more variety
var body = self.attachAsset('visitor', {
anchorX: 0.5,
anchorY: 1.0
});
var head = self.attachAsset('visitorHead', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -200
});
var hair = self.attachAsset('visitorHair', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -240
});
var leftEye = self.attachAsset('visitorEye', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: -210
});
var rightEye = self.attachAsset('visitorEye', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: -210
});
var nose = self.attachAsset('visitorNose', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -190
});
var mouth = self.attachAsset('visitorMouth', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -170
});
// Visitor properties
self.name = '';
self.apartmentNumber = 0;
self.isDoppelganger = false;
self.hairColor = 0x654321;
self.eyeSpacing = 50;
self.noseSize = 1.0;
self.mouthWidth = 1.0;
self.skinTone = 0xfdbcb4;
self.eyeColor = 0x2c3e50;
self.setFeatures = function (features) {
hair.tint = features.hairColor;
leftEye.x = -features.eyeSpacing / 2;
rightEye.x = features.eyeSpacing / 2;
nose.scaleX = features.noseSize;
nose.scaleY = features.noseSize;
mouth.scaleX = features.mouthWidth;
self.hairColor = features.hairColor;
self.eyeSpacing = features.eyeSpacing;
self.noseSize = features.noseSize;
self.mouthWidth = features.mouthWidth;
// Use skin tone from features if available
if (features.skinTone) {
self.skinTone = features.skinTone;
head.tint = self.skinTone;
body.tint = self.skinTone;
}
// Make anomalies very obvious for doppelgangers
if (features.isObviousAnomaly) {
if (features.anomalyType === 'eye') {
leftEye.tint = 0xff0000; // Red eye
rightEye.scaleX = 1.5; // Different sized eyes
} else if (features.anomalyType === 'mouth') {
mouth.tint = 0x0000ff; // Blue mouth
mouth.rotation = 0.2; // Tilted mouth
} else if (features.anomalyType === 'nose') {
nose.tint = 0x00ff00; // Green nose
nose.scaleX = 2.0; // Very large nose
} else if (features.anomalyType === 'hair') {
hair.tint = 0xff00ff; // Bright magenta hair
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
// Game state
var currentVisitor = null;
var currentIDCard = null;
var currentRecord = null;
var currentConversation = null;
var middleImage = null;
var gameActive = false;
var score = 0;
var mistakes = 0;
var maxMistakes = 3;
var visitorCount = 0;
var gameStarted = false;
var currentMenu = null;
// Track visited names for doppelganger detection
var visitedNames = storage.visitedNames || [];
// Visitor reasons database
var visitReasons = {
en: ["I'm here to visit my friend in apartment 102.", "I need to deliver a package to my neighbor.", "I forgot my keys and need to get spare from building manager.", "I'm here for a dinner party tonight.", "I need to check on my elderly neighbor.", "I'm bringing groceries to my sick roommate.", "I have a repair appointment scheduled today.", "I'm here to pick up my mail from vacation.", "I need to return borrowed tools to my friend.", "I'm visiting my cousin who lives here."],
tr: ["102 numaralı dairede arkadaşımı ziyarete geliyorum.", "Komşuma paket teslim etmem gerekiyor.", "Anahtarlarımı unuttum, yöneticiden yedek almam lazım.", "Bu akşam yemek partisi için geliyorum.", "Yaşlı komşumu kontrol etmem gerekiyor.", "Hasta ev arkadaşıma market alışverişi getiriyorum.", "Bugün tamirat randevum var.", "Tatilden postalarımı almaya geliyorum.", "Arkadaşımdan ödünç aldığım aletleri geri vermeye geliyorum.", "Burada yaşayan kuzenimle buluşmaya geliyorum."]
};
// Additional clues system
var additionalClues = {
timeClues: ["Visitor arrived at unusual hour", "Claims to have appointment but building is closed", "Says visiting friend but it's very late"],
behaviorClues: ["Visitor seems nervous and sweating", "Avoiding eye contact", "Fidgeting with hands constantly", "Speaking too quickly", "Can't remember apartment number clearly"],
storyClues: ["Story doesn't match resident's schedule", "Claims relationship that doesn't exist", "Knows too much personal information", "Contradicts previous statements"]
};
// Enhanced resident database with more variety
var residents = [{
name: 'John Smith',
apartment: 101,
hairColor: 0x654321,
eyeSpacing: 50,
noseSize: 1.0,
mouthWidth: 1.0,
skinTone: 0xfdbcb4
}, {
name: 'Mary Johnson',
apartment: 102,
hairColor: 0x8B4513,
eyeSpacing: 45,
noseSize: 0.8,
mouthWidth: 1.2,
skinTone: 0xf1c27d
}, {
name: 'Bob Wilson',
apartment: 103,
hairColor: 0x2F4F4F,
eyeSpacing: 55,
noseSize: 1.3,
mouthWidth: 0.9,
skinTone: 0x8d5524
}, {
name: 'Lisa Brown',
apartment: 201,
hairColor: 0xFFD700,
eyeSpacing: 48,
noseSize: 0.9,
mouthWidth: 1.1,
skinTone: 0xdeb887
}, {
name: 'Mike Davis',
apartment: 202,
hairColor: 0x8B0000,
eyeSpacing: 52,
noseSize: 1.1,
mouthWidth: 0.8,
skinTone: 0x654321
}, {
name: 'Sarah Garcia',
apartment: 203,
hairColor: 0x2E8B57,
eyeSpacing: 42,
noseSize: 0.7,
mouthWidth: 1.3,
skinTone: 0xfdbcb4
}, {
name: 'David Chen',
apartment: 301,
hairColor: 0x000000,
eyeSpacing: 47,
noseSize: 1.2,
mouthWidth: 0.9,
skinTone: 0xffdbac
}, {
name: 'Emma Williams',
apartment: 302,
hairColor: 0xDC143C,
eyeSpacing: 53,
noseSize: 0.9,
mouthWidth: 1.0,
skinTone: 0xf1c27d
}, {
name: 'Alex Rodriguez',
apartment: 303,
hairColor: 0x4B0082,
eyeSpacing: 49,
noseSize: 1.1,
mouthWidth: 1.1,
skinTone: 0xdeb887
}, {
name: 'Nina Petrov',
apartment: 401,
hairColor: 0xFF1493,
eyeSpacing: 44,
noseSize: 0.8,
mouthWidth: 1.4,
skinTone: 0xfdbcb4
}];
function showMainMenu() {
currentMenu = game.addChild(new MainMenu());
}
function showSettings() {
currentMenu = game.addChild(new SettingsMenu());
}
function startGame() {
gameActive = true;
gameStarted = true;
score = 0;
mistakes = 0;
visitorCount = 0;
LK.setScore(0);
// Clear visited names for new game
visitedNames = [];
storage.visitedNames = [];
updateButtonTexts();
LK.setTimeout(spawnVisitor, 2000);
}
// Create background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create desk
var desk = game.addChild(LK.getAsset('desk', {
anchorX: 0.5,
anchorY: 1.0,
x: 1024,
y: 2732
}));
// Create buttons
var approveButton = game.addChild(LK.getAsset('denyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 2500
}));
approveButton.tint = 0x27ae60;
var denyButton = game.addChild(LK.getAsset('denyButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1348,
y: 2500
}));
// Button labels
var approveText = new Text2('APPROVE', {
size: 55,
fill: '#ffffff'
});
approveText.anchor.set(0.5, 0.5);
approveText.x = 700;
approveText.y = 2500;
game.addChild(approveText);
var denyText = new Text2('DENY', {
size: 55,
fill: '#ffffff'
});
denyText.anchor.set(0.5, 0.5);
denyText.x = 1348;
denyText.y = 2500;
game.addChild(denyText);
function updateButtonTexts() {
var language = storage.language || 'en';
if (language === 'tr') {
approveText.setText('ONAYLA');
denyText.setText('REDDET');
scoreText.setText('Puan: ' + LK.getScore());
mistakesText.setText('Hatalar: ' + mistakes + '/' + maxMistakes);
instructionText.setText('Ziyaretciyi kimligi ve kayitlariyla karsilastirin. Konusma, davranis ve gorsel ipuclarini kontrol edin!');
} else {
approveText.setText('APPROVE');
denyText.setText('DENY');
scoreText.setText('Score: ' + LK.getScore());
mistakesText.setText('Mistakes: ' + mistakes + '/' + maxMistakes);
instructionText.setText('Compare visitor to ID and records. Check conversation, behavior and visual clues!');
}
}
function showClueNotification(clueText) {
var clueBox = game.addChild(new ConversationBox());
clueBox.x = 1024;
clueBox.y = 400;
clueBox.showMessage("🚨 " + clueText);
clueBox.messageText.tint = 0xff6b6b;
LK.setTimeout(function () {
if (clueBox) {
clueBox.hideMessage();
}
}, 3000);
}
// Score display
var scoreText = new Text2('Score: 0', {
size: 75,
fill: '#ffffff'
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Mistakes display
var mistakesText = new Text2('Mistakes: 0/3', {
size: 55,
fill: '#ff6b6b'
});
mistakesText.anchor.set(1, 0);
mistakesText.x = 2048 - 50;
mistakesText.y = 100;
game.addChild(mistakesText);
// Instructions
var instructionText = new Text2('Compare visitor to ID and records. Check conversation, behavior and visual clues!', {
size: 45,
fill: '#ecf0f1',
maxWidth: 600,
wordWrap: true,
align: 'left'
});
instructionText.anchor.set(0, 0);
instructionText.x = 150;
instructionText.y = 150;
game.addChild(instructionText);
function getRandomResident() {
return residents[Math.floor(Math.random() * residents.length)];
}
function createDoppelgangerFeatures(originalFeatures) {
var features = {
hairColor: originalFeatures.hairColor,
eyeSpacing: originalFeatures.eyeSpacing,
noseSize: originalFeatures.noseSize,
mouthWidth: originalFeatures.mouthWidth,
isObviousAnomaly: false,
anomalyType: ''
};
// 60% chance for obvious anomaly, 40% for subtle
var isObvious = Math.random() < 0.6;
if (isObvious) {
features.isObviousAnomaly = true;
var anomalyTypes = ['eye', 'mouth', 'nose', 'hair'];
features.anomalyType = anomalyTypes[Math.floor(Math.random() * anomalyTypes.length)];
} else {
// Subtle changes
var changeType = Math.floor(Math.random() * 4);
switch (changeType) {
case 0:
// Hair color - more dramatic changes
var colors = [0x654321, 0x8B4513, 0x2F4F4F, 0xFFD700, 0x8B0000, 0x2E8B57, 0x000000, 0xDC143C, 0x4B0082, 0xFF1493];
do {
features.hairColor = colors[Math.floor(Math.random() * colors.length)];
} while (features.hairColor === originalFeatures.hairColor);
break;
case 1:
// Eye spacing - more noticeable
features.eyeSpacing = originalFeatures.eyeSpacing + (Math.random() > 0.5 ? 15 : -15);
break;
case 2:
// Nose size - more dramatic
features.noseSize = originalFeatures.noseSize + (Math.random() > 0.5 ? 0.6 : -0.5);
break;
case 3:
// Mouth width - more noticeable
features.mouthWidth = originalFeatures.mouthWidth + (Math.random() > 0.5 ? 0.7 : -0.6);
break;
}
}
return features;
}
function spawnVisitor() {
if (!gameActive) return;
visitorCount++;
var resident = getRandomResident();
// Check if this name has been visited before
var hasVisitedBefore = visitedNames.indexOf(resident.name) !== -1;
// If name visited before, automatically make it a doppelganger
// Otherwise use random chance
var isDoppelganger = hasVisitedBefore || Math.random() < 0.4; // 40% chance of doppelganger
// Add name to visited list if not already there
if (!hasVisitedBefore) {
visitedNames.push(resident.name);
storage.visitedNames = visitedNames;
}
// Create visitor
currentVisitor = game.addChild(new Visitor());
currentVisitor.x = 1024;
currentVisitor.y = 1800;
currentVisitor.name = resident.name;
currentVisitor.apartmentNumber = resident.apartment;
currentVisitor.isDoppelganger = isDoppelganger;
var visitorFeatures = isDoppelganger ? createDoppelgangerFeatures(resident) : resident;
currentVisitor.setFeatures(visitorFeatures);
// Store additional clues for doppelgangers
currentVisitor.hasTimeClue = isDoppelganger && Math.random() < 0.3;
currentVisitor.hasBehaviorClue = isDoppelganger && Math.random() < 0.4;
currentVisitor.hasStoryClue = isDoppelganger && Math.random() < 0.5;
// Create ID card (ALWAYS shows original resident features, never doppelganger features)
currentIDCard = game.addChild(new IDCard());
currentIDCard.x = 400;
currentIDCard.y = 2300;
currentIDCard.setInfo(resident.name, resident.apartment, resident, isDoppelganger);
// Create building record (always shows correct resident info)
currentRecord = game.addChild(new RecordCard());
currentRecord.x = 1648;
currentRecord.y = 2300;
currentRecord.setInfo(resident.name, resident.apartment, resident);
// Create middle image between the two cards
var middleImage = game.addChild(LK.getAsset('middleImage', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2300
}));
// Create conversation box
currentConversation = game.addChild(new ConversationBox());
currentConversation.x = 1024;
currentConversation.y = 1000;
// Show visitor's reason for visiting
var language = storage.language || 'en';
var reasons = visitReasons[language];
var randomReason = reasons[Math.floor(Math.random() * reasons.length)];
// For doppelgangers, sometimes give suspicious reasons
if (isDoppelganger && Math.random() < 0.6) {
if (language === 'tr') {
var suspiciousReasons = ["Sadece... arkadaşımı ziyarete geliyorum...", "Burada yaşadığımı unuttum mu? Tabii ki buraya aittim!", "Normal insan aktiviteleri için buradayım.", "Size neden söylemek zorundayım? Ben buralıyım!", "Daire numaramı mı? Şey... 20... 3? Evet, 203!"];
} else {
var suspiciousReasons = ["I'm just... visiting my friend...", "Did I forget I live here? Of course I belong here!", "I'm here for normal human activities.", "Why should I tell you? I belong here!", "My apartment? Uh... 20... 3? Yes, 203!"];
}
randomReason = suspiciousReasons[Math.floor(Math.random() * suspiciousReasons.length)];
}
currentConversation.showMessage(randomReason);
// Auto-hide conversation after 4 seconds
LK.setTimeout(function () {
if (currentConversation) {
currentConversation.hideMessage();
currentConversation = null;
}
}, 4000);
// Animate visitor entrance
currentVisitor.y = 1200;
tween(currentVisitor, {
y: 1800
}, {
duration: 1000
});
if (storage.soundEnabled !== false) {
LK.getSound('doorbell').play();
}
}
function handleDecision(approved) {
if (!gameActive || !currentVisitor) return;
var correct = approved && !currentVisitor.isDoppelganger || !approved && currentVisitor.isDoppelganger;
var language = storage.language || 'en';
if (correct) {
score += 10;
LK.setScore(score);
var scoreLabel = language === 'tr' ? 'Puan: ' : 'Score: ';
scoreText.setText(scoreLabel + score);
if (storage.soundEnabled !== false) {
LK.getSound('correct').play();
}
if (currentVisitor.isDoppelganger) {
LK.effects.flashObject(currentVisitor, 0xff0000, 500);
// Check if this was a repeat visitor
var wasRepeatVisitor = visitedNames.indexOf(currentVisitor.name) !== -1 && visitedNames.lastIndexOf(currentVisitor.name) !== visitedNames.length - 1;
if (wasRepeatVisitor) {
var repeatText = language === 'tr' ? "Doğru! Bu kişi daha önce gelmişti - Tekrar ziyaretçi tespit edildi!" : "Correct! This person visited before - Repeat visitor detected!";
showClueNotification(repeatText);
} else {
// Show what clues were available
var cluesFound = [];
if (currentVisitor.hasTimeClue) cluesFound.push(language === 'tr' ? "Zaman ipucu" : "Time clue");
if (currentVisitor.hasBehaviorClue) cluesFound.push(language === 'tr' ? "Davranış ipucu" : "Behavior clue");
if (currentVisitor.hasStoryClue) cluesFound.push(language === 'tr' ? "Hikaye ipucu" : "Story clue");
if (cluesFound.length > 0) {
var clueText = language === 'tr' ? "Doğru! Bulduğunuz ipuçları: " + cluesFound.join(", ") : "Correct! Clues found: " + cluesFound.join(", ");
showClueNotification(clueText);
}
}
} else {
LK.effects.flashObject(currentVisitor, 0x00ff00, 500);
}
} else {
mistakes++;
var mistakeLabel = language === 'tr' ? 'Hatalar: ' : 'Mistakes: ';
mistakesText.setText(mistakeLabel + mistakes + '/' + maxMistakes);
if (storage.soundEnabled !== false) {
LK.getSound('wrong').play();
}
LK.effects.flashScreen(0xff0000, 300);
// Show missed clues if it was a doppelganger
if (currentVisitor.isDoppelganger && !approved) {
var missedClues = [];
if (currentVisitor.hasTimeClue) missedClues.push(language === 'tr' ? "Zaman ipucu" : "Time clue");
if (currentVisitor.hasBehaviorClue) missedClues.push(language === 'tr' ? "Davranış ipucu" : "Behavior clue");
if (currentVisitor.hasStoryClue) missedClues.push(language === 'tr' ? "Hikaye ipucu" : "Story clue");
if (missedClues.length > 0) {
var missedText = language === 'tr' ? "Kaçırdığınız ipuçları: " + missedClues.join(", ") : "Missed clues: " + missedClues.join(", ");
showClueNotification(missedText);
}
}
if (mistakes >= maxMistakes) {
gameActive = false;
gameStarted = false;
// Transform current visitor into anomaly killer
if (currentVisitor) {
// Hide conversation and cards first
if (currentConversation) {
currentConversation.destroy();
currentConversation = null;
}
if (currentIDCard) {
currentIDCard.destroy();
currentIDCard = null;
}
if (currentRecord) {
currentRecord.destroy();
currentRecord = null;
}
if (middleImage) {
middleImage.destroy();
middleImage = null;
}
// Transform the visitor into an anomaly killer
tween(currentVisitor, {
tint: 0x1a1a1a,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Create proper anomaly killer to replace visitor
var anomalyKiller = game.addChild(new AnomalyKiller());
if (currentVisitor) {
anomalyKiller.x = currentVisitor.x;
anomalyKiller.y = currentVisitor.y;
currentVisitor.destroy();
currentVisitor = null;
} else {
anomalyKiller.x = 1024;
anomalyKiller.y = 1800;
}
anomalyKiller.killPlayer();
}
});
} else {
// Fallback: spawn new anomaly killer if no current visitor
var anomalyKiller = game.addChild(new AnomalyKiller());
anomalyKiller.killPlayer();
}
return;
}
}
// Clean up conversation if still active
if (currentConversation) {
currentConversation.destroy();
currentConversation = null;
}
// Remove current visitor and cards
tween(currentVisitor, {
y: 1200
}, {
duration: 800,
onFinish: function onFinish() {
if (currentVisitor) {
currentVisitor.destroy();
}
if (currentIDCard) {
currentIDCard.destroy();
}
if (currentRecord) {
currentRecord.destroy();
}
if (middleImage) {
middleImage.destroy();
}
currentVisitor = null;
currentIDCard = null;
currentRecord = null;
// Spawn next visitor after a short delay
if (gameActive) {
LK.setTimeout(spawnVisitor, 1500);
}
}
});
// Check win condition
if (score >= 100) {
gameActive = false;
gameStarted = false;
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
}
// Button event handlers
approveButton.down = function (x, y, obj) {
if (gameActive && currentVisitor) {
// Enhanced button animation
tween(approveButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
onFinish: function onFinish() {
tween(approveButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.bounceOut
});
}
});
LK.effects.flashObject(approveButton, 0xffffff, 200);
handleDecision(true);
}
};
denyButton.down = function (x, y, obj) {
if (gameActive && currentVisitor) {
// Enhanced button animation
tween(denyButton, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
onFinish: function onFinish() {
tween(denyButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.bounceOut
});
}
});
LK.effects.flashObject(denyButton, 0xffffff, 200);
handleDecision(false);
}
};
// Initialize main menu
showMainMenu();
game.update = function () {
// Game loop - update score display only when game is active
if (gameStarted && gameActive) {
var language = storage.language || 'en';
var scoreLabel = language === 'tr' ? 'Puan: ' : 'Score: ';
scoreText.setText(scoreLabel + LK.getScore());
}
// Hide instruction text and buttons when not in game
if (gameStarted) {
instructionText.alpha = 1;
approveButton.alpha = 1;
denyButton.alpha = 1;
approveText.alpha = 1;
denyText.alpha = 1;
} else {
instructionText.alpha = 0;
approveButton.alpha = 0;
denyButton.alpha = 0;
approveText.alpha = 0;
denyText.alpha = 0;
}
};