Merhaba sevgili e-bergi okuyucuları! Geçen ay sizlere PyGame ile oyun geliştirmeye giriş amaçlı nasıl “Merhaba Dünya” programı yazılacağını anlatmıştık. Bu ayki yazımızda ise basit bir araba yarışı oyunu yazmaya başlayacağız. İki boyutlu oyunumuz bu aylık sağa, sola, ileri ve biraz geri gidebilen ve gaza bastıkça hızlanan, gazı bırakınca yavaşlayan bir arabadan oluşacak. Daha sonra da bu oyunu nasıl geliştirebileceğimizi göreceğiz. Bu yazıda da geçen ayki http://e-bergi.com/2010/Nisan/PyGame-ile-Oyun-Gelistirme yazımızı okuduğunuzu ve orada anlatılan programları kurduğunuzu varsayarak anlatacağım.

Tabii ki oyunu yazmaya başlamadan önce bir plan yapmamız gerekiyor. Nasıl bir oyun yapacağımıza karar verdikten sonra oyunun kurallarını belirliyoruz. Bu kuralları belirlemeden yazmaya başlarsak sonra bir değişiklik yapmak için tüm oyunun yazılış planını değiştirmemiz gerekebilir. Peki bizim oyunumuzda neler olacak? Amacımız bir araba oyunu yapmak olduğu için oyunumuzda bir yol, bariyer, bariyerin dışı ve kontrol ettiğimiz araba olacak. Arabamız yukarı ok tuşuna bastığında hızlanacak ve belli bir hızdan sonra sabit hızla gidecek. Yukarı ok tuşunu bıraktığımız zaman ise gazı bıraktığımız için araba yavaşlamaya başlayacak fakat aşağı ok veya boşluk tuşuna bastığımızda daha çabuk yavaşlayacak, sanki el freni çekilmiş gibi. Bir de araba bariyerlerin dışına çıktığı zaman arabanın yavaşlaması gerekiyor, böylece arabayı yolda sürme mecburiyeti vermiş olacağız. Sağ ve sol oka bastığımızda araba sağa sola gidecek ama sağa ve sola gidiş hızını ileri gidiş hızına göre ayarlayacağız. Aşağı ok tuşuna arabanın hızı sıfırken basarsak da bir müddet geri gidecek. Sürekli geri gitmesini yazmamıza şimdilik gerek yok, zaten ileriye gidişle aynı mantıkta bir kodu olacaktır. Bir de arabanın yaptığı hızı da ekranın sol tarafına yazdıracağız. Bu aylık rakip araba mevcut olmayacağı için çarpışma kontrol vb yapmayacağız.

Aşağıda oyunun tüm kodunu bulabilirsiniz. Ayrıca oyunda kullanılan birkaç resmi de http://e-bergi.com/2010/Mayis/araba.gif, http://e-bergi.com/2010/Mayis/yol.jpg http://e-bergi.com/2010/Mayis/bariyer.jpg adreslerinden indirebilirsiniz.

