Jump to content

Opengl jogo


WolfmanZ

Recommended Posts

Boas tardes tenho um projecto para acabar que é o jogo asteroids.

teclas: "W" move nave na direcçao da "ponta" desta, "A" roda a nave para a esquerda, "D" roda a nave para a direita "Espaço" dispara tiros

Problema 1 - ao rodar e avançar a nave a nave nao roda sobre o seu centro mas sim sobre o ponto (0,0,0).

Problema 2 - os tiros ao rodar a nave perdem a direcçao da nave.

#include<stdlib.h>
#include<glut.h>  
#include <time.h>
#include <math.h>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>


using namespace std;
float X_CENTRE = 0.0;
float Y_CENTRE = 0.0;
float rot = 0.0;
float AsteroidX[6];
float AsteroidY[6];
float StarX[250];
float StarY[250];
float angle = 0;
float bulletAngle = 0;
bool fired = false;
float BulletLocX = 0.0;
float BulletLocY = 0.0;
bool collision = false;
bool deathcount[6];
float killed = 0.0;
bool stardrawn = false;
float score = 0.0;
char ascore [6];
void drawship()
{
    glColor3f(1, 1, 1);
    glLoadIdentity();
    glRotatef(angle,0.0,0.0,1.0);
  glBegin(GL_POLYGON);
  glVertex2f( X_CENTRE, Y_CENTRE + 5);
  glVertex2f( X_CENTRE + 5, Y_CENTRE - 9);
  glVertex2f( X_CENTRE, Y_CENTRE -2);
  glVertex2f( X_CENTRE -5, Y_CENTRE-9);
  glEnd();
  glFlush();

}
void XYrand()
{
    for(int i = 0; i < 6; i++){
    float k = rand() % 200;
    k = k - 100;
    if(k < -90){
		    k = -90;
    }
    if(k > 90){
		    k = 90;
    }
    AsteroidX[i] = k;
}
for(int i = 0; i < 6; i++){
    float z = rand() % 200;
    z = z - 100;
    if(z < -90){
		    z = -90;
    }
    if(z > 90){
		    z = 90;
    }
    AsteroidY[i] = z;
   }
}
void drawAsteroid()
{
glColor3f(0.45, 0.2, 0.0);
glLoadIdentity();
for(int i = 0; i < 6; i++){
    if(deathcount[i]){
    glBegin(GL_POLYGON);
    glVertex2f(AsteroidX[i] + 9,AsteroidY[i]);
    glVertex2f(AsteroidX[i], AsteroidY[i] - 9);
    glVertex2f(AsteroidX[i] - 9, AsteroidY[i]);
    glVertex2f(AsteroidX[i], AsteroidY[i] + 9);
    glEnd();
    }
}
glFlush();
}
void drawBullet()
{
    glPushMatrix();
 glTranslatef(X_CENTRE,Y_CENTRE,0);
    glRotatef(angle,0.0,0.0,1.0);
    glColor3f(1, 0, 0);
    glPointSize(3.0);
    glBegin(GL_POINTS);
    glVertex2f(X_CENTRE+BulletLocX , Y_CENTRE+BulletLocY);
    glEnd();
    glPopMatrix();
}
void renderBitmapString( float x,  float y, float z,void *font, char *string) { 
   char *c;
   glRasterPos3f(x, y,z);
   for (c=string; *c != '\0'; c++) {
    glutBitmapCharacter(font, *c);
   }
}
void drawScore()
{
    sprintf(ascore,"Score: %f",score);
    glLoadIdentity();

}
void keyinput(int key, int x, int y)
{
    switch(key){
 case GLUT_KEY_UP:
  Y_CENTRE = Y_CENTRE + 1;
  break;
 case GLUT_KEY_DOWN:
  Y_CENTRE = Y_CENTRE - 1;
  break;
  break;
    case GLUT_KEY_LEFT:
		    angle = angle + 5;
		    break;
    case GLUT_KEY_RIGHT:
		    angle = angle - 5;
		    break;
    }
}
void shoot(unsigned char key,int x, int y){
    switch(key){
    case 32:
		    if(fired != true){
		    bulletAngle = angle +90;
		    bulletAngle = (bulletAngle * 3.142)/180;
		    }
	  fired = true;
    break;
    }
}
void bulletPath(){
    BulletLocX = BulletLocX + (5*cos(bulletAngle)/10);
    glutPostRedisplay();
    BulletLocY = BulletLocY + (5*sin(bulletAngle)/10);
    glutPostRedisplay();
}
void CollisionTest()
{
    for(int i = 0; i < 6; i++){
		    if(deathcount[i])
		    {
		    int j = AsteroidX[i] - BulletLocX;
		    int k = AsteroidY[i] - BulletLocY;
		    if((k < 9 && k > -9)&&(j < 9 && j > -9))
		    {
				    collision = true;
				    deathcount[i] = false;
				    AsteroidX[i] = 200;
				    AsteroidY[i] = 200;
				    killed++;
				    score++;
				    break;
	    }
		    }
}
}
void reshape(int width, int height)
{
  glMatrixMode(GL_PROJECTION);
  glViewport(0, 0, width, height);
  glOrtho(-100, 100, -100, 100, -100.0, 100.0);
  glMatrixMode(GL_MODELVIEW);
}
void display(void)
{ 
  glClear (GL_COLOR_BUFFER_BIT);
  glClearColor(0.0, 0.0, 0.0, 1.0);
  glPointSize(1.0);
  drawBullet();
  drawAsteroid();
  drawship();
  drawScore();
  if (fired)
  {
	   bulletPath();
  }
  CollisionTest();
  if(BulletLocX > 100.0 || BulletLocX < -100.0 || BulletLocY > 100.0 || BulletLocY < -100.0 || collision == true)
  {
	   collision = false;
	   fired = false;
	   BulletLocX = X_CENTRE;
	   BulletLocY = Y_CENTRE;
  }
  if(killed == 6){
	   for(int i = 0; i < 6; i++){
			   deathcount[i] = true;
			   killed = 0;
			   XYrand();
			   drawAsteroid();
	   }
  }
  renderBitmapString( -90,90,0.0,GLUT_BITMAP_HELVETICA_12,ascore);
  glutSwapBuffers();
}
void init(void)
{
    srand((unsigned)time(0));
    XYrand();
for(int i = 0; i < 6; i++){
    deathcount[i] = true;
}
  glClearColor (0.0, 0.0, 0.0, 0.0);  
}

