Ubuntu'da Bilgisayar Grafikleri için C ile OpenGL Kullanımı

Başlatan Hatti, 24 Nisan 2011 - 13:40:34

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

Hatti

Başlamak için şu paketleri yükleyelim:
sudo apt-get install freeglut3 freeglut3-dev


Şurada gerekli olabilecek bazı paketler için detaylı bir liste var ama ihtiyaç duydukça yüklemeniz daha iyi olur.


Sonrasında /usr/include/GL dizini altındaki freeglut_std.h, glu.h, gl.h başlık dosyalarını incelemeniz bir ön fikir verebilir.


Sisteminizin desteklediği işleyici ve sürümünü öğrenmek için uçbirimden aşağıdaki komutu kullanabilirsiniz:
glxinfo | grep version


Kaynak kodun içine açıklamalar yazarak bir giriş yapmaya çalışacağım. Daha detaylı bilgi için yazının sonuna birkaç bağlantı ekleyeceğim.
Şimdi ilk programı yazalım:
// merhabaGL.c

#include <GL/glut.h>
#include <stdio.h>

static void sahneyiyapilandir(void){
glClearColor(0.5f, 0.0f, 0.5f, 1.0f);
/* Penceremizin içinin hangi renk değerleri ile temizleneceğini
* belirliyoruz. Bunu kırmızı, yeşil ve mavi renk değerlerini
* girerek yapıyoruz (RGB). Bir de alfa kanalı var, ona da saydamlık
* değeri diyebiliriz. Sayıların sonunda bulunan f değerlerin float
* türünden gerçek sayı olduğunu anlatıyor. Bu değerler 0.0 ile 1.0
* arasında olacaklar.
*
* glClearColor hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glClearColor.xml
*
* Bazı renkler için değerler şöyle;
* Kara için : 0.0, 0.0, 0.0
* Ak için : 1.0, 1.0, 1.0
* Kırmızı için : 1.0, 0.0, 0.0
* Yeşil için : 0.0, 1.0, 0.0
* Mavi için : 0.0, 0.0, 1.0
*/
}

static void sahneyigoster(void){
glClear(GL_COLOR_BUFFER_BIT);
/* Yeni oluşturulacak sahne için temizlik yapıyoruz. Bu temizlik
* sırasında ekran glClearColor ile belirlediğimiz renge boyanacak.
*
* glClear hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml
*/

glColor3f(1.0f, 1.0f, 1.0f);
/* Elimize bir fırça aldık. Daha doğrusu bir renk seçtik. Komutta geçen
* 3, üç değer gireceğimizi, f ise değerlerin float türünde olacağını
* gösteriyor.
*
* glColor hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml
*/

glBegin(GL_POINTS);
/* Bir çizime başladığımızı belirtiyoruz. GlBegin ifadesi GL_POINTS,
* GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES,
* GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP,
* GL_POLYGON değerlerini alabilir. Biz burada nokta çizeceğimizi
* belirttik.
*
* glBegin ve glEnd hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml
*/

glVertex2f(0.0f, 0.0f);
/* Kartezyen koordinat sisteminde x=0, y=0 noktasını yani tam olarak
* pencerenin ortasını gösteriyor. 2f iki değer alacağını ve değerlerin
* float türünden olacağını anlatıyor. Ayrıca pencerenin sağ-üst tarafı
* ++ bölgesi, sağ-alt tarafı +- bölgesi, sol-üst tarafı -+ bölgesi ve
* sol-alt tarafı -- bölgesi.
*
* glVertex hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml
*/

glEnd();
/* Çizimi bitirdiğimizi gösteriyoruz.
*/

glFlush();
/* Sahneyi göstermek için perdeyi açıyoruz.
*
* glFlush hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml
*/
}

int main (int argc, char **argv){
glutInit(&argc, argv);
/* Kütüphaneyi kullanabilmek için onu başlatıyoruz.
*
* glutInit hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node10.html
*/

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
/* Pencere görüntü modunu RGBA ve tek tamponlu olarak belirliyoruz.
*
* glutInitDisplayMode hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node12.html
*/

glutCreateWindow("GNU/Linux");
/* Yeni bir pencere oluşturduk.
*
* glutCreateWindow hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node16.html
*/

sahneyiyapilandir();
/* Bazı tanımlamalar için bir işlev.
*/

glutDisplayFunc(&sahneyigoster);
/* Ekrana çizdirmek için kullanacağımız işlev.
*
* glutDisplayFunc hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node46.html
*/

glutMainLoop();
/* Ana döngüye giriş.
*
* OpenGL kütüphanesini ve ek kitaplıklarını kullanmamız için freeglut
* araç takımını kullanmamız şart değil. Ancak işleri çok kolaylaştırıyor.
* Şu kaynak kodu win32 altında derleseniz yine çalışacaktır.
*
* glutMainLoop hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node14.html
*/

return(0);
/* Bu satırın bir önemi yok.
*/
}




Derlemek için:
gcc -lGL -lGLU -lglut merhabaGL.c -o merhabaGL


Çalıştırmak için:
./merhabaGL


Her şey yolunda gittiyse sonucu görmüş olmanız gerekir. Biraz daha geliştirelim. İkinci program:
// birazdahaGL.c

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#define AK 1.0f, 1.0f, 1.0f
#define MOR 0.5f, 0.0f, 0.5f

static int sahnelemesayaci=0;
/* Bir sayaç koyalım.
*/

static void sahneyiyapilandir(void){
glClearColor(MOR, 1.0f);
}

static void sahneyigoster(void){
glClear(GL_COLOR_BUFFER_BIT);

int aci=0, olcek=0;
double kx=0, ky=0;

glColor3f(AK);
glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f);
glEnd();

for (olcek=1; olcek<15 ; olcek++){
glBegin(GL_POINTS);
for(aci = 1; aci <= 360; aci++) {
kx = sin(((double)aci)*(M_PI/180))/(float)olcek;
ky = cos(((double)aci)*(M_PI/180))/(float)olcek;
glVertex2f(kx,ky);
}
glEnd();
}

glFlush();
sahnelemesayaci++;
}

static void temizle(void){
printf("Sahneyi %d kez gosterdim.\n",sahnelemesayaci);
}

int main (int argc, char **argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);

glutInitWindowSize(500, 500);
/* Pencere boyutunu kendimiz belirledik. Buraya int türünden iki değer
* girmemiz gerekiyor. Birincisi penceremizin piksel olarak genişliği,
* ikincisi ise yine piksel olarak yüksekliği.
*
* glutInitWindowSize ve glutInitWindowPosition hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node11.html
*/

glutInitWindowPosition(50, 50);
/* Pencerenin ekranın neresinde çıkacağını belirledik. Buraya da int
* türünden iki değer girmemiz gerekiyor. Birincisi pencerenin ekranın
* solundan piksel olarak uzaklığı, ikincisi ise yine piksel olarak
* ekranın üstünden tarafından uzaklığı.
*/

glutCreateWindow("GNU/Linux");
sahneyiyapilandir();
glutDisplayFunc(&sahneyigoster);

atexit(temizle);
/* Pencereyi kapattığımızda çalışacak bir işlev gösterelim.
*/

glutMainLoop();
return(0);
}



