>>HOMEPAGE

    Home     Manual       Relatório Técnico         Código Fonte         Downloads        Links Úteis


//==================================================================
// Projeto: Batalha Naval
// Por: Renata Corrêa - Silmara Pedretti Gomes
// Versão: 0.3
// Disciplina: IA725 - Profa. Ting
// Julho/2004
//==================================================================

#define PI 3.1415

#define SUB 'S' //Submarino oculto
#define SUBA 'T' //Submatino afundado
#define SUBM 'U' //Submarino visualizado

#define BAR 'B' //Barco oculto
#define BARA 'C' //Barco afundado
#define BARM 'D' //Barco visualizado

#define NAV 'N' //Navio oculto
#define NAVA 'O' //Navio afundado
#define NAVM 'P' //Navio visualizado

#define BANDEIRA 'X' //Bandeira

//Variáveis que guardam a primeira posição das Embarcações
//Lembrando que elas sempre a parecem na horizontal ->
int intSubIni;
int intNavIni;
int intBarIni;

//essa matriz irá controlar as posições do plano ->
char plano[10][10];

//Controla se o jogo acabou ->
char chrFim[3];

//Controla a iluminação entre noite e dia...padrão = dia
//int EhDia=1;

void keyboard(unsigned char key, int x, int y);
void init();
void ConfiguraIluminacao();
void ConfiguraTextura();
bool PosicaoOcupada(int intPosx, int intPosy, int intTamEmbarc);
void pickRects(int button, int state, int x, int y);
void processHits(GLint hits, GLuint buffer[]);
void MarcaPosicoes(int x, int y);
void display();
int LoadBMP(char *filename);

GLint WIDTH=800;
GLint HEIGHT=600;

GLfloat obs[3]={0.0,19.0,0.0};
GLfloat look[3]={0.0,3.0,0.0};


GLfloat tetaxz=0;
GLfloat raioxz=11;
//GLfloat win=150.0;

// Buffer para selecção
GLuint s_buffer[512];

// Dimensões da janela
GLint w0 = 0;
GLint h0 = 0;

// Acumuladores de movimento do rato
signed int mx0 = 0;
signed int my0 = 0;

// Ponto de vista
int viewpoint = 0;

// Modo pick
int pick = 1;


time_t hor_ini, hor_fim;
double tempo_final;


void ConfiguraIluminacao()
{
//Configuração padrão -> dia
GLfloat lightpos[4] = { 1.0, 3.0, 5.0, 0.0 };
GLfloat lightamb[4] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat lightdif[4] = { 0.8, 0.8, 0.8, 1.0 };
GLfloat lightesp[4] = { 0.5, 0.5, 0.5, 1.0 };

//Configuração noite
if(EhDia==0){
lightamb[0] = 0.1;
lightamb[1] = 0.1;
lightamb[2] = 0.1;

lightdif[0] = 0.5;
lightdif[1] = 0.5;
lightdif[2] = 0.5;

lightesp[0] = 0.1;
lightesp[1] = 0.1;
lightesp[2] = 0.1;

glClearColor(0.0,0.0,0.1,1);
}
else
glClearColor(0.8,0.8,0.9,1);


//Configuração para tonalização pelo método de Gouraud
glShadeModel (GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
glLightfv(GL_LIGHT0, GL_AMBIENT, lightamb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightdif);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightesp);
glEnable(GL_LIGHTING);
glDepthMask(GL_TRUE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHT0);
}

//---------------------------------------------------------------------------
void ConfiguraTextura(){

/*
Habilita a Texturizacao.
Criacao inicial das texturas.
*/

glEnable ( GL_TEXTURE_2D ); // Habilitar o uso de texturas
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); // Definir a forma de armazenamento dos pixels na textura (1= alinhamento por byte)
glGenTextures ( 6, texture_id ); // vetor com os números das texturas

//Textura 0 - mar
glBindTexture ( GL_TEXTURE_2D, texture_id[txId_Mar] ); // Define a textura corrente
LoadBMP ("mar.bmp"); // Carrega o arquivo

//Textura 1 - tecido
glBindTexture ( GL_TEXTURE_2D, texture_id[txId_Tecido] );
LoadBMP ("tecido_zig.bmp");

//Textura 2 - metal1
glBindTexture ( GL_TEXTURE_2D, texture_id[txId_Metal1] );
LoadBMP ("metal4.bmp");

//Textura 3 - metal2
glBindTexture ( GL_TEXTURE_2D, texture_id[txId_Metal2] );
LoadBMP ("metal1.bmp");

//Textura 4 - madeira
glBindTexture ( GL_TEXTURE_2D, texture_id[txId_Madeira] );
LoadBMP ("madeira.bmp");

//Textura 5 - metal
glBindTexture ( GL_TEXTURE_2D, texture_id[txId_MetalEncaixe] );
LoadBMP ("metal2.bmp");

//Textura 6 - bomba
glBindTexture ( GL_TEXTURE_2D, texture_id[txId_Bomba] );
LoadBMP ("lua.bmp");

//Textura 7 - prata
glBindTexture ( GL_TEXTURE_2D, texture_id[txId_Prata] );
LoadBMP ("prata.bmp");


glBindTexture ( GL_TEXTURE_2D, 0);

}


//---------------------------------------------------------------------------
//Função utilizada para posicionar as embarções ->
void Posiciona(int intTam, char chrID)
{
int intPosx, intPosy;
bool bolControle = true;

intPosx = intPosy = 0;

//sortear onde o submarino será colocado
while (bolControle)
{
intPosx = rand() % (10-intTam);
intPosy = rand() % 10;

//a linha abaixo exibe a posição dos objetos, só deve ser usada para testes.
//printf ("\nx = %i, y = %i", intPosx, intPosy);


if (!PosicaoOcupada(intPosx, intPosy, intTam)) //verifica se as posições para acomodar a embarcação estão ocupadas por outra embarcação
bolControle = false; //Se retornar true, está ocupada caso contrário não está
}
//Neste momento tem-se as coordenadas da embarcação
if (chrID == SUB)
intSubIni = intPosx;
else if (chrID == BAR)
intBarIni = intPosx;
if (chrID == NAV)
intNavIni = intPosx;

for (int intCount = 0; intCount < intTam; intCount++)
{
plano[intPosx][intPosy] = chrID;
intPosx++;
}

}


//---------------------------------------------------------------------------
void PosicionaEmbarc()
{
time_t t;
//inicializa o gerador de número randomico
srand((unsigned) time(&t));

Posiciona(SUBMARINO, SUB);
Posiciona(BARCO, BAR);
Posiciona(NAVIO, NAV);

//Informação para o usuário de como jogar
// Teclas: T:tiro Setas:movimentam o tabuleiro R/shift+R:movimentam tabuleiro
printf(" Batalha Naval \n");
printf("------------------------------------------------------------------------\n");
printf(" Teclas: T:tiro Setas, R, Shitf+R:movimentam o tabuleiro \n");
printf("------------------------------------------------------------------------\n");

}
//---------------------------------------------------------------------------
void desenha(void){
int i, j;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //¤ Limpando o color e o depth buffer ->


glColor3f(0.9, 0.9, 1.0);
glLoadIdentity();


/* calcula a posicao do observador */
obs[0]=raioxz*cos(2*PI*tetaxz/360);
obs[2]=raioxz*sin(2*PI*tetaxz/360);
gluLookAt(obs[0],obs[1],obs[2],look[0],look[1],look[2],0.0,1.0,0.0);


// Modelando o chão
desenha_tabuleiro();


for(j=0; j<10; j++) //linha
{
for(i=0; i<10; i++) //coluna
{
//Se a posição já foi escolhida e está marcada como errada, ou seja, tem bomba
if (plano[i][j] == BANDEIRA) constroe_bandeira(i, j);
else if (plano[i][j] == SUBM) {constroe_submarino(intSubIni, j); i+=2;}
else if (plano[i][j] == BARM) {constroe_barco(intBarIni, j); i++; }
else if (plano[i][j] == NAVM) {constroe_navio(intNavIni, j); i++; }
else if (plano[i][j] == SUBA || plano[i][j] == NAVA || plano[i][j] == BARA) constroe_bomba(i, j);
}
}


glCallList(submarino);
glCallList(navio);
glCallList(barco);

glFlush();

glutSwapBuffers();

}

