jsuarez/tools/MapMaker.py (192 lines of code) (raw):
from pdb import set_trace as T
from scipy.misc import imread
from scipy.misc import imsave
from sim.lib import Enums
from sim.lib.Enums import Material
import time
import sys
import numpy as np
import pygame
def readRGB(path):
return imread(path)[:, :, :3]
def pgRead(path, alpha=False, rot=90):
try:
img = readRGB(path)
except FileNotFoundError:
return None
img = pygame.pixelcopy.make_surface(img)
if alpha:
img.set_colorkey((255, 255, 255))
return pygame.transform.rotate(img, rot)
class TextureInitializer():
def __init__(self, sz, root='resource/', scale=1):
self.width = sz
self.statHeight = 2
self.scale = scale
self.material = readRGB(root+'Material/textures.png')
self.material = self.textureTiles()
self.entity = self.textureFromFile(Enums.Entity, root+'Entity/')
def textureTiles(self):
reverse = {}
for mat in Material:
mat = mat.value
texCoords = mat.tex
tex = self.getTile(*texCoords)
tex = pygame.pixelcopy.make_surface(tex)
mat.tex = pygame.transform.rotate(tex, 90)
mat.tex = pygame.transform.scale(mat.tex, (int(self.width*self.scale),
int(self.width*self.scale)))
reverse[mat.index] = mat.tex
return reverse
def getTile(self, r, c):
w = self.width
tile = self.material[r*w:r*w+w, c*w:c*w+w, :]
return tile
def textureFromFile(self, enum, path, alpha=True, rot=270):
reverse = {}
for e in enum:
texPath = path + e.name.lower() + '.png'
tex = pgRead(texPath, alpha=alpha, rot=rot)
e.value.tex = tex
if type(e.value.data) == tuple:
reverse[e.value.data[0]] = tex
else:
reverse[e.value.data] = tex
return reverse
class MapMaker:
def __init__(self, w, h, load, res=4):
self.W, self.H = 2*512, 2*512
self.deltaX, self.deltaY = 0, 0
self.fDir = 'resource/map/'
self.fName = 'profs'
self.env = np.ones((h, w), dtype=int)
self.textures = TextureInitializer(16 )
self.client = Client(res)
self.resInd = res
self.setupScreen(self.W, self.H)
self.loadIf(load)
self.start = time.time()
def save(self):
np.savetxt(self.fDir + self.fName + '.txt', self.env, fmt='%d')
pygame.image.save(self.screen, self.fDir + self.fName + '.png')
def loadIf(self, load):
if load:
self.env = np.genfromtxt(self.fDir + self.fName + '.txt')
#self.env = imread(self.fDir + self.fName + '.png')
self.redraw()
def redraw(self):
self.screen.fill((0, 0, 0))
R, C = int(self.H//2**self.resInd), int(self.W//2**self.resInd)
RR, CC = self.env.shape
for r in range(R):
for c in range(C):
rr, cc = r+self.deltaY, c+self.deltaX
if rr < 0 or cc < 0 or rr >= RR or cc >= CC:
continue
tex = self.env[rr, cc]
self.renderTile(r, c, self.textures.material[tex])
def setupScreen(self, W, H):
pygame.init()
self.screen = pygame.display.set_mode((W, H))
def getTile(self, rPx, cPx):
return int(rPx//2**self.resInd), int(cPx//2**self.resInd)
def renderTile(self, r, c, tex):
w = 2**self.resInd
tex = pygame.transform.scale(tex, (w, w))
self.screen.blit(tex, (c*w, r*w))
def render(self):
#Draw
if self.client.clicked:
x, y = pygame.mouse.get_pos()
c, r = self.getTile(x, y)
rr, cc = r+self.deltaY, c+self.deltaX
tex = self.textures.material[self.client.tex]
R, C = self.env.shape
if rr >= 0 and cc >= 0 and rr<R and cc<C:
self.env[rr, cc] = str(self.client.tex)
self.renderTile(r, c, tex)
#buff = pygame.transform.scale(self.buffer, (sx, sy))
#Render
#self.screen.blit(buff, (tx, ty))
pygame.display.flip()
def update(self):
self.client.update()
if self.client.resInd != self.resInd:
self.resInd = self.client.resInd
self.redraw()
if self.client.deltaX != self.deltaX:
self.deltaX = self.client.deltaX
self.redraw()
if self.client.deltaY != self.deltaY:
self.deltaY = self.client.deltaY
self.redraw()
self.render()
if time.time() - self.start > 5.0:
self.start = time.time()
self.save()
class Client:
def __init__(self, resInd):
self.volX, self.volY = 0, 0
self.volDeltaX, self.volDeltaY = 0, 0
self.deltaX, self.deltaY = 0, 0
self.clicked = False
self.rightClicked = False
self.tex = 1
self.resInd = resInd
self.delta = 10
def update(self):
self.processEvents(pygame.event.get())
def quit(self):
pygame.quit()
sys.exit()
def mouseDown(self, button):
if button == 1 and not self.clicked:
self.volX, self.volY = pygame.mouse.get_pos()
self.clicked = True
if button == 3 and not self.rightClicked:
self.volX, self.volY = pygame.mouse.get_pos()
self.rightClicked = True
def mouseUp(self, button):
if button == 1:
if self.clicked:
self.deltaX += self.volDeltaX
self.deltaY += self.volDeltaY
self.volDeltaX, self.volDeltaY = 0, 0
self.clicked = False
elif button == 3:
self.rightClicked = False
elif button == 4:
if self.resInd < 6:
self.resInd += 1
elif button == 5:
if self.resInd > 3:
self.resInd -= 1
print(self.resInd)
def keyUp(self, button):
if button == pygame.K_a:
self.deltaX -= self.delta
elif button == pygame.K_d:
self.deltaX += self.delta
elif button == pygame.K_s:
self.deltaY += self.delta
elif button == pygame.K_w:
self.deltaY -= self.delta
elif button == pygame.K_e:
if self.tex < 6:
self.tex += 1
elif button == pygame.K_q:
if self.tex > 0:
self.tex -= 1
def processEvents(self, events):
for e in events:
if e.type == pygame.QUIT:
self.quit()
elif e.type == pygame.MOUSEBUTTONDOWN:
self.mouseDown(e.button)
elif e.type == pygame.MOUSEBUTTONUP:
self.mouseUp(e.button)
elif e.type == pygame.KEYUP:
print('KeyUp')
self.keyUp(e.key)
if __name__ == '__main__':
w, h, load = int(sys.argv[1]), int(sys.argv[2]), True
if len(sys.argv) > 3 and sys.argv[3] == '--noload':
load=False
mapMaker = MapMaker(w, h, load)
while True:
mapMaker.update()