UNPKG

@axieinfinity/mixer

Version:
174 lines (133 loc) 5.13 kB
# @axieinfinity/mixer ![NPM version][npm-image] [npm-image]: https://img.shields.io/npm/v/%40axieinfinity%2Fmixer A utility for rendering 2D Axie with support for accessories, animations. Use `@axieinfinity/mixer` in your project ## 📦 Installation ``` npm install @axieinfinity/mixer ``` or with yarn ``` yarn add @axieinfinity/mixer ``` ## ⚠️ Important Notes - This version does not include data by default. You must import the required JSON data files and call `initAxieMixer` before using the utility functions. - To render evolved parts, use version ***1.4.1*** or later. ## 🆕 Features - Images URL: https://axiecdn.axieinfinity.com/mixer-stuffs/v6 - Accessory spines URL: https://axiecdn.axieinfinity.com/mixer-stuffs/accessory-spines/v1 - Full support for Nightmare parts - All accessories migrated to Spine 2D ## 🚀 Example Usage #### 1. Initialize Mixer and Render an Axie ```ts import { initAxieMixer, AxieBuilderResult, getAxieSpineFromGenes, } from '@axieinfinity/mixer'; import GenesData from '@axieinfinity/mixer/dist/data/axie-2d-v3-stuff-genes.json'; import SamplesData from '@axieinfinity/mixer/dist/data/axie-2d-v3-stuff-samples.json'; import VariantsData from '@axieinfinity/mixer/dist/data/axie-2d-v3-stuff-variant.json'; import AnimationsData from '@axieinfinity/mixer/dist/data/axie-2d-v3-stuff-animations.json'; initAxieMixer(GenesData, SamplesData, VariantsData, AnimationsData); const axieGenes512 = '0x20000000000003000181a09082040000000100040800800400000090086044020001000010008002000100100840450200010004186044020001001008808404'; const skipAnimation = false; const meta = new Map(); meta.set('accessory-id', '2727'); // set accessory-id to axieId meta.set('accessory-air', 'accessory-air1a'); meta.set('accessory-cheek', 'accessory-cheek1a'); meta.set('accessory-ground', 'accessory-ground1a'); meta.set('accessory-hip', 'accessory-hip1a'); meta.set('accessory-neck', 'accessory-neck1a'); meta.set('accessory-suit-off', 'true'); // set accessory-suit-off to true or false toggle mystic suit const { skeletonDataAsset, combo, variant }: AxieBuilderResult = getAxieSpineFromGenes(axieGenes512, meta, skipAnimation); ``` #### 2. Displaying Accessories on an Axie ```ts import { Assets } from 'pixi.js'; import { Spine } from 'pixi-spine'; import { ISkeletonData } from '@pixi-spine/base'; interface AccessoryFields { name: string; placement: string; // e.g., Air | Ground | Cheek key: string; // e.g., ground1a | air1d | cheek2a } const ACCESSORY_SPINES_URL = 'https://axiecdn.axieinfinity.com/mixer-stuffs/accessory-spines/v1'; function getSpineUrl(key: string): string { /* * e.g. https://axiecdn.axieinfinity.com/mixer-stuffs/accessory-spines/v1/air1b/air1b.json * https://axiecdn.axieinfinity.com/mixer-stuffs/accessory-spines/v1/air1a/air1a.json * */ return `${ACCESSORY_SPINES_URL}/${key}/${key}.json`; } class AccessoryModel { spine: Spine; data: AccessoryFields; constructor(data: AccessoryFields, spineData: ISkeletonData) { this.data = data; this.spine = new Spine(spineData); this.spine.scale.set(1, -1); // Flip vertically for correct orientation const animationName = spineData.animations[0]?.name; if (animationName) { this.spine.state.setAnimation(0, animationName, true); } } get slotName(): string { // e.g., body-air, body-ground, body-cheek, etc. return `body-${this.data.placement.toLowerCase()}`; } } async function main() { const axieSpine: Spine; // Assume axieSpine is already instantiated const groundAccessory: AccessoryFields = { name: "Snowman", placement: "Ground", key: "ground1a", }; const airAccessory: AccessoryFields = { name: "Mr. Ube", placement: "Air", key: "air1d", }; const cheekAccessory: AccessoryFields = { name: "Bloodmaw", placement: "Cheek", key: "cheek2a", }; // Create accessory assets Assets.addBundle("accessories", { [groundAccessory.key]: getSpineUrl(groundAccessory.key), [airAccessory.key]: getSpineUrl(airAccessory.key), [cheekAccessory.key]: getSpineUrl(cheekAccessory.key), }); // Load accessory assets const assets = await Assets.loadBundle("accessories"); // Ground accessory const ground = new AccessoryModel(groundAccessory, assets[groundAccessory.key]); const groundSlotIndex = axieSpine.skeleton.findSlotIndex(ground.slotName); if (groundSlotIndex >= 0) { axieSpine.slotContainers[groundSlotIndex].addChild(ground.spine); } // Air accessory const air = new AccessoryModel(airAccessory, assets[airAccessory.key]); const airSlotIndex = axieSpine.skeleton.findSlotIndex(air.slotName); if (airSlotIndex >= 0) { axieSpine.slotContainers[airSlotIndex].addChild(air.spine); } // Cheek accessory const cheek = new AccessoryModel(cheekAccessory, assets[cheekAccessory.key]); const cheekSlotIndex = axieSpine.skeleton.findSlotIndex(cheek.slotName); if (cheekSlotIndex >= 0) { axieSpine.slotContainers[cheekSlotIndex].addChild(cheek.spine); } // continue with Pixi application .... } main(); ```