Biraz değişiklik ile bir örnek daha yapalım. Üçüncü program:
//gelistirelimGL.c

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#define AK 1.0f, 1.0f, 1.0f
#define KARA 0.0f, 0.0f, 0.0f
#define KIRMIZI 1.0f, 0.0f, 0.0f
#define YESIL 0.0f, 1.0f, 0.0f
#define MAVI 0.0f, 0.0f, 1.0f
#define SARI 1.0f, 1.0f, 0.0f
#define CAMGOBEGI 0.0f, 1.0f, 1.0f
#define GALIBARDA 1.0f, 0.0f, 1.0f
//#define MOR 0.5f, 0.0f, 0.5f
#define MOR 0.41f, 0.18f, 0.34f
#define MOR2 0.540f, 0.310f, 0.425f
#define KAVUN 0.895f, 0.367f, 0.137f

static int sahnelemesayaci=0;
static float cizgi_x=0.0f;
static float cizgi_y=0.75f;
static float nokta_x=0.0f;
static float nokta_y=0.75f;

static void sahneyiyapilandir(void){
glClearColor (MOR, 1.0f);
}

static void sahneyigoster(void){
glClear(GL_COLOR_BUFFER_BIT);

int aci=0, olcek=0, adet=0;
double kx=0, ky=0, lx=0, ly=0;

glColor3f(AK);
glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f);
glEnd();

for (olcek=1; olcek<15 ; olcek++){
glBegin(GL_POINTS);
for(aci = 1; aci <= 360; aci++) {
kx = sin(((double)aci)*(M_PI/180))/(float)olcek;
ky = cos(((double)aci)*(M_PI/180))/(float)olcek;
glVertex2f(kx,ky);
}
glEnd();
}

glColor3f(MOR2);

glBegin(GL_LINES);
/* Bu sefer çizgi çizeceğimizi belirttik.
*/
 
for(aci = 1; aci <= 360; aci++){
kx = sin(((double)aci)*(M_PI/180));
ky = cos(((double)aci)*(M_PI/180));

glVertex2f(0.0f, 0.0f);
/* Çizginin başlangıç koordinatı.
*/

glVertex2f(kx,ky);
/* Çizginin bitiş koordinatı.
*/

}
glEnd();
/* glBegin ve glEnd arasında 360 adet ayrı çizgi çizdik.
* Ortak noktaları pencerenin merkezinden başlamaları.
*/

glColor3f(KAVUN);
for(adet = 1; adet <= 12; adet++) {
lx = sin(((double)adet)*(M_PI/6))/1.125f;
ly = cos(((double)adet)*(M_PI/6))/1.125f;

glBegin(GL_LINE_LOOP);
/* GL_LINES ile GL_LINE_LOOP arasındaki fark için şuna bakın:
* http://www.dgp.toronto.edu/~ah/csc418/fall_2001/tut/img/prims.gif
*/

for(aci = 1; aci <= 90; aci++) {
kx = sin(((double)aci)*(M_PI/45))/24.0f;
ky = cos(((double)aci)*(M_PI/45))/24.0f;
glVertex2f(kx+lx, ky+ly);
}
glEnd();
}

glLineWidth(5.0);
/* Çizgi kalınlığını artırdık.
*
* glLineWidth hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml
*/

glColor3f(SARI);
glBegin(GL_LINES);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.0f);
glEnd();

glColor3f(CAMGOBEGI);
glBegin(GL_LINES);
glVertex2f(0.0f, 0.0f);
glVertex2f(cizgi_x, cizgi_y);
glEnd();

glLineWidth(1.0);
/* Çizgi kalınlığını varsayılan değere getirdik.
*/

glColor3f(GALIBARDA);

glPointSize(10.0);
/* Noktanın boyutunu büyüttük.
*
* glPointSize hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glPointSize.xml
*/

glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.0f);
glVertex2f(nokta_x, nokta_y);
glEnd();

glPointSize(1.0);
/* Noktanın boyutunu varsayılan değere getirdik.
*/

glFlush();
sahnelemesayaci++;
}

static void temizle(void){
printf("Sahneyi %d kez gosterdim.\n",sahnelemesayaci);
}

static void pencere_boyutlandir(int en, int boy){
glLoadIdentity();
/* Yeni duruma göre koordinat sistemini sıfırladık.
*
* glLoadIdentity hakkında ayrıntılı bilgi için:
* http://www.opengl.org/sdk/docs/man/xhtml/glLoadIdentity.xml
*/
 
glutPostRedisplay();
/* glutDisplayFunc ile belirlenen işlevin yeniden yürütülmesini söyledik.
*
* glutPostRedisplay hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node20.html
*/
}

static void fare_durumu(int durum){
/* Farenin nerede olduğunu biliyoruz!
*/

static unsigned int yon=0;
float x, y;

if (durum==GLUT_ENTERED) {
y=((float)(rand() % 100+1));
yon%2 !=0 ? (y = y/100.0) : (y = y/-100.0);
cizgi_y = y;

x=((float)(rand() % 100+1));
yon%3 !=0 ? (x = x/100.0) : (x = x/-100.0);
cizgi_x = x;

yon++;
glutPostRedisplay();
}
else if (durum==GLUT_LEFT) {
nokta_x = cizgi_x;
nokta_y = cizgi_y;
}
/* Fare pencere içine girdiğinde bir çizginin ikinci koordinatını
* rastgele değiştirdik. Dışına çıktığında ise o koordinata bir nokta
* çizilecek (tekrar pencere içine girdiğimizde görümesini istedik).
*/
}

static void olaylar(void){
glutEntryFunc(&fare_durumu);
/* Farenin durumunu öğreniyoruz.
*
* glutEntryFunc hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node53.html
*/
}

int main (int argc, char **argv){
srand(time(NULL));

glutInit (&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowSize(500, 500);
glutInitWindowPosition(50, 50);
glutCreateWindow("GNU/Linux");
sahneyiyapilandir();

glutReshapeFunc(&pencere_boyutlandir);
/* Bu işlev pencere yeniden bolyutlandırıldığında kendisine parametre
* olarak geçilen işlevi çağırır ayrıca ona pencerenin yeni boyutlarını
* int türünde gönderir. Bu örnekte pencerenin boyutlarını
* değiştirdiğimizde çizimde bir değişiklik olmayacak. Önceki örnekte
* penceremizin boyutları değiştikçe çizimimiz ona göre değişiyordu.
*
* glutReshapeFunc hakkında ayrıntılı bilgi için:
* http://www.opengl.org/documentation/specs/glut/spec3/node48.html
*/

glutDisplayFunc(&sahneyigoster);

olaylar();
/* Bazı durumları öğrenmek için ayrı bir işlev çağıralım.
*/

atexit(temizle);
glutMainLoop();
return(0);
}



Ayrıca main içindeki glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); ifadesini glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); olarak ve sahneyigoster içindeki glFlush(); ifadesini glutSwapBuffers(); olarak değiştirerek bu son örneği tekrar derleyin. Böylece pencere yenilenirken tek tampondan kaynaklanan görüntü kirliliği yaşanmayacak.


Aslında başta niyetim standart time işlevlerini kullanarak sistem saatini okuyup ona göre çalışan basit bir saat yapmaktı. Ancak sonra benim gibi 40 yılda bir kod yazan biri için bu işin biraz uzun süreceğini fark ettim...


Yararlanabilecek bazı kaynaklar şunlar:
30 Dakikada OpenGL'e Giriş
Temel OpenGL
C ve OpenGL
Linux Focus OpenGL Programlama
OpenGLtr
NeHe OpenGL Lessons
Nate Robins OpenGL Tutors
Bluebook
Redbook
Redbook Examples
OpenGL Examples
OpenGL 2.1 Reference Page

travego0403

