Jogando Snake Game usando Raspberry Pi Game Pad – (Parte 38/38)

Jugar al juego Snake usando Raspberry Pi Game Pad – (Parte 38/38)

Este artículo trata sobre cómo desarrollar un hardware de gamepad simple y una interfaz con la placa Raspberrypi y también sobre la técnica de interconectar un código de juego escrito en HTML5 con el gamepad . Aquí se ha modificado un juego de serpientes escrito en HTML5 y JavaScript para que se pueda jugar con el nuevo mando de cuatro botones. En este proyecto se utilizan técnicas de señal, tubería, bifurcación, etc.

El juego Snake que se ejecuta en una ventana del navegador forma la GUI o interfaz de todo el sistema. En un sistema operativo Linux, cada dispositivo de hardware se representa como un archivo. El dispositivo se puede controlar simplemente leyendo y escribiendo en este archivo. El hardware de un sistema operativo está en un lado y el usuario que intenta acceder al hardware está en el otro lado, y en el medio puede haber varias capas de procesos en ejecución que se comunican entre sí mediante métodos de comunicación entre procesos. En este proyecto hay un gamepad que es el hardware y hay un proceso que lee el gamepad y también hay un archivo Pipe o FIFO entre el juego y el proceso de lectura del gamepad.

((wysiwyg_imageupload:11011:))

El juego se ejecuta en una ventana del navegador y se comunica con el panel de juego a través de un Named Pipe o FIFO. Hay varios procesos en ejecución que pueden leer el panel de juego y escribir los comandos necesarios en el FIFO para controlar el juego. El JavaScript escrito en el código del juego simplemente lee el FIFO para ingresar datos de control.

Diagrama de blocos do gamepad Raspberry pi

Fig. 2: Diagrama de bloques del gamepad Raspberry Pi

