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

Playing Snake Game using Raspberry Pi Game Pad – (Part 38/38)

This article discusses about how to develop simple game pad hardware and interface with the Raspberrypi board and also about the technique of interfacing a game code written in HTML5 with the game pad . Here a Snake Game written in HTML5 and JavaScript has been modified so that it can be played with the new game pad with four buttons. In this project, signal, pipe, fork, etc. techniques are used.

The Snake game running in a browser window forms the GUI or front end of the entire system. In a Linux operating system, each hardware device is represented as a file. The device can be controlled by simply reading and writing to this file. The hardware of an operating system is on one side and the user trying to access the hardware is on the other side, and in between there may be several layers of running processes that communicate with each other using inter-process communication methods. In this project there is a game pad which is the hardware and there is a process that reads the game pad and there is also a Pipe or FIFO file between the game and the game pad reading process.

((wysiwyg_imageupload:11011:))

The game runs in a browser window and communicates with the game pad via a Named Pipe or FIFO. There are several processes running that can read the game pad and write the necessary commands to the FIFO to control the game. The JavaScript written in the game code simply reads the FIFO for input control data.

Diagrama de blocos do gamepad Raspberry pi

Fig. 2: Raspberry Pi gamepad block diagram

The parent process here creates four child processes that are dedicated to each of the gamepad keys. Whenever a key is pressed or released, they generate a signal and send it to the parent process with a value. Using this method the parent process can identify which key was pressed or released.
As soon as the parent process detects a keystroke from the value received along with the signal, it simply writes a specific command value to the NAMED PIPE or FIFO. The HTML game will continuously read the FIFO every 100ms and change the snake's direction according to the read command.
The next part of the JavaScript reads the file every 100 ms and changes the direction of the snake's movement in the game.
//++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++//
loadFile function
{
reader = new XMLHttpRequest new ActiveXObject('MSXML2.XMLHTTP');
reader.open('get', 'xyz', true);
reader.onreadystatechange=displayContents;
reader.send(null);
}
displayContents function
{
ch = reader.responseText(0);
if(ch == 'I')
title = (title == EAST) ? EAST WEST;
else if(ch == 'r')
heading = (title == WEST) ? WEST EAST;
else if(ch == 'u')
heading = (title == SOUTH) ? SOUTH NORTH;
else if(ch == 'd')
heading = (title == NORTH) ? NORTH SOUTH;
}
//++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++//
The functions used in coding the Gamepad code for writing operations to the FIFO are explained in the following section.
The FIFO needs to be created using the following command in the same directory where the gamepad executable and game HTML files exist.
mkfifo xyz
FIFO can also be created using the code itself by adding the mkfifo , open function as explained in a previous documentation .
The user can write data to the temporary file from the terminal itself using the 'echo' command as shown in the following example.
echo abcdef >> /tmp/my_fifo
The parent FIFO writing process is written in such a way that it will write commands to the FIFO in response to signals received from the child process. The commands that will be written to the FIFO to control the snake's direction are listed below;
you -> Snake up
d -> Snake down
l -> Left Snake
r -> Cobra RIGHT
These commands can be written in FIFO with the help of system function.
system(“echo r >> xyz );
The above function call will turn Snake to the right.

Project source code

###

 #include <bcm2835.h>
 #include <pthread.h>
 #include <unistd.h>
 #include <signal.h>
 #include <sys/time.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>

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

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

#define SNAKE_FIFO_NAME "xyz"

empty set_pins_input (void);
void set_pins_output(void);
void set_output_pins_low(void);

void button_signal_handler ( int sig, siginfo_t *siginfo, void *context );
empty signal_on_state_change_pin1 ( empty );
empty signal_on_state_change_pin2 ( empty );
empty signal_on_state_change_pin3 (void);
empty signal_on_state_change_pin4 (void);
void sig_set_handler (int signal, void *handler);
void sig_send_val (pid_t id, int sign, int val);

pid_t son_id(5);
internal point = 0;

