Page 2 of 2
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 20, 2026 9:07 am
by IceSoft
D Ogre wrote: Fri Feb 20, 2026 12:22 am
I'm currently working on further compatibility with Spriter's file format.
The scml file (Spriter Pro json Format) is easier using with PB writting a PB wrapper (C++)
In this case you can use the original example:
https://github.com/lucidspriter/SpriterPlusPlus
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 20, 2026 7:35 pm
by D Ogre
I rather not make use of any outside dependencies in my engine. I'm almost done implementing everything anyhow. It's actually not as hard as it seems. The JSON and XML libraries work just fine in reading a Papagayo and Spriter Pro files.
;==============================================================================
; SpriterPlayer.pbi - Spriter Pro SCML Parser and Animation Player
; Parses SCML XML, interpolates keyframes, applies bone hierarchy transforms
; Requires: Engine.pbi, AssetPack.pbi
I'll be working on a demo shortly.

Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Sat Feb 21, 2026 6:22 pm
by D Ogre
This is for anyone who wants to know how to read the data from a Spriter SCML file:
Code: Select all
; ### Key Data Extracted:
;
; **Image Files:**
; - boss_0/boss_torso_0.png (127x146) pivot: 0.5357,0.0909
; - boss_0/boss_thigh_a.png (57x52) pivot: 0.7988,0.7838
; - boss_0/boss_thigh_0.png (39x48) pivot: 0.4035,0.8406
; - ... (28 total image files)
;
; **Sound Files:**
; - sounds/EXPLOD14.wav
; - sounds/BossLaugh.wav
; - sounds/BossHit_1.wav
; - sounds/BossHit_2.wav
; - sounds/FireBreath.wav
;
; **Bone Data:**
; - Bone_001 (boss_torso_0) size: 127.0x146.0
; - Bone_002 (boss_thigh_a) size: 57.0x52.0
; - ... (11 bones total)
;
; **Animation Data:**
; - Animation "Idle" (2000ms)
; - Timeline 0: bone_001 (Boss_0_boss_torso_0)
; - Key @0ms: x=0.00, y=0.00, angle=0.00, scale=1.00
; - Key @128ms: x=0.00, y=0.00, angle=359.00, scale=1.00
; - ... (16 keys)
; - Timeline 24: bone_010
; - Key @0ms: x=19.56, y=18.11, angle=110.66, scale=0.41
; - Key @128ms: x=19.56, y=18.11, angle=106.98, scale=0.41
; - ... (17 keys)
; - ... (26 timelines total)
Structure SpriterFile
id.i
name.s
width.i
height.i
pivot_x.f
pivot_y.f
type.s
EndStructure
Structure SpriterFolder
id.i
name.s
List files.SpriterFile()
EndStructure
Structure SpriterBone
name.s
realname.s
w.f
h.f
EndStructure
Structure SpriterAnimationKey
time.i
x.f
y.f
angle.f
scale_x.f
spin.i
EndStructure
Structure SpriterTimeline
id.i
name.s
obj.s
List keys.SpriterAnimationKey()
EndStructure
Structure SpriterAnimation
name.s
length.i
List timelines.SpriterTimeline()
EndStructure
Structure SpriterEntity
id.i
name.s
List bones.SpriterBone()
List animations.SpriterAnimation()
EndStructure
Global NewList folders.SpriterFolder()
Global NewList entities.SpriterEntity()
Procedure LoadSpriterData(filename.s)
Protected xml = LoadXML(#PB_Any, filename)
If Not xml
Debug "Error loading XML file: " + filename
ProcedureReturn #False
EndIf
Protected *root = MainXMLNode(xml)
If Not *root Or GetXMLNodeName(*root) <> "spriter_data"
Debug "Invalid Spriter file format"
FreeXML(xml)
ProcedureReturn #False
EndIf
; Load folders and files
Protected *folder = ChildXMLNode(*root)
While *folder
If GetXMLNodeName(*folder) = "folder"
AddElement(folders())
folders()\id = Val(GetXMLAttribute(*folder, "id"))
folders()\name = GetXMLAttribute(*folder, "name")
Protected *file = ChildXMLNode(*folder)
While *file
If GetXMLNodeName(*file) = "file"
AddElement(folders()\files())
folders()\files()\id = Val(GetXMLAttribute(*file, "id"))
folders()\files()\name = GetXMLAttribute(*file, "name")
folders()\files()\width = Val(GetXMLAttribute(*file, "width"))
folders()\files()\height = Val(GetXMLAttribute(*file, "height"))
folders()\files()\pivot_x = ValF(GetXMLAttribute(*file, "pivot_x"))
folders()\files()\pivot_y = ValF(GetXMLAttribute(*file, "pivot_y"))
folders()\files()\type = GetXMLAttribute(*file, "type")
EndIf
*file = NextXMLNode(*file)
Wend
EndIf
*folder = NextXMLNode(*folder)
Wend
; Load entities, bones and animations
*folder = ChildXMLNode(*root)
While *folder
If GetXMLNodeName(*folder) = "entity"
AddElement(entities())
entities()\id = Val(GetXMLAttribute(*folder, "id"))
entities()\name = GetXMLAttribute(*folder, "name")
Protected *obj = ChildXMLNode(*folder)
While *obj
Select GetXMLNodeName(*obj)
Case "obj_info"
Protected type.s = GetXMLAttribute(*obj, "type")
If type = "bone"
AddElement(entities()\bones())
entities()\bones()\name = GetXMLAttribute(*obj, "name")
entities()\bones()\realname = GetXMLAttribute(*obj, "realname")
entities()\bones()\w = ValF(GetXMLAttribute(*obj, "w"))
entities()\bones()\h = ValF(GetXMLAttribute(*obj, "h"))
EndIf
Case "animation"
AddElement(entities()\animations())
entities()\animations()\name = GetXMLAttribute(*obj, "name")
entities()\animations()\length = Val(GetXMLAttribute(*obj, "length"))
Protected *timeline = ChildXMLNode(*obj)
While *timeline
If GetXMLNodeName(*timeline) = "timeline"
AddElement(entities()\animations()\timelines())
entities()\animations()\timelines()\id = Val(GetXMLAttribute(*timeline, "id"))
entities()\animations()\timelines()\name = GetXMLAttribute(*timeline, "name")
entities()\animations()\timelines()\obj = GetXMLAttribute(*timeline, "obj")
Protected *key = ChildXMLNode(*timeline)
While *key
If GetXMLNodeName(*key) = "key"
AddElement(entities()\animations()\timelines()\keys())
entities()\animations()\timelines()\keys()\time = Val(GetXMLAttribute(*key, "time"))
entities()\animations()\timelines()\keys()\spin = Val(GetXMLAttribute(*key, "spin"))
Protected *bone = ChildXMLNode(*key)
If *bone And GetXMLNodeName(*bone) = "bone"
entities()\animations()\timelines()\keys()\x = ValF(GetXMLAttribute(*bone, "x"))
entities()\animations()\timelines()\keys()\y = ValF(GetXMLAttribute(*bone, "y"))
entities()\animations()\timelines()\keys()\angle = ValF(GetXMLAttribute(*bone, "angle"))
entities()\animations()\timelines()\keys()\scale_x = ValF(GetXMLAttribute(*bone, "scale_x"))
EndIf
EndIf
*key = NextXMLNode(*key)
Wend
EndIf
*timeline = NextXMLNode(*timeline)
Wend
EndSelect
*obj = NextXMLNode(*obj)
Wend
EndIf
*folder = NextXMLNode(*folder)
Wend
FreeXML(xml)
ProcedureReturn #True
EndProcedure
; Example usage
File.s = OpenFileRequester("Open Spriter SCML", "", "Spriter (*.scml)|*.scml|All files (*.*)|*.*" ,0)
If File
Debug "Spriter File :" + file
If LoadSpriterData(File)
Debug "Loaded Spriter data successfully"
; List all image files
Debug "=== Image Files ==="
ForEach folders()
ForEach folders()\files()
If folders()\files()\type <> "sound"
Debug Str(folders()\files()\id) + ": " + folders()\files()\name +
" (" + Str(folders()\files()\width) + "x" + Str(folders()\files()\height) + ")" +
" pivot: " + StrF(folders()\files()\pivot_x, 4) + "," + StrF(folders()\files()\pivot_y, 4)
EndIf
Next
Next
; List all sound files
Debug "=== Sound Files ==="
ForEach folders()
ForEach folders()\files()
If folders()\files()\type = "sound"
Debug Str(folders()\files()\id) + ": " + folders()\files()\name
EndIf
Next
Next
; List all bones
Debug "=== Bone Data ==="
ForEach entities()
ForEach entities()\bones()
Debug entities()\bones()\name + " (" + entities()\bones()\realname + ")" +
" size: " + StrF(entities()\bones()\w, 1) + "x" + StrF(entities()\bones()\h, 1)
Next
Next
; List animation data
Debug "=== Animation Data ==="
ForEach entities()
ForEach entities()\animations()
Debug "Animation: " + entities()\animations()\name +
" (" + Str(entities()\animations()\length) + "ms)"
ForEach entities()\animations()\timelines()
Debug " Timeline " + Str(entities()\animations()\timelines()\id) +
": " + entities()\animations()\timelines()\name +
" (" + entities()\animations()\timelines()\obj + ")"
ForEach entities()\animations()\timelines()\keys()
Debug " Key @ " + Str(entities()\animations()\timelines()\keys()\time) + "ms: " +
"x=" + StrF(entities()\animations()\timelines()\keys()\x, 2) +
", y=" + StrF(entities()\animations()\timelines()\keys()\y, 2) +
", angle=" + StrF(entities()\animations()\timelines()\keys()\angle, 2) +
", scale=" + StrF(entities()\animations()\timelines()\keys()\scale_x, 2)
Next
Next
Next
Next
EndIf
EndIf
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 27, 2026 12:59 am
by D Ogre
^^^ Moved Spriter Demo Viewer to the top of post. ^^^
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 27, 2026 6:53 am
by IceSoft
@D Ogre,
Good work so far. Good start point now!
I tried the orginal GreyGay example from BrashMonkey.
works:
- Animation seems to works
-SCML file is correct load as far Im can see
wrong:
- position of the sprites need fine tuning
ToDo:
Not all HUD function be implemented: Scale_Up/Down, etc
Here are the correct animation and position of the Gray Gay example:
https://youtu.be/oR4eCCZ6xCQ
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 27, 2026 7:38 am
by D Ogre
There is nothing wromg with the demo. The loader and rendering system is designed for the r11 Spriter file format. The GreyGuy is actually the older b5.95 format. i am working on mods to the Demo to allow correct loading of both formats.
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 27, 2026 8:43 am
by IceSoft
D Ogre wrote: Fri Feb 27, 2026 7:38 am
There is nothing wromg with the demo. The loader and rendering system is designed for the r11 Spriter file format. The GreyGuy is actually the older b5.95 format. i am working on mods to the Demo to allow correct loading of both formats.
Can you add a message about the loaded scml version?
and a hint "that scml version is currently not supported."
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 27, 2026 9:27 am
by IceSoft
D Ogre wrote: Fri Feb 27, 2026 7:38 am
There is nothing wromg with the demo. The loader and rendering system is designed for the r11 Spriter file format. The GreyGuy is actually the older b5.95 format. i am working on mods to the Demo to allow correct loading of both formats.
Can you try this scml:
https://manneko.itch.io/viking-boy
its r11 but position be wrong:
<spriter_data scml_version="1.0" generator="BrashMonkey Spriter" generator_version="r11">
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 27, 2026 7:31 pm
by D Ogre
New version of Spriter Demo posted above.

Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Fri Feb 27, 2026 8:53 pm
by IceSoft
D Ogre wrote: Fri Feb 27, 2026 7:31 pm
New version of Spriter Demo posted above.
Great work. Works now.
Thanks for sharing
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Sat Feb 28, 2026 6:09 am
by IceSoft
@D Ogre
I created a scml with sound.
Works as far as I can say but plays the whole animation.
seems <soundline> is currently not supported
Code: Select all
...
<timeline id="3" obj="1" name="bone_001" object_type="bone">
<key id="0">
<bone x="3" y="7" angle="152.987335"/>
</key>
<key id="1" time="199" spin="-1">
<bone x="3" y="7" angle="236.700579"/>
</key>
</timeline>
<soundline id="-1" name="sample-3s">
<key id="0" time="199" curve_type="instant">
<object folder="1" file="0" panning="-0.656"/>
</key>
</soundline>
</animation>
</entity>
</spriter_data>
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Sat Feb 28, 2026 4:05 pm
by D Ogre
I'm still ironing out bugs and implementations. As I do so, test away! I want to completely nail this...
New Update above. Here's and update with some bug fixes. Well, hopefully.
There are still some problems to work out, but I'll get there...
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Sat Feb 28, 2026 6:17 pm
by IceSoft
Sounds works better now.
New issue:
Pressing [SPACE] => The sound is still running
@D Ogre,
Please copy all new versions into the first entry.
Its easier to find and please remove/delete the wrong code snippets too.
Good work as far.
Re: 2D Modular Sprite Engine (Spriter Pro)
Posted: Sat Feb 28, 2026 8:44 pm
by D Ogre
I'll take a look at the sound handling code later this evening. I think I may have simply left out a SoundStatus() and PauseSound()/ResumeSound(). Lol.