2 Eylül 2008 Salı

Visual C++ 2008 ve Allegro Kurulumu

Bilgisayarınızda visual studio yoksa bu yeni sürümleri öneririm. Kotasına güvenen indirsin :)

Önce "Visual c++ 2008 Express ve Allegro kütüphane" download linklerini vereyim:

     *Net Framework 3.5 gerekli
http://www.microsoft.com/downloads/details.aspx?FamilyId=AB99342F-5D1A-413D-8319-81DA479AB0D7&displaylang=en

     *Ve de Windows SDK (Burada altta PSDK-x86.exe i seçbilirsiniz (32bit için))
http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en#top

     *Visual C++ Express Edition 2008
http://www.microsoft.com/express/download/#webInstall

     *Allegro Kütüphanesi
http://wiki.allegro.cc/Visual_C%2B%2B_Express_2008

Bunları kurduktan sonra isterseniz kendimiz için şablon bir allegro programı yazalım.

Masaüstüne "GameProject" isimli bir klasör açın ve indirdiğiniz allegro (.zip) dosyasını "GameProject" klasörüne çıkartın. Daha sonra;

Visual c++ i açın "Yeni Proje->Empty Project" i seçin. "Project->Options" bölümünden "C++->General" sekmesinden  şu ayarları yapın: 

(değerleri verirken tırnak işaretlerini mutlaka yazın!)

*Additional Include Directory Files = "$(ProjectDir)\include"

"Linker->General" Bölümüne de:

*Additional Library Directories = "$(ProjectDir)\lib"

"Linker->Input" kısmına da:

*Additional Dependencies = alleg.lib

Ayarları yaptık şimdi kodlara geçelim.

Solda Bulunan Solution Explorer a sağ tıkayın Header Files e New Item diyerek
Dialog'tan .h (Header) filesi seçin adını "Game" verin, aşağıdaki kodları ekleyin


#ifndef GAME_H
#define GAME_H

#include 

/* --------------------------- TEMPLATE --------------------------- */
#define $START_MAIN_PROGRAM int main(){
#define $END_MAIN_PROGRAM   return 0;}END_OF_MAIN();
/* --------------------------- TEMPLATE --------------------------- */

class Game
{
public:
 virtual void Initialize(void);
 virtual void DestroyGame(void);
 virtual void Update(void);

 void run(void);

private:
 BITMAP *buffer;
};

#endif


Daha sonra Source Files e tıklayıp (.c Source Files) "Game" seçin ve oluşturulan Game.cpp dosyasına şu kodları ekelyin


#include "Game.h"

void Game::Initialize(void)
{
 allegro_init();
 install_keyboard();
 install_mouse();

 set_window_title("Game");

 set_color_depth(desktop_color_depth());
 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);

 buffer = create_bitmap(640, 480);
}

void Game::DestroyGame(void)
{
 destroy_bitmap(buffer);
 allegro_exit();
}

void Game::Update(void)
{
 draw_sprite(screen, buffer, 0, 0);
 /* UPDATE GAME CODE */
}

void Game::run(void)
{
 while(!key[KEY_ESC])
 {
  Update();
 }
}


ve birde main.cpp ekliyoruz. Bunlarda son kodlarımız. Projeyi kaydetmeyi unutmayın. Artık masaüstüne açtığınız "GameProject" isimli klasörü zipleyip her zaman kullanmak için saklayabilirsiniz.

main.cpp:


#include "Game.h"

$START_MAIN_PROGRAM

 Game game;

 game.Initialize();

 game.run();

 game.DestroyGame();

$END_MAIN_PROGRAM

18 Ağustos 2008 Pazartesi

Allegro'da Sprite oluşturalım !

Önce masaüstünde bir klasör açın ve adını "Allegro Sprite Denemsi" olarak değiştirin.
Sonra DEV C++ editörünü açın, "Yeni Proje" diyerek "Multimedia" bölümünden "Allegro"
yu seçin, masaüstüne açtığınız klasörün içine kaydedin. Son olarak aşığdaki kodları ekleyerek programınızı "Run" komutu ile çalıştırın.

sprite.h dosyası
------------------------------------------------------------------------------------
#ifndef sprite_H_INCLUDED
#define sprite_H_INCLUDED

#include <allegro.h>

enum Yon { _LEFT = 0, _RIGHT = 1, _DOWN = 2, _UP = 3 };

class Sprite
{
      public:
             BITMAP *_image;
             int _x;
             int _y;
             Sprite();
             ~Sprite();
             void Draw(BITMAP*);
             void Move(int,int);
};

#endif

sprite.c dosyası
------------------------------------------------------------------------------------
#include "sprite.h"

Sprite::Sprite()
{
                _image = NULL;
                _x = 0;
                _y = 0;
}

Sprite::~Sprite()
{
                 if(_image != NULL)
                 {
                           destroy_bitmap(_image);
                 }
}

void Sprite::Draw(BITMAP *__buffer)
{
     if(_image != NULL)
     {
         acquire_screen();
         clear_bitmap(__buffer);
         draw_sprite(__buffer, _image, _x, _y);
         release_screen();
     }
}

void Sprite::Move(int yon, int speed)
{
    switch(yon)
    {
        case (int)_LEFT: _x-=speed; break;           
        case (int)_RIGHT: _x+=speed; break;
        case (int)_UP: _y-=speed; break;
        case (int)_DOWN: _y+=speed; break;
    }     
}

main.cpp dosyası
------------------------------------------------------------------------------------
#include <allegro.h>
#include "sprite.h"

BITMAP *buffer;
BITMAP *scr;

void init();
void deinit();

int main() {
 init();

    Sprite *spr;
    spr->_image = scr;
    spr->_x = 100;
    spr->_y = 100;
    
 while (!key[KEY_ESC]) {
  /* put your code here */
  draw_sprite(screen, buffer, 0, 0);
        
  spr->Draw(buffer);
  
  if(key[KEY_LEFT]) spr->Move(0, 2);
  if(key[KEY_RIGHT]) spr->Move(1, 2);
  if(key[KEY_DOWN]) spr->Move(2, 2);
  if(key[KEY_UP]) spr->Move(3, 2);  
 }

 deinit();
 return 0;
}
END_OF_MAIN()

void init() {
 int depth, res;
 allegro_init();
 depth = desktop_color_depth();
 if (depth == 0) depth = 32;
 set_color_depth(depth);
 res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
 if (res != 0) {
  allegro_message(allegro_error);
  exit(-1);
 }

 install_timer();
 install_keyboard();
 install_mouse();
 /* add other initializations here */
 buffer = create_bitmap(640,480);
 scr = load_bitmap("picture.bmp", 0);
}

void deinit() {
 clear_keybuf();
 /* add other deinitializations here */
}

16 Ağustos 2008 Cumartesi

C++ ile yeni bir Allegro denemesi

Allegro ve c++ ikilisi oyun programlama da ne kadar yeterli bilemem fakat bana çok zevkli gelmeye başladı. İşte size yeni bir örnek daha:


14 Ağustos 2008 Perşembe

Allegroyu biraz kolaylaştıralım !

C++ ile Allegro programlarken, programa giriş noktası yani main() fonksiyonunun hemen başında, ilk satırlarında basit ama uğraştıran, birtakım kodlar yazmak zorundayız. Gerçi gerek yok ama sadece kolaylık olması için bu işleri yapan bir sınıf oluşturabilirz. Hem c++ için pratik yapmış oluruz. 

Kodlara gelince:

//İşimizi görecek olan sınıf
settings.h dosyası :

/* Allegro yardımcı sınıf (beta) */
#include <allegro.h>

enum __DEPTH { x8, x15, x16, x24, x32 };
enum __GFX { WINDOWED = 0, FULLSCREEN = 1, ISNULL = 2 };

/* interface */
class Settings
{
    BITMAP *buffer;
    public:
        enum __GFX gfx_mode;  
        enum __DEPTH color_depth;
        bool _install_keyboard;
        bool _install_mouse;
        bool _show_mouse;
        bool buffer_install;
        int buffer_w, buffer_h;
        BITMAP *__mouse;
        const char* window_title;
              
        Settings();
        ~Settings();         
        void install();               
};

Settings::Settings()
{
    gfx_mode = WINDOWED;
    color_depth = x16;
    _install_keyboard = true;
    _install_mouse = true;
    buffer_install = true;
    __mouse = NULL;
    _show_mouse = true;
    buffer_w = 800;
    buffer_h = 600;
    window_title = "Allegro Game";
}

Settings::~Settings()
{
    /* dispose */                    
}

void Settings::install()
{
    allegro_init();  
    
    if(buffer_install == true)
    {
         buffer = create_bitmap(buffer_w, buffer_h);
    }
    
    switch(color_depth)
    {
        case x8: set_color_depth(8); break;
        case x15: set_color_depth(15); break;
        case x16: set_color_depth(16); break;
        case x24: set_color_depth(24); break;
        case x32: set_color_depth(32); break;
    }
    
    switch(gfx_mode)
    {
         case WINDOWED: set_gfx_mode(GFX_AUTODETECT_WINDOWED, buffer_w, buffer_h, 0, 0); break;               
         case FULLSCREEN: set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, buffer_w, buffer_h, 0, 0); break;
         case ISNULL: set_gfx_mode(GFX_AUTODETECT, buffer_w, buffer_h, 0, 0); break;
    }
    
        if(_install_keyboard == true)
        {
            install_keyboard();
        }  
            if(_install_mouse == true)
            {
                install_mouse();
            }
                if(_show_mouse == true)
                {
                    show_mouse(__mouse);
                }
        
        set_window_title(window_title);
}

//Ana program kodlarımız
ve main.cs:

#include <stdlib.h>
#include <allegro.h>
#include "settings.h"

Settings gSettings;

void InstallAllegro() {
    gSettings.color_depth = x32;
    gSettings.window_title = "Allegro Denemesi";
    gSettings._show_mouse = false;
    gSettings.buffer_w = 320;
    gSettings.buffer_h = 240;
    gSettings.install();
}

int main()
{
    //Ne kadar kısa demi :)
    InstallAllegro();
    
    while(!key[KEY_ESC]);
    
    allegro_exit();
    return 0;
} END_OF_MAIN();

12 Ağustos 2008 Salı

C++ ve Allegro İle Oyun Programlama

Şimdilik allegro ile pencere oluşturup beyaz renkte bir çizgi çizmeyi göstereceğim.
Ben öğrendikçe de sizlerle paylaşacağım ...

