5 Eylül 2021 Pazar

13- Mouse ile basit nesne karakter yönetimi

 Karakter nesne:



 3D alan üzerinde mausu tıkladığımız yerde tel küp kafes oluşmakta ve kırmızı küre (karakterimiz) işaretlenen
noktaya gitmektedir. Hedefe varmadan yeni bir hedef belirleyebilir yada sol mausu sürükleyerek peşinizden
koşturabilirsiniz.





 

  N_Karakter uygulamayı: indir

uygulama kodumuz aşağıda verilmiştir.






/// 3D ALANDA HEDEF BULMA
// Daha önce 2d alan üzerindeki yapmıs olduğum yön bulma algoritmasını
// bu 3d alana uyarladık. Daha da sadelestirilebilir.
// Farklı çözümlemeler muhakkak vardır.
// kullanmadığımız değişkenler kalmış olabilir

// 3d bir pencerede uzayda kaybolmama ve doğru konumlanma icin Nesneler her
// zaman bu 2 matrix arasına alınır.
//glPushMatrix(); nesne glPopMatrix();  nesnelerin zemine (istediğimiz yere) doğru 
//konumlanmasını sağlayan matrixlerdir
// Nesnelerin istediğimiz yere doğru konumlanması icin nesne bu ikisi arasında olmalıdır.


#include <iomanip>
#include<stdlib.h>
#include<stdio.h>
#include <gl/glaux.h>
#include <time.h>
#include <math.h>
#include <iostream>
#include <gl/freeglut.h>
#include <gl/gl.h>
#include <iostream>
#define ESC 27

bool karakterAl= false;
float GAZ= 0.0;

float lazer=0.0;
short dur,yon;
float iox,ioz,arax,araz;
int ay=0,ay1=0;

GLdouble ox=0.0,oy=0.0,oz=0.0;

float tcap,icap,xcap,fcap;

float scb,ascb=1;;/// solid cube ve anahtar

float d=0;

int anapen;
int altpen;
float der=0;
float rad=0,rado1;

float uz1,uz2;
static char bas[10];

float tx;
float my=30;
float tz;
float mx;
float mz=0;

float ty=0.1;

float x = 0.0, y = 9.0,z=-10; //
float deltaMove = 0.0; //


// Camera direction kamera yönü
float lx = 0.0, ly=-15,lz=0.1; // camera points initially along y-axis
float angle = 0.0; // angle of rotation for the camera direction
float deltaAngle = 0.0; // additional angle change when dragging

// Mouse drag control
int isDragging = 0; // true when dragging sürüklemek
int xDragStart = 0; // records the x-coordinate when dragging starts


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

using namespace std;

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

void harfYaz(char *s)
{
unsigned int i;
  for (i = 0; i < strlen (s); i++)
    glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, s[i]);
}

void harfYazak(char *s)
{
unsigned int i;
  for (i = 0; i < strlen (s); i++)
    glutBitmapCharacter (GLUT_BITMAP_HELVETICA_12, s[i]);
}

void kamera(int w, int h)
{
float ratio =  ((float) w) / ((float) h); // window aspect ratio
glMatrixMode(GL_PROJECTION); // projection matrix is active
glLoadIdentity(); // reset the projection
gluPerspective(60.0, ratio, 0.1, 150.0); // perspective transformation
glMatrixMode(GL_MODELVIEW); // return to modelview mode
glViewport(0, 0, w, h); // set viewport (drawing area) to entire window

}

void zeminTop()// zeminde belirli aralıklarla çoğaltacağımız topların prototipi
{
glColor3f(1.0, 1.0, 1.0);/// bazen farkında olmadan renkler karışabilir. Bu şekilde
                         /// beyaz bir filtre yaparak istediğimiz rengi elde ederiz.


  //glPushMatrix(); bir sonraki foksiyonda çoğaltma esnasında matrixleri kullandığımz için burada
  // kullanmasakda olur.

glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(0.16, 6, 6);

//glPopMatrix();
}


