1 Mayıs 2013 Çarşamba

Particle In A Box Yayınlandı!

Sonunda oyunu tamamlayıp Chrome Web Store'da yayınlamayı başardım! Oyunun linkini sitemden bulabilirsiniz. İyi eğlenceler!

26 Nisan 2013 Cuma

Yeni İnternet Sitem

Geçen gün kendime yeni bir internet sitesi açtım: http://antonsem.com/ . Bundan sonra bütün yazılarımı, derslerimi, incelemelerimi ve projelerimi oradan paylaşacağım. Eski yazı ve dersleri de şu anda bu sitede daha organize bir şekilde bulabilirsiniz. Bu internet sitesi yapma işinde henüz amatör olduğum için site çok iyi görünmüyor ve birçok hatam olabilir. Zaman geçtikçe bunları düzelteceğim tabi :) Hepinizi yeni siteme beklerim...

18 Nisan 2013 Perşembe

Başka Bir Game Jam: Ludum Dare

Uzun bir aradan sonra tekrar merhaba arkadaşlar. Bir süredir ders, sınav derken buralara uğrayamadım. Şimdi de çok fazla vaktim yok o yüzden ne yazık ki şu anda yeni bir ders yapmayacağım ama yakın gelecekte birkaç Unity3D dersi, ona bağlı olarak C# ve işinize yarayacağını düşündüğüm Blender dersi yazmayı planlıyorum. En son da bir oyun nasıl Google Play'e koyulur onu anlatacağım.

Peki madem ders yapmayacağım ne diye bunları yazıyorum? Çünkü size Ludum Dare'yi tanıtacağım. Hayır, Ludum Dair diye okunmuyor, bildiğiniz Ludum Dare. Latince'de isim vermek anlamına geliyor. Başlıktan da anlayabileceğiniz üzere bu bir game jam (oyun reçeli?). Formatı Global Game Jam'e çok benzer, tek farkı internet üzerinden yapılıyor olması. Belki bir çoğunuza garip gelebilir, sonuçta Türkiye'de Global Game Jam hep çok büyük ve (özellikle Ankara'da) ödüllü bir organizasyon olmuştur. Bu oldukça yanlış bir yaklaşım. Bu tür organizasyonların amacı hiçbir zaman yarışma olmadı, olmamalı. Amaç diğer oyun yapımcıları ile bir araya gelmek, yeni insanlar tanımak, yeni şeyler öğrenmek. Bu noktada şunu belirtmek isterim ki katıldığım her game jam bana çok şey katmıştır. Belki şu anda bildiklerimin %40'ını bunun gibi organizasyonlarda öğrenmişimdir.

Game jam'i de tanımladığıma göre gelelim Ludum'um kendisine. Ludum 2002'den beri yılda 3 kere düzenlenen bir organizasyon ve 26 Nisan'da 26.sı düzenlenecek. Türkiye saatine göre 27'sinin sabahında, saat 4'te başlayacak ama olsun, 26'sında hazır olmak gerek :) . Bu organizasyon başlamadan önce bir tema belirlenir. Bu seçim de katılımcılara, yani bize bırakılır. Organizatörler bir süredir tema önerilerini alıyordu, şu anda seçme aşaması devam ediyor, http://www.ludumdare.com/theme/ adresinden "tema katliamına" ulaşabilirsiniz. Buradan beğendiğiniz temaya "GOOD", beğenmediğinize de "BAD" diyebilirsiniz. Orada çıkan tema değil de bir oyun türü ya da bambaşka bir şey ise "SLAUGHTER" düğmesine basıyorsunuz. En çok oy alan tema 27 Nisan saat 4.00'da açıklanacak ve organizasyon başlayacak. 48 saat sonra, oyununuzu yapmayı bitirince siteye koyacaksınız ve oylama başlayacak. Birinci olursanız da her game jamde olduğu gibi kocaman bir aferin alacaksınız :) .

"Bir paragraf önce toplanmaktan bahsettin ve bu organizasyon internet üzerinden gerçekleşiyor. Hani game jam ruhu? Hani yeni insanlar tanıma?" diyenlerinizi duyar gibiyim. İşte bu noktada biz devreye giriyoruz. ODTÜ Bilgisayar Topluluğu olarak bir araya gelebileceğimiz bir yer ayarlayacağız ve 48 saat boyunca orada yaşayacağız. Tabi ki sizi de bekleriz. Gelin tanışalım, birlikte oyun yapalım, eğlenelim. Eğer hayatınızda hiç oyun yapmadıysanız da başlamak için çok güzel bir fırsatınız var, gelin öğretelim! Ne olursa olsun bu 48 saatin sonunda boş gitmeyeceksiniz, mutlaka bir şeyler öğrenmiş olacaksınız. En kötü tanışmış oluruz, fena mı?

Son olarak Ludum'un bize sağladıklarından bahsedeceğim. Birçok programın lisansı yanında özellikle bizi ilgilendiren Unity Pro'nun üç aylık deneme lisansını dağıtıyor organizatörler. Belki başlangıç aşamasında bu lisans çok lazım olmayabilir ama siz yine de alın, zararı olmaz.

Merak edenler için:

Ludum Dare resmi sitesi.
Bu da bizi en çok ilgilendiren kısmı.

Herhangi bir sorunuz olursa aşağıdaki yorum kısmından sorabilirsiniz.
Kendinize çok iyi bakın, haftaya görüşmek üzere.

21 Şubat 2013 Perşembe

Bağımsız Oyun Yapımcısı, Hüseyin Uslu


Türkiye'de amatör oyun sektörü konulu yazımda söz verdiğim gibi Hüseyin Uslu'nun kendini ve oyunlarını tanıttığı, en sonunda da yeni başlayanlara ve başlamak isteyenlere birkaç tavsiye verdiği yazıyı yayınlıyorum. Buyurun okuyun.

Adım Hüseyin Uslu, Başkent Üniversitesi Bilgisayar Mühendisliği mezunuyum ve indie yani bağımsız oyun geliştiricisiyim. Atari 2600 ile oyunlarla tanışdığım ilk günlerden beri kendimi sıkı bir oyuncu olarak niteleyebilirim. 

Bağımsız geliştirici olarak oyun geliştirmeye başlamamın temel sebebi olarak ise oyun programcılığının, ilgi duyduğum gerçek zamanlı sistemlere ve alt-seviye programlamaya yakın bir profil çiziyor olması diyebilirim. Global Game Jam'lere katılarak birkaç basit oyunla sürece ısındıktan sonra, ilk olarak Minecraft tarzı bir block motoru üzerinde çalışmaya başlayarak oyun geliştirmeye ilk adımımı attım.