int main (void)
{
int i;
int cobra_fifo = -1;

if (!bcm2835_init )
return 1;

set_pins_output;
set_output_pins_low ;
set_pins_input ;
delay (100);

sig_set_handler ( SIGUSR1, &button_signal_handler );

if (! (child_id (0) = fork ))
{
signal_on_state_change_pin1 ;
_exit(0);
}
other;

if (! (child_id (1) = fork ))
{
signal_on_state_change_pin2 ;
_exit(0);
}
other;

if (! (child_id (2) = fork ))
{
signal_on_state_change_pin3 ;
_exit(0);
}
other;

if (! (child_id (3) = fork ))
{
signal_on_state_change_pin4 ;
_exit(0);
}
other;

while (1)
{
system("echo x >> xyz");

delay (100);
}

bcm2835_close ;
return 0;
}

empty signal_on_state_change_pin1 (empty)
{
while (1)
{
if (bcm2835_gpio_lev(IN_PIN1))
{
delay (50);
if (bcm2835_gpio_lev(IN_PIN1))
{
sig_send_val (getppid , SIGUSR1, 1);

to do
{
while ( bcm2835_gpio_lev (IN_PIN1))
delay (1);
delay (50);
}
while (bcm2835_gpio_lev(IN_PIN1));

sig_send_val (getppid , SIGUSR1, 1);
}
other;
}other;
delay (1);
}
}

empty signal_on_state_change_pin2 (empty)
{
while (1)
{
if (bcm2835_gpio_lev(IN_PIN2))
{
delay (50);
if (bcm2835_gpio_lev(IN_PIN2))
{
sig_send_val (getppid , SIGUSR1, 2);

to do
{
while ( bcm2835_gpio_lev (IN_PIN2))
delay (1);
delay (50);
}
while (bcm2835_gpio_lev(IN_PIN2));

sig_send_val (getppid , SIGUSR1, 2);
}
other;
}other;
delay (1);
}
}

empty signal_on_state_change_pin3 (empty)
{
while (1)
{
if (bcm2835_gpio_lev(IN_PIN3))
{
delay (50);
if (bcm2835_gpio_lev(IN_PIN3))
{
sig_send_val (getppid , SIGUSR1, 3);

to do
{
while ( bcm2835_gpio_lev (IN_PIN3))
delay (1);
delay (50);
}
while (bcm2835_gpio_lev(IN_PIN3));

sig_send_val (getppid , SIGUSR1, 3);
}
other;
}other;
delay (1);
}
}

empty signal_on_state_change_pin4 (empty)
{
while (1)
{
if (bcm2835_gpio_lev(IN_PIN4))
{
delay (50);
if (bcm2835_gpio_lev(IN_PIN4))
{
sig_send_val (getppid , SIGUSR1, 4);

to do
{
while ( bcm2835_gpio_lev (IN_PIN4))
delay (1);
delay (50);
}
while (bcm2835_gpio_lev(IN_PIN4));

sig_send_val (getppid , SIGUSR1, 4);
}
other;
}other;
delay (1);
}
}

void button_signal_handler (int sig, siginfo_t *siginfo, void *context)
{
if ( 1 == *( ( int * ) &siginfo -> si_value ) )
system("echo you >> xyz");
else if ( 2 == *( ( int * ) &siginfo -> si_value ) )
system("echo r >> xyz");
else if (3 == *( (int *) &siginfo -> si_value))
system("echo l >> xyz");
else if ( 4 == *( ( int * ) &siginfo -> si_value ) )
system("echo d >> xyz");
other;

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

empty set_output_pins_low (empty)
{

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

empty set_pins_output (empty)
{
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);
}

empty set_pins_input (empty)
{
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 ( pid_t id, int signo, char *msg )
{

union sign *sigdata;

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

sigqueue (id, signal, *sigdata);

free (sigdata);
}

void sig_send_val ( pid_t id, int sign, int val )
{
union sign *sigdata;

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

sigqueue (id, signal, *sigdata);

free (sigdata);
}

void sig_set_handler (int signal, void *handler)
{
struct Sigaction *act;
act=malloc(sizeof(struct Sigaction));
act -> sa_sigaction = handler;
act -> sa_flags = SA_SIGINFO;

Sigaction (sign, act, NULL);
}

###

Circuit diagrams

Circuit Diagram for Playing Snake-Raspberry-Pi Game

Project video

Back to blog

Leave a comment

Please note, comments need to be approved before they are published.