#include <stdlib.h>
#include <allegro.h> //Allegro kütüphanesi

int main(void)
{    
    allegro_init();        //Allegro Hazırlanıyor ...
    install_keyboard();    //Klavye Yükleniyor ...
    install_mouse();       //Fare Yükleniyor ...
    show_mouse(NULL);      //Fare Aktif Hale getiriliyor ...
    
    //Grafik modeu Ayarlanıyor ...
    //FULLSCREEN yazan kısımı WINDOWED olarak değiştiriseniz
    //program pencerede çalışır.
    int ret = set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 800, 600, 0, 0); 
    
    //Grafik modu uygulanamıyorsa hata mesajı göster ...
    if(ret != 0)
    {
           allegro_message(allegro_error);
           return 1;
    }
    
    //ESC tuşuna basılmadığı sürece yapılacak işlemler
    while(!key[KEY_ESC])
    {
        //Çizgi çiziliyor x1=0, x2=0, y1=0, y2=0
        //makecol(r, g, b) -> bu kod renk üretir.
        line(screen, 0, 0, 150, 150, makecol(255, 255, 255));
    }
    
    //ESC ye basıldıktan sonra döngü sona erdiğinde allegro dan çık ...
    allegro_exit();
    return 0;
} END_OF_MAIN();

22 Temmuz 2008 Salı

Örnek Flash Oyunum

Sonunda basit de olsa 2D bir oyun yaptık... Flash sayesinde :)

Flash Çalışmasını indirmek için tıklayın (.fla)



Ne kadar basit bir oyun olsa da geliştirlmeye açık. Mesela siz tahmine göre "yukarı"-
"aşağı" şeklinde animasyonlarla sayıyı buldurmaya çalışabilirsiniz ...

13 Temmuz 2008 Pazar

Flash'ta preloading yapımı

Flash'ta geliştirdiğiniz oyunlarda çok işinize yarayacak bir uygulama yapacağız.
Oyun yüklenmeden önce kullanıcıya ön yükleme ekranı göstermelisiniz ki sıkılıp kapatmasın ve bilgilensin.

1. Şimdi Flash'ta bir proje açın, adını "preloading uygulaması" olarak değiştirin.
2. Sonra "Insert - New Symbol - Movie Clip" yapın ve bir dikdörtgen çizin, kenarlıkları kalın ve iç dolgu rengi olmasın.
3. Sonra "Insert - New Symbol - Graphics" yapın ve oluşturduğunuz movie clip in içine atın. Uzunluğunu sıfırlayın (W:0) ve "Instance Name" ini "lbarPos" olarak değiştirin.
4. Movie clipin içine bir de "Dynamic Text" olarak "LOADING 0%" yazın.
Instance Name ini "loadingText" olarak değiştirin.

Son olarak görüntü aşağıdaki gibi olmalı.



Şimdi Movie Clibi ana sahneye taşıyın ve adını(Instance Name) "loadingBar" olarak değiştirin. Bu birinci kare idi. İkinci kareye de bir kaç resim import ederek yerleştirin.

Sonra birinci kareye tıklayıp Actions kısmına şu kodları ekleyin.

5. Kodlar :

stop(); //Animasyonu durduruyoruz.

onEnterFrame = function()
{
 yuklenen = _root.getBytesLoaded(); //swf dosyamızın yüklenmiş byte miktarı
 toplam = _root.getBytesTotal(); //swf dosyamızın toplam byte miktarı
 max = 226; //önyükleme movie clibimizin içindeki lbarPos isimli graphics
                   //nesnesinin maksimum uzunluğu
 
 oran = yuklenen / toplam * 100; //Yükleme oranı % cinsinden
 oran2 = max * oran / 100; //Yükleme oranının maximum uzunlukla oranı
 
        //ana sahnedeki loadingBar nesnemizin içindeki loadingText isimli dynamic
        //text nesnesine yükleme oranını yazdırıyoruz.
 loadingBar.loadingText.text = "LOADING "+ Math.round(oran)+"%";
        //ve uzunluğu artırarak loading efektini veriyoruz
 loadingBar.lbarPos._width = Math.round(oran2);
 
        //Eğer yükleme tamamlandıysa ikinci kareye (resimlerin bulunduğu yere) geç.
 if(yuklenen == toplam) gotoAndStop(2);
}


Ve son olarak CTRL+Enter yapıp animasyonu test edin ve bu penceredeki menuden simulate download seçin böylece animasyonu internette yükleniyormuş gibi görürsünüz.
preloading, flash loading screen, flash loading scene, flash oyun programlama, flash ön yükleme ekranı, flash progressbar

25 Haziran 2008 Çarşamba

Flash'ta Oyun programlama - Pdf Dökümanları



Sanırım 2D Oyunların en iyileri flash'ta geliştiriliyor. Animasyonları ve grafikleri siz hazırlıyorsunuz. Gerisini Action Script tamamlıyor. Tabi bu kadar da kolay değil,
fizik hesaplamaları buradada canımızı sıkabiliyor ...

İşte sizin için internetten araştırıp bulduğum 2 süper pdf dökümanı:

1.Dosya (.pdf)
2.Dosya (.pdf)

5 Haziran 2008 Perşembe

XNA ile Healt Bar yapımı



Genelde aksiyon oyunlarında gördüğümüz bu healt(can,sağlık nyse..) bar yine iki parçalı bir resmin belirli kısımlarının gösterilmesi ile yapılıyor. Bu da source(kaynak) rectangle ile sağlanıyor. Şimdi kodları görelim...

//İlk önce işimizi kolaylaştırmak için bir Sprite sınıfı yazıyoruz.



Şimdi Oyun kodlarına geçelim.





buradan resmi kopyalayın ve XNA Game Studio'da yeni bir Proje açın Content Manager ile resmi yükleyin ve kodları deneyin. Bu küçük bir uygulama fakat yararlı da...
"KOŞMADAN ÖNCE YÜRÜMEYİ ÖĞRENMEK GEREK" :: (:Tom millerin oyun prog. kitabından:)

yazar: CANER DEMİRCİ ((gerisi de var inşallah...))

2 Haziran 2008 Pazartesi

XNA'da Texture Yüklemek ve Render Etmek

Visual Studio açın ve bir XNA Game Studio projesi yaratın. Solution Sekmesindeki
ağaç yapıda "Content" e sağ tıklayıp projenize bir resim dosyası ekleyin.
(Benim tercihim .png formatı) ve daha sonra "Properties" sekmesinde bu dosyanın özelliklerinden "Asset Name" i "deneme" olarak değiştirin. Böylece Xna Game Studio bu 
resim dosyasını .XNB formatına dönüştürecek.

ve sıra kodlarda :

//İlk olarak yükleyeceğimiz resmi ekranda göstermek için
//bir SpriteBatch tanımlıyoruz ...
private SpriteBatch spriteBatch;

//Sonra Texture2D sınıfından texturemizi tanımlıyoruz
private Texture2D myTexture;

//Texturemizin ekrandaki Pozisyonu (Vector2 sınıfı ile)
private Vector2 Position;

//Texturemizin ne kadar Scale edileceği (yani büyültüp küçültme oranı)
// 1 verildiğinde eni ile boyunu 1 ile çarpar yani uzunluğu ve genişliğinde
// bir değişme olmaz
private float Scale; 

//Origin değeri yani merkez noktası
private Vector2 Origin;

//Şimdide Rotation yani döndürme açısı (orjine e göre)
private float Rotation;

//Texturemizin ekstra rengi yani White = Beyaz verilirse renk değişmez
private Color color;

//Texturemizin SourceRectangle değeri yani resmin tam olarak texturenin ne kadar
//bir kısmının gösterileceğini belirle
//Source Rectangle => X, Y, Width, Height değerlerini alır.
//X, Y den başlayark Width ve Height değerleri boyunca devam eder
private Rectangle Source;

//Yüklediğimiz resmin asset name i
private string AssetName = "deneme";


Nesnelerimizi tanımladık şimdi yapacağımız işlemler:
1-Initialize() -> Oyun hazırlanırken ilk değerlerimizi veriyoruz
2-LoadContent() -> bu metod ile texture nesnemizi yükleyeceğiz
3-Draw() -> bu metod ile texture nesnemizi yani resmimizi ekranda göstereceğiz

protected override void Initialize()
{
  this.Scale = 1.0f;
  this.Position = new Vector2(100, 100);
  this.Origin = Vector2.Zero;
  this.color = Color.White;
  this.Rotation = 0f;  

  base.Initialize();
}

protected override void LoadContent()
{
  spriteBatch = new SpriteBatch(GraphicsDevice);
  myTexture = Content.Load(AssetName);
  
  //Bu değeri Initialize metodunda veremedik çünkü texture uzunluk ve yükseklik
  //değerini yüklenen resim den alacağımız için ve resim LoadContent() metodunda
  //yüklendiği için şimdi veriyoruz.
  this.Source = new Rectangle(0, 0, this.myTexture.Width, this.myTexture.Height);
}

protected override void Draw()
{
  graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

  //SpriteBatch nesnemizin render işlemine start veriyoruz
  spriteBatch.Begin();

  //Ve Texture render ediliyor.
  spriteBatch.Draw(myTexture, this.Position, this.Source, this.Color, this.Rotation,
    this.Origin, this.Scale, SpriteEffects.None, 0);

  //SpriteBatch nesnemizin render işlemine son veriyoruz
  spriteBatch.End();
}



kodların hepsini vermedim sadece gerekli blokları yazdım. Çünkü böylesi sizin için daha iyi XNA Game Studio'u açtığınızda karşınıza hazır kodlar gelecektir. Bütün kodu yümüyle kopyalayıp yazmak öğrenme açısından iyi değildir. Kodları yerine kendiniz ilk önceleri bakarak yazın ve "RUn" komutunu verip çalıştırın. Böylece kodu deneyip ne yapabildiğinizi görürsünüz. Zaten sonraları da değiştirmek ve geliştirmek isteyeceksiniz bu arada da belki yüzlerce hata mesajı alacaksınız ama sonunda anlayarak, deneyerek, görerek öğrenmiş olacaksınız.

yazar: Caner DEMİRCİ  (( devamı gelecek ... ))

6 Mayıs 2008 Salı

Visual C++ ile Görsel Programlama

NEDEN C++ ?

Bu soruya çok basit ve net bir cevap verebiliriz. çünkü Windows C++ ile yazıldı. bu durumda C++ ile yazdığınız uygulamalarda windows bileşenlerine tam erişim imkanınız olacaktır. 

