SpriteSheetApplicationSAB
This page is related to Summer of Code 2014 |
See the list of Summer of Code 2014 Ideas |
This is a Summer of Code 2014 student page |
Contents
Description
Aishiko GSOC 2014 SpriteSheets
My proposal is to take the current functions for drawing sprites and move it to allow for spritesheets, while hiding any of the changes from campaign designers. It should allow for the seemless intergration of spritesheets and allow for a period of conversion from multiple files to sheets.
IRC
Aishiko, Aishiko_laptop
Prelim Implementation Ideas
Goals
Eliminate as many small single images as possible from the program. Enable Sprite Sheets to be used in;
- Gameplay
- Units
- Terrain
- etc
- Menus, mouse pointers, etc. Optional Goal I doubt at this point that I'll
make it this far.
- Reuse as much as the existing syntax as possible
- Create Unit Tests to make sure that the areas modified are as good as I can
make them.
- Make it easy for the artists to add sprites to a sprite sheet:
Problems
- Not all units and terrain are 72x72
- Adding a boarder around each image to make it easier for the artists to see what sort of space they have to work with will make taking the current images and converting them a bit harder as well as creating a script to convert them (which remains a soft goal, ie if I have to do it AFTER the summer, I'll do that.) Stupid perfectionist leanings, at least for what I think of to get the project ready!
- Syntax making sure that its easy to use and understand for the average user
First Steps
I will create a test program that will allow me to make sure that the sprites are being parsed properly. I'll need a spritesheet for this, preferably a big one. Through this whole process if it breaks it should only break on the sprite sheets until then it shouldn't break anything exisiting.
Cache
In cache the spritesheets need to be parsed, either all at once or only those grids that are currently needed and the found corners saved as above. When an image is needed from a spritesheet it will gotten out of the sheet and then passed into the cache that will using and holding that image such as the scaled_to_zoom_ or tod_colored_images_. The sheets will remained cached until the game is exited completely or the cache is full the oldest referenced image will be dropped.
Plan A
How This Will Work
The way this will work is each sheet will be a grid of one colour that is not used in any of the sprites (say a shade of pink) this RGBA colour is a Primary Key, it will lay out a grid of equal sized areas within our spritesheet. Then each of those grid squares (or rectangles) each frame/image has a second border of colour, say a different shade of pink. Each unit's spritesheet will then be read at loading into the cache, each grid square will be searched for an image if found it will be loaded into an object that will contain the following information:
- SpriteSheetName
- Row
- Column
- Upper Y
- Upper X
- Lower Y
- Lower X
So each Spritesheet will generate a SpriteAddress Object and will have objects in it that give the information about each frame (given above we'll call it a SpriteFrameAddress Object). The Spritesheet and its SpriteAddress and its SpriteFrameAddress Objects will be stored in the same cache as the spritesheet itself (so we won't have to refind each frame.
WML
The current syntax is:
image="units/elves-wood/sorceress-melee-attack-[1~10,1,2].png:[80*5,100*2,80*5]"
I envision it to be more like one of these to work as with a spritesheet:
image="units/Elvish_Sorceress[2.1~2.10,2.1~2.2].png:[80*5,100*2,80*5]"
or
image="units/elves-wood/Elvish_Sorceress[2.1~2.10,2.1~2.2].png:[80*5,100*2,80*5]"
or
image="units/elves-wood/Elvish_Sorceress<2.1~2.10,2.1~2.2>.png:[80*5,100*2,80*5]"
Another option is to do:
image="units/elves-wood/Elvish_Sorceress<25,35,77,107>.png:[80]"
In this case we would call it with the x,y of the 2 corners need to pull it out. This might be a good starting point for getting them to just work however I would still wish to get it more streamlined and less prone to errors.
In the Elvish Sorceress example the first [] set would translate out to: row 4, columns 1-4, and the second set would stay the timing with times of 5ms, 75ms,
100ms, and then 130ms for the images in order. This should take the current
markup language and merely extand it to allow for rows and columns be the
callers for an image. The <sheetName> will either relate to a memory address of
the sheet or to an image under units/ like units/Elvish_Sorceress.png
4.5 would be 4th row 5th column. I would take the current syntax and modify it slightly to work with rows and columns. The block of [4.1~4.4] might be <4.1~4.4> depending on whether or not its more readable.
When the WML goes for the individual images that create that animation it'll look at the generated SpriteAddressObject for the needed SpriteFrameAddresses This could be extended to so there is a SpriteAnimation object that will read the configs for the unit and have say the Attack Animation instead of calling each image seperately (perhaps as a later extention?)
The ojbects might not be needed and just a config file generated that holds all the Row, Column, and X,Y data for each image might be all that is needed and will work fine. The idea of holding a config of where each image is located and saving that would remove the overhead of searching everytime a frame is called. These frames would then be passed to the normal cache used and stored there, until they expire.
Plan B
WML
Each Spritesheet will have a Spritesheet set of tags in the unit config file, it will look something like:
[Spritesheet] File=file_path/name.png [Image] ImageID=1 ImageName="Attack_1" Upper_X=x Upper_Y=y Lower_X=x Lower_Y=y [/Image] -- More Images here [/Spritesheet]
OR
[Spritesheet] File=file_path/name.png [Image] ImageID=1 ImageName="Attack_1" Coordinates=[x,y,x,y] --upper followed by lower x,y [/Image] -- More Images here [/Spritesheet]
Each animation sequence called by doing a call like:
image="units/Elvish_Sorceress[1~10,1,2].png:[80*5,100*2,80*5]"
Almost like normal to say Elvish_Sorceress.png, images 1-10 and then 1 and finally 2 for the attack sequence in this case.
Spritesheet Details
Each Spritesheet will have each unit outlined in a box (Colour and size matters not in this version unless we want to implement a side program that will parse out the correct information for the artists.) everytime there is an added frame the artist just needs to add the correct information as above to add it in, they will not have to be in any sort of order IE Image 1 can be beside Image 50. There is the added overhead on the artist to make sure they add the right Xs and Ys to make it work. However this way has less processing overhead to make it work and see more positive gains from moving to spritesheets.
On loading an image if the [SpriteSheet] tags are found then it will automatically check for each called image within the spritesheet's definition pulling out the requried frames as needed. This method will require no more parsing overhead then the usual requirements of parsing the data in the config (IE no need to "scan" the image file looking for grids or borders or anything like that. The spritesheet can be packed as tightly as desired by the artist, and even notes left in the file, such as a block of text that says "Attack animation here". Each unit can have more then 1 spritesheet however, they can only have 1 image with an ImageID, this is unique to the unit not the spritesheet file.
Testing
Phase One
I will create a test program that will allow me to make sure that the sprites are being parsed properly. This program will be intergrated and become the spritesheet core of the program. Having this out by itself will allow me to see what sort of difference there is when parsing just the needed gridboxes and the whole sheet. This will allow me to come up with some decent error messages for malformed sprite boxes.
Phase Two
In addition to creating unit tests, I'll try out various hardware to see what sort of performance changes I can detect during the course of getting things working. I'll test on a Quad-core with 8 or more GB RAM, a Dual-core with 4GB RAM, and a 32bit single core with 1-4 GB RAM (I don't have any Macs so I can not test on that and I only have Windows in a VM, so most testing will be done under Linux I'll depend on the various developers that use windows to let me know how it is affecting the running under Windows)
Deliverables
Status | Requirement Level | Number ID | Goal Defined |
Required | 1A | Properly working Spritesheet cache to speed up loading and elimnate glithy and laging animations do to disk access times. | |
Required | 1B | dynamic so that low mem devices are not adversely effected. | |
Plan A Only! | 2 | Properly parse spritesheets and quickly be able to pass that information on for each frame. | |
Required | 3A | Spritesheets that are flexible and easy for artists and WML users to implement. | |
Required | 3B | Spritesheets that do not have a fixed size for every frame they hold. | |
Plan A Only! | 3C | Nor a Fixed grid size that holds each frame in its border. | |
Plan A Only! Optional | 3D | Not require to have the gridlines or the borders be a particular width (optional, could be axed for performance reasons). | |
Plan B Only! Optional | 3D | Not require the borders be a particular width. | |
Required | 4 | WML syntax for Spritesheets that is not long, complex, hard to understand, or prone to errors. | |
Required | 5 | No negative or negible impact on loading times |
Packages Required
Package Name | Reason | Status |
SDL | Needed for getting the colour information | Plan A required otherwise Not needed |
Boost | Might be able to provide a performance boost (no pun intended) | Optional |
13 Week Timeline
Status |
Start/End_Dates |
Goals |
Current | March 20 - April 20: |
|
Next | April 21 - May 18: |
|
May 19 - June 1: |
| |
June 1 - 15: |
| |
June 16 - 29: |
| |
June 23 - 27: |
| |
June 30 - July 13: |
| |
July 14 - 27: |
| |
July 28 - Aug 10: |
| |
Aug 3: |
| |
Aug 11 - 17: |
| |
Aug 22: |
|
The Weeks in the Program
Week 1: May 19 to May 25 Week 2: May 26 to June 1 Week 3: June 2 to June 8 Week 4: June 9 to June 15 Week 5: June 16 to June 22 Week 6: June 23 to June 29 Week 7: June 30 to July 6 Week 8: July 6 to July 13 Week 9: July 14 to July 20 Week 10: July 21 to July 27 Week 11: July 28 to August 3 Week 12: August 4 to August 10 Week 13: August 11 to August 17
Optional tasks if everything goes smoother and easier then planed in no particular order:
- Convert all the sprites, update all the .cfg for the base units
- Create script to allow Addon Artists convert their sprites
Artists Weigh In
OK, not just for artists, go to http://forums.wesnoth.org/viewtopic.php?f=9&t=40191 and weigh in on the details that effect you as an user! And only those details, and thank you for helping me make Wesnoth a little bit better.