Orjinali http://kivy.org/docs/tutorials/pong.html
Merhaba,
Bu sefer yine Python programlama dilini kullanarak bişeyler yapacağız. Kivy hızlı uygulama geliştirmek için açık kaynak bir Python kütüphanesi.
Bu çalışmada Kivy kütüphanesini kullanarak basit Pong oyunu yapacağız.
Kivy kütüphanesi sitesi www.kivy.org adresinden zip olarak indirilip kullanılabiliyor. Kullanmak için de yazmış olduğunuz python programı indirdiğiniz klasör içindeki kivy.bat dosyası ile çalıştırınca gerisi otomatik hallediliyor.
İlk önce uygulamamız için bir klasör oluşturup içine main.py adında bir Python script dosyası üretiyoruz.
Şimdi bu siyah arkaplan üzerine yayılmaya başlayalım. PongGame sınıfının boş olan görüntüsüne birşeyler ekleyebilmek için önce .kv uzantılı bir görsel dosyası oluşturacağız. Bu amaçla adı pong.kv olan bir yeni dosya üretiyoruz.
<PongGame>:
satırı uygulamamızdaki PongGame sınıfının görselini tanımlama bloğuna başladığımızı bildiriyor.
canvas birçok programlama dilinde çizim yapılacak alan tanımlarken kullanılır burada da ekranın ortasındaki kalın çizgiyi (pardon dikdörtgeni) çizeceğiz. canvas içerisinde Rectangle bloğu kullanarak sadece bir tane dikdörtgen çiziliyor. Dikdörtgenin pos özelliği sol üst köşesinin koordinatlarını belirler. Koordinatlar aynı şekil pencerenin sol üst köşesi x=0, y=0 dan başlar sağa ve aşağıya doğru büyür. Burada yatay olarak pencere ortasından 5 piksel sola, dikey olarak da en üste ayarlanıyor. Niye 5 piksel sola çünkü 10 piksel genişliğinde bir dikdörtgen çizeceğiz ve tam ortada olmasını istiyoruz. Dikdörtgenin size özelliği sırasıyla genişlik ve yüksekliği belirler. Burada genişlik 10 piksel yükseklik ise pencere yüksekliği kadar ayarlanmış.
Gelelim Label bloklarına , önce yazı boyutu font_size özelliği ile 70 piksel yapılıyor. Yazının yatay olarak ortası center_x özelliği ile pencerenin yatay olarak 1/4 ve 3/4 ünde iki adet Label var. Yazıların üst koordinatları top özelliği ile pencere üst çizgiden 50 piksel aşağıda olacak. Yazılarda ne yazacağı da text özelliği ile 0 yapılıyor.
Uygulamayı çalıştırıp pencere boyutunu değiştirince görüyoruzki yerleştirdiğimiz elemanlar da otomatik olarak pozisyon ve boyut değiştiriyor. Genel olarak sabit duran ekran elemanları hazır, topumuza geçelim.
Şimdi bir PongBall sınıfı tanımlayacağız ve bunun görseli ve hareketlerini oluşturacağız. PongBall sınıfının Python kodu şöyle:
main.py
pong.kv
Dikkat ettiyseniz sadece PongBall görselini tanımlamadık , tanımladığımız topu gidip PongGame görselinde ekranın ortasına koyduk.
Evet sevgili top ekranın ortasına geldi , tanımında move fonksiyonu da var ama hareket etmiyor neden? Çünkü bu move fonksiyonunu belirli aralıklarla çağırmamız gerekir. Şu anda kimse çağırmıyor. Bu belirli aralıkta çağırma işlemlerinde Kivy kütüphanesinin Clock sınıfı kullanılır.
Bu noktada biraz duralım. Biz topumuzu tanımladık ve onun move fonksiyonunu çağırmak için uygulamamıza kod ilave ediyoruz. Ancak daha topumuzun ana kod içersinde herhangi bir tanımlaması yok. Top sadece bir yönde gitmeyecek duvarlara ve raketlere vurunca geri sekecek falan. O zaman biz tüm bu hareketler için update adında bir fonksiyon tanımlıyalım ve move yerine onu çağıralım:
main.py
pong.kv
Sonunda topumuz dolaşmaya başladı, kenarlardan da sekiyor. Sıra geldi hareket eden raketler ve skor takibine. Sınıf eklenmesi ve kv kuralı eklemelerinin ayrıntılarına daha önce anlattığımız için girmeyeceğiz. Bunun yerine Player görselinin bizim komutlarımıza göre nasıl hareket edeceğine odaklanalım. PongPaddle sınıfı için yazılan kodu ve kv kuralının tamamını yazı sonunda bulabilirsiniz.
Kivy'de kullanıcı olaylarına on_touch_down , on_touch_move ve on_touch_up metodlarıyla erişilir. Default olarak olay oluştuğunda bu metodlar ana pencere kodundan itibaren pencere içindeki ve onların içindeki görsellerde sırasıyla aranır, ilk bulunan metod çalıştırılır. Bizim raketler pek de matah bir hareket yapmıyor sadece yukarı aşağı hareket ediyor. Bu yüzden sadece ana pencereye ekleyeceğimiz tek bir metodla ikisini de kontrol edebiliriz.
Her oyuncu için skoru bir NumericProperty içinde saklayacağız. Skor etiketlerini oyuncuların score NumericProperty'si ile eşleştireceğiz. Bu durumda oyuncunun score özelliğini değiştirince otomatik olarak Skor tabela yazıları değişecektir.
Top kenardan dışarı çıktığında skoru yenileyip ortadan oyuna yeni bir top sokacağız. Bu amaçla update metodunu değiştireceğiz. PongPaddle sınıfına ayrıca bounce_ball metodu ekleyerek topun raketin değişik noktalarından değişik açılarla sekmesini sağlayacağız. İşte bu PongPaddle sınıfı:
Ve kodumuzun son hali:
main.py
pong.kv
Hepsi bu kadar , yeni yazılarda görüşmek üzere...
Merhaba,
Bu sefer yine Python programlama dilini kullanarak bişeyler yapacağız. Kivy hızlı uygulama geliştirmek için açık kaynak bir Python kütüphanesi.
Bu çalışmada Kivy kütüphanesini kullanarak basit Pong oyunu yapacağız.
Kivy kütüphanesi sitesi www.kivy.org adresinden zip olarak indirilip kullanılabiliyor. Kullanmak için de yazmış olduğunuz python programı indirdiğiniz klasör içindeki kivy.bat dosyası ile çalıştırınca gerisi otomatik hallediliyor.
İlk önce uygulamamız için bir klasör oluşturup içine main.py adında bir Python script dosyası üretiyoruz.
Dosyayı kaydedip uygulamayı çalıştırırsak sadece siyah bir pencere elde etmiş oluruz. Çok basit bir Kivy uygulaması yazdık. Burada Widget sınıfından bir PongGame sınıfı klonlayıp App sınıfından klonladığımız PongApp uygulama sınıfı içinde yerleştirip en sonunda uygulamamızı çalıştırıyoruz.from kivy.app import App from kivy.uix.widget import Widget class PongGame(Widget): pass class PongApp(App): def build(self): return PongGame() if __name__ == '__main__': PongApp().run()
Şimdi bu siyah arkaplan üzerine yayılmaya başlayalım. PongGame sınıfının boş olan görüntüsüne birşeyler ekleyebilmek için önce .kv uzantılı bir görsel dosyası oluşturacağız. Bu amaçla adı pong.kv olan bir yeni dosya üretiyoruz.
Uygulamamızın sınıfı PongApp olduğu için dosya adı pong.kv olmalı. İlk satır her kv dosyasında olması gereken bir satır. Burada hangi Kivy versiyonunu kullandığımız yazıyor. Arkasından gelen satırlar sanki bir Python script gibi di mi?. Programı çalıştırıp bakın ekrana neler geldi. Bu kod içinde ekradaki 2 tane "0" sayısını ve tam ortadaki dikey çizgiyi tahmin edebildiniz mi?
#:kivy 1.0.9 <PongGame>: canvas: Rectangle: pos: self.center_x - 5, 0 size: 10, self.height Label: font_size: 70 center_x: root.width / 4 top: root.top - 50 text: "0" Label: font_size: 70 center_x: root.width * 3 / 4 top: root.top - 50 text: "0"
<PongGame>:
satırı uygulamamızdaki PongGame sınıfının görselini tanımlama bloğuna başladığımızı bildiriyor.
canvas birçok programlama dilinde çizim yapılacak alan tanımlarken kullanılır burada da ekranın ortasındaki kalın çizgiyi (pardon dikdörtgeni) çizeceğiz. canvas içerisinde Rectangle bloğu kullanarak sadece bir tane dikdörtgen çiziliyor. Dikdörtgenin pos özelliği sol üst köşesinin koordinatlarını belirler. Koordinatlar aynı şekil pencerenin sol üst köşesi x=0, y=0 dan başlar sağa ve aşağıya doğru büyür. Burada yatay olarak pencere ortasından 5 piksel sola, dikey olarak da en üste ayarlanıyor. Niye 5 piksel sola çünkü 10 piksel genişliğinde bir dikdörtgen çizeceğiz ve tam ortada olmasını istiyoruz. Dikdörtgenin size özelliği sırasıyla genişlik ve yüksekliği belirler. Burada genişlik 10 piksel yükseklik ise pencere yüksekliği kadar ayarlanmış.
Gelelim Label bloklarına , önce yazı boyutu font_size özelliği ile 70 piksel yapılıyor. Yazının yatay olarak ortası center_x özelliği ile pencerenin yatay olarak 1/4 ve 3/4 ünde iki adet Label var. Yazıların üst koordinatları top özelliği ile pencere üst çizgiden 50 piksel aşağıda olacak. Yazılarda ne yazacağı da text özelliği ile 0 yapılıyor.
Uygulamayı çalıştırıp pencere boyutunu değiştirince görüyoruzki yerleştirdiğimiz elemanlar da otomatik olarak pozisyon ve boyut değiştiriyor. Genel olarak sabit duran ekran elemanları hazır, topumuza geçelim.
Şimdi bir PongBall sınıfı tanımlayacağız ve bunun görseli ve hareketlerini oluşturacağız. PongBall sınıfının Python kodu şöyle:
Tabi topumuzun görseli için de bir kv kuralı tanımlıyoruz:class PongBall(Widget): # x ve y ekseninde topun hızı velocity_x = NumericProperty(0) velocity_y = NumericProperty(0) # referencelist property ile ball.velocity özelliği ya da # kısaca örneğin w.pos , w.x ve w.y kullanabiliriz velocity = ReferenceListProperty(velocity_x, velocity_y) # ``move`` fonksiyonu topumuzu bir adım sonrasına götürür # bunu belli sıklıkta çağırmak topa animasyon verir def move(self): self.pos = Vector(*self.velocity) + self.pos
50x50 piksel boyutlarında bir yuvarlak çiziyoruz. Yaptığımız kodların çalışabilmesi için Properties ve Vector kütüphanelerini de programa dahil edeceğiz. Kodumuzun son hali ve kv dosyamız şu hale geldi:<PongBall>: size: 50, 50 canvas: Ellipse: pos: self.pos size: self.size
main.py
from kivy.app import App from kivy.uix.widget import Widget from kivy.properties import NumericProperty, ReferenceListProperty from kivy.vector import Vector class PongBall(Widget): velocity_x = NumericProperty(0) velocity_y = NumericProperty(0) velocity = ReferenceListProperty(velocity_x, velocity_y) def move(self): self.pos = Vector(*self.velocity) + self.pos class PongGame(Widget): pass class PongApp(App): def build(self): return PongGame() if __name__ == '__main__': PongApp().run()
pong.kv
#:kivy 1.0.9 <PongBall>: size: 50, 50 canvas: Ellipse: pos: self.pos size: self.size <PongGame>: canvas: Rectangle: pos: self.center_x-5, 0 size: 10, self.height Label: font_size: 70 center_x: root.width / 4 top: root.top - 50 text: "0" Label: font_size: 70 center_x: root.width * 3 / 4 top: root.top - 50 text: "0" PongBall: center: self.parent.center
Dikkat ettiyseniz sadece PongBall görselini tanımlamadık , tanımladığımız topu gidip PongGame görselinde ekranın ortasına koyduk.
Evet sevgili top ekranın ortasına geldi , tanımında move fonksiyonu da var ama hareket etmiyor neden? Çünkü bu move fonksiyonunu belirli aralıklarla çağırmamız gerekir. Şu anda kimse çağırmıyor. Bu belirli aralıkta çağırma işlemlerinde Kivy kütüphanesinin Clock sınıfı kullanılır.
Bu kod game sınıfının update fonksiyonunu saniyede 60 kere çağırır.Clock.schedule_interval(game.update, 1.0/60.0)
Bu noktada biraz duralım. Biz topumuzu tanımladık ve onun move fonksiyonunu çağırmak için uygulamamıza kod ilave ediyoruz. Ancak daha topumuzun ana kod içersinde herhangi bir tanımlaması yok. Top sadece bir yönde gitmeyecek duvarlara ve raketlere vurunca geri sekecek falan. O zaman biz tüm bu hareketler için update adında bir fonksiyon tanımlıyalım ve move yerine onu çağıralım:
Bir de kv dosyası içerisine PongBall görselimize ana programda ulaşabilmek için bir isimlendirme ekleyeceğiz. Bunu sağlamak için PongGame sınıfımıza bir ObjectProperty ekleyeceğiz ve kv kuralında tanımladığımız nesneye bağlayacağız.class PongGame(Widget): def update(self, dt): # ball.move ve diğer işlemler burada pass class PongApp(App): def build(self): game = PongGame() Clock.schedule_interval(game.update, 1.0/60.0) return game
kv dosyasındaki PongBall nesnesine bir id vermeyi unutmayalım:class PongGame(Widget): ball = ObjectProperty(None) def update(self, dt): self.ball.move() # üst ve alt kenardan sekmeler if (self.ball.y < 0) or (self.ball.top > self.height): self.ball.velocity_y *= -1 # sol ve sağ kenardan sekmeler if (self.ball.x < 0) or (self.ball.right > self.width): self.ball.velocity_x *= -1
Tüm bu değişiklikleri yapsak da top hala hareket etmiyor. Nedeni hızının sıfır olması. Topa ilk başlangıçta bir hız vermek için serve_ball adlı bir fonksiyon yazalım. Son gelinen programlar şöyle:<PongGame>: ball: pong_ball # ... (canvas ve Label'lar) PongBall: id: pong_ball center: self.parent.center
main.py
from kivy.app import App from kivy.uix.widget import Widget from kivy.properties import NumericProperty, ReferenceListProperty,\ ObjectProperty from kivy.vector import Vector from kivy.clock import Clock from random import randint class PongBall(Widget): velocity_x = NumericProperty(0) velocity_y = NumericProperty(0) velocity = ReferenceListProperty(velocity_x, velocity_y) def move(self): self.pos = Vector(*self.velocity) + self.pos class PongGame(Widget): ball = ObjectProperty(None) def serve_ball(self): self.ball.center = self.center self.ball.velocity = Vector(4, 0).rotate(randint(0, 360)) def update(self, dt): self.ball.move() #üst ve alt kenarda zıplama if (self.ball.y < 0) or (self.ball.top > self.height): self.ball.velocity_y *= -1 #sol ve sağ kenarda zıplama if (self.ball.x < 0) or (self.ball.right > self.width): self.ball.velocity_x *= -1 class PongApp(App): def build(self): game = PongGame() game.serve_ball() Clock.schedule_interval(game.update, 1.0 / 60.0) return game if __name__ == '__main__': PongApp().run()
pong.kv
#:kivy 1.0.9 <PongBall>: size: 50, 50 canvas: Ellipse: pos: self.pos size: self.size <PongGame>: ball: pong_ball canvas: Rectangle: pos: self.center_x-5, 0 size: 10, self.height Label: font_size: 70 center_x: root.width / 4 top: root.top - 50 text: "0" Label: font_size: 70 center_x: root.width * 3 / 4 top: root.top - 50 text: "0" PongBall: id: pong_ball center: self.parent.center
Sonunda topumuz dolaşmaya başladı, kenarlardan da sekiyor. Sıra geldi hareket eden raketler ve skor takibine. Sınıf eklenmesi ve kv kuralı eklemelerinin ayrıntılarına daha önce anlattığımız için girmeyeceğiz. Bunun yerine Player görselinin bizim komutlarımıza göre nasıl hareket edeceğine odaklanalım. PongPaddle sınıfı için yazılan kodu ve kv kuralının tamamını yazı sonunda bulabilirsiniz.
Kivy'de kullanıcı olaylarına on_touch_down , on_touch_move ve on_touch_up metodlarıyla erişilir. Default olarak olay oluştuğunda bu metodlar ana pencere kodundan itibaren pencere içindeki ve onların içindeki görsellerde sırasıyla aranır, ilk bulunan metod çalıştırılır. Bizim raketler pek de matah bir hareket yapmıyor sadece yukarı aşağı hareket ediyor. Bu yüzden sadece ana pencereye ekleyeceğimiz tek bir metodla ikisini de kontrol edebiliriz.
Burada ekranın sağında ya da solunda tıklama yapılmasına göre soldaki ya da sağdaki oyuncunun raketi hareket ettiriliyor.def on_touch_move(self, touch): if touch.x < self.width/3: self.player1.center_y = touch.y if touch.x > self.width - self.width/3: self.player2.center_y = touch.y
Her oyuncu için skoru bir NumericProperty içinde saklayacağız. Skor etiketlerini oyuncuların score NumericProperty'si ile eşleştireceğiz. Bu durumda oyuncunun score özelliğini değiştirince otomatik olarak Skor tabela yazıları değişecektir.
Top kenardan dışarı çıktığında skoru yenileyip ortadan oyuna yeni bir top sokacağız. Bu amaçla update metodunu değiştireceğiz. PongPaddle sınıfına ayrıca bounce_ball metodu ekleyerek topun raketin değişik noktalarından değişik açılarla sekmesini sağlayacağız. İşte bu PongPaddle sınıfı:
Not: Bu kodda özellikle raket kenarlardan top değişik sekiyor isterseniz kendiniz iyileştirme yapabilirsiniz.class PongPaddle(Widget): score = NumericProperty(0) def bounce_ball(self, ball): if self.collide_widget(ball): speedup = 1.1 offset = 0.02 * Vector(0, ball.center_y-self.center_y) ball.velocity = speedup * (offset - ball.velocity)
Ve kodumuzun son hali:
main.py
from kivy.app import App from kivy.uix.widget import Widget from kivy.properties import NumericProperty, ReferenceListProperty,\ ObjectProperty from kivy.vector import Vector from kivy.clock import Clock class PongPaddle(Widget): score = NumericProperty(0) def bounce_ball(self, ball): if self.collide_widget(ball): vx, vy = ball.velocity offset = (ball.center_y - self.center_y) / (self.height / 2) bounced = Vector(-1 * vx, vy) vel = bounced * 1.1 ball.velocity = vel.x, vel.y + offset class PongBall(Widget): velocity_x = NumericProperty(0) velocity_y = NumericProperty(0) velocity = ReferenceListProperty(velocity_x, velocity_y) def move(self): self.pos = Vector(*self.velocity) + self.pos class PongGame(Widget): ball = ObjectProperty(None) player1 = ObjectProperty(None) player2 = ObjectProperty(None) def serve_ball(self, vel=(4, 0)): self.ball.center = self.center self.ball.velocity = vel def update(self, dt): self.ball.move() #bounce of paddles self.player1.bounce_ball(self.ball) self.player2.bounce_ball(self.ball) #bounce ball off bottom or top if (self.ball.y < self.y) or (self.ball.top > self.top): self.ball.velocity_y *= -1 #went of to a side to score point? if self.ball.x < self.x: self.player2.score += 1 self.serve_ball(vel=(4, 0)) if self.ball.x > self.width: self.player1.score += 1 self.serve_ball(vel=(-4, 0)) def on_touch_move(self, touch): if touch.x < self.width / 3: self.player1.center_y = touch.y if touch.x > self.width - self.width / 3: self.player2.center_y = touch.y class PongApp(App): def build(self): game = PongGame() game.serve_ball() Clock.schedule_interval(game.update, 1.0 / 60.0) return game if __name__ == '__main__': PongApp().run()
pong.kv
#:kivy 1.0.9 <PongBall>: size: 50, 50 canvas: Ellipse: pos: self.pos size: self.size <PongPaddle>: size: 25, 200 canvas: Rectangle: pos:self.pos size:self.size <PongGame>: ball: pong_ball player1: player_left player2: player_right canvas: Rectangle: pos: self.center_x-5, 0 size: 10, self.height Label: font_size: 70 center_x: root.width / 4 top: root.top - 50 text: str(root.player1.score) Label: font_size: 70 center_x: root.width * 3 / 4 top: root.top - 50 text: str(root.player2.score) PongBall: id: pong_ball center: self.parent.center PongPaddle: id: player_left x: root.x center_y: root.center_y PongPaddle: id: player_right x: root.width-self.width center_y: root.center_y
Hepsi bu kadar , yeni yazılarda görüşmek üzere...
Hiç yorum yok:
Yorum Gönder