Tabii birileri çıkıp size Visual Basic ile de herşeyi yaparsınız diyebilir yada Visual C++ ile birlikte MFC Application wizard kullanın işiniz kolaylaşacaktır diye nasihat edebilir. sakın dinlemeyin ( siz önce temelini öğrenin) MFC de microsoft tarafından kolay uygulama hazırlamak için geliştirilmiş bir sistemdir. kendi içersinde birçok hazır fonksiyon ile kullanımı kolaylaştırır. ama onunla uğraşmaktansa Visual Basic yada daha iyisi Delphi ile uğraşmayı tercih edebilirsiniz. çünkü MFC ile hazırlanan EXE dosyası windows98de bile tam uyumlu çalışmayacaktır ve sizden mfc40.dll isimli bir dosya isteyecektir. Ama sizin amacınız C++ ile oyun yazmak olduğuna göre hepsini unutun. Bugüne kadar öğrendiğiniz birçok kolaylaştırılmış fonksiyonu unutun. Resim çizer gibi form çizmeyi unutun ( Buna daha sonra değineceğiz, aslında Visual C++ ile de çok basit şekilde form çiziliyor ama MFC ile değil)

Tüm bunların yerine önce işin temelini öğreneceğiz. tabii Visual Basic yada Delphi biliyorsanız onlar sayesinde Form nedir değişken nedir diye sormadığınız için çok daha hızlı öğreneceksiniz.

Ben bu sistemi öğrenmeye çalışırken birileri bana "Amerikayı yeniden keşfetmeye gerek yok ! MFC ile çok kolayca form hazırlarsın" diye nasihat etmişti. ama işin aslı bu değil. Win32 sistemini öğrenmek aslında bisiklet kullanmak gibi diyebiliriz. öğrenmesi zor ama onu kullandıktan sonra diğer araçlar çok daha kolay kullanılır. tabii o Amerikayı keşfetmek istemeyenler de üç tekerlekli MFC sihirbazı ile yollarına devam edebilir.

Uygulamalarınızda güç istiyorsanız zor yolları göze almalısınız. Tüm büyük oyunlar Visual C++ ile yazılmıştır.

API ( Windows´un hazır fonksiyonları )

öncelikle belirteyim ki bu ders sadece Microsoft Win32 bileşenleri kullanılarak anlatılmıştır. Bu açıdan sadece visual C kullanıcıları değil Visual Basic, Delphi, Net veya C# kullanıcıları da bu dersten faydalanabilir. Esas amacımız görsel windows programcılığına genel bir bakış yapıp daha sonra oyun programlamaya yönelmektir. Burada anlatacağım bilgileri internetten uzun arayışlar sonucu öğrenmiş bulunmaktayım. herhangi bir sürç-ü lisan edersem affola.

Microsoft firması ilk Windows´u tasarlarken API adı verilen bir bileşen kullanmıştır. daha sonra hem daha kullanışlı olduğu için hemde geriye doğru destek vermesi gerektiğinden sonraki windows sistemlerinde de API sistemi devam etmiştir. bu açıdan burada öğreneceğiniz uygulama Win-95, Win-NT, Win98, WinME ,WinXP sistemlerinde de çalışacaktır. 

-ilk Mesaj-

Herhangi bir Api´yi kullanabilmek için hazırladığınız exe dosyasının windows içindeki gerekli DLL dosyası yardımı ile hazır bir yapıyı çağırması yeterlidir.

Mesela: Ekrana Mesaj kutusu çıkarmak için C:windowssystem dizinindeki User32.dll içersinden MessageBox isimli fonksiyonun çağrılması yeterlidir. Sizin tekrar pencere tanımlamanız yada düğme çizmeniz gerekmez. Aşağıda Visual C++ ile kullanılacak mesaj komutunu görüyorsunuz. Birçok programda mesaj işlemi daha da kısadır ama esas mesaj penceresi budur. Diğer programlar size göstermeden arkaplanda bu fonksiyonu çağırır. Programda bunu kullandığınızda işletim sisteminin kullandığı yerel lisanı kullanan bir mesaj penceresi gelir. burada MB_OK kelimesi mesaj kutusunda dil Türkçe ise Tamam yazısı çıkarır. dil Rusça ise DA yazısı çıkarır. Mesaj penceresini siz çizmediğiniz gibi düğmedeki yazıyı da siz yazmazsınız, hepsi api sayesinde otomatik olarak meydana çıkar.

MessageBox( NULL,"mesaj metni","mesaj penceresi başlığı",MB_OK);
(Visual C++ ile kullanımı aşağıda ayrıntılı olarak anlatılmıştır.)

Visual C++ giriş ( ilk programımız)

Visual C++ programını açıp File >> New menüsünden ilk programımızı yapacağız. ilk program olduğu için sadece mesaj veren bir program yapıyoruz. Karşımıza gelen pencereden Win32 Application seçiyoruz. ve projemiz için bir isim yazıyoruz. location kısmında ise projenin kaydedileceği dizin bulunuyor.



Dosya adı yazdıktan sonra bize hazır proje isteyip istemediğimiz sorulacaktır. biz en üsttekini seçerek boş bir sayfa istiyoruz



Karşımıza gelen pencereye de OK ve Finish dedikten sonra boş bir proje oluşturduk. Şimdi projenin içini dolduracağız. yukardaki Yeni Yazı Sayfası (New Text File) düğmesine tıklaynca sağ taraftaki boş alana yazı sayfası çıkıyor.



En Basit Program ( Sadece bir mesaj kutusu)





Beyaz sayfayı yazı ile doldurduktan sonra kaydediyoruz. Kayıt sırasında dosya uzantısı olarak ".C" yada ".CPP" yazmanız gerekiyor, böylece program bunun bir kod sayfası olduğunu anlıyor. eğer normal txt dosyası olarak kaydederseniz özel fonksiyonlar renkli görünmeyecektir. örnek isim: proje.cpp



yazdığımız kod sayfasını kaydettikten sonra projeye dahil etmemiz gerekiyor. bunu iki şekilde yapabiliriz. birincisi: kod yazılı olan beyaz sayfada boş biryere sağ tıklayıp insert File into Project >> ProjeAdı seçeneği ile



ikincisi sol alt taraftan FileView kısmını açarak ( bu kısımda projede yer alan tüm dosyalar görünür, kod sayfaları, ikon, menü vb.)



Dosya kontrol kısmını açtıktan sonra Source Files >> Add Files to Folder diyerek az önce kaydettiğimiz proje.cpp isimli dosyayı seçiyoruz.



Böylece ilk projemizi tamamladık. Projeye ilk başlarken bu adımları tekrar yapmanız gerekiyor. 
Projeyi çalıştırmak için F5 tuşunu kullanabilirsiniz. Hataları görmek için ise F7 tuşunu kullanabilirsiniz. F7 projeyi exe dosyası olarak hazırlar. F5 ise hazırlanan exe dosyasını çalıştırır. exe dosyası çalıştığında sadece bir mesaj kutusu ekrana gelecektir. programda form falan yok. mesaj penceresi kapanınca program da biter.



Buradaki amacımız esas döngüyü görmekti. programın içersine yazdığımız WinMain isimli kısım Ana döngüyü oluşturur. Programda çalışacak tüm komutları buradaki iki parantez arasına yazacağız. tabii birçok fonksiyon ve değişken tanımlarını bunun dışında yapıyoruz ama programın çalışması için bu kısım kesinlikle gerekli.

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{

}

şimdi de bir form yapalım. Form yaparken başka bir özellik daha karşımıza çıkıyor. LRESULT CALLBACK isimli fonksiyon. bu fonksiyon form tarafından gönderilen mesajları alan bir sistem içeriyor. bu kısımda gelen mesaja göre işlem yapıyoruz.

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ 

}

MESSAGE ( mesaj sistemi)

Windows içersinde her program çalışırken windows ile program arasında mesaj alışverişi olur. Form ilk defa çizilirken program windows´a WM_CREATE isimli mesajı gönderir. form kapatılınca WM_CLOSE isimli bir mesaj gönderir. Form yok edilirken WM_DESTROY isimli bir mesaj gönderir. bunun gibi birçok mesaj bulunmaktadır. henhangi bir düğmeye basılınca WM_COMMAND isimli bir mesaj gönderir. uzun bir listeyi Microsoft´un sitesinde bulabilirsiniz. Biz şimdilik bizim için gerekli olanlara bakacağız.

Switch Fonksiyonu

Bu kısma girmeden önce Standart C kullanımında Switch fonksiyonunu öğrenmelisiniz. Switch yapı olarak IF-ELSE fonksiyonuna benzer ama daha kullanışlıdır. örnekle daha iyi anlatabilirim. case kısmında karşılaştırmalar yapılır. basitçe herbir case için sorgulama yapar diyebiliriz. iki kesme işareti "//" olan satırlar gereksizdir. sadece programcının hatırlatma yazılarını belirtir.

mesaj = 2 ;   // herhangi bir değişken tanımlıyoruz

 switch(mesaj)
  {
      case 1:
              //mesaj değişkeni 1 ise yapılacak işlemler 
      break;

      case 2:
              //mesaj değişkeni 2 ise yapılacak işlemler
      break;

      case 3:
              //mesaj değişkeni 3 ise yapılacak işlemler
      break;

     default:
     // son seçenek
 }

yukardaki işlemde mesaj=2 olduğu için "case 2:" kısmı işlem yapacaktır. program diğer kısımlara uğramadan geçecektir. eğer case kısımlarından hiçbiri doğru değilse default kısmındaki işlem yapılacaktır. Detaylı bilgiyi Standart C ile ilgili kaynaklarda bulabilirsiniz.( ansi-c diye de arayabilirsiniz)

Visual C++ Pencereler (ikinci Program - En Basit Pencere)

Yeni bir proje oluşturup kod olarak aşağıdaki satırları yazıyoruz. her satırda gerekli açıklamaları komut penceresinin altında yaptım. yeni başladıysanız hepsini bir anda anlayamazsınız. Parça parça anlamaya çalışın. aşağıdaki beyaz sayfadaki kodu aynen kopyalayıp kullanabilirsiniz.





Basit Parçalar Birleşince Karmaşık Görünebilir

