Plazma sayı 8, sayfa 29

Bu sayfadaki yazılar

Sayfanın metni

Sayfa 29

Şimdi ise birkaç pixel fonksiyonu göreceğiz. Surface'lerin yapısını tanıtırken sadece pixels değişkeninin değiştirilebilir olduğu belirtilmişti. Bu değişkende yüzeyin pixellerinin renk bilgisi saklanmaktadır. Bu değişken dizisinin değerleri değiştirilebilir ve bu değişiklikler sayesinde ekrandaki pixellerin rengi değiştirilir. Bu işi yapan basit iki pixel fonksiyonu yazalım. Biri seçtiğimiz yüzeye istediğimiz renkte bir pixel yerleştirmeye, diğeri de seçtiğimiz yüzeydeki istediğimiz pixel'in renk değerini almamıza yarayacak.

Uint32 getpixel( SDL Surface *surface, 1 int bpp © surface->format->BytesPerPixel; /* p renk de#erini almak istedi#imiz pixel'in adresi */ Uint8 *p - (Uint8 *)surface->pixels * y * surface->pitch * x * bpp; switch (bpp) 1 case 1: return *p; case 2: return *(Uint16 *)p; case 3: if(SDL BYTEORDER -- SDL BIG ENDIAN) return << 16 | << 8 | pi2l;

int x, int y)

else return | plill << 8 | pi2l << 16; case 4: return *(Uint32 *)p; default:

return 0; /* Bu sonuç ç#kmaz ama

ne olur ne olmaz. */

Pixel dizisinde koordinatlar ilk 0,0 koordinatından başlar ilk elemanı ve her elemanda ilk olarak x değeri büyür. Bu büyüme pixel başına düşen bit kadar olur. Pixel başına 1 bit düşüyorsa her bit ayrı bir koordinattır. Ama 3 bit düşüyorsa 3 bitte bir koordinatları bir ileri gider. x koordinatı değeri limitine ulaştığında sıfırlanır ve y değeri bir artar.

Uint8 *p (Uint8 *) surface->pixels * * surface->piteh * x * bpp;

Satırında yaptığımız işlemde x değerini bpp değişkeni ile çarpıyoruz. bpp değişkeni yüzeyin pixel başına düşen byte sayısını saklıyor. Yukarıda dizinin bir sonraki elemanının koordinat sistemindeki bir sonraki noktanın rengini saklar demiştik ama eğer yüzeyde pixel başına düşen byte sayısı 1 ise doğrudur. Ama bazı durumlarda pixel başına düşen byte sayısı 2 veya 3'e çıkabilir. Mesela RGB renk paleti kullanıldığında her koordinat için ilk byte kırmızı renk değeri, ikincisi yeşil ve üçüncüsü mavi renk değeridir. RGBA renk paletinde ise ilk üçü RGB gibi dördüncüsü ise alfa değeridir. İşte bu yüzden x değerini bpp ile çarptık. Pitch değişkeninde ise yüzeyin bir satırının uzunluğu tutuluyor. y değeri için bir demek x koordinatının limiti kadar gitmiş olmak ve bir nokta daha ileri gitmek demektir.

void putpixel( SDL Surface *surface, 1 int bpp - surface->format->BytesPerPixel; /* p yerle#tirmek istedi#imiz pixel'in adresi

int x, int Y;

Uint8 *p - (Uint8 *)surface->pixels * y * surface->piteh * x *

switch(bpp)

case 1: *p pixel; break; case 2: *(Uintl16 *)p pixel; break; case 3: if(SDL BYTEORDER -- SDL BIG ENDIAN) ( #5 (pixel >> 16) & Oxff; pll) (pixel >> 8) & Oxff; pl2|) 5” pixel & Oxff; ) else | pl0|J 5 pixel & Oxff; plll #5 (pixel >> 8) & Oxff; pl21) # (pixel >> 16) & Oxff; ) break; case 4: *(Uint32 *)p pixel; break;

j

getpixel fonksiyonuna oldukça benziyor. getpixel fonksiyonunda hedef pixel'in adresini bulup oradaki değerleri alıyorduk, burada ise yine hedef pixel'in adresini buluyoruz, ardından hedef pixel'in değerlerini istediğimiz renk değeri ile değiştiriyoruz. Dikkat edilecek nokta ise renk değerini değiştirirken pixel başına düşen bit sayısına göre hesaplama yapıyoruz. Oldukça basit ama kullanışlı.

Bu arada bu pixel fonksiyonlarını kullanırken veya bir yüzeyin pixel verilerine direk ulaşırken ilk olarak üzerinde çalışacağınız yüzeyi kilitlemelisiniz. Açıkçası dalgınlık ve merak ile kilitlemeden de çalıştırdığım oldu. Bunun nedeni ise bütün yüzeylerin ihtiyacı olmamasıdır. Neden diye sormayın bilmiyorum. Ama öyle.

Peki bunu nasıl anlayacaksınız? SDL_MUSTLOCK fonksiyonu ile. En iyisi size bunu yapan bir kod ile açıklamak.

if ( SDL MUSTLOCK(screen) ) (

if ( SDL LockSurface(screen) < 0 ) ( İprintf | stderr, "Yuzey kilitlenemiyor: $shn",

SDL GetError() Vi return; )

Burada ilk olarak screen yüzeyini SDL_MUSTLOCK fonksiyonu ile kontrol eder ve kilitlenmeyi gerektirip gerektirmediğine bakarız. 0 değeri dönerse istediğiniz zaman istediğiniz pixele veri yazabilir, istediğiniz pixelden veri okuyabilirsiniz. Ama 0 verisi dönmezse bu yüzeyi kilitlemeniz gerekir. Böyle olunca da SDL_LockSurface fonksiyonu devreye girer ve parametre olarak girilen yüzey kilitlenir ama bir sorun olur da kilitlenemezse fprintf fonksiyonu ile stderr dosyasına "Yüzey kilitlenemiyor: Hata mesajı" şeklinde bir hata bildirimi yazdırırız.

Uint32 pixel)

Bu arada SDL 1.1.8'den beri yüzey kilitlemek rekürsif, yani ardarda istediğiniz kadar kilit atabilirsiniz bir yüzeye ama bu gibi durumlarda da attığınız her kilit için yüzeyi bir kez daha açmanız gerekir.

Klavyeyle gezinmek için ← ve → tuşları.