Skip to content

Instantly share code, notes, and snippets.

@selenologist
Last active January 25, 2016 02:32
Show Gist options
  • Save selenologist/e84cfb5231e673de9982 to your computer and use it in GitHub Desktop.
Save selenologist/e84cfb5231e673de9982 to your computer and use it in GitHub Desktop.
# Draws Pokemon maps, from game data (using files from pret/pokered)
import os
import stat
import struct
from PIL import Image, ImageDraw
tilePixels = 8
blockTiles = 4
blockSize = blockTiles * blockTiles
blockPixels = blockTiles * tilePixels
def openBinary(filename):
return [struct.unpack('B', x)[0] for x in open(filename, 'rb').read()]
def openTileset(name):
# this could be better
tilefile = None
try:
tilefile = open("gfx/tilesets/%s.png" % name, 'r')
except IOError:
try:
tilefile = open("gfx/tilesets/%s.t1.png" % name, 'r')
except IOError:
try:
tilefile = open("gfx/tilesets/%s.t2.png" % name, 'r')
except IOError:
print("No such tileset '%s'!" % name)
raise IOError
tiles = Image.open(tilefile)
tiles = [tiles.crop((x * tilePixels, y * tilePixels,
(x+1) * tilePixels, (y+1) * tilePixels))
for y in range(0,6)
for x in range(0,16)]
blockSet = openBinary("gfx/blocksets/%s.bst" % name)
walkable = openBinary("gfx/tilesets/%s.tilecoll" % name)
return (tiles, blockSet, walkable)
overworld = openTileset("overworld")
def dumpUnique16x16s(tileSet, directory):
if not os.path.isdir(directory):
try:
os.mkdir(directory)
except _, e:
print("Error creating output directory:")
raise e
tiles, blockSet, _ = tileSet
unique = [] # use a list instead of set to preserve ordering somewhat
atomicTiles = 2
patternsInBlock = 4
tilesInPattern = 4
patternPixels = 16
for block in range(0, 128): # 128 total blocks
blockBase = blockSize * block
def getPattern(pattern):
top = blockBase + \
pattern % atomicTiles * atomicTiles + \
pattern / atomicTiles * blockTiles * 2
bottom = top + blockTiles
top = blockSet[top : top + atomicTiles]
bottom = blockSet[bottom : bottom + atomicTiles]
return tuple(top + bottom) # tuples are hashable
for n in range(0, patternsInBlock):
pattern = getPattern(n)
if pattern not in unique:
unique.append(pattern)
for index, pattern in enumerate(unique):
output = Image.new("RGBA", (patternPixels, patternPixels), 0xFF00FF)
map(output.paste,
[tiles[tile] for tile in pattern],
zip([x % atomicTiles * tilePixels for x in range(0, tilesInPattern)],
[y / atomicTiles * tilePixels for y in range(0, tilesInPattern)]))
output.save("%s/%i.png" % (directory,index))
def renderBlock(target, block, tileSet, position):
tiles, blockSet, walkable = tileSet
blockBase = blockSize * block
for y in range(0, blockTiles):
for x in range(0, blockTiles):
blockIndex = y * blockTiles + x
tile = blockSet[blockBase + blockIndex]
destination = (position[0] + x * tilePixels,
position[1] + y * tilePixels)
target.paste(tiles[tile],
(destination[0] , destination[1],
destination[0] + tilePixels, destination[1] + tilePixels))
tint = None
if tile in walkable:
tint = (0 , 0 , 255, 64) # 25% blue
else:
tint = (255, 0 , 0 , 64) # 25% red
draw = ImageDraw.Draw(target, 'RGBA')
draw.rectangle([destination[0] , destination[1],
destination[0] + tilePixels, destination[1] + tilePixels],
tint)
def renderMap(mapData, mapDimensions, tileSet):
mapX, mapY = mapDimensions
output = Image.new("RGB", (mapX * blockPixels, mapY * blockPixels), 0xFF00FF)
map(lambda number, block:
renderBlock(output,
block,
tileSet,
(number % mapX * blockPixels,
number / mapX * blockPixels)),
range(0,mapX * mapY),
mapData)
return output
def dumpBlocks():
for i in range(0, 128):
block = Image.new("RGB", (blockPixels, blockPixels), 0xFF00FF)
renderBlock(block, i, overworld, (0,0))
block.save("overworld/%i.png" % i)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment