C++’ın temelini öğrendiniz ama basit konsol uygulamalarında takılı kaldınız. Grafik, ses, klavye… gibi şeyleri kontrol edebilmeniz için tüm bu yazılım fonksiyonlarını C++’da kullanabileceğiniz hale getiren bir API’ye (Application Programmer’s Interface) ihtiyacınız var.
İşte bu SDL’in yaptığıdır. Windows, linux, mac… araçlarını alıp kodlanabilecek bir halde sarmalıyor ve desteklediği platformlarda derleniyor. SDL’i kullanmanız için öncelikle install etmelisiniz.
SDL bir dll’dir (dynamically linked library) . Bir dll 3 parçaya sahiptir:
- Header dosyası (library.h)
- Library dosyası (library.lib)
- Binary dosyası (library.dll)
Derleyiciniz SDL_Init() ve diğel SDL fonksiyonlarının ne yapıda olduğunu anlayabilmesi için header dosyasına ihtiyaç duyar. Derleyicinizi header dosyasının bulunduğu klasörü araması için konfigüre edebileceğiniz gibi header dosyasını derleyicinizin baktığı lokasyona da koyabilirsiniz. Eğer derleyiciniz SDL.h dosyasını bulmadım diyorsa muhtemelen yanlış yerde olduğu içindir.
Derleyici tüm dosyalarınızı derledikten sonra kaynak dosyalarının linklenmesi lazım. Düzgün bir şekilde linklenmesi için tüm fonksiyonların adresini bilmesi gerekiyor. Dynamically linked library için, bu adresler library dosyasının içerisindedir. Library dosyası, “Import Address Table” ‘a sahiptir, bununla programınız runtime’da fonksiyonları import edebilir.
Header dosyaları gibi, derleyicimizi fazladan başka klasörleri taraması için ayarlayabiliriz veyahut derleyiciyle gelen diğer lib dosyalarının yanına koyabiliriz . Ayrıca linker’a da yerlerini söylemeliyiz yoksa linklenmez.
Programınız derlenip linklendikten sonra programınız çalıştığında kütüphane dosyalarıyla bağlanabilmesi lazım. Dynamically linked olmuş bir uygulamayı çalıştırabilmek için içiin runtime’da library binary ‘lerini import etmeliyiz. İşletim sistemi biz programı çalıştırdığımızda library binary dosyasını bulabilmeli. Bunun için ya executable ile aynı dosyaya koyuyoruz ya da işletim sisteminin kütüphaneleri tututğu yere koyuyoruz.
SDL’in farklı sistemlerde farklı kurulumları aşağıdaki linkte gösterilmiştir:
https://lazyfoo.net/tutorials/SDL/01_hello_SDL/index.php
Ben kurulumu vcpkg ile yaptım. vcpkg bir paket yöneticisi. Micrsof windows 10da visual studio üzerinde çalışıyorum. Birkaç ufak kod satırıyla rahatlıkla farklı küttüphaneleri yüklüyebiliyorum. (öneririm). vcpkg ile yaptıktan sonra Visual studio community’de dosyanın başına aşağıdaki satırı yazmak gerekebiliyor.
#define SDL_MAIN_HANDLED
İlk Window
Bizim için büyük insanlık için çok ufak bir adım atacağız. Ekrana bir pencere çıkartacağız.
Öncelikle kullanacağımız kütüphaneleri include ettik ve render edeceğimiz pencerenin yüksekliği ve genişliği için 2 adet değişken tanımladık. <iostream> yerine çıktı için <stdio.h> (namı diğer printf) kullanmamızın sebebi printf’in thread safe olmasıymış. (Eğer thread safe nedir bilmiyorsanız şimdilik kafanızı hiç karıştırmayın)
//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
Daha sonra main fonksiyonumuzu yazıyoruz. Main’i yazarken parametre listesine int ve char* türünden iki değişken koyuyoruz. Başka bir şekilde yazmak hataya neden olacaktır. SDL birden fazla platformla uyumlu olması için bu tarz bir main’e ihtiyaç duyuyor.
int main( int argc, char* args[] )
{
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
}
Daha sonra SDL_Window ve SDL_Surface i tanımladık. SDL_Surface sadece bir resimdir. Bu resim dosyadan okunabileceği gibi pencerenin içinde de olabilir. Şimdilik pencerenin içindeki bir resim’den ibaret.
Window ve surface’ı tanımladıktan sonra SDL’i initialize ediyoruz. SDL’i initialize etmeden hiçbir SDL fonsiyonunu çağıramazsınız(bir nevi arabanını kontağını çevirip başlatmak olarak düşünebilirsiniz). Şuanlık önemsediğimiz tek şey SDL’in video subsystem’i olduğu için sadece SDL_INIT_VIDEO bayrağını(flag) pass ediyoruz.
Bir hata olduğunda SDL_Init() fonksiyonu -1 döndürecektir. Hatanın ne olduğunu öğrenmek için SDL_GetError() kullanıyoruz. SDL_GetError kullanışlı bir fonksiyondur. Herhangibir sdl fonksiyonunda hata olduğunda bu fonksiyon yardımıyla öğrenebiliriz.
else
{
//Create window
window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
}
sdl initialize edildiğinde pencere oluşturmak için SDL_CreateWindow fonksiyonunu kullanıyoruz. Birinci parametresi pencerenin başlığı, 2. ve 3. parametresi pencerenin oluşturulduğu (x,y) pozisyonu. Eğer pencerenin nerede oluşturulduğunu önemsemiyorsak SDL_WINDOWPOS_UNDEFINED yazıp geçiyoruz. Son parametre olarak oluşturma bayraklarını(creation flags) yazıyoruz.
Eğer bir hata olursa SDL_CreateWindow, NULL döndürüyor. Hatayı çıktı almak için yine SDL_GetError() fonksiyonuyla alıyoruz.
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface( window );
//Fill the surface white
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );
//Update the surface
SDL_UpdateWindowSurface( window );
//Wait two seconds
SDL_Delay( 2000 );
}
}
Pencereyi başarılı bir şekilde oluşturduktan sonra bir şeyler çizdirebilmek için pencerenin yüzeyini (window surface) elde etmemiz lazım (elimizde bir yüzey olacak ki ona çizdirebilerim). SDL_GetWindowSurface ile yüzeyi elde edebiliyoruz.
Bu dersi basit tutmak için yüzeye sadece bir dikdörtgen bastıracağız (SDL_FillRect). Fonksiyona çok takılmayın şuanki amacımız sadece pencere oluşturmak.
Render hakkında bilmeniz gereken önemli bir şey yüzeye bir şey çizmeniz onun ekranda göreceğiniz anlamına gelmiyor. Tüm çizimlerinizi yaptıktan sonra SDL_UpdateWindowSurface fonksiyonunu çağırarak pencerei update ediyoruz (yüzeye çizdiklerimizi ekrana basmış oluyoruz).
Penceremizi oluşturduk, doldurduk ve gösterdik ve programımız anında kapandı :). Penceremizin ekranda belli bir süre kalabilmesi için update fonksiyonundan sonra belli bir süre beklemeliyiz bunun için SDL_Delay fonksiyonunu kullanıyoruz. SDL_Delay fonksiyonu, verilen milisecond cinsinden süre kadar bekleyecektir. Milisaniye, saniyenin 1/1000’i dir. 2 saniye beklemek için 2000 milisaniye yazacağız.
Bu fonksiyonu kullanırken penceremiz fare ve klavye girdilerine yanıt vermeyecektir, endişelenecek bir durum yok.
//Destroy window
SDL_DestroyWindow( window );
//Quit SDL subsystems
SDL_Quit();
return 0;
}
2 saniye bekledikten sonra hafızayı serbest bırakmak için penceremizi SDL_DestroyWindow() fonksiyonuyla yok ediyoruz. Bu fonksiyon ayrıca SDL_Surface ile de ilgileniyor. Tüm her şeyi deallocate ettikten sonra, programı sonrandırmadan önce sdl’den çıkış(quit) ediyoruz ve return 0;)
Kodun tamamını aşağıda bulabilirsiniz:
/*This source code copyrighted by Lazy Foo' Productions (2004-2022)
and may not be redistributed without written permission.*/
//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main( int argc, char* args[] )
{
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Create window
window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface( window );
//Fill the surface white
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );
//Update the surface
SDL_UpdateWindowSurface( window );
//Wait two seconds
SDL_Delay( 2000 );
}
}
//Destroy window
SDL_DestroyWindow( window );
//Quit SDL subsystems
SDL_Quit();
return 0;
}


Leave a Reply