Çok güzel bir konu. Yalnız 3.programda bir hata mı var yoksa benden mi kaynaklanıyor.Tamam srand() ifadesini silmemiz gerekiyor onu silmemişsinde. :)

Bu arada bende bir örnek vereyim. Sinüs fonksiyonunun grafiğini merak edenler olabilir, ufak değişikliklerlede istenilen fonksiyona çevirilebilir.Kodlama biraz kötü olabilir ama idare edin artık. :)

#include <GL/glut.h>
#include <math.h>
void sinus(void);

int main(int argc, char ** argv)
{
  glutInit(&argc, argv);                 //Glut kütüphanesi ilklendirme
  glutInitWindowSize(500,500);           //Pencere boyutu
  glutCreateWindow("Sinus Fonksiyonu");  //Pencere oluştur ve isim ata
  glutDisplayFunc(sinus);                //Sinus fonksiyonunu pencereye gönder
  glutMainLoop();                        //Gelecek sinyalleri bekle
  return 0;
}

void sinus(void)
{
  double x,y;
  int i;
  double xolcek=0.0027;         //Ekran 1-1 boyutundadır ekrana sığdırmak için
  double yolcek=0.99;           //bir ölçekle çarpıyoruz


  glClearColor(0.0,0.0,0.0,0.0);        //Temizlenme rengini ayarla (Siyah)
  glClear(GL_COLOR_BUFFER_BIT);         //Tamponları temizle
  glColor3f(0.0,1.0,0.0);               //Çizgi rengi Yeşil

  glPointSize(5.0);                     //Nokta büyüküğünü ayarla
 
  glBegin(GL_LINES);
  glVertex2f(0,-1);         //Verilen iki nokta arası çizgi çiz
  glVertex2f(0,1);          // Koordinat eksenleri
  glVertex2f(-1,0);
  glVertex2f(1,0);
  glEnd();

  glBegin(GL_POINTS);
  glVertex2f(0.01*xolcek,0.5*yolcek);    // y ekseni 0.5 skalası
  glVertex2f(-0.01*xolcek,0.5*yolcek);
  glVertex2f(0.01*xolcek,-0.5*yolcek);    // y ekseni -0.5 skalası
  glVertex2f(-0.01*xolcek,-0.5*yolcek);

  glEnd();                  //Çizimi bitir
  glFlush();                // Çizimi ekranda göster

  glBegin(GL_POINTS);          // Sinüs eğrisi çizimine başla

  i=-360;
  while(i <= 360){     
      glColor3f(0,0,1);         // Mavi sinüs eğrisi
      double k=i*M_PI/180;      // Radyana çevir
      y=sin(k);
      glVertex2f(i*xolcek,y*yolcek);   
     
      if((i%45)==0){                //45 ve katlarına skala koy x-ekseni
          glColor3f(0,1,0);   
          glVertex2f(i*xolcek,0.01*yolcek);
          glVertex2f(i*xolcek,-0.01*yolcek);
      }
      i++;
           
  }
  glEnd();
  glFlush();
 
}
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

utdmr

Tam da PyOpenGL öğrenmeye niyetlendiğim zamana denk geldi :). Python ile çağrıları aynı, çok işime yarayacaktır :).

Çok teşekkürler bu anlatım ve örnekler için :).
Kişisel Blogum: Çoğunlukla Zararsız - cogunluklazararsiz.org
--
Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius -and a lot of courage- to move in the opposite direction.

DoGuKaN

Tam da Java öğrenmeye niyetlendiğim zamana denk geldi :D Java öğrendikten sonra başlarım JavaGL'e.

Erdem

Bunları sadece aklıma gelen rastgele fikirler :D

Aslında noktaları şekilleri de soyutlayabilirmiyiz acaba:

#include <iostream>
#include <vector>

using namespace std;


class Nokta { /*  ... */ };

class Renk {  /*  ... */ };


class Sekil
{
public:
    Nokta nereden () { return merkez_; }
    void hareketEt (Nokta nereye)
    {
        merkez_ = nereye;
        /*  ... */
        cizimYap ();
    }
    virtual void cizimYap () = 0;
    virtual void dondur (int aci) = 0;
private:
    Nokta merkez_;
    Renk renk_;   
};

class Daire : public Sekil
{
public:

    Daire (int yaricap)
        : yaricap_ (yaricap)
    {}

    void cizimYap () {  /*  ... */ };
    void dondur (int aci)
    {
        cout << "Ben" << aci << " lik bir açıyla dönen bir daireyim :o\n";
    };
   
private:
   
    int yaricap_;
};

class Ucgen : public Sekil
{
public:
    Ucgen (int taban, int yukseklik)
        : taban_ (taban), yukseklik_ (yukseklik)
    {}
    void cizimYap () {  /*  ... */ };
    void dondur (int aci)
    {
        cout << "Ben" << aci << " lik bir açıyla dönen bir ucgenim :o\n";
    };
private:
    int taban_, yukseklik_;
};


typedef vector<Sekil*> Sekiller;

void tumunuDondur (Sekiller & sekil, int aci)
{
    for (int i = 0; i < sekil.size (); ++i) sekil[i]->dondur (aci);
}


int main ()
{

    Ucgen* ucgen;
    ucgen = new Ucgen (5,8);
    Daire* daire;
    daire = new Daire (6);
   
    Sekiller birkacsekil;
    birkacsekil.push_back (ucgen);
    birkacsekil.push_back (daire);
   
    tumunuDondur (birkacsekil, 34);
    delete ucgen;
    delete daire;
   
}


Ya da acaba MVC tasarım desenini kullanabilirmiydik.

Model – (oyun öğeleri, örneğin. Oyuncu, Kılıç)
View – Çizimle ilgili işler
Controller – Kullanıcıdan gelen girdileri işle

Örneğin Oyuncu bir modeldir. Konum, Genişlik, Yükseklik gibi nitelikleri olabilir. Gene Controller'ın Güncelle(), Çiz() gibi üye işlevleri olabilir.

Hatti

Arkadaşlar faydalı bulmanıza sevindim.

@travego0403, örnekleri geany ile yazdım buraya aktarırken tab girintileri silinmiş. Hepsini çalıştırdım, bende bir sorun çıkmamıştı. Bir kullanım hatası yapmış olabilirim ama şimdi fark edemedim. Fonksiyon grafiği çizen programda çizimi yapan işlevin sonunda bir kere glFlush(); kullanmak yeterli olur.

@Erdem, C++' dan pek anlamam. Soyutlama tabii ki yapabilirsin. Temel işlevleri öğrendikten sonra daha iyi olur. Bir noktaya ait her türlü bilgiyi bir yapı içinde tutabilirsin. Hatta bağlı liste yaparsın. Temel şekillerden diğer şekilleri oluşturup yine bunları soyutlayıp kullanabilirsin. Tamamen hayal gücüne kalmış.

Alıntı YapÖrneğin Oyuncu bir modeldir. Konum, Genişlik, Yükseklik gibi nitelikleri olabilir. Gene Controller'ın Güncelle(), Çiz() gibi üye işlevleri olabilir.
Half-Life   :)

Erdem

Alıntı yapılan: Hatti - 24 Nisan 2011 - 20:33:15
Hatta bağlı liste yaparsın.

Aslında C++ için std::deque ve std::list gibi Standart Şablon Kütüphanesinin içinde bağlı liste gerçeklemeleri için buna pek ihtiyaç kalmıyor  ;)

Ama örneğin bir grafik nesnesine ihtiyacımız olabilir.  Örneğin arama algoritmalarını A* gibi gerçekleştirmek için.

