78 lines
2.4 KiB
JavaScript
78 lines
2.4 KiB
JavaScript
// src/pages/agent-office/canvas/SpriteLoader.js
|
||
|
||
import { ProceduralSprite } from './ProceduralSprite.js';
|
||
|
||
/**
|
||
* 스프라이트 로더 — PNG 스프라이트시트가 있으면 사용, 없으면 프로시저럴 폴백
|
||
*
|
||
* 스프라이트시트 규격 (Phase 2):
|
||
* - 프레임 크기: 16×32px
|
||
* - 행: 방향 (0=down, 1=up, 2=right)
|
||
* - 열: 상태별 프레임 (idle 2 | walk 4 | type 2 | wait 2 | break 2 = 12열)
|
||
*/
|
||
export class SpriteLoader {
|
||
constructor() {
|
||
this.sprites = new Map(); // agentId → { image: Image, loaded: boolean }
|
||
}
|
||
|
||
/** PNG 스프라이트시트 로드 시도 */
|
||
async tryLoad(agentId, url) {
|
||
return new Promise((resolve) => {
|
||
const img = new Image();
|
||
img.onload = () => {
|
||
this.sprites.set(agentId, { image: img, loaded: true });
|
||
resolve(true);
|
||
};
|
||
img.onerror = () => {
|
||
resolve(false); // 폴백 사용
|
||
};
|
||
img.src = url;
|
||
});
|
||
}
|
||
|
||
hasSprite(agentId) {
|
||
return this.sprites.has(agentId) && this.sprites.get(agentId).loaded;
|
||
}
|
||
|
||
/**
|
||
* 에이전트 1프레임 그리기 (스프라이트 또는 프로시저럴)
|
||
*/
|
||
draw(ctx, agentId, state, direction, frame, x, y, scale) {
|
||
if (this.hasSprite(agentId)) {
|
||
this._drawFromSheet(ctx, agentId, state, direction, frame, x, y, scale);
|
||
} else {
|
||
ProceduralSprite.draw(ctx, agentId, state, direction, frame, x, y, scale);
|
||
}
|
||
}
|
||
|
||
_drawFromSheet(ctx, agentId, state, direction, frame, x, y, scale) {
|
||
const { image } = this.sprites.get(agentId);
|
||
const frameW = 16;
|
||
const frameH = 32;
|
||
|
||
// 방향 → 행
|
||
const dirRow = direction === 'up' ? 1 : direction === 'right' || direction === 'left' ? 2 : 0;
|
||
|
||
// 상태 → 열 오프셋
|
||
const stateOffsets = { idle: 0, walk: 2, type: 6, wait: 8, break_anim: 10 };
|
||
const mappedState = state === 'working' ? 'type' : state === 'waiting' ? 'wait'
|
||
: state === 'reporting' ? 'type' : state === 'break' ? 'break_anim'
|
||
: state === 'walk' ? 'walk' : 'idle';
|
||
const colOffset = stateOffsets[mappedState] || 0;
|
||
|
||
const srcX = (colOffset + frame) * frameW;
|
||
const srcY = dirRow * frameH;
|
||
const destW = frameW * scale;
|
||
const destH = frameH * scale;
|
||
|
||
ctx.save();
|
||
if (direction === 'left') {
|
||
ctx.translate(x, 0);
|
||
ctx.scale(-1, 1);
|
||
ctx.translate(-x, 0);
|
||
}
|
||
ctx.drawImage(image, srcX, srcY, frameW, frameH, x - destW / 2, y - destH, destW, destH);
|
||
ctx.restore();
|
||
}
|
||
}
|