void alan()
{ int i, j;

// zeminimiz
glColor3f(0.0, 0.7, 0.0);
glTranslatef(0,0,0);
glBegin(GL_QUADS);
glVertex4f(-60.0,0, -60.0, 1);
glVertex4f(-60.0,0,  60.0, 1);
glVertex4f(60.0,0, 60.0, 1);
glVertex4f( 60.0,0, -60.0, 1);
glEnd();


// 11*11 121 adet zemine 2 birim arayla top yerlestiriyoruz.
for(i = -5; i < 6; i++)
for(j = -5; j < 6; j++) {
glPushMatrix();// nesnelerin zemine (istediğimiz yere) doğru konumlanmasını sağlayan matrix
glTranslatef(i*2.0,0 , j*2.0);
zeminTop();
glPopMatrix();// nesnelerin istediğimiz yere doğru konumlanmasını sağlayan 2. matrix
              // 3d uzayda kaybolmama ve doğru konumlama icin Nesneler her zaman bu 2 matrix arasına alınır.
}
}

//**********************************************************************************


void update(void)// yon tusları ile kamera hareket hızı
{

if (deltaMove) { // update camera position
mx += deltaMove * lx * 0.1;
mz += deltaMove * lz * 0.1;
}
glutPostRedisplay(); // redisplay everything
}
void koordinat()

{

    glPushMatrix();
glTranslatef(0,0.1,0);
glColor3f(0.0,0.0,1.0);
glLineWidth(1);
glBegin(GL_LINES);
glVertex3f(0.0,0,-20.0);
glVertex3f(0.0,0,20.0);
glColor3f(1.0,0.0,0.0);
glVertex3f(-20.0,0,0.0);
glVertex3f(20.0,0,0.0);
glEnd();   glPopMatrix();
}

void koorcapsd()
{

    glPushMatrix();
glTranslatef(0,0.2,0);
glColor3f(0.0,0.0,1.0);
glLineWidth(3);
glBegin(GL_LINES);


glVertex3f(ox,0,oz);
glVertex3f(0,0,0);
    glEnd();  glPopMatrix();



}//********************************************************

void karakter1()//******************************
{

{
glColor4f(0.9,0.2,0.0,1.0);
            glTranslatef (tx,-0.23 ,tz );
            glPushMatrix();
            glScalef(3,1,1);
             glRotatef(d,0,1,0); //önünü hedef yönüne döndürmek
             glutSolidSphere(0.50, 20, 20);
           glPopMatrix(); }


if(yon==1||yon==3)d=-rad*180/3.14;/// kendi içinde zıt
if(yon==2||yon==4)d=-1*rad*180/3.14;///bunlarda kendi içinde zıt

}


void karakter2()
{
   glColor3f(1.0,0.0,0.0);
            glTranslatef (tx,0.02 ,tz );
            glPushMatrix();
            glRotatef(d,0,1,0);//önünü hedef yönüne döndürmek

 glBegin(GL_TRIANGLES);
glVertex3f(-0.5,0,0.5);///glColor3f(0.0,1.0,0.0);
glVertex3f(-0.5,0,-0.5); ///glColor3f(1.0,0.0,0.0);
glVertex3f(1.0,0,0.0);
glEnd();


if(yon==1||yon==3)d=-rad*180/3.14;/// kendi içinde zıt
if(yon==2||yon==4)d=-1*rad*180/3.14;///bunlarda kendi içinde zıt

  glPopMatrix();
}///-------------------------------------



void adem()//  konum isaretleme tel kafesimiz
 {
    glColor3f(0.0, 0.0, 1.0);// mavi renk

  if(ascb==1){

         if(tx==ox)scb=0;else scb=1.0;
    {glPushMatrix();

glTranslatef (iox,0 , ioz );

        glutWireCube(scb);
         glPopMatrix();}
    }
 }//------------------------------