1\. import pygame, sys, time, random
2\. from pygame.locals import *
3\. 
4\. pencereGenis = 800
5\. pencereYuksek = 600
6\. Siyah = (0, 0, 0)
7\. Beyaz = (255, 255, 255)
8.
9\. 
10.
11\. def cikis():
12\.    pygame.quit()
13\.    sys.exit()
14.
15\. def yaziYaz(yazi, tip, yuzey, x, y):
16\.         yaziS = tip.render(yazi, 1, Beyaz)
17\.         yaziRect = yaziS.get_rect()
18\.         yaziRect.topleft = (x, y)
19\.         yuzey.blit(yaziS, yaziRect)
20.
21\. pygame.init()
22.
23\. saat = pygame.time.Clock()
24.
25\. pencereYuzeyi = pygame.display.set_mode((pencereGenis, pencereYuksek),0, 32)
26\. pygame.display.set_caption('ODTU Bilgisayar Toplulugu - Araba Oyunu')
27.
28\. tip = pygame.font.SysFont(None, 48)
29.
30\. araba = pygame.Rect(400, 450, 60, 100)
31\. solBariyer = pygame.Rect(150, -200, 10, 1000)
32\. sagBariyer = pygame.Rect(640, -200, 10, 1000)
33\. arabaResim = pygame.image.load('araba.gif')
34\. yol = pygame.Rect(0, -200, 800, 1000)
35\. yolResim = pygame.image.load('yol.jpg')
36\. bariyer = pygame.image.load('bariyer.jpg')
37.
38\. gitSola = False
39\. gitSaga = False
40\. gitYukari = False
41\. gitAsagi = False
42\. Hizlan = False
43\. Yavasla = False
44\. YolDisi = False
45\. elFreni = False
46.
47\. Hiz = 0.0
48.#Oyun döngüsü başlıyor
49\. while True:
50.
51\.    for olay in pygame.event.get():
52\.        if olay.type == QUIT:
53\.                 cikis()
54\.                 
55\.        if olay.type == KEYDOWN:
56\.                 if olay.key == K_LEFT:
57\.                        gitSaga = False
58\.                        gitSola = True
59\.             if olay.key == K_RIGHT:
60\.                        gitSola = False
61\.                        gitSaga = True
62\.                if olay.key == K_UP:
63\.                        Yavasla = False
64\.                        gitYukari = True
65\.                        gitAsagi = False
66\.                        Hizlan = True
67\.                    elFreni = False
68\.                if olay.key == K_DOWN:
69\.                     if Hiz>0:
70\.                        elFreni = True
71\.                        Hizlan = False
72\.                            Yavasla = False
73\.                        else:
74\.                            gitAsagi = True
75\.                if olay.key == K_SPACE:
76\.                        elFreni = True
77\.                    Hizlan = False
78.
79\.        if olay.type == KEYUP:
80\.                if olay.key == K_ESCAPE:
81\.                        cikis()
82\.                        
83\.                if olay.key == K_LEFT:
84\.                    gitSola = False
85\.            if olay.key == K_RIGHT:
86\.                    gitSaga = False
87\.            if olay.key == K_UP:
88\.                    Hizlan = False
89\.                    Yavasla = True
90\.            if olay.key == K_DOWN:
91\.                    gitAsagi = False
92.
93\.    if Hiz == 20:
94\.            Hizlan = False
95.
96\.  if araba.right >= 640 or araba.left <= 160:
97\.            YolDisi = True
98\.  if araba.right < 640 and araba.left > 160:
99\.            YolDisi = False
100.
101\.      if elFreni:
102\.       if Hiz > 0.3:
103\.                   Hiz -= 0.3
104\.            elif Hiz <= 0.5:
105\.                   Hiz = 0
106.
107\.    if Hizlan and Hiz < 20:
108\.       if not YolDisi:
109\.                   Hiz += 0.08
110\.            else:
111\.                   Hiz -= 0.05
112\.    if Yavasla:
113\.            if Hiz <= 1:
114\.                   Hiz = 0
115\.            else:
116\.                   Hiz -= 0.05
117\.    if YolDisi:
118\.            if Hiz <= 1:
119\.                   Hiz = 1
120\.            else:
121\.                   Hiz -= 0.1
122.
123\.    if Hiz >= 3:
124\.           yanHiz = Hiz / 3
125\.     else:
126\.               yanHiz = Hiz
127.
128.
129\.    if gitAsagi:
130\.         if yol.bottom > pencereYuksek:
131\.                       yol.bottom -= 2.0
132\.    if gitYukari:
133\.       if yol.top < 0:
134\.               yol.top += Hiz
135\.       else:
136\.               yol.top = -180
137\.    if gitSaga and araba.right < pencereGenis:
138\.           if gitYukari or gitAsagi:
139\.               araba.right += yanHiz
140\.    if gitSola and araba.left > 0:
141\.       if gitYukari or gitAsagi:
142\.               araba.left -= yanHiz
143.
144\.    pencereYuzeyi.blit(yolResim, yol)
145\.    yaziYaz('HIZ: %s ' % int(10 * Hiz), tip, pencereYuzeyi, 10, 400)
146\.    pencereYuzeyi.blit(bariyer, sagBariyer)
147\.    pencereYuzeyi.blit(bariyer, solBariyer)
148\.    pencereYuzeyi.blit(arabaResim, araba)
149\.    pygame.display.update()
150\.    saat.tick(40)

