User prompt
Reduce showcase size for Kadazanman asset to 768x 1528 px after being selected, while the image of Kadazanman is 100% to the size of Kadazan male button
User prompt
Make the showcase size for Kadazanman asset to 768x1528 px and make the Kadazanman asset to be visible to 100% to the Kadazanman button size
User prompt
Add asset Kadazanman to Kadazan male attire
User prompt
Resize Nyonya showcase size to 768 x 1528 px, make Nyonya asset can be visible to 100% size to the Baba Nyonya's item button
User prompt
Fix the animation bug for Nyonya asset showcase
User prompt
Nyonya asset is disappearred and cannot be showcased after it is selected from the button
User prompt
Nyonya showcase will disappear after being selected, fix this bug
User prompt
Nyonya asset showcase is too small, make sure the showcase size can be seen in entire screen
User prompt
Make the Nyonya asset showcase bigger
User prompt
Make Nyonya asset to be 768 x 1528 px for showcase, and the image displayed is 100% to the female Baba and Nyonya button
User prompt
Make Nyonya asset to be visible 100% to the size of button, as Nyonya asset is too small in the button
User prompt
Replace female babaNyonyaTop with the asset Nyonya
User prompt
Make sure the word "Tetapkan Semula" is withinn the UI panel
User prompt
Separate the gender selector to two lines
User prompt
Above is female and below is male for gender selector at the left side of character base
User prompt
Move the selection of gender to the left side of character base
User prompt
All of the UI panel separated from each other, and didn't overlapp with each other, Make sure all of the word is within UI panel, especially for the word Bahasa Melayu ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Use the existing 'ui Panel' as backgrounds for my buttons
User prompt
Remove Chetti bottom from female and male clothing options
User prompt
Remove Baba Nyonya bottom for male and female
User prompt
Change wardrobe layout to 2 pages, and the users can access pages by clicking arrow buttons, First page consists of 6 items and second page consists of 4 items ↪💡 Consider importing and using the following plugins: @upit/tween.v1 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
To properly fix this issue without modifying the code, the offset value would need to be significantly more negative (perhaps around -600 or -700) to move the entire grid of buttons higher within the scroll container. Additionally, the initial position of the scroll container itself could be adjusted to start higher in the interface.
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'down')' in or related to this line: 'self.down = function (x, y, obj) {' Line Number: 1901
User prompt
All of the buttons are too below in the wardrobe
User prompt
Add Siamese for wardrobe ethnic selection according to the gender above the first line of button
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { savedCharacters: [], currentLanguage: "en", currentWardrobePage: 0 }); /**** * Classes ****/ var CategorySelector = Container.expand(function () { var self = Container.call(this); self.categories = [{ id: 'siamese', label: { en: 'Siamese', ms: 'Siam', zh: '暹罗', ta: 'சியாமீஸ்' } }, { id: 'malay', label: { en: 'Malay', ms: 'Melayu', zh: '马来', ta: 'மலாய்' } }, { id: 'chinese', label: { en: 'Chinese', ms: 'Cina', zh: '华人', ta: 'சீன' } }, { id: 'indian', label: { en: 'Indian', ms: 'India', zh: '印度', ta: 'இந்திய' } }, { id: 'indigenous', label: { en: 'Indigenous', ms: 'Orang Asli', zh: '原住民', ta: 'பழங்குடி' } }, { id: 'iban', label: { en: 'Iban', ms: 'Iban', zh: '伊班族', ta: 'இபான்' } }, { id: 'kadazan', label: { en: 'Kadazan', ms: 'Kadazan', zh: '卡达山族', ta: 'கடசான்' } }, { id: 'babanyonya', label: { en: 'Baba Nyonya', ms: 'Baba Nyonya', zh: '峇峇娘惹', ta: 'பாபா நியோனியா' } }, { id: 'chetti', label: { en: 'Chetti', ms: 'Chetti', zh: '切蒂', ta: 'செட்டி' } }, { id: 'modern', label: { en: 'Serani', ms: 'Serani', zh: 'Serani', ta: 'Serani' } }]; self.selectedCategory = 'malay'; self.buttons = []; self.updateLanguage = function (lang) { for (var i = 0; i < self.categories.length; i++) { var cat = self.categories[i]; self.buttons[i].setText(cat.label[lang]); } }; self.setup = function () { var spacing = 250; var startX = -((self.categories.length - 1) * spacing) / 2; for (var i = 0; i < self.categories.length; i++) { var cat = self.categories[i]; var lang = storage.currentLanguage; var btn = new UIButton(cat.label[lang], 180, 60, 0x87CEFA); btn.x = startX + i * spacing; btn.y = -80; // Positioned higher to improve layout btn.categoryId = cat.id; btn.setCallback(function () { var catId = this.categoryId; LK.getSound('categoryChange').play(); self.selectedCategory = catId; self.updateButtonStates(); if (self.onCategoryChange) { self.onCategoryChange(catId); } }.bind(btn)); self.addChild(btn); self.buttons.push(btn); } self.updateButtonStates(); return self; }; self.updateButtonStates = function () { for (var i = 0; i < self.buttons.length; i++) { var btn = self.buttons[i]; if (btn.categoryId === self.selectedCategory) { btn.buttonText.style.fill = "#FFFFFF"; tween(btn.children[0], { tint: 0x4682B4 }, { duration: 200 }); } else { btn.buttonText.style.fill = "#000000"; tween(btn.children[0], { tint: 0x87CEFA }, { duration: 200 }); } } }; self.setChangeCallback = function (callback) { self.onCategoryChange = callback; return self; }; return self; }); var Character = Container.expand(function () { var self = Container.call(this); // Create character base - default to female self.gender = 'female'; var base = self.attachAsset('characterBaseFemale', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); // Layers for different clothing types self.layers = { base: base, bottom: null, top: null, headdress: null, accessory: null }; // Method to change the character gender self.setGender = function (gender) { self.gender = gender; // Remove current base if (self.layers.base) { self.removeChild(self.layers.base); } // Create new base based on gender var baseAssetId = gender === 'male' ? 'Malecharacterbase' : 'characterBaseFemale'; var newBase = self.attachAsset(baseAssetId, { anchorX: 0.5, anchorY: 0.5, scaleX: gender === 'male' ? 0.6 : 1, // Scale male character width to 60% to avoid looking too fat scaleY: gender === 'male' ? 0.5127 : 1 // Scale male character to fit 1528px height }); // Update reference self.layers.base = newBase; // Ensure proper layering self.sortLayers(); return self; }; self.equip = function (item) { if (!item) return; // Check if trying to equip kurta for Indian male if (item.itemName === 'kurta' && self.gender === 'male') { return self; // Don't equip kurta for Indian male } // Check if trying to equip headdress for indigenous female if (item.type === 'headdress' && self.gender === 'female' && item.category === 'indigenous') { return self; // Don't equip headdress for indigenous female } // Remove previous item in this layer if exists if (self.layers[item.type]) { self.removeChild(self.layers[item.type]); } // Add new item and store reference self.layers[item.type] = item; self.addChild(item); // Position according to type switch (item.type) { case 'top': item.y = 50; break; case 'bottom': item.y = 300; break; case 'headdress': item.y = -300; break; case 'accessory': item.y = -100; break; } // Ensure proper layering self.sortLayers(); return self; }; self.sortLayers = function () { // Manual sorting to ensure correct layering var layerOrder = ['base', 'bottom', 'top', 'accessory', 'headdress']; var zIndex = 0; layerOrder.forEach(function (layerName) { var layer = self.layers[layerName]; if (layer) { // Remove and re-add to ensure proper order if (layer.parent === self) { self.removeChild(layer); } self.addChild(layer); } }); }; self.getData = function () { var data = { gender: self.gender, items: {} }; // Store item data for each layer for (var layerName in self.layers) { if (layerName !== 'base' && self.layers[layerName]) { data.items[layerName] = { name: self.layers[layerName].itemName, category: self.layers[layerName].category }; } } return data || {}; // Return empty object if data is undefined }; self.loadData = function (data) { // Clear current items for (var layerName in self.layers) { if (layerName !== 'base' && self.layers[layerName]) { self.removeChild(self.layers[layerName]); self.layers[layerName] = null; } } // Set gender if provided in data if (data && data.gender) { self.setGender(data.gender); } // Load saved items if (data && data.items) { for (var layerName in data.items) { var itemData = data.items[layerName]; var item = new ClothingItem(layerName, itemData.category, itemData.name); self.equip(item); } } return self; }; return self; }); var ClothingItem = Container.expand(function (type, category, itemName) { var self = Container.call(this); self.type = type; self.category = category; self.itemName = itemName; // Use the appropriate asset based on item name var itemGraphics; // For all items, use the appropriate asset itemGraphics = self.attachAsset(itemName, { anchorX: 0.5, anchorY: 0.5 }); // Add specific styling for Changsan to fit button size with minimal padding if (itemName === 'Changsan') { itemGraphics.width = itemGraphics.width * 0.98; // 98% width (1% padding on each side) itemGraphics.height = itemGraphics.height * 0.98; // 98% height (1% padding on each side) } // Center the item graphics in its container if (itemGraphics) { // Store original dimensions for reference self.originalWidth = itemGraphics.width; self.originalHeight = itemGraphics.height; // Properly center the item within the container itemGraphics.x = 0; itemGraphics.y = 0; // Allow items to be displayed at their original size in buttons // Only scale down if they're extremely large if (self.originalHeight > 1500 || self.originalWidth > 900) { var scaleFactor = Math.min(900 / self.originalWidth, 1500 / self.originalHeight); // Special case for Ibanman and Ibanwoman - maintain exact 768x1528 ratio even in buttons if (itemName === 'Ibanman' || itemName === 'Ibanwoman') { scaleFactor = Math.min(768 / self.originalWidth, 1528 / self.originalHeight); // Ensure Ibanwoman is displayed properly with 768x1528 aspect ratio if (itemName === 'Ibanwoman') { // Preserve aspect ratio while ensuring proper dimensions scaleFactor = Math.min(768 / self.originalWidth, 1528 / self.originalHeight); } } itemGraphics.scale.set(scaleFactor, scaleFactor); } // For certain types, adjust position to prevent overlap if (self.type === 'headdress') { itemGraphics.y = -itemGraphics.height * 0.25; } else if (self.type === 'accessory') { itemGraphics.y = -itemGraphics.height * 0.1; } } self.select = function () { LK.getSound('itemSelect').play(); // If we're in a character and there's a base layer, hide it if (self.parent && self.parent.layers && self.parent.layers.base) { self.parent.layers.base.visible = false; } // If this is a saree, remove any bottom layer if (self.itemName === 'saree' && self.parent && self.parent.layers && self.parent.layers.bottom) { self.parent.removeChild(self.parent.layers.bottom); self.parent.layers.bottom = null; } // Scale up the attire when selected to fit 768x1528 dimensions if (self.children[0]) { // Store original scale if not already stored if (!self.originalScale) { self.originalScale = { x: self.children[0].scale.x, y: self.children[0].scale.y }; } // Calculate scale factor to fit within 768x1528 area while maximizing size var maxWidth = 768; var maxHeight = 1528; var currentWidth = self.originalWidth * self.originalScale.x; var currentHeight = self.originalHeight * self.originalScale.y; var scaleFactor = Math.min(maxWidth / currentWidth, maxHeight / currentHeight); // Special handling for Ibanman and Ibanwoman to ensure exact 768x1528 dimensions if (self.itemName === 'Ibanman' || self.itemName === 'Ibanwoman') { scaleFactor = Math.min(768 / self.originalWidth, 1528 / self.originalHeight); // Force exact dimensions for Ibanwoman if (self.itemName === 'Ibanwoman') { // Calculate the exact scale needed for 768x1528px var ibanWomanScaleFactor = Math.min(768 / self.originalWidth, 1528 / self.originalHeight); scaleFactor = ibanWomanScaleFactor; } } // Apply larger scale with animation tween(self.children[0], { scaleX: self.originalScale.x * scaleFactor, scaleY: self.originalScale.y * scaleFactor }, { duration: 500, easing: tween.easeOut }); } return self; }; self.down = function (x, y, obj) { // Handle item selection self.select(); // Show cultural info if this is a Baju Kurung if (self.itemName === 'bajuKurung' && typeof culturalInfoPanel !== 'undefined') { culturalInfoPanel.show('bajuKurung'); } }; return self; }); var CulturalInfoPanel = Container.expand(function () { var self = Container.call(this); // Create background panel var bg = self.attachAsset('uiPanel', { anchorX: 0.5, anchorY: 0.5, width: 1600, height: 1200, tint: 0xFFFAF0 // Ivory color }); // Title text self.titleText = new Text2("Cultural Information", { size: 60, fill: 0x4682B4 }); self.titleText.anchor.set(0.5, 0); self.titleText.y = -bg.height / 2 + 40; self.addChild(self.titleText); // Info text with word wrapping self.infoText = new Text2("", { size: 40, fill: 0x333333, wordWrap: true, wordWrapWidth: 1400 }); self.infoText.anchor.set(0.5, 0); self.infoText.y = -bg.height / 2 + 130; self.addChild(self.infoText); // Close button var closeButton = new UIButton("X", 80, 80, 0xF44336); closeButton.x = bg.width / 2 - 60; closeButton.y = -bg.height / 2 + 60; closeButton.setCallback(function () { self.hide(); }); self.addChild(closeButton); // Show panel with specific item info self.show = function (itemName) { // Hide panel initially for animation self.visible = true; self.alpha = 0; // Get current language var lang = storage.currentLanguage; // Update title based on language var titleTranslations = { en: "Cultural Information", ms: "Maklumat Budaya", zh: "文化信息", ta: "கலாச்சார தகவல்" }; self.titleText.setText(titleTranslations[lang] || "Cultural Information"); // Set content if available for this item if (culturalInfoScripts[itemName] && culturalInfoScripts[itemName][lang]) { self.infoText.setText(culturalInfoScripts[itemName][lang]); } else { // Default text if no info available var defaultText = { en: "No information available for this item.", ms: "Tiada maklumat tersedia untuk item ini.", zh: "没有关于此物品的信息。", ta: "இந்த பொருளுக்கு தகவல் இல்லை." }; self.infoText.setText(defaultText[lang]); } // Fade in animation tween(self, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); return self; }; // Hide panel self.hide = function () { self.visible = false; return self; }; // Initial state self.visible = false; return self; }); var GenderSelector = Container.expand(function () { var self = Container.call(this); self.genders = [{ id: 'female', label: { en: 'Female', ms: 'Perempuan', zh: '女', ta: 'பெண்' } }, { id: 'male', label: { en: 'Male', ms: 'Lelaki', zh: '男', ta: 'ஆண்' } }]; self.selectedGender = 'female'; self.buttons = []; self.updateLanguage = function (lang) { for (var i = 0; i < self.genders.length; i++) { var gender = self.genders[i]; self.buttons[i].setText(gender.label[lang]); } }; self.setup = function () { var spacing = 200; var startX = -((self.genders.length - 1) * spacing) / 2; for (var i = 0; i < self.genders.length; i++) { var gender = self.genders[i]; var lang = storage.currentLanguage; var btn = new UIButton(gender.label[lang], 180, 60, 0x87CEFA); btn.x = startX + i * spacing; btn.genderId = gender.id; btn.setCallback(function () { var genderId = this.genderId; LK.getSound('categoryChange').play(); self.selectedGender = genderId; self.updateButtonStates(); if (self.onGenderChange) { self.onGenderChange(genderId); } }.bind(btn)); self.addChild(btn); self.buttons.push(btn); } self.updateButtonStates(); return self; }; self.updateButtonStates = function () { for (var i = 0; i < self.buttons.length; i++) { var btn = self.buttons[i]; if (btn.genderId === self.selectedGender) { btn.buttonText.style.fill = "#FFFFFF"; tween(btn.children[0], { tint: 0x4682B4 }, { duration: 200 }); } else { btn.buttonText.style.fill = "#000000"; tween(btn.children[0], { tint: 0x87CEFA }, { duration: 200 }); } } }; self.setChangeCallback = function (callback) { self.onGenderChange = callback; return self; }; return self; }); var ItemSelector = Container.expand(function () { var self = Container.call(this); self.items = { siamese: { female: { top: [{ name: 'siameseDress', label: { en: 'Siamese Dress', ms: 'Pakaian Siam', zh: '暹罗服装', ta: 'சியாமீஸ் ஆடை' } }], headdress: [] }, male: { top: [{ name: 'siameseTop', label: { en: 'Siamese Attire', ms: 'Pakaian Siam', zh: '暹罗男装', ta: 'சியாமீஸ் ஆடை' } }], headdress: [] } }, malay: { female: { top: [{ name: 'bajuKurung', label: { en: 'Baju Kurung', ms: 'Baju Kurung', zh: '马来传统服装', ta: 'பாஜு குருங்' } }], headdress: [] }, male: { top: [{ name: 'bajuMelayu', label: { en: 'Baju Melayu', ms: 'Baju Melayu', zh: '马来男装', ta: 'பாஜு மேலாயு' } }], headdress: [] } }, chinese: { female: { top: [{ name: 'cheongsam', label: { en: 'Cheongsam', ms: 'Cheongsam', zh: '旗袍', ta: 'சியோங்சாம்' } }], accessory: [] }, male: { top: [{ name: 'Changsan', label: { en: 'Changshan', ms: 'Changshan', zh: '长衫', ta: 'சாங்ஷான்' } }], accessory: [] } }, indian: { female: { top: [{ name: 'saree', label: { en: 'Saree', ms: 'Sari', zh: '纱丽', ta: 'சேலை' } }], accessory: [] }, male: { top: [{ name: 'kurta', label: { en: 'Kurta', ms: 'Kurta', zh: '库尔塔', ta: 'குர்தா' } }], bottom: [{ name: 'Dhotti', label: { en: 'Dhoti', ms: 'Dhoti', zh: '多蒂', ta: 'தோட்டி' } }] } }, indigenous: { female: { top: [{ name: 'indigenousVest', label: { en: 'Traditional Vest', ms: 'Rompi Tradisional', zh: '传统背心', ta: 'பாரம்பரிய மேலாடை' } }], headdress: [{ name: 'headDress', label: { en: 'Headdress', ms: 'Hiasan Kepala', zh: '头饰', ta: 'தலை அணி' } }] }, male: {} }, iban: { female: { top: [{ name: 'indigenousVest', label: { en: 'Ngepan Vest', ms: 'Rompi Ngepan', zh: '伊班族背心', ta: 'நெகபன் மேலாடை' } }], headdress: [] }, male: { top: [{ name: 'ibanVest', label: { en: 'Iban Vest', ms: 'Rompi Iban', zh: '伊班族背心', ta: 'இபான் மேலாடை' } }], headdress: [] } }, kadazan: { female: { top: [{ name: 'indigenousVest', label: { en: 'Sinuangga Vest', ms: 'Rompi Sinuangga', zh: '卡达山族背心', ta: 'சினுவாங்க மேலாடை' } }], headdress: [] }, male: { top: [{ name: 'kadazanVest', label: { en: 'Kadazan Vest', ms: 'Rompi Kadazan', zh: '卡达山族背心', ta: 'கடசான் மேலாடை' } }], headdress: [] } }, babanyonya: { female: { top: [{ name: 'babaNyonyaTop', label: { en: 'Kebaya Nyonya', ms: 'Kebaya Nyonya', zh: '娘惹峇峇服', ta: 'கெபாயா நியோனியா' } }], bottom: [], accessory: [] }, male: { top: [{ name: 'babaNyonyaTop', label: { en: 'Baba Tunic', ms: 'Tunik Baba', zh: '峇峇上衣', ta: 'பாபா மேலாடை' } }], bottom: [], accessory: [] } }, chetti: { female: { top: [{ name: 'chettiTop', label: { en: 'Chetti Saree', ms: 'Sari Chetti', zh: '切蒂纱丽', ta: 'செட்டி சேலை' } }], accessory: [] }, male: { top: [{ name: 'chettiTop', label: { en: 'Chetti Veshti', ms: 'Veshti Chetti', zh: '切蒂传统服装', ta: 'செட்டி வேஷ்டி' } }], bottom: [], accessory: [] } }, modern: { female: { top: [{ name: 'modernTop', label: { en: 'Modern Top', ms: 'Atasan Moden', zh: '现代上衣', ta: 'நவீன மேல்' } }], bottom: [] }, male: { top: [{ name: 'modernMaleTop', label: { en: 'Modern Top', ms: 'Atasan Moden', zh: '现代上衣', ta: 'நவீன மேல்' } }], bottom: [] } } }; self.currentCategory = 'malay'; self.currentType = 'top'; self.itemButtons = []; self.typeButtons = []; // Group by type instead of category, considering gender self.getItemsByType = function () { var types = {}; var currentGender = typeof genderSelector !== 'undefined' && genderSelector ? genderSelector.selectedGender : 'female'; // Get all available types for current category and gender if (self.items[self.currentCategory] && self.items[self.currentCategory][currentGender]) { for (var type in self.items[self.currentCategory][currentGender]) { types[type] = true; } } return Object.keys(types); }; self.setCategory = function (category) { self.currentCategory = category; // Determine available types for this category based on gender var types = self.getItemsByType(); // Default to first type if current not available if (!types.includes(self.currentType)) { self.currentType = types.length > 0 ? types[0] : null; } // If no valid types for the current category/gender combination, don't proceed if (!self.currentType) { self.refreshTypeButtons(); return self; } self.refreshTypeButtons(); self.refreshItems(); return self; }; self.setType = function (type) { self.currentType = type; self.refreshItems(); return self; }; self.refreshTypeButtons = function () { // Clear existing buttons for (var i = 0; i < self.typeButtons.length; i++) { self.removeChild(self.typeButtons[i]); } self.typeButtons = []; var types = self.getItemsByType(); var spacing = 180; var startX = -((types.length - 1) * spacing) / 2; // Type translation mapping var typeLabels = { top: { en: 'Top', ms: 'Atas', zh: '上身', ta: 'மேல்' }, bottom: { en: 'Bottom', ms: 'Bawah', zh: '下身', ta: 'கீழ்' }, headdress: { en: 'Headdress', ms: 'Hiasan Kepala', zh: '头饰', ta: 'தலை அணி' }, accessory: { en: 'Accessory', ms: 'Aksesori', zh: '饰品', ta: 'அணிகலன்' } }; // Create buttons for each available type for (var i = 0; i < types.length; i++) { var type = types[i]; var label = typeLabels[type][storage.currentLanguage] || type; var btn = new UIButton(label, 150, 50, 0xBBBBBB); btn.x = startX + i * spacing; btn.y = -400; // Moved much higher to position buttons correctly btn.typeName = type; btn.setCallback(function () { self.setType(this.typeName); self.updateTypeButtonStates(); }.bind(btn)); self.addChild(btn); self.typeButtons.push(btn); } self.updateTypeButtonStates(); }; self.updateTypeButtonStates = function () { for (var i = 0; i < self.typeButtons.length; i++) { var btn = self.typeButtons[i]; if (btn.typeName === self.currentType) { btn.buttonText.style.fill = "#FFFFFF"; tween(btn.children[0], { tint: 0x555555 }, { duration: 200 }); } else { btn.buttonText.style.fill = "#000000"; tween(btn.children[0], { tint: 0xBBBBBB }, { duration: 200 }); } } }; self.refreshItems = function () { // Clear existing item buttons for (var i = 0; i < self.itemButtons.length; i++) { self.removeChild(self.itemButtons[i]); } self.itemButtons = []; var currentGender = typeof genderSelector !== 'undefined' && genderSelector ? genderSelector.selectedGender : 'female'; var currentItems = []; // Get items for the current category, gender and type if (self.items[self.currentCategory] && self.items[self.currentCategory][currentGender] && self.items[self.currentCategory][currentGender][self.currentType]) { currentItems = self.items[self.currentCategory][currentGender][self.currentType] || []; } // Only handle Chinese male top type properly - don't empty Changsan when it should appear if (self.currentCategory === 'chinese' && currentGender === 'male' && self.currentType === 'top') { // Check if Changsan is not already in items var hasChangsan = currentItems.some(function (item) { return item.name === 'Changsan'; }); if (!hasChangsan) { // Add Changsan if it's not already present currentItems.push({ name: 'Changsan', label: { en: 'Changshan', ms: 'Changshan', zh: '长衫', ta: 'சாங்ஷான்' } }); } } // Handle Baba Nyonya category if (self.currentCategory === 'babanyonya') { if (currentGender === 'female' && self.currentType === 'top') { // Check if babaNyonyaTop is not already in items var hasBabaNyonyaTop = currentItems.some(function (item) { return item.name === 'babaNyonyaTop'; }); if (!hasBabaNyonyaTop) { currentItems.push({ name: 'babaNyonyaTop', label: { en: 'Kebaya Nyonya', ms: 'Kebaya Nyonya', zh: '娘惹峇峇服', ta: 'கெபாயா நியோனியா' } }); } } else if (currentGender === 'male' && self.currentType === 'top') { // Check if babaNyonyaTop is not already in items for male var hasBabaNyonyaTop = currentItems.some(function (item) { return item.name === 'babaNyonyaTop'; }); if (!hasBabaNyonyaTop) { currentItems.push({ name: 'babaNyonyaTop', label: { en: 'Baba Tunic', ms: 'Tunik Baba', zh: '峇峇上衣', ta: 'பாபா மேலாடை' } }); } } // Bottom section removed for Baba Nyonya male and female } // Handle Chetti category if (self.currentCategory === 'chetti') { if (self.currentType === 'top') { // Check if chettiTop is not already in items var hasChettiTop = currentItems.some(function (item) { return item.name === 'chettiTop'; }); if (!hasChettiTop) { currentItems.push({ name: 'chettiTop', label: { en: currentGender === 'female' ? 'Chetti Saree' : 'Chetti Veshti', ms: currentGender === 'female' ? 'Sari Chetti' : 'Veshti Chetti', zh: currentGender === 'female' ? '切蒂纱丽' : '切蒂传统服装', ta: currentGender === 'female' ? 'செட்டி சேலை' : 'செட்டி வேஷ்டி' } }); } } else if (currentGender === 'male' && self.currentType === 'bottom') { // Check if chettiBottom is not already in items var hasChettiBottom = currentItems.some(function (item) { return item.name === 'chettiBottom'; }); if (!hasChettiBottom) { currentItems.push({ name: 'chettiBottom', label: { en: 'Chetti Dhoti', ms: 'Dhoti Chetti', zh: '切蒂多蒂', ta: 'செட்டி தோட்டி' } }); } } } // Filter items to ensure gender-specific clothing and prevent Changsan from appearing in non-Chinese categories var filteredItems = currentItems.filter(function (item) { // Immediately remove Changsan from all non-Chinese categories if (item.name === 'Changsan' && self.currentCategory !== 'chinese') { return false; } // Double-check to explicitly prevent Changsan from appearing in Orang Asli, Iban, and Kadazan categories if (item.name === 'Changsan' && (self.currentCategory === 'indigenous' || self.currentCategory === 'iban' || self.currentCategory === 'kadazan')) { return false; } // Double-check to explicitly prevent Changsan from appearing in Orang Asli, Iban, and Kadazan categories if (item.name === 'Changsan' && (self.currentCategory === 'indigenous' || self.currentCategory === 'iban' || self.currentCategory === 'kadazan')) { return false; } // Always ensure we're only showing items appropriate for the current gender return self.items[self.currentCategory] && self.items[self.currentCategory][currentGender] && self.items[self.currentCategory][currentGender][self.currentType] && self.items[self.currentCategory][currentGender][self.currentType].some(function (validItem) { return validItem.name === item.name; }); }); // Use larger buttons to match attire's image size for better display var buttonWidth = 900; // Width for the button var buttonHeight = 1200; // Height for the button to maintain aspect ratio var itemsPerRow = 2; // Two items per row for better utilization of space var horizontalSpacing = 950; // Spacing between items horizontally var verticalSpacing = 1300; // Spacing between rows // Create a scroll container for wardrobe items if (!self.scrollContainer) { self.scrollContainer = new Container(); self.addChild(self.scrollContainer); // Implement scroll functionality self.lastY = 0; self.isDragging = false; self.scrollY = 0; self.maxScrollY = 0; self.down = function (x, y, obj) { self.isDragging = true; self.lastY = y; }; self.move = function (x, y, obj) { if (self.isDragging) { var deltaY = y - self.lastY; self.scrollY += deltaY; // Limit scrolling if (self.scrollY > 0) { self.scrollY = 0; } else if (self.scrollY < -self.maxScrollY) { self.scrollY = -self.maxScrollY; } self.scrollContainer.y = self.scrollY; self.lastY = y; } }; self.up = function (x, y, obj) { self.isDragging = false; }; } // Create buttons for each item for (var i = 0; i < filteredItems.length; i++) { var row = Math.floor(i / itemsPerRow); var col = i % itemsPerRow; var item = filteredItems[i]; var label = item.label[storage.currentLanguage] || item.name; var itemContainer = new Container(); // Use standard button for all items { // For all items, use a larger button background var bg = LK.getAsset('itemButton', { anchorX: 0.5, anchorY: 0.5, width: 300, // Fixed to 300px width height: 300 // Fixed to 300px height }); itemContainer.addChild(bg); // Create item preview with large display var itemPreview = new ClothingItem(self.currentType, self.currentCategory, item.name); // Make all attires fit 100% of the item button size var itemAsset = itemPreview.children[0]; if (itemAsset) { // Reset scale first to ensure proper sizing itemAsset.scale.set(1, 1); // Force all attires to fit exactly 100% of the button size itemAsset.width = bg.width; itemAsset.height = bg.height; // Special case for Ibanman and Ibanwoman - ensure it displays at 100% while maintaining aspect ratio if (item.name === 'Ibanman' || item.name === 'Ibanwoman') { var aspectRatio = 768 / 1528; // Correct aspect ratio var scaleFactor = Math.min(bg.width / (itemAsset.width * aspectRatio), bg.height / itemAsset.height); // Use exact scaling for Ibanwoman to ensure 768x1528 ratio if (item.name === 'Ibanwoman') { // Calculate the exact scale needed to fit in button while preserving aspect ratio var exactRatio = 768 / 1528; var exactScaleFactor = Math.min(bg.width / (itemAsset.width * exactRatio), bg.height / itemAsset.height); itemAsset.scale.set(exactScaleFactor * exactRatio, exactScaleFactor); } else { itemAsset.scale.set(scaleFactor * aspectRatio, scaleFactor); } } // Center perfectly in the button itemAsset.position.set(0, 0); } itemPreview.position.set(0, 0); itemContainer.addChild(itemPreview); } // Item label for all items var itemLabel = new Text2(label, { size: 50, fill: 0x000000 }); itemLabel.anchor.set(0.5, 0); itemLabel.y = buttonHeight / 2 + 30; itemContainer.addChild(itemLabel); // Calculate grid position var gridStartX = -((itemsPerRow - 1) * horizontalSpacing) / 2; var posX = gridStartX + col * horizontalSpacing; var posY = row * verticalSpacing - 700; // Moved buttons significantly higher in the scroll container itemContainer.x = posX; itemContainer.y = posY; itemContainer.itemName = item.name; // Handle selection itemContainer.interactive = true; itemContainer.down = function (x, y, obj) { // Create and return a new ClothingItem when selected var itemInstance = new ClothingItem(self.currentType, self.currentCategory, this.itemName); if (self.onItemSelected) { LK.getSound('itemSelect').play(); self.onItemSelected(itemInstance); } // Visual feedback tween(this, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeOut }); }.bind(this) }); }.bind(itemContainer); self.scrollContainer.addChild(itemContainer); self.itemButtons.push(itemContainer); } // Calculate maximum scroll based on content height var totalRows = Math.ceil(filteredItems.length / itemsPerRow); var contentHeight = totalRows * verticalSpacing; var visibleHeight = 1300; // Adjusted visible area height for larger buttons self.maxScrollY = Math.max(0, contentHeight - visibleHeight); // Position scroll container for better visibility of large items self.scrollContainer.y = self.scrollY; return self; }; self.setSelectionCallback = function (callback) { self.onItemSelected = function (item) { // First call the original callback callback(item); // Show cultural info directly if this is baju kurung if (item.itemName === 'bajuKurung') { if (typeof culturalInfoPanel !== 'undefined') { culturalInfoPanel.show('bajuKurung'); } } }; return self; }; return self; }); var LanguageSelector = Container.expand(function () { var self = Container.call(this); self.languages = [{ code: 'en', name: 'English' }, { code: 'ms', name: 'Bahasa Melayu' }, { code: 'zh', name: '中文' }, { code: 'ta', name: 'தமிழ்' }]; self.buttons = []; self.setup = function () { var spacing = 200; var startX = -((self.languages.length - 1) * spacing) / 2; for (var i = 0; i < self.languages.length; i++) { var lang = self.languages[i]; var btn = new UIButton(lang.name, 140, 50, 0xDDDDDD); btn.x = startX + i * spacing; btn.languageCode = lang.code; btn.setCallback(function () { var langCode = this.languageCode; storage.currentLanguage = langCode; // Update button states self.updateButtonStates(); // Notify about language change if (self.onLanguageChange) { self.onLanguageChange(langCode); } }.bind(btn)); self.addChild(btn); self.buttons.push(btn); } self.updateButtonStates(); return self; }; self.updateButtonStates = function () { for (var i = 0; i < self.buttons.length; i++) { var btn = self.buttons[i]; if (btn.languageCode === storage.currentLanguage) { btn.buttonText.style.fill = "#FFFFFF"; tween(btn.children[0], { tint: 0x4682B4 }, { duration: 200 }); } else { btn.buttonText.style.fill = "#000000"; tween(btn.children[0], { tint: 0xDDDDDD }, { duration: 200 }); } } }; self.setChangeCallback = function (callback) { self.onLanguageChange = callback; return self; }; return self; }); var UIButton = Container.expand(function (text, width, height, bgColor) { var self = Container.call(this); self.width = width || 200; self.height = height || 80; self.bgColor = bgColor || 0x6495ED; var buttonBg = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5, width: self.width, height: self.height, tint: self.bgColor }); self.buttonText = new Text2(text, { size: 30, fill: 0x000000 }); self.buttonText.anchor.set(0.5, 0.5); // Make sure style property exists before accessing it if (!self.buttonText.style) { self.buttonText.style = {}; } self.buttonText.style.fill = "#000000"; self.addChild(self.buttonText); self.setText = function (newText) { self.buttonText.setText(newText); if (!self.buttonText.style) { self.buttonText.style = {}; } // At this point we've ensured style exists, so we can safely access it self.buttonText.style.fill = self.buttonText.style.fill || "#000000"; return self; }; self.down = function (x, y, obj) { // Button pressed effect tween(buttonBg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut }); }; self.up = function (x, y, obj) { // Button release effect tween(buttonBg, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeOut }); // Trigger callback if set if (self.callback) { self.callback(); } }; self.setCallback = function (callback) { self.callback = callback; return self; }; return self; }); var Wardrobe = Container.expand(function () { var self = Container.call(this); var background = self.attachAsset('uiPanel', { anchorX: 0.5, anchorY: 0.5, width: 1800, height: 2000, tint: 0xF5F5F5 }); var title = new Text2("Ethnic Wardrobe", { size: 60, fill: 0x4682B4 }); title.anchor.set(0.5, 0); title.y = -background.height / 2 + 40; self.addChild(title); var closeButton = new UIButton("X", 80, 80, 0xF44336); closeButton.x = background.width / 2 - 60; closeButton.y = -background.height / 2 + 60; closeButton.setCallback(function () { self.hide(); }); self.addChild(closeButton); // Create outfit container var outfitContainer = new Container(); self.addChild(outfitContainer); // Add pagination controls var leftArrow = self.attachAsset('arrowLeft', { anchorX: 0.5, anchorY: 0.5 }); leftArrow.x = -background.width / 2 + 100; leftArrow.y = background.height / 2 - 100; // Add text marker inside left arrow to indicate back var leftText = new Text2("<", { size: 50, fill: 0xFFFFFF }); leftText.anchor.set(0.5, 0.5); leftArrow.addChild(leftText); self.addChild(leftArrow); var rightArrow = self.attachAsset('arrowRight', { anchorX: 0.5, anchorY: 0.5 }); rightArrow.x = background.width / 2 - 100; rightArrow.y = background.height / 2 - 100; // Add text marker inside right arrow to indicate forward var rightText = new Text2(">", { size: 50, fill: 0xFFFFFF }); rightText.anchor.set(0.5, 0.5); rightArrow.addChild(rightText); self.addChild(rightArrow); // Add page indicator self.pageIndicator = new Text2("Page 1/2", { size: 30, fill: 0x000000 }); self.pageIndicator.anchor.set(0.5, 0.5); self.pageIndicator.y = background.height / 2 - 100; self.addChild(self.pageIndicator); // Set up arrow interactivity leftArrow.interactive = true; rightArrow.interactive = true; leftArrow.down = function (x, y, obj) { if (storage.currentWardrobePage > 0) { storage.currentWardrobePage--; self.loadOutfits(); // Provide visual feedback tween(this, { scaleX: 0.8, scaleY: 0.8 }, { duration: 100, easing: tween.easeOut, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeOut }); }.bind(this) }); } }.bind(leftArrow); rightArrow.down = function (x, y, obj) { if (storage.currentWardrobePage < 1) { // Only two pages (0 and 1) storage.currentWardrobePage++; self.loadOutfits(); // Provide visual feedback tween(this, { scaleX: 0.8, scaleY: 0.8 }, { duration: 100, easing: tween.easeOut, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeOut }); }.bind(this) }); } }.bind(rightArrow); self.updateLanguage = function (language) { var titleTranslations = { en: "Ethnic Wardrobe", ms: "Almari Pakaian Etnik", zh: "民族服装衣柜", ta: "இன ஆடை அலமாரி" }; title.setText(titleTranslations[language] || "Ethnic Wardrobe"); return self; }; self.loadOutfits = function () { var savedCharacters = storage.savedCharacters || []; // Clear existing outfits outfitContainer.removeChildren(); // Set to true to display all ethnic outfits var displayAllEthnics = true; // Only display ethnic outfits, not saved characters var outfitsToDisplay = []; // Add ethnic outfit presets if (displayAllEthnics) { var ethnicCategories = ['siamese', 'malay', 'chinese', 'indian', 'indigenous', 'iban', 'kadazan', 'babanyonya', 'chetti', 'modern']; var currentGender = typeof genderSelector !== 'undefined' && genderSelector ? genderSelector.selectedGender : 'female'; for (var c = 0; c < ethnicCategories.length; c++) { var category = ethnicCategories[c]; var outfitData = { items: {} }; // Get available items for this ethnic category based on gender if (itemSelector.items[category] && itemSelector.items[category][currentGender]) { for (var type in itemSelector.items[category][currentGender]) { if (itemSelector.items[category][currentGender][type] && itemSelector.items[category][currentGender][type].length > 0) { // Get the first item of this type for the current gender var item = itemSelector.items[category][currentGender][type][0]; // Special case for Malay male outfit - use bajumelayu for top if (category === 'malay' && currentGender === 'male' && type === 'top') { outfitData.items[type] = { name: 'bajumelayu', category: category }; // Special case for Indian male outfit - use Dhotti for bottom } else if (category === 'indian' && currentGender === 'male' && type === 'bottom') { outfitData.items[type] = { name: 'Dhotti', category: category }; } else { outfitData.items[type] = { name: item.name, category: category }; } } } } // Only add outfit if it has items if (Object.keys(outfitData.items).length > 0) { outfitsToDisplay.push(outfitData); } } } if (outfitsToDisplay.length === 0) { var noOutfitsText = new Text2("No saved outfits", { size: 40, fill: 0x888888 }); noOutfitsText.anchor.set(0.5, 0.5); outfitContainer.addChild(noOutfitsText); return self; } // Update page indicator var totalPages = Math.ceil(outfitsToDisplay.length / 6); self.pageIndicator.setText("Page " + (storage.currentWardrobePage + 1) + "/" + totalPages); // Calculate grid layout for pagination var itemsPerRow = 3; // 3 items per row var itemsPerPage = 6; // 6 items per page var itemSize = 350; // Size for each item var padding = 60; // Padding between items var startX = -(itemsPerRow - 1) / 2 * (itemSize + padding); var startY = -300; // Position items higher in the panel // Translations for ethnic categories var categoryLabels = { siamese: { en: 'Siamese', ms: 'Siam', zh: '暹罗', ta: 'சியாமீஸ்' }, malay: { en: 'Malay', ms: 'Melayu', zh: '马来', ta: 'மலாய்' }, chinese: { en: 'Chinese', ms: 'Cina', zh: '华人', ta: 'சீன' }, indian: { en: 'Indian', ms: 'India', zh: '印度', ta: 'இந்திய' }, indigenous: { en: 'Indigenous', ms: 'Orang Asli', zh: '原住民', ta: 'பழங்குடி' }, iban: { en: 'Iban', ms: 'Iban', zh: '伊班族', ta: 'இபான்' }, kadazan: { en: 'Kadazan', ms: 'Kadazan', zh: '卡达山族', ta: 'கடசான்' }, babanyonya: { en: 'Baba Nyonya', ms: 'Baba Nyonya', zh: '峇峇娘惹', ta: 'பாபா நியோனியா' }, chetti: { en: 'Chetti', ms: 'Chetti', zh: '切蒂', ta: 'செட்டி' }, modern: { en: 'Serani', ms: 'Serani', zh: 'Serani', ta: 'Serani' } }; // Calculate start and end indices for pagination var startIndex = storage.currentWardrobePage * itemsPerPage; var endIndex = Math.min(startIndex + itemsPerPage, outfitsToDisplay.length); // Display items for current page only for (var i = startIndex; i < endIndex; i++) { var pageIndex = i - startIndex; // Index relative to current page var row = Math.floor(pageIndex / itemsPerRow); var col = pageIndex % itemsPerRow; var outfitPreview = new Character(); // Remove base from character preview in wardrobe outfitPreview.removeChild(outfitPreview.layers.base); outfitPreview.layers.base = null; outfitPreview.scale.set(0.25, 0.25); outfitPreview.loadData(outfitsToDisplay[i]); var outfitFrame = LK.getAsset('itemButton', { anchorX: 0.5, anchorY: 0.5, width: itemSize, height: itemSize, tint: 0xEEEEEE }); var outfitItem = new Container(); outfitItem.addChild(outfitFrame); // Adjust scale of outfit preview to ensure it fits within the frame // Better calculation for scaling to ensure attire is fully visible var baseScale = 0.15; // Base scale for outfit preview outfitPreview.scale.set(baseScale, baseScale); // Ensure the preview fits while keeping attire visible var maxHeight = itemSize * 0.75; if (outfitPreview.height > maxHeight) { var heightScaleFactor = maxHeight / outfitPreview.height; outfitPreview.scale.set(baseScale * heightScaleFactor, baseScale * heightScaleFactor); } // Center the preview in the frame and adjust Y position to prevent overlap outfitPreview.position.set(0, -20); // Move up slightly to avoid overlap with label outfitItem.addChild(outfitPreview); // Calculate position based on grid layout outfitItem.x = startX + col * (itemSize + padding); outfitItem.y = startY + row * (itemSize + padding + 40); // Try to determine ethnic category var categoryName = "Outfit"; var categoryId = null; if (outfitsToDisplay[i].items && Object.keys(outfitsToDisplay[i].items).length > 0) { var firstItem = Object.values(outfitsToDisplay[i].items)[0]; if (firstItem && firstItem.category && categoryLabels[firstItem.category]) { categoryId = firstItem.category; categoryName = categoryLabels[categoryId][storage.currentLanguage] || categoryId; } } var labelText = categoryId ? categoryName : "Outfit " + (i - ethnicCategories.length + 1); var outfitLabel = new Text2(labelText, { size: 30, fill: 0x000000 }); outfitLabel.anchor.set(0.5, 0); outfitLabel.y = itemSize / 2 + 15; outfitItem.addChild(outfitLabel); // Load button functionality outfitItem.outfitData = outfitsToDisplay[i]; outfitItem.interactive = true; outfitItem.down = function (x, y, obj) { if (self.onOutfitSelected) { self.onOutfitSelected(this.outfitData); } // Visual feedback tween(this, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100, easing: tween.easeOut, onFinish: function () { tween(this, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeOut }); }.bind(this) }); }.bind(outfitItem); outfitContainer.addChild(outfitItem); } return self; }; self.show = function () { // Reset to first page when opening wardrobe storage.currentWardrobePage = 0; self.visible = true; self.loadOutfits(); return self; }; self.hide = function () { self.visible = false; // Show title text when wardrobe is closed if (typeof titleText !== 'undefined' && titleText) { titleText.visible = true; } return self; }; self.setOutfitSelectedCallback = function (callback) { self.onOutfitSelected = callback; return self; }; // Initial state self.visible = false; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xE6E6FA }); /**** * Game Code ****/ // Game constants // Initialize ItemSelector var itemSelector = new ItemSelector(); itemSelector.x = 2048 / 2; itemSelector.y = 150; // Moved even higher for better positioning itemSelector.currentCategory = 'malay'; // Initialize current category game.addChild(itemSelector); // Initialize with category selection after adding to the game itemSelector.setCategory('malay'); // Add Indigenous female attire itemSelector.items.indigenous.female.top = [{ name: 'Indigenous', label: { en: 'Indigenous Attire', ms: 'Pakaian Orang Asli', zh: '原住民服装', ta: 'பழங்குடி ஆடை' } }]; // Add Ibanman to Iban male attire itemSelector.items.iban.male.top = [{ name: 'Ibanman', label: { en: 'Iban Attire', ms: 'Pakaian Iban', zh: '伊班族服装', ta: 'இபான் ஆடை' } }]; // Add Ibanwoman to Iban female attire itemSelector.items.iban.female.top = [{ name: 'Ibanwoman', label: { en: 'Iban Female Attire', ms: 'Pakaian Wanita Iban', zh: '伊班族女性服装', ta: 'இபான் பெண் ஆடை' } }]; // Indian traditional // Indigenous traditional // Modern fusion // Sounds // Music // Initialize storage defaults if they don't exist if (storage.savedCharacters === undefined) { storage.savedCharacters = []; } if (storage.currentLanguage === undefined) { storage.currentLanguage = "en"; } var translations = { title: { en: 'Malaysian Mosaic', ms: 'Mozek Malaysia', zh: '马来西亚镶嵌', ta: 'மலேசிய மொசைக்' }, reset: { en: 'Reset', ms: 'Tetapkan Semula', zh: '重置', ta: 'மீட்டமை' } }; // Create background var background = LK.getAsset('backgroundBox', { anchorX: 0.5, anchorY: 0.5 }); background.x = 2048 / 2; background.y = 2732 / 2; game.addChild(background); // Add cultural information scripts var culturalInfoScripts = { bajuKurung: { en: "Before the 20th century, Malay women only wore kemban cloth. After the arrival of Islam, they began wearing the modest baju kurung. Baju kurung is typically known as a type of loose-fitting, long dress, sometimes reaching the knees, paired with a long folded skirt. It covers the entire body, revealing only the face and hands, seen as complying with Islamic dress rules. Baju kurung can be paired with traditional fabrics like songket or batik, and complemented with a selendang or head covering. Baju kurung is suitable for formal occasions or daily affairs.", ms: "Sebelum kurun ke-20, wanita Melayu hanya memakai kain kemban sahaja. Setelah kedatangan Islam, mereka mula memakai baju kurung yang sopan. Baju kurung lazimnya diketahui sebagai jenis baju longgar yang labuh, kadang kala hingga ke lutut dan dipadankan dengan kain panjang yang berlipat tepi. Baju tersebut meliputi seluruh tubuh, memperlihatkan wajah dan tangan sahaja, dilihat sebagai mematuhi peraturan pakaian Islam. Baju kurung boleh dipadankan dengan kain tradisional seperti songket atau batik. Digandingkan dengan kain selendang atau tudung kepala. Baju kurung sesuai dipakai dalam majlis-majlis formal atau urusan seharian.", zh: "在20世纪之前,马来女性只穿kemban布。伊斯兰教到来后,她们开始穿着保守的baju kurung。Baju kurung通常被称为一种宽松、长款的衣服,有时候长及膝盖,搭配长折边裙子。它覆盖全身,只露出脸部和双手,被视为符合伊斯兰着装规则。Baju kurung可以与传统织物如songket或batik搭配,并配以selendang或头巾。Baju kurung适合正式场合或日常事务穿着。", ta: "20ஆம் நூற்றாண்டுக்கு முன், மலாய் பெண்கள் கெம்பான் துணி மட்டுமே அணிந்தனர். இஸ்லாம் வருகைக்குப் பிறகு, அவர்கள் அடக்கமான பாஜு குருங் அணியத் தொடங்கினர். பாஜு குருங் பொதுவாக தளர்வான, நீண்ட ஆடையாக அறியப்படுகிறது, சில நேரங்களில் முழங்கால் வரை நீண்டு, மடிப்புடன் கூடிய நீண்ட பாவாடையுடன் இணைக்கப்படுகிறது. இது முகம் மற்றும் கைகள் மட்டுமே வெளிப்படும் வகையில் முழு உடலையும் மூடுகிறது, இஸ்லாமிய உடை விதிகளுக்கு இணங்குவதாக கருதப்படுகிறது. பாஜு குருங் சாங்கேட் அல்லது பாட்டிக் போன்ற பாரம்பரிய துணிகளுடன் இணைக்கப்படலாம். செலண்டாங் அல்லது தலைப்பாகை உடன் இணைக்கப்படுகிறது. பாஜு குருங் முறையான நிகழ்வுகள் அல்லது அன்றாட விவகாரங்களுக்கு ஏற்றது." } }; // Add title to GUI var titleText = new Text2(translations.title[storage.currentLanguage], { size: 80, fill: 0x4682B4 }); titleText.anchor.set(0.5, 0); titleText.y = 20; LK.gui.top.addChild(titleText); // Add gender selection var genderSelector = new GenderSelector(); genderSelector.x = 2048 / 2; genderSelector.y = 180; genderSelector.setup(); game.addChild(genderSelector); // Add character var character = new Character(); character.x = 2048 / 2; character.y = 2732 / 2 - 100; game.addChild(character); // ItemSelector instance already created earlier in the code // Add language selector var languageSelector = new LanguageSelector(); languageSelector.x = 2048 / 2; languageSelector.y = 2732 - 100; languageSelector.setup(); game.addChild(languageSelector); // Add action buttons var resetButton = new UIButton(translations.reset[storage.currentLanguage], 200, 80, 0xF44336); resetButton.x = 2048 - 300; resetButton.y = 200; game.addChild(resetButton); // Add wardrobe button var wardrobeText = { en: "Ethnic Collection", ms: "Koleksi Etnik", zh: "民族服装集", ta: "இன ஆடை தொகுப்பு" }; // Create a wardrobe button with larger size and better contrast var wardrobeButton = new UIButton(wardrobeText[storage.currentLanguage], 240, 90, 0x8A2BE2); // Set button position wardrobeButton.x = 2048 - 300; wardrobeButton.y = 300; // Make text larger and bolder for better readability wardrobeButton.buttonText.style.size = 40; wardrobeButton.buttonText.style.fill = "#FFFFFF"; game.addChild(wardrobeButton); // Create wardrobe component var wardrobe = new Wardrobe(); wardrobe.x = 2048 / 2; wardrobe.y = 2732 / 2; wardrobe.updateLanguage(storage.currentLanguage); game.addChild(wardrobe); // Connect components genderSelector.setChangeCallback(function (gender) { // Change character base to gender-specific asset character.setGender(gender); }); // Initialize ItemSelector with needed functionality itemSelector.setSelectionCallback(function (item) { character.equip(item); // Show cultural info for baju kurung when selected if (item.itemName === 'bajuKurung') { // Display cultural information panel with baju kurung script culturalInfoPanel.show('bajuKurung'); } }); languageSelector.setChangeCallback(function (language) { // Update all UI text titleText.setText(translations.title[language]); resetButton.setText(translations.reset[language]); wardrobeButton.setText(wardrobeText[language]); // Update gender selector genderSelector.updateLanguage(language); wardrobe.updateLanguage(language); }); // Add cultural info panel var culturalInfoPanel = new CulturalInfoPanel(); culturalInfoPanel.x = 2048 / 2; culturalInfoPanel.y = 2732 / 2; game.addChild(culturalInfoPanel); // Add error message element var errorMessage = new Text2("", { size: 40, fill: 0xFF0000 }); errorMessage.anchor.set(0.5, 0); errorMessage.y = 2732 - 180; // Position above language selector errorMessage.visible = false; LK.gui.bottom.addChild(errorMessage); // Function to show error message temporarily function showError(message, duration) { errorMessage.setText(message); errorMessage.visible = true; LK.setTimeout(function () { errorMessage.visible = false; }, duration || 3000); } // Function to check if character is wearing baju kurung and show the cultural info function checkForBajuKurung() { // Check if character is wearing baju kurung var wearing = false; var itemName = ""; // Check all layers for (var layerName in character.layers) { if (layerName !== 'base' && character.layers[layerName]) { var item = character.layers[layerName]; // Check if this is baju kurung if (item.itemName === 'bajuKurung') { wearing = true; itemName = 'bajuKurung'; break; } } } // If wearing baju kurung, show cultural info if (wearing && itemName) { culturalInfoPanel.show(itemName); } } resetButton.setCallback(function () { // Reset character by clearing all items for (var layerName in character.layers) { if (layerName !== 'base' && character.layers[layerName]) { character.removeChild(character.layers[layerName]); character.layers[layerName] = null; } } }); // Setup wardrobe button wardrobeButton.setCallback(function () { wardrobe.show(); // Hide title text when wardrobe is open titleText.visible = false; }); // Setup wardrobe outfit selection wardrobe.setOutfitSelectedCallback(function (outfitData) { // Apply outfit to character character.loadData(outfitData); // Set character as current outfit automatically for (var categoryId in character.layers) { if (categoryId !== 'base' && character.layers[categoryId]) { if (character.layers[categoryId].select) { character.layers[categoryId].select(); } } } wardrobe.hide(); LK.getSound('itemSelect').play(); }); // Play background music LK.playMusic('malaysiaMix'); // Game update function game.update = function () { // Game logic updates would go here if needed }; // Add event handler for character character.down = function (x, y, obj) { // Check if character is wearing baju kurung for (var layerName in character.layers) { if (layerName !== 'base' && character.layers[layerName]) { var item = character.layers[layerName]; if (item.itemName === 'bajuKurung' && typeof culturalInfoPanel !== 'undefined') { culturalInfoPanel.show('bajuKurung'); break; } } } };
===================================================================
--- original.js
+++ change.js
@@ -747,17 +747,9 @@
zh: '娘惹峇峇服',
ta: 'கெபாயா நியோனியா'
}
}],
- bottom: [{
- name: 'babaNyonyaBottom',
- label: {
- en: 'Sarong Batik',
- ms: 'Sarong Batik',
- zh: '娘惹峇峇裙',
- ta: 'சரோங் பாத்திக்'
- }
- }],
+ bottom: [],
accessory: []
},
male: {
top: [{
@@ -768,17 +760,9 @@
zh: '峇峇上衣',
ta: 'பாபா மேலாடை'
}
}],
- bottom: [{
- name: 'babaNyonyaBottom',
- label: {
- en: 'Baba Pants',
- ms: 'Seluar Baba',
- zh: '峇峇裤子',
- ta: 'பாபா கால்சட்டை'
- }
- }],
+ bottom: [],
accessory: []
}
},
chetti: {
@@ -1725,10 +1709,10 @@
/****
* Game Code
****/
-// Initialize ItemSelector
// Game constants
+// Initialize ItemSelector
var itemSelector = new ItemSelector();
itemSelector.x = 2048 / 2;
itemSelector.y = 150; // Moved even higher for better positioning
itemSelector.currentCategory = 'malay'; // Initialize current category