Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Cambio de pantallas o niveles con pygame
#1
Hola!

Pues ya estoy por aqui Smile

Como comente en mi presentacion, estoy trasteando con el modulo de videojuegos pygame. Aunque he ido aprendiendo a ratos, muchas veces lo he dejado parado por un tiempo. Ya que tambien quise conocer tkinter para crear alguna GUI.

La cosa es que la mayoria de tutoriales de pygame se basan en una pantalla unica o escena. O como mucho un gestor de escenas donde esta el menu, la pantalla de juego y los records. Osea, tres o cuatro escenas. Suelen usar una clase director y otra clase de escenas.

Pero no es eso lo que yo quiero. Lo que busco es crear un mapeado extenso con pygame. Es decir, como los juegos de toda la vida. No el clasico Pong, Tetris, Asteroids y tal...

Nosotros controlamos un personaje que va cambiando de pantalla a medida que llega al final de cada una. Aunque tambien pueden haber pantallas inferiores o superiores. Pues eso, un mapeado de toda la vida.

Lo maximo que he logrado crear yo, es que controlamos un cuadrado y se mueve en dos pantallas. Cuando llega al final de una, cambia a la otra. Eso si, respetando la coordenada propia para dar continuidad a su recorrido entre pantallas.

Cuando tenga el codigo un poco ordenado lo posteo. Ahora tengo las clases en varios modulos y prefiero ponerlo aqui todo junto para dar mas claridad al script.

A mi modo de ver, se deben crear tres clases muy basicas: El Personaje, el Obstaculo y la Pantalla. De la clase Pantalla se deben instanciar las demas pantallas que visita nuestro personaje.  Pero ahi es cuendo me lio. Ya que dentro del bucle del juego se deberia llevar un control de la pantalla actual y el registro de obstaculos y colisiones en esa pantalla.

Es script que pondre es muy basico y hace daño a la vista. Ya que en el bucle principal esta cargado de IFs y solo son dos pantallas. Y para colmo, el obstaculo sale en ambas. Cosa que no tiene logica.

Bueno, cuando lo tenga todo ordenado lo posteo. Un saludo y perdon por el tocho Confused
Responder
#2
Hola. Efectivamente tendríamos que ver el código para poder darte una mano. Como regla general para facilitar la depuración o resolución de un problema siempre es conveniente reducir el código a la mínima cantidad posible, únicamente lo necesario para reproducir el error o la situación que quieras mostrar.

Saludos
Responder
#3
(22-09-2018, 10:26 PM)Francisco escribió: Hola. Efectivamente tendríamos que ver el código para poder darte una mano. Como regla general para facilitar la depuración o resolución de un problema siempre es conveniente reducir el código a la mínima cantidad posible, únicamente lo necesario para reproducir el error o la situación que quieras mostrar.

Saludos

Lo primero gracias por tener en cuenta la sugerencia. Veo que ya hay un apartado en programcion de videojuegos Smile 

Pues aqui va el script que comentaba. Igual hace daño a los ojos. Y es muy basico. Se trata que cuando nuestro juegador (en este caso un cuadrado verde) llegue al final de la pantalla, aparezca en una nueva. Aparte, de su colision con el cuadrado (muro) naranja. En la primera pantalla puede estar relativamente bien. Pero el problema viene al cambio de estas pantallas. Me gustaria, logicamente, que hubiera otro escenario de objetos. Esto no se si se debe implementar en la clase de Rooms (habitaciones) o dejarlo en el bucle principal del script.

Pero claro, si son muchas pantalla se puede liar la mundial con el codigo. Bueno, aqui dejo el pequeño borrador que comento.


Código:
import pygame


# Constantes ESCENA PRINCIPAL Y FPS
ANCHO = 1024
ALTO = 768
FPS = 60

# Constantes COLORES
BLANCO = (255, 255, 255)
NEGRO = (0, 0, 0)
ROJO = (255, 0, 0)
VERDE = (0, 255, 0)
AZUL = (0, 0, 255)
NARANJA = (255, 128, 0)
GRIS = (192, 192, 192)