Başlangıç

1\. import pygame, sys, time, random
2\. from pygame.locals import *

Geçen ayki yazımızda bahsettiğimiz gibi oyunun başında eklememiz gereken modülleri burada ekliyoruz. Bu modüllerden random ve time modülü isimlerinden de anlaşılacağı gibi rastgele bir sayı seçmemizi ve oyun esnasında zaman kontrolü yapmamızı sağlıyorlar.

4\. pencereGenis = 800
5\. pencereYuksek = 600
6\. Siyah = (0, 0, 0)
7\. Beyaz = (255, 255, 255)

Bu bölümde istediğimiz pencere genişliğini ve yüksekliğini birer değişkene atıyoruz. Daha sonra mesela yüksekliği değiştirmek istersek sadece pencereYuksek değişkeninin değerlerini değiştirerip 600'ü her kullandığımız yerde değişiklik yapmak zorunda kalmayacağız. Renkler için de birer değişken oluşturup RGB değerlerini bu değişkenlere atıyoruz.

Fonksiyon Tanımlama

11\. def cikis():
12\.    pygame.quit()
13\.    sys.exit()
14.
15\. def yaziYaz(yazi, tip, yuzey, x, y):
16\.         yaziS = tip.render(yazi, 1, Beyaz)
17\.         yaziRect = yaziS.get_rect()
18\.         yaziRect.topleft = (x, y)
19\.         yuzey.blit(yaziS, yaziRect)
20.
21\. pygame.init()

11. satırdan itibaren ise iki tane fonksiyon tanımlıyoruz. Birincisi cikis() fonksiyonumuz, geçen ay bahsettiğimiz gibi pencere kapatılırsa veya bizim belirttiğimiz herhangi bir durum olursa pygame ve sys modüllerini kapatıp güvenli çıkış yapmayı sağlayan bir fonksiyon. İkinci fonksiyonumuz yaziYaz() fonksiyonu ise 5 değişken alıp yazı yazmayı sağlıyor. İlk değişken yazının kendisini, ikincisi tipini üçüncüsü yazılacağı yüzeyi ve son ikisi ekrandaki koordinatını belirliyor. 21. satırda da pygame kütüphanesinin fonksiyonlarını başlatıyoruz.

pygame.time.Clock() Nesnesi ve tick() Metodu

23\. saat = pygame.time.Clock()
24.
25\. pencereYuzeyi = pygame.display.set_mode((pencereGenis, pencereYuksek),0, 32)
26\. pygame.display.set_caption('ODTU Bilgisayar Toplulugu - Araba Oyunu')
27.
28\. tip = pygame.font.SysFont(None, 48)

23. satırda time modülünün kullanımını görüyoruz. Bir değişkene atadığımız pygame.time.Clock() nesnesi ilerde 150. satırda kullandığımız tick() metodunun çalışmasına yardımcı oluyor. Bu ikili, oyun döngüsünün bir saniye içinde kaç kez çalıştığını kontrol ediyor. Yani 150. satırdaki saat.tick(40) bir saniye içinde 40'tan fazla döngü olmasını engelliyor. Bu şekilde oyunumuz hızlı ve yavaş bilgisayarlarda eşit hızda çalışıyor.

25. satırda ise geçen ayki yazımızda bahsettiğimiz gibi pencerenin boyutunu belirliyoruz. 26. satırda da penceredeki başlığımızı atıyoruz.

28. satırda oyunda yazılacak yazılar için genel bir yazı tipi belirliyor ve bunu bir değişkene atıyoruz.