void klavye (unsigned char key, int x, int y)// klavyeden veri alma
{
  if(key==49){mz=0;my=30;ly=-15;  }// kamera bakış açısı üst
      if(key=='z'||key=='Z'){GAZ=0;}// durdur
      if(key=='x'||key=='X'){GAZ=0.1;}// hızı değiştir
      if(key=='a'||key=='A'){if(karakterAl==1)karakterAl=0;else karakterAl=1;}// karakter değistir
 if(key==32){tx=0;tz=0;mx=0;mz=0; ox=0;oz=0;ay=0;ay1=0;icap=0;fcap=0;rad=0;}// konum sıfırlama

      if(key==27){exit(0);}// kapat çık
      if(key==48){my=10;mz=-25;tx=0; ly=-0.2;}// kamera bakış açısı perspektif

}///-------------------------------------



   void yonler()

    { //  Daha önce 2d alan üzerindeki yapmıs olduğum yön bulma algoritmasını
                    // bu 3d alana uyarladık. Daha da sadelestirilebilir.
                    // Farklı çözümlemeler muhakkak vardır.


    switch(yon){

     case 1:
             if(tx>=ox+iox&&tz>=oz+ioz){GAZ=0;ox=tx;oz=tz;}
                                 if(ay==1 )
                                { lazer=GAZ;if(ox!=0 )ay1=1;
                                       if(ay1==1){
                                            tx+=cos( rad )*GAZ;
                                            tz+=sin( rad )*GAZ;
                                            }

                                }else {GAZ=0;tx=tx;tz=tz;}
                                                                      break;
    case 2:
          if(tx>=ox+iox&&tz<=oz+ioz){GAZ=0;ox=tx;oz=tz;}
                                 if(ay==1 )
                                { lazer=GAZ;if(ox!=0 )ay1=1;
                                       if(ay1==1){
                                            tx+=cos( rad )*GAZ;
                                            tz+=sin( rad )*GAZ;
                                            }

                                }else {GAZ=0;tx=tx;tz=tz;}

                                                                       break;
     case 3:
                     if(tx<=ox+iox&&tz<=oz+ioz){GAZ=0;ox=tx;oz=tz;}
                                 if(ay==1 )
                                { lazer=GAZ;if(ox!=0 )ay1=1;
                                       if(ay1==1){
                                            tx+=cos( rad )*GAZ;
                                            tz+=sin( rad )*GAZ;
                                            }


                                } else {GAZ=0;tx=tx;tz=tz;}

                                                                      break;
     case 4:
                     if(tx<=ox+iox&&tz>=oz+ioz){GAZ=0;ox=tx;oz=tz;}
                                 if(ay==1 )
                                { lazer=GAZ;if(ox!=0 )ay1=1;
                                       if(ay1==1){

                                            tx+=cos( rad )*GAZ;
                                            tz+=sin( rad )*GAZ;
                                            }


                                } else {GAZ=0;tx=tx;tz=tz;}
                                                                      break;


 glutPostRedisplay();

 }}//----------------------------------------------------------------------------------------------------

void renderScene()// 3d sahne dünyamız
{

  xcap=(ox*ox)+(oz*oz);// karakterimizin değişen
       xcap=sqrt(xcap) ;// hedefleri doğru bulması icin (uzaklık, çap alma işlemi)


// Clear color and depth buffers
glClearColor(0.0, 0.7, 1.0, 1.0); // sky color is light blue
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 glLoadIdentity();// uzay matrixini almak


gluLookAt(mx, my, mz,
      mx + lx,my + ly,mz + lz,
  0.0f,1.0f,0.0f);///  kamera yönetimi

      yonler();
      update();
      alan();
      koordinat();

glPushMatrix();
    glDepthMask(GL_FALSE);
    glTranslated(ox,oy,oz);// tel kafesin konumunu alma
    adem();/// telkafes (hedef isaretleme)
    glutSolidSphere(0.0,15,15);

    glDepthMask(GL_TRUE);
    glPopMatrix();

        if(karakterAl==true)karakter1();// top hedefe giden
        if(karakterAl==false)karakter2();// ücgen hedefe giden

      glutSwapBuffers();// görüntü alma
      glutPostRedisplay();// run time çalışma

}


void altkare(){//alt pencereyi çizgilerle ayırma

                             glColor3f(0.0,0.5,1.0);

                               glBegin(GL_LINES);

                         glVertex2f(0.0,-1.0);
                         glVertex2f(0.0,1.0);
                         glVertex2f(1.0,0.0);
                         glVertex2f(-1.0,0.0);
                         glVertex2f(-0.8,1.0);
                         glVertex2f(-0.8,-1.0);
                         glVertex2f(0.8,1.0);
                         glVertex2f(0.8,-1.0);

                           glEnd();;

}






void altRender()// alt pencerenin dünyası