#include <windows.h> ilk satır bu programda windows bileşenleri kullanacağımızı belirtiyor.
const char Classismi[] = "pencere";burada tanımlanan değişken biraz aşağıdaki WNDCLASSEX objesi için isim olacaktır. 
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)  {
      
switch
(msg)      {
          
case 
WM_CLOSE:              
DestroyWindow(hwnd);
          
break;          

case 
WM_DESTROY:              
PostQuitMessage(0);          
break;          
default:              
return 
DefWindowProc(hwnd, msg, wParam, lParam);      
}      return 0; 
 }          LRESULT CALLBACK isimli fonksiyon içersinde programdan gelen mesajlar(msg) işlenecektir. burada temel iki tane WM_ mesajı yazılmıştır.(WindowsMessage) Eğer programda bir düğme olsaydı WM_COMMAND ile düğmeye basıldığını anlayabilirdik. ( ilgili örnek sonraki sayfada işlenecektir)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)  { } WinMain isimli fonksiyonun mutlaka olması gerektiğini az önceki örnekte görmüştük. bu bizim ana döngümüz.
WNDCLASSEX wc; // Pencere özelliklerini tanımlayacak olan cisim belirleniyor wc

HWND hwnd; // Pencerenin kontrolunda kullanılacak handle ( kulp, sap , kabza) 

MSG Msg; // mesaj için değişken
Bu kısımda önemli bir bilgi için açıklamaya ara veriyorum. HANDLE isimli değişken win32 programcılığında çok önemlidir. herhangi bir nesne ile uğraşırken bu handle numarasını bilmemiz gerekir. Diyelim ki pencereyi gizlemek istiyoruz bu durumda: 

ShowWindow(hwnd, SW_HIDE);

fonksiyonunu kullanabiliriz. Eğer pencereyi tekrar görünür yapmak istersek. ShowWindow(hwnd, SW_SHOW); komutu ile açığa çıkarırız. burada handle numarası hangi pencerenin gizleneceğini belirtir. Diyelim ki Pencere üzerindeki Butonu gizlemek istiyoruz bu durumda ShowWindow(hbuton, SW_HIDE); şeklinde bir komut ile gizleyebiliriz. buradaki hbuton ise buton için tanımlanacak bir handle değişkenidir. ( buton yapmayı ilerde göreceğiz.handle ile ilgili bilgiyi uygulama yaptıkça pekiştirirsiniz ) Açıklamaya geri dönelim:
wc.cbSize = sizeof(WNDCLASSEX); 
wc.style = 0; 
wc.lpfnWndProc = WndProc; //LRESULT CALLBACK fonksiyonun adı, pencere mesajları oraya yollayacak
wc.cbClsExtra = 0; 
wc.cbWndExtra = 0; 
wc.hInstance = hInstance; 
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //Pencere için gerekli icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Pencere üzerinde iken fare işaterçisi hangi şekilde olacak
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); //Pencere rengi
wc.lpszMenuName = NULL;
wc.lpszClassName = Classismi; //Tanımlanan Bu yapıyı çağırmak için kullanılacak isim
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // Pencere için minik icon 

 if(!RegisterClassEx(&wc)) 
{
  MessageBox(NULL, "Pencere tanımlama hatası!", "Hata!", MB_ICONEXCLAMATION | MB_OK); 
  return 0; 
}
Bu kısımda oluşacak pencere için gerekli özellikler bir yapı ile tanımlanıyor. Açıklama yazmadığım özellikler için WNDCLASSEX yapısının açıklamasına microsoft.com sitesinden ulaşabilirsiniz. sıfır yada NULL yazılanlar özel tanımlamalar için gerekli, bizim şimdilik onlarla işimiz olmayacak.
 if(!RegisterClassEx(&wc)) kısmında ise hazırlanan bu yapı windows´a onaylatılıyor. eğer yapıda hata varsa daha pencere açılmadan ekrana Mesaj kutusu çıkacaktır.
hwnd = CreateWindow(Classismi,"Pencere başlığı",WS_OVERLAPPEDWINDOW, 200, 200, 300, 200,NULL, NULL, hInstance, NULL);işte esas fonksiyon bu CreateWindow , ( veya CreateWindowEx ) O kadar yazının tek amacı bu fonksiyona yol verebilmek için bu fonksiyon ile tüm pencere bileşenlerini oluşturacağız. Butonu da aynı fonksiyonla oluşturuyoruz. liste kutusunu da aynı fonksiyon ile. çünkü windows içersinde tüm bileşenler birer pencere olarak varsayılır. bir buton da windows için bir penceredir. sadece şekli farklıdır.

CreateWindow fonksiyonuna ayrıntılı olarak bakmamız gerekiyor, çünkü bu fonksiyonu çok kullanacağız ve bize çok şey öğretebilir. Microsoft´un sitesinde bu fonksiyon şu şekilde tanımlanır.Açıklaması altında.

HWND CreateWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
HWND CreateWindow( // bu HWND ( yani handle=kulp)oluşan yapının sayı cinsinden karşılığıdır. tüm pencerelerin bir handle numarası vardır. bu numarayı bilirseniz sizin programınızın dışında bir programa da emir verebilirsiniz.

LPCTSTR lpClassName, //oluşacak pencere için belirlenen bir sınıf adı. bu sınıfı biz WNDCLASSEX türünden kendimiz oluşturabileceğimiz gibi. BUTTON LISTVIEW, COMBOBOX gibi hazır sınıfları da kullanabiliriz.

LPCTSTR lpWindowName, // Pencerenin adı Eğer bu bir pencere ise bu title olacaktır ( pencerenin tepesindeki yazı) eğer bu bir buton ise düğme üzerindeki yazı olacaktır.

DWORD dwStyle, // pencere özel tanımlamaları bunun listesi .çok uzundur. bir pencere için birkaç farklı sitil kullanılabilir. aralarına dik çizgi konarak "|". 
Eğer hazırlanan ana pencere(form) ise bunlar 
WS_BORDER(kenar çizgisi olsun)
WS_MINIMIZE(program açılışta simge durumunda olsun)
WS_CHILD ( ana pencere dışındaki buton, liste, yazı vb. cisimler için kullanılır. zorunludur)
vb. pencere özellikleri olacaktır.

Eğer hazırlanan buton ise bunlar 
BS_DEFPUSHBUTTON (enter tuşuna basılınca çalışan buton)
BS_CENTER (düğme içindeki yazı ortalı olur) 
BS_PUSHBUTTON (normal bir düğme için)
BS_CHECKBOX (Buton ; onay kutucuğu gibi olur)

Eğer hazırlanan ComboBox ise bunlar 
CBS_DROPDOWN ( seçilebilir liste)
CBS_SORT (girilen yazıları otomatik listeler)

Eğer hazırlanan Edit (Text-Metin kutusu )ise bunlar 
ES_AUTOHSCROLL (yazı kutusunda sağa doğru kaydırma yapar)
ES_LOWERCASE (girilen tüm yazılar küçük harfe dönüşür)
ES_NUMBER ( sadece rakam girilebilir, harf yazılamaz)

Yukarda saydıklarım uzun bir listeden ufak bir parça, uzun listeyi microsoft.com sitesinde developer bölümünde bulacaksınız.Windows sistemini Microsoft yazdığına göre en iyi açıklamaları da onlar yapacaktır.

int x, // oluşan pencerenin soldan uzaklığı, eğer ana pencere ise ekranın solunda uzaklığı

int y, // pencerenin yukardan uzaklığı

int nWidth, //pencere eni
int nHeight, //pencere yüksekliği

HWND hWndParent, // Eğer oluşturulan Ana pencere ise bu değer Null yani boş girilir. Eğer oluşturulan düğme veya metin kutusu gibi yavru bir pencere ise bu değer ana pencerenin HANDLE değeridir.

HMENU hMenu, // Program içersinde dilerseniz tüm alt pencerelere birer menü numarası verebilirsiniz, ( düğme liste vb.) böylece daha kolay erişim imkanınız olur.

HINSTANCE hInstance, //instance numarası, program içersinde sadece bir instance numarası vardır. bu da ilk oluşturma sırasında ana pencereye atanır. ana pencere veya yavru pencerede bu sayı aynıdır.

LPVOID lpParam //pencere oluşturma bilgisinin işaretçisi. özel durumlarda kullanılır. şimdilik bunu boş geçeceğiz (null) sınırsız sayıda yavru pencere oluşturma gibi özel durumlarda kullanılır.
);

Eğer CreateWindow fonksiyonunu anlayabildiyseniz önemli kısmını bitirdik demektir. bunda sonra gelen kısımda pencereyi ekranda gösteren komut ve mesajı alıp parçalara ayıran iki komut var. bunları zaten herzaman kullanacaksınız.

ShowWindow(hwnd, SW_SHOW); //pencereyi göster
UpdateWindow(hwnd); //pencereyi tazele

// üçüncü adım: mesajların alınması ve ayrılması 
while(GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg); 
} 
return Msg.wParam;  //ana döngünün sonu
}

Sonuçta elde ettiğimiz boş pencere böyle olacak.



kaynak: www.tr3d.com (Bu sitede Grafik ve programlama üzerine güzel kaynaklar bulabilirsiniz özellikler 3D Studio Max ile ilgilenenlere tavsiye ederim)

Windows Tetris Oyunu Kaynak kodları

C# ile GDI (grafik kütüphanesi) kullanılarak yazılmış güzel bir tetris oyunu ve kaynak kodları öğrenciler için sunulmuş, windows ta çalışan 2 boyutlu oyun yapmak isteyenlerin incelemesi gereken iyi bir kaynak olmuş ...


Programcı : Şahin UZUNOK kaynak: www.csharpnedir.com DOWNLOAD : http://www.csharpnedir.com/kod/Tetris2007.zip

25 Nisan 2008 Cuma

Euro 2008 Oyunu


EA Canada tarafından geliştirilen UEFA Euro 2008'de, daha hızlı ve kontrollü bir motor bulunacak. Euro 2007'e katılan tüm takımları ve resmi stadyumları içerecek. 50'nin üzerinde Avrupa milli takımıyla oynama imkanı olacak. Ülke Kaptanı isimli yeni mod sayesinde oyuncular sahaya takımlarının kaptanı olarak çıkacaklar. Ayrıca turnuvanın atmosferini geliştirecek olan interaktif kutlamalar yoluyla sahada başarılarını kutlayabilecekler. Buna ek olarak Ülkeler Savaşı modunda, diğer oyuncularla başarıya ulaştırmak için birlikte mücadele edebilecekler.


