Quinta-feira, 25 de Setembro de 2008

Usa a cabeça - jogo do pong

 

link: http://videos.sapo.pt/kpmTcS97THz7DoCk6sCz

 

Projecto desenvolvido por Mário Vairinhos (programação) em parceria com Nuno Dias (design) em Outubro de 2007 no evento CODEBITS 2007 organizado pelo SAPO e que mereceu o prémio Hack.

Faz agora quase um ano o fim-de-semana passado na gare do oriente a comer chocolates e pizzas na companhia de 400 nerds.

O projecto foi desenvolvido em C/C++ recorrendo à biblioteca open source de visão por computador OPENCV.

 

Publica-se o código-fonte do projecto. Todo o projecto foi escrito à pressa, ao estilo quick & dirty, numa espécie de correria para o terminar antes do prazo limite.

usaacabeca.c

#include "cv.h"
#include "highgui.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>

#ifdef _EiC
#define WIN32
#endif

static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade = 0;
///////////////////////////PROTÓTIPOS////////////////////////
void detect_and_draw( IplImage* image );
void insere(IplImage* origem, int _larg, int _alt, int _x, int _y);
void insere_sprite(int sp_num,int _x,int _y);
void bola_fisica(void);
void bola_colisao(void);
void bola_init(void);
/////////////////////////////////////////////////////////////
const char* cascade_name =
    "haarcascade_frontalface_alt.xml";
/*    "haarcascade_profileface.xml";*/

    IplImage *frame,*fundojpg, *fundo, *frame_copy = 0;
    IplImage *sprite[11]; // algarismos[0 a 9] + bola[10]

    int bola_vel=10;
    double bola_ang=-0.3;
    double bola_x=50;
    double bola_y=50;

    int tique=0;
    int taque=1;
    CvCapture* capture = 0;
    int largura=640;
    int altura=480;
    int caplargura;
    int capaltura;
    double rl;
    double ra;
    CvScalar corfundo;
    CvScalar corfigura;
    int moldura_stroke=5;
    int player[2];
    int player_x[2];
    int player_y[2];
    int player_larg[2];
    int player_alt[2];
    int players=0;

    double scale = 2.5; // detecção do cascade



int main( int argc, char** argv )
{
    int i;
   
/////////////////////////////////////////////TEMPLATE/////////////////////////
    int optlen = strlen("--cascade=");
    const char* input_name;
    if( argc > 1 && strncmp( argv[1], "--cascade=", optlen ) == 0 )
    {
        cascade_name = argv[1] + optlen;
        input_name = argc > 2 ? argv[2] : 0;
    }else{
        cascade_name = "../../data/haarcascades/haarcascade_frontalface_alt2.xml";
        input_name = argc > 1 ? argv[1] : 0;
    }
    cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
    if( !cascade ) return -1;
    storage = cvCreateMemStorage(0);
//////////////////////////////////////////////// INIT /////////////////////////////

    corfundo = cvScalar(10,120,10,0); // BGR
    corfigura = cvScalar(255,255,255,0);
///////////////////////////////////////////////////////////////////////////////
    if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
        capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
    else
        return -1;


    cvNamedWindow( "result", 0 );
    cvResizeWindow( "result", largura, altura);


////////////////////////////////////////////////SPRITES///////////////////
        sprite[0] = cvLoadImage("0.jpg",1);
        sprite[1] = cvLoadImage("1.jpg",1);
        sprite[2] = cvLoadImage("2.jpg",1);
        sprite[3] = cvLoadImage("3.jpg",1);
        sprite[4] = cvLoadImage("4.jpg",1);
        sprite[5] = cvLoadImage("5.jpg",1);
        sprite[6] = cvLoadImage("6.jpg",1);
        sprite[7] = cvLoadImage("7.jpg",1);
        sprite[8] = cvLoadImage("8.jpg",1);
        sprite[9] = cvLoadImage("9.jpg",1);
        sprite[10] = cvLoadImage("bola.jpg",1); //BOLA
        bola_init();
/////////////////////////////////////////////////////////////////////////////
    if( capture )
    {
        for(;;)
        {

            if( !cvGrabFrame( capture ))break;
            frame = cvRetrieveFrame( capture );
            if( !frame ){
                break;
            }else{

                caplargura=frame->width;
                capaltura=frame->height;
                rl=largura/caplargura;
                ra=altura/capaltura;
               
            }


            if( !frame_copy ){
                // PRIMEIRA VEZ
                frame_copy = cvCreateImage( cvSize(frame->width,frame->height),IPL_DEPTH_8U, frame->nChannels );
                printf( "largura = %d \n", frame->width );
            }
           
           
            if( frame->origin == IPL_ORIGIN_TL )
                cvCopy( frame, frame_copy, 0 );
            else
                cvFlip( frame, frame_copy, 0 );
           

            cvFlip( frame_copy, frame_copy, 1 );

            if (!fundo) fundo=cvCreateImage( cvSize(largura,altura),IPL_DEPTH_8U, frame->nChannels );
            //cvSet(fundo, corfundo, NULL );

            if (!fundojpg){
                fundojpg=cvLoadImage("fundo.jpg",1);
            }else{
                cvCopy(fundojpg,fundo,0);
            }
            detect_and_draw( frame_copy );
            bola_fisica();
            bola_colisao();



            insere_sprite(player[0],100,15);
            insere_sprite(player[1],190,15);

           


            cvShowImage( "result", fundo );


            cvWaitKey( 1 );
        }



        cvReleaseImage( &frame_copy );
        cvReleaseCapture( &capture );
    }
   
    cvDestroyWindow("result");

    return 0;
}

