GSoC Sprite Sheets Shuger

From The Battle for Wesnoth Wiki
Revision as of 18:15, 8 April 2010 by Shuger (talk | contribs) (separate files)


This page is related to Summer of Code 2010
See the list of Summer of Code 2010 Ideas



This is a Summer of Code 2010 student page



Description

I want add sprite sheet support to Wesnoth. The general idea is to assemble multiple small images into few bigger.

IRC

Shuger

Questionnaire

http://wiki.wesnoth.org/User:Shuger

Implementation

Sprite Formats

In my idea of implementation there are three possible sprite formats:

  • separate files
  • normal sprite sheet
  • optimized sprite sheet

separate files

Current way of managing sprites, each image in a separate file.

wml remains the same.

normal sprite sheet

Multiple sprites on one big image. This is a way for artists to work if they prefer sprite sheets over separate images. The artist can place sprites in a sheet in any way he/she wants.

example wml:

[frame]
    x_position = 32
    y_position = 32
    x_size = 32
    y_size = 32
    image="units/elves-wood/archer+female-spritesheet.png"
[/frame]

x_position and y_position - position of the sprite in the sheet, in pixels from top left corner(because of the way SDL coordinate system works).
x_size and y_size - optimized sprite size.

optimzed sprite sheet

This format is not for manual editing. It is created from separete files or normal sprite sheet automatically. To generate it special packing algorithms will be used to optimize it's size. This will be the format normally used. Generation should occur at build time uing a custom tool added to build process. It will be possible too run tool manually if someon desires.

Algorithm: 1. Parse wml file created by artist and collect all information about needed sprites for certain unit. 2. Load all needed images, parts normal sprite sheet specified by wml file. 3. Optimze all sprites by cutting unneeded part of sprites. 4. Use a rectangle packing algorithm to pack them into as small space as possible. 5. Bake optimized sprites onto new optimized sprite sheet using information from step 4. Write it to a new file. 6. Update wml file with changing all references to optimized version and adding each sprite offset and size information.

example wml frame definition:

[frame]
    x_position = 32
    y_position = 32
    x_size = 24
    y_size = 24
    x_offset = 6
    y_offset = 6
    image="units/elves-wood/archer+female-spritesheet.png"
[/frame]

notes:

x_position and y_position - position of the sprite in the sheet, in pixels from top left corner(because of the way SDL coordinate system works).

x_size and y_size - optimized sprite size.

x_offset and y_offset - If image was optimized by cutting transparent border it needs to be offset during blitting.


Comment on step 3: Many sprites have image (say 72x72 pixels) where only a part is actually a sprite and the rest is wide transparent border. This doesn't considerably impact image size on disk, because of png compression but is taking significant amount of uneeded memory when loaded into SDL surface (which doesn't use compression). The point of this step is to crop the image by finding a minimal rectangle to fit entire sprite in and then store the size and offset of this rectangle in comparison to original image in order to blit image properly.

Memory

First gain for the memory will come from cropping sprites as described earlier. Second will come from using a cache. There is no need to store every spritesheet in uncompressed format as it will requie a lot of memory even if not needed. On the other hand disk operations are very slow so reading spriteshhets during game should be avoided. The solution to this is to hold currently unused sprites in compressed format. SDL_image allows it. Instead of directly loading into a surface images can be loaded without parsing into memory. It will take only as much memory as file on hard drive. Also compressing one big image gives better results then many small ones.

First step is to load image from hard drive using SDL_RWFromFile function. Then once cached sprite sheet will be needed it will unpacked using IMG_Load_RW (this is from SDL_image library). Once not needed anymore, uncompressed surface will be deleted from memory.

This may require some changes to Wesnoth cache code. Also while it may seem that uncompressing raw data is performance loss, it's actually not that slow compared to reading from disk which takes most of the time neded to load image completely.

Performance

Croping sprites will increase blitting speed beacause there will be less data for SL to process in blitting functions.

Workfolw

1. Artist makes sprite bay making separate images or normal sprite sheet.

2. He can test those normally. The game will support both formats.

3. Special tool will be run at build time to process al images and sprite sheets