//==================================================================
// 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;
}
//---------------------------------------------------------------------------
|