int main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize (400, 400);
  glutInitWindowPosition (100, 100);
  glutCreateWindow ("Asteroids");

  init();
  glutDisplayFunc(display);
  glutSpecialFunc(keyinput);
  glutKeyboardFunc(shoot);
  glutReshapeFunc(reshape);
  glutIdleFunc(display);
  glutMainLoop();
  return 0;
}

Agradeço a ajuda ! Cumps

Link to comment
Share on other sites

Tens que fazer uma translação para a posição onde queres rodar a nave. Se estás a desenhar a nave a partir do (0,0,0), é normal que a nave esteja a ser rodada no ponto (0,0,0).

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Link to comment
Share on other sites

Tens que fazer uma translação para a posição onde queres rodar a nave. Se estás a desenhar a nave a partir do (0,0,0), é normal que a nave esteja a ser rodada no ponto (0,0,0).

glPushMatrix();
 glTranslatef(X_CENTRE, Y_CENTRE, 0); aqui faz a translaçao
 glColor3f(1, 1, 1);
 glLoadIdentity();
 glRotatef(angle,0.0,0.0,1.0);
glBegin(GL_POLYGON);
glVertex2f( X_CENTRE, Y_CENTRE + 5);
glVertex2f( X_CENTRE + 5, Y_CENTRE - 9);
glVertex2f( X_CENTRE, Y_CENTRE);
glVertex2f( X_CENTRE -5, Y_CENTRE-9);
glEnd();
glFlush();
glPopMatrix();

Será que o problema pode estar aqui no que faz as teclas?

void keyinput(int key, int x, int y)
{
 switch(key){
case GLUT_KEY_UP:
Y_CENTRE = Y_CENTRE + 1;
break;
case GLUT_KEY_DOWN:
Y_CENTRE = Y_CENTRE - 1;
break;
 case GLUT_KEY_LEFT:
		 angle = angle + 5;
		 break;
 case GLUT_KEY_RIGHT:
		 angle = angle - 5;
		 break;
 }
}
Edited by WolfmanZ
Link to comment
Share on other sites

Repara bem. Estás a fazer uma translação, tudo bem. Mas onde é que estás efectivamente a desenhar a nave? Será que os vértices estão efectivamente a ser desenhados no local para onde fizeste a translação?

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Link to comment
Share on other sites