Alıntı yapılan: Hatti - 24 Nisan 2011 - 20:33:15
Half-Life   :)

Half Life'ı C ile mi kodlamışlar. Benim bir kısmını okuduğum Programming Game AI By Example kitapta 2D Half Life türü Raven isimli bir oyun var. İçinde akıllı yapay zekayla hareket eden botlar var. Sanırım 30.000 satır falan kod vardı. Bunu C ile nasıl kodladıklarını tahmin bile etmek istemiyorum  :D

C++ kodları da biraz karmaşık şablon olanakları kullanıyor. O yüzden en iyisi D ile kodlamak diye düşünüyorum :)

Daha önceden C++ ve Allegro kullanarak başladığım ama bitirmediğim bir Pacman oyunu vardı:



Eğer bu sefer o tür bir oyun kodlarsam D kullanacağımı tahmin ediyorum :)

Örneğin D ile kodlanan Titanion isimli bir oyun:


Hatti

Öyle büyük bir oyun yapmak ekip işi zaten. Nasıl bir bina yapılırken farklı uzmanlık alanında birçok insan çalışıyor... İşin içinde grafikten başka unsurlar da var ama sen bunları biliyorsundur zaten. Aslında Half-Life örneğini senin bahsettiğin MVC tasarım deseni bağlamında OpenGL kullanan ve o an aklıma gelen bir örnek olduğu için vermiştim.

Half-Life, Quake 1 motorunun değiştirilmiş bir sürümü. Şimdi wikipediadan da baktığım kadarıyla goldsrc C++ ile yazılmış. Ancak quake motoru C ile. Şurada oyun motorları ve hangi diller kullanıldığını gösteren bir tablo var, oradan bakabilirsin (özgür ve kapalı olanlar ayrı ayrı listelenmiş).



Mesaj tekrarı yüzünden mesajınız birleştirildi. Bu mesajın gönderim tarihi : 25 Nisan 2011 - 11:14:36

Anladığım kadarıyla Allegro, 2 boyutlu grafik ve ses için kullanılıyor sadece. Yani çarpışma denetimi vb. konularda bir desteği yok. Oyun yapacaksan GLUT yerine SDL kullanman daha avantajlı oluyor sanırım gerçi derinlemesine bir bilgim yok...

Erdem

Alıntı yapılan: Hatti - 25 Nisan 2011 - 10:54:16
Anladığım kadarıyla Allegro, 2 boyutlu grafik ve ses için kullanılıyor sadece. Yani çarpışma denetimi vb. konularda bir desteği yok.

Evet allegro bir grafik motoru ve ses kütüphanesi sağlıyor. Ama gene allegro kullanarak ve yardımcı fizik kütüphanelerinden faydalınarak oyun yapılabilir.

Alıntı yapılan: Hatti - 25 Nisan 2011 - 10:54:16
Oyun yapacaksan GLUT yerine SDL kullanman daha avantajlı oluyor sanırım gerçi derinlemesine bir bilgim yok...

Aslında şu anda oyun yapmayı düşünmüyorum  ???

Ama grafik teorisine hala ilgim var. Belki D ile grafik nesneleri yazabilirim :)

Sanırım sadece OpenGL örneğin resim yüklemeye izin vermiyor. Bunun için ek bir kütüphane kullanmak gerekiyor. O yüzden sizin de bahsettiğiniz gibi SDL bunların hepsini sağlıyor.

Aslında Pacman'i bitirebilirdim ama XNA ile. Daha sonra özellikle açık kaynak kodlu ve her platformda çalışsın diye SDL ve Allegro'ya geçirmek istedim. O yüzden biraz iş uzadı :)

Burada örneğin ben çarpışma algılamasını da kendim bir kutucuk kullanarak yapmıştım.

http://www.youtube.com/watch?v=Shpgi01Q_Pg

Aslında oyun yapmak için hiç programlama bilmeye bile gerek yok.

http://www.youtube.com/watch?v=sMQZKfpw7Fk

Scirra isimli bir oyun geliştirme ortamı var. Ama maalesef sadece windows altında çalışıyor  ::)

http://www.scirra.com


travego0403

@Hatti, Hata dediğim şey aslında seninde söylediğin gibi önce srand() fonksiyonunu time() ile tohumlamak istemişsin ama daha sonra bundan vazgeçince o satır orda kalmış ve time kütüphanesi eklenmediği için hata veriyor.Sadece onu söylemek istemiştim.  :) Benim verdiğim örnektede haklısın 2 defa glFlush() kullanmak gereksiz.

Bende OpenGL de daha yeni sayılırım.OpenGL ile ilk olarak, sadece bana derslerde lazım olan  matematiksel fonksiyonların grafiklerini C++ ta çizdirmek için araştırırken karşılaştım.Daha sonra ekranda bir küp çizmek ve bunu ekranda döndürmek hoşuma gitti.Böylece grafik programlamaya ilgi duymaya başladım. :) Sonuçta bana grafik çizmek otomasyon  ya da veri tabanı programcılığından daha zevkli geliyor.

Türkçe kaynak az olduğu için, öğrenmesi biraz zahmetli oluyor bu yüzdende ilerlemede yavaşlıyor.

Bu başlığıda isterseniz OpenGL örneklerinin paylaşıldığı bir başlık yapabiliriz. Elimizden geldiği kadar yaptığımız örnekleri burada paylaşabiliriz. İyi bir şey olmaz mı ?  :)
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

Hatti

Şimdi anladım onu, time.h  :)

Alıntı YapBu başlığıda isterseniz OpenGL örneklerinin paylaşıldığı bir başlık yapabiliriz. Elimizden geldiği kadar yaptığımız örnekleri burada paylaşabiliriz. İyi bir şey olmaz mı ?  :)

Bu başlığı bunun için açmıştım zaten.  :)

Hatti

Hareketli nesneler üzerine bir örnek. Açıklamaları yorum satırlarında yaptım.

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

#define PEN_GEN 350
#define PEN_YUK 350

#define AK 1.0f, 1.0f, 1.0f
#define KARA 0.0f, 0.0f, 0.0f
#define KIRMIZI 1.0f, 0.0f, 0.0f
#define YESIL 0.0f, 1.0f, 0.0f
#define MAVI 0.0f, 0.0f, 1.0f
#define SARI 1.0f, 1.0f, 0.0f
#define CAMGOBEGI 0.0f, 1.0f, 1.0f
#define GALIBARDA 1.0f, 0.0f, 1.0f
#define MOR 0.5f, 0.0f, 0.5f
#define MOR1 0.41f, 0.18f, 0.34f
#define MOR2 0.540f, 0.310f, 0.425f
#define KAVUN 0.895f, 0.367f, 0.137f
#define GRI_A 0.45f, 0.45f, 0.42f
#define GRI_K 0.23f, 0.23f, 0.21f

enum{
KUZEYDOGU, GUNEYDOGU, GUNEYBATI, KUZEYBATI,
AKTIF, PASIF
};

struct{
float x;
float y;
}nokta1={0.0f, 0.0f}, nokta2={0.0f, 0.0f}, nokta3={0.0f, 0.0f};
/* nokta1: Karlanma etkisi için.
* nokta2 ve nokta3: Kare çizimi için.
*/

static void sahnegoster (void);
static void sahneyapilandir (void);
static void temizle (void);
static void fare (int);
static void olaylar (void);
static void pboyutlandir (int, int);
static void zguncelle (int);
static void saniyedeki_kare_sayisi (void);
static void ayarlar (void);

int sayac = 0;
int pen_x = 50;
int pen_y = 50;

