Cargador de mapas de tiled...

Losersjuegos cuenta con una secciones de ejemplos en su web. Utilice esta sección para consultar o proponer ideas acerca de ellos.

Cargador de mapas de tiled...

Notapor Barajas » Vie Jul 20, 2012 1:58 pm

Hola, creo que ha estas altura ya todos sabemos que tiled es un programa que nos permite crear mapas de tiles de forma fácil, asi que como estoy trabajando en un proyecto con tiled, he creado este cargador de mapas, que carga automáticamente las imágenes del mapa, las parte en tileset y no hay que molestarse mucho, la única condición es que los mapas deben estar en comprimidos en base 64 con gzip... pero funciona :D

Aquí el código:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import base64
import gzip
import StringIO
from xml.dom import minidom, Node
import pygame
from pygame import *

def load_ima(name):
return pygame.image.load(name).convert_alpha()

class Mapa():
def __init__(self):
self.imagenes = []
self.imagenes_de_capa = []
self.conjunto_de_capas = []
self.tilewidth = 0
self.tileheight = 0
def convertir(self, lista, col):
#una lista unidimensional a una bidimensional
nueva = []
for i in range(0, len(lista), col):
nueva.append(lista[i:i+col])
return nueva
def traducir(self, cadena):
# Decodificar.
cadena = base64.decodestring(cadena)
# Descomprimir.
copmressed_stream = StringIO.StringIO(cadena)
gzipper = gzip.GzipFile(fileobj=copmressed_stream)
cadena = gzipper.read()
salida = []
#me cuesta explicar lo que susede aqui...
#solo dejemoslo en que se convierte...
for idx in xrange(0, len(cadena), 4):
val = ord(str(cadena[idx])) | (ord(str(cadena[idx + 1])) << 8) | \
(ord(str(cadena[idx + 2])) << 16) | (ord(str(cadena[idx + 3])) << 24)
salida.append(val)

return salida

#-------------------

def cargar_mapa(self, nombre): #función para poder cargar el mapa...
Mapa_tmx = minidom.parse(""+nombre)
nodo_principal = Mapa_tmx.childNodes[1]

#Estas modificaciones son para poder cargar imagenes directamente...
tileset = nodo_principal.getElementsByTagName('tileset')
self.tilewidth = int(tileset[0].attributes.get("tilewidth").value)
self.tileheight = int(tileset[0].attributes.get("tileheight").value)

#buscamos en todas las etiquetas de imagenes...
for j in nodo_principal.getElementsByTagName('image'):
# buscamos en cada unoa de las etiquetas el atributo source
# que contine la dirección del la imagen con respecto al
# archvivo
temp_ima_name = j.attributes.get("source").value
#cargamos la imagen
temp_ima = load_ima(temp_ima_name)
#creo una lista con la imagen partida en tiles....
temp_tiles = cut_by_w_h(temp_ima,self.tilewidth,self.tileheight)
#las agrego a una lista principal
self.imagenes = self.imagenes+temp_tiles

#buscamos el tamaño del mapa
tamano_width = int(nodo_principal.attributes.get("width").value)
tamano_height = int(nodo_principal.attributes.get("height").value)

for i in range(len(nodo_principal.childNodes)):
nodo_actual = nodo_principal.childNodes[i]
#revisamos si existe un nodo...
if nodo_actual.nodeType == 1:
#si el nodo no es de tilesets, pregunto si es de capas...
if nodo_actual.nodeName == "layer":
datos = nodo_actual.childNodes[1]
#quitamos saltos de linea y espacios...
capa = datos.childNodes[0].data.replace("\n", "").replace(" ", "")
capa = self.traducir(capa)
capa = self.convertir(capa, tamano_width)
self.conjunto_de_capas.append(capa)

#esto es por que me gustan los returns XD
return self.conjunto_de_capas

def get_capa(self,num):
#no tengo que explicarlo... ¿verdad?
return self.conjunto_de_capas[num]

def imprime_capa(self,superficie,numero, x=0,y=0):
#imprime una capa determinada en una superficie determinada
capa = self.conjunto_de_capas[numero]

image_num = 0
#para calcular la posición inicial y final
# x=0
# y=0
#esto es una alluda para ver como luce en modo texto el mapa....
print "####################"
# empezamos el recorrido
for fila in capa:
x=0
print ":",
for columna in fila:
#si el numero es diferente a 0...
if columna != 0:
# seleccionamos la imagen, recordemos que tiled
# comienza a contar espacio no vacio a partir de 1
# pero nuestra lista de imagenes comienza en el 0
ima = self.imagenes[columna-1]
#la colocamos en el mapa...
superficie.blit(ima, (x,y))
print columna,
# esto es simplemente para poder velo en modo texto...
else:
print " ",
#aumentamos la posición en X...
x+=self.tilewidth
print ":"
# y ahora aumentamos la posición en Y...
y+=self.tileheight