El proceso principal aquí crea cuatro procesos secundarios que están dedicados a cada una de las teclas del gamepad. Cada vez que se presiona o suelta una tecla, generan una señal y la envían al proceso principal con un valor. Con este método, el proceso principal puede identificar qué tecla se presionó o soltó.
Tan pronto como el proceso principal detecta una pulsación de tecla del valor recibido junto con la señal, simplemente escribe un valor de comando específico en NAMED PIPE o FIFO. El juego HTML leerá continuamente el FIFO cada 100 ms y cambiará la dirección de la serpiente de acuerdo con el comando de lectura.
La siguiente parte de JavaScript lee el archivo cada 100 ms y cambia la dirección del movimiento de la serpiente en el juego.
//++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++//
función cargar archivo
{
lector = nuevo XMLHttpRequest nuevo ActiveXObject('MSXML2.XMLHTTP');
lector.open('get', 'xyz', verdadero);
lector.onreadystatechange=mostrar contenido;
lector.enviar (nulo);
}
función mostrar contenido
{
ch = lector.responseText(0);
si(ch == 'yo')
título = (título == ESTE)? ESTE OESTE;
de lo contrario si (ch == 'r')
rumbo = (título == OESTE)? OESTE-ESTE;
de lo contrario si (ch == 'u')
rumbo = (título == SUR)? SUR NORTE;
de lo contrario si (ch == 'd')
rumbo = (título == NORTE)? NORTE SUR;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++//
Las funciones utilizadas en la codificación del código del Gamepad para escribir operaciones en el FIFO se explican en la siguiente sección.
El FIFO debe crearse usando el siguiente comando en el mismo directorio donde existen el ejecutable del gamepad y los archivos HTML del juego.
mkfifo xyz
FIFO también se puede crear utilizando el propio código añadiendo la función abierta mkfifo como se explica en una documentación anterior .
El usuario puede escribir datos en el archivo temporal desde el propio terminal utilizando el comando 'echo' como se muestra en el siguiente ejemplo.
eco abcdef >> /tmp/mi_fifo
El proceso de escritura FIFO principal está escrito de tal manera que escribirá comandos en el FIFO en respuesta a las señales recibidas del proceso secundario. Los comandos que se escribirán en el FIFO para controlar la dirección de la serpiente se enumeran a continuación;
tú -> Serpiente
d -> Serpiente hacia abajo
l -> Serpiente izquierda
r -> Cobra DERECHA
Estos comandos se pueden escribir en FIFO con la ayuda de la función del sistema.
sistema(“eco r >> xyz );
La llamada a la función anterior girará a Snake hacia la derecha.

Código fuente del proyecto

###

 #incluir <bcm2835.h>
 #incluir <pthread.h>
 #incluir <unistd.h>
 #incluir <señal.h>
 #incluir <sys/time.h>
 #incluir <stdlib.h>
 #incluir <sys/types.h>
 #incluir <sys/stat.h>
 #incluir <fcntl.h>

#definir IN_PIN1 RPI_GPIO_P1_07
#definir IN_PIN2 RPI_GPIO_P1_22
#definir IN_PIN3 RPI_GPIO_P1_18
#definir IN_PIN4 RPI_GPIO_P1_16

#definir OUT_PIN1 RPI_GPIO_P1_15
#definir OUT_PIN2 RPI_V2_GPIO_P1_13
#definir OUT_PIN3 RPI_GPIO_P1_12
#definir OUT_PIN4 RPI_GPIO_P1_11

#define SNAKE_FIFO_NAME "xyz"

set_pins_input vacío (nulo);
vacío set_pins_output(vacío);
vacío set_output_pins_low(vacío);

void button_signal_handler (int sig, siginfo_t *siginfo, void *context);
señal vacía_on_state_change_pin1 (vacío);
señal vacía_on_state_change_pin2 (vacío);
señal vacía_on_state_change_pin3 (nulo);
señal vacía_on_state_change_pin4 (nulo);
void sig_set_handler (señal int, void *handler);
void sig_send_val (id_pid_t, signo int, valor int);

pid_t hijo_id(5);
punto interno = 0;

int principal (nulo)
{
ent i;
int cobra_fifo = -1;

si (!bcm2835_init)
devolver 1;

set_pins_output;
set_output_pins_low;
set_pins_input;
retraso (100);

sig_set_handler (SIGUSR1, &button_signal_handler);

si (! (child_id (0) = bifurcación))
{
señal_on_state_change_pin1;
_salir(0);
}
otro;

si (! (child_id (1) = bifurcación))
{
señal_on_state_change_pin2;
_salir(0);
}
otro;

si (! (child_id (2) = bifurcación))
{
señal_on_state_change_pin3;
_salir(0);
}
otro;

si (! (child_id (3) = bifurcación))
{
señal_on_state_change_pin4;
_salir(0);
}
otro;

mientras (1)
{
sistema("eco x >> xyz");

retraso (100);
}

bcm2835_close;
devolver 0;
}

señal vacía_on_state_change_pin1 (vacío)
{
mientras (1)
{
si (bcm2835_gpio_lev(IN_PIN1))
{
retraso (50);
si (bcm2835_gpio_lev(IN_PIN1))
{
sig_send_val (getppid, SIGUSR1, 1);

hacer
{
mientras (bcm2835_gpio_lev (IN_PIN1))
retraso (1);
retraso (50);
}
mientras (bcm2835_gpio_lev(IN_PIN1));

sig_send_val (getppid, SIGUSR1, 1);
}
otro;
}otro;
retraso (1);
}
}

señal vacía_on_state_change_pin2 (vacío)
{
mientras (1)
{
si (bcm2835_gpio_lev(IN_PIN2))
{
retraso (50);
si (bcm2835_gpio_lev(IN_PIN2))
{
sig_send_val (getppid, SIGUSR1, 2);

hacer
{
mientras (bcm2835_gpio_lev (IN_PIN2))
retraso (1);
retraso (50);
}
mientras (bcm2835_gpio_lev(IN_PIN2));

sig_send_val (getppid, SIGUSR1, 2);
}
otro;
}otro;
retraso (1);
}
}

señal vacía_on_state_change_pin3 (vacío)
{
mientras (1)
{
si (bcm2835_gpio_lev(IN_PIN3))
{
retraso (50);
si (bcm2835_gpio_lev(IN_PIN3))
{
sig_send_val (getppid, SIGUSR1, 3);

hacer
{
mientras (bcm2835_gpio_lev (IN_PIN3))
retraso (1);
retraso (50);
}
mientras (bcm2835_gpio_lev(IN_PIN3));

sig_send_val (getppid, SIGUSR1, 3);
}
otro;
}otro;
retraso (1);
}
}

señal vacía_on_state_change_pin4 (vacío)
{
mientras (1)
{
si (bcm2835_gpio_lev(IN_PIN4))
{
retraso (50);
si (bcm2835_gpio_lev(IN_PIN4))
{
sig_send_val (getppid, SIGUSR1, 4);

hacer
{
mientras (bcm2835_gpio_lev (IN_PIN4))
retraso (1);
retraso (50);
}
mientras (bcm2835_gpio_lev(IN_PIN4));

sig_send_val (getppid, SIGUSR1, 4);
}
otro;
}otro;
retraso (1);
}
}

void button_signal_handler (int sig, siginfo_t *siginfo, void *context)
{
si ( 1 == *( ( int * ) &siginfo -> si_value ) )
sistema("hace eco de ti >> xyz");
de lo contrario si ( 2 == *( ( int * ) &siginfo -> si_value ) )
sistema("echo r >> xyz");
de lo contrario si (3 == *( (int *) &siginfo -> si_value))
sistema("echo l >> xyz");
de lo contrario si ( 4 == *( ( int * ) &siginfo -> si_value ) )
sistema("echo d >> xyz");
otro;

bcm2835_gpio_write (OUT_PIN1,st);
st = ~st;
}

vacío set_output_pins_low (vacío)
{

bcm2835_gpio_write (OUT_PIN1, BAJO);
bcm2835_gpio_write(OUT_PIN2, BAJO);
bcm2835_gpio_write (OUT_PIN3, BAJO);
bcm2835_gpio_write (OUT_PIN4, BAJO);
}

set_pins_output vacío (vacío)
{
bcm2835_gpio_fsel (OUT_PIN1, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel (OUT_PIN2, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel (OUT_PIN3, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel (OUT_PIN4, BCM2835_GPIO_FSEL_OUTP);
}

set_pins_input vacío (vacío)
{
bcm2835_gpio_fsel (IN_PIN1, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_set_pud (IN_PIN1, BCM2835_GPIO_PUD_OFF);

bcm2835_gpio_fsel (IN_PIN2, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_set_pud (IN_PIN2, BCM2835_GPIO_PUD_OFF);

bcm2835_gpio_fsel (IN_PIN3, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel (IN_PIN3, BCM2835_GPIO_FSEL_INPT);

bcm2835_gpio_set_pud (IN_PIN4, BCM2835_GPIO_PUD_OFF);
bcm2835_gpio_set_pud (IN_PIN4, BCM2835_GPIO_PUD_OFF);
}

void sig_send_msg (id_pid_t, int signo, char *msg)
{

signo de unión *sigdata;

sigdata=malloc(sizeof(sigval union));
sigdata -> sival_ptr = mensaje;

sigqueue (identificación, señal, *sigdata);

gratis (sigdata);
}

void sig_send_val (id_pid_t, signo int, valor int)
{
signo de unión *sigdata;

sigdata=malloc(sizeof(sigval union));
sigdata -> sival_int = val;

sigqueue (identificación, señal, *sigdata);

gratis (sigdata);
}

void sig_set_handler (señal int, void *handler)
{
estructura Sigaction *actuar;
act=malloc(sizeof(struct Sigaction));
actuar -> sa_sigaction = controlador;
actuar -> sa_flags = SA_SIGINFO;

Sigaction (signo, acto, NULL);
}

###

Diagramas de circuito

Diagrama de circuito para jugar al juego Snake-Raspberry-Pi

Vídeo del proyecto

Regresar al blog

Deja un comentario

Ten en cuenta que los comentarios deben aprobarse antes de que se publiquen.