pilas.demos.piezas

Package pilas :: Package demos :: Module piezas |
[hide private]
[frames] | no frames]

# Source Code for Module pilas.demos.piezas

      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 pilas
     10  import random
     11
     12
     13 -class Piezas(pilas.escena.Base):
     14      """Representa la escena de rompecabezas.
     15
     16      La escena comienza con una imagen que se descompone en muchos
     17      actores Pieza.
     18      """
     19
     20 -    def __init__(self, ruta_a_la_imagen="fondos/noche.jpg", filas=4, columnas=4, al_terminar=None):
     21          pilas.escena.Base.__init__(self)
     22          self.ruta_a_la_imagen = ruta_a_la_imagen
     23          self.filas = filas
     24          self.columnas = columnas
     25          self.al_terminar = al_terminar
     26
     27 -    def iniciar(self):
     28          pilas.actores.utils.eliminar_a_todos()
     29          grilla = pilas.imagenes.cargar_grilla(self.ruta_a_la_imagen, self.columnas, self.filas)
     30          self.crear_piezas(grilla, self.filas, self.columnas)
     31          self.pieza_en_movimiento = None
     32
     33          pilas.eventos.click_de_mouse.conectar(self.al_hacer_click)
     34          pilas.eventos.termina_click.conectar(self.al_soltar_el_click)
     35          pilas.eventos.mueve_mouse.conectar(self.al_mover_el_mouse)
     36
     37          self.sonido_tick = pilas.sonidos.cargar("tick.wav")
     38          self.al_terminar = self.al_terminar
     39          self.piezas_desconectadas = self.filas * self.columnas -1
     40
     41 -    def crear_piezas(self, grilla, filas, columnas):
     42          "Genera todas las piezas en base al tamaño del constructor."
     43          self.piezas = []
     44          self.grupos = {}
     45
     46          for x in range(filas * columnas):
     47              self.grupos[x] = set([x])
     48              pieza = Pieza(self, grilla, x, filas, columnas)
     49              self.piezas.append(pieza)
     50              pieza.x = random.randint(-200, 200)
     51              pieza.y = random.randint(-200, 200)
     52
     53
     54 -    def al_hacer_click(self, evento):
     55          "Atiente cualquier click que realice el usuario en la pantalla."
     56          x, y = evento.x, evento.y
     57          pieza_debajo_de_mouse = pilas.actores.utils.obtener_actor_en(x, y)
     58
     59          if pieza_debajo_de_mouse and isinstance(pieza_debajo_de_mouse, Pieza):
     60              self.pieza_en_movimiento = pieza_debajo_de_mouse
     61              self.pieza_en_movimiento.mostrar_arriba_todas_las_piezas()
     62
     63 -    def al_soltar_el_click(self, evento):
     64          if self.pieza_en_movimiento:
     65              self.pieza_en_movimiento.soltar_todas_las_piezas_del_grupo()
     66              self.pieza_en_movimiento.mostrar_abajo_todas_las_piezas()
     67              self.pieza_en_movimiento = None
     68
     69 -    def al_mover_el_mouse(self, evento):
     70          if self.pieza_en_movimiento:
     71              self.pieza_en_movimiento.x += evento.dx
     72              self.pieza_en_movimiento.y += evento.dy
     73
     74 -    def conectar(self, pieza_a, pieza_b):
     75          a = pieza_a.numero
     76          b = pieza_b.numero
     77
     78
     79          if a in self.grupos[b]:
     80              #Evita contectar mas de una vez a dos piezas.
     81              return
     82
     83          """Inicialmente comienzo con::
     84
     85
     86              0: [0, 1, 2]
     87              1: [0, 1, 2]
     88              2: [0, 1, 2]
     89              3: [3]
     90
     91          ¿y si conecto la pieza 3 con la 2?
     92
     93          - tendría que obtener todas las piezas que conoce 2.
     94
     95          - iterar en ese grupo y decirle a cada pieza que sume a 3 en su grupo::
     96
     97              0: [0, 1, 2, 3]
     98              1: [0, 1, 2, 3]
     99              2: [0, 1, 2, 3]
    100
    101          - luego solo me falta tomar a uno de esos grupos actualizados
    102            y decirle a 3 que ese será su grupo::
    103
    104              3: [0, 1, 2, 3]
    105          """
    106
    107          grupo_nuevo = set(self.grupos[a]).union(self.grupos[b])
    108
    109          for pieza in grupo_nuevo:
    110              self.grupos[pieza] = grupo_nuevo
    111
    112          self.piezas_desconectadas -= 1
    113
    114          if self.piezas_desconectadas < 1:
    115              if self.al_terminar:
    116                  self.al_terminar()
    117
    118          self.sonido_tick.reproducir()
    119
    120 -class Pieza(pilas.actores.Animado):
    121      """Representa una pieza del rompecabezas.
    122
    123      Esta pieza se puede arrastrar con el mouse y cuando se suelta
    124      intentará conectarse con las demás."""
    125
    126 -    def __init__(self, escena_padre, grilla, cuadro, filas, columnas):
    127          "Genera la pieza que representa una parte de la imagen completa."
    128          self.escena_padre = escena_padre
    129          self.numero = cuadro
    130          pilas.actores.Animado.__init__(self, grilla)
    131
    132          self.z_de_la_pieza_mas_alta = 0
    133          self.asignar_numero_de_piezas_laterales(cuadro, columnas)
    134
    135          self.definir_cuadro(cuadro)
    136
    137          self.radio_de_colision = self.obtener_ancho() / 2 + 12
    138          self.piezas_conectadas = []
    139
    140 -    def asignar_numero_de_piezas_laterales(self, cuadro, columnas):
    141          "Guarda el numero de las piezas que se pueden conectar en sus bordes."
    142          self.numero_arriba = cuadro - columnas
    143          self.numero_abajo = cuadro + columnas
    144
    145          if cuadro % columnas == 0:
    146              self.numero_izquierda = -1
    147          else:
    148              self.numero_izquierda = cuadro - 1
    149
    150          if cuadro % columnas == columnas -1:
    151              self.numero_derecha = -1
    152          else:
    153              self.numero_derecha = cuadro + 1
    154
    155 -    def soltar_todas_las_piezas_del_grupo(self):
    156          for numero in self.escena_padre.grupos[self.numero]:
    157              pieza = self.escena_padre.piezas[numero]
    158              pieza.soltar()
    159
    160 -    def soltar(self):
    161          # Busca todas las colisiones entre esta pieza
    162          # que se suelta y todas las demás.
    163          colisiones = pilas.escena_actual().colisiones.obtener_colisiones(self, self.escena_padre.piezas)
    164
    165          for x in colisiones:
    166              self.intentar_conectarse_a(x)
    167
    168 -    def se_pueden_conectar_los_bordes(self, borde1, borde2):
    169          distancia = pilas.utils.distancia(borde1, borde2)
    170          return  distancia < 12
    171
    172 -    def intentar_conectarse_a(self, otra):
    173          "Intenta vincular dos piezas, siempre y cuando coincidan en sus bordes."
    174
    175          # Intenta conectar los bordes laterales
    176          if self.numero_derecha == otra.numero:
    177              if self.se_pueden_conectar_los_bordes(self.derecha, otra.izquierda):
    178                  otra.izquierda = self.derecha
    179                  otra.arriba = self.arriba
    180                  self.conectar_con(otra)
    181
    182          elif self.numero_izquierda == otra.numero:
    183              if self.se_pueden_conectar_los_bordes(self.izquierda, otra.derecha):
    184                  otra.derecha = self.izquierda
    185                  otra.arriba = self.arriba
    186                  self.conectar_con(otra)
    187
    188          # Intenta conectar los bordes superior e inferior
    189          if self.numero_abajo == otra.numero:
    190              if self.se_pueden_conectar_los_bordes(self.abajo, otra.arriba):
    191                  otra.arriba = self.abajo
    192                  otra.izquierda = self.izquierda
    193                  self.conectar_con(otra)
    194
    195          elif self.numero_arriba == otra.numero:
    196              if self.se_pueden_conectar_los_bordes(self.arriba, otra.abajo):
    197                  otra.abajo = self.arriba
    198                  otra.izquierda = self.izquierda
    199                  self.conectar_con(otra)
    200
    201
    202 -    def conectar_con(self, otra_pieza):
    203          self.escena_padre.conectar(self, otra_pieza)
    204
    205
    206 -    def __repr__(self):
    207          return "<<Pieza %d>>" %(self.animacion.obtener_cuadro())
    208
    209
    210 -    def set_x(self, x):
    211          "A diferencia de los actores normales, las piezas tienen que mover a todo su grupo."
    212          dx = x - self.x
    213
    214          for numero in self.escena_padre.grupos[self.numero]:
    215              try:
    216                  pieza = self.escena_padre.piezas[numero]
    217                  pieza.definir_posicion(pieza.x + dx, pieza.y)
    218              except IndexError:
    219                  pass
    220
    221 -    def set_y(self, y):
    222          "A diferencia de los actores normales, las piezas tienen que mover a todo su grupo."
    223          dy = y - self.y
    224
    225          for numero in self.escena_padre.grupos[self.numero]:
    226              try:
    227                  pieza = self.escena_padre.piezas[numero]
    228                  pieza.definir_posicion(pieza.x, pieza.y + dy)
    229              except IndexError:
    230                  pass
    231
    232 -    def get_x(self):
    233          x, y = self.obtener_posicion()
    234          return x
    235
    236 -    def get_y(self):
    237          x, y = self.obtener_posicion()
    238          return y
    239
    240      x = property(get_x, set_x, doc="Define la posición horizontal.")
    241      y = property(get_y, set_y, doc="Define la posición vertical.")
    242
    243 -    def mostrar_arriba_todas_las_piezas(self):
    244          for numero in self.escena_padre.grupos[self.numero]:
    245              pieza = self.escena_padre.piezas[numero]
    246              pieza.z = -1
    247
    248 -    def mostrar_abajo_todas_las_piezas(self):
    249          for numero in self.escena_padre.grupos[self.numero]:
    250              pieza = self.escena_padre.piezas[numero]
    251              pieza.z = 0
    252