Euro 2008'in yapımcısı Simon Humber yapımla ilgili olarak, milli takımlar arasındaki rekabeti oyuna taşııdıklarını ve oyunculara ülke kaptanı veya kahramanlarından biri rolüne bürünme imkânı vererek oyuncuların milli takımları için hissettikleri coşkuyu kucaklayacaklarını söylüyor. Ayrıca oyunun motorunu yeni bir düzeye taşıdıklarını ve gerçek turnuva deneyimini ve yaşanan duyguları yakalayabilecek bir oyun yaratmak için pek çok yenilikçi özellik eklediklerini belirtiyor.
UEFA Euro 2008'in diğer bir özelliği ilk defa tüm Avrupa'da, önde gelen cep telefonu operatörleri vasıtasıyla cep telefonlarına da indirilebilecek. Yeni tek düğme kontrol sistemi sayesinde cep telefonlarında rahatça oynanacak. Oyun 11 Nisan'da Avrupa'da, 20 Mayıs'ta ise Amerika'da piyasaya sürülecek. Bence en iyi futbol oyunu KONAMI yapar. PES 2008 mesela ... Konami yaptığı futbol oyunlarında yapay zeka olarak daha önde ...

Windows Sayısal Loto Oyunu

Madem daha directx öğrenemedik o zaman windows ta bişeyler yapayım dedim (can sıkıntısından) ve Sayısal Loto tahmin oyunu yaptım. Oldukça basit bir şey ama c# ile ilgilenenler için Properties(özellik tanımlama) nasıl olur? bunu öğretebilir ...

Download Kaynak kodu : http://www.dosyaupload.net/download.php?file=82505

22 Nisan 2008 Salı

Yapay Zeka - Arama Algoritması

Öngörüsel (heuristic) arama işlemlerinden gerçekleştirmesi en kolay olanlardan birisi Best First Search ya da diğer adıyla Hill Climbing Search olarak adlandırılan bu arama stratejisidir. Hill Climbing algoritmasında arama işleminde o anda aktif olan düğüm genişletilir ve çocuk düğümler değerlendirilir. Bunlardan en iyi değerlere sahip olan düğüm bir sonraki genişletme işleminde kullanılmak üzere seçilir.

Arama işlemi çocukların hepsinden daha iyi bir duruma erişildiğinde sona erer. Bu sistemde hatalı öngörüsel (heuristic) değerler sonsuz yollara, dolayısıyla arama işleminin başarısızlıkla sonuçlanmasına neden olur. Bu nedenle bu algoritmanın başarısı için öngörüsel değerlerinin doğru belirlenmesi büyük önem taşır. Algoritmada önceki basamaklarla ilgili bilgi tutulmamaktadır dolayısıyla hata durumu ile karşılaşıldığında eldeki yanlış çözüm üzerinde bir düzeltme yapılabilmesi söz konusu değildir. Algoritma, tüm çocuklardan daha iyi durumdaki bir düğüme erişildiğinde sona erdiğinden yele maksimum noktaları da sorun yaratmaktadır. İyi mutlak açıdan en iyi olmak zorunda değildir. Hill Climbing algoritması yerel ve global maksimum arasındaki ayrımı yapamamaktadır. Algoritmamızda AÇIK olarak adlandıracağımız gidilebilecek durumların tutulduğu bir liste ve KAPALI olarak adlandırdığımız ziyaret ettiğimiz durumların tutulduğu bir liste kullanılmaktadır. Algoritma aşağıdaki gibidir.

Best First Search Algoritmasının Açık Metin Hali:

1. AÇIK listesine Start düğümünü ekle
2. KAPALI listesini boşalt
3. AÇIK listesinde eleman olduğu surece
4. AÇIK listesinin en solundaki elemanı listeden çıkart . Bu elemanı X olarak adlandıralım.
5. X'ın çocuklarını bul
6. X'in tüm çocukları için
6.1. Eğer child AÇIK ve KAPALI listesinde değil ise 
6.1.1. Child'e bir herustik değer ver ve AÇIK listesine ekle.
6.2. Child AÇIK Listesinde ise
6.2.1. Eğer daha kısa bir yol ile ulaşılmış ise AÇIK lisesindeki Child kayıdının Herustik değerini değiştir.
6.2.2. Child'ın ebeveyn bilgisini günceller.
6.3. Eğer child KAPALI listesinde ise
6.3.1. Eğer daha kısa bir yol bulunmuş ise KAPALI listesinden çıkartıp yeni bilgilere göre güncelleyip AÇIK listesine ekle.
7. X nodunu KAPALI listesine ekle
8. AÇIK listesini herustik değerlerine göre yeniden sırala (En iyi seçenek sola gelecek şekilde)

Best First Search Algoritmasının Arakod Hali:

Procedure best_first_search* (Hill Climbing Search)
Begin
  Open := [Start];
  Closed :=[];
  While open <> [] do Begin
    Remove the leftmost state from open, call it X;
    If  X =goal then return the return the path form the Start to X
    Else begin
      Generate children of X;
      For each child of X do
      Case
        The child is not on open or closed: Begin
          Assign the child a herustic value;
          Add the child to open
        End;
        The child is already on open:
          If the child was reached by a shorter path
          Then give the state on open the shorter path
        The child is already on closed:
        If the child was reached by a shorter path then Begin
          Remove the state from closed;
          Add the child to open
        end
      end;
      put X on closed;
      re-order states on open by heuristic merit (best leftmost)
    end;
  return failure
end.


Algoritma her iterasyonda AÇIK listesinden bir elemanı (anlık olarak en iyi -çözüme en yakın- olan elemanı) çıkartır. Eğer algoritma hedef şartlarına erişirse hedefe ulaşılmasını sağlayan yol bilgisini geri döndürür. Burada dikkat edilecek nokta algoritmanın her düğümün kendi (babası) ebeveyni hakkında bilgi içerdiğini kabul ettiğidir.

kaynak: www.yapay-zeka.org

C++ ile 2D Oyun yapıyor ve çok güzel



Part2


Part3

17 Nisan 2008 Perşembe

Manged Directx Örnek Uygulama - 3

Örnek Uygulama 3

Şimdi de birden çok texture’ü nasıl temel şekilimizin üzerinde görüntüleyeceğimizi görelim.



kaynak: Öğretim Görevlisi Murat GÜNEŞ

Manged Directx Örnek Uygulama - 2

Örnek Uygulama 2

Bu uygulamada da ekrana çizdirdiğimiz teel şekilin(dörtgen) üzerine texture kaplayacağız.



kaynak: Öğretim Görevlisi Murat Güneş

16 Nisan 2008 Çarşamba

Managed Directx Örnek Uygulama - 1

Bu uygulamada ekrana temel şekillerin nasıl çizdirildiğini inceleyeceğiz. İlk uygulama olduğu için texture yerine şimdilik vertexleri boyamayı tercih ediyoruz. Yani kullanacağımız vertex tipi “TransformedColored” olacak.

using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D = Microsoft.DirectX.Direct3D;

namespace Oyun1
{
 public class oyun : Form
 {
  Device device=null;
  VertexBuffer vertbuffer=null;
  public oyun()
  {
   this.ClientSize = new Size(450,450);
   this.Text = "Oyun Deneme!";
  }
  public bool grafik_hazirla()
  {
   try
   {
    PresentParameters d3dpp = new PresentParameters();
    d3dpp.Windowed = true;
    d3dpp.SwapEffect = SwapEffect.Discard;
    device = new Device(0,DeviceType.Hardware,this,CreateFlags.SoftwareVertexProcessing,d3dpp);
    vertbuffer = new VertexBuffer(typeof(CustomVertex.TransformedColored),4,device,Usage.WriteOnly,CustomVertex.TransformedColored.Format,Pool.Default);
    GraphicsStream stm = vertbuffer.Lock(0,0,0);
    CustomVertex.TransformedColored[] verts = new Microsoft.DirectX.Direct3D.CustomVertex.TransformedColored[4];
    verts[0].X = 100; verts[0].Y = 100;verts[0].Z = 0;verts[0].Rhw = 1;verts[0].Color = System.Drawing.Color.Blue.ToArgb();
    verts[1].X = 300; verts[1].Y = 100;verts[1].Z = 0;verts[1].Rhw = 1;verts[1].Color = System.Drawing.Color.Black.ToArgb();
    verts[2].X = 100; verts[2].Y = 300;verts[2].Z = 0;verts[2].Rhw = 1;verts[2].Color = System.Drawing.Color.Red.ToArgb();
    verts[3].X = 300; verts[3].Y = 300;verts[3].Z = 0;verts[3].Rhw = 1;verts[3].Color = System.Drawing.Color.Brown.ToArgb();
    stm.Write(verts);
    vertbuffer.Unlock();
    return true;
   }
   catch(DirectXException hata)
   {
    MessageBox.Show(hata.ToString());
    return false;
   }
  }
  private void render()
  {
   if(device==null)
    return;
   device.Clear(ClearFlags.Target,System.Drawing.Color.BlueViolet,1.0f,0);
   device.BeginScene();
   device.SetStreamSource(0,vertbuffer,0);
   device.VertexFormat = CustomVertex.TransformedColored.Format;
   device.DrawPrimitives(PrimitiveType.TriangleStrip,0,2);
   device.EndScene();
   device.Present();
  }
  protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
  {
   this.render();
  }
  protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
  {
   if ((int)(byte)e.KeyChar == (int)System.Windows.Forms.Keys.Escape)
    this.Close();
  }
  static void Main()
  {
   using(oyun f1=new oyun())
   {
    if(!f1.grafik_hazirla())
    {
     MessageBox.Show("Grafik Hazırlanamıyor!");
     return;
    }
    f1.Show();
    while(f1.Created)
    {
     f1.render();
     Application.DoEvents();
    }
   }
  }
 }
}

Managed Directx Bölüm - 7 Temel Şekillerin Çizilmesi ve Texture

Temel Şekillerin Çizilmesi ve Texture

Artık çalışmaya başlayabiliriz: Adaptörlerin ve Device’ların ne olduğunu biliyoruz, görüntü modlarının ne olduğunu anladık, temel Direct 3D program yapısını biliyoruz ve projeksiyonlar, kameralar ve dönüşümlerle ilgili bilmemiz gerekenleri(şimdilik) biliyoruz. Şimdi tek ihtiyacımız olan şey ortaya koyacağımız sahnelerde rol alacak aktörler: Temel şekilleri çizmek.

Temel şekillerin çizimi, tekil 3D objelerin vertex koleksiyonlarının oluşturulması anlamına gelir. Direct 3D, diğer 3D objeleri oluşturmak için temel olarak poligon – üçgen – kullanır. Çünkü sadece üç nokta ile tanımlanan bir şekil kesinlikle bir düzlemde olacaktır, konveks olacaktır ve bu karakteristikler mümkün olan en hızlı rendering’i sağlayacaktır.

