@axieinfinity/mixer
Version:
Axie Infinity Mixer
174 lines (133 loc) • 5.13 kB
Markdown
![NPM version][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
```
npm install @axieinfinity/mixer
```
or with yarn
```
yarn add @axieinfinity/mixer
```
- 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.
- 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
```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);
```
```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", {
[]: getSpineUrl(groundAccessory.key),
[]: getSpineUrl(airAccessory.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();
```