{
   glClearColor(0.9, 0.8, 0.2, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

       glTexCoord4f(1, 0,0,1);
        glColor3f(0.7, 0.7, 0.7);
       glRectd(-0.25,-1.0,0.45,1);
       altkare();// alt pencereyi bölümlere ayırma


   glColor3f(0.0, 0.0, 0.0);
       sprintf (bas,"a: karakter al " );
       glRasterPos2f (-0.25, -0.8);
       harfYazak (bas);

       sprintf (bas,"yon tuslari-sag maus");
       glRasterPos2f (-0.25, 0.1);
       harfYazak (bas);

      sprintf (bas,"ox oz : %1.1f : %1.1f ",ox,oz );
      glRasterPos2f (0.05, 0.1);
      harfYaz (bas);


      sprintf (bas," tx  tz : %1.1f : %1.1f ",tx,tz );
      glRasterPos2f (0.05, -0.9);
      harfYaz (bas);

     if(yon==1)  {glColor3f(0.0, 0.0, 0.0);
      sprintf (bas,"1 Dogu");
      glRasterPos2f (-0.99, 0.1);
      harfYaz (bas);}

        if(yon==2)  {glColor3f(0.0, 0.0, 0.0);
      sprintf (bas,"2 kuzey");
      glRasterPos2f (-0.99, -0.8);
      harfYaz (bas);}

       if(yon==4)  {glColor3f(0.0, 0.0, 0.0);
      sprintf (bas,"4 Guney");
      glRasterPos2f (0.80, 0.1);
      harfYaz (bas);}

      if(yon==3)  {glColor3f(0.0, 0.0, 0.0);
      sprintf (bas,"3 Bati");
      glRasterPos2f (0.66, -0.9);
      harfYaz (bas);}

      {glColor3f(0.0, 0.0, 0.0);
      sprintf (bas,"x: Gaz=0.1");
      glRasterPos2f (0.46, -0.8);
      harfYazak (bas);}

           glColor3f(0.0, 0.0, 0.0);
     sprintf (bas,"  gaz %1.2f  ",GAZ );
      glRasterPos2f (0.8, -0.8);
      harfYaz (bas);
/// ************************

        glColor3f(0.0, 0.0, 0.0);
      sprintf (bas,"z: Gaz=0.0");
      glRasterPos2f (0.45, 0.18);
      harfYazak (bas);


      glColor3f(0.0, 0.0, 0.0);

      sprintf (bas,"drc:%1.0f ",d);
      glRasterPos2f (-0.5, -0.8);
      harfYaz (bas);

      sprintf (bas," rad:%1.1f ",rad);///= 0,0174
      glRasterPos2f (-0.5, 0.1);
      harfYaz (bas);
     sprintf (bas,"0 ve 1 kamera acisi ");
     glRasterPos2f (-0.79, 0.1);
      harfYazak (bas);

       sprintf (bas," xcap: %1.0f ",xcap);
       glRasterPos2f (-0.78, -0.8);
       harfYaz (bas);


/// **************************
     glutSwapBuffers();/// sürekli görüntü alma
     glutPostRedisplay();///sürekli döngü run time anlık veri alma
}


void pressSpecialKey(int key, int xx, int yy)
{
switch (key) {
case GLUT_KEY_UP : deltaMove = 0.30; break;// kamera tuş yönetimi
case GLUT_KEY_DOWN : deltaMove = -0.30; break;// kamera tuş yönetimi
}
}

void releaseSpecialKey(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_UP : deltaMove = 0.0; break;// tus yukarda kamerayı durdur
case GLUT_KEY_DOWN : deltaMove = 0.0; break;// tus yukarda kamerayı durdur
}
}


//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx



void mouseMove(int x, int y) // sürekli maus konumunu  almak (basarak yada basmadan sürüklerken)
                             // sürükleme esnasındaki sürekliliği bu anlık
                              //konum yakalama fonksiyunuyla yapıyoruz. glutMotionFunc(mouseMove);
{   ascb=0;
if (isDragging) { // only when dragging
// update the change in angle
deltaAngle = (x - xDragStart) * 0.005;
// camera's direction is set to angle + deltaAngle
lx = -sin(angle + deltaAngle);
lz = cos(angle + deltaAngle);
}


///*************************************************************
 GLint viewport[4];// burdan
     GLdouble modelview[16],projection[16];
     GLfloat wx=x,wy,wz;

    glGetIntegerv(GL_VIEWPORT,viewport);
    y=viewport[3]-y;
    wy=y;
    glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
    glGetDoublev(GL_PROJECTION_MATRIX,projection);
    glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&wz);
    gluUnProject(wx,wy,wz,modelview,projection,viewport,&ox,&oy,&oz);// bu arada ki kod bloku 3d uzayda mausun tıkladığı xyz konumunu bize verir
                                                                     // bunu internette ki bir uygulamadan aldım. O uygulamayıda blogda vereceğim inşallah.
                                                                     // burada fonksiyon sonuna kadar olan bölümü bir alttaki
                                                                     //tıklanan maus fonksiyonunda da kullanacağız.
             if(xcap!=tcap) {arax=tx;araz=tz;iox=arax;ioz=araz;
                     rad=atan2(araz,arax); }// hedefe varmadan hedef değiştiğinde yeni hedef konumunu almak

                  uz1=ox;   uz2=oz;  ///x z kordinatlarinin atanmasi
   rad=atan2(uz2,uz1);///2 nokta arasindaki aciyi alma


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

           if(ox>0&&oz>0) {yon=1;ay=1;} ///  dogu

         if(ox>0&&oz<0) {yon=2;ay=1; } /// kuzey

  if(ox<0&&oz<0) {yon=3; ay=1;} /// bati

                        if(ox<0&&oz>0) {yon=4; ay=1;} /// guney


}//<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>


