1.4.6 • Published 5 months ago
@axieinfinity/mixer v1.4.6
@axieinfinity/mixer
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
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
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();
1.4.6
5 months ago
1.4.4
10 months ago
1.4.3
10 months ago
1.4.1
1 year ago
1.4.0-beta.14
1 year ago
1.3.0-beta.2
2 years ago
1.3.0-beta.1
3 years ago
1.2.0
3 years ago
1.0.1
3 years ago
0.1.1
3 years ago
1.0.0
3 years ago