Ir para conteúdo


- - - - -

Opengl jogo


  • Por favor inicie sessão para responder
16 respostas a este tópico

#1 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 15:30

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.

Código :
#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

#2 KTachyon

KTachyon

    Unsigned User

  • Moderador
  • PipPipPipPipPipPip
  • 3512 mensagens

Publicado 02 de Julho de 2012 - 15:46

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).



#3 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 15:59

Ver MensagemKTachyon, em 02 de Julho de 2012 - 15:46, disse:

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).

Código :
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?

Código :
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;
         }
}

Editado por WolfmanZ, 02 de Julho de 2012 - 16:01.


#4 KTachyon

KTachyon

    Unsigned User

  • Moderador
  • PipPipPipPipPipPip
  • 3512 mensagens

Publicado 02 de Julho de 2012 - 16:03

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?

#5 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 16:13

Ver MensagemKTachyon, em 02 de Julho de 2012 - 16:03, disse:

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.

#6 KTachyon

KTachyon

    Unsigned User

  • Moderador
  • PipPipPipPipPipPip
  • 3512 mensagens

Publicado 02 de Julho de 2012 - 16:20

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.

#7 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 16:22

Ver MensagemKTachyon, em 02 de Julho de 2012 - 16:20, disse:

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?

Editado por WolfmanZ, 02 de Julho de 2012 - 16:28.


#8 KTachyon

KTachyon

    Unsigned User

  • Moderador
  • PipPipPipPipPipPip
  • 3512 mensagens

Publicado 02 de Julho de 2012 - 16:30

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.

Código (C):
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.

#9 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 16:37

Ver MensagemKTachyon, em 02 de Julho de 2012 - 16:30, disse:

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.

Código (C):
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)

#10 KTachyon

KTachyon

    Unsigned User

  • Moderador
  • PipPipPipPipPipPip
  • 3512 mensagens

Publicado 02 de Julho de 2012 - 16:49

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


#11 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 16:51

Ver MensagemKTachyon, em 02 de Julho de 2012 - 16:49, disse:

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

Código :
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

Editado por WolfmanZ, 02 de Julho de 2012 - 17:00.


#12 KTachyon

KTachyon

    Unsigned User

  • Moderador
  • PipPipPipPipPipPip
  • 3512 mensagens

Publicado 02 de Julho de 2012 - 17:04

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)

#13 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 17:28

Código :
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

#14 KTachyon

KTachyon

    Unsigned User

  • Moderador
  • PipPipPipPipPipPip
  • 3512 mensagens

Publicado 02 de Julho de 2012 - 17:39

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.

#15 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 18:00

pois já meti a funcionar!

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

Código :
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[i] na nave tive de tirar as variaveis, neste caso basta fazer translaçoes?

#16 KTachyon

KTachyon

    Unsigned User

  • Moderador
  • PipPipPipPipPipPip
  • 3512 mensagens

Publicado 02 de Julho de 2012 - 18:06

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

#17 WolfmanZ

WolfmanZ

    Boolean User

  • Membro
  • PipPipPip
  • 131 mensagens

Publicado 02 de Julho de 2012 - 18:09

Ver MensagemKTachyon, em 02 de Julho de 2012 - 18:06, disse:

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

Código :
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

Editado por WolfmanZ, 03 de Julho de 2012 - 02:19.