본문으로 건너뛰기

스프라이트시트·XML 생성기 · Starling / Sparrow XML

Sparrow XML은 프레임마다 SubTexture 하나를 두고 트림을 frameX·frameY로 저장하며, HaxeFlixel 같은 엔진은 프레임 이름 접두사로 애니메이션을 묶습니다. 이 내보내기는 페이지마다 XML 하나를 쓰며 검증에서 Phaser가 불러와 그렸습니다. HaxeFlixel·FNF 엔진은 시험하지 않았습니다.

Sparrow / Starling XML(여러 FNF 모드의 "spritesheet and XML")은 패킹된 PNG를 TextureAtlas element (imagePath="…")로, 프레임마다 SubTexture 하나로 설명합니다. name, x, y, width, height가 있고, 트림된 프레임에는 frameX, frameY(음수 오프셋)와 frameWidth, frameHeight(원래 크기)가 붙습니다. Nerulio는 페이지마다 XML 하나를 쓰고 회전하지 않습니다. Phaser 4.2는 트림된 프레임을 제대로 그리지만 Phaser 3.90은 그렇지 못하므로, Phaser 3에서는 트림을 끄는 "Sparrow XML (Phaser 3)" 프리셋을 쓰세요. HaxeFlixel과 FNF 엔진은 시험하지 않았습니다.

패킹할 프레임 이미지, GIF 또는 .aseprite 파일을 끌어다 놓으세요
빈 Studio 열기
브라우저에서 처리하며 파일은 업로드되지 않습니다.
Studio 패킹·내보내기: 프레임마다 윤곽이 표시된 아틀라스 페이지, 사용 면적, 내보내기 대상
CC0 에셋(OpenGameArt)을 연 실제 Studio 화면입니다.
내보내기 대상
  • Starling / Sparrow XML검증됨· Phaser 4.2
  • Godot 4검증됨· Godot 4.7.2
  • Unity 6검증됨· Unity 6000.5.3f1
  • Phaser 3 / 4검증됨· Phaser 3.90 + 4.2
  • PixiJS 8검증됨· PixiJS 8.21
  • Aseprite JSON검증됨· Phaser load.aseprite · PixiJS 8.21
  • .aseprite검증됨· Aseprite 1.3.18
  • Spine / libGDX검증됨· spine-canvas 4.2
  • LÖVE검증됨· LÖVE 11.5
  • Defold빌드 확인· Defold bob.jar 1.13.1
  • GameMaker미검증
  • CSS sprites검증됨· Chromium
  • GIF / APNG디코딩 확인· Pillow

SubTexture 읽는 법

프레임 하나가 요소 하나입니다. x, y, width, height로 페이지에서 저장된 픽셀을 잘라 냅니다. 트림된 프레임이면 frameX와 frameY가 전체 프레임이 그 픽셀 기준으로 어디서 시작하는지 알려 주는데, 전체 프레임이 왼쪽 위에서 시작하므로 음수입니다. frameWidth, frameHeight는 그 크기입니다.

애니메이션은 파일에 저장되지 않고 프레임 이름으로 만듭니다. 예를 들어 이름이 run_으로 시작하는 모든 SubTexture입니다. Phaser는 접두어와 generateFrameNames로 이렇게 하므로, 애니메이션 목록이 있는 JSON 아틀라스보다 이름이 더 중요합니다.

알아 둘 버그: Phaser 3.90의 AtlasXML 파서는 트림된 크기와 전체 크기를 setTrim에 거꾸로 넘깁니다. 그래서 Phaser 3.90에서는 트림된 XML 프레임이 잘못 그려집니다. 같은 파일이 Phaser 4.2에서는 제대로 그려집니다. "Sparrow XML (Phaser 3)" 프리셋은 트림을 꺼서 어떤 프레임에도 frameX/frameY가 없고, 두 버전 모두 통과합니다. Nerulio 엔진 검증 49회 중 실패는 이 2회뿐이었습니다.