pygame.Rect() ve Oyuna Resim Ekleme

30\. araba = pygame.Rect(400, 450, 60, 100)
31\. solBariyer = pygame.Rect(150, -200, 10, 1000)
32\. sagBariyer = pygame.Rect(640, -200, 10, 1000)
33\. arabaResim = pygame.image.load('araba.gif')
34\. yol = pygame.Rect(0, -200, 800, 1000)
35\. yolResim = pygame.image.load('yol.jpg')
36\. bariyer = pygame.image.load('bariyer.jpg')

Öncelikle yazı yazarken kullandığımız gibi açtığımız resimlerin de üstünde yaşayacakları birer Rect nesnesi oluşturmamız gerekiyor. Bu Rect nesnelerini pygame.Rect() fonksiyonu ile oluşturacağız. Bu fonksiyonun ilk iki değişkeni nesnenin sol ve üst koordinatı diğer iki değişkeni de nesnenin genişliği ve yüksekliğidir. Bu değişkenlere veya nesnenin bazı değerlerine sonra

araba.left – nesnenin sol koordinatı / y ekseni değeri.
araba.right – nesnenin sağ koordinatı / y ekseni değeri.
araba.top – nesnenin üst koordinatı / x ekseni değeri.
araba.bottom – nesnenin alt koordinat / x ekseni değeri.
araba.width – nesneni genişliği
araba.height – nesnenin yüksekliği özelliklerini kullanarak ulaşabilirsiniz.

Açacağımız tüm resimler için bir Rect nesnesi oluşturduktan sonra 33. satırda gördüğünüz gibi resimleri oyunumuza aktarabiliriz. Bunun için de pygame.image.load() fonksiyonunu kullanıp bir değişkene atıyoruz ve resme bundan sonra ulaşmak için bu değişkeni kullanıyoruz. Fonksiyonun parametresi ise oyunumuzun bulunduğu klasöre göreli resmin adresidir. Yani oyun ile resim aynı klasördeyse 'araba.gif' yazmak yeterli olacak; fakat başka bir klasörün daha içindeyse onu belirtmemiz gerekecektir.

Oyundaki Kontrol Değişkenleri

38\. gitSola = False
39\. gitSaga = False
40\. gitYukari = False
41\. gitAsagi = False
42\. Hizlan = False
43\. Yavasla = False
44\. YolDisi = False
45\. elFreni = False
46.
47\. Hiz = 0.0

Oyunda bazı durumlarda değiştirilecek ve değerine göre bazı işlemler yapılmasını sağlayacak değişkenler oluşturuyoruz. False değeri atananlar hızlanmayı, sağa, sola, yukarı, aşağı gitmeyi, hızlanmayı ve yavaşlamayı kontrol etmemiz için oluşturulmuştur. Hiz değişkeimiz ise yolu ne hızda aşağı kaydıracağımızı söylemektedir. Evet, arabayı ileri götürmek yerine yolu geri götürerek hızlanma etkisi yaratmaya çalışacağız =)

Oyun Döngüsü

49\. while True:

Oyunumuzun 49. satırından itibaren saniyede 40 kez tekrarlanacak döngü başlıyor. Döngü sayesinde oyunumuz sürekli aynı görüntüyee sahip olmayacak ve görüntüler bizim kontrolümüzde saniyede 40 defa değişecek.

Olay Kontrolü

51\.    for olay in pygame.event.get():
52\.            if olay.type == QUIT:
53\.                cikis()
54\.                
55\.             if olay.type == KEYDOWN:
56\.                 if olay.key == K_LEFT:
57\.                        gitSaga = False
58\.                        gitSola = True
59\.             if olay.key == K_RIGHT:
60\.                        gitSola = False
61\.                        gitSaga = True