//---------------------------------------------------------------------------
//Gerenciamento do menu com as coordenadas ->
void MenuXY(int op)
{
int x, y;
bool bolControle = true;


while (bolControle)
{
bolControle = false;

do
{
fflush(stdin); //->limpando o buffer do teclado
printf("Coordenada do ponto x (de 0 a 9):");
scanf("%d", &x);
}while (x > 9 || x < 0);
do
{
fflush(stdin); //->limpando o buffer do teclado
printf("Coordenada do ponto y (de 0 a 9):");
scanf("%d", &y);
}while (y > 9 || y < 0);


if (plano[x][y] == '0') plano[x][y] = BANDEIRA;
else if (plano[x][y] == SUB)
{
int intBombas = 0; plano[x][y] = SUBA;

//verificando se todas as posições estão com bomba
for (int intCount = intSubIni; intCount < (SUBMARINO+intSubIni); intCount++)
{ if (plano[intCount][y] == SUBA) intBombas++; }

if (intBombas == SUBMARINO)//Indica que o Submarino foi descoberto por inteiro
{ for (int intCount = intSubIni; intCount < (SUBMARINO+intSubIni); intCount++)
{ plano[intCount][y] = SUBM; chrFim[0] = '1'; }
}
}
else if (plano[x][y] == BAR)
{
int intBombas = 0; plano[x][y] = BARA;

//verificando se todas as posições estão com bomba
for (int intCount = intBarIni; intCount < (BARCO+intBarIni); intCount++)
{ if (plano[intCount][y] == BARA) intBombas++; }

if (intBombas == BARCO) //Indica que o Barco foi descoberto por inteiro
{ for (int intCount = intBarIni; intCount < (BARCO+intBarIni); intCount++)
{ plano[intCount][y] = BARM; chrFim[1] = '1'; }
}
}
else if (plano[x][y] == NAV)
{
int intBombas = 0; plano[x][y] = NAVA;

//verificando se todas as posições estão com bomba
for (int intCount = intNavIni; intCount < (NAVIO+intNavIni); intCount++)
{ if (plano[intCount][y] == NAVA) intBombas++;}

if (intBombas == NAVIO) //Indica que o Navio foi descoberto por inteiro
{ for (int intCount = intNavIni; intCount < (NAVIO+intNavIni); intCount++)
{ plano[intCount][y] = NAVM; chrFim[2] = '1'; }
}
}
else
bolControle = true;
}

glutPostRedisplay();

//Verifica se o jogo terminou
if (chrFim[0] == '1' && chrFim[1] == '1' && chrFim[2] == '1')
{
char chrOP;
fflush(stdin); //->limpando o buffer...
desenha(); //Para que mostre o último barco antes de recomeçar ->

time(&hor_fim);
tempo_final = difftime( hor_fim, hor_ini);
printf( "\nTempo de jogo: %6.0f segundos.\n", tempo_final);
printf("\nParabens, voce ganhou!\n");
printf("Deseja jogar novamente?<S/N>: ");
scanf("%c", &chrOP);
if (chrOP == 'S' || chrOP == 's')
{

init();
desenha();
}
// else
// exit(0);
}
}


//---------------------------------------------------------------------------
void teclado(unsigned char key, int x, int y){
switch (key) {
case 27: //esc
exit(0);
break;
case 'A': case 'a':
if(EhDia == 1) EhDia=0;
else EhDia=1; //alternando entre noite e dia
ConfiguraIluminacao();
glutPostRedisplay();
break;
case 'r':
raioxz=raioxz+1;
glutPostRedisplay();
break;
case 'R':
raioxz=raioxz-1;
if(raioxz==0) raioxz=1;
glutPostRedisplay();
break;
case 't': case 'T':
MenuXY(1);
break;
}
}

//---------------------------------------------------------------------------
void especial(int key, int x, int y){
switch (key) {
case GLUT_KEY_UP:
obs[1]=obs[1]+1;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
obs[1] =obs[1]-1;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
tetaxz=tetaxz+2;
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT:
tetaxz=tetaxz-2;
glutPostRedisplay();
break;
}
}