Örneğin ekrana bir kare çizmek istersek, iki tane üçgen kullanmanız gerekir. Bir küp çizmek istersek 12 adet üçgen kullanmalıyız(herbir yüz için iki adet). Şekilde görüldüğü gibi;



Burada bir konudan bahsetmek gerekecek. Birinci bölümde de bahsettiğim gibi 3D objeler ikiye ayrılıyor: Katı modeller ve Meshler. Direct 3D’nin kullandığı objeler, sadece yüzeylerden oluşan meshlerdir. Bu yüzdendir ki eski oyunlarda(yenilerinde bu yavaş yavaş aşılıyor) ekrandaki bir objenin içine giren kamera objenin içerisini ve hatta ötesini gösteriyordu.

Üçgenlerle çalışırken Direct 3D bize, genellikle debug amaçlı kullanımı olan, çizgilerin ve noktaların listesini tanımlamamız için izin verir. Bu sayede içgen kullanırken objemizin wireframe(tel-kafes) görüntüsünü görebilir ve gizli yüzeyleri kontrol edebiliriz.

Direct 3D’de obje oluşturma adımları aşağıdaki gibidir:

1. Verteks tipinini tanımlanması,
2. Bir verteks tamponu(vertex buffer) oluşturulması,
3. Tanımlanmış verteks tipine göre, objenin herbir verteksiyle tamponun doldurulması,
4. Tamponun Device’ta çizilmesi, diğer bir deyişle temel şekil tipinin bildirilmesi.

Şimdilik bütün vertekslerin x,y ve z koordinatlarında tanımlandığını varsayalım(bununla ilgili daha detaylı bilgiyi ileride göreceğiz), bu sayede temel şekil tiplerinin çizimine konsantre olabiliriz.

Verteks tamponu bir kez doldurulduğunda, bunu ekrana çizmek için aşağıdaki kodlar kullanılır:

D3Ddevice.SetStreamSource(0,vb,0);

D3Ddevice.DrawPrimitives(,0,);

Burada vb, VertexBuffer’dan, D3Ddevice da Direct3D.Device’tan türetilmiş birer objedir.

Temel şekil tipi, aşağıdaki PrimitiveType enumeration değerlerinden biri olabilir:

PointList:Herbir verteks diğerlerinden izole edilerek render edilir, bu sayede bir kayan noktalar(floating points) görebiliriz. Çok kullanışlı bir yöntem değil çünkü, DirectX’in 8.0 sürümünden sonra PointSprites isimli yeni bir özelliğe sahibiz. Partikül efektini PointSprites ile vermek daha mantıklı. Aşağıdaki şekil, bir nokta listesi(PointList) olarak renderlenmiş vertekslerin kurulumunu gösteriyor.



LineList:Verteksler, her çifti bir çizgi birleştirmek üzere, çift çift renderlenir. Bu enumeration, eğer vertekslerin sayısına dikkat etmezsek, hata üretir.



LineStrip:Tampondaki(buffer) bütün verteksler tek bir polyline(çoklu çizgi) olarak renderlenir. Bu yöntem özellikle debug amaçlı kullanışlıdır çünkü, bu temel şekil tipi(primitive type) bize, verteks sayısından bağımsız olarak, objemizin wireframe(tel-kafes) görüntüsünü görme imkanı sunar.



TriangleList:Verteksler, izole edilmiş üçgenler gibi, üçerli gruplar halinde renderlenir. Bu bize, kompleks sahneleri(scene) renderlerken en büyük akıcılığı sağlar fakat, eğer bağlantılı üçgenler çizmek istiyorsak ikilenen(üzerinden geçilen) vertekslerin tekrar çizdirilmesi sözkonusudur.



• TriangleStrip:Bu temel şekil tipini, bağlantılı üçgenler çizerken kullanacağız. Bu, karmaşık sahneleri(scene) renderlemek için en çok kullanılan temel şekil tipidir. Çünkü ikilenen verteksleri tekrar çizmek zorunda kalmayız. Çizilen ilk iki verteksten sonra çizilen herbir verteks, bu ilk iki verteksi kullanarak, yeni bir üçgen oluşmasını sağlar.



• TriangleFan:Bu temel şekil tipinde, bütün üçgenler ortak bir verteks kullanır(buffer’daki ilk verteks) ve her yeni verteks, ilk verteksi ve kendinden önce ekleneni kullanarak, yeni bir üçgen oluşturur.



Üçgenleri çizerken, eğer Direct 3D’nin, bir üçgenin sadece ön yüzünü çizmesini (renderlemesini) istiyorsak, üçgenin verteks sıralamasına özel önem göstermeliyiz. Arka yüzeyleri gizleme özelliği “culling” olarak anılır. Bir culling modunu seçtiğimizde, eğer ön yüzün saat yönünde veya saat yönünün tersinde olmasını istiyorsak, bunu belirtmeliyiz; bu sayede aynı verteks düzenini kullanarak bütün üçgenleri çizebiliriz.

Pekala, muhtemelen “bu temel şekil tipleri ilginç ama ekrana tek bir şekil çizmek istersem, bir bitmap ya da diskteki bir dosya gibi. Bunu direkt ekrana çizdiremez miyim?” diye düşünüyorsunuz. Yanıt; hayır. Bir dörtgen oluşturmalısınız(iki üçgenden oluşan) ve resminizi bir texture olarak onun üzerine uygulamalısınız. Yokarıdaki Mesh&Texture başlığı altındaki örneği hatırlayın.

kaynak: Öğretim Görevlisi Murat GÜNEŞ

15 Nisan 2008 Salı

Managed Directx Bölüm - 6 Kameranın Yerleştirilmesi

Kameranın Yerleştirilmesi

3D koordinat sistemiyle çalışırken ekstra bir özellik olarak, DirectX, aynı sahneyi farklı noktalardan görebilmemiz için kamerayı yerleştirmemize izin verir.

Kamera pozisyonu, objenin World koordinatlarına uygulanan bazı özel dönüşümlerle(transformations) hesaplanır. Bu dönüşümler için gerekli olan matrisi manuel olarak hesaplayıp .Transform.View özelliğine setleyebiliriz veya yardımcı fonksiyonlar da kullanabiliriz; Matrix.LookAtLH ve Matrix.LookAtRH gibi. Bu yardımcı fonksiyonlar kameranın pozisyonunu ve baktığı yönü üç nokta ile tanımlar:

1. Kameranın 3D pozisyonu,
2. Kameranın baktığı yerin 3D pozisyonu,
3. (Genellikle y ekseni olan) yukarı doğrultusu.

Eğer bir görüntü(kamera) matrisi tanımlamazsak, DirectX bizim için varsayım bir matris tanımlayacaktır ama bu akılda tutulması gereken önemli bir konsepttir. İlk Prince of Persia oyununu hatırlayın. Burada Prens, oyunun bir sahnesinde, bir yere düşüyordu ve ekran yukarı-aşağı doğrultusunda değişiyordu. Bu özelliği tek bir satır kodla oluşturabileceğinizi hayal edin: Kamera matrisini 1800 döndürerek(bir yönlendirme matrisi ile çarparak). Buradan da anlaşılıyor ki; Direct 3D, 2D oyunlarda dahi büyük avantajlar sağlıyor.

kaynak: Öğretim Görevlisi Murat GÜNEŞ

Managed Directx Bölüm - 5 Matrisleri ve 3D Dönüşümleri Anlamak

Matrisleri ve 3D Dönüşümleri Anlamak

Direct 3D ile çalışırken en önemli nokta, dönüşüm matrislerinin nasıl çalıştığını bilmektir. Matrisleri kullanarak, 3D dünyadaki(veya eğer z bileşenini ihmal edersek, 2D dünyadaki) herhangi bir objenin rotation(yönlendirme), scaling(ölçeklendirme, boyutlandırma) veya translation(çevirimini) yapabiliriz ve bu işlemlerin doğru bir şekilde uygulanması, projeksiyon tipini tanımlamamıza(bir önceki konuda belirttiğimiz gibi) ve hatta aynı sahneyi farklı noktalardan görmek için kamerayı hareket ettirmemize yardımcı olacaktır.

Şimdi basit bir translation yaparak dönüşüm matrislerinin kullanımına bir göz atalım ve sonra bu operasyonu daha kompleks işlemler için dallandıralım. Bir üçgeni y ekseni boyunca yukarıya doğru hareket ettirmek istediğimizi farz edelim. Şekil 1'i inceleyin.



Üçgenimizin aşağıda verilen noktalarla tanımlandığını varsayalım.



y ekseni boyunca 40 birim yukarıya hareket ettirmek için ihtiyacımız olan şey, her y pozisyonunu 40 ile toplamak. Bu durumda vertexler için yeni koordinatlarımız aşağıdaki gibi olacaktır.



Aynı sonuç, her bir verteksi bir satır ve dört sütundan oluşan bir matris gibi göstererek de alınabilirdi. Bu durumda aşağıdaki gibi üç tane matris elde ederdik:



İlk üç sütun vertex koordinatları, 1 de son sütun değeri olacak şekilde sıralanırdı. Ve bu matris özel bir matrisle çarpılarak, ki bu özel matris de vertex matrisinden translation transformation (çevirim dönüşümü) üretmek için oluşturulmuştur, her bir vertexin yeni koordinatları bulunabilirdi.



Sonuç matrisini hesaplamak için, ilk matrisin satırındaki her bir değeri almalı ve ikinci matriste karşılık gelen sütundaki her bir değer ile çarpmalıyız. Daha sonra bütün sonuçların toplamını işletmeliyiz. Bu durumda yukarıdaki örneğin hesaplanması aşağıdaki gibi olur:



Burada fazla detaya girmeden şunu bilmemiz yeterli olacaktır: Transformation(dönüşüm) matrisinin son satırına vereceğimiz değerler, vertex matrisindeki ilgili koordinat değerini(x,y,z) artıracaktır. Ayrıca, dönüşüm matrisindeki 1 değerini değiştirerek scaling(ölçeklendirme, boyutlandırma) yapabiliriz. Bu değerleri diyagonalden kesirliye çevirerek küçültme veya daha büyük değerler vererek objemizi genişletmemiz mümkündür. Veya herhangi bir eksen etrafında şekli döndürmek için sinüs ve kosinüs kombinasyonlarını bu matriste kullanabiliriz.