Döngü başlar başlamaz bir olay (event) kontrolü yapıyoruz. PyGame’de olaylar pygame.event.get() fonksiyonu ile alınıyor ve biz de 51. satırda yeni bir döngüde ‘olay’ ismi verdiğimiz olayları kontrol ediyoruz. 52. satırda gördüğünüz gibi olayımızın tipinin (olay.type) QUIT olup olmadığına bakıyoruz. 55. satırdan itibaren ise geçen ay görmediğimiz yeni bir olay tipini kontrol etmeye başlıyoruz. Klavyede bir tuşa basılmışsa olay tipi KEYDOWN, tuş bırakılmışsa KEYUP olacaktır ve hangi tuşa basıldığını öğrenmek için olay.key’i kontrol ediyoruz. Buradaki ‘olay’ 51. satırda for döngüsü başlarken verdiğimiz isim olduğu için sizin programınızda değişebilir. Eğer olay.key, K_LEFT ise sol ok tuşuna basılmış demektir. Bunun gibi hangi tuşun nasıl gösterildiğini görmek istiyorsanız http://www.pygame.org/docs/ref/key.html adresindeki bilgilerden yararlanabilirsiniz. Ayrıca diğer olayları (event) nasıl kontrol edebileceğinizi öğrenmek için http://www.pygame.org/docs/ref/event.html sayfasına göz atabilirsiniz.

Oyunumuza geri dönersek, döngü içinde kontrol ettiğimiz olaylar eğer KEYDOWN ise hangi tuşa basıldığını öğrenip ona gore bir komut veriyoruz. 56. satırda sol ok tuşuna basıldıysa gitSaga değişkenine False değeri verip gitSola değişkenine True değeri veriyoruz. Buradaki amacımız arabamız daha önceden sağa gidiyorsa bunu önce engelleyip sonra sola gitmesini sağlamaktır. Eğer ikisi de True olursa daha sonra yazdığımız if’li ifadelerde sorun çıkacaktır. Aynı şekilde sağ ok tuşuna basıldıysa da değişkenlerimizi değiştiriyoruz.

62\.                if olay.key == K_UP:
63\.                        Yavasla = False
64\.                        gitYukari = True
65\.                        gitAsagi = False
66\.                        Hizlan = True
67\.                     elFreni = False

62. satırdan itibaren yukarı ok tuşuna basıldıysa ne yapılacağını söylüyoruz. Yukarı tuş arabamız için gaz anlamı taşıdığı için hızlanması ve yukarı gitmesini sağlamamız gerekiyor. Hizlan ve gitYukari değişkenlerine True değerini veriyoruz. Daha önceden Yavasla, elFreni veya gitAsagi değişkenlerinden birinin True değeri taşıyor olma ihtimalini göz önünde bulundurarak bu değişkenlere de False değerini atıyoruz.

68\.                if olay.key == K_DOWN:
69\.                     if Hiz>0:
70\.                            elFreni = True
71\.                            Hizlan = False
72\.                            Yavasla = False
73\.                            else:
74\.                                gitAsagi = True
75\.                if olay.key == K_SPACE:
76\.                        elFreni = True
77\.                    Hizlan = False

68. satırda ise aşağı ok tuşuna basılma durumunu kontrol etmeye başlıyoruz. Yukarı oktan farklı olarak bu tuşun el freni gibi bir etki de yaratmasını sağlamak istiyoruz. Yani araba eğer ilerliyorsa el freni çekilsin, araba duruyorsa da aşağı doğru gitsin… Bunun için de arabanın hızı sıfırdan büyükse elFreni değerini True, daha önceden araba hızlanıyor veya yavaşlıyor olabilir diye düşünerek Hizlan ve Yavasla değerlerini de False atıyoruz (El freni çekildiği zaman çok çabuk yavaşlayacağı için Yavasla değişkeninin True olmaması gerekiyor. Çünkü Yavasla değişkeni True olduğunda arabayı sürtünmeden yavaşlıyormuş gibi uzun bir sürede yavaşlatacağız.) Eğer arabanın hızı sıfırsa da gitAsagi değerini True atıyouz. 75. satırda ise boşluk tuşuna basıldığında el frenini çalıştırıyoruz.

