Problema con dibujar mapa

Agrupa todas las consultas sobre los lenguajes de programacion como C, C++, Python, Java ...

Problema con dibujar mapa

Notapor Juanxo » Sab Mar 21, 2009 12:38 pm

Buenas.

He creado una funcion para dibujar los obstaculos de terreno sobre un mapa (todo con tiles), pero esta me da un error de list index out of range exactamente en la sentencia marcada en l codigo:

Código: Seleccionar todo
    def imprimir_obstaculos(self,screen):

        tile_origen_x=self.camara_x/64
        tile_origen_y=self.camara_y/64

        tile_destino_x=tile_origen_x + ANCHO/64 + 1
        tile_destino_y = tile_origen_y + ALTO/64 + 1

        filas=0

        for fila in range(tile_origen_y,tile_destino_y):
            columna=0
            for celda in range(tile_origen_x,tile_destino_x):

             ***AQUI DA ERROR*** if self.obstaculos[fila][celda] in self.Tiles_Obstaculo:

                    columnaT,filaT = self.Tiles_Obstaculo[self.obstaculos[fila][celda]]
                    screen.blit(self.image,(64*columna,64*filas),(64*columnaT,64*filaT,64,64))
                    columna+=1
            filas+=1
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Re: Problema con dibujar mapa

Notapor endaramiz » Sab Mar 21, 2009 8:34 pm

Ya que no tengo todo el código para poderlo ejecutar, te pongo los prints que haría yo para intentar encontrar el error:
Código: Seleccionar todo
    def imprimir_obstaculos(self,screen):
        [...]
        print "matriz: ", self.obstaculos #
        print "filas: ", len(self.obstaculos) #
        for i in range(len(self.obstaculos)): #
            print "columnas de fila ", i, ": ", len(self.obstaculos[i]) #
        for fila in range(tile_origen_y,tile_destino_y):
            columna=0
            for celda in range(tile_origen_x,tile_destino_x):
                print fila, celda #

             ***AQUI DA ERROR*** if self.obstaculos[fila][celda] in self.Tiles_Obstaculo:
                    [...]


Podría ser porque la cámara no está fuera del mapa.

Saludos.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor Juanxo » Dom Mar 22, 2009 12:48 am

gracias david. El problema estaba en ese +1 que tenia tile_destino_y, que creaba una fila mas de las que había en el array.

He estado pensando, y quiero ver si habría algúna manera de hacer lo siguiente:

el terreno del mapa lo he transformado en una superficie, siguiendo el ejemplo de RPG de hugo. He intentado hacer lo mismo con el fondo de obstaculos, pero el problema es que al blitear, superpone el de obstaculos al de terreno, quedando la mayoría de la pantalla negra. Podría hacer algo parecido a lo de colorkey con la superficie, para transparentar los pixels que no tuvieran objetos (es decir, los cuadrados negros)??
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Notapor endaramiz » Dom Mar 22, 2009 10:21 am

Juanxo escribió:el terreno del mapa lo he transformado en una superficie, siguiendo el ejemplo de RPG de hugo. He intentado hacer lo mismo con el fondo de obstaculos, pero el problema es que al blitear, superpone el de obstaculos al de terreno, quedando la mayoría de la pantalla negra. Podría hacer algo parecido a lo de colorkey con la superficie, para transparentar los pixels que no tuvieran objetos (es decir, los cuadrados negros)??

Como tú bien has dicho, se podría hacer con el colorkey sobre la Surface de los obstáculos. Ya sea en negro, que es con el color que se crea la Surface por defecto o poniendole un color raro (255,0,255) de fondo.
De todas formas, dependiendo de como esté construido el programa, a lo mejor te interesa más blitear todos los obstáculos en la Surface terreno y trabajar con una sola imagen. Así ahorrarías unos pocos milisegundos por cuadro(si llega xD) porque no dibujarías el trozo de terreno que luego va a ser tapado por un obstáculo. Y quizás lo simplifique un poco. Pero, para decirlo con certeza, tendría que ver todo el código.

Saludos.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor Juanxo » Dom Mar 22, 2009 3:02 pm

Gracias de nuevo. Ya lo pense, pero no merecía la pena, ya que los obstaculos(rocas troncos, etc) no tienen la forma exacta del tile, por lo que quedarían huecos vacíos. Al final tambien he descartado la opción de crear una nueva superficie para los obstaculos, ya que estaría creando una superficie mayoritariamente vacía, por lo que mejor he decidido blitear directamente en la pantalla teniendo en cuenta el scroll y ya me funciona correctamente. El código completo es el siguiente:

Código: Seleccionar todo

# -*- coding: cp1252 -*-

import pygame,os,sys
from pygame.locals import *
# -*- coding: cp1252 -*-
DATOS='images'
#=========================================
#Prueba de mapa de tiles, con scrolling
#Ejemplos de apoyo:
#   mini_rpg(scrolling de camara)
#   mono(Creacion de mapa como lectura de fichero)
#   http://www.wired-weasel.com/users/serhid/blog/?page_id=4(creacion de tilemaps)
#
#
#========================================

ANCHO=640
ALTO=480

def load_image(name,colorkey=False, pos=10):
    fullname=os.path.join(DATOS,name)

    try:
        image=pygame.image.load(fullname)

    except pygame.error,message:
        print 'No se puede cargar la imagen: ',fullname
        raise SystemExit,message

    image=image.convert()

    if (colorkey):
           
        colorkey=image.get_at((pos,0))
        image.set_colorkey(colorkey,RLEACCEL)


    return image , image.get_rect()                   
                               

class Escenario():

    def __init__(self , nivel=1):
         
      #creamos las matrices del mapa
      self.mapa = self.cargar_nivel(nivel)
      self.obstaculos=self.cargar_obstaculos(nivel)

      self.image , self.rect = load_image('fondos.bmp',True,760)

      #diccionarios de la (columna,fila) de un tipo de tile dentro de la grilla
      self.Tiles_Terreno={ '1': (3,13)}
     
      self.Tiles_Obstaculo={'1': (3,12),
                        '2': (0,12) }


      # coordenada superior izquierda de la cámara.
      # estas variables intentan alcanzar el valor de las variables
      # 'destino_camara_x' y 'destino_camara_y'.     
      self.camara_x = 0
      self.camara_y = 0
     

      self.fondo= self.crear_fondo(self.mapa)

      #posicion a la que debe llegar la camara
      self.destino_camara_x=0
      self.destino_camara_y=0
     
      self.dibujar_mapa()

     
    def imprimir(self,screen):

      origen=(self.camara_x,self.camara_y,ANCHO,ALTO)
      destino=(0,0,ANCHO,ALTO)
      screen.blit(self.fondo,destino,origen)
     

    def update(self):
      self.camara_x+=(self.destino_camara_x-self.camara_x)/8.0
      self.camara_y+=(self.destino_camara_y-self.camara_y)/8.0

    def mirar_a(self,rect):
      self.destino_camara_x=rect.x-ANCHO/2
      self.destino_camara_y=rect.y-ALTO/2
      self._aplicar_limites()

    def cargar_nivel(self , nivel):
      nombre_del_archivo='nivel_%d.txt'%nivel#empleamos el format string para poder asignar
      archivo=open(nombre_del_archivo,'rt')#el nombre del fichero
      mapa=archivo.readlines()#devuelve un String con el mapa
      archivo.close()
      return mapa

    def cargar_obstaculos(self,nivel):
      nombre_del_archivo='obstaculos_nivel_%d.txt'%nivel
      archivo=open(nombre_del_archivo)
      obstaculos=archivo.readlines()
      return obstaculos


    def crear_fondo(self,array):

      filas=len(array)
      columnas=len(array[0])-1
      ancho=columnas*64
      alto=filas*64

      return pygame.Surface((ancho,alto)).convert()

   
    def _aplicar_limites(self):
      if self.destino_camara_x < 0:
          self.destino_camara_x = 0
     
      if self.destino_camara_y < 0:
          self.destino_camara_y = 0

      if self.destino_camara_x + ANCHO > self.fondo.get_width()-64:
          self.destino_camara_x = self.fondo.get_width() - ANCHO-64

      if self.destino_camara_y + ALTO > self.fondo.get_height()-64:
          self.destino_camara_y = self.fondo.get_height() - ALTO-64



    def puede_pisar(self,x,y):
      fila=y/64
      columna=x/64

      try:
          celda=self.obstaculos[fila][columna]
      except:
          return False

      if celda in ['0']:
          return True

      return False

     

    def dibujar_mapa(self):



      filas=0
      for fila in self.mapa:
          columna=0
          for celda in fila:
           
            if celda in self.Tiles_Terreno:
                columnaT , filaT = self.Tiles_Terreno[celda]
                self.fondo.blit(self.image,(64*columna,64*filas),(64*columnaT,64*filaT,64,64))
                columna+=1
               
          filas+=1

    def imprimir_obstaculos(self,screen):

      tile_origen_x=self.camara_x/64
      tile_origen_y=self.camara_y/64

      tile_destino_x=tile_origen_x + ANCHO/64+1
      tile_destino_y = tile_origen_y + ALTO/64 +2

      if tile_destino_x >= len(self.obstaculos[0])-1:
          tile_destino_x = len(self.obstaculos[0])-1

      if tile_destino_y>=len(self.obstaculos):
          tile_destino_y=len(self.obstaculos)

      filas=0
      for fila in range(tile_origen_y,tile_destino_y):
          columna=0
          for celda in range(tile_origen_x,tile_destino_x):
                  if self.obstaculos[fila][celda] == '0':
                          columna+=1
       
                  if self.obstaculos[fila][celda] in self.Tiles_Obstaculo:

                      columnaT,filaT = self.Tiles_Obstaculo[self.obstaculos[fila][celda]]
                      screen.blit(self.image,(64*columna-self.camara_x%64,64*filas-self.camara_y%64),(64*columnaT,64*filaT,64,64))
                      columna+=1
          filas+=1

         
         