Şanslıyız ki programımızda dönüşüm kullanmak için bütün bu detaylara kafa yormak zorunda değiliz. Transformation(dönüşüm) yapabilmemiz için bilmemiz gerekenler:

• Dönüşüm matrisleri bilgi kaybetmeden birbirleri ile çarpılabilirler. Bir objeyi aynı anda çevirmek(translate) ve yönlendirmek(rotation) istersek, basit bir şekilde, translation(çevirim) matrisini yönlendirme(rotation) matrisi ile çarparız ve sonucu vertex matris(ler)imiz ile çarptığımızda istenen sonucu elde ederiz.

• Device objesi üç kullanışlı özelliğe sahiptir: 

Birincisi projeksiyon matrisini getirmek için kullanılır:

.Transform.Projection ‘önceki konuda açıklanmıştır.

İkincisi 3D dünyamızda istediğimiz dönüşümleri göstermek için kullanılır:

.Transform.World  ‘bu konuda açıklanmıştır.

Ve üçüncüsü de kamera pozisyonunu belirtmek için kullanılır:

.Transform.View  ‘bu konuda açıklanmıştır.

• D3DX isimli kütüphane bütün dönüşüm(transformation) matrislerini oluşturmak için, matrislerin çarpımları için ve tanımlama(identity) matrisi döndürmek için birtakım fonksiyonlar içerir. (Tanımlama(identity) matrisi, World matrisini güncellemeden önce temizlemek için kullanılan, dönüşmemiş verteksler döndüren özel bir matristir.)

kaynak: Öğretim Görevlisi Murat Güneş

Managed Directx Bölüm - 4 3D Koordinat Sistemleri ve Projeksiyonlar

3D Koordinat Sistemleri ve Projeksiyonlar

Üç boyutlu oyun yazmakla hiçbir ilişkimiz olmasa dahi 3D koordinat sisteminin temel konseptlerini anlamalıyız çünkü Direct 3D'de yaptığımız her şey 3D bir dünya içindeki noktalar ve şekillerle tanımlanmıştır. Elbette z değerini ihmal edebiliriz ve 2D bir dünyada olduğumuzu farz edebiliriz ama sıfır dahi olsa z değeri hala orada duruyor olacak.

Üç kartezyen boyutla çalıştığımız zaman iki tip koordinat sistemi kullanabiliriz: sol-el(left-handed) ve sağ-el(right-handed). Bu isimler, x ve y eksenine göre değişen z eksenini referans alır. bu pozisyonu tanımlamak için, bir elinizin parmaklarıyla x ekseninin pozitif yönüne işaret edin ve y ekseninin pozitif yönüne doğru, saat yönünün tersine hareket ettirin; z ekseni baş parmağınızın işaret ettiği doğrultu olacaktır. Baş parmağınızın işaret ettiği yön ise z ekseninin pozitif bileşenlerine işaret edecektir.



Farklı bir açıdan bakacak olursak, sol-el koordinat sisteminde, ekrandan uzaklaştıkça, z değeri pozitif yönde büyüyecektir(x ve y ekseninin ekranda kaldığını varsayarsak). Sağ-el koordinat sistemi de tam tersi şekilde; ekrandan izleyiciye doğru geldikçe z değeri pozitif yönde küçülecektir.

Direct 3D, sol-el koordinat sistemini kullanır, bu da z'nin pozitif değerinin göründüğü anlamına gelir ve negatif değerler görünmez(ta ki biz kamera pozisyonunu değiştirene kadar ki Direct 3D ile bu da mümkün).

3D koordinat sistemlerini anladıktan sonra sıradaki adım; bu sistemlerin 3D objeleri 2D ekranımızda nasıl gösterdiğini anlamaktır.

Şanslıyız ki bütün zor matematiksel işlemler DirectX tarafından yapılmakta ama projeksiyonların konseptini ve ekranda objelerin nasıl görüneceği ile ilgili temel bilgiyi DirectX'e nasıl adapte ettiklerini bilmeliyiz.

Direct 3D iki farklı projeksiyon tipini destekler;

• Perspektif Projeksiyonu:En yaygın kullanılan projeksiyon tipidir, z farkını hesaplayıp objeleri buna göre ayarlar. Bu projeksiyon tipi, ekrandan uzaklaşan objelerin daha küçük görünmesini sağlar -yani objeler gerçekte olduğu gibi deforme olurlar-. Düz bir yol üzerindeki kesikli şeritlerin ufukta birleşmiş gibi görüneceğini hatırlayın. Şekil 2 perspektif projeksiyonunu grafiksel olarak göstermektedir. 



• Orthogonal Projeksiyon:Bu projeksiyon tipinde, z bileşeni ihmal edilmiştir ve ekrandan uzaklaştıkça, objeler küçülmez ya da yakınlaştıkça büyümez. Bu projeksiyon genellikle 2D oyunlarda veya basit 3D oyunlarda kullanılır. 

Projeksiyon tipini tanımlarken, koordinat sitemi tipini seçmeli ve projeksiyonun tipine bağlı olarak birtakım parametreleri belirtmeliyiz. Direct 3D altı adet ana fonksiyon sunar(bunlardan dördü özel koordinat sistemleri oluşturmak içindir) ve bu fonksiyonlarla oyunumuz için seçtiğimiz projeksiyonu açıkça belirtmemizi sağlar. Bu fonksiyonlar, Direct 3D tarafından, 3D koordinatlardan ekran koordinatlarına yapılacak dönüşümü hesaplamak için kullanılmak üzere matrisler döndürür.

• Matrix.OrthoRH, Matrix.OrthoLH:Bir orthogonal projeksiyon tanımlamak için obje koordinatlarına uygulanması gereken dönüşümleri(transformations) içeren bir matris döndürür(RH =>Right-Handed,LH=>Left-Handed). Her iki fonksiyon da, ekranın genişlik ve yükseklik değerini ve gösterilecek olan z ekseni menzilini parametre olarak alır (ilk z değerinden önceki ve son z değerinden sonraki noktalar gösterilmeyecektir). 
• Matrix.PerspectiveRH, Matrix.PerspectiveLH:Sağ ve sol-el koordinat sistemlerinde, belirtilen ekran genişlik ve yükseklik değerleri ile birlikte z ekseni menzilini(ilk ve son noktalar) parametre olarak alır ve perspektif projeksiyonu için dönüşüm(transformation) matrisi döndürür. 
Matrix.PerspectiveFovRH, Matrix.PerspectiveFovLH:Sağ ve sol-el koordinat sistemlerinde, Fov'un(Field of view-görüntü alanı) radyan cinsinden açı değerini ve z ekseni menzilini parametre olarak alır ve perspektif projeksiyonu için transformation(dönüşüm) matrisi döndürür. 


Managed Directx Bölüm - 3 Mesh ve Texture Yükleme

Mesh ve Texture Yükleme

Bir C#.NET/Windows Application açtıktan sonra DirectX, Direct3D ve Direct3DX referanslarını projemize ekliyoruz. Ardından Editörde General Declerations kısmında using anahtar sözcüğü ile “Microsoft.DirectX” ve “Microsoft.DirectX.Direct3D” classlarına erişiyoruz. Öncelikle bir device hazırlamamız gerekiyor. Kodların hepsi aşağıdaki örnekte açıklanmıştır. Ayrıca kodlarda kameraguncelle isimli bir method var ve yön tuşları aracılığıyla kamerayı hareket ettirmenizi sağlayan birtakım matrix işlemlerini denetliyor. Onunla ilgili ayrıntılı bilgiyi de bir sonraki konu başlığında işleyeceğiz. Bu arada bir Class içerisinde bir device tanımlayıp onu farklı methodlarda kullanabilmek için device’ı “new” keywordu ile deklare ettiğimiz methodu, device’ı kullanacağımız diğer methodda handle etmemiz gerekiyor(Add Handler ile) tabi bu bir yöntem ve bu iş için başka yöntemler de var. Yazdığım örnek uygulamada bu yöntemi kullandım. 
Son olarak mesh ve texture yüklemek için;

Mesh mesh;
Texture texture;
mesh = mesh.FromFile("dosya.x", MeshFlags.SystemMemory, d3ddevice, materials);
texture = TextureLoader.FromFile(d3ddevice, "dosya.bmp");

Kaynak: Öğretim Görevlisi Murat Güneş

Managed Directx Bölüm - 2

Bu bölümde Direct3D üzerine yoğunlaşacağız. Ve Direct3DX'in bazı yardımcı fonksiyonlarını göreceğiz.

Adapters

DirectX'te, sistemimizde kullandığımız adaptör ya da birden fazla ise adaptörler(örneğin ekstradan bir 3D Accelerator kartımız varsa) hakkında bilgi veren birtakım fonksiyonlar var. Hemen şunu da belirtelim managed DirectX ile unmanaged kullanım arasındaki en temel fark; .NET öncesi programlama dillerinde DirectX kullanmaya kalktığımızda yapmamız gereken ilk iş "DirectXn"(n=DirectX sürümü) tipinde bir master obje tanımlayıp diğer bileşenleri, vs. bundan türetmemiz gerekiyordu. Managed kullanımda ise yukarıda da belirttiğimiz alt nesneleri direkt olarak türetebiliyoruz. Her neyse... DirectX'te adaptörümüz hakkında bilgi edinmemizi sağlayan hazır bir fonksiyon var adı da "AdapterDetail". Kullanımı aşağıdaki gibi;

AdapterDetail adaptor_bilgisi;
int i;

For(int i = 0;i< Manager.Adapters.Count – 1,i++)
 {
 adaptor_bilgisi = Manager.Adapters(i).Information
 MessageBox.Show (adaptor_bilgisi.Description)
 }

Yukarıdaki kodda adaptörler hakkında bilgiyi getiren fonksiyonun yanında bir de Manager isimli, Direct3D ile ilgili temel işlemleri yerine getiren bir obje var.

Device

DirectX'in sunduğu özel bir nesne tipi "Device" 3D hızlandırıcı katmana erişmemizi sağlar. Her bir adaptör için üç Device tipinden birini seçmeliyiz. Bunlar;

- Hardware(Hardware Abstraction Layer):HAL(Donanım Soyutlama Katmanı) device türettiğimizde direkt donanım özelliklerine ve dolayısıyla da yüksek bir hıza erişiriz. Bu tip bir aygıtı türetirken sistemimizde 3D hızlandırıcı kartımız yoksa(ki yeni ekran kartlarının hepsi bu özellikte) DirectX hata verecektir.