79\.            if olay.type == KEYUP:
80\.                if olay.key == K_ESCAPE:
81\.                        cikis()
82\.                        
83\.                if olay.key == K_LEFT:
84\.                    gitSola = False
85\.                if olay.key == K_RIGHT:
86\.                    gitSaga = False
87\.                if olay.key == K_UP:
88\.                    Hizlan = False
89\.                    Yavasla = True
90\.                 if olay.key == K_DOWN:
91\.                    gitAsagi = False

79. satırda olayın KEYUP olup olmadığını kontrol ediyoruz ve sonrasında hangi tuşun bırakıldığına bakıyoruz. Bu bölümde genellikle KEYDOWN bölümünde yaptıklarımızın tersini yapıyoruz. Yukarı ok tuşu bırakıldığında el freni durumunu değiştirmemize gerek kalmıyor çünkü zaten yukarı ok tuşuna bastığımızda elFreni değişkenini False atıyoruz. KEYUP, yani tuş bırakılması durumunda herhangi bir değişiklik yapmazsak gaza bastığımızda araba hızlanmaya başlar ve biz gazı bıraksak da hızlanmaya devam eder veya sağ ok tuşuna bastığımızda sağa gitmeye başlar fakat bıraksak da sağa gitmeye devam eder. Bu nedenle burada yaptığımız kontroller oldukça önemlidir.

Değişken Durum Kontrolü

93\.    if Hiz == 20:
94\.            Hizlan = False
95.
96\.  if araba.right >= 640 or araba.left <= 160:
97\.            YolDisi = True
98\.  if araba.right < 640 and araba.left > 160:
99\.            YolDisi = False

93. satırdan sonra artık olay kontrolünün sonucunda değişkenlerin edindiği değerlere göre yapılacakları yazmaya başlıyoruz. Mesela ilk olarak 93. satırda hız sınırımızı belirliyoruz. Hiz değişkeni 20 olduğunda daha fazla hızlanmayı engelleyebilmek için Hizlan değişkenini False atıyoruz.

96. satırda ise arabanın hangi durumda yoldan çıktığını tanımlıyoruz. Yani arabanın sağ kısmının x ekseni değeri (araba.right) ekranın en soldan 640. pikselinden daha sağa giderse veya sol kısmının x ekseni değeri (araba.left) ekranın en soldan 160. pikselinden daha sola giderse arabanın yoldan çıktığını söylüyoruz ve YolDisi değişkenini True atıyoruz. 98. satırda ise tam tersini yapıyoruz fakat bu kez ‘or’ yerine ‘and’ kullanıyoruz. Eğer ‘or’ kullanırsak arabanın sağ kısmı 640. pikselden daha soldayken ifademiz her zaman True olacaktır. Yani arabanın sol kısmı 160. pikselin solunda bile olsa ifade True olacağı için YolDisi her durumda False olacaktır.

101\.      if elFreni:
102\.       if Hiz > 0.3:
103\.                       Hiz -= 0.3
104\.               else:
105\.                              Hiz = 0

101. satırda boşluk tuşuna basıldığında veya araba ilerlerken aşağı ok tuşuna basıldığında True değeri alan elFreni değişkeni kontrol ediliyor. El freni uygulamaya geçtiyse ve Hiz değişkeni 0.3’ten büyükse Hiz’i 0.3 azaltıyoruz ve 0.3’ten büyük değilse Hiz’i 0 atıyoruz. Her durumda 0.3 azaltamıyoruz çünkü Hiz 0.4 iken 0.3 azaltınca Hiz = 0.1 oluyor ve tekrar 0.3 azaltırsak eksiye düşüyor ve araba geri gitmeye başlıyor. Bunu engellemek için böyle bir kontrol yapmamız şart oluyor.

107\.    if Hizlan and Hiz < 20:
108\.       if  not YolDisi:
109\.                       Hiz += 0.08
110\.               else:
111\.                       Hiz -= 0.05