//---------------------------------------------------------------------------
void MontaChao(){
// Modelando o chão
glColor3f(0.1f,0.1f,1.0f);
glTranslatef(8,-2.0,8);
GLfloat Line = 0;
int Grid=0;
int Cont = 0;

glBindTexture ( GL_TEXTURE_2D, texture_id[txId_Mar] );
for (int Col =0; Col <=9; Col++)
{
Cont = 0;
for(Line = 0; Line <= 18; Line+=2,Cont++)
{
glLoadName (Col);
glPushName(Cont);
glPushMatrix();
glTranslatef(-Col*2, 0, -Line);
glBegin(GL_QUAD_STRIP);
glTexCoord2f(1.0f, 1.0f);glVertex3f(0, 0, 0);
glTexCoord2f(0.0f, 0.0f);glVertex3f(2, 0, 0);
glTexCoord2f(0.0f, 1.0f);glVertex3f(0, 0, 2);
glTexCoord2f(1.0f, 0.0f);glVertex3f(2, 0, 2);
glEnd();
glPopMatrix();
glPopName();
}
}
glBindTexture ( GL_TEXTURE_2D, 0);

}

//---------------------------------------------------------------------------
// Define matriz de Projecção
void setViewPoint(int pick_mode)
{

int w = w0;
int h = h0-10;
GLint viewport[4];

// Definir matriz de projecção (Perspectiva)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if (pick_mode) {
glGetIntegerv(GL_VIEWPORT, viewport);
gluPickMatrix(mx0,h0-my0,1,1,viewport);
}

gluPerspective(70.0,WIDTH/(float)HEIGHT,0.1,30.0);

glMatrixMode(GL_MODELVIEW);
}


//---------------------------------------------------------------------------
void checkSelection()
{
int x, y;
//Inicializando variável
x = y = -999;

unsigned int t,i, j, k, a;
glSelectBuffer(sizeof(s_buffer), s_buffer);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
setViewPoint(1);
glPushMatrix();
MontaChao();
glPopMatrix();
t = glRenderMode(GL_RENDER);
printf("SELECTION: %d :", t);
k = 0;
for (i = 0; i< t; i++) {
printf(" [%u,%u] " , s_buffer[k+1], s_buffer[k+2]);
for (j = 0 ; j < s_buffer[k]; j++) {
a = s_buffer[k+j+3];
if (y == -999)
y = a;
else if (x == -999)
x = a;

printf(" %u " , a);
}
k += s_buffer[k] + 3;
}

MarcaPosicoes(x, y);
printf("\n");
setViewPoint(0);
desenha();
}

//---------------------------------------------------------------------------
//Verifica se existe espaço para posicionar a embarcação
//Se for possível, retorna false, indicando que a posição está livre,
//caso contrário retorna false ->
bool PosicaoOcupada(int intPosx, int intPosy, int intTamEmbarc)
{
bool bolRet = false;

for (int intCountx = intPosx; intCountx < (intTamEmbarc+intPosx); intCountx++)
{
if (plano[intCountx][intPosy] != '0')
{
bolRet = true;
}
}
return bolRet;
}


//---------------------------------------------------------------------------
// Função callback chamada para gerenciar eventos do mouse

/* pickRects() sets up selection mode, name stack,
* and projection matrix for picking. Then the objects
* are drawn.
*/
#define BUFSIZE 512

void GerenciaMouse(int button, int state, int x, int y)
{
/*if (button == GLUT_RIGHT_BUTTON)
{
if (state == GLUT_DOWN)
CriaMenu();
}
else */
if(button==GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
if (pick) {
// Actualizar objectos selecionados
mx0 = x;
my0 = y;
checkSelection();
desenha();
} else {
// Iniciar acumuladores quando se clica no botão
mx0 = x;
my0 = y;
}
}

glutPostRedisplay();
}


