PUCRS/FACIN
Curso de Especiali
zação em Desenvolvimento de Jogos Digitais

Computação Gráfica 2D

Profs.
    Márcio Sarroglia Pinho
    Isabel Harb Manssour


Colisão entre Sprites e Tiles

O objetivo desta aula é criar um programa que controle a colisão entre uma sprite e os tiles de uma cena.
Copie a última versão do Framework, disponível no Moodle.
Carregue o projeto no Visual Studio e abra o arquivo
PlayState.cpp.

Colocando uma Moldura na Sprite

Para facilitar a visualização das colisões, vamos inicialmente desenhar uma moldura ao redor da sprite.
No final do método PlayState::draw, antes da chamada da função  SDL_GL_SwapBuffers() coloque o trecho de código abaixo.
Observe como este código faz o desenho. Veja as coordenadas dos vértices.
Teste o programa.

    // Desenha um box ao redor da sprite do cao
    glColor3f(0,0,0);
    glBegin(GL_LINE_LOOP);
        glVertex2f(spriteCao->getX(), spriteCao->getY());
        glVertex2f(spriteCao->getX()+spriteCao->getWidth(),spriteCao->getY());
        glVertex2f(spriteCao->getX()+spriteCao->getWidth(),spriteCao->getY()+spriteCao->getHeight());
       glVertex2f(spriteCao->getX(),spriteCao->getY()+spriteCao->getHeight());
    glEnd();
    glColor3f(1,1,1);

Controlando o movimento da sprite

No método 
PlayState::handleEvents(), após o final do while que faz o processamento dos eventos, coloque o código abaixo.
Este código controla o movimento da sprite na tela.

    // verifica a tecla pressionada para atualizar as sprites

    float salvaX, salvaY;
    salvaX = spriteCao->getX();
    salvaY = spriteCao->getY();

    bool pressionou = false;
    if (keystate[SDLK_UP]==1) {
        cout << "Pra cima " << endl;
        spriteCao->setY(spriteCao->getY()-1);
        pressionou = true;
    }
    if (keystate[SDLK_DOWN]==1) {
        cout << "Pra baixo " << endl;
        spriteCao->setY(spriteCao->getY()+1);
        pressionou = true;
    }
    if (keystate[SDLK_RIGHT]==1) {
        cout << "Pra direita " << endl;
        spriteCao->setX(spriteCao->getX()+1);
        pressionou = true;
    }
    if (keystate[SDLK_LEFT]==1) {
        cout << "Pra esquerda " << endl;
        spriteCao->setX(spriteCao->getX()-1);
        pressionou = true;
    }

    // testa colisão da sprite com o tile que contem o obstáculo
    if (pressionou) {
        if (TemColisaoSpriteTile(spriteCao, mapColisao)) {
            spriteCao->setPosition(salvaX,salvaY);
        }
        pressionou = false;
    }


Detectando a colisão da sprite com os tiles
Substituta o código do método  PlayState::TemColisaoSpriteTile  pelo trecho de código abaixo.

// método que testa se há colisão entre uma sprite e os elementos do tile
bool PlayState::TemColisaoSpriteTile(CSprite *sprite, CTilesMap *map) {
    int nTile;

    cout << "Posicao Sprite: " << sprite->getX() << " " << sprite->getY() << endl;
    //cout << "Largura do tile: " << map->getWidth() << endl;
    cout << "Largura do sprite: " << sprite->getWidth() << endl;

    int tileX, tileY;
    tileX = sprite->getX() / map->getWidth();
    tileY = sprite->getY() / map->getHeight() ;
    cout << "Posicao do tile: [" << tileX << ", " << tileY << "] : " ;
    nTile = map->getTileNumber(tileX, tileY);
    cout << nTile << endl;
    if (nTile == 192) // é fundo ??
        return false;
    else return true;

}

Exercício

Modifique o programa de forma a detectar a colisão nos quatro lados da sprite.

FIM.