TextureAtlas
루트 요소. imagePath가 PNG 페이지 이름이고 너비와 높이가 함께 있습니다.
SubTexture
프레임 하나: 이름과 페이지 위 사각형.
frameX, frameY
저장된 픽셀에서 본 전체 프레임의 음수 오프셋(트림된 프레임만).
frameWidth, frameHeight
트림 전 프레임 크기.
pivotX, pivotY
전체 프레임 위 픽셀 단위 피벗. Nerulio는 쓰지만 Phaser XML 로더는 읽지 않습니다.

예시: 두 프리셋의 같은 프레임과 Phaser 3.90 버그

Starling / Sparrow XML 프리셋(트림 켬), 페이지 38 × 50
SubTexture name="run_0" x="0" y="34" width="18" height="15"
            frameX="-10" frameY="-10" frameWidth="40" frameHeight="29" pivotX="20" pivotY="29"

"Sparrow XML (Phaser 3)" 프리셋(트림 끔), 페이지 82 × 91
SubTexture name="run_0" x="0" y="0" width="40" height="29" pivotX="20" pivotY="29"

Phaser 3.90 AtlasXML 호출     setTrim(18, 15, 10, 10, 40, 29)
Frame.setTrim이 기대하는 순서  setTrim(40, 29, 10, 10, 18, 15)  (전체 크기가 먼저, 트림 크기가 마지막)

여기서 트림을 끈 대가: 38 × 50 = 1,900 px² 대신 82 × 91 = 7,462 px² (3.9배)

Phaser의 JSON 파서는 sourceSize를 먼저, spriteSourceSize를 나중에 넘깁니다. 그래서 트림된 JSON 아틀라스는 Phaser 3.90에서도 괜찮고, 같은 프레임을 XML로 주면 잘못 그려집니다.

이렇게 작동합니다

  • 트림 프레임의 frameX·frameY와 피벗이 든 SubTexture 항목의 페이지별 XML.
  • 프리셋 두 개: Starling / Sparrow XML(트림 켬)과 트림을 끈 "Sparrow XML (Phaser 3)".
  • Phaser 4.2는 둘 다 그리고, Phaser 3.90은 트림된 XML 프레임을 잘못 그리므로(Phaser 버그) Phaser 3 프리셋을 쓰세요.
  • 이 대상은 회전을 쓰지 않습니다.

사용 방법

  1. 번호 붙은 프레임·GIF·.aseprite 파일이나 시트(적용까지)를 넣습니다.
  2. 타임라인에서 프레임 이름을 확인합니다. 각 이름이 SubTexture 이름이 됩니다.
  3. 패킹·내보내기에서 Starling / Sparrow XML이나 Sparrow XML (Phaser 3)을 고릅니다.
  4. 엔진에서 PNG와 XML을 불러옵니다.

받게 되는 파일

파일용도
run.xmlTextureAtlas element (imagePath="run.png", width, height)와 프레임마다 SubTexture 하나. frameX·frameY·frameWidth·frameHeight는 트림된 프레임에만, pivotX·pivotY는 픽셀 단위.
run.png페이지. 여러 페이지면 run-0.png와 run-0.xml, run-1.png와 run-1.xml 식.

불러오기

  1. Phaser 4.2: this.load.atlasXML("run", "run.png", "run.xml") 후 this.add.sprite(x, y, "run", "run_0"). 어느 XML 프리셋이든 됩니다.
  2. Phaser 3.90: "Sparrow XML (Phaser 3)"으로 내보내고 같은 방법으로 불러옵니다.
  3. 이름으로 애니메이션 만들기: this.anims.create({ key: "run", frames: this.anims.generateFrameNames("run", { prefix: "run_", start: 0, end: 5 }), frameRate: 10, repeat: -1 }).
  4. 다른 엔진(HaxeFlixel, FNF 엔진, Starling)도 같은 SubTexture 구조를 읽지만 여기서는 실행하지 않았습니다. 믿고 쓰기 전에 트림된 프레임 하나를 원본 이미지와 비교하세요.