def trasforma_a_imagenes(self, capa_num):
#esto resive el numero de la capa y regresa una imagen de sus dimenciones...
capa = self.conjunto_de_capas[capa_num]

filas = len(capa)
columnas = len(capa[0])
# primero creamos una imagen vacia de las dimenciones de la capa...
imagen_capa = pygame.Surface((columnas*self.tileheight, filas*self.tilewidth))
# le fijamos un color que usaremos de trasparencia a la imagen...
imagen_capa.fill((255,0,255))
# sobre ella dibujamos la capa...
self.imprime_capa(imagen_capa,capa_num)
# y borramos el color alfa...
imagen_capa.set_colorkey((255,0,255))
# regresamos una copia de la imagen...
return imagen_capa.copy()

def imprime_imagen_capa(self, pantalla, pos_x=0,pos_y=0, numero=0):
#
pantalla.blit(self.imagenes_de_capa[numero],(pos_x,pos_y))

def hacer_colisionbox_capa(self, numero):
# esto crea una serie de cajas de colisiones de una capa determinada
capa = self.conjunto_de_capas[numero]
colision_rects = []
x=0
y=0
w = 0
temp_x = 0
for fila in capa:
x=0
for columna in fila:
# esto junta por columna, las cajas de colision
# para que sean menos
if columna != 0:
if temp_x == 0 and w == 0:
temp_x = x
w+=self.tilewidth
else:
if w != 0:
colision_rects.append(pygame.Rect(temp_x,y, w, self.tileheight))
w=0
temp_x = 0
x+=self.tilewidth

#---esto es en el caso de que la columna este llena de tiles...
# ya que si eso ocurre, nunca se cumplira la condición del "else"
if w != 0:
colision_rects.append(pygame.Rect(temp_x,y, w, self.tileheight))
w=0
temp_x = 0
y+=self.tileheight

return colision_rects

def cut_by_w_h(imagen,w,h):
Lista_ima = [];
ima_w = imagen.get_width()
ima_h = imagen.get_height()
columnas = (ima_w/w)
filas = (ima_h/h)
f = 0
c = 0
ima_temp = pygame.Surface((w, h))
while(f<filas):
while(c<columnas):
ima_temp.fill((255,255,255))
ima_temp.set_colorkey((255,255,255))
rect = ((c * w),(f * h),w, h)
ima_temp.blit(imagen, (0,0), rect)
Lista_ima.append(ima_temp.copy())
c+=1
c=0
f+=1
return Lista_ima


Un ejemplo de su uso...

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygame
from pygame import *
# puedes ponerle cualquier nombre....
from carga_mapa import *

def main():
# inicializamos pygame
screen = pygame.display.set_mode((640, 480))
#creamos el objeto para cargar el mapa
mapa = Mapa()
# cargamos el mapa ...
mapa.cargar_mapa("prueva_tile.tmx")

# creo una lista de imágenes...
imagenes = []
for ima in range(len(mapa.conjunto_de_capas)):
# donde guardo las imágenes de capas...
imagenes.append(mapa.trasforma_a_imagenes(ima))

hacer = True
delay_frames = (1000/25)
while hacer:
pygame.time.delay(delay_frames)
for event in pygame.event.get():
if event.type == QUIT:
hacer = False
screen.fill((130,130,130))
# imprimimos las imágenes de las capas
for image in imagenes:
screen.blit(image, (0,0))

pygame.display.update()
pygame.quit()

main()



Se aceptan criticas :D
Vi veri universum vivus vici
Avatar de Usuario
Barajas
 
Mensajes: 209
Registrado: Mar Nov 16, 2010 12:06 am

Re: Cargador de mapas de tiled...

Notapor carlostex » Vie Jul 20, 2012 5:06 pm

En que formato se guarda el tile?
Yo usaba uno que se llamaba tilemap que guarda el archivo en formato xml, luego use una biblioteca llamada tinyxml y era muy facil cargar el archivo con pocas lineas.
El conocimiento de unos es conocimiento de todos.
Avatar de Usuario
carlostex
 
Mensajes: 249
Registrado: Mar Jul 14, 2009 4:13 am
Ubicación: mexico

Re: Cargador de mapas de tiled...

Notapor Barajas » Vie Jul 20, 2012 6:41 pm

carlostex escribió:En que formato se guarda el tile?


Lo guarda en su formato tmx, el cual es solo un xml. Pero que puede guardar la lista completa en una cadena comprimida con gzip y en base 64...., de hecho puede notar que se trata de un mapa con dimensiones de 40*15, lo que significa 600 datos reducidos a una cotar cadena en comparación y eso reduce el tamaño del archivo bastante...