void murat(int button, int state, int x, int y) // ** tıklanan  maus **
                                                // sağ kulak ile kamera bakış açısı sol kulak konum alma)
{

if (button == GLUT_RIGHT_BUTTON) { // sağ maus basılı iken ekran yönetimi
     ascb=0;ay=0;
if (state == GLUT_DOWN) { // left mouse button pressed
isDragging = 1; // start dragging
xDragStart = x; // save x where button first pressed

}
else  { /* (state = GLUT_UP) */
angle += deltaAngle; // update camera turning angle
isDragging = 0; // no longer dragging
}
}

///  ----------------------------------------------------------
switch(button) {
case GLUT_LEFT_BUTTON :  // sol buton kullan

{
     ascb=1;
 if(state == GLUT_DOWN) {  iox=ox;ioz=oz;///sol buton basıldığında  koordinat ataması ***
                               GAZ=0.03;// ilk hız atama

 GLint viewport[4];// buradan (3d uzayda xyz konumunu verir)
     GLdouble modelview[16],projection[16];
     GLfloat wx=x,wy,wz;

    glGetIntegerv(GL_VIEWPORT,viewport);
    y=viewport[3]-y;
    wy=y;
    glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
    glGetDoublev(GL_PROJECTION_MATRIX,projection);
    glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&wz);
    gluUnProject(wx,wy,wz,modelview,projection,viewport,&ox,&oy,&oz);// buraya 3d 
//uzayda xyz konumunu verir

                    if(xcap!=tcap) {arax=tx;araz=tz;iox=arax;ioz=araz;

       rad=atan2(araz,arax);// hedefe varmadan hedef değiştiğinde 
//yeni hedef konumunu almak
          }
                  uz1=ox;   uz2=oz;  // x z kordinatlarinin atanmasi (y sürekli 0 karakterlerimiz için)
   rad=atan2(uz2,uz1);// 2 nokta (x,z) arasindaki aciyi alma


           ///---------yön bulma------------------

            if(ox>0&&oz>0) {yon=1;ay=1;} ///  dogu

         if(ox>0&&oz<0) {yon=2;ay=1; } /// kuzey

  if(ox<0&&oz<0) {yon=3; ay=1;} /// bati

                        if(ox<0&&oz>0) {yon=4; ay=1;} /// guney

                          break;
            }
        }
}
}//-------------------------------------------------------

//----------------------------------------------------------------------
// Main program  - standard GLUT initializations and callbacks
//----------------------------------------------------------------------
int main(int argc, char **argv)
{
// general initializations
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(5, 5);
glutInitWindowSize(800,600);
    anapen=glutCreateWindow("OpenGL/Mekke Program");

// register callbacks
glutReshapeFunc(kamera); // window reshape callback
glutDisplayFunc(renderScene); // (re)display callback

glutIgnoreKeyRepeat(1); // ignore key repeat when holding key down
glutMouseFunc(murat); // process mouse button push/release

glutMotionFunc(mouseMove); // process mouse dragging motion
glutKeyboardFunc(klavye);
glutSpecialFunc(pressSpecialKey); // process special key pressed

glutSpecialUpFunc(releaseSpecialKey); // process special key release
    glEnable(GL_DEPTH_TEST);// subwin den once olmalı

    altpen=glutCreateSubWindow(anapen,5,565,790,34);//pen,x-y,weight-high
glutDisplayFunc(altRender);


glutMainLoop();

return 0; // this is just to keep the compiler happy
}

Hiç yorum yok:

Yorum Gönder