Package pilas :: Package actores :: Module mapa
[hide private]
[frames] | no frames]

Source Code for Module pilas.actores.mapa

  1  # -*- encoding: utf-8 -*- 
  2  # Pilas engine - A video game framework. 
  3  # 
  4  # Copyright 2010 - Hugo Ruscitti 
  5  # License: LGPLv3 (see http://www.gnu.org/licenses/lgpl.html) 
  6  # 
  7  # Website - http://www.pilas-engine.com.ar 
  8   
  9  import copy 
 10  import math 
 11   
 12  import pilas 
 13  from pilas.actores import Actor 
 14   
15 -class Mapa(Actor):
16 """Representa una mapa de bloques rectangulares, ideal para crear escenarios de plataformas 17 y mapas. 18 """ 19 20
21 - def __init__(self, grilla=None, x=0, y=0, filas=20, columnas=20):
22 """Inicializa el mapa. 23 24 :param grilla: La imagen a utilizar cómo grilla con los bloques del escenario. 25 :param x: Posición horizontal del mapa. 26 :param y: Posición vertical del mapa. 27 :param filas: Cantidad de filas que tendrá el mapa. 28 :param columnas: Cantidad de columnas que tendrá el mapa. 29 """ 30 Actor.__init__(self, 'invisible.png', x, y) 31 32 self.filas = filas 33 self.columnas = columnas 34 35 # Genera una matriz indicando cuales de los bloque son solidos. 36 self.matriz_de_bloques = self._generar_matriz_de_bloques(filas, columnas) 37 38 if not grilla: 39 grilla = pilas.imagenes.cargar_grilla("grillas/plataformas_10_10.png", 10, 10) 40 41 self.grilla = grilla 42 self.superficie = pilas.imagenes.cargar_superficie(columnas * self.grilla.cuadro_ancho, filas * self.grilla.cuadro_alto) 43 self.imagen = self.superficie
44
45 - def _generar_matriz_de_bloques(self, filas, columnas):
46 cols = copy.copy([False] * columnas) 47 matriz_de_bloques = [] 48 49 for indice_fila in range(filas): 50 matriz_de_bloques.append(copy.copy(cols)) 51 52 return matriz_de_bloques
53
54 - def pintar_bloque(self, fila, columna, indice, es_bloque_solido=True):
55 """Define un bloque de la grilla. 56 57 :param fila: La fila que se definirá (comenzando desde 0). 58 :param columna: La columna que se definirá (comenzando desde 0). 59 :param indice: El número de cuadro referente a la grilla (comenzando desde 0). 60 :param es_bloque_solido: True o False para indicar si los objetos físicos deberán colisionar con este bloque. 61 """ 62 #self.matriz_de_bloques[fila][columna] = es_bloque_solido 63 self.matriz_de_bloques[fila][columna] = es_bloque_solido 64 65 # Definimos el cuadro que deseamos dibujar en la Superficie. 66 self.grilla.definir_cuadro(indice) 67 68 # Dibujamos el cuadro de la grilla en la Superficie. 69 ancho = self.grilla.cuadro_ancho 70 alto = self.grilla.cuadro_alto 71 72 x = columna * ancho 73 y = fila * alto 74 75 self.grilla.dibujarse_sobre_una_pizarra(self.superficie, x, y)
76
77 - def pintar_limite_de_bloques(self):
78 """Dibuja los bordes de cada bloque.""" 79 ancho = self.grilla.cuadro_ancho 80 alto = self.grilla.cuadro_alto 81 82 for fila in range(self.filas): 83 for columna in range(self.columnas): 84 self._pintar_borde_de_grilla(fila, columna)
85
86 - def _pintar_borde_de_grilla(self, fila, columna):
87 ancho = self.grilla.cuadro_ancho 88 alto = self.grilla.cuadro_alto 89 x = columna * ancho 90 y = fila * alto 91 92 self.superficie.rectangulo(x+1, y+1, ancho-2, alto-2) 93 94 texto_coordenada = "%d, %d" %(fila, columna) 95 self.superficie.texto(texto_coordenada, x+3, y-3 + alto, magnitud=8)
96
97 - def obtener_distancia_al_suelo(self, x, y, maximo):
98 """Retorna la distancia en pixels desde un punto del mundo al suelo. 99 100 Es importante mostrar que las coordenadas x e y son coordenadas del 101 mundo, no coordenadas de mouse o relativas al mapa. 102 103 El argumento maximo es la cantidad de pixels que tomaremos como 104 valor limite de la busqueda. Por ejemplo, si colocamos 100 como 105 limite y la funcion nos retorna 100 es porque no encontró un suelo 106 a menos de 100 pixels. Este límite existe por una cuestión de 107 eficiencia. 108 109 :param x: Posición horizontal de referencia. 110 :param y: Posición vertical de referencia. 111 :param maximo: Cantidad máxima de pixels a leer. 112 """ 113 114 # TODO: se puede hacer mas eficiente el algoritmo si en lugar 115 # de recorrer desde 0 a maximo solamente se recorre dando 116 # saltos por bloques (de 'self.grilla.cuadro_alto' pixels) 117 try: 118 x, y = self.convertir_de_coordenada_absoluta_a_coordenada_mapa(x, y) 119 120 # El 'resto' es la coordenada 'y' interna a ese tile dentro 121 # del mapa. 122 resto = int(y % self.grilla.cuadro_alto) 123 124 if not resto and self.es_punto_solido_coordenada_mapa(x, y): 125 return 0 126 127 # Es la distancia en pixels a la siguiente fila que se 128 # tiene que evaluar. 129 inicial = self.grilla.cuadro_alto - resto 130 131 # Recorre el escenario hacia abajo, saltando por las filas 132 # del mapa. Si encuentra un suelo se detiene y retorna la 133 # cantidad de pixels que recorrió. 134 for distancia in range(inicial, maximo, self.grilla.cuadro_alto): 135 if self.es_punto_solido_coordenada_mapa(x, y+distancia): 136 return distancia 137 138 except Exception: 139 return maximo 140 141 return maximo
142
143 - def es_bloque_solido(self, fila, columna):
144 """Indica si un determinado bloque es solido. 145 146 Los bloques sólidos se utilizan para marcar paredes y plataformas, es 147 decir que son bloques que generalmente no se pueden sobrepasar. 148 149 :param fila: La fila que se observará. 150 :param columna: La columna que se observará. 151 """ 152 if not 0 <= fila < self.filas or not 0 <= columna < self.columnas: 153 raise Exception("La fila y columna consultadas estan fuera del area del mapa.") 154 155 return self.matriz_de_bloques[fila][columna]
156
157 - def es_punto_solido(self, x, y):
158 """Indica si una coordenada del escenario está sobre un bloque solido. 159 160 :param x: Posición horizontal a consultar. 161 :param y: Posición vertical a consultar. 162 163 """ 164 # Los parametros x e y son coordenadas del escenario, 165 # lo que se conoce como coordenanadas absolutas. 166 167 # La siguiente conversión pasa esas coordenadas absolutas 168 # a coordenadas del mapa, es decir, donde el punto (0, 0) 169 # es la esquina superior izquierda del mapa. 170 x, y = self.convertir_de_coordenada_absoluta_a_coordenada_mapa(x, y) 171 return self.es_punto_solido_coordenada_mapa(x, y)
172
174 """Toma un punto de pantalla y lo convierte a una coordenada dentro del mapa. 175 176 :param x: Coordenada horizontal de pantalla. 177 :param y: Coordenada vertical de pantalla. 178 """ 179 dx, dy = self.centro 180 x = x + dx - self.x 181 y = -y + dy + self.y 182 return x, y
183
184 - def es_punto_solido_coordenada_mapa(self, x, y):
185 """Consulta si un punto (x, y) está señalando un bloque sólido. 186 187 :param x: Coordenada horizontal. 188 :param y: Coordenada vertical. 189 """ 190 fila = self.obtener_numero_de_fila(y) 191 columna = self.obtener_numero_de_columna(x) 192 return self.es_bloque_solido(fila, columna)
193
194 - def obtener_numero_de_fila(self, y):
195 """Retorna el número de fila correspondiente a una coordenada vertical. 196 197 :param y: La coordenada vertical (relativa al mapa, no a la pantalla). 198 """ 199 # 'y' tiene que ser una coordenada del mapa 200 return self._convertir_en_int(y / self.grilla.cuadro_alto)
201
202 - def obtener_numero_de_columna(self, x):
203 """Retorna el número de columna correspondiente a una coordenada horizontal. 204 205 :param x: La coordenada horizontal (relativa al mapa, no a la pantalla). 206 """ 207 # 'x'tiene que ser una coordenada del mapa 208 return self._convertir_en_int(x / self.grilla.cuadro_ancho)
209
210 - def _convertir_en_int(self, valor):
211 return int(math.floor(valor))
212