static char program_durumu=PASIF;
/* Karenin hareketini kontrol etmek için (gelip gidecek).
*/

int main (int argc, char **argv){
glutInit (&argc, argv);
ayarlar();
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(PEN_GEN, PEN_YUK);
glutInitWindowPosition(pen_x, pen_y);
glutCreateWindow("Animasyon");
sahneyapilandir();
glutReshapeFunc(&pboyutlandir);
glutDisplayFunc(&sahnegoster);
olaylar();
atexit(temizle);
glutMainLoop();
return(0);
}

static void olaylar (void){
glutEntryFunc(&fare);

glutTimerFunc(0, zguncelle, 0);
/* Bildirimi:
* void glutTimerFunc(unsigned int msecs, void (*func)(int value), value);
*
* Bu işlev zguncelle olarak bildirdiğimiz işlevi 0 milisaniye sonra
* çağıracak. İlk parametre milisaniye, ikinci parametre çağırdığımız
* işlev ve son parametre de o işleve geçirilecek değer.
*/
}

static void temizle (void){
printf("Toplam kare sayısı: %d\n",sayac);
}

static void pboyutlandir (int en, int boy){
glLoadIdentity();
glutPostRedisplay();
}

static void fare (int durum){
if (durum==GLUT_ENTERED) {
program_durumu = AKTIF;
}
else if (durum==GLUT_LEFT) {
program_durumu = PASIF;
}
/* Fare pencere içindeyken kare hareket edecek. Pencere dışındayken
* duracak.
*/
}

static void zguncelle (int deger){
static char geldi = 1;

if(program_durumu==AKTIF) {
if (geldi) {
nokta2.x = nokta2.x - 0.005f;
nokta2.y = nokta2.y - 0.005f;
nokta3.x = nokta3.x + 0.005f;
nokta3.y = nokta3.y + 0.005f;
if (nokta3.x >= 1.0f)
geldi = 0;
}
else {
nokta2.x = nokta2.x + 0.005f;
nokta2.y = nokta2.y + 0.005f;
nokta3.x = nokta3.x - 0.005f;
nokta3.y = nokta3.y - 0.005f;
if (nokta2.x >= 0.0f)
geldi = 1;
}
}
/* Karenin hareketiyle ilgili.
*/

glutTimerFunc(25, zguncelle, 0);
/* Bunu olaylar işlevinde çağırmıştık. Burada; çağrılan işlevin içinde
* tekrar kullandığımız için sürekli yani 25 milisaniyede bir kendini
* çalıştıran bir işlev oldu artık zguncelle.
* (25/1000=0.025 saniye)
*/

saniyedeki_kare_sayisi();
glutPostRedisplay ();
}

static void saniyedeki_kare_sayisi(void){
float hesap = 0.0f;
static float kare = 0.0f;
int simdiki_zaman = glutGet(GLUT_ELAPSED_TIME);
static int gecmis_zaman = 0;
float fark = 0.0f;

/* int glutGet(GLenum state);
* glutGet bir çok parametre olabiliyor. Amacı bize bilgi vermek.
* http://www.opengl.org/documentation/specs/glut/spec3/node70.html
*
* GLUT_ELAPSED_TIME: glutInit yapılandırmasından bu yana geçen süreyi
* bize int türünden milisaniye olarak  söylüyor.
*/

kare++;
fark = (simdiki_zaman - gecmis_zaman) / 1000.0f;
if (fark >= 5.0f) {
hesap = kare / fark;
printf("%1.1f saniyede %5.0f kare = %4.3f\n", fark, kare, hesap);
    gecmis_zaman = simdiki_zaman;
    kare = 0;
}
}

static void ayarlar (void){
int genislik = glutGet(GLUT_SCREEN_WIDTH);
int yukseklik = glutGet(GLUT_SCREEN_HEIGHT);
/* Burada da glutGet ile ekranın piksel olarak genişliği ve yüksekliğini
* sorguladık. Bu bilgilerle pencereyi ekranın ortasında açılmaya
* zorlayalım.
*/

if (genislik!=0 && yukseklik!=0) {
pen_x = (genislik-PEN_GEN)/2;
pen_y = (yukseklik-PEN_YUK)/2;
}
}

static void sahneyapilandir (void){
glClearColor (KARA, 1.0f);
}

static void sahnegoster (void){
int say;
char bolgeler=KUZEYDOGU;
glClear(GL_COLOR_BUFFER_BIT);

glColor3f(GRI_K);
glBegin(GL_LINES);
glVertex2f(-1.0f, -1.0f);
glVertex2f(1.0f, 1.0f);
glVertex2f(-1.0f, 1.0f);
glVertex2f(1.0f, -1.0f);
glEnd();
/* Çapraz çizgiler.
*/

sayac%2 ? glColor3f(AK) : glColor3f(SARI);
glBegin(GL_POINTS);
for (say=0 ; say<999 ; ++say) {
switch(bolgeler){
case KUZEYDOGU:
nokta1.x = ((float)(rand()%100+1))/100.0f;
nokta1.y = ((float)(rand()%100+1))/100.0f;
bolgeler = GUNEYDOGU;
break;
case GUNEYDOGU:
nokta1.x = ((float)(rand()%100+1))/100.0f;
nokta1.y = ((float)(rand()%100+1))/-100.0f;
bolgeler = GUNEYBATI;
break;
case GUNEYBATI:
nokta1.x = ((float)(rand()%100+1))/-100.0f;
nokta1.y = ((float)(rand()%100+1))/-100.0f;
bolgeler = KUZEYBATI;
break;
case KUZEYBATI:
nokta1.x = ((float)(rand()%100+1))/-100.0f;
nokta1.y = ((float)(rand()%100+1))/100.0f;
bolgeler = KUZEYDOGU;
break;
}
glVertex2f(nokta1.x, nokta1.y);
}
glEnd();
/* Karlanmalar.
*/

glColor3f(KAVUN);

glRectf(nokta2.x, nokta2.y, nokta3.x, nokta3.y);
/* Dikdörtgen çiziminin bildirimi:
* void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
*
* glRectd, glRecti, glRects şeklinde kullanımları da tanımlı.
* (d: double, f: float, i: int, s: short)
*
* x1 ve y1: Dikdörtgenin birinci koordinat noktası.
* x2 ve y2: Dikdörtgenin ikinci koordinat noktası.
*/

glColor3f(GRI_A);
glLineWidth(2.0);
glBegin(GL_LINE_LOOP);
glVertex2f(nokta2.x, nokta2.y);
glVertex2f(nokta3.x, nokta2.y);
glVertex2f(nokta3.x, nokta3.y);
glVertex2f(nokta2.x, nokta3.y);
glEnd();
glLineWidth(1.0);
/* Dikdörtgenin çevresine çizgi.
*/

glutSwapBuffers();
/* Görüntü modunu GLUT_DOUBLE olarak belirlediğimiz için glFlush();
* yerine glutSwapBuffers(); kullanıyoruz. Çift tamponlu bir penceremiz
* var ve bu işlev ile tamponlar yer değiştiriyor.
*/

sayac++;
}

ulusoyab

Benim GL ile ilgili bir sıkıntım var. 3 Boyutta  değişik görünümlerde  penceredeki nesnelerin seçimi. bu konuda  bildiğiniz bir örnek var mı?

travego0403