class Conejo(pygame.sprite.Sprite):

    def __init__(self,escenario):
      pygame.sprite.Sprite.__init__(self)
      self.image,self.rect=load_image('conejo.bmp',True)
     
      self.rect.move_ip(64,64)#centrado en primer cuadrado


      self.escenario=escenario

    def update(self):

      teclas=pygame.key.get_pressed()

      dx=0
      dy=0
     
      if teclas[K_UP]:
          dy=-2
      elif teclas[K_DOWN]:
          dy=2

      if teclas[K_RIGHT]:
          dx=2
      elif teclas[K_LEFT]:
          dx=-2

      if not self.escenario.puede_pisar(self.rect.centerx+dx,self.rect.centery):
          dx=0

      if not self.escenario.puede_pisar(self.rect.centerx,self.rect.centery+dy):
          dy=0

      if self.rect.x+self.rect.width-self.escenario.camara_x>=ANCHO:
          self.rect.x=ANCHO-self.rect.width+self.escenario.camara_x

      if self.rect.y+self.rect.height/2  <= 0 :
          self.rect.y =- self.rect.height/2         
      self.rect.move_ip(dx,dy)

      self.escenario.mirar_a(self.rect)

    def imprimir(self,screen):
      x=self.rect.x-self.escenario.camara_x
      y=self.rect.y-self.escenario.camara_y

      screen.blit(self.image,(x,y))

             
def main():
   
    pygame.init()


    escenario=Escenario()
    """
************************************************************
    Mi intención con estos tres try es conseguir:
      1-que la altura de la pantalla sea menor o igual que la altura total del mapa
      2- idem pero con el ancho
      3- que las dimensiones de las matrices sean iguales.

    Supongo que no estarán bien expresados, porque no controlo demasiado el tema de los
    errores en pygame. Si alguno sabe como sería, Por favor me lo comunique
****************************************************************
    try:
      ALTO/64 <= len(escenario.mapa)
    except:
      print 'El alto de la pantalla es mayor que la altura del mapa'
      exit()

    try:
      ANCHO/64 <= len(escenario.mapa[0])
    except:
      print 'El ancho de la pantalla es mayor que el ancho del mapa'
      exit()

    try:
      len(self.mapa[0]) = len(self.obstaculos[0])
    except:
      print 'Las dimensiones de las matrices de los mapas y obstaculos no coinciden'
      exit()


"""

    screen=pygame.display.set_mode((ANCHO,ALTO))
     
    clock=pygame.time.Clock()
   


    conejo=Conejo(escenario)
   




    #main loop
    while True:
     
      clock.tick(80)
     
      key=pygame.key.get_pressed()
      for e in pygame.event.get():
          if e.type==QUIT:
            sys.exit()


      conejo.update()

      escenario.update()
     
      escenario.imprimir(screen)
      escenario.imprimir_obstaculos(screen)

      conejo.imprimir(screen)
      pygame.display.flip()
      pygame.time.wait(10)


if __name__=='__main__':
    main()



Por cierto, se me ha estropeado la mayoria de las indentaciones. alguno sabe como arreglarlo??
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)


Volver a Sobre lenguajes de programación

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados

cron