• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Sign in to follow this  
Followers 0
WolfmanZ

Opengl jogo

17 posts in this topic

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

0

Share this post


Link to post
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).

0

Share this post


Link to post
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
0

Share this post


Link to post
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?

0

Share this post


Link to post
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?

Sim acho que estão.

0

Share this post


Link to post
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.

0

Share this post


Link to post
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
0

Share this post


Link to post
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.

0

Share this post


Link to post
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)

0

Share this post


Link to post
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

0

Share this post


Link to post
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
0

Share this post


Link to post
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)

0

Share this post


Link to post
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

0

Share this post


Link to post
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.

0

Share this post


Link to post
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?

0

Share this post


Link to post
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.

0

Share this post


Link to post
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
0

Share this post


Link to post
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
Sign in to follow this  
Followers 0