Uzun bir aradan sonra bir örnek daha ekleyelim.
Program bir kutuda hareket eden bir gaz molekünü modelliyor. Bir fizikçidende bu beklenirdi. :) İlk başta çok sayıda molekül düşünmüştüm ama moleküllerin kendi aralarındaki çarpışmalardan sonraki yönlerini bulmak biraz karışık geldiği için daha sonraya bıraktım.
Program yazılırken kabul edilenler:
*Molekülün ilk hızı sabit ve rastgele bir yön seçilip ilk hareket veriliyor.
*Birden fazla molekül olsaydı Maxwell Hız dağılımına uyması gerekirdi, tek molekül olduğu için gözardı edilmiştir.
*Molekül kabın duvarları ile esnek çarpışma yapıyor.

Program başta sizden molekülün yarıçapını istiyor buraya 0.03 gibi bir değer girerseniz daha güzel bir sonuç elde edersiniz.

Program biraz geliştirilerek oyuna da dönüştürülebilir. :) Alt ve üst tarafa klavye ile hareket eden birer platform konulabilir. Top buralardan sekerek karşılıklı oynanan bir oyuna çevirilebilir. Bu fikir kodları buraya yazarken aklıma geldi, inşallah boş bi zamanımda bunu da yaparım.  :D

#include <iostream>
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

using namespace std;

void sahne();
void cember(float,float,float);
void klavye (unsigned char ,int, int);
void parametreAyarla();
float R;
float kx;
float ky;
float hizx;
float hizy;


int main(int argc, char** argv) {
   
    cout<<"2 Boyutlu kutuda bir gaz molekulu simulasyonuna hosgeldiniz.\n"
            "Program baslangicta molekulu sol usst kosede bir yere \nyerlestirir,"
            " bir yon secer ve ilk hareketi verir.\nProgramdan cikmak icin ESC tusunu kullanabilirsiniz.\n";
    cout<<"Gaz molekulunun yari capini giriniz.(0 - 0.3 arasi)Onerilen : 0.03";
    cin>>R;
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE);
    glutInitWindowSize(600,600);
    glutCreateWindow("2 Boyutlu kutuda bir gaz molekulu");
    parametreAyarla();
    glutDisplayFunc(sahne);
    glutKeyboardFunc(klavye);
    glutIdleFunc(sahne);
    glutMainLoop(); 
    return 0;
}
void parametreAyarla(){
    srand(time(NULL));
    kx=(float)(rand()%60)/80;   // X-Konum
    ky=(float)(rand()%40)/60;
    hizx=0.004;                 //Hiz
    hizy=0.004;
    if(rand()%1000>500){
        hizx=-hizx;
    }
    if(rand()%1000>500){
        hizy=-hizy;
    }
   
}
void sahne(){
   
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glColor3f(0,1,0); 
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_LINE_LOOP);
    glVertex2f(-0.9,0.7);               //Kutuyu çiz
    glVertex2f(0.9,0.7);
    glVertex2f(0.9,-0.7);
    glVertex2f(-0.9,-0.7);
    glEnd();
    if(kx>0.9-R||kx<-0.9+R){            //Duvardan çarpma şartları
        hizx=-hizx;
    }
    if(ky>0.7-R||ky<-0.7+R){
        hizy=-hizy;
    }
    cember(R,kx,ky); 
    glutSwapBuffers();
    kx+=hizx;
    ky+=hizy;
}
void cember(float r,float x0,float y0){
    int i=0;
    float x;
    float y;
    glBegin(GL_POLYGON);
    while(i<=360){           
        x=r*cos(i*M_PI/180)-x0;
        y=r*sin(i*M_PI/180)+y0;
        glVertex2f(x,y);
        i++;       
    }
    glEnd();   
   
   
}
void klavye (unsigned char tus,int y, int x){
    if (tus == 27){ //ESC tusuna basılınca programdan cik
        exit(0);
    }
    sahne();
}




"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

Erdem


sem

Elinize sağlık @travego0403. Teşekkürler güzel paylaşımlar için.


En son örnek kodu derledim, çalıştırdım. Bende %99 CPU harcıyor. Bu olağan bir şey midir bana özel mi oldu acaba?

".NET çemberinden geçen lirisist etkisi bir 'Volcano', bir yüzüm Java bir yüzüm Badalamenti Don Tano"
----------------------------------------------------------------------------------------------------------------------
"Her yer ölüm yine, burası dünya
Derken ölüm bile bu nasıl dünya?
Benden ölüm dile, batıyor gün yine
Burası dünya?

travego0403

#16
Şimdi tekrar baktımda ekstra bir işlemci gücü harcaması bende yok.Diğer arkadaşlarda çalıştırıp kontrol ederse seviniriz.
Ama Ati ekran kartımın sahipli sürücülerini yüklediğim zaman OpenGL de kasılmalar başlıyordu.Bu yüzden açık kaynak sürücülerle devam ediyorum.Sanırım bu 11.04 ten kaynaklanıyor.
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

Erdem

Mikro işlemci kullanımı oyun döngüsüyle ilgili.

Örneğin şöyle bir oyun döngümüz olsun:

1- Kullanıcıdan gelenleri oku
2- Oyunu güncelle
3- Çiz

Bunun dezavantajları:

1- Oyun farklı bilgisayarlarda farklı hızlarla çalışır. 
2-  Mikro işlemci kullanımı neredeyse %100'e ulaşır
3- Ana oyun döngüsü program geliştikçe çok uzun olmaya başlar ve kod eklemek güçleşebilir.
4- Kodun diğer platformlara taşınması güçleşebilir.

En basit çözüm burada oyun örneğin 60 FPS hızla çalışıyorsa 1000/60 = 16.7 milisaniye bir karenin çizilme süresi olarak ayarlayabiliriz. Güncelle çiz kısmı örneğin 8 milisaniyede tamamlandıysa geri kalan zamanda sistem duraklamaya girebilir. Ama bunun da bazı dezavantajları var.

Konu çok uzun olduğu için sadece bağlantılarını veriyorum:

http://www.koonsolo.com/news/dewitters-gameloop/
http://gafferongames.com/game-physics/fix-your-timestep/

Hatta şu aralar ben de eksik bulduğum deneme oyunundaki oyun döngüsünü geliştirmeye çalışıyorum.  Konunun ayrıntılarını burada bulabilirsiniz:

http://ddili.org/forum/thread/554

Bir de oyunlar açısından bakınca durum nasıl olur tam bilemiyorum ama TDPL'de Erlang dilinin önerdiği bir ilkeden bahsedildiğini duymuştum:
Alıntı Yap"mikro işlemcileri olabildiğince meşgul edin." Çok çekirdekli işlemcilerimizi süs diye almadık. :)

Kitabın o kısmını ben henüz okumadım  :D

Hatti

@ulusoyab, çoklu pencerelerle ilgili gelişmiş bir örnek bilmiyorum.


@travego0403, güzel bir örnek olmuş.


Benim sistemde gaz molekülü örneği %53 civarında işlemci kullanımı yaptı. Bu örnekte sisteme yüklenmenin sebebi glutIdleFunc(sahne); işlevine bağlanabilir. Burada sisteme boşta olduğu her an için glutDisplayFunc(sahne); işlevini çağırtmış oluyoruz dolaylı olarak. Onun yerine bir timer işlevi ile (daha önce bir örnekte verdiğim glutTimerFunc gibi) sistem biraz rahatlatılabilir. Bunun dışında şekil listeleri (glGenLists) kullanılabilir. Böylece diyelim ki topun çizimini her kare için ayrıca yapmaya gerek kalmaz. Bu örnek için bunun önemsenecek bir getirisi olmaz gerçi. Kısacası bu tür ayarlamalar yaparak işlemci kullanımı önemli ölçüde aşağıya çekilebilir.