Tens que centrar a nave no ponto para onde fizeste a translação para que a rotação faça efeito. Estás a adicionar o X_CENTRE e Y_CENTRE à posição dos vértices. A rotação vai fazer efeito sobre o ponto onde estás a fazer a translação, o que faz com que a nave gire em torno de um ponto em vez de rodar.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Link to comment
Share on other sites

Tens que centrar a nave no ponto para onde fizeste a translação para que a rotação faça efeito. Estás a adicionar o X_CENTRE e Y_CENTRE à posição dos vértices. A rotação vai fazer efeito sobre o ponto onde estás a fazer a translação, o que faz com que a nave gire em torno de um ponto em vez de rodar.

Então e como faço para a por a rodar?

Tenho de fazer um rotatef para os 4 pontos da nave?

Edited by WolfmanZ
Link to comment
Share on other sites

Não podes adicionar os valores X_CENTRE e Y_CENTRE. Essa deslocação já é feita pela translação. Quando desenhas os vértices já estás a desenha-los no local para onde fizeste a translação, logo não precisas de voltar a somar esse valor aos vértices. Simplesmente desenhas a nave como se a quisesses desenhar no centro e utilizas a translação para deslocar a nave para o sítio que queres que seja o centro.

glBegin(GL_POLYGON);
   glVertex2f( 0, 5);
   glVertex2f( 5, -9);
   glVertex2f( 0, 0);
   glVertex2f( -5, -9);
glEnd();

Claro que, não me parece que este polígono dê alguma coisa de correcto, mas isso é outro problema que também deves ter que resolver.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Link to comment
Share on other sites

Não podes adicionar os valores X_CENTRE e Y_CENTRE. Essa deslocação já é feita pela translação. Quando desenhas os vértices já estás a desenha-los no local para onde fizeste a translação, logo não precisas de voltar a somar esse valor aos vértices. Simplesmente desenhas a nave como se a quisesses desenhar no centro e utilizas a translação para deslocar a nave para o sítio que queres que seja o centro.

glBegin(GL_POLYGON);
glVertex2f( 0, 5);
glVertex2f( 5, -9);
glVertex2f( 0, 0);
glVertex2f( -5, -9);
glEnd();

Claro que, não me parece que este polígono dê alguma coisa de correcto, mas isso é outro problema que também deves ter que resolver.

Pois já o mudei para um triangulo mas assim ao usar a tecla W ele vai para cima e nao para a frente, isto é, na direcçao do vertice (0,5)

Link to comment
Share on other sites

Porque tens que calcular a direcção a partir do ângulo. Ou seja, tens que arranjar um vector que, consoante o ângulo, te move a nave na direcção certa.

Basicamente é só utilizares trigonometria:

dir_x = sin(angle) * mov

dir_y = cos(angle) * mov

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Link to comment
Share on other sites

Porque tens que calcular a direcção a partir do ângulo. Ou seja, tens que arranjar um vector que, consoante o ângulo, te move a nave na direcção certa.

Basicamente é só utilizares trigonometria:

dir_x = sin(angle) * mov

dir_y = cos(angle) * mov

pois o problema é a trigonometria mas esse dir_x e dir_y vao ser o X_CENTRE e Y_CENTRE certo?

OBRIGADO pela ajuda que tens dado andava a 2 dias nisto.

P.S. ja consegui meter

case GLUT_KEY_UP:
  X_CENTRE = X_CENTRE + cos(90 *3.14/180 + angle*3.14/180);
  Y_CENTRE = Y_CENTRE + sin(90 *3.14/180 + angle*3.14/180);
  BulletLocY = BulletLocY + sin(90 *3.14/180 + angle*3.14/180);
  BulletLocX = BulletLocX + cos(90 *3.14/180 + angle*3.14/180);

so que queria em vez de para a nave se mover ter de carregar nas teclas ela estar sempre a andar para a frente e para para mudar de direcçao tinha de rodar a nave e andar para o sentido oposto, isto é, fazer com que a nave tenha aceleraçao

Edited by WolfmanZ
Link to comment
Share on other sites

Neps, o dir_x e o dir_y têm que ser incrementos para o X_CENTRE e Y_CENTRE. O mov é o valor bruto que queres incrementar (e que representa a velocidade da nave).

Ou seja, se tiveres um factor de velocidade (mov) de 1 por segundo (isto depois depende de muita coisa e experimentar valores mais ou menos a olho para veres a que é que isso corresponde no teu jogo, visto que esses incrementos não são feitos por segundo, mas por ciclo), se carregares na tecla durante 2 segundos, vais mover a nave 2 unidades na direcção para onde a nave estiver a apontar.