107. satırda Hizlan değişkeninin True olması ve Hiz’in 20’den (hız sınırı) küçük olması durumunda arabanın yol dışında olup olmadığına bakılıyor. Araba yoldaysa hızı 0.08 artıyor, değilse de 0.05 azalıyor.

112\.    if Yavasla:
113\.               if Hiz <= 1:
114\.                       Hiz = 0
115\.               else:
116\.                       Hiz -= 0.05

112. satırda Yavasla değişkenini True ise el freni bölümü gibi bir kontrolden geçip Hiz değişkeni 0.05 azaltılıyor veya tamamen sıfırlanıyor.

117\.    if YolDisi:
118\.               if Hiz <= 1:
119\.                       Hiz = 1
120\.               else:
121\.                       Hiz -= 0.1

117. satırda araba yol dışına çıkınca hızında nasıl bir değişiklik yapılacağını yazıyoruz. Yol dışında arabanın hızını tamamen sıfırlamak yerine 1’e kadar düşürüyoruz. Böylece araba yol dışında hiç hızlanamayacak ve gaza bassa bile bir müddet sonra 1 hızla gitmeye mahkum kalacak. Bunun için de Hiz değişkenini sürekli 0.1 azaltıyoruz ve 1’den az veya 1’e eşit olursa azalmayı engelliyoruz.

123\.    if Hiz >= 3:
124\.           yanHiz = Hiz / 3
125\.     else:
126\.            yanHiz = Hiz

123. satırda da arabanın sağa ve sola gidiş hızını ayarlıyoruz. Arabanın hızı 3’ten küçükse sağa ve sola gidiş hızı ileri gidiş hızına eşit olacak; değilse ileri gidiş hızının 3’te birine eşit olacaktır. Böylece araba hareketsizse sağa sola gitmesini ve çok hızlıyken kolayca sağ sol yapmasını engelliyoruz.

Arabayı Hareket Ettirme

129\.    if gitAsagi:
130\.         if yol.bottom > pencereYuksek:
131\.                   yol.bottom -= 2.0
132\.    if gitYukari:
133\.           if yol.top < 0:
134\.               yol.top += Hiz
135\.           else:
136\.               yol.top = -180

129. satırdan itibaren arabanın nasıl yukarı, aşağı, sola ve sağa gideceğini tanımlıyoruz. Mesela gitAsagi değişkeni True ise yol.bottom değerine bakıyoruz. Bu değer başta oluşturduğumuz yol Rect nesnesinin en altının y ekseni değeridir. yol nesnesi ekranın yüksekliğinden daha uzun olduğundan en üstü ve en altı aynı anda görüntüye giremez. Eğer en altı pencere yüksekliğinden aşağıdaysa (x ve y ekseni ekranın sol üst köşesinde (0,0) değerini alır ve aşağı gittikçe y değeri, sağa gittikçe x değeri artar) yani yol.bottom > pencereYuksek ise yol nesnesini 2 piksel yukarı götürüyoruz. Burada yolu yukarı götürmek arabanın geri gittiği izlenimini oluşturacaktır.

130. satırda arabanın yukarı gitmesini anlatıyoruz. Eğer yolun en üstü ekranda görünmüyorsa yani y ekseni değeri sıfırdan küçükse yolu Hiz değişkeni kadar aşağı kaydırıyoruz. Fakat oluşturduğumuz yol nesnesi arabanın gideceği hayali yol kadar uzun olmadığı için en üstü bir şekilde y ekseninde 0 değerini alıyor. Yani eğer bir şey yapmazsak araba bir müddet sonra yol nesnesinden çıkıp boşlukta kalabilir. Bunu engellemek için yol nesnesinin en üstü ekranın en üst çizgisine (y=0) ulaştığında, yol nesnesini Hiz değeri kadar aşağı kaydırmak yerine 180 piksel yukarı götürüyoruz. 180 piksel olması ise tamamen yol.jpg resminden kaynaklanmaktadır. Görüntüde atlama olmaması için en uygun değerin bu olduğunu birkaç denemede siz de bulabilirsiniz. Mesela 150 değeri verirsek ounu oynarken yoldaki çizgilerin yol.top == 0 durumunda atladığını görebilirsiniz.

