top of page

#1 Pong contra parede

Das minhas vontades de desenvolver um projeto que seja simples, porém que requeira um certo conhecimento em C e PIC ou muita sede de aprender veio a ideia deste projeto.

Consiste em um jogo de ping pong "contra" a parede, onde o jogador tem sua raquete e a bola é rebatida contra parede.

Pois bem, isto foi desenvolvido usando PIC16F877A que é um otimo PIC para pequenos projetos já que consiste de 8 bits e algumas portas I/O, utilizando uma matriz de LED 8X8 para apresentar a bola e a raquete e mais dois botões para direcionar a raquete.

A ideia consiste na seguinte lógica:

 A bola será um led da matriz acesso, disso para fazer a animação este led será intercalado, fazendo com que simule a animação para as direções: vertical, horizontal e inclinado.

Caso chegue no ultimo led da matriz, isso significa que houve uma colisão com a parede, disso haverá uma outra direção a ser seguida e assim sucessivamente.

 

Várias ideias iniciais para desenvolvimento do projeto foram pensadas e a mais viável para este projeto é abusar do uso de Shift BIT para animar os led e dar a impressão de movimento.

 

Para reduzir efeitos de Pooling que é quando precisa fazer uma interrupção, porém o processador executa até o fim do código, foi reduzido o uso de Delays, que deterioram o projeto e assim pode-se apresentar diversos "Bugs".

Abaixo, segue o código do projeto desenvolvido em C, com o uso do MikroC for PIC:

// Pong crazy: creat by Julien Victor -----

      volatile  char  ball_pb;
      volatile char  ball_pd;
      volatile char  pad_pb;
      volatile char  pad_pd;
      volatile char  pad_pb_temp;
      int j=0;
      int i;
      int direcao_top;
      int direcao_butt;
      int direcao_right;
      int direcao_left;
      volatile int flag_mov;
      int colision_flag;
      bit aux;
      bit aux1;
      bit result;
      int k;

void timer(){

  PORTB=ball_pb;
  PORTD=ball_pd;
  Delay_ms(50);
  PORTB=pad_pb;
  PORTD=pad_pd;
  Delay_ms(50);

}

// Rotina colisao escolhe movimentos -----------
// so chama rotina quando detecta colisao

void col_ball_butt(){

  direcao_top = rand() % 2;

  switch(direcao_top){

     case 0:     // direçao reta p cima
     flag_mov=1;
     break;

     case 1:     // direçao incl esq
     flag_mov=2;
     break;

     case 2:     // direçao incl dir
     flag_mov=3;
     break;

  }
  colision_flag=0;

  game_over=0;
}
// fim -------------------------------------

// Rotina colisao escolhe movimentos -----------
// so chama rotina quando detecta colisao

void col_ball_top(){

  direcao_butt = rand() % 2;

  switch (direcao_butt){

     case 0:     // direçao reta
     flag_mov=5;
     break;

     case 1:     // direçao incl esq
     flag_mov=4;
     break;

     case 2:     // direçao incl dir
     flag_mov=6;
     break;

  }
  colision_flag=0;
}
// fim -------------------------------------

// Rotina colisao escolhe movimentos -----------
// so chama rotina quando detecta colisao

void col_ball_left(){

  direcao_right = rand() % 2;

  switch (direcao_right){

     case 0:     // direçao reta
     flag_mov=7;
     break;

     case 1:     // direçao incl esq
     flag_mov=8;
     break;

     case 2:     // direçao incl dir
     flag_mov=9;
     break;

  }
  colision_flag=0;
}
// fim -------------------------------------

// Rotina colisao escolhe movimentos -----------
// so chama rotina quando detecta colisao

void col_ball_right(){

  direcao_left = rand() % 2;

  switch (direcao_left){

     case 0:     // direçao reta
     flag_mov=10;
     break;

     case 1:     // direçao incl esq
     flag_mov=11;
     break;

     case 2:     // direçao incl dir
     flag_mov=12;
     break;

  }
  colision_flag=0;
}
// fim -------------------------------------





// Rotina movimento ----------------------

 void mov(){


    if(colision_flag==0){

    // de baixo p cima
    if(flag_mov==1){

    ball_pd=ball_pd>>1;}

    if(flag_mov==2){

    ball_pd=ball_pd>>1;
    ball_pb=ball_pb>>1;}
    //fim

    if(flag_mov==3){

    ball_pd=ball_pd>>1;
    ball_pb=ball_pb<<1;}

    // de cima p baixo
    if(flag_mov==4 && PORTB.RB0!=1){

    ball_pd=ball_pd<<1;}

    if(flag_mov==5 && PORTB.RB0!=1){

    ball_pd=ball_pd<<1;
    ball_pb=ball_pb<<1;}


    if(flag_mov==6 && PORTB.RB0!=1){

    ball_pd=ball_pd<<1;
    ball_pb=ball_pb>>1;}
    //fim    -ok

    // da esq p dir
    if(flag_mov==7){

    ball_pb=ball_pb<<1;}

    if(flag_mov==8){

    ball_pd=ball_pd>>1;
    ball_pb=ball_pb<<1;}


    if(flag_mov==9){

    ball_pd=ball_pd>>1;
    ball_pb=ball_pb<<1;}
    //fim

    // da dir p esq
    if(flag_mov==10){

    ball_pb=ball_pb>>1;}

    if(flag_mov==11){

    ball_pd=ball_pd>>1;
    ball_pb=ball_pb>>1;}


    if(flag_mov==12){

    ball_pd=ball_pd>>1;
    ball_pb=ball_pb>>1;}
    //fim
    Delay_ms(100);
    }

 }

