img2map.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. # Python tool to convert an image to map for the Anarch game. The input image
  2. # has to be in gif format.
  3. #
  4. # by drummyfish
  5. # released under CC0 1.0.
  6. import sys
  7. from PIL import Image
  8. elementTypes = [
  9. "NONE",
  10. "BARREL",
  11. "HEALTH",
  12. "BULLETS",
  13. "ROCKETS",
  14. "PLASMA",
  15. "TREE",
  16. "FINISH",
  17. "TELEPORTER",
  18. "TERMINAL",
  19. "COLUMN",
  20. "RUIN",
  21. "LAMP",
  22. "CARD0",
  23. "CARD1",
  24. "CARD2",
  25. "LOCK0",
  26. "LOCK1",
  27. "LOCK2",
  28. "BLOCKER",
  29. "",
  30. "",
  31. "",
  32. "",
  33. "",
  34. "",
  35. "",
  36. "",
  37. "",
  38. "",
  39. "",
  40. "",
  41. "MONSTER_SPIDER",
  42. "MONSTER_DESTROYER",
  43. "MONSTER_WARRIOR",
  44. "MONSTER_PLASMABOT",
  45. "MONSTER_ENDER",
  46. "MONSTER_TURRET",
  47. "MONSTER_EXPLODER"
  48. ]
  49. propertyTypes = [
  50. "ELEVATOR",
  51. "SQUEEZER",
  52. "DOOR"
  53. ]
  54. image = Image.open(sys.argv[1])
  55. pixels = image.load()
  56. palette = []
  57. paletteInverse = [0 for i in range(256)]
  58. x = 5
  59. y = 69
  60. i = 0
  61. # load the palette/sca
  62. for i in range(256):
  63. if i % 64 == 0:
  64. x = 5
  65. y += 1
  66. palette.append(pixels[(x,y)])
  67. paletteInverse[pixels[(x,y)]] = i
  68. x += 1
  69. def getPixel(x,y):
  70. return paletteInverse[pixels[(x,y)]]
  71. def loadTileDict(x,y):
  72. result = []
  73. for i in range(64):
  74. texture = getPixel(x + i,y + 31)
  75. if texture > 7:
  76. raise(Exception("Texture index can't be higher than 7."))
  77. height = 0
  78. for j in range(31):
  79. if getPixel(x + i,y + 30 - j) == 7:
  80. break
  81. height += 1
  82. result.append((texture,height))
  83. return result
  84. def defineName(n):
  85. c = chr(ord("A") + n)
  86. return c + c
  87. floorDict = loadTileDict(5,37)
  88. ceilDict = loadTileDict(5,5)
  89. floorColor = getPixel(41,122)
  90. ceilColor = getPixel(41,118)
  91. backgroundTex = getPixel(41,126)
  92. doorTex = getPixel(41,130)
  93. playerStart = [0,0,0]
  94. textures = []
  95. elements = []
  96. defines = []
  97. levelMap = [[(0,False) for i in range(64)] for j in range(64)]
  98. # load the map
  99. for y in range(64):
  100. for x in range(64):
  101. n = getPixel(70 + x,5 + y)
  102. if n < 64:
  103. levelMap[63 - x][y] = (n,False)
  104. else:
  105. # tile with special property, create a define for it
  106. prop = n / 64 - 1
  107. tile = n % 64
  108. defNum = -1
  109. for i in range(len(defines)):
  110. if defines[i] == (tile,prop):
  111. defNum = i
  112. break
  113. if defNum == -1: # not found:
  114. defNum = len(defines)
  115. defines.append((tile,prop))
  116. levelMap[63 - x][y] = (defNum,True)
  117. # load elements
  118. playerFound = False
  119. for y in range(64):
  120. for x in range(64):
  121. n = getPixel(x + 70, y + 70)
  122. if n < len(elementTypes):
  123. elements.append((n,63 - x,y))
  124. elif n >= 240:
  125. if playerFound:
  126. raise(Exception("Multiple player starting positions specified."))
  127. playerStart = [63 - x,y,(n - 240) * 16]
  128. playerFound = True
  129. if not playerFound:
  130. raise(Exception("Player starting position not specified."))
  131. if len(elements) > 128:
  132. raise(Exception("More than 128 level elements."))
  133. for i in range(128 - len(elements)):
  134. elements.append((0,0,0))
  135. # load textures
  136. x = 41
  137. y = 114
  138. for i in range(7):
  139. textures.append(getPixel(x,y))
  140. x += 4
  141. def numAlign(n):
  142. return str(n) + "," + (" " if n < 10 else "")
  143. def mapXScale():
  144. r = " // "
  145. for i in range(64):
  146. r += str(i).ljust(2) + " "
  147. return r + "\n"
  148. def printC():
  149. result = ""
  150. result += " { // level\n"
  151. result += " { // mapArray\n"
  152. result += " #define o 0\n"
  153. for i in range(len(defines)):
  154. result += " #define " + defineName(i) + " (" + str(defines[i][0]) + " | SFG_TILE_PROPERTY_" + propertyTypes[defines[i][1]] + ")\n"
  155. result += mapXScale()
  156. for y in range(64):
  157. result += "/*" + str(y).ljust(2) + "*/ "
  158. for x in range(64):
  159. item = levelMap[x][y]
  160. if not item[1]:
  161. result += ("o " if item[0] == 0 else str(item[0]).ljust(2))
  162. else:
  163. result += defineName(item[0])
  164. result += "," if y < 63 or x < 63 else " "
  165. result += " /*" + str(y).ljust(2) + "*/ \n"
  166. result += mapXScale()
  167. for i in range(len(defines)):
  168. result += " #undef " + defineName(i) + "\n"
  169. result += " #undef o\n"
  170. result += " },\n"
  171. result += " { // tileDictionary\n "
  172. for i in range(64):
  173. result += "SFG_TD(" + str(floorDict[i][1]).rjust(2) + "," + str(ceilDict[i][1]).rjust(2) + "," + str(floorDict[i][0]) + "," + str(ceilDict[i][0]) + ")"
  174. result += "," if i != 63 else " "
  175. if (i + 1) % 4 == 0:
  176. result += " // " + str(i - 3) + " \n "
  177. result += "}, // tileDictionary\n"
  178. s = ""
  179. first = True
  180. for t in textures:
  181. if first:
  182. first = False
  183. else:
  184. s += ","
  185. s += str(t).ljust(2)
  186. result += " {" + s + "}, // textureIndices\n"
  187. result += " " + numAlign(doorTex) + " // doorTextureIndex\n"
  188. result += " " + numAlign(floorColor) + " // floorColor\n"
  189. result += " " + numAlign(ceilColor) + " // ceilingColor\n"
  190. result += " {" + str(playerStart[0]).ljust(2) + ", " + str(playerStart[1]).ljust(2) + ", " + str(playerStart[2]).ljust(3) + "}, // player start: x, y, direction\n"
  191. result += " " + numAlign(backgroundTex) + " // backgroundImage\n"
  192. result += " { // elements\n"
  193. even = True
  194. i = 0
  195. for e in elements:
  196. if even:
  197. result += " "
  198. result += "{SFG_LEVEL_ELEMENT_" + elementTypes[e[0]] + ", {" + str(e[1]) + "," + str(e[2]) + "}}"
  199. if i < 127:
  200. result += ","
  201. if not even:
  202. result += "\n"
  203. even = not even
  204. i += 1
  205. result += " }, // elements\n"
  206. result += " } // level\n"
  207. print(result)
  208. printC()