문제 해결

증상유력한 원인확인 방법해결
Phaser 3.90에서만 트림된 프레임이 밀리거나 크기가 틀리게 그려짐Phaser 3.90의 AtlasXML이 트림 크기와 전체 크기를 setTrim에 거꾸로 넘김그 프레임에 frameX가 있고, 같은 파일이 Phaser 4.2에서는 정상"Sparrow XML (Phaser 3)" 프리셋(트림 끔), JSON 아틀라스(여기선 트림 정상), 또는 Phaser 4 사용
프레임이 돌아가거나 뒤집힘프레임을 회전시킨 패커의 XML(rotated="true")인데 Phaser XML 파서는 이를 읽지 않음XML에서 rotated 검색회전 없이 다시 패킹. Nerulio XML 내보내기는 회전된 패킹을 거부함
애니메이션에 엉뚱한 프레임이 섞임접두어가 너무 넓음: run_이 run_attack_0에도 걸림XML의 프레임 이름 목록 확인내보내기 전에 애니메이션마다 고유한 접두어를 줌
스프라이트 원점이 피벗을 무시함Phaser XML 로더는 사각형과 트림 속성만 읽고 pivotX/pivotY는 읽지 않음스프라이트 원점이 가운데에 머묾sprite.setOrigin(0.5, 1) 호출, 또는 Phaser가 pivot을 원점으로 쓰는 JSON 아틀라스 사용

다른 방법

방법이럴 때 더 낫습니다
Phaser JSON 아틀라스Phaser 게임이라면: 3.90과 4.2 모두 트림이 정상이고 피벗이 스프라이트 원점이 되며 애니메이션 파일도 함께 옵니다. Phaser 텍스처 아틀라스 참고.
기존 FNF 시트 미리보기·변환이미 있는 spritesheet + XML을 GIF로 바꾸려면 FNF 스프라이트시트를 GIF로 참고.

엔진별 내보내기와 검증 방법

"검증됨"은 실제 CC0 에셋으로 내보낸 파일을 해당 엔진·도구가 직접 불러와 원본과 비교했다는 뜻입니다. 불러오지 않은 형식은 그렇게 표시합니다.

대상파일검증
Godot 4.tres SpriteFrames · .tscn AnimatedSprite2D · .png.import검증됨 Godot 4.7.2Godot가 불러와 모든 애니메이션 프레임을 그려 원본과 비교했습니다. 씬은 Nearest 필터를 쓰고 회전은 쓰지 않습니다.
Unity 6.unity.json · Editor/NerulioSpriteImporter.cs · AnimationClip검증됨 Unity 6000.5.3f1배치 모드에서 스프라이트 영역·피벗·픽셀·클립 키·길이를 확인했습니다.
Phaser 3 / 4atlas JSON (multiatlas) · .anims.json검증됨 Phaser 3.90 + 4.2두 버전 모두에서 프레임과 애니메이션을 그렸습니다.
PixiJS 8spritesheet JSON · animations · anchor · meta.scale검증됨 PixiJS 8.21회전·여러 페이지 아틀라스도 포함해 확인했습니다.
Aseprite JSONhash / array · frameTags · slices검증됨 Phaser load.aseprite · PixiJS 8.21태그의 방향과 반복 횟수가 유지됩니다.
.asepritelayers · tags · durations · slices검증됨 Aseprite 1.3.18Aseprite 명령줄로 열어 렌더링했습니다.
Spine / libGDX.atlas검증됨 spine-canvas 4.2Spine 런타임이 회전·트림 영역을 모두 그렸습니다. libGDX 자체는 실행하지 않았습니다.
Starling / Sparrow XMLXML per page검증됨 Phaser 4.2Phaser 3.90은 트림된 XML 프레임을 잘못 그립니다(Phaser 버그). "Sparrow XML (Phaser 3)" 프리셋은 트림을 끄며 3.90·4.2 모두 통과합니다.
LÖVELua quads · nerulio_atlas.lua · main.lua검증됨 LÖVE 11.5포함된 헬퍼로 모든 프레임을 그리고 모든 애니메이션을 재생했습니다.
Defold.atlas · .tilesource빌드 확인 Defold bob.jar 1.13.1Defold 명령줄 빌더로 빌드하고 빌드된 텍스처의 UV를 다시 읽어 확인했습니다.
GameMakerspr_<name>_stripN.png · gamemaker.json미검증GameMaker에서 불러오지 않았습니다(헤드리스 실행 불가). 스트립은 GameMaker 스트립 가져오기 방식대로 자릅니다.
CSS sprites.css · preview .html검증됨 Chromium포함된 스타일시트로 모든 클래스를 그렸습니다.
GIF / APNGone file per animation디코딩 확인 Pillow내보낸 뒤 모든 프레임과 지연 시간을 다시 디코딩했습니다. APNG는 원본과 동일합니다.