- Reference(Reference Resterizer):Bu tip bir device türettiğimizde her şey software tarafından yapılacak ve türettiğimiz device donanım bağımsız olacaktır. Ancak bu tip bir Device ile oyun yazmayı aklınızdan bile geçirmeyin çünkü inanılmaz yavaş olacaktır( işlem hızı yaklaşık 1-5 fps arasında).

Device classından bir instance aldığımızda classın Constructor'ına girmemiz gereken parametreler sırasıyla aşağıdaki gibidir;

- Adapter:Burada Default adaptörümüzü kullanacağımızı belirtmek için Manager objesini kullanacağız.
- DeiceType:Amacımız bir oyun yazmaksa tabii ki Hardware seçilecek.
- WinHandle:Aygıtın sunum yapacağı pencerenin Handle'ı(Intptr.)
- Create Flags:Bir enumeration'dır. Seçilebilecek Flaglar aşağıdaki gibidir;
   -SoftwareVertexProcessing:En ideal seçenek, DirectX'e bütün vertex hesaplamalarının Software tarafından yapılacağını bildirir. Bu seçenek en yavaş çalışan seçenektir ama her durumda kullanılabilir.
   -HardwareVertexProcessing:Bu seçenek DirectX'in yazılım katmanında kullanılan Shading(gölgeleme) ve Lighting(ışıklandırma) işlemleri hariç tüm vertex işlemleri için donanımı kullanmasını sağlar. 
   -MixedVertexProcessing:İsminden de anlaşılacağı üzere en iyi performans için iki prosesin karışımını kullanır.
- PresentationParameters:Adından da anlaşılacağı gibi programcının device’ın sunumu için kullanabileceği birtakım ince ayarlar sunar. Sunduğu özellikler aşağıda açıklanmıştır;

- EnableAutoDepthStencil:Depth Buffer tabir edilen derinlik tamponu, Direct3D tarafından kullanılmak üzere derinlik bilgilerini saklayan bir Device özelliğidir. Bu konunun kavranması için derinlik algısı örneği geldi aklıma. Tek gözünüzü kapattığınızda, bakış açınıza göre, x ve y eksenleri aynı, z eksenleri farklı olan iki noktadan hangisinin size daha yakın olduğunu ayırt edemezsiniz. İşte size depth buffer’in yaptığı iş. Render edilen yüzeye yakın olan cisimler ile uzak olan cisimlerin ayırt edilebilmesi için gerekli z ekseni(derinlik) bilgilerini tutar. EnableAutoDepthStencil ise True ya da False değerlerini alır.
- AutoDepthStencilFormat:Depth Buffer’da kullanılan format. Bu format değeri geçerli bir depth buffer formatına setlenmelidir. Mesela “DepthFormat.D16” 16
bitlik bir depth buffer belirtir.
- BackBufferCount:1 ile 3 arasında değişen Back Bufferların numarası.
- BackBufferFormat: Format enumeration’u ile belirtilmiş her bir buffer’in formatı. Örneğimizde mevcut görüntü formatını kullanıyoruz. Burada girilen format stencil’de olduğu gibi geçerli bir format olmalıdır. Direct3D’nin CheckDeviceType methodu ile geçerli formatlar kontrol edilebilir. Windowed modda çalışılacaksa bu değere Unknown setlenerek mevcut görüntü ayarlarıyla çalışılabilir.
- BackBufferWidth ve Height:BackBuffer’in pixel cinsinden genişliği ve yüksekliği. Eğer windowed modda çalışılmıyorsa, bu değerler, CheckDeviceType methodu ile alınan görüntü formatlarından birisine uymalıdır.
- SwapEffect:Oyunun render edilme aşamasında back buffer’dan ekrana gönderilen her bir karenin(front buffer) oluşturduğu bir akış söz konusudur. Render methodumuz çağırıldığında ekrandaki görüntü bir önceki ile değiştirilir(swap). İşte bu değişim esnasında kullanılan SwapEffectleri; Dicard, Flip ve Copy efektleridir. Bunlar sırasıyla aşağıda açıklanmıştır;

o Discard:Bu efekt titpinde değiştirme işlemi(swap)  sırasında back buffer’ın içeriği korunmaz. Bu yüzden her kare (frame) için içerik yenilenmelidir.
o Flip:Bu efektte bufferların ekrana aktarılması swap chain denilen bir değiştirme zinciri ile yapılır. Front bufferları(ekran) içeren döngüsel bir sıra gibi düşünülebilir. Bu sıra içerisinde back bufferlar sıfırdan n-1’e kadar numaralanırlar(n = back buffer sayısı). Bu sıralamada 0 numaralı back buffer en son gösterilendir. Döngü devam ederken front buffer(n-1) back buffer, back buffer(0) da front buffera dönüşür ve bu şekilde devam eder.
o Copy:Bu efektte ise back buffer’ın içeriği korunur. Back buffer’ın içeriği front buffer’ın üzerine kopyalanır.

- Windowed:True değerini aldığında pencere, false değerini aldığında da tam ekran modunda çalışılacağını belirtir. Pencere modunda çalışıldığında back buffer formatı arka plan çözünürlüğü ile aynı olmalıdır. Ben bunun için aşağıdaki yöntemi kullanıyorum;

gmodu = Manager.Adapters [Manager.Adapters.Default.Adapter].CurrentDisplayMode;
PresentParameters d3dpp = New PresentParameters();
d3dpp.BackBufferFormat = gmodu.Format;

Pencere modunda çalışırken BackBufferWidth ve Height parametreleri verilmek    zorunda değildir. Tam ekran modunda ise width ve height parametreleri kullanılabilir bir ekran çözünürlüğü ile örtüşmelidir.
- DeviceWindowHandle:DirectX tarafından kullanılacak pencerenin handle’ı(Intptr).

Yukarıdaki hikaye kısmını anlattığımıza göre asıl işimize, yani .X dosyalarımızın ve texturelerimizin yuklenmesine gelelim. Burada amacım device, presentation parameters gibi bileşenleri ayarladıktan sonra .X dosyasını yüklemenin ne kadar kolay olduğunu göstermek. Bu amaçla directX’te kullanılan iki nesneden bahsedeceğim; “mesh” ve “texture”. 

“mesh” ve “texture” nedir, nasıl kullanılır?

Mesh, DirectX’te ingilizcedeki anlamına yakın bir anlamda kullanılıyor. 3D animasyon yapanlar bilirler ki, yapılan çizimler ikiye ayrılır; katı modeller ve sadece yüzeylerden oluşan meshler. İşte kullanacağımız 3D modellerimiz bu, sadece yüzeylerden oluşan meshler yani .X dosyaları. Texture ise bu yüzeylere kaplanacak bitmap dosyaları.

Kaynak: Öğretim Görevlisi Murat Güneş

Managed Directx Bölüm - 1

DirectX SDK

DirectX bilindiği üzere, Microsoft tarafından oyun geliştiricilerin hizmetine sunulmuş ileri düzey bir grafik API’sidir(Application Programming Interface). Bu API tamamen ücretsizdir ve Microsoft’un sitesinden indirilebilir. Piyasada  kullanılan tek API DirectX değildir tabii ki. Onun en büyük rakibi yine ücretsiz olarak dağıtılan ve açık kodlu bir API olan OpenGL’dir (Open Graphics Language). OpenGL Silicon Graphics firmasının geliştirdiği bir API’dir. OpenGL ile yazılan oyunlara en güzel örnek olarak Quake serisi verilebilir.

DirectX iki farklı şekilde kullanılabilir. Birinci kullanım, DirectX ile yazılmış bir oyunu oynayabilmek için makineye DirectX Runtime(Debug veya Retail seçenekleri ile) kurulmasıdır. İkinci kullanım ise, ki bizi ilgilendiren kısım da budur zaten, Oyun geliştirirken DirectX API’sinden yararlanabilmek için DirectX SDK’nın makineye kurulmasıdır. DirectX 9.0 sürümü ile birlikte .NET ile kullanımının kolaylaşması için Managed Code sistemine geçti. Yani DirectX SDK’yı makinenize kurduktan sonra .NET içerisinden dll’leri(DirectX, Direct3D, Direct3DX vs.) projenize referans olarak göstermeniz yeterli.

İşe ilk olarak DirectX’in bileşenlerini tanıtmakla başlayalım.

Direct X Bileşenleri

-Direct3D(D3D):3D hızlandırıcı katmanına erişmek için kullanılır.
-Direct3DX(D3DX):Direct3D Extensions, Matrix Multiplications(matrix çarpımları) gibi kod yazma işlemini kolaylaştıran birtakım yardımcı fonksiyonlar sunar.
-DirectDraw:Aslında DirectDraw şu anda kullanılmayan bir teknoloji fakat eski oyunların da yeni DirectX sürümleriyle çalışabilmesi için hala barındırılıyor ve yenileştirme içermiyor. 2D oyunların geliştirilmesinde kullanılıyor.
-Direct Input:Input aygıtlarını denetlemede kullanılan bir directX bileşeni, Force Feedback özellikli joystickleri de destekliyor.
-DirectPlay:MultiPlayer oyunlar geliştirmek için kullanılıyor. Bilgisayarlar arasında hızlı ve güvenilir data transferi sağlıyor. Bilgisayarlar arası bağlantı P to P(Peer To Peer) olabileceği gibi Client Server mimarisi ile de yapılabiliyor. İşlem temeli TCP soketlerine dayanıyor.
-DirectAudio:Eski sürümlerinden gelen DirectMusic ve DirectSound isimli iki interface’i var. Aslında DirectAudio yeni bir arayüz değil sadece bu iki arayüzün birlikte kullanımını sağlıyor. Bununla beraber DirectX9.0’ın Managed kullanımı (.NET ile kullanımı) sadece DirectAudio'yu sunuyor.
-DirectShow:Ses ve videoları yakalama ve oynatma için kullanılan bir DirectX bileşeni. Ancak managed kullanımda sadece belli başlı özelliklerine erişebiliyoruz. Daha fazla detaya girebilmek için directX’i unmanaged kullanmalıyız.
-DirectSetup:DirectX içeren uygulamalarımızı paketlerken yardımcı olan bir bileşen.

Kaynak : Öğretim Görevlisi Murat Güneş

25 Mart 2008 Salı

Xna da Mesh Yükleme


XNA da ilk adımlar... Mesh (3 Boyutlu nesne) xna ortamına nasıl eklenir, ekranda nasıl gösterilir, transformasyon işlemleri nasıl yapılır ? Aşağıdaki linkte bu soruların cevaplarını bulabilirsiniz. www.directxnedir.com