class Jugador(pygame.sprite.Sprite):
   '''Clase basica del jugador'''
   def __init__(self, x, y, ancho, alto, color, velocidad):
       super().__init__()
       self.image = pygame.Surface([ancho, alto])
       self.image.fill(color)
       self.rect = self.image.get_rect()
       self.rect.x = x
       self.rect.y = y
       self.velocidad = velocidad
     
   def update(self):
       # Movimientos del jugador
       tecla = pygame.key.get_pressed()
       if tecla[pygame.K_LEFT]:
           self.rect.x -= self.velocidad          
       if tecla[pygame.K_RIGHT]:
           self.rect.x += self.velocidad          
       if tecla[pygame.K_UP]:
           self.rect.y -= self.velocidad      
       if tecla[pygame.K_DOWN]:
           self.rect.y += self.velocidad

class Pared(pygame.sprite.Sprite):
   '''Clase basica Pared'''
   def __init__(self, x, y, ancho, alto, color):
       super().__init__()
       self.image = pygame.Surface([ancho, alto])
       self.image.fill(color)
       self.rect = self.image.get_rect()
       self.rect.x = x
       self.rect.y = y
       self.solido = True        

class Rooms:
   def __init__(self, color):
       self.color = color        
       self.ventana = pygame.display.set_mode((1024, 768))    
   def dibuja(self):
       self.ventana.fill(self.color)
       

# Creacion de personaje y objetos
p1 = Jugador(10, 10, 30, 30, VERDE, 4)
muro1 = Pared(100, 50, 100, 100, NARANJA)
muro2 = Pared(50, 50, 80, 50, AZUL)

# Grupos de objetos
objetos = pygame.sprite.Group()
obj_muro = pygame.sprite.Group()
obj_muro.add(muro1)
objetos.add(p1, obj_muro)

# Pantallas
room_0 = Rooms(AZUL)
room_1 = Rooms(NEGRO)
pantalla = [room_0, room_1]

# Inicializacion pygame
pygame.init()

# Reloj
reloj = pygame.time.Clock()    
               
def bucleJuego():
   # Eljuego empieza en la pantalla 0
   actual = 0
   pantalla[actual].ventana
   
   # Bucle de salida del programa
   salir = False
   while not salir:
       reloj.tick(FPS)
       for evento in pygame.event.get():
           if evento.type == pygame.QUIT:
               salir = True
       
       # Movimientos personaje y limites de las pantallas
       if p1.rect.left <= 0 and actual == 0:
           p1.rect.left = 0
       if p1.rect.right >= ANCHO and actual == 1:
           p1.rect.right = ANCHO                
       if p1.rect.centerx >= ANCHO:
           actual = 1
           p1.rect.x = 0            
       if p1.rect.centerx <= 0 and actual == 1:
           actual = 0
           p1.rect.right = ANCHO        
     
       copia_x, copia_y = p1.rect.x, p1.rect.y
       
       # Actualizacion de objetos
       objetos.update()
       
       # Colision con muro
       colisiones = pygame.sprite.spritecollide(p1, obj_muro, False)
       for colision in colisiones:
           if colision.solido:
               p1.rect.x, p1.rect.y = copia_x, copia_y
                 
       
       pantalla[actual].dibuja()
       
       # Dibujado de objetos
       objetos.draw(pantalla[actual].ventana)
       
       # Actualizacion de pantalla
       pygame.display.update()
       
       
bucleJuego()
pygame.quit
Responder
#4
A mi juicio tu código está bien implementado. Coincido en que la clase Rooms debería tener un atributo objects que almacene las instancias de Pared o cualesquiera otros objetos que estén contenidos dentro del escenario, así puedes quitar objetos.draw(pantalla[actual].ventana) del bucle principal y ubicarlo dentro de Rooms.dibuja().
Responder
#5
(23-09-2018, 04:43 PM)Francisco escribió: Coincido en que la clase Rooms debería tener un atributo objects que almacene las instancias de Pared o cualesquiera otros objetos que estén contenidos dentro del escenario, así puedes quitar objetos.draw(pantalla[actual].ventana) del bucle principal y ubicarlo dentro de Rooms.dibuja().

Si, al final lo hice asi. El mayor problema que veo es trabajar con el bucle principal del juego. Y a la vez, dar vida a cada una de las pantallas. Eso sin contar que un objeto se puede mover a distintos ciclos o frames. Supongo que aun estoy muy verde en estos temas. En todo caso, muchas gracias por la ayuda Shy
Responder


Salto de foro:


Usuarios navegando en este tema: 1 invitado(s)