I’ve been trying to procedurally generate .aseprite binary files for a project I’m working on, but I’m having some trouble serializing tilesets and Tilemaps
I’ve been able to create a struct that represents the Aseprite file, and I’ve been able to successfully serialize and open a generated aseprite file with a single Frame, two layers in the frame, and two cells in the frame (each pointed at one of the two layers) each filled with a different color
The api usage for that example looks something like this
file := &aseprite.AseFile{
Width: 32,
Height: 32,
ColorDepth: 32,
Frames: []aseprite.Frame{
{
Duration: 100,
Layers: []aseprite.Layer{
{
Flags: 3,
Type: 0,
ChildLevel: 0,
DefaultWidth: 32,
DefaultHeight: 32,
BlendMode: 0,
Opacity: 255,
Name: "Layer 0",
},
{
Flags: 3,
Type: 0,
ChildLevel: 0,
DefaultWidth: 32,
DefaultHeight: 32,
BlendMode: 0,
Opacity: 255,
Name: "Layer 1",
},
},
Cels: []aseprite.Cel{
{
LayerIndex: 0, XOffset: 0, YOffset: 0,
Opacity: 255, CelType: 0,
Width: 32, Height: 32,
PixelData: makePixels(32, 32, 0, 255, 0, 255),
},
{
LayerIndex: 1, XOffset: 0, YOffset: 0,
Opacity: 255, CelType: 0,
Width: 32, Height: 32,
PixelData: makePixels(32, 32, 255, 0, 0, 255),
},
},
},
},
}
I then serialize the Aseprite struct by starting with the file headers, and then serializing each of the frames (which serialize their cells and chunks)
type AseFile struct {
Width, Height uint16
ColorDepth uint16
Tilesets []Tileset
Frames []Frame
}
// Serialize writes the full .aseprite file to w.
func (a *AseFile) Serialize(w io.Writer) error {
buf := new(bytes.Buffer)
// File header (128 bytes)
binary.Write(buf, binary.LittleEndian, uint32(0)) // placeholder for file size
binary.Write(buf, binary.LittleEndian, uint16(magicFile)) // magic
binary.Write(buf, binary.LittleEndian, uint16(len(a.Frames))) // frame count
binary.Write(buf, binary.LittleEndian, a.Width)
binary.Write(buf, binary.LittleEndian, a.Height)
binary.Write(buf, binary.LittleEndian, a.ColorDepth)
binary.Write(buf, binary.LittleEndian, uint32(1)) // flags (enable tilemap layers)
binary.Write(buf, binary.LittleEndian, uint16(100)) // speed
binary.Write(buf, binary.LittleEndian, uint32(0)) // reserved
binary.Write(buf, binary.LittleEndian, uint32(0)) // reserved
buf.Write([]byte{0, 0, 0, 0}) // palette + pad
buf.Write(make([]byte, 128-buf.Len())) // pad to 128 bytes
// Frames
for _, frame := range a.Frames {
fb, err := frame.serialize()
if err != nil {
return err
}
buf.Write(fb)
}
// Patch file size
b := buf.Bytes()
binary.LittleEndian.PutUint32(b[0:4], uint32(len(b)))
// Write out
_, err := w.Write(b)
return err
}
And here’s the frame struct which handles serialization of the Frames Layers and Cells
// Frame holds one frame’s duration and its chunks.
type Frame struct {
Duration uint16
Layers []Layer
Cels []Cel
Tilesets []Tileset
}
Everything has been working well, but I’ve spent all day struggling to make any progress on generating tilemaps
The motivation for this whole project is that I’m building a procedural tilemap generator, and I’d like to be able to export to native aseprite files with tilemap feature support
I guess what I’m actually asking for help with is an overview of what’s required to serialize a minimal aseprite file with the following:
- A valid Tileset Chunk
- A Layer Chunk with LayerType equal to Tilemap
- A Cel Chunk with CelType equal to Compressed Tilemap
For the Tilesets, do I just serialize each of them into the First Frame of the file?
How do I link a Cel Chunk to the appropriate Layer Chunk?
I’d appreciate any help with this, and I’ll update my post if make any progress or come up with any clarifying examples
Thanks,