void detect_and_draw( IplImage* img )
{
    static CvScalar colors[] =
    {
        {{0,0,255}},
        {{0,128,255}},
        {{0,255,255}},
        {{0,255,0}},
        {{255,128,0}},
        {{255,255,0}},
        {{255,0,0}},
        {{255,0,255}}
    };

    IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
    IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),cvRound (img->height/scale)),8, 1 );
    int i;

    cvCvtColor( img, gray, CV_BGR2GRAY );
    cvResize( gray, small_img, CV_INTER_LINEAR );
    cvEqualizeHist( small_img, small_img );
    cvClearMemStorage( storage );

   
    if( cascade )
    {
        double t = (double)cvGetTickCount();
        CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
                                            1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,
                                            cvSize(30, 30) );
        t = (double)cvGetTickCount() - t;
        //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
        for( i = 0; i < (faces ? faces->total : 0); i++ )
        {
            CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
           
            CvPoint center1;
            CvPoint center2;
            center1.x=cvRound((r->x)*scale);
            center1.y=cvRound((r->y)*scale);
            center2.x=cvRound((r->x + r->width)*scale);
            center2.y=cvRound((r->y + r->height)*scale);
            cvRectangle(img,cvPoint(center1.x+moldura_stroke-3,center1.y+moldura_stroke-3),cvPoint(center2.x-moldura_stroke+2,center2.y-moldura_stroke+2),corfigura,moldura_stroke,8,0);



            if (i<2){
                player_larg[i] = abs(center2.x-center1.x);
                player_alt[i] = abs(center2.y-center1.y);
                player_x[i]=center1.x+(player_larg[i]/2);
                player_y[i]=center1.y+(player_alt[i]/2);

            }   

            insere(img,r->height,r->width,center1.x,center1.y);

        }
    }

    cvReleaseImage( &gray );
    cvReleaseImage( &small_img );
}



void insere(IplImage* origem,int _larg, int _alt, int _x, int _y){
            int x,y;
            for(y=0; y <_alt*scale  ;y++){//
                for(x=0 ; x< _larg*scale ;x++){//
                        uchar* ds  = (uchar*)(origem->imageData   + (y+_y)*origem->widthStep);
                        uchar* dd  = (uchar*)(fundo->imageData + (y+cvRound(ra*_y))*fundo->widthStep);
                        dd[(x+cvRound(_x*rl))*3+0]=ds[(x+_x)*3+0];
                        dd[(x+cvRound(_x*rl))*3+1]=ds[(x+_x)*3+2];
                        dd[(x+cvRound(_x*rl))*3+2]=ds[(x+_x)*3+3];

                    }
            }


}



void insere_sprite(int sp_num, int _x, int _y){
            int x,y;
            for(y=0; y < sprite[sp_num]->height  ;y++){//
                for(x=0 ; x< sprite[sp_num]->width ;x++){//
                        uchar* ds  = (uchar*)(sprite[sp_num]->imageData   + (y)*sprite[sp_num]->widthStep);
                        uchar* dd  = (uchar*)(fundo->imageData + (y+cvRound(ra*_y))*fundo->widthStep);
                        dd[(x+cvRound(_x*rl))*3+0]=ds[(x)*3+0];
                        dd[(x+cvRound(_x*rl))*3+1]=ds[(x)*3+1];
                        dd[(x+cvRound(_x*rl))*3+2]=ds[(x)*3+2];

                    }
            }


}


void bola_fisica(){
    double x=bola_vel*cos(bola_ang);
    double y=bola_vel*sin(bola_ang);
    bola_x+=x;
    bola_y+=y;
    insere_sprite(10,bola_x,bola_y);
}



void bola_colisao(){
    int barra=5;
    int i;
    // parede de cima e de baixo
    if (bola_y<(sprite[10]->height+5) || bola_y>(capaltura-sprite[10]->height-5)){
        bola_ang=- bola_ang;
    }
    // golo
    if (bola_x<3){
        player[1]+=1;
        if (player[1]>=10){
            player[1]=0;
            player[0]=0;
        }
        bola_init();
        return;
    }
    if (bola_x>caplargura-sprite[10]->width-10){
        player[0]+=1;
        if (player[0]>=10){
            player[1]=0;
            player[0]=0;
        }
        bola_init();
        return;
    }
    //PADDLE

    for(i=0;i<=1;i++){
        if (   (bola_x+40<(player_x[i]+barra))
            && (bola_x+40>(player_x[i]-barra))
            && (bola_y>(player_y[i]-player_alt[i]/2))
            && (bola_y<(player_y[i]+player_alt[i]/2))  ){
            //printf( "COLISÃO 0 %d \n",i );
            bola_ang= 3.14 - bola_ang;
            bola_fisica();
        }
    }


}

void bola_init(){
        bola_x=caplargura/2;
        bola_y=capaltura/2;
        bola_ang=3.14+bola_ang;
};


 

 

 

 

 

publicado por nop às 22:31
link do post | comentar | favorito
|

pesquisar

 

tags

arduino

c/c++

codebits

deca

director

flash

iniciação

maa

materiais

mobile

oficina

opencv

relé

tui

ua

todas as tags

recentes

O NOP mudou de casa :)

Museu Municipal Penafiel ...

Mylamp - tutorial

Materiais - iniciação

Multimédia em Ambientes A...

Usa a cabeça - jogo do po...

Arduino - acelerómetro - ...

Arduino - input analógico...

Arduino - sonar Maxbotix...

Arduino - input analógico...

arquivos

Novembro 2012

Abril 2009

Outubro 2008

Setembro 2008

Abril 2008

Fevereiro 2008

links