Diferencia entre revisiones de «Python»

De Wikitronica
Saltar a: navegación, buscar
(Dibujo)
(Instalación)
 
(No se muestran 51 ediciones intermedias de 2 usuarios)
Línea 1: Línea 1:
 +
== Instalación ==
  
 +
 +
Python tiene muchas versiones, pero una de las más completas se llama Python(x,y). Esta se puede descargar del siguiente enlace.
 +
 +
Ver [https://code.google.com/p/pythonxy/'''Página Oficial de Python(x,y)''']
 +
 +
El archivo de instalación de Python ofrece la posibilidad de incluir gran cantidad de módulos y librerías, hay que poner especial atención al momento de la instalación, de manera que no estemos olvidando ningún paquete importante, como por ejemplo el PySerial.
 +
 +
 +
Además de eso, es necesario instalar el módulo de Pygame, disponible en el siguiente enlace.
 +
 +
Ver [http://www.pygame.org/download.shtml'''Página Oficial de Pygame''']
 +
 +
Este agregado facilita enormemente el desarrollo de interfaces gráficas pues es un paquete de Python especial para el desarrollo de videojuegos.
  
 
== Inicializaciones ==
 
== Inicializaciones ==
Línea 103: Línea 117:
 
==== '' Colores'' ====
 
==== '' Colores'' ====
  
Los colores se basan en el sistema RGB (Red, Green, Blue), y están determinado por un vector de tres coordenadas, donde la primera indica el grado de rojo, la segunda del verde y la tercera del azul. Así, si colocamos 0 en las tres coordenadas se tendrá negro, y si colocamos lo máximo, es decir, 255 ($FF), se tendrá blanco; el resto de los colores se obtiene por mezcla de estas tonalidades.
+
Los colores se basan en el sistema RGB (Red, Green, Blue), y están determinados por un vector de tres coordenadas, donde la primera indica el grado de rojo, la segunda de verde y la tercera de azul. Así, si colocamos 0 en las tres coordenadas se tendrá negro, y si colocamos lo máximo, es decir, 255 ($FF), se tendrá blanco; el resto de los colores se obtiene por mezcla de estas tonalidades.
  
 
* Negro = (0,0,0)
 
* Negro = (0,0,0)
Línea 118: Línea 132:
 
==== '' Dibujo'' ====
 
==== '' Dibujo'' ====
  
Pygame permite dibujar diversas formas geométricas como rectángulos, círculos, elipses, polígonos, líneas, etc; de manera sencilla, utilizando la función draw. La sintaxis de cada una depende de la figura a dibujar, a continuación mostraremos los casos del rectángulo y el círculo:
+
Pygame permite dibujar diversas formas geométricas como rectángulos, círculos, elipses, polígonos, líneas, etc; de manera sencilla, utilizando la función draw. La sintaxis de cada una depende de la figura a dibujar, a continuación mostraremos los casos del rectángulo, círculo y arco:
  
<syntaxhighlightlang="python">
+
<syntaxhighlight lang="python">
  
 +
#rect(Surface, color, Rect, width=0)
 +
#El parametro Rect es un vector de 4 coordenadas en donde se coloca (PosX,PosY,Ancho,Largo)
  
 +
#Creamos un rectangulo blanco en la posicion (20,20) de ancho 100 pixeles y largo 50 pix
 +
rectangulo1=pygame.draw.rect(screen,(255,255,255),(20,20,100,50))
 +
 +
#circle(Surface, color, pos, radius, width=0)
 +
#Creamos un circulo negro de centro (40,40) y radio 15pix
 +
Circulo1=pygame.draw.circle(screen,(0,0,0),(40,40),15)
 +
 +
#arc(Surface, color, Rect, start_angle, stop_angle, width=1) Rect establece al area que llenara el arco
 +
#Se crea un arco azul que empieza en pi y termina en 2pi, el angulo se mide en radianes
 +
Arco1=pygame.draw.arc(screen,(0,0,255),(20,20,100,50),3.1416,3.1416*2)
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
== Eventos de teclado ==
 +
 +
A partir de pygame se puede ver si determinada tecla está presionada de una manera sencilla utilizando los eventos de teclado. Éstos se colocan dentro de un for que "captura" el evento y luego se ve si la tecla (representadas por constantes en pygame) está presionada o no.
 +
 +
<syntaxhighlight lang="python">
 +
for event in pygame.event.get():    #capturo el evento 
 +
    if event.type == pygame.KEYDOWN: #Caso para tecla presionada 
 +
      if event.key== K_a:          #Si la tecla es la letra a
 +
          #realizo cualquier accion
 +
      elif event.key == K_UP:      #Si la tecla es la flecha hacia arriba
 +
          #realizo accion
 +
    elif event.type == pygame.KEYUP: #Caso para teclas levantadas
 +
        #Realizo accion
 +
 +
 +
</syntaxhighlight>
 +
 +
Nótese que el margen es el que establece qué está dentro de cada condicional. Ver el apartado Teclas de la sección de referencias para mayor información sobre las constantes.
 +
 +
Pygame también permite tomar en cuenta los modificadores de teclado como caps lock, numlock, ctrl, etc; esto se ve a través de los KMODS, por ejemplo:
 +
 +
<syntaxhighlight lang="python">
 +
for event in pygame.event.get():    #capturo el evento 
 +
    if event.type == pygame.KEYDOWN: #Caso para tecla presionada       
 +
        if pygame.key.get_mods() & KMOD_SHIFT: #Si la tecla shift esta presionada
 +
            #realizo cualquier accion
 +
 +
</syntaxhighlight>
 +
 +
La siguiente figura corresponde a un [https://www.dropbox.com/s/gc611uhj2c60ri8/Ejemplo%20wikitronica.txt'''ejemplo'''] de los puntos 1, 2 y 3
 +
 +
[[Image:Ejemplo wikitronica.png|350px|center|thumb|Ejemplo de los puntos 1, 2 y 3]]
 +
 +
 +
 +
 +
 +
== Programación Orientada a Objetos ==
 +
 +
 +
Python puede funcionar con programación orientada a objetos, de forma similar a como lo hace JAVA. En este tipo de programación se definen una clases, que son análogas a las structuras en C, salvo que dichas clases incluyen además ciertas operaciones (funciones) que puede ejecutar el objeto. Esto quiere, a muy groso modo, lo siguiente:
 +
 +
 +
* Uno puede definir tipos de objetos llamados clases. Por ejemplo: las clases de los círculos, los perros, etc.
 +
* Estas clases tienen atributos propios de sí. Por ejemplo: los círculos tienen radio, centro, color, etc.
 +
* Las clases incluyen funciones, que son operaciones que pueden realizar en un determinado momento. Por ejemplo: un círculo puede aparecer en pantalla, moverse, etc.
 +
* Las clases pueden generar varios objetos, que son especies de variables de un determinado tipo de dato, salvo por que incluyen las funciones ya mencionadas.
 +
* Si se genera más de un objeto de una determinada clase, ambos objetos serán en esencia idénticos a menos que utilicemos un constructor para diferenciarlos.
 +
* Un constructor es una función que inicializa los parámetros de nuestro objeto y que permite distinguirlo de los demás dándole un nombre y características distintas.
 +
* Una determinada clase puede tener más de un constructor si es necesario.
 +
 +
 +
=== ''Definición de una Clase'' ===
 +
 +
Ahora veamos más en detalle cada una de las partes de una definición de clase:
 +
Lo primero que debemos hacer es colocar la etiqueta "class" seguida del nombre que le queremos colocar a nuestra clase, lo segundo es declarar el inicializador (constructor) con los campos que tendrá. Este constructor es una función llamada "__init__" que recibe al propio objeto "__init__(self)" y a toda una serie de parámetros que le colocamos a nuestro objeto. En este caso, además del propio objeto, tenemos como elementos: la posición (x,y) el radio (size), el color, y el espesor. Para este constructor en particular, si se crea el objeto, puede no especificársele ni el color ni el espesor, ya que tienen valores por defecto, sin embargo, todos los demás datos deben ser indicados para cada objeto de la clase.
 +
 +
<syntaxhighlight lang="python">
 +
#Creacion de la clase circulo
 +
 +
class Circulo:
 +
 +
    def __init__(self, x, y, size, color = (255,255,255), width=1):
 +
          self.x = x
 +
          self.y = y
 +
          self.size = size
 +
          self.color = color
 +
          self.width = width
 +
</syntaxhighlight>
 +
 +
Definida la clase del ejemplo, las siguientes son llamadas posibles para crear objetos
 +
 +
<syntaxhighlight lang="python">
 +
#Creacion de objetos de clase circulo
 +
    mi_circulo1 = Circulo(100, 100, 30, (255,0,0), 0) #Crea un circulo con centro en (100,100) radio 30, color rojo y espesor=0 (completamente relleno)
 +
    mi_circulo2 = Circulo(300, 200, 50)              #Crea un circulo con centro en (300,200) radio 50, color blanco y espesor = 1
 +
    mi_circulo3 = Circulo(300, 500, 60, (0,0,255))    #Crea un circulo con centro en (300,500) radio 60, color azul y espesor = 1
 +
 +
</syntaxhighlight>
 +
 +
Sin embargo, un objeto es algo vacío si no tiene asociadas las acciones que este puede hacer. La siguiente versión muestra la clase Círculo, esta vez con una acción que le permite aparecer en pantalla; la función display. Nótese que esta acción tiene una única instrucción que llama a pygame.draw.circle, pero la cantidad de instrucciones que puede tener cada acción y la cantidad de acciones por clase no es limitada.
 +
 +
<syntaxhighlight lang="python">
 +
#Creacion de la clase circulo con funciones
 +
 +
class Circulo:
 +
 +
    def __init__(self, x, y, size, color = (255,255,255), width=1):
 +
          self.x = x
 +
          self.y = y
 +
          self.size = size
 +
          self.color = color
 +
          self.width = width
 +
 +
    def display(self):
 +
          pygame.draw.circle(screen, self.color, (self.x, self.y), self.size, self.width)
 +
</syntaxhighlight>
 +
 +
Declarada esta variante de la clase, pueden crearse objetos circulos que, en cualquier parte del programa, pueden llamarse a aparecer en pantalla mediante la instrucción
 +
 +
<syntaxhighlight lang="python">
 +
#Llamada de la funcion display para un determinado circulo
 +
    mi_circulo1.display()
 +
    mi_circulo3.display()
 +
</syntaxhighlight>
 +
 +
 +
=== ''Ejemplo completo de utilización de Clases '' ===
 +
 +
Este ejemplo utiliza la clase círculo ya explicada en el apartado anterior, crea objetos de esta clase y los muestra por pantalla. Preste atención a la manera adecuada de utilizar las clases dentro de un programa completo y estructurado.
 +
 +
<syntaxhighlight lang="python">
 +
import os, sys, math, pygame
 +
from pygame.locals import *
 +
 +
#Definir Colores
 +
negro = 0, 0, 0
 +
blanco = 255, 255, 255
 +
rojo = 255, 0, 0
 +
verde = 0, 255, 0
 +
azul = 0, 0, 255
 +
 +
#Preparar el Screen
 +
screen = pygame.display.set_mode((800, 600))
 +
 +
#Definicion de la clase circulo
 +
class Circulo:
 +
 +
    def __init__(self, (x,y), size, color=(255,255,255), width=1):
 +
          self.x = x
 +
          self.y = y
 +
          self.size = size
 +
          self.color = color
 +
          self.width = width
 +
 +
    def display(self):
 +
          pygame.draw.circle(screen, self.color, (self.x, self.y), self.size,self.width)
 +
 +
#Creacion de objetos
 +
circulo1 = Circulo((100,100), 30, azul, 0)
 +
circulo2 = Circulo((200,300), 40, verde, 8)
 +
circulo3 = Circulo((600,500), 20)
 +
circulo4 = Circulo((700,300), 50,rojo,4)
 +
 +
#Generar Reloj
 +
clock = pygame.time.Clock()
 +
 +
#Ciclo continuo del programa
 +
fps = 30   
 +
correr = True
 +
 +
while correr:
 +
    clock.tick(fps)
 +
          for event in pygame.event.get():
 +
              if event.type == pygame.QUIT:
 +
                    correr = False
 +
 +
    screen.fill(negro)
 +
    circulo1.display()
 +
    circulo2.display()
 +
    circulo3.display()
 +
    circulo4.display()
 +
    pygame.display.flip()
 +
 +
pygame.quit()
 +
sys.exit()
 +
</syntaxhighlight>
 +
 +
Si se realiza la corrida de este programa, puede verse en pantalla el siguiente resultado:
 +
 +
[[Image:Ejemplo_de_Clases_en_Python.jpg|350px|center|thumb|Ejemplo de implementación de la clase círculo]]
 +
 +
 +
 +
== Animaciones ==
 +
 +
Antes de leer este apartado se recomienda enormemente que lea primero el de programación orientada a objetos.
 +
 +
 +
Python presenta muchas ventajas con respecto a otros lenguajes de programación, pero quizás uno de sus puntos más fuertes es la facilidad con la que permite realizar animaciones. Para esto se podría simplemente pedir al programa que dibuje una secuencia determinada de imágenes a una cierta velocidad, por ejemplo 30 FPS. Sin embargo, esto requiere una gran cantidad de imágenes y existen formas mucho más prácticas de animar objetos, como la que explicaremos a continuación.
 +
 +
 +
Antes que nada se requiere una librería llama Pyeuclid que incluye ya prefabricadas una gran cantidad de funciones de gran utilidad, esta librería se puede obtener aquí: [https://code.google.com/p/pyeuclid/'''Acceso a Pyeuclid''']
 +
En los vínculos externos seleccionamos euclid.py y se nos despliega una página con todo el contenido del archivo. Este contenido lo debemos guardar en un archivo de extensión ".py" usando por ejemplo notepad o notepad++ y lo colocamos en el mismo directorio del programa de animaciones en el que estamos trabajando.
 +
 +
 +
Hecho esto podemos comenzar a trabajar importando el archivo y creando las variables y clases necesarias, pero en esta oportunidad queremos que nuestra clase tenga una función asociada que le permita desplazarse "Ciculo.move()". El siguiente ejemplo muestra un programa que genera 5 círculos de manera aleatoria y deja que estos se muevan por la pantalla también de manera aleatoria. Cómo se generan los números aleatorios para crear los circulos o para decidir su movimiento no es de tanta importancia como lo es el fenómeno de generación de animaciones en Python, así que cuando lo lea no preste demasiada atención a esos detalles:
 +
 +
[[Ejemplo de Animaciones en Python]]
 +
 +
 +
Este es un pequeño extracto del ejemplo colocado en el link de arriba, que contiene las especificaciones sobre la creación de clases y las funciones agenas a la clase pero necesarias para el funcionamiento del programa. Básicamente, lo que se hace es modificar la velocidad al azar, utilizando "get_random_velocity()" y "change_velocity()". Más importante aún se utiliza la funcion move(), que reposiciona al circulo, sumándole a su posicion actual su velocidad multiplicada por un diferencial de tiempo. 
 +
 +
<syntaxhighlight lang="python">
 +
#Creo la clase circulo, en este caso position es un vector que resume las coordenadas (x,y) y Vector2 es un vector que pertenece a pyeuclide
 +
class Circulo:
 +
    def __init__(self, position, size, color = (255,255,255), velocity= eucly.Vector2(0,0), width=1):
 +
        self.position = position
 +
        self.size = size
 +
        self.color = color
 +
        self.width = width
 +
        self.velocity = velocity
 +
 +
    #Esta es una variante de la funcion Display ya vista, que descompone primero las coordenadas de position en rx y ry
 +
    def display(self):
 +
        rx, ry = int(self.position.x), int(self.position.y)
 +
        pygame.draw.circle(screen, self.color, (rx, ry), self.size, self.width)
 +
 +
    #Esta es una funcion de movimiento que reescribe la posicion final con la inicial mas la velocidad por tiempo
 +
    def move(self):
 +
        self.position = self.position + dtime * self.velocity
 +
 +
    #Esta es una funcion que permite cambiar la velocidad de el objeto
 +
    def change_velocity(self,velocidad):
 +
        self.velocity = velocity
 +
 +
#Esta funcion no pertenece a la clase, pero genera un vector de velocidad al azar.       
 +
def get_random_velocity():
 +
    new_angle = random.uniform(0, math.pi*2)
 +
    new_x = math.sin(new_angle)
 +
    new_y = math.cos(new_angle)
 +
    new_vector = eucly.Vector2(new_x,new_y)
 +
    new_vector.normalize()
 +
    new_vector *= velocidad_inicial
 +
    return new_vector
 +
</syntaxhighlight>
 +
 +
 +
Por último pueden observar los videotutoriales en el apartado de referencias, son de gran utilidad para entender y profundizar en esta parte.
 +
  
 
== Pyserial ==
 
== Pyserial ==
Línea 138: Línea 395:
 
import serial                        #Importa modulo para comunicacion serial
 
import serial                        #Importa modulo para comunicacion serial
 
ser = serial.Serial('COM10',9600)      #Abre el puerto COM1 y lo configura para transmitir a 9600baud
 
ser = serial.Serial('COM10',9600)      #Abre el puerto COM1 y lo configura para transmitir a 9600baud
 
  
 
</syntaxhighlight>
 
</syntaxhighlight>
Línea 157: Línea 413:
  
 
# Para Lectura a través de serial
 
# Para Lectura a través de serial
 
 
x = ser.read()      # Capturar un byte por serial y almacenarlo en X
 
x = ser.read()      # Capturar un byte por serial y almacenarlo en X
 
s = ser.read(10)    # Capturar hasta 10 bytes y almacenarlos en S
 
s = ser.read(10)    # Capturar hasta 10 bytes y almacenarlos en S
Línea 163: Línea 418:
  
 
# Para Escritura a través de serial
 
# Para Escritura a través de serial
 
 
ser.write("hello")  # Envia por puerto serial la cadena de caracteres o el caracter escritos
 
ser.write("hello")  # Envia por puerto serial la cadena de caracteres o el caracter escritos
  
Línea 175: Línea 429:
 
*[http://www.pygame.org/docs/ref/image.html'''Images.''' ''Pygame'']
 
*[http://www.pygame.org/docs/ref/image.html'''Images.''' ''Pygame'']
 
*[http://www.pygame.org/docs/ref/music.html'''Audio.''' ''Pygame'']
 
*[http://www.pygame.org/docs/ref/music.html'''Audio.''' ''Pygame'']
 +
*[http://www.pygame.org/docs/ref/draw.html'''Draw''' ''Pygame'']
 +
*[http://www.pygame.org/docs/ref/key.html'''Teclas''' ''Pygame'']
 +
*[http://www.youtube.com/watch?v=7AKatTpNSNQ&list=PLE3D1A71BB598FEF6'''Clases y Animaciones''' ''Pygame'']

Revisión actual del 20:42 28 abr 2013

Instalación

Python tiene muchas versiones, pero una de las más completas se llama Python(x,y). Esta se puede descargar del siguiente enlace.

Ver Página Oficial de Python(x,y)

El archivo de instalación de Python ofrece la posibilidad de incluir gran cantidad de módulos y librerías, hay que poner especial atención al momento de la instalación, de manera que no estemos olvidando ningún paquete importante, como por ejemplo el PySerial.


Además de eso, es necesario instalar el módulo de Pygame, disponible en el siguiente enlace.

Ver Página Oficial de Pygame

Este agregado facilita enormemente el desarrollo de interfaces gráficas pues es un paquete de Python especial para el desarrollo de videojuegos.

Inicializaciones

Módulos

Los módulos son archivos que contienen las definiciones y argumentos utilizados en Python, por lo que se debe comenzar el programa importando los que necesitemos, esto se realiza a través del comando import. Algunos módulos son standard, como sys, mientras que otros dependen de lo que se quiera realizar, como pygame o serial.

Además, se pueden importar archivos .py que contengan definiciones o funciones que deseemos utilizar en nuestro programa, y, de esta manera, un programa muy largo se puede fragmentar en varios archivos distintos.

Por ejemplo, un modelo de inicialización de módulos sería:

import sys, pygame       #Importa modulo pygame
from pygame.locals import *
import serial            #Importa modulo para comunicacion serial

El * colocado importa todas las definiciones menos aquellas que comiencen por guión bajo (_).

Si se desea utilizar pygame, se debe iniciar utilizando pygame.init() en la función principal.

Imágenes y audio

Para utilizar imágenes o audio en el programa (utilizando pygame), primero los archivos deben estar en la misma carpeta del proyecto, luego se deben cargar empleando:

#Para cargar imagenes
foto = pygame.image.load("foto.jpg")

#Para cargar y reproducir audio:
loops = -1     #Cantidad de veces que se repetira la cancion, -1 significa que siempre se repite
start = 0.0    #Determina el tiempo en el que empezara la pieza
pygame.mixer.music.load("cancion.mp3")
pygame.mixer.music.play(loops,start)

#Para dejar de reproducir audio:
pygame.mixer.music.stop()

Los formatos de imagen permitidos por pygame son:

  • JPG
  • PNG
  • GIF (Inanimada)
  • BMP
  • PCX
  • TGA (Sin comprimir)
  • TIF
  • LBM
  • PBM, PGM, PPM
  • XPM

Pantalla

Para configurar las características de la ventana, es decir, su tamaño, el nombre, y la imagen de fondo, se puede proceder como sigue:

#Esta es la funcion principal mencionada previamente

def main():
  
  pygame.init()                                     #Inicio Pygame
  screen = pygame.display.set_mode((1024, 720))     #Crea una ventana de 1024 de ancho por 720 de alto de nombre screen       
  pygame.display.set_caption("Python-Wikitronica")  #Nombre de la ventana (esquina superior izquierda)  
  fondo = pygame.image.load("Fondo.jpg")            #Cargo la imagen de fondo  
  screen.blit(fondo, (0, 0))                        #la dibujo en "screen", en la posicion (0,0)
  pygame.display.flip()                             #Actualizo toda la superficie de la pantalla

Para mejores resultados, hacer la imagen de fondo del mismo tamaño de la pantalla. Y nótese, que se debe mantener el margen en todas las líneas de código porque sino se tendrá el error "IndentationError: unexpected indent"

Escritura y dibujo

Escritura

Para escribir en pantalla, se procede de una manera similar a mostrar una imagen. Primero, se debe determinar la fuente con la cual se escribirá, luego se escribe el mensaje y se muestra en pantalla. Esto se puede realizar de la siguiente forma:

#Opcion 1 para seleccionar la fuente
fuente = pygame.font.Font(None, 25)  #None es el tipo de letra default. 25 es el tamaño de la letra
# Para esta opcion, si se quiere usar una fuente distinta, el archivo debe estar en la misma carpeta del programa y se coloca:
fuente2 = pygame.font.Font("Nombredefuente.ttf", 25)

#Opcion 2
print pygame.font.get_fonts()              #Con este comando se ven todas las fuentes que se tienen instaladas en el sistema
fuente3 = pygame.font.SysFont('arial', 25) #Se coloca cualquiera de esas fuentes

#Se le asigna un mensaje a una variable
texto = "Programa de prueba. Python-Wikitronica"

#Font.render(text, antialias, color, background=None)
mensaje = fuente.render(texto, 1, (0, 0, 0))       #Se escriben en color negro, con el tipo de letra de la variable fuente.
                                                   #background=None (No se pone ningun color de fondo)
#Se muestra en pantalla
SCREEN.blit(mensaje, (400, 400))    #Se muestra en la posición (400,400)
pygame.display.flip()               #Actualizo toda la superficie de la pantalla

Colores

Los colores se basan en el sistema RGB (Red, Green, Blue), y están determinados por un vector de tres coordenadas, donde la primera indica el grado de rojo, la segunda de verde y la tercera de azul. Así, si colocamos 0 en las tres coordenadas se tendrá negro, y si colocamos lo máximo, es decir, 255 ($FF), se tendrá blanco; el resto de los colores se obtiene por mezcla de estas tonalidades.

  • Negro = (0,0,0)
  • Blanco = (255,255,255)
  • Rojo = (255,0,0)
  • Verde = (0,255,0)
  • Azul = (0,0,255)
  • Amarillo = (255,255,0)
  • Magenta =(255,0,255)
  • Cian=(0,255,255)

Ver Tabla de colores para mayor información

Dibujo

Pygame permite dibujar diversas formas geométricas como rectángulos, círculos, elipses, polígonos, líneas, etc; de manera sencilla, utilizando la función draw. La sintaxis de cada una depende de la figura a dibujar, a continuación mostraremos los casos del rectángulo, círculo y arco:

#rect(Surface, color, Rect, width=0)
#El parametro Rect es un vector de 4 coordenadas en donde se coloca (PosX,PosY,Ancho,Largo)

#Creamos un rectangulo blanco en la posicion (20,20) de ancho 100 pixeles y largo 50 pix
rectangulo1=pygame.draw.rect(screen,(255,255,255),(20,20,100,50))

#circle(Surface, color, pos, radius, width=0)
#Creamos un circulo negro de centro (40,40) y radio 15pix
Circulo1=pygame.draw.circle(screen,(0,0,0),(40,40),15)

#arc(Surface, color, Rect, start_angle, stop_angle, width=1) Rect establece al area que llenara el arco
#Se crea un arco azul que empieza en pi y termina en 2pi, el angulo se mide en radianes
Arco1=pygame.draw.arc(screen,(0,0,255),(20,20,100,50),3.1416,3.1416*2)

Eventos de teclado

A partir de pygame se puede ver si determinada tecla está presionada de una manera sencilla utilizando los eventos de teclado. Éstos se colocan dentro de un for que "captura" el evento y luego se ve si la tecla (representadas por constantes en pygame) está presionada o no.

for event in pygame.event.get():     #capturo el evento   
    if event.type == pygame.KEYDOWN: #Caso para tecla presionada  
       if event.key== K_a:           #Si la tecla es la letra a
           #realizo cualquier accion
       elif event.key == K_UP:       #Si la tecla es la flecha hacia arriba
           #realizo accion
    elif event.type == pygame.KEYUP: #Caso para teclas levantadas
        #Realizo accion

Nótese que el margen es el que establece qué está dentro de cada condicional. Ver el apartado Teclas de la sección de referencias para mayor información sobre las constantes.

Pygame también permite tomar en cuenta los modificadores de teclado como caps lock, numlock, ctrl, etc; esto se ve a través de los KMODS, por ejemplo:

for event in pygame.event.get():     #capturo el evento   
    if event.type == pygame.KEYDOWN: #Caso para tecla presionada        
         if pygame.key.get_mods() & KMOD_SHIFT: #Si la tecla shift esta presionada
             #realizo cualquier accion

La siguiente figura corresponde a un ejemplo de los puntos 1, 2 y 3

Ejemplo de los puntos 1, 2 y 3



Programación Orientada a Objetos

Python puede funcionar con programación orientada a objetos, de forma similar a como lo hace JAVA. En este tipo de programación se definen una clases, que son análogas a las structuras en C, salvo que dichas clases incluyen además ciertas operaciones (funciones) que puede ejecutar el objeto. Esto quiere, a muy groso modo, lo siguiente:


  • Uno puede definir tipos de objetos llamados clases. Por ejemplo: las clases de los círculos, los perros, etc.
  • Estas clases tienen atributos propios de sí. Por ejemplo: los círculos tienen radio, centro, color, etc.
  • Las clases incluyen funciones, que son operaciones que pueden realizar en un determinado momento. Por ejemplo: un círculo puede aparecer en pantalla, moverse, etc.
  • Las clases pueden generar varios objetos, que son especies de variables de un determinado tipo de dato, salvo por que incluyen las funciones ya mencionadas.
  • Si se genera más de un objeto de una determinada clase, ambos objetos serán en esencia idénticos a menos que utilicemos un constructor para diferenciarlos.
  • Un constructor es una función que inicializa los parámetros de nuestro objeto y que permite distinguirlo de los demás dándole un nombre y características distintas.
  • Una determinada clase puede tener más de un constructor si es necesario.


Definición de una Clase

Ahora veamos más en detalle cada una de las partes de una definición de clase: Lo primero que debemos hacer es colocar la etiqueta "class" seguida del nombre que le queremos colocar a nuestra clase, lo segundo es declarar el inicializador (constructor) con los campos que tendrá. Este constructor es una función llamada "__init__" que recibe al propio objeto "__init__(self)" y a toda una serie de parámetros que le colocamos a nuestro objeto. En este caso, además del propio objeto, tenemos como elementos: la posición (x,y) el radio (size), el color, y el espesor. Para este constructor en particular, si se crea el objeto, puede no especificársele ni el color ni el espesor, ya que tienen valores por defecto, sin embargo, todos los demás datos deben ser indicados para cada objeto de la clase.

#Creacion de la clase circulo

class Circulo:

     def __init__(self, x, y, size, color = (255,255,255), width=1):
          self.x = x
          self.y = y
          self.size = size
          self.color = color
          self.width = width

Definida la clase del ejemplo, las siguientes son llamadas posibles para crear objetos

#Creacion de objetos de clase circulo
     mi_circulo1 = Circulo(100, 100, 30, (255,0,0), 0) #Crea un circulo con centro en (100,100) radio 30, color rojo y espesor=0 (completamente relleno)
     mi_circulo2 = Circulo(300, 200, 50)               #Crea un circulo con centro en (300,200) radio 50, color blanco y espesor = 1
     mi_circulo3 = Circulo(300, 500, 60, (0,0,255))    #Crea un circulo con centro en (300,500) radio 60, color azul y espesor = 1

Sin embargo, un objeto es algo vacío si no tiene asociadas las acciones que este puede hacer. La siguiente versión muestra la clase Círculo, esta vez con una acción que le permite aparecer en pantalla; la función display. Nótese que esta acción tiene una única instrucción que llama a pygame.draw.circle, pero la cantidad de instrucciones que puede tener cada acción y la cantidad de acciones por clase no es limitada.

#Creacion de la clase circulo con funciones

class Circulo:

     def __init__(self, x, y, size, color = (255,255,255), width=1):
          self.x = x
          self.y = y
          self.size = size
          self.color = color
          self.width = width

     def display(self):
          pygame.draw.circle(screen, self.color, (self.x, self.y), self.size, self.width)

Declarada esta variante de la clase, pueden crearse objetos circulos que, en cualquier parte del programa, pueden llamarse a aparecer en pantalla mediante la instrucción

#Llamada de la funcion display para un determinado circulo
     mi_circulo1.display()
     mi_circulo3.display()


Ejemplo completo de utilización de Clases

Este ejemplo utiliza la clase círculo ya explicada en el apartado anterior, crea objetos de esta clase y los muestra por pantalla. Preste atención a la manera adecuada de utilizar las clases dentro de un programa completo y estructurado.

import os, sys, math, pygame
from pygame.locals import *

#Definir Colores
negro = 0, 0, 0
blanco = 255, 255, 255
rojo = 255, 0, 0
verde = 0, 255, 0
azul = 0, 0, 255

#Preparar el Screen
screen = pygame.display.set_mode((800, 600))

#Definicion de la clase circulo
class Circulo:

     def __init__(self, (x,y), size, color=(255,255,255), width=1):
          self.x = x
          self.y = y
          self.size = size
          self.color = color
          self.width = width

     def display(self):
          pygame.draw.circle(screen, self.color, (self.x, self.y), self.size,self.width)

#Creacion de objetos
circulo1 = Circulo((100,100), 30, azul, 0)
circulo2 = Circulo((200,300), 40, verde, 8)
circulo3 = Circulo((600,500), 20)
circulo4 = Circulo((700,300), 50,rojo,4)

#Generar Reloj
clock = pygame.time.Clock()

#Ciclo continuo del programa
fps = 30     
correr = True

while correr:
     clock.tick(fps)
          for event in pygame.event.get():
               if event.type == pygame.QUIT:
                    correr = False

     screen.fill(negro)
     circulo1.display()
     circulo2.display()
     circulo3.display()
     circulo4.display()
     pygame.display.flip()

pygame.quit()
sys.exit()

Si se realiza la corrida de este programa, puede verse en pantalla el siguiente resultado:

Ejemplo de implementación de la clase círculo


Animaciones

Antes de leer este apartado se recomienda enormemente que lea primero el de programación orientada a objetos.


Python presenta muchas ventajas con respecto a otros lenguajes de programación, pero quizás uno de sus puntos más fuertes es la facilidad con la que permite realizar animaciones. Para esto se podría simplemente pedir al programa que dibuje una secuencia determinada de imágenes a una cierta velocidad, por ejemplo 30 FPS. Sin embargo, esto requiere una gran cantidad de imágenes y existen formas mucho más prácticas de animar objetos, como la que explicaremos a continuación.


Antes que nada se requiere una librería llama Pyeuclid que incluye ya prefabricadas una gran cantidad de funciones de gran utilidad, esta librería se puede obtener aquí: Acceso a Pyeuclid En los vínculos externos seleccionamos euclid.py y se nos despliega una página con todo el contenido del archivo. Este contenido lo debemos guardar en un archivo de extensión ".py" usando por ejemplo notepad o notepad++ y lo colocamos en el mismo directorio del programa de animaciones en el que estamos trabajando.


Hecho esto podemos comenzar a trabajar importando el archivo y creando las variables y clases necesarias, pero en esta oportunidad queremos que nuestra clase tenga una función asociada que le permita desplazarse "Ciculo.move()". El siguiente ejemplo muestra un programa que genera 5 círculos de manera aleatoria y deja que estos se muevan por la pantalla también de manera aleatoria. Cómo se generan los números aleatorios para crear los circulos o para decidir su movimiento no es de tanta importancia como lo es el fenómeno de generación de animaciones en Python, así que cuando lo lea no preste demasiada atención a esos detalles:

Ejemplo de Animaciones en Python


Este es un pequeño extracto del ejemplo colocado en el link de arriba, que contiene las especificaciones sobre la creación de clases y las funciones agenas a la clase pero necesarias para el funcionamiento del programa. Básicamente, lo que se hace es modificar la velocidad al azar, utilizando "get_random_velocity()" y "change_velocity()". Más importante aún se utiliza la funcion move(), que reposiciona al circulo, sumándole a su posicion actual su velocidad multiplicada por un diferencial de tiempo.

#Creo la clase circulo, en este caso position es un vector que resume las coordenadas (x,y) y Vector2 es un vector que pertenece a pyeuclide
class Circulo:
    def __init__(self, position, size, color = (255,255,255), velocity= eucly.Vector2(0,0), width=1):
        self.position = position
        self.size = size
        self.color = color
        self.width = width
        self.velocity = velocity

    #Esta es una variante de la funcion Display ya vista, que descompone primero las coordenadas de position en rx y ry	
    def display(self):
        rx, ry = int(self.position.x), int(self.position.y)
        pygame.draw.circle(screen, self.color, (rx, ry), self.size, self.width)

    #Esta es una funcion de movimiento que reescribe la posicion final con la inicial mas la velocidad por tiempo	
    def move(self):
        self.position = self.position + dtime * self.velocity

    #Esta es una funcion que permite cambiar la velocidad de el objeto	
    def change_velocity(self,velocidad):
        self.velocity = velocity

#Esta funcion no pertenece a la clase, pero genera un vector de velocidad al azar.        
def get_random_velocity():
    new_angle = random.uniform(0, math.pi*2)
    new_x = math.sin(new_angle)
    new_y = math.cos(new_angle)
    new_vector = eucly.Vector2(new_x,new_y)
    new_vector.normalize()
    new_vector *= velocidad_inicial
    return new_vector


Por último pueden observar los videotutoriales en el apartado de referencias, son de gran utilidad para entender y profundizar en esta parte.


Pyserial

Un módulo de interés al utilizar Python(x,y) combinado con nuestro microcontrolador es Pyserial.

Pyserial es muy amigable y fácil de utilizar pues los grandes conjuntos de instrucciones utilizados para la transmisión y recepción de información a los que estamos acostumbrados se resumen en funciones muy sencillas de manejar.

Al trabajar con puerto serial en Python lo primero que se debe hacer es importar la librería de serial, luego abrir el o los puertos y configurarlos a la velocidad de transmisión deseada. A continuación se muestra un ejemplo de como hacer esto:

import serial                         #Importa modulo para comunicacion serial
ser = serial.Serial('COM10',9600)      #Abre el puerto COM1 y lo configura para transmitir a 9600baud

Es importante saber que puerto es el que deseamos abrir, y la manera de identificarlo es buscándo a través del administrador de dispositivos (Device Manager) ubicado en el panel de control. La siguiente imágen busca ilustrar un poco como conseguir esta información:


Buscar Información Sobre El Puerto Serial



Una vez inicializado el puerto de manera correcta, las rutinas de transmisión y recepción son bien sencillas:


# Para Lectura a través de serial
x = ser.read()       # Capturar un byte por serial y almacenarlo en X
s = ser.read(10)     # Capturar hasta 10 bytes y almacenarlos en S


# Para Escritura a través de serial
ser.write("hello")   # Envia por puerto serial la cadena de caracteres o el caracter escritos


Referencias

Contributors

Anny, GMarzinotto