검증 근거

내보내기: 실제 CC0 에셋으로 실제 엔진에서 49회 실행해 47회 통과. 실패 2회는 Phaser 3.90의 트림 XML 버그이며 Phaser 3 프리셋으로 피합니다. 실제 프레임 세트 5개로 패커 비교(CodeAndWeb 무료 웹 패커, GAPTools, free-tex-packer): 회전 허용 시 5개 모두 가장 작은 시트, 회전 없이는 5개 중 4개. 모든 프레임이 픽셀 단위로 복원됩니다.

한계

  • 폴리곤(메시) 패킹은 제공하지 않습니다. 검증한 엔진 중 내보낸 데이터로 메시 아틀라스를 그리는 엔진이 없기 때문입니다.
  • GameMaker 스트립은 GameMaker 자체에서 검증하지 않았습니다.
  • 배율 변형(@0.5x~@4x)은 최근접 이웃 방식만 씁니다.
  • 트림된 Starling XML은 Phaser 3.90에서 잘못 그려지므로 "Sparrow XML (Phaser 3)" 프리셋을 쓰세요.

버전과 출처

닌자와 궁수 프레임 세트로 Phaser 3.90.0과 4.2.1에서 불러와 그렸습니다. 트림을 켠 Starling 프리셋은 3.90에서만 실패했고(엔진 실행 49회 중 2회), Phaser 3 프리셋은 두 버전 모두 통과했습니다. setTrim 인수 순서는 Phaser 3.90 소스에서 인용했습니다. HaxeFlixel, Starling, FNF 엔진은 실행하지 않았습니다.

참고한 공식 문서

자주 묻는 질문

Friday Night Funkin'·HaxeFlixel에서 되나요?

시험하지 않았습니다. XML은 Phaser에서만 검증했습니다. 같은 Sparrow XML 형식이지만 여기서 HaxeFlixel 빌드를 돌리지는 않았습니다.

Phaser 3에서 트림된 프레임이 밀려 보이는 이유는?

Phaser 3.90의 XML 파서가 트림 크기와 전체 크기를 반대로 넘기기 때문입니다. "Sparrow XML (Phaser 3)" 프리셋은 트림을 꺼서 3.90·4.2 모두 통과합니다.

무료인가요? 계정이 필요한가요?

이 페이지의 기능은 모두 무료이며 계정 없이 쓸 수 있습니다. 워터마크나 막혀 있는 내보내기가 없습니다.

스프라이트가 업로드되나요?

아니요. Studio는 이 브라우저 탭 안에서 디코딩·패킹·내보내기를 합니다. 프로젝트는 브라우저(IndexedDB)에 자동 저장되며 .nerulio 파일로 저장할 수 있습니다.

Aseprite나 엔진 플러그인을 설치해야 하나요?

아니요. .aseprite 파일은 브라우저에서 읽고 씁니다. 엔진별 번들에는 그 엔진에 필요한 것이 들어 있습니다(Godot는 가져오기 설정과 씬, Unity와 Godot 타일셋은 작은 편집기 스크립트).