Browse Source

abstracting drummyfish code into a class

pixelbath 3 years ago
commit
a4884260e1
1 changed files with 280 additions and 0 deletions
  1. 280 0
      anarchmap.py

+ 280 - 0
anarchmap.py

@@ -0,0 +1,280 @@
+# Converts an Anarch map image to usable data.
+#
+# by drummyfish, edits by pixelbath
+# released under CC0 1.0.
+
+from PIL import Image
+import math
+
+class AnarchMap:
+    def __init__(self, image_path):
+        self.elementTypes = [
+            "NONE",
+            "BARREL",
+            "HEALTH",
+            "BULLETS",
+            "ROCKETS",
+            "PLASMA",
+            "TREE",
+            "FINISH",
+            "TELEPORTER",
+            "TERMINAL",
+            "COLUMN",
+            "RUIN",
+            "LAMP",
+            "CARD0",
+            "CARD1",
+            "CARD2",
+            "LOCK0",
+            "LOCK1",
+            "LOCK2",
+            "BLOCKER",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "MONSTER_SPIDER",
+            "MONSTER_DESTROYER",
+            "MONSTER_WARRIOR",
+            "MONSTER_PLASMABOT",
+            "MONSTER_ENDER",
+            "MONSTER_TURRET",
+            "MONSTER_EXPLODER"
+        ]
+
+        self.propertyTypes = [
+            "ELEVATOR",
+            "SQUEEZER",
+            "DOOR"
+        ]
+
+        with Image.open(image_path) as image:
+            self.pixel_data = image.load()
+
+        self.palette = []
+        self.paletteInverse = [0 for i in range(256)]
+
+        x = 5
+        y = 69
+        i = 0
+
+        # load the palette/sca
+        for i in range(256):
+            if i % 64 == 0:
+                x = 5
+                y += 1
+
+            self.palette.append(self.pixel_data[(x,y)])
+            self.paletteInverse[self.pixel_data[(x,y)]] = i
+            x += 1
+
+        self.floorDict = self.load_tile_dict(5,37)
+        self.ceilDict = self.load_tile_dict(5,5)
+        self.floorColor = self.get_pixel(41,122)
+        self.ceilColor = self.get_pixel(41,118)
+        self.backgroundTex = self.get_pixel(41,126)
+        self.doorTex = self.get_pixel(41,130)
+        self.playerStart = [0,0,0]
+        self.textures = []
+        self.elements = []
+        self.defines = []
+
+        self.levelMap = [[(0,False) for i in range(64)] for j in range(64)]
+
+        # load the map
+        for y in range(64):
+            for x in range(64):
+                n = self.get_pixel(70 + x, 5 + y)
+
+                if n < 64:
+                    self.levelMap[63 - x][y] = (n,False)
+                else:
+                    # tile with special property, create a define for it
+
+                    prop = math.floor(n / 64) - 1
+                    tile = n % 64
+
+                    defNum = -1
+
+                    for i in range(len(self.defines)):
+                        if self.defines[i] == (tile, prop):
+                            defNum = i
+                            break
+                    
+                    if defNum == -1: # not found:
+                        defNum = len(self.defines)
+                        self.defines.append((tile,prop))
+
+                    self.levelMap[63 - x][y] = (defNum,True)
+
+        # load elements
+        playerFound = False
+
+        for y in range(64):
+            for x in range(64):
+                n = self.get_pixel(x + 70, y + 70)
+
+                if n < len(self.elementTypes):
+                    self.elements.append((n,63 - x,y)) 
+                elif n >= 240:
+                    if playerFound:
+                        raise(Exception("Multiple player starting positions specified."))
+
+                    playerStart = [63 - x,y,(n - 240) * 16]
+                    playerFound = True
+
+        if not playerFound:
+            raise(Exception("Player starting position not specified."))
+
+        if len(self.elements) > 128:
+            raise(Exception("More than 128 level elements."))
+
+        for i in range(128 - len(self.elements)):
+            self.elements.append((0,0,0))
+
+        # load textures
+        x = 41
+        y = 114
+
+        for i in range(7):
+            self.textures.append(self.get_pixel(x, y))
+            x += 4
+
+
+    def get_pixel(self, x, y):
+        return self.paletteInverse[self.pixel_data[(x, y)]]
+
+    def load_tile_dict(self, x, y):
+        result = []
+
+        for i in range(64):
+            texture = self.get_pixel(x + i, y + 31)
+
+            if texture > 7:
+                raise(Exception("Texture index can't be higher than 7."))
+
+            height = 0
+
+            for j in range(31):
+                if self.get_pixel(x + i, y + 30 - j) == 7:
+                    break
+
+                height += 1
+
+            result.append((texture,height))
+
+        return result
+
+    def defineName(self, n):
+        c = chr(ord("A") + n)
+        return c + c
+
+    def numAlign(self, n):
+        return str(n) + "," + (" " if n < 10 else "")
+
+    def mapXScale(self):
+        r = "    // "
+
+        for i in range(64):
+            r += str(i).ljust(2) + " "
+
+        return r + "\n"
+
+    def printC(self):
+        result = ""
+        result += "  {          // level\n"
+        result += "    {        // mapArray\n"
+        result += "    #define o 0\n"
+
+        for i in range(len(self.defines)):
+            print("%s : %s" % (self.defines[i][0], self.defines[i][1]))
+            result += "    #define " + self.defineName(i) + " (" + str(self.defines[i][0]) + " | SFG_TILE_PROPERTY_" + self.propertyTypes[self.defines[i][1]] + ")\n"
+
+        result += self.mapXScale()
+
+        for y in range(64):
+            result += "/*" + str(y).ljust(2) + "*/ "
+
+            for x in range(64):
+                item = self.levelMap[x][y]
+
+                if not item[1]:
+                    result += ("o " if item[0] == 0 else str(item[0]).ljust(2))
+                else:
+                    result += self.defineName(item[0])
+
+                result += "," if y < 63 or x < 63 else " "
+
+            result += " /*" + str(y).ljust(2) + "*/ \n"
+
+        result += self.mapXScale()
+
+        for i in range(len(self.defines)):
+            result += "    #undef " + self.defineName(i) + "\n"
+
+        result += "    #undef o\n"
+        result += "    },\n"
+        result += "    {        // tileDictionary\n      "
+
+        for i in range(64):
+            result += "SFG_TD(" + str(self.floorDict[i][1]).rjust(2) + "," + str(self.ceilDict[i][1]).rjust(2) + "," + str(self.floorDict[i][0]) + "," + str(self.ceilDict[i][0]) + ")"
+
+            result += "," if i != 63 else " "
+
+            if (i + 1) % 4 == 0:
+                result += " // " + str(i - 3) + " \n      "
+
+        result += "},                    // tileDictionary\n"
+
+        s = ""
+        first = True
+
+        for t in self.textures:
+            if first:
+                first = False
+            else:
+                s += ","
+
+            s += str(t).ljust(2)
+
+        result += "    {" + s + "}, // textureIndices\n"
+        result += "    " + self.numAlign(self.doorTex) + "                     // doorTextureIndex\n"
+        result += "    " + self.numAlign(self.floorColor) + "                     // floorColor\n"
+        result += "    " + self.numAlign(self.ceilColor) + "                     // ceilingColor\n"
+        result += "    {" + str(self.playerStart[0]).ljust(2) + ", " + str(self.playerStart[1]).ljust(2) + ", " + str(self.playerStart[2]).ljust(3) + "},          // player start: x, y, direction\n"
+        result += "    " + self.numAlign(self.backgroundTex) + "                     // backgroundImage\n"
+        result += "    {                       // elements\n"
+
+        even = True
+
+        i = 0
+
+        for e in self.elements:
+            if even:
+                result += "      "
+
+            result += "{SFG_LEVEL_ELEMENT_" + self.elementTypes[e[0]] + ", {" + str(e[1]) + "," + str(e[2]) + "}}"
+
+            if i < 127:
+                result += ","
+
+            if not even:
+                result += "\n"
+
+            even = not even
+
+            i += 1
+
+        result += "    }, // elements\n"
+        result += "  } // level\n"
+
+        print(result)
+