Klavye ile hareket eden nokta örneği.


#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0

#define ESCAPE 27

#define PEN_GEN 250
#define PEN_YUK 250

#define AK 1.0f, 1.0f, 1.0f
#define KARA 0.0f, 0.0f, 0.0f
#define KIRMIZI 1.0f, 0.0f, 0.0f

typedef struct {
float x;
float y;
}_nokta;

static void sahnegoster(void);
static void sahneyapilandir (void);
static void klavye_basildi(unsigned char, int, int);
static void klavye_birakildi(unsigned char, int, int);
static void zguncelle(int);
static void pboyutlandir(int, int);
static void olaylar(void);

char tus_durumu[256] = {FALSE}; //bool
_nokta n1={0.0f, 0.0f};

int main (int argc, char **argv){
glutInit (&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(PEN_GEN, PEN_YUK);
glutCreateWindow("Gezen Nokta");
sahneyapilandir();
glutDisplayFunc(&sahnegoster);
olaylar();
printf("Noktanın hareketi w, a, s, d tuşları ile...\n");

/* glutIgnoreKeyRepeat(1);
*  void glutIgnoreKeyRepeat(int ignore);
*  Basılan tuşun tekrarına gerek yok.
*/

glutMainLoop();
return(0);
}

static void olaylar(void){
glutKeyboardFunc(&klavye_basildi);
/* void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y));
* key: klavyenin basılan tuşu, x ve y farenin koordinatları
*/

    glutKeyboardUpFunc(&klavye_birakildi);
/* void glutKeyboardUpFunc(void (*func)(unsigned char key, int x, int y));
* Klavyenin bırakılan tuşu
*/

/* F tuşları, ok tuşları ve diğer home, end falan için glutSpecialFunc
* işlevini tanımlamak gerekiyor. Ona sonra bakabiliriz.
*/

glutTimerFunc(0, zguncelle, 0);
}

static void klavye_basildi(unsigned char tus,int x,int y){
tus_durumu[tus] = TRUE;
}

static void klavye_birakildi(unsigned char tus,int x,int y){
tus_durumu[tus] = FALSE;
}

static void zguncelle(int value){
const float adim = 0.03f;

if((tus_durumu['a']==TRUE) || (tus_durumu['A']==TRUE)){
        n1.x = n1.x - adim;
    }
    if((tus_durumu['d']==TRUE) || (tus_durumu['D']==TRUE)){
        n1.x = n1.x + adim;
    }
    if((tus_durumu['w']==TRUE) || (tus_durumu['W']==TRUE)){
        n1.y = n1.y + adim;
    }
    if((tus_durumu['s']==TRUE) || (tus_durumu['S']==TRUE)){
        n1.y = n1.y - adim;
    }
    if(tus_durumu[ESCAPE]==TRUE){
        exit(0);
    }
   
glutTimerFunc(25, zguncelle, 0);
glutPostRedisplay ();
}

static void pboyutlandir(int en, int boy){
glLoadIdentity();
glutPostRedisplay();
}

static void sahneyapilandir (void){
glClearColor(KARA, 1.0f);
}

static void sahnegoster (void){
glClear(GL_COLOR_BUFFER_BIT);

if((tus_durumu['a']==TRUE) || (tus_durumu['A']==TRUE) ||
(tus_durumu['d']==TRUE) || (tus_durumu['D']==TRUE) ||
(tus_durumu['w']==TRUE) || (tus_durumu['W']==TRUE) ||
(tus_durumu['s']==TRUE) || (tus_durumu['S']==TRUE)){
        glColor3f(KIRMIZI);
        glPointSize(6.0);
    }
    else {
glColor3f(AK);
glPointSize(4.0);
}

glBegin(GL_POINTS);
glVertex2f(n1.x, n1.y);
glEnd();

    glutSwapBuffers();
}

travego0403

@Hatti
Teşekkür ederim, yarın ya da haftasonu(Şu an Final haftası fazla zaman ayıramıyorum) detaylı bir şekilde inceleyeceğim örneği. :)
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

microanaliz

Buradaki bilgiler bayağı işime yaradı az kaldı bırakacakrım c dilini arkadaşların sayesinde bazı şeyleri çözdüm
MicroAnaliz

microanaliz

PC lerde bu yaygınca kullanılmaktadırç Eğer ticari amaçla OpenGL kullanacak iseniz o zaman SGI dan OpenGL lisansı almanız gerekir.

İstediğimiz gibi kullanamayızmı paralımı
MicroAnaliz

travego0403

Anladığım kadarıyla lisans almaya gerek yok.İngilizcesi iyi olan arkadaşlar bakarlarsa daha iyi bilgi verebilirler.

http://www.opengl.org/about/licensing/
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman

endryz

geçenlerde ubuntu türkiye wiki sayfasında yayınlanan opengl komutlarını öğrenip(hazırlayan kişiye çok teşekkürler), eskiden kalma c bilgisiyle ve biraz internet kurcalamasıyla(sayfada bulunmayan farklı opengl komutları için) bir pong oyunu da ben yaptım. kısaca özellikleri;

-sol taraftaki raket 'w' ileri yukarı 's' ile aşağı, sağ taraftaki raket ise 'o' ile yukarı 'l' ile aşağı hareket ediyor. esc oyundan çıkmayı sağlıyor.
-top ilk seferde rastgele bir hız vektörleriyle (0, 0) noktasında oluşturuluyor. Daha sonra sayıyı kazanan oyuncu servis kullanıyormuş gibi onun tarafında başlıyor ve sayıyı alan değiştike başlama yeride değişiyor.
-raketler ekran sınırının dışına çıkmıyor.
-eğer çarpışması sırasında raket hareketliyse, top raketin o anki hız vektöründen bileşen alıyor. böylece etkiyle topun yönünü ve hızını değiştirme şansı oluyor.

bir eksik olarak skor yazımında, sağ taraftaki sayı çift haneli olunca yanıp sönmeye başlıyor. bir türlü çözemedim onu.

ayrıca oyunu bilgisayara karşı oynanabilir hale getirmek istiyorum ama pek bi fikir oluşmadı kafamda. yani hesaplama yapınca bilgisayar hep kazanabilir, kaybetme olayını insanı değerlere nasıl çekebileceğim konusunda. yardım edebilecek arkadaş varsa sevinirim. beraber de yapabiliriz.

kodları elimden geldiğince anlaşılır yazmaya çalıştım.hata tespitleri ve önerilerinize açığım.

son olarak sormak istediğim ise, sadece ubuntu kullanıyorum ve bu oyunu windows ortamında çalışacak şekilde derlemeye berecemedim. nasıl yapacağım bunu?


#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#define esc 27
#define aktif 1
#define pasif 0

struct raket_yapisi{
float konum_x[4], konum_y[4];
}raket[2];

struct daire_yapisi{
float konum_x, konum_y, hiz_x, hiz_y, nokta_x[360], nokta_y[360];
}daire;

struct ilerleme_yapisi{
float pozitif, negatif;
}ilerleme = {0.010, -0.010};

char tus_kontrol[256] = {pasif}, kayip[100];
int i, j, derece, kayip_sayisi_sol = 0, kayip_sayisi_sag = 0;