//---------------------------------------------------------------------------
void MarcaPosicoes(int x, int y)
{

if (plano[x][y] == '0')
{
plano[x][y] = BANDEIRA;
}
else if (plano[x][y] == SUB)
{
int intBombas = 0;
plano[x][y] = SUBA;

//verificando se todas as posições estão com bomba
for (int intCount = intSubIni; intCount < (SUBMARINO+intSubIni); intCount++)
{
if (plano[intCount][y] == SUBA)
intBombas++;
}

//Indica que o Submarino foi descoberto por inteiro
if (intBombas == SUBMARINO)
{
for (int intCount = intSubIni; intCount < (SUBMARINO+intSubIni); intCount++)
{
plano[intCount][y] = SUBM;
chrFim[0] = '1';
}
}
}
else if (plano[x][y] == BAR)
{
int intBombas = 0;
plano[x][y] = BARA;

//verificando se todas as posições estão com bomba
for (int intCount = intBarIni; intCount < (BARCO+intBarIni); intCount++)
{
if (plano[intCount][y] == BARA)
intBombas++;
}

//Indica que o Barco foi descoberto por inteiro
if (intBombas == BARCO)
{
for (int intCount = intBarIni; intCount < (BARCO+intBarIni); intCount++)
{
plano[intCount][y] = BARM;
chrFim[1] = '1';
}
}
}
else if (plano[x][y] == NAV)
{
int intBombas = 0;
plano[x][y] = NAVA;

//verificando se todas as posições estão com bomba
for (int intCount = intNavIni; intCount < (NAVIO+intNavIni); intCount++)
{
if (plano[intCount][y] == NAVA)
intBombas++;
}

//Indica que o Navio foi descoberto por inteiro
if (intBombas == NAVIO)
{
for (int intCount = intNavIni; intCount < (NAVIO+intNavIni); intCount++)
{
plano[intCount][y] = NAVM;
chrFim[2] = '1';
}
}
}

glutPostRedisplay();


if (chrFim[0] == '1' && chrFim[1] == '1' && chrFim[2] == '1')
{
char chrOP;
setViewPoint(0);
desenha(); //Para que mostre o último barco antes de recomeçar ->
pick = 0;

time(&hor_fim);
tempo_final = difftime( hor_fim, hor_ini);
printf( "\nTempo de jogo: %6.0f segundos.\n", tempo_final);
printf("\nParabens, voce ganhou!\n");
printf("Deseja jogar novamente?<S/N>: ");
fflush(stdin); //->limpando o buffer...
scanf("%c", &chrOP);
if (chrOP == 'S' || chrOP == 's')
{
pick = 1;
init();
desenha();
}
}

}

//=======================================================================================
//=======================================================================================
// Carrega o arquivo BMP
int LoadBMP(char *filename)
{
#define SAIR {fclose(fp_arquivo); return -1;}
#define CTOI(C) (*(int*)&C)

GLubyte *image;
GLubyte Header[0x54];
GLuint DataPos, imageSize;
GLsizei Width,Height;

int nb = 0;


// Abre o arquivo e efetua a leitura do Header do arquivo BMP
FILE * fp_arquivo = fopen(filename,"rb");
if (!fp_arquivo)
return -1;
if (fread(Header,1,0x36,fp_arquivo)!=0x36)
SAIR;
if (Header[0]!='B' || Header[1]!='M')
SAIR;
if (CTOI(Header[0x1E])!=0)
SAIR;
if (CTOI(Header[0x1C])!=24)
SAIR;

// Recupera a informação dos atributos de
// altura e largura da imagem

Width = CTOI(Header[0x12]);
Height = CTOI(Header[0x16]);
( CTOI(Header[0x0A]) == 0 ) ? ( DataPos=0x36 ) : ( DataPos = CTOI(Header[0x0A]) );

imageSize=Width*Height*3;

// Efetura a Carga da Imagem
image = (GLubyte *) malloc ( imageSize );
int retorno;
retorno = fread(image,1,imageSize,fp_arquivo);

if (retorno !=imageSize)
{
free (image);
SAIR;
}

// Inverte os valores de R e B
int t, i;

for ( i = 0; i < imageSize; i += 3 )
{
t = image[i];
image[i] = image[i+2];
image[i+2] = t;
}

// Tratamento da textura para o OpenGL

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

// Faz a geraçao da textura na memória
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

fclose (fp_arquivo);
free (image);
return 1;
}

//---------------------------------------------------------------------------