El archivo usado en el ejemplo....

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE map SYSTEM "http://mapeditor.org/dtd/1.0/map.dtd">
<map version="1.0" orientation="orthogonal" width="40" height="15" tilewidth="32" tileheight="32">
<tileset firstgid="1" name="tileset_sdl" tilewidth="32" tileheight="32">
<image source="tileset.png" width="320" height="160"/>
</tileset>
<layer name="Capa de Patrones 1" width="40" height="15">
<data encoding="base64" compression="gzip">
H4sIAAAAAAAAA+2RQQqAMAwEY1TsoWf//1QjGGiFtpJu1UMW5joMSSTcJiECfQT2eV/fvC/fIqzC9tDl9+vbiD6+mAGuv9+PwT4C+c676R/e7AsJpaVtoeGzzOq7dylf95W6LH3qqW0fAAM5AE3LgDBgCQAA
</data>
</layer>
<layer name="Capa de patrones 2" width="40" height="15">
<data encoding="base64" compression="gzip">
H4sIAAAAAAAAA2NiYGBgohGmBuAhAhOrjoeB+gDdfmxsdPXY3IxNLa3chy6OSw82fbQC5NpBD7eNglEwCkbBKBgFpAIAjKs1ZWAJAAA=
</data>
</layer>
</map>


Aun que puedes darle que no comprima (tiled el llama CSV )y el resultado que pondría para la primera capa seria:
<layer name="Capa de Patrones 1" width="40" height="15">
<data encoding="csv">
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,4,5,7,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,8,8,8,0,0,0,0,0,0,1,2,2,8,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,8,8,8,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12,0,0,0,0,0,0,0,0,0,0,0,1,2,2,8,8,8,8,8,12,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,
22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
</data>


Y en XML puro....

<layer name="Capa de Patrones 1" width="40" height="15">
<data>
<tile gid="12"/>
<tile gid="0"/>
<tile gid="0"/>
<tile gid="0"/>
...
...


¿ Aun que como los guarda tilemap ?
Vi veri universum vivus vici
Avatar de Usuario
Barajas
 
Mensajes: 209
Registrado: Mar Nov 16, 2010 12:06 am

Re: Cargador de mapas de tiled...

Notapor shackra » Sab Ago 04, 2012 3:28 am

prueba va con b mi 'jito xd
por todo lo demás, gracias por el ejemplo. espero probarlo pronto!
Avatar de Usuario
shackra
 
Mensajes: 308
Registrado: Lun Jun 15, 2009 4:10 pm
Ubicación: Costa Rica

Re: Cargador de mapas de tiled...

Notapor Barajas » Sab Ago 04, 2012 2:35 pm

shackra escribió:prueba va con b mi 'jito xd

¡¡WAAAA!! ¡¡Es cierto... !! :oops: :oops:
De vez en cuando me confundo... (una vez incluso escribí "nobiembre"... me lo recuerdan cada vez que pueden. "chicos, recuerden que noviembre se escribe con 'v'... ")

Por lo demás, espero que les sea útil...
Vi veri universum vivus vici
Avatar de Usuario
Barajas
 
Mensajes: 209
Registrado: Mar Nov 16, 2010 12:06 am

Re: Cargador de mapas de tiled...

Notapor d0hk0o » Sab Ago 04, 2012 5:49 pm

Yo estuve buscando esa rutina para c++! pero no la encontré, tuve que trabajar con ticpp, pero solo trabajé con codificación base64, no le puse compresión zlib o gzip porque había que investigar y no disponía de mucho tiempo u.u

Pero se agradece, si llego a utilizar python de seguro que la usaré!
d0hk0o
 
Mensajes: 13
Registrado: Mar Mar 22, 2011 5:54 pm

Re: Cargador de mapas de tiled...

Notapor Barajas » Sab Ago 04, 2012 9:55 pm

Bueno, d0hk0o, creo que aquí esta la rutina que buscas... http://usefulgamedev.weebly.com/c-tiled-map-loader.html
Vi veri universum vivus vici
Avatar de Usuario
Barajas
 
Mensajes: 209
Registrado: Mar Nov 16, 2010 12:06 am

Re: Cargador de mapas de tiled...

Notapor d0hk0o » Dom Ago 05, 2012 5:02 am

:-O! gracias! creo que con esto se completa el tema de Tiled para trabajar en python y c++. Lo bueno de este programa es que puedes almacenar propiedades del mapa, propiedad de cada tile, objetos en el mapa cada uno con sus respectivos atributos, creo que no le falta nada...
d0hk0o
 
Mensajes: 13
Registrado: Mar Mar 22, 2011 5:54 pm


Volver a Ejemplos

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado