La Raspberry Pi por consola con curses
Introducción
curses es una librería histórica en el paisaje UNIX. Ir un poco más lejos con la línea de comandos necesita entender el funcionamiento de esta librería que es omnipresente en la mayor parte de los programas existentes en línea de comandos. Escrita en C, esta librería permite diseñar interfaces de consola. Con curses, el desarrollador tiene la posibilidad de crear menús interactivos, cuadros de diálogo o añadir animaciones al texto. Todo esto tiene lugar dentro de la consola. Gracias al éxito de curses, los desarrolladores del lenguaje han decido incluir un módulo para manipular esta librería desde Python. Por lo tanto, curses está disponible en la librería estándar desde Python 2.x.
Los aspectos fundamentales
En primer lugar, un sencillo recordatorio: curses es una librería para crear interfaces interactivas. Debido a su naturaleza, cargar el módulo desde REPL, inspeccionarlo e invocar a las funciones del módulo de manera interactiva, como se ha demostrado en los anteriores capítulos con módulos, no es aconsejable aquí y no funciona, incluso se corre el riesgo de dejar colgado a su terminal. Otra manera de probar una aplicación escrita con este módulo es escribir un script, probarlo y construir la aplicación bloque a bloque.
Para entender cómo funciona el módulo, a continuación se muestra un primer ejemplo que cubre los aspectos básicos hasta llegar gradualmente al tradicional programa Hello world. El programa básico es el siguiente (Capitulo_6/curses_1.py):
1 #!/usr/bin/env python3
2 import curses
3
4 screen = curses.initscr()
5 screen.keypad(1)
6 screen.addch(
7 5,
8 10,
9 "H"
10 )
11 screen.refresh()
12 screen.getch()
13 curses.endwin()
Antes de empezar a trabajar con esta librería, se tiene que inicializar. La primera función que se debe llamar es initscr(), visible en la línea 4, función que se ocupa de crear la pantalla virtual sobre la que vamos a trabajar. Una vez que se ejecuta esta función, devuelve un objeto de tipo WindowObject, elemento principal para escribir en el terminal.
Sin embargo, es necesaria la explicación de algunos conceptos de geometría antes de ir más lejos.
Imagine ahora que el terminal abierto que se muestra en la pantalla conectada a su Raspberry...
Proyecto #1: un menú interactivo
Las especificaciones de esta aplicación son las siguientes: mostrar un menú interactivo que ejecuta una acción en función de la opción del usuario.
La arquitectura de este menú fundamentalmente se hará a través de una clase llamada MenuPi. Como sucedió con el ejemplo anterior, el constructor de la clase recibe como argumento la pantalla virtual inicializada automáticamente cuando la función curses.wrapper() invoca a la clase. El inicio del programa se puede escribir de la siguiente manera:
1 #!/usr/bin/env python3
2 import curses, os
3
4 class MenuPi:
5 def __init__(self, screen):
6 self.pantalla = screen
7 self.nombre_menu = self.__class__.__name__
8 self.pantalla.keypad(1)
9 self.mostrar_opciones()
10 self.pantalla.getch()
curses se configura para interpretar los caracteres introducidos por el teclado a través de la función pantalla.keypad(1). El nombre del menú se copia en el nombre de la clase y se almacena en la variable nombre_menu. La función mostrar_opciones() es responsable de la visualización de las posibles opciones por pantalla y toma forma fundamentalmente gracias a la función addstr(), que se encarga de crear las entradas de menú:
12 def mostrar_opciones(self):
13 self.pantalla.clear()
14 self.pantalla.border(0)
15 self.pantalla.addstr(2, 4, "Bienvenido a
{0} ".format(self.nombre_menu))
16 self.pantalla.addstr(4, 4, "Seleccione una opción entre
[1] y [5]:")
17 self.pantalla.addstr(6, 6, "[1] - Solicitar su nombre y
apellidos y decir hola")
18 self.pantalla.addstr(7, 6, "[2] - Ver la fecha actual")
19 self.pantalla.addstr(8, 6, "[3] - Ver el espacio
disponible en la Raspberry Pi")
20 self.pantalla.addstr(9...
Proyecto #2: una calculadora
Programar una calculadora con curses es relativamente sencillo. Como sucedía en el proyecto anterior, se deben tener en cuenta dos aspectos: el diseño y la lectura de los eventos de teclado.
Empecemos por el primer punto, es decir el aspecto de la calculadora. El inicio del programa se puede escribir de esta manera:
1 #!/usr/bin/env python3
2 import curses, string
3
4 class PiCalc:
5 def __init__(self, screen):
6 self.pantalla = screen
7 self.pantalla.keypad(1)
8 self.dibujar_calc()
9 self.pantalla.getch()
Como sucedía con la aplicación anterior, el código de la calculadora se organiza dentro de una clase llamada PiCalc. La función pintar_calc() gestiona completamente la ubicación de los elementos en la pantalla virtual pantalla. Se articula de la siguiente manera:
11 def pintar_calc(self):
12 self.pantalla.clear()
13 self.pantalla_altura, self.pantalla_anchura =
self.pantalla.getmaxyx()
14
15 self.calculadora_altura = 30
16 self.calculadora_anchura = 60
17
18 self.calculadora = curses.newwin(
19 self.calculadora_altura,
20 self.calculadora_anchura,
21 (self.pantalla_altura // 2) -
(self.calculadora_altura // 2),
22 (self.pantalla_anchura // 2) -
(self.calculadora_anchura // 2)
23 )
24
25 self.calculadora.box()
26 self.pantalla.refresh()
Con el objetivo de imitar la forma de una calculadora en la pantalla, debemos crear una ventana rectangular. La librería está provista de una función que permite crear una o varias ventanas en la pantalla virtual principal: newwin(). Los dos primeros argumentos son el número de puntos...
Proyecto #3: el juego de la serpiente
¿Quién no ha jugado a la serpiente? Este juego apareció en los años 70 para las primeras consolas de videojuegos. En los años 90 volvió a tomar fuerza gracias a la empresa de telecomunicaciones Nokia, porque lo instaló por defecto en todos los teléfonos móviles de la marca, principalmente los célebres modelos 3210 y 3310. Para los que no han conocido estas épocas, el juego de la serpiente consiste en controlar una serpiente y hacer que se mueva en el centro de la pantalla. El objetivo es recoger el máximo número de frutas posible, evitando que la serpiente se muerda la cola. Videojuego imprescindible, a continuación se muestra cómo programar la serpiente con la librería curses, con el objetivo de poder jugar con ayuda del teclado y de la Raspberry Pi, evidentemente.
Para no saltarse la regla habitual, el código del juego se encapsula en una clase llamada PiSerpiente:
1 #!/usr/bin/env python3
2 import curses
3 from curses import KEY_RIGHT, KEY_LEFT, KEY_UP, KEY_DOWN
4 from random import randint
5
6 class PiSerpiente:
7 def __init__(self, screen):
8 self.pantalla = screen
Son necesarias algunas importaciones, principalmente las teclas arriba, abajo, izquierda y derecha que tienen su propia variable declarada dentro de la librería curses. Un poco más adelante en el juego, será necesario generar enteros a partir de un rango y nos será útil la función randint().
Es necesario un mínimo de diseño con el objetivo de entender los elementos necesarios para elaborar el juego. En primer lugar, la serpiente. Las partes de su cuerpo estarán en una lista de dos dimensiones, también llamada matriz y se declara de la siguiente manera:
10 self.serpiente = [[1, 10], [1, 9], [1, 8], [1, 7]]
Cada array se corresponde con una coordenada X e Y, que está destinada a la ventana del juego. Como recordatorio, el índice de un array en Python empieza en 0. De esta manera, serpiente[0] devuelve las coordenadas de la cabeza de la serpiente, serpiente[1] la segunda parte de su cuerpo y así sucesivamente.
La comida que la serpiente debe comer funciona con el mismo principio, es decir, un array que indica las coordenadas:
11 ...
Conclusión
Este capítulo revisa la librería curses a través de tres proyectos diferentes.