Se esta direcção for 45 graus (π/4 em radianos), a tua nave vai mover-se (0.707, 0.707) por segundo, ou seja no final dos dois segundos o (X_CENTRE, Y_CENTRE) será (1.414, 1.414)

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Link to comment
Share on other sites

case GLUT_KEY_UP:
  X_CENTRE = X_CENTRE + cos(90 *3.14/180 + angle*3.14/180)*mov;
  Y_CENTRE = Y_CENTRE + sin(90 *3.14/180 + angle*3.14/180)*mov;
  BulletLocY = BulletLocY + sin(90 *3.14/180 + angle*3.14/180)*mov;
  BulletLocX = BulletLocX + cos(90 *3.14/180 + angle*3.14/180)*mov;

sim mas assim ta andar bem so que queria por em vez de estar sempre a carregar no W que ela andasse constantemente

Link to comment
Share on other sites

Pah, isso já é outra questão. Basicamente estás a actualizar a posição quando o utilizador carrega na tecla e a mantém carregada. Se queres que a velocidade se mantenha tens que pensar que a tecla apenas define o vector de velocidade, que tem que ser actualizada noutro lado, de forma a que a actualização seja constante.

Ou seja, sempre que vais voltar a fazer update, incrementas o vector de velocidade à posição da nave. Quando começas o jogo, a velocidade é zero, logo a velocidade inicial é (0, 0). Quando o utilizador carrega no W, alteras a velocidade para se adequar ao ângulo.

Se depois rodares e "acelerares", tens que ter em conta que o vector de velocidade tem que ir "lentamente" combatendo a inércia que lhe deste anteriormente, caso contrário há uma mudança brusca de direcção.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Link to comment
Share on other sites

pois já meti a funcionar!

Entretanto tenho de dar movimento ao asteroids so que acho que tenho um problema parecido ao da nave:

float AsteroidX[6];
float AsteroidY[6];
void drawAsteroid()
{
glColor3f(0.45, 0.2, 0.0);
glLoadIdentity();
for(int i = 0; i < 6; i++){
    if(deathcount[i]){
    glBegin(GL_POLYGON);
    glVertex2f(AsteroidX[i] + 9,AsteroidY[i]);
    glVertex2f(AsteroidX[i], AsteroidY[i] - 9);
    glVertex2f(AsteroidX[i] - 9, AsteroidY[i]);
    glVertex2f(AsteroidX[i], AsteroidY[i] + 9);
    glEnd();
    }
}
glFlush();

o AsteroidX na nave tive de tirar as variaveis, neste caso basta fazer translaçoes?

Link to comment
Share on other sites

Sim. Cada asteroide vai ter uma translação (AndroidX, AndroidY) e desenhas apenas os vértices centrados na posição actual.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Link to comment
Share on other sites

Sim. Cada asteroide vai ter uma translação (AndroidX, AndroidY) e desenhas apenas os vértices centrados na posição actual.

void drawAsteroid()
{
mov=mov+0.01;
for(int i = 0; i < 6; i++){   //limites janela asteroids
	if(i%2==0){
	andax[i] = mov+AsteroidX[i];
	anday[i] = mov+AsteroidY[i];
	}
	else{
	andax[i] = -mov+AsteroidX[i];
	anday[i] = -mov+AsteroidY[i];
	}
}
for(int i = 0; i < 6; i++){
	if(andax[i] > 91){
		andax[i]=andax[i]-200;
	}
	if(andax[i] < -91){
		andax[i]=andax[i]+200;
	}
	if(anday[i] > 91){
		anday[i]=anday[i]-200;
	}
	if(anday[i] < -91){			
		anday[i]=anday[i]+200;
	}
}
glColor3f(0.45, 0.2, 0.0);
glLoadIdentity();
for(int i = 0; i < 6; i++){
       if(deathcount[i]){
       glBegin(GL_POLYGON);
	glVertex2f(andax[i] + 9, anday[i]);
       glVertex2f(andax[i], anday[i] - 9);
       glVertex2f((andax[i] - 9), anday[i]);
       glVertex2f(andax[i], anday[i] + 9);
       glEnd();
       }
}
glFlush();
}

isto esta a funcionar mais ao menos bem porque os limites estao bem so que passado um tempo os asteroids desaparecem. preciso de ajuda urgente

Edited by WolfmanZ
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.