void g_ilk_degerler(int deger, float x, float y, float a){

if(!deger){

raket[0].konum_x[0] = -1.0;
raket[0].konum_y[0] = +0.2;

raket[0].konum_x[1] = -0.950;
raket[0].konum_y[1] = +0.2;

raket[0].konum_x[2] = -0.950;
raket[0].konum_y[2] = -0.2;

raket[0].konum_x[3] = -1.0;
raket[0].konum_y[3] = -0.2;

raket[1].konum_x[0] = +1.0;
raket[1].konum_y[0] = +0.2;

raket[1].konum_x[1] = +0.950;
raket[1].konum_y[1] = +0.2;

raket[1].konum_x[2] = +0.950;
raket[1].konum_y[2] = -0.2;

raket[1].konum_x[3] = +1.0;
raket[1].konum_y[3] = -0.2;

}

srand(time(NULL));

do{
derece = rand() % 360;
}while((derece >= 65 &&derece <= 115) || (derece >= 245 && derece <= 295));

daire.hiz_y = 1.50*sin(float(derece*M_PI)/180) / 100;
daire.hiz_x = a*fabs(1.75 * cos(float(derece*M_PI)/180) / 100);

daire.konum_x = x;
daire.konum_y = y;

}

void raket_konumu(int deger){

if(tus_kontrol[esc] == aktif)
exit(0);

if((tus_kontrol['s'] == aktif || tus_kontrol['S'] == aktif) && fabs(raket[0].konum_y[2]) <= 1.0 && fabs(raket[0].konum_y[3]) <= 1.0){
for(i=0; i<4;i++)
raket[0].konum_y[i] += ilerleme.negatif;
}

if((tus_kontrol['w'] == aktif || tus_kontrol['W'] == aktif) && fabs(raket[0].konum_y[0]) <= 1.0 && fabs(raket[0].konum_y[1]) <= 1.0){
for(i=0; i<4;i++)
raket[0].konum_y[i] += ilerleme.pozitif;
}

if((tus_kontrol['l'] == aktif || tus_kontrol['L'] == aktif) && fabs(raket[1].konum_y[2]) <= 1.0 && fabs(raket[1].konum_y[3]) <= 1.0){
for(i=0; i<4;i++)
raket[1].konum_y[i] += ilerleme.negatif;
}

if((tus_kontrol['o'] == aktif || tus_kontrol['O'] == aktif) && fabs(raket[1].konum_y[1]) <= 1.0 && fabs(raket[1].konum_y[1]) <= 1.0){
for(i=0; i<4;i++)
raket[1].konum_y[i] += ilerleme.pozitif;
}

glutTimerFunc(8, raket_konumu, 0);
glutPostRedisplay();

}

void raket_cizimi(){

for(j=0; j<2; j++){
glBegin(GL_POLYGON);
for(i=0; i<4; i++){
glVertex2f(raket[j].konum_x[i], raket[j].konum_y[i]);
}
glEnd();
}

}


void daire_cizimi(){

daire.konum_x += daire.hiz_x;
daire.konum_y += daire.hiz_y;

glBegin(GL_POLYGON);

if(daire.konum_x - 0.020 < -0.970){

g_ilk_degerler(1, raket[0].konum_x[1] + 0.1, raket[0].konum_y[1] - 0.2, +1);
kayip_sayisi_sol++;
usleep(250000);

}

if(daire.konum_x + 0.020 > 0.970){

g_ilk_degerler(1, raket[1].konum_x[1] - 0.1, raket[1].konum_y[1] - 0.2, -1);
kayip_sayisi_sag++;
usleep(250000);

}

if(fabs(daire.konum_y) + 0.025 > 1.0)
daire.hiz_y = -daire.hiz_y;

for(i=0; i<360; i++){

daire.nokta_x[i] = 0.8*0.025 * cos(float(i)*M_PI/180) + daire.konum_x;
daire.nokta_y[i] = 0.025 * sin(float(i)*M_PI/180) + daire.konum_y;

glVertex2f(daire.nokta_x[i], daire.nokta_y[i]);

}

glEnd();

}

int carpisma_algilama(){

if(daire.konum_x - 0.025 <= -0.950){

if(daire.konum_y < raket[0].konum_y[1] + 0.05 && daire.konum_y > raket[0].konum_y[2] - 0.05){

if(tus_kontrol['w'] == aktif || tus_kontrol['W'] == aktif)
daire.hiz_y += ilerleme.negatif/1.25;

if(tus_kontrol['s'] == aktif || tus_kontrol['S'] == aktif)
daire.hiz_y += ilerleme.pozitif/1.25;

daire.hiz_x *= -1;

}
}

if(daire.konum_x + 0.025 >= +0.950){

if(daire.konum_y < raket[1].konum_y[1] + 0.05 && daire.konum_y > raket[1].konum_y[2] - 0.05){

if(tus_kontrol['o'] == aktif || tus_kontrol['O'] == aktif)
daire.hiz_y += ilerleme.negatif/1.25;

if(tus_kontrol['l'] == aktif || tus_kontrol['L'] == aktif)
daire.hiz_y += ilerleme.pozitif/1.25;

daire.hiz_x *= -1;

}
}

else return 0;

}

void skor_gosterimi(){

sprintf(kayip, "%d", kayip_sayisi_sag);
glRasterPos2f(-0.1, 0.9);

for (char *p = kayip ; *p; p++)
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *p);

glEnd();

sprintf(kayip, "%d", kayip_sayisi_sol);
glRasterPos2f(0.075, 0.9);

for (char *p = kayip ; *p; p++)
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *p);
glEnd();
}

void sinir_cizimi(){

glLineStipple(2, 0x00FF);
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINES);

glVertex2f(-0.950, 1.0);
glVertex2f(-0.950, -1.0);

glVertex2f(+0.950, 1.0);
glVertex2f(+0.950, -1.0);

glEnd();

glDisable(GL_LINE_STIPPLE);

glBegin(GL_LINES);

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

glEnd();

}

void goruntuleme(){

glClear(GL_COLOR_BUFFER_BIT);

daire_cizimi();

carpisma_algilama();

raket_cizimi();
sinir_cizimi();
skor_gosterimi();

glFlush();

}

void tusa_bas(unsigned char tus, int x, int y){
tus_kontrol[tus] = aktif;
}

void tusu_birak(unsigned char tus, int x, int y){
tus_kontrol[tus] = pasif;
}

int main(int argc, char **argv){

glutInit(&argc, argv);
glutInitWindowSize(1000,800);
glutInitWindowPosition(50, 50);
glutCreateWindow("PONG");
glutDisplayFunc(&goruntuleme);
g_ilk_degerler(0, 0.0, 0.0, 1.0);
glutKeyboardFunc(&tusa_bas);
glutKeyboardUpFunc(&tusu_birak);
glutTimerFunc(0, raket_konumu, 0);
glutMainLoop();

return 0;

}


0: her türlü amaç için yazılımı çalıştırma özgürlüğü.
1: yazılımın nasıl çalıştığını inceleme ve kendi gereksinimleri doğrultusunda değiştirme özgürlüğü.
2: yeniden dağıtma ve toplumla paylaşma özgürlüğü.
3: yazılımı geliştirme ve gelişmiş haliyle topluma dağıtma özgürlüğü.



travego0403

Wikideki derslerden yararlanan birini görmek çok hoş, böyle takip edildiğini görmek insana güç, kuvvet veriyor yeni konuları eklemek için. :)

Bende OpenGL ye yeni başladığımda bir Pong(kodladığım zaman ismini bilmiyordum :) ) yapmıştım, Tabi ki bir kaç sorunu var ama düzeltmeyede uğraşmadım, zor geldi. :)
http://forum.ubuntu-tr.net/index.php?topic=27738.0
"Matematik bir dildir ve bu dilde şairlere fizikçi denir." Richard Feynman