pilas.actores.mapa

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
    173 -    def convertir_de_coordenada_absoluta_a_coordenada_mapa(self, x, y):
    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