TileSet.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // $Id$
  2. using System;
  3. using System.IO;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using Lisp;
  7. public class TileGroup {
  8. public string Name;
  9. public ArrayList Tiles = new ArrayList();
  10. public void Write(LispWriter writer) {
  11. writer.StartList("tilegroup");
  12. writer.Write("name", Name);
  13. writer.Write("tiles", Tiles);
  14. writer.EndList("tilegroup");
  15. }
  16. public void Parse(Lisp.Parser parser) {
  17. int d = parser.Depth;
  18. while(parser.Parse() && parser.Depth >= d) {
  19. if(parser.Depth == d+1) {
  20. if(parser.Type != Parser.LispType.SYMBOL)
  21. throw new Exception("expected SYMBOL at supertux-tiles level, but got \"" + parser.StringValue + "\"");
  22. string symbol = parser.SymbolValue;
  23. parser.Parse();
  24. switch(symbol) {
  25. case "name":
  26. Name = parser.StringValue;
  27. break;
  28. case "tiles":
  29. do {
  30. Tiles.Add(parser.IntegerValue);
  31. } while(parser.Parse()
  32. && parser.Type == Parser.LispType.INTEGER);
  33. break;
  34. default:
  35. Console.WriteLine("Unknown section " + symbol);
  36. break;
  37. }
  38. }
  39. }
  40. }
  41. }
  42. public class TileSet {
  43. public const int TILE_WIDTH = 32;
  44. public const int TILE_HEIGHT = 32;
  45. private bool isNew = false;
  46. /// <summary>Whether version of tileset file is too new</summary>
  47. public bool IsNew {
  48. get {
  49. return isNew;
  50. }
  51. }
  52. public ArrayList Tiles = new ArrayList();
  53. public ArrayList TileGroups = new ArrayList();
  54. public void Write(string filename) {
  55. FileStream fs = new FileStream(filename, FileMode.Create);
  56. TextWriter tw = new StreamWriter(fs);
  57. LispWriter writer = new LispWriter(tw);
  58. writer.WriteComment("Generated by tiler");
  59. writer.StartList("supertux-tiles");
  60. foreach(TileGroup tilegroup in TileGroups) {
  61. tilegroup.Write(writer);
  62. }
  63. foreach(Tile tile in Tiles) {
  64. if(tile == null)
  65. continue;
  66. if(tile.ID >= 0)
  67. tile.Write(writer);
  68. }
  69. writer.EndList("supertux-tiles");
  70. tw.Close();
  71. fs.Close();
  72. }
  73. public void Parse(string filename) {
  74. FileStream fs = new FileStream(filename, FileMode.Open);
  75. StreamReader stream = new StreamReader(fs);
  76. Lisp.Parser parser = new Lisp.Parser(stream);
  77. parser.Parse();
  78. if(parser.Type != Parser.LispType.START_LIST)
  79. throw new Exception("Expected START_LIST");
  80. parser.Parse();
  81. if(parser.Type != Parser.LispType.SYMBOL)
  82. throw new Exception("Expected symbol");
  83. if(parser.SymbolValue != "supertux-tiles")
  84. throw new Exception("not a supertux tile files but " +
  85. parser.SymbolValue);
  86. ParseTiles(parser);
  87. stream.Close();
  88. fs.Close();
  89. }
  90. public void ParseTiles(Lisp.Parser parser) {
  91. isNew = false;
  92. int d = parser.Depth;
  93. while(parser.Parse() && parser.Depth >= d) {
  94. if(parser.Depth == d && parser.Type != Parser.LispType.START_LIST) {
  95. Console.WriteLine("non-cons type in list...");
  96. continue;
  97. }
  98. if(parser.Depth == d+1) {
  99. if(parser.Type != Parser.LispType.SYMBOL) {
  100. throw new Exception("Expected symbol in list element");
  101. }
  102. switch(parser.SymbolValue) {
  103. case "properties":
  104. SkipList(parser);
  105. break;
  106. case "tilegroup":
  107. TileGroup tilegroup = new TileGroup();
  108. tilegroup.Parse(parser);
  109. TileGroups.Add(tilegroup);
  110. break;
  111. case "tile":
  112. Tile tile = new Tile();
  113. tile.Parse(parser);
  114. while(tile.ID >= Tiles.Count)
  115. Tiles.Add(null);
  116. Tiles[tile.ID] = tile;
  117. break;
  118. case "tiles":
  119. ParseMoreTiles(parser);
  120. isNew = true;
  121. break;
  122. default:
  123. throw new Exception("Unexpected listentry: " +
  124. parser.SymbolValue);
  125. }
  126. }
  127. }
  128. }
  129. public void ParseMoreTiles(Lisp.Parser parser)
  130. {
  131. int blockWidth = 0;
  132. int blockHeight = 0;
  133. List<int> ids = new List<int>();
  134. List<int> attributes = new List<int>();
  135. List<int> datas = new List<int>();
  136. List<string> imageNames = new List<string>();
  137. float animFps = 0;
  138. int d = parser.Depth;
  139. while(parser.Parse() && parser.Depth >= d) {
  140. if(parser.Depth == d+1) {
  141. if(parser.Type != Parser.LispType.SYMBOL)
  142. throw new Exception("expected SYMBOL at supertux-tiles---tiles level, but got \"" + parser.StringValue + "\"");
  143. string symbol = parser.SymbolValue;
  144. parser.Parse();
  145. switch(symbol) {
  146. case "width":
  147. blockWidth = parser.IntegerValue;
  148. break;
  149. case "height":
  150. blockHeight = parser.IntegerValue;
  151. break;
  152. case "ids":
  153. Parser.ParseIntList(parser, ids);
  154. break;
  155. case "attributes":
  156. Parser.ParseIntList(parser, attributes);
  157. break;
  158. case "datas":
  159. Parser.ParseIntList(parser, datas);
  160. break;
  161. case "anim-fps":
  162. animFps = parser.FloatValue;
  163. break;
  164. case "image":
  165. int subDepth = parser.Depth;
  166. while(parser.Depth >= subDepth) {
  167. imageNames.Add(parser.StringValue);
  168. parser.Parse();
  169. }
  170. break;
  171. default:
  172. Console.WriteLine("Unknown tiles element " + symbol);
  173. break;
  174. }
  175. }
  176. }
  177. if(ids.Count != blockWidth * blockHeight)
  178. throw new ApplicationException("Must have width*height ids in tiles block, but found " + ids.Count.ToString());
  179. if((attributes.Count != blockWidth * blockHeight) && attributes.Count > 0) //missing atributes == all-are-0-attributes
  180. throw new ApplicationException("Must have width*height attributes in tiles block");
  181. if((datas.Count != blockWidth * blockHeight) && datas.Count > 0) //missing DATAs == all-are-0-DATAs
  182. throw new ApplicationException("Must have width*height DATAs in tiles block");
  183. int id = 0;
  184. for(int y = 0; y < blockHeight; ++y) {
  185. for(int x = 0; x < blockWidth; ++x) {
  186. if (ids[id] != 0) {
  187. Tile tile = new Tile();
  188. tile.Images = new ArrayList();
  189. foreach (string str in imageNames)
  190. {
  191. ImageRegion region = new ImageRegion();
  192. region.ImageFile = str;
  193. region.Region.X = x * TILE_WIDTH;
  194. region.Region.Y = y * TILE_HEIGHT;
  195. region.Region.Width = TILE_WIDTH;
  196. region.Region.Height = TILE_HEIGHT;
  197. tile.Images.Add(region);
  198. }
  199. tile.ID = ids[id];
  200. tile.Attributes = (attributes.Count > 0)?attributes[id]:0; //missing atributes == all-are-0-attributes
  201. tile.Data = (datas.Count > 0)?datas[id]:0; //missing DATAs == all-are-0-DATAs
  202. tile.AnimFps = animFps;
  203. while(Tiles.Count <= tile.ID)
  204. Tiles.Add(null);
  205. Tiles[tile.ID] = tile;
  206. }
  207. id++;
  208. }
  209. }
  210. }
  211. private void SkipList(Lisp.Parser parser)
  212. {
  213. int d = parser.Depth;
  214. while(parser.Parse() && parser.Depth >= d)
  215. ;
  216. }
  217. }