Creating a Spritesheet with three.js
Hopefully this saves people some time!
This is using the pixi.js spritesheet format but it shouldn’t be difficult to make it work with whatever spritesheet/sprite atlas format.
One improvement might be to return a promise and resolve it.
import {
TextureLoader,
SpriteMaterial,
Sprite,
NearestFilter,
} from 'three';
import { Character } from './character';
import ss from './spritesheet.png';
import ssData from './spritesheet-data.json';
import { StartingRoom } from './starting-room';
const SPRITESHEET_BLOCK_WIDTH = 25;
const SPRITESHEET_BLOCK_HEIGHT = 25;
export class TextureAtlas {
spritesheet: any;
spritesheetData: any;
xStep: number;
yStep: number;
constructor(onload) {
const loader = new TextureLoader();
loader.load(
ss,
spritesheet => {
this.spritesheetData = {};
spritesheet.horizontalTiles = ssData.meta.size.w / SPRITESHEET_BLOCK_WIDTH;
spritesheet.verticleTiles = ssData.meta.size.h / SPRITESHEET_BLOCK_HEIGHT;
Object.keys(ssData.frames).forEach(frame => {
this.spritesheetData[frame] = {
x: ssData.frames[frame].frame.x,
y: ssData.frames[frame].frame.y,
w: ssData.frames[frame].frame.w,
h: ssData.frames[frame].frame.h,
};
});
spritesheet.magFilter = NearestFilter;
this.spritesheet = spritesheet;
this.xStep = 1 / this.spritesheet.horizontalTiles;
this.yStep = 1 / this.spritesheet.verticleTiles;
this.spritesheet.repeat.set(this.xStep, this.yStep);
onload();
},
// onError callback
err => {
console.error('An error happened.');
}
);
}
setOffset(name) {
const sdata = this.spritesheetData[name];
this.spritesheet.offset.x = (sdata.x % this.spritesheet.image.width) / this.spritesheet.image.width;
this.spritesheet.offset.y = 1 - (sdata.y % this.spritesheet.image.height) / this.spritesheet.image.height - this.yStep;
}
}
// usage
textureAtlas.setOffset('spritename.png');
const material = new SpriteMaterial({ map: textureAtlas.spritesheet.clone() });
const sprite = new Sprite(material);
scene.add(sprite);