Minecraft ve benzeri block tabanlı oyunlar, yapıları itibari oldukça basit olsadalar da işin mutfağında,
tatmin edici performans alabilmek için bir çok püf noktasına dikkat edilmesi gereken yapımlar. Ayrıca grafiksel malzeme gereksinimlerin oldukça az olması nedeniyle, yeni başlayan bir oyun programcısının, tek başına "programmer-art" olarak tabir ettiğimiz temel materyallerle üzerinde çalışabileceği ve ihtiyaç duyacağı bütün teknikleri tatbik edebileceği bir tür. İşte bu yüzden ilk projem, geçen bir kaç ay içerisinde açık kaynak olarak yayınladığım Voxeliq adlı block motoru (https://github.com/raistlinthewiz/voxeliq) oldu.

Devamında büyük ölçüde tamamlanmış ArchStone adlı (http://www.int6.org/games/archstone/) bir şanş-oyunu geliştirdim ve yakın zamanda Unity3D'nin platformu desteklemesi ile birlikte Windows 8 Store'da yayınlamayı planlıyorum.

Şu anda aktif olarak da Frenzied adlı (http://www.int6.org/category/frenzied/) bir puzzle oyunu geliştirmekteyim. MonoGame ve C# kullanarak geliştirmekte olduğum Frenzied, Windows 8 Store, Windows Phone 7 & 8, Android ve IOS gibi birçok platformu desteklemekte ve yakın zamanda sırasıyla bu platformlarda yerini alacak.

Ek olarak XNA'nın varisi olan ve Mono tarafından desteklenen C# tabanlı MonoGame (http://monogame.net/) projesini aktif olarak takip ediyor ve katkıda bulunuyorum. 

Yeni başlayanlara vereceğim nacizane tavsiyem ise, herşeyden önce bu işe küçük adımlar atarak başlamaları gerektiğini söylemek olacaktır. Genellikle oyun geliştirmeye yeni başlayanların en büyük hatası, altından kalkabileceklerinden daha büyük proje ve fikirlerlerle başlangıç yapmaya çalışmalarıdır. 

Programlama, oyun geliştiriciliği açısıdan temel taşlardan biri olsa da, oyun geliştiriciliği çok disiplinli bir süreç olarak karşımıza çıkmakta. İşte bu yüzden geniş çaplı projelerde, tek bir geliştirici için bütün bu süreçler bir noktadan sonra ağır bir yük haline gelebilmekte ve motivasyon kaybının en önemli nedeni olmakta. Mümkün mertebe, küçük çaplı projelerle yola çıkmak ve her şeyden önce basit bile olsa birkaç oyunu A'dan Z'ye bitirerek bütün süreci deneyimlemekte fayda görüyorum. Bu noktada GGJ (Global Game Jam) ve Ludum Dare gibi kısıtlı sürede oyun geliştirmeniz gereken ve süreci görebileceğiniz Jam'lere katılmakta oldukça yararlı olacaktır.

Ek olarak oyun geliştiriciliğine yeni başlayanlar, genelde hangi dili tercih etmelerini gerektiği konusunda karar vermekte zorlanmaktalar. C++ gibi bir dili bilmek / öğrenmek, bir oyun programcısı açısından oldukça önemli olsa da, şu unutulmamalı ki, muhtemelen yeni başladığınızda geliştereceğiniz oyunlar, C++ ve C# gibi managed bir dil arasındaki performans farkının çok önemli bir faktör olmadığı oyunlar olacak. İşte bu yüzden C# gibi harika bir dili taban alan ve Windows, MacOS, Linux, Android, IOS, Windows Phone 7, Windows Phone 8 ve Ouya gibi birçok platformda çalışabilen MonoGame (http://monogame.net/) projesini şiddetle tavsiye ediyorum. Tabi ki kullanacağınız dil veya framework, hiç bir zaman amaç olmamalı, sadece bir araç olarak kalmalı ve her projeye en uygun dili / platformu tercih etmeliyiz.

Son olarak da sürekli olarak takip ettiğim ve yeni başlayanlara yararlı olacağını düşündüğüm bir kaç kaynağı paylaşmak istiyorum;
* http://reddit.com/r/gamedev - reddit'in oyun programcıları için olan oldukça faydalı alt-bölümü.
* http://gamedev.stackexchange.com/ - oyun programlama ile alakalı teknik soru ve cevapları bulabileceğiniz bir kaynak.
* http://www.pixelprospector.com/ - Bir bağımsız oyun geliştiricisinin ihtiyacı olabileceği bütün kaynakları bir araya toplayan bir site.
* https://www.facebook.com/groups/gamedevturkey/ - Diğer Türk oyun geliştiricilerle bir araya gelip paylaşımda bulunabileceğiniz grup.
* http://www.oyungelistirici.org/ - Oyun geliştirme hakkında bulabileceğiniz nadir Türkçe kaynaklardan.

19 Şubat 2013 Salı

Türkiye'de Amatör Oyun Sektörü


Merhaba arkaraşlar. Uzun zamandır yazı yazmadım, biraz boşladım buraları. Tahmin edebileceğiniz gibi bunun sorumlusu büyük ölçüde derslerin ağırlığı. Hazır tatil, dersler başlamadan bir iki yazı yazayım dedim. Bu seferki yazım bir ders değil, bir tanıtım yazısı. Türkiye'de geliştirilen oyunlardan bahsedeceğim sizlere. Ama öyle sık sık rastladığınız bir yazı olmayacak bu; öyle bir yazı zaten yazmıştım önceden, şuradan ulaşabilirsiniz: http://e-bergi.com/2010/Kasim/Turkiye-Oyun-Sektoru , http://e-bergi.com/2011/Ocak/trkiyede-oyun-sektr-2 . Bizler gibi amatörce oyun geliştirmeye çalışanlardan ve oyunlarından bahsedeceğim sizlere.

Son birkaç gündür forumlarda dolaşıyorum ve Türkiye'de ne kadar çok oyun geliştirmeye çalışan insan varmış, onu fark ettim. Sözü daha fazla dolandırmayıp tanıtımlara geçeyim...

İlk oyunumuz Ornito. Bu oyunun geliştiricis Ahmet Sami Avcı hepimiz gibi çocukluğundan beri oyun oynuyor. Oyun yapımına lise yıllarında RPG Maker ile başlamış. Şu anda Gazi Üniversitesinde İngilizce Öğretmenliği okuyan Ahmet'in şimdiye kadar giriştiği en büyük oyun projesi Ornito. Ornito'nun tarzı J-RPG (Japon rol yapma oyunu). Hikayesi çok farklı başlamıyor ama oyundaki espiri anlayışı ve pop kültüre yaptığı göndermelerle öne çıkıyor. Oyunlarda hikeyeye önem veriyorsanız ve J-RPG seviyorsanız kaçırmayın.
Ornito'nun sitesi www.buwue.org şu anda yapım aşamasında. Şimdilik güncel bilgilere oyungezer forumlarından, http://oyungezer.com.tr/forum?func=view&catid=69&id=1603576 ulaşabilirsiniz.






Sıradaki geliştiricimiz Ege Üniversitesinin Devlet Türk Musikisi Konsetvatuarı mezunu Emre Şaşmaz. Emre'nin şimdiye kadar iki oyun geliştirdi. İkisi de korku türünde. Sayha adlı oyunu dün gece oynamak gibi ufak bir hata yaptım... En son Amnisia'yı oynarken bu kadar tırstım. Konusu da Amnisia'yı andırıyor. Oyunun başında hafızamızı kaybetmiş, biraz da kafayı yemiş bir şekilde bir tımarhanede buluyoruz. Oyundaki ses ve panik atak efektleri oynayanı tedirgin etmeyi gerçekten iyi başarıyor. Ne yazık ki Seyha'nın sadece demosu var, sitesinden daha fazla geliştirmeyeceğini açıkladı. Oyun hakkında daha fazla bilgi almak ve indirmek için http://sayha.pantharay.com/ sitesine bakabilirsiniz.

Sayha'nın grafikleri çok hoş görünüyor.


Çok korkarsanz panik atak geçirebilirsiniz.

Emre'nin ikinci oyunu Mühürkent. Ne yazık ki demosunu deneme fırsatım olmadı ama gördüğüm ekran görüntülerinden ve sitesinde izlediğim videodan Seyha'dan aşağı kalır bir yanı olmadığını gördüm. Son gelişmeleri Emre'nin blogundan, http://blog.pantharay.com/ 'dan takip edebilirsiniz.


Bundan sonra bahsedeceğim oyun Ocean City Racing. Ocean City Racing'i Yeditepe Üniversitesinin Yönetim Bilişim Sistemlerinden mezun olan Onur Uça geliştiriyor. Ocean City Racing açık dünya bir yarış oyunu. Unreal Engine ile geliştirilen oyun görsel açıdan çok iyi görünüyor. Henüz bir demosu olmadığı için oynanışı konusunda bir yorum yapamayacağım ama sitesinde birçok videosu mevcut. Ayrıca oyunu şu anda Steam GreenLight'ta bulabilir ve destek verebilirsiniz. Oyunun resmi sitesi: http://www.oceancitygame.com/ Steam Greenlight Sitesi: http://steamcommunity.com/sharedfiles/filedetails/?id=93449140&searchtext=ocean+city+racing . Onur'un diğer projeleri için sitesini inceleyebilirsiniz: http://www.onuruca.com/ .


Ocean City Racing'in grafikleri oldukça güzel görünüyor.

Ocean City Racing'de araba haricinde de araç kullanabiliyorsunuz.


Bu yazıyı yazmdan önce bansettiğim birçok oyun geliştiricisine mail attım, cevap verenlerden birisi Hüseyin Uslu oldu. Cevabı biraz uzunca oldu, o yüzden tamamını ayrı bir yazı olarak yayınlayacağım. Hüseyin Başkent Üniversitesi bilgisayar mühendisliği bölümünden mezun. Programlamaya çok ilgi duyan Hüseyin Global Game Jam'lere katılarak kendini epey geliştirdikten sonra Minecraft tarzı bir oyun motoru üstünde çalışmaya başlamış. Motorun ismi Voxeliq. İlk gördüğünüzde Minecraft klonu sanabilirsiniz. Görünüş itibari ile çok benziyor olsa da Voxeliq ile birçok farklı şey yapabilirsiniz, mesela oyun gibi. Evet yukarıda da dedğim gibi Voxeliq bir oyun motoru. Minecraft'tan bir diğer farkı da performansı. Açık kaynak olarak yayınlanan bu motorun kodlarını dilediğiniz gibi kurcalayıp geliştirebilirsiniz. Bütün kodlarını şuradan indirebilirsiniz: https://github.com/raistlinthewiz/voxeliq .

Voxeliq Minecraft'ı andırsa da özünde bir oyun motoru.


Hüseyin'in üstünde çalıştığı bir başka oyun da ArchStone. ArchStone Unity3D ile geliştirilen ufak bir şans oyunu. Daha ayrınıtı bilgilere şu steden ulaşabilirsiniz: http://www.int6.org/games/archstone/



Hüseyin'in şu anda üstünde çalıştığı bir proje daha var, ismi Frenzied. Frenzied gerçek anlamda Monogame ile geliştirilen bir bulmaca (puzzle) oyunu. Monogame sayesinde gerçek anlamda multiplatform olan (Windows 8 Store, Windows Phone 7, Windows Phone 8, Android, Windows Desktop, IOS, MacOS, Linux, Ouya) Frenzied yakında tamamlanacak gibi görünüyor.



Hüseyin'in çalışmalarını daha yakından takip etmek için http://www.int6.org sitesini ziyaret edebilirsiniz.

Mail atıp da ulaşamadığım bir site var, Kartoon.gen.tr. Ne yazık ki o siteyi ve içeriğini yapan arkadaşın ismini de bulamadım ama girerseniz siz de göreceksiniz ki sitede çok başarılı ve eğlenceli birçok oyun ve animasyon yer alıyor. Bunların arasında en ünlüsü Abuzittin'in maceraları sanırım. Abuizittin serisi point & click dediğimiz Monkey Island tarzı macera oyunlardan oluşuyor. Seri boyunca arkadaşının nişan yüzüğünü kaybetmesinden mafya işlerine karışmasına kadar bir çok absürt olay geliyor Abuzittin'in başına.

Abuzittin'in maceraları bir yüzükle başlıyor.


Kartoon.org.tr'de bulabileceğiniz oyunlar arasında kendi içerisinde birçok mini oyunu olan Virüslerin saldırısı, yazı tabanlı Gizemli Orman, birkaç tane de ufak oyun var. Hepsi çok eğlenceli yapımlardır, azıcık bile olsa böyle şeylere ilginiz varsa kaçırmayın derim.

Evet, bir yazının daha sonuna geldik. Türkiye'deki amatör oyun geliştiricileri bu kadar değil tabi, bunlar sadece ilk etapta bulduğum ve ulaşabildğim (en azında bilgi bulabildiğim) insanlardı. Siz de kendinizi amatör de olsa bir oyun geliştiricisi olarak görüyorsanız bu yazının altına yorum yazın ya da bana bir şekilde ulaşın, bir sonraki yazıda sizin oyununuzdan ve sizden de bahsedeyim. Bir dahaki yazıya kadar hoşçakalın.

27 Ocak 2013 Pazar

GGJ 2013'te yaptığımız oyun, Feed The Boss

Global Game Jam 2013'ün son saatleri... Ceren Tecim ve Tülin Samav ile aralıksız, 48 saat boyunca geliştirdiğimiz oyun sonunda bitti!

Feed The Boss, Stairway To Earth'ten çok farklı değil, amacınız Karanlık Lord'a yaranıp sağ kolu olmak. Bunun için bölüm içinde bulduğunuz kalpleri ona götürmelisiniz. Tabi bunu rakibinizden önce yapmalısınız. Kalbi ilk alan rakibiniz olursa ona vurarak kalbini düşürmesini sağlayabilirsiniz. Kalp sizde iken rakibinize vuramazsınız.

Kontoller:

Sarı Hayalet:
Zıpla: yukarı yön tuşu
Sağa: sağ yön tuşu
Sola: sol yön tuşu
Vur: sağ shift

Kırmızı Hayalet
Zıpla: w
Sağa: a
Sola: d
Vur: sol shift

Birkaç tane  de ekran görüntüsü koyayım:





Oyunu bu sayfadan indirebilirsiniz.

5 Ocak 2013 Cumartesi

Particle In A Box son beta sürümü

Artık aklıma gelen ve yapmak istediğim her şeyi yaptım. Oyunun düzeltilecek bir tarafını bulamıyorum, o yüzden sanırım son hali böyle olacak. Bundan sonra sadece bölüm yapacağım. Bu sürümde şunları ekledim:

- Bölümler seviye atladıkça açılıyor
- Arkaplan ekledim ve menülerin görünümlerini değiştirdim
- "Credits" menüsü ekledim
- "How to play" menüsünü güncelledim

Daha önce Particle In A Box oynadıysanız options'a girip oyun kayıtlarını silin. Özellikle bundan sonraki geri bildirimler benim için çok önemli. Herhangi bir eksik görürseniz ya da bir öneriniz olursa lütfen haber verin.

Birkaç ekran görüntüsü:





Windows ve Android betalarını bu sayfadan indirebilirsiniz.

19 Aralık 2012 Çarşamba

Particle In A Box beta

Sonunda biraz boş zaman bulup Particle In A Box ile uğraşabildim. Başlıktan da anlaşıldığı gibi oyunu beta sürümüne kadar getirdim. Oyunun bu sürümünde getirdiğim en önemli özellik skorlarınızı kaydedebiliyor olmanız. Daha doğrusu skorlar otomatik olarak kaydediliyor, siz istediğiniz zaman silebiliyorsunuz. Bir de fark edeceğiniz gibi menüleri değiştirdim, çok daha güzel ve kullanışlı bir hale getirdim. Son olarak da oyunun Android versiyonunu yaptım ve onun da apk'sını indirip telefonlarınızda ya da tabletlerinizde oynayabilirsiniz. Bu aşamada oyunu daha çok teknik açıdan geliştirdiğim için sadece iki yeni bölüm yapabildim.

http://antonsemchenkoprojects.blogspot.com/2012/12/particle-in-box-alpha.html

Not: Yenilikler sadece yukarıda bahsettiklerimle sınırlı değil, diğerlerini oyunu oynayınca fark edersiniz zaten.
Not2: Herhangi bir sorunla karşılaşırsanız ya da öneriniz olursa mutlaka yazın.

21 Kasım 2012 Çarşamba

Unity Dersleri

Gördüm ki Unity ile oyun geliştirmek çok basit, çok fazla bir şey bilmeye gerek yok. O yüzden Unity dersleri hazırlamaya karar verdim. Daha yeni olduğum için hemen başlamayacağım ama kendimi hazır hissettiğimde ilk dersi yapacağım.


20 Kasım 2012 Salı

Particle In A Box Alpha

Unity ile Android için geliştirmeye başladığım oynun, pc alpha versiyonudur. Şimdilik sadece dokuz bölümü var.



Kontolleri oldukça basit, topun "a"ya basarak yükselmesini sağlıyorsunuz. Bir de "s"ye basarak hızlandırabilirsiniz. Amacınız her bölümdeki bütün topları toplayarak finiş çizgisine ulaşmak.

Oyunu deneyenler şurası zor olmuş, burayı böyle yapsan daha güzel olur, bir de şöyle bir şey ekle şeklinde feedback verirse sevinirim.

30 Ekim 2012 Salı

Projelerim

Yaptığım ve yapacağım bütün projeleri bir sayfada toplayayım dedim. Şimdilik sadece Stairway to Earth ve Goyun sayma uygulamasını koydum. Yakında şu anda üstünde uğraştığım oyunun da tanıtımını yapacağım. Buyurun siz de bakın: http://antonsemchenkoprojects.blogspot.com/

27 Haziran 2012 Çarşamba

Pygame (4)

Herkese tekrar merhaba. Bu sefer arayı fazla açmayım hemen yeni bir ders yazayım dedim. Geçen derste menü yapacağımızda bahsetmiştim, fazla uzatmadan benim kullandığım yöntemi anlatayım.

Yapacağımız şey oyunun döndüğü while döngüsünün içine bir while döngüsü daha eklemek. Menüye gireceğimiz zaman ikinci while'ın şartını doğru yapacağız, işimiz bitince de yine yanlış yaparsak asıl oyunun döndüğü while döngüsü kaldığı yerden devam edecektir. Tabi bunun için öncelikle menünün while döngüsünü yazmamız lazım.

Yapacağımız menüde önce butonları yapalım, sonra içlerine yazı yazarız. Bütün bunları bir sınıf ile halledebiliriz. Bu sınıf çağrıldığında butonun kendisi olan bir dikdörtgen ve içindeki yazıyı döndürecek. O halde sınıf dikdörtgenin boyutlarını, rengini ve yazıyı argüman olarak almalı. Ayrıca işimizi kolaylaştırmak için işlevini de argüman olarak alalım ve basıp basmadığımızı kontrol eden bir fonksiyon yazalım. Hemen hemen her şeyi düşündüğümüze göre sınıfı yazmaya başlayalım:


class düğme():
    def __init__(self, renk, boyut, koordinat, yazı, yazının_rengi, işlevi):
        self.işlev = işlevi
        self.renk = renk
        self.boyut = boyut
        self.koordinat = koordinat
        self.yazı = bizim_font.render(yazı, True, yazının rengi)
        self.kare = pygame.Rect(self.koordinat, self.boyut)

    def bas(self):
        (x, y) = pygame.mouse.get_pos()
        if self.kare.collidepoint((x, y)):
            return True
        else:
            return False

Tabi bir önceki derste anlattığım gibi bizim_font'u tanımlamış olmamız lazım. Yukarıda kullandığım pygame.mouse.get_pos() fonksiyonu tahmin edebileceğiniz gibi mouse'un koordinatlarını (x, y) şeklinde döndürüyor. kare.colliedpont((koordinatlar)) fonksiyonu da aynı kare.colliderect() fonksiyonu gibi çalışıyor. Aralarındaki tek fark colliderect iki karenin çarpışıp çarpışmadığını kontrol ediyor, collidepoint ise bir noktanın karenin içinde olup olmadığını kontrol ediyor. Artık düme_ismi.bas() fonksiyonunu çağırdığımız zaman düğmeye basabildiysek True, basamadıysak False değerini döndürecek.

Bundan sonra istediğiniz düğmeyi kolayca yaratabilirsiniz. Hemen yapalım iki tane:


düğme1 = düğme((255, 255, 255), (120, 40), (çözünürlük[0] / 2 - 60, 100), "Yeni Oyun", (255, 0, 0), "başla")
düğme2 = düğme((255, 255, 255), (90, 40), (çözünürlük[0] / 2 - 45, 145), "Çıkış", (255, 0, 0), "çık")



Arkaplan renkleri beyaz, yazıları kırmızı olan, "Yeni Oyun" ve "Çıkış" diye iki tane düğme yarattık. Şimdi bunları ekrana çizdirelim. Bunu yapmadan önce bir şeyi daha hesaba katmalıyız, ileride bunlar gibi birçok düğme yaratmak isteyebiliriz. O halde hepsini daha kolay yönetebilmek için düğmeler_listesi diye bir liste yaratalım. Bu liste yardımı ile istediğimiz kadar düğmeyi ekrana tek bir fonksiyon ile çizdirebiliriz.

En son ilk while döngümüzün içine (devam şartına bağlı olan döngü) yeni bir while döngüsü koyalım (menü şartına bağlı olan döngü).


düğmeler_listesi = [düğme1, düğme2]

menü = True

while devam:
    while menü:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONDOWN:
                for i in düğmeler_listesi:
                    if i.bas():
                        if i.işlev == "başla":
                            menü = False
                        if i.işlev == "çık":
                            menü = False
                            devam = False
         
                 
        pencere.fill((0, 0, 0)) #menünün arkaplanı siyah olacak
        for i in düğmeler_listesi: #bütün düğmeleri üç satır kod ile çizdirmemize yarayan fonksiyon
            pygame.draw.rect(pencere, i.renk, i.kare) #düğmenin arkaplanı olan kareyi çizdiriyoruz
            pencere.blit(i.yazı, i.yazı_koordinat) #düğmenin üstündeki yazıyı yazdırıyoruz
        pygame.display.update()
        time.sleep(0.0025)



Satırları tek tek açıklayayım. for event ile başlayan sonraki satırlar zaten tanıdık, sadece pygame.MOUSEBUTTONDOWN kısmı farklı ki bu fonksiyon pygame.KEYDOWN'un mouse'a uyarlanmış hali. Mouse'ta bir tuşa basarsan anlamı taşıyor. Sonra yaptığımız listenin faydalarını göremeye başlıyoruz. Düğme sayısı ne olursa olsun hepsini tek bir for döngüsü ile kontrol edebiliyoruz (önemli not: for döngüsünü daha önce anlatmamış olduğumu fark ettim, ilk derse if elif else'ten sonrasına ekledim). Eğer mouse'un herhangi bir düğmesine basarsak, for döngüsü, düğmeler_listesi'ndeki her bir düğmeyi "acaba hangisine basıldı" diye kontrol edecek. Eğer gerçekten bir düğmeye basmışsak  ve bas() fonksiyonu True değerini döndürmüşse o zaman oyunumuz tam olarak hangi düğmeye bastığımızı if ile kontrol etmeye başlayacak. Burada işlev değişkenini kullanmak yerine düğmenin üstünde ne yazdığına bakarak da aynı işi yapabilirdik.

Oyun içindeyken menüye girmek istersek daha önce yazdığımız, "for event in pygame ..." kısmına yeni bir tuş ekleyerek bunu yapabilirsiniz.

Şimdiye kadar yazdığınız kod, oyunu ilk açtığınızda karşınıza menü ekranını getirecek ve eğer Yeni Oyun düğmesine basarsanız yeni oyun başlayacaktır. Buna benzer bir kod yazmış olmanız lazım:



import pygame, time, random

pygame.init()

#### DEĞİŞKENLER ####

çözünürlük = (800, 600)
devam = menü = True #menü değişkenini burada tanımladım
son_düşman_ekleme = pygame.time.get_ticks()

pencere = pygame.display.set_mode(çözünürlük)

bizim_font = pygame.font.SysFont("arial", 30)


#### CLASSLAR ####

class oyuncu():
    def __init__(self, boyut, resim):
        self.skor = 0
        self.can = 10
        self.boyut = boyut
        self.resim = pygame.image.load(resim)
        self.kare = pygame.Rect((350, çözünürlük[1] - self.boyut[1]), self.boyut)
        self.sağa = False
        self.sola = False
    def hareket(self, yön):
        if yön == "sağa":
            self.sağa = True
        elif yön == "sola":
            self.sola = True
    def hareket_iptal(self, yön):
        if yön == "sağa":
            self.sağa = False
        elif yön == "sola":
            self.sola = False


class düğme():
    def __init__(self, renk, boyut, koordinat, metin, yazının_rengi, işlevi):
        self.işlev = işlevi
        self.renk = renk
        self.boyut = boyut
        self.koordinat = koordinat
        self.yazı = bizim_font.render(metin, True, yazının_rengi)
        self.yazı_koordinat = (koordinat[0] + 3, koordinat[1] + 3)
        self.kare = pygame.Rect(self.koordinat, self.boyut)
    def bas(self):
        (x, y) = pygame.mouse.get_pos()
        if self.kare.collidepoint((x, y)):
            return True
        else:
            return False


class mermi():
    global çözünürlük
    def __init__(self, oyuncu):
        self.kare = pygame.Rect((oyuncu.kare.left + oyuncu.boyut[0] / 2, çözünürlük[1] - oyuncu.boyut[1]), (2,
                                                                                                            3))



class düşman():
    def __init__(self):
        pos_x = random.randint(0, çözünürlük[0] - 50)
        self.kare = pygame.Rect((pos_x, -50), (50, 50))


#### FONKSİYONLAR ####


def hareketler():
    global oyuncu1, çözünürlük, mermi_listesi
    if oyuncu1.sağa and oyuncu1.kare.right < çözünürlük[0]:
        oyuncu1.kare.left += 1
    if oyuncu1.sola and oyuncu1.kare.left > 0:
        oyuncu1.kare.left -= 1

    for i in mermi_listesi:
        i.kare.top -= 3
        if i.kare.bottom < 0:
            mermi_listesi.remove(i)

    for i in düşman_listesi:
        i.kare.bottom += 1
        if i.kare.top > çözünürlük[1]:
            düşman_listesi.remove(i)
            oyuncu1.can -= 1


def düşman_ekle():
    global son_düşman_ekleme
    if pygame.time.get_ticks() - son_düşman_ekleme > 3000:
        son_düşman_ekleme = pygame.time.get_ticks()
        düşman_listesi.append(düşman())


def çarpışma():
    global oyuncu1, düşman_listesi, mermi_listesi
    for i in düşman_listesi:
        for k in mermi_listesi:
            if i.kare.colliderect(k.kare):
                düşman_listesi.remove(i)
                mermi_listesi.remove(k)
                oyuncu1.skor += 1
        if i.kare.colliderect(oyuncu1.kare):
            düşman_listesi.remove(i)
            oyuncu1.can -= 1

oyuncu1 = oyuncu((50, 50), "uzay_gemisi.gif")
#düğmeleri yaratıyoruz:
düğme1 = düğme((255, 255, 255), (120, 40), (çözünürlük[0] / 2 - 60, 100), "Yeni Oyun", (255, 0, 0), "başla")
düğme2 = düğme((255, 255, 255), (90, 40), (çözünürlük[0] / 2 - 45, 145), "Çıkış", (255, 0, 0), "çık")

#### LİSTELER ####


mermi_listesi = []
düşman_listesi = []
düğmeler_listesi = [düğme1, düğme2] #düğmeler listesini yaratıp içine düğme1 ve düğme2'yi ekledik


while devam:
    while menü:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONDOWN:
                for i in düğmeler_listesi:
                    if i.bas():
                        if i.işlev == "başla":
                            menü = False
                        if i.işlev == "çık":
                            menü = False
                            devam = False
         
                 
        pencere.fill((0, 0, 0)) #menünün arkaplanı siyah olacak
        for i in düğmeler_listesi: #bütün düğmeleri üç satır kod ile çizdirmemize yarayan fonksiyon
            pygame.draw.rect(pencere, i.renk, i.kare) #düğmenin arkaplanı olan kareyi çizdiriyoruz
            pencere.blit(i.yazı, i.yazı_koordinat) #düğmenin üstündeki yazıyı yazdırıyoruz
        pygame.display.update()
        time.sleep(0.0025)

     



     
    if oyuncu1.can == 0:
        devam = False
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            devam = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket("sağa")
            if event.key == pygame.K_SPACE:
                mermi_listesi.append(mermi(oyuncu1))
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket_iptal("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket_iptal("sağa")


    hareketler()

    düşman_ekle()
    çarpışma()



    pencere.fill((0, 0, 0))
    pencere.blit(oyuncu1.resim, oyuncu1.kare)

    for i in mermi_listesi:
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)

    for i in düşman_listesi:
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)
    can_yazı = bizim_font.render(str(oyuncu1.can), True, (0, 255, 0))
    skor_yazı = bizim_font.render(str(oyuncu1.skor), True, (255, 0, 0))


    pencere.blit(can_yazı, (5, 5))
    pencere.blit(skor_yazı, (5, 35))

    pygame.display.update()
    time.sleep(0.0025)

pygame.quit()



Menü yazılarının arkaplanlarını düzgün ayarladıktan sonra komple kaldırabilirsiniz. O karelerin tek işlevleri yazılara tıklayıp tıklamadığınızı kontrol etmek. pygame.draw.rect(pencere, i.renk, i.kare) satırını silerseniz o çirkin kareler kaybolacaklardır.

En son oyuna ses eklemek kaldı. Bu işlemi de resim eklemeye benzer bir şekilde yapıyoruz: pygame.mixer.Sound("ses.wav") komutu ile kullanacağımız sesi kullanıyoruz (ses.wav örnek bir isim, aynı resmi tanımlarken pygame.image.load("resim.jpg")'deki resim.jpg gibi). Hemen ates.wav dosyasını çalalım mesela:

ates_sesi = pygame.mixer.Sound("ates.wav")
ates_sesi.play()


Evet, her şey bu kadar basit. ates_sesi'ni resimleri tanımladığımız yerde tanımlayalım, mermiyi oluştururken de çalalım, yani ates_sesi.play()'i mermi sınıfının içine bir yere yazalım:


class mermi():
    global çözünürlük
    def __init__(self, oyuncu):
        self.kare = pygame.Rect((oyuncu.kare.left + oyuncu.boyut[0] / 2, çözünürlük[1] - oyuncu.boyut[1]), (2,3))
         ates_sesi.play()



Bu derste anlatmak istediklerim de bu kadar. Ses ile ne yapabileceğinizi daha ayrıntılı bir şekilde öğrenmek için müzik ve mixer dokumentasyonlarına bakabilirsiniz. Bir sonraki derste görüşmek üzere.

20 Haziran 2012 Çarşamba

Pygame (3)

Merhaba arkadaşlar! Okul, sınavlar falan derken uzun zamandır yazı yazmadım. Hazır finaller de bitmiş şimdi tam zamanı dedim. En son derste NES'ten bildiğimiz Star Force benzeri bir oyunun taslağını yapmıştık, bu derste de resim ve yazı ekleyeceğiz. İşe yazı ile başlayalım. Önce kullanacağımız fontu tanıtmamız lazım, bunu pencereyi tanımladığımız satırın altında bir yerlerde şu şekilde yapıyoruz:

bizim_font = pygame.font.SysFont("arial", 30)

Bu komut sistemin mevcut fontlarına bakacak, içlerinden arial isimli fontu bulacak ve istediğimiz zaman 30 piksel büyüklüğünde yazdıracak. Yazdırma işlemi iki adımda olacak:


yazı_yaz = bizim_font.render("Trololo", True, (0, 255, 0))
pencere.blit(yazı_yaz, (0, 0))


İlk satırda ne yazacağımızı ve hangi renkle yazacağımızı belirledik, ikinci satırda "blit" fonksiyonunu kullanarak yazıları ekrana çizdirdik (resimleri de hemen hemen aynı şekilde çizdireceğiz). Oyuna skor ve can göstergelerini eklemek için gereken her şeyi biliyoruz. Daha önce can sayacını oyuncu sınıfını içine eklemiştik, şimdi aynı şekilde skor sayacını da ekleyelim.


class oyuncu():
    def __init__(self, renk, boyut):
        self.skor = 0 #skor sayacını buraya ekledik
        self.can = 10
        self.boyut = boyut
        self.kare = pygame.Rect((350, çözünürlük[1] - self.boyut[1]), self.boyut)
        self.renk = renk
        self.sağa = False
        self.sola = False
    def hareket(self, yön):
        if yön == "sağa":
            self.sağa = True
        elif yön == "sola":
            self.sola = True
    def hareket_iptal(self, yön):
        if yön == "sağa":
            self.sağa = False
        elif yön == "sola":
            self.sola = False


Şimdi de skoru arttırması için çarpışma fonksiyonunda düzeltmeler yapalım:


def çarpışma():
    global oyuncu1, düşman_listesi, mermi_listesi
    for i in düşman_listesi:
        for k in mermi_listesi:
            if i.kare.colliderect(k.kare):
                düşman_listesi.remove(i)
                mermi_listesi.remove(k)
                oyuncu1.skor += 1 #skoru arttır
        if i.kare.colliderect(oyuncu1.kare):
            düşman_listesi.remove(i)
            oyuncu1.can -= 1


Canın azalmasını zaten önceden yapmıştık. Fontumuzu daha önce gösterdiğim şekilde tanımladıktan sonra pygame.display.update() fonksiyonundan hemen önce yazılarımızı yazdıralım:


#skoru ve canı yazıya çevirme
    can_yazı = bizim_font.render(str(oyuncu1.can), True, (0, 255, 0))
    skor_yazı = bizim_font.render(str(oyuncu1.skor), True, (255, 0, 0))


# Yazı yazdırma:
    pencere.blit(can_yazı, (5, 5))
    pencere.blit(skor_yazı, (5, 35))

    pygame.display.update()


Gördüğünüz gibi oyuncu1.can'ı ve oyuncu1.skor'u önce "string" tipine çevirdim çünkü render fonksiyonu sayılarla değil, sadece karakterlerle çalışıyor. Daha sonra da can_yazı'yı ve skor_yazı'yı 5, 5 ve 5, 35 koordinatlarına çizdirdim. İsterseniz bir de "while devam:" satırının hemen altına


if oyuncu1.can == 0:
        devam = False


ekleyin ki canınız bittiğinde oyun da bitsin. Bu şekilde oyunu açarsanız sol üst köşede yeşil can ve kırmızı skor göstergelerini göreceksiniz. Ayrıca print(oyuncu1.can) satırlarını da silebilirsiniz, onlarla işimiz kalmadı.

Şimdi gelelim resim eklemeye. Aynı yazıda olduğu gibi resmi çizdirmeden önce onu tanımlamalıyız, bunu pygame.image.load("resmin_adı") fonksiyonu ile yapıyoruz. Resmin adını yazarken uzantısını da unutmamaya dikkat edin. Eğer resim .py uzantılı dosyanın olduğu klasörde değil de bir alt klasördeyse adresi olduğu gibi yazabilirsiniz. Örnek vereyim, oyunum klasörünün içinde oyun.py dosyası ve resimler diye bir klasör varsa ve uzay_gemizi.jpg resmi resim klasörünün içindeyse kodunuz şu şekilde olmalı: pygame.image.load("resimler/uzay_gemisi.jpg")

Ekrana çizdirme işini yine blit ile yapıyoruz. Hemen bir örnek yazayım:

benim_resmim = pygame.image.load("resim.gif")
pencere.blit(benim_resmim, (15, 15))


Tabi ki bunları pencereyi tanımladıktan sonra yazmalısınız. Hemen oyuncu sınıfına resim tanımlama işini verelim o halde:


class oyuncu():
    def __init__(self, renk, boyut, resim):
        self.skor = 0
        self.can = 10
        self.boyut = boyut
        self.resim = pygame.image.load(resim) #resmi burada tanımladık.
        self.kare = pygame.Rect((350, çözünürlük[1] - self.boyut[1]), self.boyut)
        self.renk = renk
        self.sağa = False
        self.sola = False
    def hareket(self, yön):
        if yön == "sağa":
            self.sağa = True
        elif yön == "sola":
            self.sola = True
    def hareket_iptal(self, yön):
        if yön == "sağa":
            self.sağa = False
        elif yön == "sola":
            self.sola = False



oyuncu1 = oyuncu((255, 0, 0), (50, 50), "uzay_gemisi.gif") #resmi de ekledik

Artık oyuncu yaratırken renk ve boyutun yanında bir de resim adresi vereceğiz. Resmi pencereye çizdirmek için de

pygame.draw.rect(pencere, oyuncu1.renk, oyuncu1.kare)


satırını

pencere.blit(oyuncu1.resim, oyuncu1.kare)


ile değiştirmemiz yeterli olacaktır. Artık oyuncu karesinin rengi ile ilgilenmediğimize göre o oyuncu sınıfının içindeki self.renk satırını ve onunla ilgili her şeyi silebiliriz. Kodunuzun son hali böyle bir şey olmalı:


import pygame, time, random

pygame.init()

#### DEĞİŞKENLER ####

çözünürlük = (800, 600)
devam = True
son_düşman_ekleme = pygame.time.get_ticks()

pencere = pygame.display.set_mode(çözünürlük)

bizim_font = pygame.font.SysFont("arial", 30) #Fontu yarattık


#### CLASSLAR ####

class oyuncu():
    def __init__(self, boyut, resim): #renk argümanını ve self.renk değişkenini sildik
        self.skor = 0
        self.can = 10
        self.boyut = boyut
        self.resim = pygame.image.load(resim)
        self.kare = pygame.Rect((350, çözünürlük[1] - self.boyut[1]), self.boyut)
        self.sağa = False
        self.sola = False
    def hareket(self, yön):
        if yön == "sağa":
            self.sağa = True
        elif yön == "sola":
            self.sola = True
    def hareket_iptal(self, yön):
        if yön == "sağa":
            self.sağa = False
        elif yön == "sola":
            self.sola = False



class mermi():
    global çözünürlük
    def __init__(self, oyuncu):
        self.kare = pygame.Rect((oyuncu.kare.left + oyuncu.boyut[0] / 2, çözünürlük[1] - oyuncu.boyut[1]), (2,
                                                                                                            3))



class düşman():
    def __init__(self):
        pos_x = random.randint(0, çözünürlük[0] - 50)
        self.kare = pygame.Rect((pos_x, -50), (50, 50))


#### FONKSİYONLAR ####


def hareketler():
    global oyuncu1, çözünürlük, mermi_listesi
    if oyuncu1.sağa and oyuncu1.kare.right < çözünürlük[0]:
        oyuncu1.kare.left += 1
    if oyuncu1.sola and oyuncu1.kare.left > 0:
        oyuncu1.kare.left -= 1

    for i in mermi_listesi:
        i.kare.top -= 3
        if i.kare.bottom < 0:
            mermi_listesi.remove(i)

    for i in düşman_listesi:
        i.kare.bottom += 1
        if i.kare.top > çözünürlük[1]:
            düşman_listesi.remove(i)
            oyuncu1.can -= 1


def düşman_ekle():
    global son_düşman_ekleme
    if pygame.time.get_ticks() - son_düşman_ekleme > 3000:
        son_düşman_ekleme = pygame.time.get_ticks()
        düşman_listesi.append(düşman())


def çarpışma():
    global oyuncu1, düşman_listesi, mermi_listesi
    for i in düşman_listesi:
        for k in mermi_listesi:
            if i.kare.colliderect(k.kare):
                düşman_listesi.remove(i)
                mermi_listesi.remove(k)
                oyuncu1.skor += 1 #skoru arttır
        if i.kare.colliderect(oyuncu1.kare):
            düşman_listesi.remove(i)
            oyuncu1.can -= 1

oyuncu1 = oyuncu((50, 50), "uzay_gemisi.gif") #resmi ekledik ve renk değişkenini kaldırdık

#### LİSTELER ####


mermi_listesi = []
düşman_listesi = []


while devam:
    if oyuncu1.can == 0: #Can sıfırlandığında oyun bitsin
        devam = False
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            devam = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket("sağa")

            if event.key == pygame.K_SPACE:
                mermi_listesi.append(mermi(oyuncu1))

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket_iptal("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket_iptal("sağa")


    hareketler()

    düşman_ekle()
    çarpışma()



    pencere.fill((0, 0, 0))
    #pygame.draw.rect(pencere, oyuncu1.renk, oyuncu1.kare)
    pencere.blit(oyuncu1.resim, oyuncu1.kare)

    for i in mermi_listesi:
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)

    for i in düşman_listesi:
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)
    #skoru ve canı yazıya çevirme
    can_yazı = bizim_font.render(str(oyuncu1.can), True, (0, 255, 0))
    skor_yazı = bizim_font.render(str(oyuncu1.skor), True, (255, 0, 0))


    # Yazı yazdırma:
    pencere.blit(can_yazı, (5, 5))
    pencere.blit(skor_yazı, (5, 35))

    pygame.display.update()
    time.sleep(0.0025)

pygame.quit()


Evet, bir dersin daha sonuna geldik arkadaşlar. Bir sonraki derste menü yapmanın pratik yollarını ve ses eklemeyi öğreteceğim. Kendinize çok iyi bakın.

6 Mart 2012 Salı

Pygame (2)

Bu derse başlamadan önce söylemek istediğim bir şey var. Hevesinizi kaçırmak istemem ama ben de daha geçen gün öğrendim ki pygame mario gibi side - scroll oyunları yapmak için hiç uygun değilmiş. Sebebi de blit ve pygame.display.update() fonksiyonları. Arka planı blit ile çizdirip update ile güncellemek çok fazla zaman alıyor ve oyun çok fazla yavaşlıyor. Mario gibi oyunlarda da arka plan normalden çok daha büyük oluyor ve güncellemesi daha da uzun sürüyor. Bu yüzden bugünkü uçak oyununa bir arka plan koymayacağım. Siz isterseniz deneyin, ne kadar yavaşladığını görürsünüz.

Kod yazmaya başlamadan önce dokümentasyon yapalım. Yazacağımız oyunda düşmanlar yukarıdan, rastgele bir yerden düz bir şekilde inecek. Yani bir düşman class'ına ihtiyacımız var. Tabi ki bir oyuncu da olacak, oyuncu sağa sola hareket edip ateş edebilecek. O halde bir oyuncu ve mermi class'ı yaratalım, ya da ikisini bir class'ın içinde de yazabiliriz. while döngüsünün içinde objeleri çizdirmenin dışında üç şey yapacağız; her objenin hareketini hesaplama (yeni pozisyonunu hesaplama), objelerin çarpışması ve yeni düşman ekleme. Düşman bir mermiye çarptığı zaman hem mermi hem düşman silinecek, düşman oyuncuya çarptığı ya da ekranın altına geldiği zaman oyuncunun canı gidecek.

Şimdilik bu kadar yeter. Kodumuza başlayabiliriz. (Not: kodu yazarken bazı yerlerde bir satıra sığmadığı için yeni bir satıra geçilmiş. Ona kafanızı takmayın. Kodu incelerseniz görürsünüz zaten. Bir de kopyalayıp yapıştırırsanız kod çalışacaktır)

import pygame, time, random

pygame.init()

#### DEĞİŞKENLER ####

çözünürlük = (800, 600)
devam = True

pencere = pygame.display.set_mode(çözünürlük)


#### CLASSLAR ####

class oyuncu():
    def __init__(self, renk, boyut):
        self.can = 10
        self.boyut = boyut
        self.kare = pygame.Rect((350, çözünürlük[1] - self.boyut[1]), self.boyut) #çözünürlük[1]'in ne demek
                                                                                                                      #olduğunu birazdan açıklarım.
        self.renk = renk
        self.sağa = False
        self.sola = False
    def hareket(self, yön):
        if yön == "sağa":
            self.sağa = True
        elif yön == "sola":
            self.sola = True
    def hareket_iptal(self, yön):
        if yön == "sağa":
            self.sağa = False
        elif yön == "sola":
            self.sola = False

#### FONKSİYONLAR ####


def hareketler():
    global oyuncu1, çözünürlük, mermi_listesi
    if oyuncu1.sağa and oyuncu1.kare.right < çözünürlük[0]:
        oyuncu1.kare.left += 1
    if oyuncu1.sola and oyuncu1.kare.left > 0:
        oyuncu1.kare.left -= 1

oyuncu1 = oyuncu((255, 0, 0), (50, 50))


while devam:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            devam = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket("sağa")

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket_iptal("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket_iptal("sağa")


    hareketler()

    pencere.fill((0, 0, 0))
    pygame.draw.rect(pencere, oyuncu1.renk, oyuncu1.kare)
    pygame.display.update()
    time.sleep(0.0025)

pygame.quit()



Bu kodu yazdığınızda kırmızı renk, 50x50, oyuncu1 adında bir kare çizilecek ve kareyi sağa sola hareket ettirebileceğiz. Bu parametreleri değiştirmek isterseniz oyuncu1 = oyuncu((255, 0, 0), (50, 50)) yerine başka bir şeyler de yazabilirsiniz. Şimdi çözünürlük[1] ve boyut[1] derken ne demek istediğimi anlatayım. Hatırlarsanız listelerde her öğenin bir numarası vardı, listenin ilk elemanın numarası (ya da sırası) 0'idi, ikincinin 1'idi. her ne kadar (800, 600) bir liste olmasa da (tam olarak tupple oluyor bu. Türkçesi demeç, istihza.com'dan bakmanızı öneririm) çok benzer bir yapıdır. çözünürlük[1] dediğimde çözünürlük'ün ikinci elemanına, yani ekranımızın yüksekliğine ulaşmış oluyorum.

Şimdi de ateş etmeyi ekleyelim. Bunun için mermi diye bir class yaratacağım, mermileri mermi_listesi diye bir listede tutacağım ve bu listedeki her elemanın pozisyonunu hareketler() fonksiyonunda hesaplayacağım son olarak da ekrana çizdireceğim.



import pygame, time, random

pygame.init()

#### DEĞİŞKENLER ####

çözünürlük = (800, 600)
devam = True

pencere = pygame.display.set_mode(çözünürlük)


#### CLASSLAR ####

class oyuncu():
    def __init__(self, renk, boyut):
        self.can = 10
        self.boyut = boyut
        self.kare = pygame.Rect((350, çözünürlük[1] - self.boyut[1]), self.boyut)
        self.renk = renk
        self.sağa = False
        self.sola = False
    def hareket(self, yön):
        if yön == "sağa":
            self.sağa = True
        elif yön == "sola":
            self.sola = True
    def hareket_iptal(self, yön):
        if yön == "sağa":
            self.sağa = False
        elif yön == "sola":
            self.sola = False



class mermi(): #mermi diye bir class oluşturduk
    global çözünürlük
    def __init__(self, oyuncu):
        self.kare = pygame.Rect((oyuncu.kare.left + oyuncu.boyut[0] / 2, çözünürlük[1] - oyuncu.boyut[1]), (2,
                                                                                                            3))



#### FONKSİYONLAR ####


def hareketler():
    global oyuncu1, çözünürlük, mermi_listesi
    if oyuncu1.sağa and oyuncu1.kare.right < çözünürlük[0]:
        oyuncu1.kare.left += 1
    if oyuncu1.sola and oyuncu1.kare.left > 0:
        oyuncu1.kare.left -= 1

    for i in mermi_listesi: #mermi listesi'ndeki her elemanı üç piksel yukarıya alıyoruz
        i.kare.top -= 3
        if i.kare.bottom < 0:
            mermi_listesi.remove(i) #mermi ekran dışına çıkarsa siliyoruz


oyuncu1 = oyuncu((255, 0, 0), (50, 50))

#### LİSTELER ####


mermi_listesi = [] #mermilerle daha kolay işlem yapabilmek için bir liste oluşturuyoruz


while devam:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            devam = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket("sağa")

            if event.key == pygame.K_SPACE: #space'e basınca bir mermi objesi yaratıyoruz
                mermi_listesi.append(mermi(oyuncu1)) #ve mermi_listesi'ne eklyoruz

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket_iptal("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket_iptal("sağa")


    hareketler()

    pencere.fill((0, 0, 0))
    pygame.draw.rect(pencere, oyuncu1.renk, oyuncu1.kare)

    for i in mermi_listesi: #mermi_listesi'ndeki her elemanı çizidiyoruz
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)
    pygame.display.update()
    time.sleep(0.0025)

pygame.quit()


Burada açıklanacak bir şey yok.

Şimdi de aynı şekilde düşman ekleyelim. Tek fark düşmanın her 3 saniyede bir kendiliğinden oluşacak olması. Bunun için pygame.time.get_ticks() fonksiyonundan faydalanacağız. Bu fonksiyon oyun başladığından beri kaç milisaniye geçmiş onu söyleyecek.


import pygame, time, random

pygame.init()

#### DEĞİŞKENLER ####

çözünürlük = (800, 600)
devam = True
son_düşman_ekleme = pygame.time.get_ticks() #Bununla son düşmanı en son ne zaman eklendiğine
                                                                         #bakacağız

pencere = pygame.display.set_mode(çözünürlük)


#### CLASSLAR ####

class oyuncu():
    def __init__(self, renk, boyut):
        self.can = 10
        self.boyut = boyut
        self.kare = pygame.Rect((350, çözünürlük[1] - self.boyut[1]), self.boyut)
        self.renk = renk
        self.sağa = False
        self.sola = False
    def hareket(self, yön):
        if yön == "sağa":
            self.sağa = True
        elif yön == "sola":
            self.sola = True
    def hareket_iptal(self, yön):
        if yön == "sağa":
            self.sağa = False
        elif yön == "sola":
            self.sola = False



class mermi():
    global çözünürlük
    def __init__(self, oyuncu):
        self.kare = pygame.Rect((oyuncu.kare.left + oyuncu.boyut[0] / 2, çözünürlük[1] - oyuncu.boyut[1]), (2,
                                                                                                            3))



class düşman(): #düşman class'ı
    def __init__(self):
        pos_x = random.randint(0, çözünürlük[0] - 50) #x pozisyonu rastgele belirlenecek
        self.kare = pygame.Rect((pos_x, -50), (50, 50))


#### FONKSİYONLAR ####


def hareketler():
    global oyuncu1, çözünürlük, mermi_listesi
    if oyuncu1.sağa and oyuncu1.kare.right < çözünürlük[0]:
        oyuncu1.kare.left += 1
    if oyuncu1.sola and oyuncu1.kare.left > 0:
        oyuncu1.kare.left -= 1

    for i in mermi_listesi:
        i.kare.top -= 3
        if i.kare.bottom < 0:
            mermi_listesi.remove(i)

    for i in düşman_listesi: #düşman_listesi'ndeki her öğenin hareketini hesaplıyoruz
        i.kare.bottom += 1
        if i.kare.top > çözünürlük[1]:
            düşman_listesi.remove(i) #düşman_listesi'ndeki bir öğe ekran dışına çıkarsa siliyoruz


def düşman_ekle(): #düşman ekleme fonksiyonu
    global son_düşman_ekleme
    if pygame.time.get_ticks() - son_düşman_ekleme > 3000: #düşman üç saniyede bir gelsin diyoruz
        son_düşman_ekleme = pygame.time.get_ticks()
        düşman_listesi.append(düşman())




oyuncu1 = oyuncu((255, 0, 0), (50, 50))

#### LİSTELER ####


mermi_listesi = []
düşman_listesi = [] #düşmanları daha kolay kontrol edebilmek için liste oluşturduk


while devam:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            devam = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket("sağa")

            if event.key == pygame.K_SPACE: #space'e basınca bir mermi objesi yaratıyoruz
                mermi_listesi.append(mermi(oyuncu1))

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket_iptal("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket_iptal("sağa")


    hareketler()

    düşman_ekle() #düşman eklenmesinin gerekli olup olmadığını kontrol ediyoruz



    pencere.fill((0, 0, 0))
    pygame.draw.rect(pencere, oyuncu1.renk, oyuncu1.kare)

    for i in mermi_listesi:
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)

    for i in düşman_listesi: #düşman_listesi'ndeki her bir objeyi ekrana çizdiriyoruz.
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)

    pygame.display.update()
    time.sleep(0.0025)

pygame.quit()


Burada da yeni bir şey yok. Şimdi objelerin çarpışıp çarpışmadığına bakacağız. Bunun için çarpışmalar() diye bir fonksiyon yazacağız.


import pygame, time, random

pygame.init()

#### DEĞİŞKENLER ####

çözünürlük = (800, 600)
devam = True
son_düşman_ekleme = pygame.time.get_ticks()

pencere = pygame.display.set_mode(çözünürlük)


#### CLASSLAR ####

class oyuncu():
    def __init__(self, renk, boyut):
        self.can = 10
        self.boyut = boyut
        self.kare = pygame.Rect((350, çözünürlük[1] - self.boyut[1]), self.boyut)
        self.renk = renk
        self.sağa = False
        self.sola = False
    def hareket(self, yön):
        if yön == "sağa":
            self.sağa = True
        elif yön == "sola":
            self.sola = True
    def hareket_iptal(self, yön):
        if yön == "sağa":
            self.sağa = False
        elif yön == "sola":
            self.sola = False



class mermi():
    global çözünürlük
    def __init__(self, oyuncu):
        self.kare = pygame.Rect((oyuncu.kare.left + oyuncu.boyut[0] / 2, çözünürlük[1] - oyuncu.boyut[1]), (2,
                                                                                                            3))



class düşman():
    def __init__(self):
        pos_x = random.randint(0, çözünürlük[0] - 50)
        self.kare = pygame.Rect((pos_x, -50), (50, 50))


#### FONKSİYONLAR ####


def hareketler():
    global oyuncu1, çözünürlük, mermi_listesi
    if oyuncu1.sağa and oyuncu1.kare.right < çözünürlük[0]:
        oyuncu1.kare.left += 1
    if oyuncu1.sola and oyuncu1.kare.left > 0:
        oyuncu1.kare.left -= 1

    for i in mermi_listesi:
        i.kare.top -= 3
        if i.kare.bottom < 0:
            mermi_listesi.remove(i)

    for i in düşman_listesi:
        i.kare.bottom += 1
        if i.kare.top > çözünürlük[1]:
            düşman_listesi.remove(i)
            oyuncu1.can -= 1 #düşman ekran dışına çıkarsa oyuncunun bir canı gider
            print(oyuncu1.can)


def düşman_ekle():
    global son_düşman_ekleme
    if pygame.time.get_ticks() - son_düşman_ekleme > 3000:
        son_düşman_ekleme = pygame.time.get_ticks()
        düşman_listesi.append(düşman())


def çarpışma(): #çarpışma fonksiyonunu yazdık
    global oyuncu1, düşman_listesi, mermi_listesi
    for i in düşman_listesi:
        for k in mermi_listesi:
            if i.kare.colliderect(k.kare):
                düşman_listesi.remove(i)
                mermi_listesi.remove(k)
        if i.kare.colliderect(oyuncu1.kare):
            düşman_listesi.remove(i)
            oyuncu1.can -= 1
            print(oyuncu1.can)





oyuncu1 = oyuncu((255, 0, 0), (50, 50))

#### LİSTELER ####


mermi_listesi = []
düşman_listesi = [] #düşmanları daha kolay kontrol edebilmek için liste oluşturduk


while devam:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            devam = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket("sağa")

            if event.key == pygame.K_SPACE:
                mermi_listesi.append(mermi(oyuncu1))

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                oyuncu1.hareket_iptal("sola")
            if event.key == pygame.K_RIGHT:
                oyuncu1.hareket_iptal("sağa")


    hareketler()

    düşman_ekle()
    çarpışma() #çarpışma fonksiyonunu çağırıyoruz



    pencere.fill((0, 0, 0))
    pygame.draw.rect(pencere, oyuncu1.renk, oyuncu1.kare)

    for i in mermi_listesi:
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)

    for i in düşman_listesi:
        pygame.draw.rect(pencere, (255, 255, 255), i.kare)

    pygame.display.update()
    time.sleep(0.0025)

pygame.quit()

Son olarak da çarpışma() fonksiyonunu ekledik. Biraz incelerseniz nasıl çalıştığını anlarsınız.

Pygame'in temeli yaklaşık olarak bu kadar. Bir sonraki derste oyunu biraz daha geliştirip resim, ses falan ekleriz.

20 Şubat 2012 Pazartesi

Pygame (1)

Bir önceki derste de söylediğim gibi bu derste görsel bir şeyler yapmaya başlayacağız. Bunun için pygame kütüphanesini kullanacağız.

Nedir bu Pygame?
Pygame bir grafik kütüphanesidir. Sakın bunu grafik motoru ile karıştırmayın, aynı şey değil. Pygame de Python gibi ücretsiz, açık kaynak kodlu bir yazılımdır. Temelde yaptığı şey kare, çizgi, yuvarlak gibi basit şekilleri çizmek. Sakın bunu azımsamayın! Pek çoğunuzun ismini sık sık duyduğu Metin 2 adlı mmorpg'nin grafikleri pygame ile yapıldı. Gerçi pygame ile üç boyutlu bir oyun yapmak  biraz abartıya kaçıyor ama siz de hemen hemen her türlü iki boyutlu oyunu rahatlıkla yapabilirsiniz. Daha fazla örnek isterseniz www.pygame.org sitesini inceleyebilirsiniz.

Kurulum
Sitede downloads'a tıklarsanız bir çok pygame sürümü olduğunu göreceksiniz. Siz Python versiyonunuza uygun olanını indirin. Yalnız dikkat edin, 64 bit pygame sürümleri sadece Python 2.7 için mevcut. Eğer bilgisayarınızda Python 3.xx 64 bit kurulu ise onu kaldırıp 32 bit yüklemeniz gerekecek. Doğru sürümü indirdikten sonra kurulum sırasında Python'un kurulu olduğu dosyayı göstermeniz lazım. Genelde otomatik olarak tespit ediliyor ama, onun için çok fazla uğraşmanıza gerek yok.

Her şeyi kurduysanız IDLE'ı açın ve import pygame yazıp enter'a basın. Eğer Python herhangi bir şey yazmazsa her şeyi doğru yapmışsınızdır. Yok eğer bir hata verirse demek ki bir yerde yanlışlık var.

İlk Adımlar
Buraya kadar geldiyseniz başlamaya hazırsınızdır. O halde hemen 800x600 bir ekran yapalım:

import pygame
pygame.init()
pencere = pygame.display.set_mode((800, 600))
pygame.display.update()

Bunları yazarsanız karşınıza siyah bir pencere çıkacak. Burada şunu yaptık: önce pygame modülünü çağırdık, sonra pygame.init() fonksiyonu ile her şeyi varsayılan değerlere ayarladık (bu fonksiyonun tam olarak ne yaptığını bilmiyorum ama mutlaka yazılması lazım). Sonra penceremizi tanımladık. Onu da önce pygame modülünden display adlı bir modülün set_mode() diye bir fonksiyonunu çağırarak. Adından da anlaşıldığı gibi bu fonksiyon ekran ayarını yapıyor. Dikkat ettiyseniz orada çift parantez kullandım. Sebebi basit, set_mode() fonksiyonu birden çok değer alıyor (çözünürlük, derinlik, pencere kenarlarının olup olmaması gibi şeyler, ayrıntılı bilgi için buraya bakabilirsiniz), geriye kalanlar yazılmadığı zaman pygame onları varsayılan olarak ayarlıyor. Eğer başka özellikleri ayarlamak isteseydik pygame.display.set_mode((800, 600), pygame.FULLSCREEN) gibi bir şeyler yazacaktık. Son olarak da update() fonksiyonu var. Aslında update() fonksiyonu argüman olarak kare ya da kareler listesi alır ve her çağrıldığında sadece o kareleri yeniler (örnek: pygame.display.update(kare1, kare2, kare3), ama eğer herhangi bir argüman vermezsek sahnedeki bütün objeleri yeniler. Bu aşamada herhangi bir argüman vermemize gerek yok.

Bu programı çalıştırdığınızda bir sorun fark etmiş olabilirsiniz, sanki çıkan pencere donup da hata veriyormuş gibi. Aslında ortada bir hata yok, sadece pygame'e ekranı çizdikten sonra ne yapması gerektiğini söylemedik, o kadar. En sona pygame.quit() yazarsanız sorun kalmayacaktır. Pencere bir anda çıkıp kapanacak. Bunu engellemek için şimdilik daha önce yaptığımız gibi input() fonksiyonunu kullanabilirsiniz.

Şimdi penceremize biraz renk ekleyelim. Herhangi bir yüzeyi, renk ile doldurmak için yüzey_adı.fill((renk_kodu)) fonksiyonunu kullanacağız. Hemen bir örnek yapalım:


import pygame
pygame.init()
pencere = pygame.display.set_mode((800, 600))
pencere.fill((255, 255, 255))
pygame.display.update()
pygame.quit()

Gördüğünüz gibi penceremizin arka planı artık beyaz. Renk kodu olarak yazdığımız sayılar size bir şey ifade etmiyorsa hemen açıklayayım. RGB kısaltmasını hepiniz duymuşsunuzdur, Red Green Blue'dan gelir. İşte yazdığımız ilk sayı kırmızıya, ikinci sayı yeşile, üçüncüsü de maviye denk gelir. 0 - 255 arasında istediğiniz bir sayı yazabilirsiniz, sayı büyüdükçe renk miktarı da artar.

Şimdi de ekrana bir kare çizdirelim.

import pygame
pygame.init()
pencere = pygame.display.set_mode((800, 600))
kare = pygame.Rect((50, 50), (100, 100))
pencere.fill((255, 255, 255))
pygame.draw.rect(pencere, (0, 255, 0), kare)
pygame.display.update()
pygame.quit()

Önce pygame.Rect((sol_üst_köşenin_koodrinatları), (karenin_boyutları)) fonksiyonu ile bir kare tanımladık. Burada dikkat etmeniz gereken şey koordinat sisteminin sol üst köşeden başlaması. Yani (0, 0) noktası sol üst köşe, y koordinatı aşağıya gittikçe artar, x koordinatı ise sola gittikçe artar. pencere.fill()'dan sonra da pygame.draw.rect(yüzey, (karenin_rengi), karenin_kendisi) fonksiyonu ile de kareyi pencere adlı yüzeye çizdirdik. pygame.draw.rect()'in pencere.fill()'dan sonra olması öncemli, yoksa ekrana önce kare çizilirdi, sonra da bütün ekran beyaza boyanırdı ve biz kareyi görmezdik.

Şimdi gelelim asıl önemli konuya, kareyi nasıl hareket ettireceğiz? Bunun için bir döngü yaratmalıyız ki python kareyi sadece bir kere çizdirip programı sonlandırmasın. Demek ki bir adet while döngüsüne ihtiyacımız var.

import pygame, time
pygame.init()
pencere = pygame.display.set_mode((800, 600))
kare = pygame.Rect((50, 50), (100, 100))
devam = 1
while devam == 1:
    pencere.fill((255, 255, 255))
    kare.right += 1
    pygame.draw.rect(pencere, (0, 255, 0), kare)
    pygame.display.update()
    time.sleep(0.025)

Kareyi hareket ettirmek için karenin sağ kenarının koordinatını her döngüde bir piksel arttırdım. Bunu gördüğünüz gibi kare.right ile yaptım. Aynı şekilde kare.left'i de kullanabilirdim. Ya da aşağı - yukarı hareket ettirmek için kare.top ya da kare.bottom'ı da kullanabilirdim. Fark ettiyseniz bir de time modülünü import edip time.sleep() fonksiyonunu kullandım. Bunu yapmamdaki amaç her döngü sonunda bilgisayarın 0.025 saniye duraklaması. Yoksa bilgisayar hem programı çalıştırabildiği kadar hızlı çalıştırır ve muhtemelen biz kareyi görene kadar pencere dışına çıkar hem de her bilgisayarda program işlemciye bağlı olarak farklı hızlarda çalışır. Yetmiyormuş gibi işlemci de gücünün 100%'ünü sadece bunun için harcar.

Kare hareket ediyor, güzel ama şimdi de yeni bir sorun daha çıktı ortaya: pencere düzgün kapanmıyor. Hemen çaresine bakalım...

import pygame, time, sys
pygame.init()
pencere = pygame.display.set_mode((800, 600))
kare = pygame.Rect((50, 50), (100, 100))
devam = 1
while devam == 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    pencere.fill((255, 255, 255))
    kare.right += 5
    pygame.draw.rect(pencere, (0, 255, 0), kare)
    pygame.display.update()
    time.sleep(0.025)

Önce sys diye bir modül import ettim, döngüye girdikten sonra da
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
diye bir şey ekledim. Artık çarpıya bastığınızda pencere sorunsuz bir şekilde kapanacaktır. IDLE şöyle bir şey diyebilir:
Traceback (most recent call last):
  File "C:/Users/GameOver/Desktop/pencere.py", line 15, in <module>
    sys.exit()
SystemExit
aldırmayın, hata falan yok. Şimdilik de bu yazdıklarımı boş verin, ileride ne olduğunu zaten anlayacaksınız.

Biraz beklerseniz karenin ekranın dışına çıktığını fark edeceksiniz. Bunu hemen önleyelim. Kare ekranın sınırına geldiğinde öteki tarafa gitsin.


import pygame, time, sys
pygame.init()
pencere = pygame.display.set_mode((800, 600))
kare = pygame.Rect((50, 50), (100, 100))
devam = 1
sola_git = True
while devam == 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    pencere.fill((255, 255, 255))
    if kare.right >= 800:
        sola_git = True
    if kare.left <= 0:
        sola_git = False
    if sola_git:
        kare.left-= 5
    else:
        kare.right += 5
    pygame.draw.rect(pencere, (0, 255, 0), kare)
    pygame.display.update()
    time.sleep(0.025)

Şimdi sola_git diye bir değişken tanımladım ve değerini True yaptım. while döngüsünün içine ise birkaç şart ekledim.

if kare.right >= 800:
    sola_git = True

Bunnu anlamı eğer karenin sağ tarafı ekranın genişliğini (yani x = 800'ü geçerse) geçerse sola_git değişkenini True yap.


if kare.left <= 0:
    sola_git = False

Bunun anlamı da eğer karenin solu ekranın soluna gelirse (yani x = 0'ı geçerse) sola_git değişkeni False. Bundan sonraki if ve elif şartları da sola_git değişkeninin True ya da False olmasına göre karenin x koordinatını 5 arttırır ya da 5 azaltır.

Gelelim bu dersin asıl önemli konusuna; kontroller. Hemen kodu yazayım, sonra gerekli açıklamaları yaparım.


import pygame, time, sys
pygame.init()
pencere = pygame.display.set_mode((800, 600))
kare = pygame.Rect((50, 50), (100, 100))
devam = 1
while devam == 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                kare.left -= 1
            if event.key == pygame.K_RIGHT:
                kare.right += 1
            if event.key == pygame.K_UP:
                kare.top -= 1
            if event.key == pygame.K_DOWN:
                kare.bottom += 1
             
    pencere.fill((255, 255, 255))
    pygame.draw.rect(pencere, (0, 255, 0), kare)
    pygame.display.update()
    time.sleep(0.025)

Burada az önceki koda yazdığım sola_git değişkenini ve ona bağlı olan her şeyi sildim, şimdilik ona ihtiyacımız yok. Onun yerine while döngüsünün başındaki for döngüsüne ekleme yaptım. Gördüğünüz gibi çıkış fonksiyonundan hemen sonra if event.type == pygame.KEYDOWN diye bir şey ekledim. Bu "eğer klavyeden bir tuş basılırsa" anlamına gelir. Daha sonra da if event.key == pygame.K_LEFT yazdım, bunun anlamı da "eğer basılan tuş sol olursa"dır. Aynı şeyi sağ, yukarı ve aşağı için yaptım. Klavyedeki bütün tuşlardan bu şekilde girdi alabilirsiniz. Bütün tuşların karşılıklarını buradan bulabilirsiniz.

Tabi yazdığımız bu oyunda karemiz çok yavaş hareket ediyor ve her hareketi için tuşu bırakıp tekrar basmamız gerekiyor. Basılı tutunca hareket etmesini sağlamanın birkaç yolu var. En basiti while döngüsünden önce pygame.key.set_repeat(zaman_aralığı, basılma_sayısı) satırını eklemek. Zaman aralığı dediğim mili saniye  cinsinden geçecek zaman, basılma_sayısı ise o zaman içinde tuşun kaç kere basıldığıdır. Böyle anlatınca anlaşılması biraz zor oluyor ama o satırı kodunuza ekleyip sayılarla biraz oynarsanız hemen anlarsınız. Kısaca karenin basar basmaz durmandan harekete başlaması için pygame.key.set_repeat(1, 1) gibi bir şey yazmanız yeterli olacaktır.

Son olarak da çok önemli bir konu olan çarpışmaya değinmek istiyorum. Başlangıç aşamasında sadece kareleri kullanacağımız için karelerin çarpışmasını anlatacağım sizlere. Pygame'in bunun için çok güzel bir fonksiyonu var: kare1.colliderect(kare2) . Eğer kare1 kare2'ye çarpıyorsa bu fonksiyon True değerini verecektir. Yok eğer çarpmıyorsa False değerini verir. Hemen bir örnek yapalım.

import pygame, time, sys
pygame.init()
pencere = pygame.display.set_mode((800, 600))
kare = pygame.Rect((50, 50), (100, 100))
kare2 = pygame.Rect((300, 50), (100, 100))
devam = 1
pygame.key.set_repeat(1, 1)
while devam == 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                kare.left -= 1
            if event.key == pygame.K_RIGHT:
                kare.right += 1
            if event.key == pygame.K_UP:
                kare.top -= 1
            if event.key == pygame.K_DOWN:
                kare.bottom += 1

    if kare.colliderect(kare2):
        if kare.right < kare2.left + 2 :
            kare.right = kare2.left
        elif kare.left > kare2.right - 2:
            kare.left = kare2.right
        if kare.top > kare2.bottom - 2:
            kare.top = kare2.bottom
        elif kare.bottom < kare2.top + 2:
            kare.bottom = kare2.top
    pencere.fill((255, 255, 255))
    pygame.draw.rect(pencere, (0, 255, 0), kare)
    pygame.draw.rect(pencere, (255, 0, 0), kare2)
    pygame.display.update()
    time.sleep(0.025)

Bu örnekte sadece if kare.colliderect(kare2) şartından sonrasını ekledim. Sanırım çok fazla açıklamaya gerek yok. Eğer kafanız karışırsa bir kağıda orijini sol üst köşe olan bir koordinat sistemi çizin ve yazdığım şartları hayal edin.

Bu ders için bu kadarı yeter sanırım. Sonraki derste basit bir uçak oyunu yapacağız, daha da sonra çeşitli grafikler, resimler, sesler ekleyeceğiz. Kendinize çok iyi bakın.