Google+ Seguidores

miércoles, 27 de mayo de 2015

Juego en PyGame - PONG - Parte 2

    5

Jugando PONG en la Magnavox Odyssey

En la entrada anterior:
Juego en PyGame - PONG - Parte 1
terminamos con nuestras 2 barras funcionando adecuadamente, así que en esta segunda parte nos dedicaremos a la construcción de nuestra pelota.

Sin más, comenzamos!......



Sin pelota no hay juego!
Vamos a nuestra clase Bola() y establecemos sus características:

__init__ de Bola()
En self.pos le asignamos las coordenadas para que la pelota inicie en el centro de la cancha (ventana), self.radio determina el tamaño de la pelota, self.velocidad y self.incremento_velocidad determinan la velocidad a la que se moverá la pelota y el incremento que tendrá cada vez que reboten contra una barra, en self.lado_impacto vamos a guardar en qué lado de la cancha la bola impacto y por último en self.sonido_rebote  cargamos el sonido que emitirá la pelota cada vez que rebote.

*más información del módulo pygame.mixer.Sound aquí: http://www.pygame.org/docs/ref/mixer.html#pygame.mixer.Sound

Ahora vamos al método dibujar y escribe lo siguiente:

Método dibujar de Bola()
Con pygame.draw.circle() nos permite dibujar un circulo en la pantalla, este nos pide donde se va a dibujar (pantalla), de que color sera, su posición y su radio.

Características de la pelota
El punto central de toda la pantalla lo obtenemos con [ANCHO / 2, ALTO / 2] y se lo pasamos al dibujar el circulo para que lo deje bien centrado.

Nuestra pelota debera tener un movimiento, quiere decir que verticalmente tendra un movimiento “y” y horizontalmente un movimiento “x”.

En self.velocidad, x = 4 e y = 4 * random.random() + 4, ¿y ese random.random() que hace?

Pues random.random() lo que hace es que cada vez que lo llamemos nos genera un numero decimal al azar entre el 0 y el 1 (por ejemplo 0.56874), así que con esa formula, cada vez que una pelota inicie su movimiento, saldrá en una dirección diferente (con respecto al eje de las “y”), si no lo entiendes, escribelo y al final sabrás a lo que me refiero.

*puedes probar el  modulo random en el interprete o shell de Python escribiendo import random y cada vez que escribas random.random() te generara un numero decimal diferente del 0 al 1.

Es hora de dibujarla, así que vamos a la función principal main() y agregamos la siguiente línea:

Creando la pelota
Creamos la pelota con bola = Bola()


Ahora en el bucle while, en la sección de dibujo ponemos:

Dibujando la pelota
Una vez hecho esto, ejecutamos veremos nuestra pelota perfectamente centrada.


Y tal como lo hicimos con las barras, ahora necesitamos decirle a nuestra pelota como debe comportarse, así que regresemos a la clase Bola() y en el método actualizar() escribimos lo siguiente:

Método actualizar de Bola()
¿Recuerdas que en la barra modificábamos su posición vertical (self.pos[1]) para darle ese efecto de movimiento? Pues con la pelota es prácticamente lo mismo con la diferencia de que también modificaremos su posición horizontal para que la pelota se mueva en todas las direcciones, asi que a los valores que tengan self.pos le sumamos los valores que contengan self.velocidad.

Ahora solo nos queda probar si la pelota se mueve pero para que funcione, tal y como lo hicimos con las barras hay que agregar la lógica al bucle while de la función principal así:

Ejecución de la lógica de la pelota
Una vez hecho, ejecutas y …………………
PAW!!!  Un error!!   


Que no cunda el pánico!, hay que analizar el error que nos muestra la consola:

Mensaje de error de la consola

El cual en mi caso me dice que tuve un error en la linea 47, con pygame.draw.circle(pantalla, BLANCO, self.pos, self.radio) en TypeError me dice que esperaba un numero entero (int) y yo le di un numero con decimales (float).

¿Entonces Python, me estas diciendo que el modulo pygame.draw.circle() admite solamente números enteros? muy bien Python dame un segundo y solucionare esto.....

Bueno, resulta que en self.velocidad = [4, 4 * random.random() + 4] se genera un numero con décimas en el segundo valor (4 * random.random() + 4) el cual lo habíamos sumado a self.pos en el método actualizar(), así que volvamos al método actualizar() y hacemos una pequeña modificación:

Método actualizar de Bola()
Con int() nos aseguramos de que self.pos siempre tendrá números enteros.


*es muy común tener errores a la hora de programar particularmente este que realmente me paso, es por eso que es muy importante detectarlos apoyándonos con la consola y aprender a interpretarla, todo esto lo logras con la practica.

Bien me salí un poco del tema para mostrarte que hasta yo cometo errores xD, ahora si ejecuta y tu pelota ¡se mueve!, pero….. desaparece (-_-) por lo que necesitamos establecer sus limites.

En el método actualizar() primero establecemos los limites superior e inferior:

Estableciendo sus limites superior e inferior
Con esto le decimos que si la posición de la pelota se pasa del limite superior o el limite inferior, entones cambia su sentido vertical con self.velocidad[1] *= -1

Si ejecutas te darás cuenta que tu pelota rebota pero de forma incorrecta, es decir, cambia su dirección cuando el centro de la pelota toca el limite de la pantalla pero queremos que rebote cuando toque el extremo de la pelota, para eso tenemos que considerar el radio de la pelota y lo logramos con la siguiente modificación:

Estableciendo sus limites superior e inferior

Ahora vamos a establecer los limites izquierdo y derecho:

Situaciones de la pelota
Es hora de ponernos serios que viene lo bueno!
 ( ͠° ͟ل͜ ͡°)

Aquí se complica un poco porque la pelota al llegar al limite de la barra, esta debe de detectar si esta tocando la barra para rebotar o de lo contrario iniciar un juego nuevo.

Para esto la pelota necesita conocer 3 valores de la barra que son: su largo, ancho y posición vertical, a que volvemos a la clase Barra() a crear 3 sencillos métodos para poder tener acceso a estos valores.

En nuestra clase Barra() creamos los siguientes métodos:

ancho, largo y posición de Barra()

Con estos 3 métodos; ancho(), largo(), y posicion() vamos a poder accesar a estos valores.



Pero para que nuestra clase Bola() pueda accesar a ellos necesitamos hacer 2 modificaciones al código que llevamos:

agregando parámetros barra1 y barra2
1- El método actualizar() de la clase Bola() va a recibir 2 parámetros; barra1 y barra2:


pasando parámetros barra1 y barra2
2- En el bucle while en la lógica del juego le pasamos las barra1 y barra2 a nuestra Pelota:


Con esto nuestra Pelota va a tener acceso a los métodos de ambas barras.

Bien, regresamos al método actualizar() de la clase Bola() y …..

Detectando los limites
agregamos las condiciones que detectaran si la pelota toca el limite izquierdo y el derecho tomando en cuenta el ancho de las barras. Por el momento no hacen nada.


Ahora escribimos lo siguiente:

Detectando si tocamos la barra o el vació

Detectando si tocamos la barra o el vació



Bien, la condición if es la que detectara si la pelota al llegar al limite se encuentra dentro del largo de la barra, es decir, si la toco (por el momento no hace nada) y de no tocarla guardara en self.lado_impacto el lado que impacto (perdió).





Y por ultimo le diremos que debe hacer si toca la barra:

Agregando el comportamiento si tocamos una barra

Reproducimos el sonido de rebote con self.sonido_rebote.play(), con self.pos[0] = barra1.ancho() + self.radio esta linea se encarga de mantener la pelota siempre dentro de los limites izquierdo y derecho porque cuando la pelota alcanza una velocidad considerable, veríamos errores en el rebote y al final cambiamos el sentido de la pelota multiplicando su velocidad horizontal por -1 y la incrementamos multiplicándola por self.incremento_velocidad (1.1 es igual al 10%).

Esta entrada estuvo bastante agitada ¿no creen?

Hasta aquí la segunda parte de esta guía, en la siguiente, concluiremos este tutorial.

Saludos! (◕‿◕)

Salvador Ramirez  Google+



Parte 1 - Parte 2 - Parte 3

5 comentarios:
Write comentarios
  1. Extraordinario. Saludos!

    ResponderEliminar
  2. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  3. espero que me respondas lo más pronto amigo... en esa parte del error que mencionabas yo sigo tus pasos y aun asi me vuelve a salir el mismo tipo de error.. que podria estar pasando?

    ResponderEliminar
    Respuestas
    1. Traceback (most recent call last):
      File "D:\User\Downloads\PONG\plantilla.py", line 206, in
      main()
      File "D:\User\Downloads\PONG\plantilla.py", line 194, in main
      bola.dibujar(pantalla)
      File "D:\User\Downloads\PONG\plantilla.py", line 100, in dibujar
      pygame.draw.circle(pantalla,BLANCO,self.pos,self.radio)
      TypeError: integer argument expected, got float
      Me sale ese error a pesar de haber puesto int() en el argumento que mencionaba el autor del juego
      def actualizar(self, barra1, barra2):
      self.pos[0]+=int(self.velocidad[0])
      self.pos[1]+=int(self.velocidad[1])

      Eliminar

Tu comentario es importante y nos motiva a seguir escribiendo...

Entradas más recientes

© 2014 Mi diario Python. Designed by Bloggertheme9 | Distributed By Gooyaabi Templates
Powered by Blogger.