User prompt
Narrowing the size of Malecharacterbase so that he doesn't look too fat
User prompt
Make sure the size of Malecharacterbase didn't overlapp the selection
User prompt
Resize Malecharacterbase to the size 768 px x 1528 px
User prompt
Replace male character base with the asset Malecharacterbase
User prompt
Separate character base according to the gender
User prompt
/* CSS */ .item-button { width: 300px; height: 300px; padding: 0; /* Remove default padding */ border: none; /* Remove default border */ background: none; /* Remove default background */ cursor: pointer; } .button-image { width: 100%; /* Fill button width */ height: 100%; /* Fill button height */ object-fit: cover; /* or 'contain' based on your needs */ display: block; /* Remove image default spacing */ }
User prompt
/* If the image is directly in the button */ button img { width: 300px; /* Adjust to your desired size */ height: 300px; /* Adjust to your desired size */ object-fit: contain; /* Preserve aspect ratio */ } /* If using a background image */ button { background-image: url(your-image.jpg); background-size: cover; /* or contain */ width: 300px; height: 300px; /* Add padding if needed */ }
User prompt
The image showcase in the items button is too small
User prompt
Asset's bajukurungbutton replaces items button for Malay female only
User prompt
Touch functionality that equips the item when selected for bajukurungbutton, replace items button for Malay female only
User prompt
Make the size of item's button to 768 px to 1528 px, same as the attire's image size, and the player can scroll down the wardrobe to see more attire
User prompt
You can crop half of the attire's image displayed in the item's button, and resize it to 250 x 250 pixels in the item's button
User prompt
Half of the attire's image is shown in the item's button with the size 250 x 250 pixels
User prompt
Using different scaling factors for different types of items within the items button, as long as it is fully occupied the items button
User prompt
Make the size of the image of attire in the items button fit with the items button size
User prompt
Make the attire's image bigger in the item's button but still inside the item's button
User prompt
The attire becomes bigger that can be shown in size 728 (width) x 1528 (height) after it was selected from the item's button ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The attire becomes bigger automatically after the attire is selected
User prompt
All of the attires must be shown inside item's button in the wardrobe
User prompt
Make sure all of the word displayed for each attire is visible
User prompt
Rearrange all of the item's button and make sure they are tidy, all of the attire didn't overlap with each other
User prompt
Rearrange the item's button and make all of them tidy
User prompt
Make all of the item's button same size, make sure that the attire always in the item's button
User prompt
Remove yellow block from Chinese female attire
User prompt
Remove songkok asset for Malay male
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { savedCharacters: [], currentLanguage: "en" }); /**** * Classes ****/ var CategorySelector = Container.expand(function () { var self = Container.call(this); self.categories = [{ 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: 'modern', label: { en: 'Modern', ms: 'Moden', zh: '现代', ta: 'நவீன' } }]; 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.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 var base = self.attachAsset('characterBase', { 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 }; self.equip = function (item) { if (!item) return; // 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 = { 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; }; 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; } } // 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; var itemGraphics = self.attachAsset(itemName, { anchorX: 0.5, anchorY: 0.5 }); // 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; // 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; } return self; }; self.down = function (x, y, obj) { // Handle item selection self.select(); }; 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 = { 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: 'changshan', label: { en: 'Changshan', ms: 'Changshan', zh: '长衫', ta: 'சாங்ஷான்' } }], accessory: [{ name: 'chineseFan', label: { en: 'Fan', ms: 'Kipas', zh: '扇子', ta: 'விசிறி' } }] } }, indian: { female: { top: [{ name: 'saree', label: { en: 'Saree', ms: 'Sari', zh: '纱丽', ta: 'சேலை' } }], accessory: [{ name: 'bindiForeheadMark', label: { en: 'Bindi', ms: 'Bindi', zh: '额头装饰', ta: 'பொட்டு' } }] }, male: { top: [{ name: 'kurta', label: { en: 'Kurta', ms: 'Kurta', zh: '库尔塔', ta: 'குர்தா' } }], bottom: [{ name: 'dhoti', 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: { top: [{ name: 'indigenousVest', label: { en: 'Traditional Vest', ms: 'Rompi Tradisional', zh: '传统背心', ta: 'பாரம்பரிய மேலாடை' } }], headdress: [{ name: 'headDress', label: { en: 'Headdress', ms: 'Hiasan Kepala', zh: '头饰', ta: 'தலை அணி' } }] } }, iban: { female: { top: [{ name: 'indigenousVest', label: { en: 'Ngepan Vest', ms: 'Rompi Ngepan', zh: '伊班族背心', ta: 'நெகபன் மேலாடை' } }], headdress: [{ name: 'headDress', label: { en: 'Pua Kumbu Headdress', ms: 'Hiasan Kepala Pua Kumbu', zh: '伊班族头饰', ta: 'புவா குமபு தலை அணி' } }] }, male: { top: [{ name: 'ibanVest', label: { en: 'Iban Vest', ms: 'Rompi Iban', zh: '伊班族背心', ta: 'இபான் மேலாடை' } }], headdress: [{ name: 'headDress', label: { en: 'Pua Kumbu Headdress', ms: 'Hiasan Kepala Pua Kumbu', zh: '伊班族头饰', ta: 'புவா குமபு தலை அணி' } }] } }, kadazan: { female: { top: [{ name: 'indigenousVest', label: { en: 'Sinuangga Vest', ms: 'Rompi Sinuangga', zh: '卡达山族背心', ta: 'சினுவாங்க மேலாடை' } }], headdress: [{ name: 'headDress', label: { en: 'Kadazan Headdress', ms: 'Hiasan Kepala Kadazan', zh: '卡达山族头饰', ta: 'கடசான் தலை அணி' } }] }, male: { top: [{ name: 'kadazanVest', label: { en: 'Kadazan Vest', ms: 'Rompi Kadazan', zh: '卡达山族背心', ta: 'கடசான் மேலாடை' } }], headdress: [{ name: 'headDress', label: { en: 'Kadazan Headdress', ms: 'Hiasan Kepala Kadazan', zh: '卡达山族头饰', ta: 'கடசான் தலை அணி' } }] } }, modern: { female: { top: [{ name: 'modernTop', label: { en: 'Modern Top', ms: 'Atasan Moden', zh: '现代上衣', ta: 'நவீன மேல்' } }], bottom: [{ name: 'modernBottom', label: { en: 'Modern Bottom', ms: 'Bawahan Moden', zh: '现代裤子', ta: 'நவீன கீழ்' } }] }, male: { top: [{ name: 'modernMaleTop', label: { en: 'Modern Top', ms: 'Atasan Moden', zh: '现代上衣', ta: 'நவீன மேல்' } }], bottom: [{ name: 'modernBottom', label: { en: 'Modern Bottom', ms: 'Bawahan Moden', zh: '现代裤子', ta: 'நவீன கீழ்' } }] } } }; 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 = genderSelector.selectedGender; // 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 = -80; 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 = genderSelector.selectedGender; 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] || []; } var filteredItems = currentItems; // Use a consistent button size and layout var buttonSize = 250; // Larger size for all buttons to fit text var itemsPerRow = 3; // Reduce items per row to allow more space var horizontalSpacing = 280; // Increased horizontal spacing between items var verticalSpacing = 300; // Increased vertical spacing between rows // 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(); // Clickable background (add first to be at the bottom) var bg = LK.getAsset('itemButton', { anchorX: 0.5, anchorY: 0.5, width: buttonSize, height: buttonSize }); itemContainer.addChild(bg); // Item preview var itemPreview = new ClothingItem(self.currentType, self.currentCategory, item.name); // Calculate appropriate scale based on the asset size to fit in button var maxDimension = Math.max(itemPreview.originalWidth || itemPreview.width, itemPreview.originalHeight || itemPreview.height); var scaleFactor = buttonSize * 0.6 / maxDimension; itemPreview.scale.set(scaleFactor, scaleFactor); // Center the preview in the button itemPreview.position.set(0, 0); itemContainer.addChild(itemPreview); // Item label var itemLabel = new Text2(label, { size: 30, fill: 0x000000 }); itemLabel.anchor.set(0.5, 0); itemLabel.y = buttonSize / 2 + 15; itemContainer.addChild(itemLabel); // Calculate grid position var gridStartX = -((itemsPerRow - 1) * horizontalSpacing) / 2; var posX = gridStartX + col * horizontalSpacing; var posY = row * verticalSpacing; 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) { 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.addChild(itemContainer); self.itemButtons.push(itemContainer); } return self; }; self.setSelectionCallback = function (callback) { self.onItemSelected = callback; 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: 1800, 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); var outfitContainer = new Container(); self.addChild(outfitContainer); 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 = ['malay', 'chinese', 'indian', 'indigenous', 'iban', 'kadazan', 'modern']; var currentGender = genderSelector.selectedGender; 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 }; } 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; } // Calculate grid layout var itemsPerRow = 4; var itemSize = 300; // Smaller consistent size var padding = 40; // Increased padding for better separation var startX = -(itemsPerRow - 1) / 2 * (itemSize + padding); var startY = 50; // Translations for ethnic categories var categoryLabels = { 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: 'கடசான்' }, modern: { en: 'Modern', ms: 'Moden', zh: '现代', ta: 'நவீன' } }; for (var i = 0; i < outfitsToDisplay.length; i++) { var row = Math.floor(i / itemsPerRow); var col = i % 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 // Calculate scaling factor based on the preview size var maxDimension = Math.max(outfitPreview.width, outfitPreview.height); var scaleFactor = itemSize * 0.4 / maxDimension; // Even smaller scale factor outfitPreview.scale.set(scaleFactor, scaleFactor); // Center the preview in the frame and adjust Y position to prevent overlap outfitPreview.position.set(0, -30); // Move up more to avoid overlap with label outfitItem.addChild(outfitPreview); 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 () { self.visible = true; self.loadOutfits(); return self; }; self.hide = function () { self.visible = false; 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 ****/ // Initialize storage defaults if they don't exist // Music // Sounds // Modern fusion // Indigenous traditional // Indian traditional // Chinese traditional // Malay traditional // Clothing items // UI elements // Character base // Text translations if (storage.savedCharacters === undefined) { storage.savedCharacters = []; } if (storage.currentLanguage === undefined) { storage.currentLanguage = "en"; } var translations = { title: { en: 'Malaysian Mosaic', ms: 'Mozek Malaysia', zh: '马来西亚镶嵌', ta: 'மலேசிய மொசைக்' }, save: { en: 'Save', ms: 'Simpan', 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 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); // Create ItemSelector instance to use as a reference but don't add to the game var itemSelector = new ItemSelector(); // Add language selector var languageSelector = new LanguageSelector(); languageSelector.x = 2048 / 2; languageSelector.y = 2732 - 100; languageSelector.setup(); game.addChild(languageSelector); // Add action buttons var saveButton = new UIButton(translations.save[storage.currentLanguage], 200, 80, 0x4CAF50); saveButton.x = 2048 - 300; saveButton.y = 100; game.addChild(saveButton); 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: "இன ஆடை தொகுப்பு" }; var wardrobeButton = new UIButton(wardrobeText[storage.currentLanguage], 200, 80, 0x9370DB); wardrobeButton.x = 2048 - 300; wardrobeButton.y = 300; 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 appearance based on gender if (gender === 'male') { character.layers.base.scale.set(0.8, 1); } else { character.layers.base.scale.set(1, 1); } }); // Initialize ItemSelector with needed functionality itemSelector.setSelectionCallback(function (item) { character.equip(item); }); languageSelector.setChangeCallback(function (language) { // Update all UI text titleText.setText(translations.title[language]); saveButton.setText(translations.save[language]); resetButton.setText(translations.reset[language]); wardrobeButton.setText(wardrobeText[language]); // Update gender selector genderSelector.updateLanguage(language); wardrobe.updateLanguage(language); }); // Button actions saveButton.setCallback(function () { var savedCharacters = storage.savedCharacters || []; savedCharacters.push(character.getData()); storage.savedCharacters = savedCharacters; LK.getSound('characterSaved').play(); // Visual feedback LK.effects.flashScreen(0x00FF00, 300); }); 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(); }); // 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 };
===================================================================
--- original.js
+++ change.js
@@ -735,12 +735,12 @@
currentItems = self.items[self.currentCategory][currentGender][self.currentType] || [];
}
var filteredItems = currentItems;
// Use a consistent button size and layout
- var buttonSize = 200; // Consistent size for all buttons
- var itemsPerRow = 4; // Display 4 items per row
- var horizontalSpacing = 220; // Horizontal spacing between items
- var verticalSpacing = 240; // Vertical spacing between rows
+ var buttonSize = 250; // Larger size for all buttons to fit text
+ var itemsPerRow = 3; // Reduce items per row to allow more space
+ var horizontalSpacing = 280; // Increased horizontal spacing between items
+ var verticalSpacing = 300; // Increased vertical spacing between rows
// Create buttons for each item
for (var i = 0; i < filteredItems.length; i++) {
var row = Math.floor(i / itemsPerRow);
var col = i % itemsPerRow;
@@ -765,13 +765,13 @@
itemPreview.position.set(0, 0);
itemContainer.addChild(itemPreview);
// Item label
var itemLabel = new Text2(label, {
- size: 24,
+ size: 30,
fill: 0x000000
});
itemLabel.anchor.set(0.5, 0);
- itemLabel.y = buttonSize / 2 + 10;
+ itemLabel.y = buttonSize / 2 + 15;
itemContainer.addChild(itemLabel);
// Calculate grid position
var gridStartX = -((itemsPerRow - 1) * horizontalSpacing) / 2;
var posX = gridStartX + col * horizontalSpacing;
@@ -1103,12 +1103,12 @@
outfitItem.addChild(outfitFrame);
// Adjust scale of outfit preview to ensure it fits within the frame
// Calculate scaling factor based on the preview size
var maxDimension = Math.max(outfitPreview.width, outfitPreview.height);
- var scaleFactor = itemSize * 0.5 / maxDimension; // Smaller scale factor
+ var scaleFactor = itemSize * 0.4 / maxDimension; // Even smaller scale factor
outfitPreview.scale.set(scaleFactor, scaleFactor);
// 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
+ outfitPreview.position.set(0, -30); // Move up more to avoid overlap with label
outfitItem.addChild(outfitPreview);
outfitItem.x = startX + col * (itemSize + padding);
outfitItem.y = startY + row * (itemSize + padding + 40);
// Try to determine ethnic category
@@ -1122,13 +1122,13 @@
}
}
var labelText = categoryId ? categoryName : "Outfit " + (i - ethnicCategories.length + 1);
var outfitLabel = new Text2(labelText, {
- size: 24,
+ size: 30,
fill: 0x000000
});
outfitLabel.anchor.set(0.5, 0);
- outfitLabel.y = itemSize / 2 + 10;
+ outfitLabel.y = itemSize / 2 + 15;
outfitItem.addChild(outfitLabel);
// Load button functionality
outfitItem.outfitData = outfitsToDisplay[i];
outfitItem.interactive = true;