// fim movimento -----------------


// colisões ---------------------

void colisoes(){

 

// colisao pad------------
  if(ball_pd==64){

        if(ball_pb=0b10000000 && pad_pb=0b11000000){
        colision_flag=1;
        col_ball_butt();
        game_over=0;
        }
        else
        if((ball_pb=0b01000000 && pad_pb=0b11000000) || (ball_pb=0b01000000 && pad_pb=0b01100000)){
        colision_flag=1;
        col_ball_butt();
        game_over=0;
        }
        else
        if((ball_pb=0b00100000 && pad_pb=0b01100000) || (ball_pb=0b00100000 && pad_pb=0b00110000)){
        colision_flag=1;
        col_ball_butt();
        game_over=0;
        }
        else
        if((ball_pb=0b00010000 && pad_pb=0b00110000) || (ball_pb=0b00010000 && pad_pb=0b00011000)){
        colision_flag=1;
        col_ball_butt();
        game_over=0;
        }
        else
        if((ball_pb=0b00001000 && pad_pb=0b00011000) || (ball_pb=0b000010000 && pad_pb=0b00001100)){
        colision_flag=1;
        col_ball_butt();
        game_over=0;
        }
        else
        if((ball_pb=0b00000100 && pad_pb=0b00001100) || (ball_pb=0b000001000 && pad_pb=0b00000110)){
        colision_flag=1;
        col_ball_butt();
        game_over=0;
        }
        else
        if((ball_pb=0b00000010 && pad_pb=0b00000110) || (ball_pb=0b000000100 && pad_pb=0b00000011)){
        colision_flag=1;
        col_ball_butt();
        game_over=0;
        }
        else
        if(ball_pb=0b00000001 && pad_pb=0b00000011){
        colision_flag=1;
        col_ball_butt();
        game_over=0;
        }
        else  game_over++;

}
// fim pad---------------



    // colisao top
    if(ball_pd==1){
     colision_flag=1;
     col_ball_top();
    }

   // colisao esq
    if(ball_pb==1){
     colision_flag=1;
     col_ball_left();
    }
   // fim

   // colisao dir
    if(ball_pb==128){
     colision_flag=1;
     col_ball_right();
    }
   // fim

}

void pad(){

     if(pad_pb <=0x64) {
     pad_pb_temp= pad_pb;
    if(PORTC.RB5!=1){
    pad_pb_temp=pad_pb_temp<<1;
                  }
     pad_pb=pad_pb_temp;
     }

         if(pad_pb >=0x04) {
     pad_pb_temp= pad_pb;
     if(PORTC.RB4!=1){
    pad_pb_temp=pad_pb_temp>>1;
                  }
    pad_pb=pad_pb_temp;

           }

}





 

 // reinicia o jogo -----
void rein(){
    
    ball_pb=0b00010000;
    ball_pd=0b00000001;
    pad_pb=0b00011000;
    pad_pd=0b10000000;
    i=0;
    game_over=0;
    //inicializa:
    col_ball_top();
}
-----------------------


void main(){
CMCON =7;
TRISD = 0b00000000;
TRISB = 0b00000000;
TRISC=0xFF;
    ball_pb=0b00010000;
    ball_pd=0b00000001;
    pad_pb=0b00011000;
    pad_pd=0b10000000;
    i=0;

    //inicializa:
    col_ball_top();


   while(1){

   if(game_over<=1){
   colisoes();
   pad();
   timer();
   mov();          }
   else
   rein();

            }
}

 




// Pong crazy: creat by Julien Victor -----

Hardware:

A parte de hardware é simples, porém requer alguma criatividade para lidar com PIC, já que o hardware se adequa ao projeto, diferentemente de um embarcado que tem uma capacidade limitada e circuito principal não é modificável.

circpong.PNG

Conforme visto acima, este circuito representa as conexões principais da matriz com as portas do Pic e das chaves com as portas utilizadas do Pic, para melhor visualização das conexões, cada chave da matriz representa um led, assim são ativadas quando um estiver em nivel logico alto e outro baixo, já que a matriz utilizada possui logica invertida, foram utilizados portas NOT para facilitar a codificação.

Existem diferentes formas de fazer o mesmo projeto, pensei em utilizar sincronização da matriz, como a utilizada em monitores, porem para isso, seria necessário a criação de uma matriz que pudesse ser manipulada, porem como as informação são independentes (pad e bola), seria uma dificuldade tremenda modificar a matriz diversas vezes e ainda o codigo ficaria muito extenso, assim creio que utilizei a codificação mais eficiente para este caso.

O projeto é simples, porem pode ser incrementado , com placar de pontos, mensagens informativas, etc.

Obrigado por chegar até aqui!

Alguma sugestão

Obrigado pelo envio!

bottom of page