137\.    if gitSaga and araba.right < pencereGenis:
138\.    if gitYukari or gitAsagi:
139\.               araba.right += yanHiz
140\.    if gitSola and araba.left > 0:
141\.           if gitYukari or gitAsagi:
142\.               araba.left -= yanHiz

137. satırda bu kez arabanın kendisini oynatıyoruz. Sağa gitmesi için gitSaga değişkeninin True olup olmadığına bakıyoruz. Eğer arabanın en sağı (araba.right) pencerenin en sağında (yani araba.right

140. satırda da sağa gitme işleminin hemen hemen aynısını sola gitmek için kullanıyoruz. Bu kez arabanın en solunun ekranın en solunda olmadığından emin olmamız gerekiyor, aksi takdirde arabanın bir bölümü ekrandan dışarı çıkabilir. Sonra da arabanın solunu yanHiz değeri kadar azaltıyoruz (x ekseninde).

Yüzeyleri Yenileme

144\.    pencereYuzeyi.blit(yolResim, yol)
145\.    yaziYaz('HIZ: %s ' % int(10 * Hiz), tip, pencereYuzeyi, 10, 400)
146\.    pencereYuzeyi.blit(bariyer, sagBariyer)
147\.    pencereYuzeyi.blit(bariyer, solBariyer)
148\.    pencereYuzeyi.blit(arabaResim, araba)
149\.    pygame.display.update()
150\.    saat.tick(40)

Oyun döngüsünün sonuna geldik. Burada artık oyunumuzun görüntüsünün her döngüde yenilenerek - sürekli aynı görüntüyü değil de - yaptığımız değişikliklere göre yeni görüntü vermesini sağlıyoruz. Geçen ayki yazımızda blit() metodundan bahsetmiştik. Bu metodla ilk olarak 144. satırda yolResim değişkenini yol nesnesi üzerinde oluşturuyoruz. Yani yolResim (yol.jpg) her döngüde yol nesnesi neredeyse orada oluşturulacak.

145. satırda da kendi yazdığımız fonksiyon olan yaziYaz() fonksiyonuna “HIZ: 100” gibi bir yazı yazdırıyoruz. Bizim Hiz değişkenimiz en çok 20 aldığı için daha gerçekçe göstermek adına Hiz değişkenini 10 ile çarpıp o şekilde yazdırıyoruz. Yani artık hız sınırımız görünürde 200 =)

146. satırda ‘bariyer’ resmini sagBariyer nesnesinin üstüne çiziyoruz. 147. satırda aynısını solBariyer için yapıyoruz. 148. Satırda ise arabaResim’i araba nesnesinin üstüne çiziyoruz. Artık araba nesnesi nereye giderse araba.gif resmi orada oluşturulacaktır.

149. satırda da geçen ay bahsettiğimiz pygame.display.update() fonksiyonu ile bu zamana kadar hayali olarak çizdiğimiz her şeyi ekranda oluşturuyoruz.

Bu bölümde blit metodunun kullanım sırası çok önemlidir. Eğer araba en üstte görünecekse en son onun blit metodu ile çizilmesi gerekir. Mesela bariyerler de yolun üstüne çizildiği için sıralama yol, bariyerler ve araba şeklinde olmalıdır. Aksi takdirde görüntüde hata olabilir veya program düzgün çalışmayabilir.

Bu ay da pygame ile çok basit de olsa temel bilgilerle yapılabilecek bir oyun tasarladık. Kodun başında eklediğimiz halde kullanmadığımız random modülünü ilerde eklenecek özellikler için saklıyoruz =) Rastgele karşımıza çıkan arabalar ve bizim arabayla çarpışmalarını kontrol edecek özellikleri nasıl ekleyeceğimizi gelecek yazımda anlatmaya çalışacağım. Gelecek yazıda görüşmek dileğiyle hoşçakalın =)

2