Kategori:
Python
Başlık:
Python ile Rastgele Hedef Vurma Oyunu

Bir önceki yazımızda Scratch ile rastgele çıkan hedefi vurma oyununun yapılışı ve algoritmasından bahsetmiştik. Bu yazımızda da aynı oyunun Python ile yapılışı üzerinde duracak ve alt kısımda da kaynak dosyaları paylaşacağız. Burada amacımız blok kodlamadan metinsel kodlamaya geçişte adaptasyonunu sağlamaktır. Bunun da somut örnekler üzerinden yapılması gerektiğini düşünüyoruz.

Bu uygulamayı yapmadan önce bilgisayarınızda Python uygulamasının ve Arcade kütüphanesinin yüklü olması gerekmektedir. Arcade kütüphanesinin Windows kurulumu hakkındaki yazımıza buradan ulaşabilirsiniz.

Şimdi sıfırdan başlayarak adım adım uygulamamızı yapalım.

1. Adım: Eclips içinde Python projesi oluşturma:

Bir Python projesi oluştururken IDE dediğimiz programları kullanarak daha hızlı ve organize program yazabiliriz. Python için PyCharm, Visual Studio, Atom gibi IDE seçenekleri mevcut. Buradaki etkinlikte ücretsiz olması ve birçok programlama dilinde kullanılması gibi nedenlerden dolayı Eclipse IDE tercih edildi. Siz istediğiniz programı kullanabilirsiniz. Büyük olasılıkla sorun çıkmayacaktır. 

Öncelikle aşağıdaki ekran görüntüsünde görültüğü gibi yeni bir PyDev projesi açıyoruz.

Daha sonra projemize aşağıdaki ekran görüntüsündeki gibi bir isim veriyoruz.


Bu proje Python 3 ile yapıldı. O yüzden buradaki interpreter seçeneğinin 3.7 olmasına dikkat ediniz. Bu işlem de gerçekleştirildikten sonra Pydev Package Explorer içinde projemiz görünüyor olacaktır.

Burada önce programda kullanacağımız resimler için klasör ve programı yazmak için bir PyDev Module oluşturacağız. Bunu "Rasgele-Hedef-Vurma-Oyunu" yazılan yani projenin adının yazılı olduğu kısma sağ tıklayıp çıkan menüden yapabilirsiniz. Programın klasör yapısını oluşturduktan sonra şöyle gözükecektir:

Oyunun ekran görünüsü aşağıdaki şekildedir:


Programın içeriğine ve  kaynak dosyalarını indirmek için TIKLAYINIZ.

İçeriği indirdikten sonra çıkartıp Eclipse projelerinizin olduğu klasöre kopyalayınız ve Eclipse programında Python projesi olarak tanımlayınınız. Yada kendi oluşturduğunuz Python projesine ekleyebilirsiniz.

Programın kaynak kodu (main.py) ve ilgili açıklamalar aşağıdaki şekildedir:


import arcade   # Hazır nesne özelleiklerinden faydalanmak için arcade kütüphanesini dahil ediyoruz.
import random    # Düşman karakterinin ekranın rastgele bölgesinden belirmesi için dahil ediyoruz.
import os      # Dosya yolunun belirlenmesi için dahil ediyoruz.
import threading   # Eş zamanlı işlem olarak düşman karakterinin belirleme zamanlaması için dahil ediyoruz.
import time

SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 768
SPRITE_SCALING_ENEMY = 0.4       # Düşman karakterinin boyutunun gerçek fotoğrafa göre ölçeklenmesi
SPRITE_SCALING_ENEMY_SHOT = 0.2  # Düşman ateşinin ölçeklenme oranı 
SPRITE_SCALING_TARGET = 0.5      # Hedef işaretçisinin ölçeklenme oranı 

class ArcadeGame(arcade.Window):   # Oyun nesnemiz arcade türünde ArcadeGame nesnesi
 
    def __init__(self, width, height):    # Oyunla ilgili başlangıç değerlerini burada tanımlıyoruz.

        super().__init__(width, height)    # Ekran boyutları ayarı
        file_path = os.path.dirname(os.path.abspath(__file__))   # Resim ve diğer kaynak dosyalara erişim için dosya yolunu belirliyoruz.
        os.chdir(file_path) # Belirlenen dosya yolunu ayarlıyoruz.
        self.enemy_list = None  # Enemy_list adıyla bir sprite dizisi tanımlıyoruz. İçeriği sonra oluşturacağız.
        self.target_list = None # Hedef işaretçisi için belirlediğimiz sprite dizisi
        self.shot_list = None  # Düşmanın ateş etme efekti için belirlenen sprite dizisi
        self.is_enemy_shot = 0  # Düşmanı vurup vurmadığımızın kontrolü için belirlenen değişken. Eğer 0 değer alıyorsa vurulmamıştır değilse vurulmuştur.
        self.hit_time = 0 # Ateş ettiğimiz anı (Fareye tıkladığımız anı) tutan değişken.  Bizim edeceğimiz ateş efektinin gizlenme zamanı için kullanıyoruz.
        self.hit_elapsed_time = 0 # Ateş ettiğimiz zamandan sonra geçemn zamanı tutan değişken. Bizim edeceğimiz ateş efektinin gizlenme zamanı için kullanıyoruz.
        self.enemy_delay = 1 # Düşman karakterinin ekranda kalma süreci için kullanıyoruz.
        self.score = 0 # Puan için kullanıyoruz.
        self.health = 10 # Baştaki sağlık miktarımız 10. 0 olduğunda oyun bitecek.
        arcade.set_background_color(arcade.color.APRICOT) #Arkaplan rengi belirleme. APRICOT yerine başka değerler verebilirsiniz.
 
    def setup(self): # Oyundaki değişken ve karakterler için ayarlamalar burada yapılıyor.
        
        
        self.target_list = arcade.SpriteList()   # Hedef işaretçimiz için belirlediğimiz sprite list    
        self.target_pointer = arcade.Sprite("images/char/target-pointer.png", SPRITE_SCALING_TARGET) # Ateş etmediğimizdeki görüntü
        self.target_pointer_fired = arcade.Sprite("images/char/target-pointer-fired.png", SPRITE_SCALING_TARGET) # Ateş ettiğimizdeki görüntü
        self.target_list.append(self.target_pointer) # target_list için ilk görüntü ateş etmediğimiz halin görüntüsü. Fareye tıkladığımızda değişecek. 
             
        
        self.enemy_list = arcade.SpriteList()    # Düşman karekteri için belirlediğimiz sprite list
        self.enemy_sprite = arcade.Sprite("images/char/enemy-cowboy.png", SPRITE_SCALING_ENEMY) # Düşmanı vurmadığımızdaki görüntü
        self.enemy_died_sprite = arcade.Sprite("images/char/enemy-cowboy-died.png", SPRITE_SCALING_ENEMY)  # Düşmanı vurduğumuzdaki görüntü
        self.enemy_sprite.center_x = 0  # Düşmanın ilk x konumu
        self.enemy_sprite.center_y = 250  # Düşmanın ilk y konumu
        self.enemy_list.append(self.enemy_sprite)  

        
        self.shot_list = arcade.SpriteList() # Düşman ateşi animasyonu için belirlediğimiz sprite list
        self.shot_effect = arcade.Sprite("images/effects/shot_image.png", SPRITE_SCALING_ENEMY_SHOT) # Düşman görüntüsü
        self.shot_effect.center_x = 0 # Düşman ateşinin x konumu
        self.shot_effect.center_y = 250 # Düşman ateşinin y konumu 
        self.shot_list.append(self.shot_effect) # Düşman görüntüsünü sprite liste ekliyoruz.


    def enemy_shot(self):  # Düşman ateşi için belirlediğimiz fonksiyon
        
        if self.is_enemy_shot == 0: # Düşmanı vurmamışsak ateş edecek
            # Ateş efektinin düşman eli üzerinde belirmesi için konum değeri veriyoruz
            self.shot_effect.center_x = self.enemy_sprite.center_x + 38 
            self.shot_effect.center_y = self.enemy_sprite.center_y - 58 
            self.shot_list.append(self.shot_effect)                    
            self.health = self.health - 1  # Ateş ettiğimizde sağlık miktarı 1 azalacak
                 
     
        
    def on_mouse_press(self, x: float, y: float, button, modifiers): # Bizim ateşimiz için belirlediğimiz fonksiyon.


        self.hit_time = time.time() # Ateş efektimizin ekranda kalma süresi için kullanıyoruz.
        
        #Ateş efektimizin ateş işaretçimizle aynı konumda olmasını sağlıyoruz.
        self.target_pointer_fired.center_x = self.target_pointer.center_x
        self.target_pointer_fired.center_y = self.target_pointer.center_y
        

        self.target_list.append(self.target_pointer_fired)
        
        # Hedef işaretçimizin düşman üzerindeki konumlarda iken düşmanı vurabilmek için  bu if bloğunu kullanıyoruz.
        if self.target_pointer.center_x > self.enemy_sprite.center_x - 50  and self.target_pointer.center_x < self.enemy_sprite.center_x + 50 and self.target_pointer.center_y > self.enemy_sprite.center_y - 80 and self.target_pointer.center_y < self.enemy_sprite.center_y + 80:
            self.score += 1
            self.is_enemy_shot = 1 #Düşman vurulmuş olacak böylelikle bize ateş edip canımızı azaltamayacak
            self.enemy_died_sprite.center_x= self.enemy_sprite.center_x
            self.enemy_died_sprite.center_y= self.enemy_sprite.center_y
            self.enemy_list.append(self.enemy_died_sprite)
  
               
    def enemy_move(self): # Düşmanın belirli aralıkla ekranın rastgele bölgelerinden çıkıp bize ateş etmesi için belirlediğimiz fonksiyon
         
        if self.health > 0:   # Canımız varsa bu olaylar gerçekleşecek                   
            enemy_timer = threading.Timer(2, self.enemy_move) # 2 saniyede bir düşmanın hareketini sağlamak için thread kullanıyoruz.
            enemy_timer.start()
            if self.enemy_died_sprite in self.enemy_list: # Düşman vurulup yeniden görünmüşse vurulma görüntüsünü kaldırıyoruz.
                self.enemy_list.remove(self.enemy_died_sprite)                     
            self.enemy_delay = 1 # Düşmanın ekranda görülme süresi dolmuşsa farklı bir yerden görülmesi için kullanıyoruz.
            enemy_shot_timer= threading.Timer (1.2, self.enemy_shot) # Düşman ateşi için düşman göründükten 1.2 saniye sonra enemy_shot fonksiyonunu çağırıyoruz
            enemy_shot_timer.start() 
            self.is_enemy_shot = 0  # Düşmanı vurulmamış olarak ayarlıyoruz   
        
        if self.enemy_delay == 1: # Düşmanın belirlenen süre (2 saniye) dolduğunda yeniden farklı bir yerde görünmesini sağlar
            self.enemy_sprite.center_x = random.randrange(SCREEN_WIDTH)
            self.enemy_sprite.center_y = random.randrange(100, SCREEN_HEIGHT)
            self.enemy_delay = 0 
            self.shot_effect.kill() # Yeniden görünmede düşman ateşi efektini kaldırıyoruz. 
             
    
       
    def on_draw(self):
        
        
        arcade.start_render() # Diğer bütün çizimlerin yapılabilmesi için öncelikle bu komutla render işlemi başlatılmalı

        # Bütün  şekiller çizdiriliyor
        self.enemy_list.draw()
        self.target_list.draw()
        self.shot_list.draw()
        
                # Skor, sağlık durumu başlıkları ve değişken değerleri ekrana yazdırılıyor.
        output = f"Score: {self.score}"
        health_info = f"Health: {self.health}"
        arcade.draw_text(output, 10, 20, arcade.color.ANTIQUE_RUBY, 14)
        arcade.draw_text(health_info, 10, 40, arcade.color.ALABAMA_CRIMSON, 14)
        
        
        if self.health <= 0: # Sağlık bitmişse GAME OVER yazısı ekranda yazdırılıyor.
            arcade.draw_text("GAME
 OVER", 410, 384, arcade.color.BISTRE_BROWN, 50)
                
    
    def on_mouse_motion(self, x:float, y:float, dx:float, dy:float): # Hedef işaretçisinin sürekli fare imleci pozisyonunda olması için fonksiyon tanımlandı
        
        
        self.target_pointer.center_x = x
        self.target_pointer.center_y = y
        
        self.target_pointer_fired.center_x = x
        self.target_pointer_fired.center_y = y
        
        
    
    def update(self,delta_time): # Anlık güncelleme ve oyunun akışıyla ilgili yapı burada oluşturuluyor.        
       
        self.enemy_list.update()
        self.shot_list.update()
        self.target_list.update()
        
        
        self.hit_elapsed_time = time.time()-self.hit_time # Bizim ateş ettiğimizde hedef işaretçisinde ateş animasyonunun kalma süresi için tanımlandı

        if self.hit_elapsed_time > 0.1: # Bizim ateşimizin ekranda kalma süresi 0.1 saniye
            self.target_pointer_fired.kill()
          
              
        if self.enemy_delay == 1: # enemy_delay değeri 1 olduğunda enemy_move fonksiyonu çalışarak düşman farklı bir konumda tekrar görünür
            self.enemy_move()
          
          
        if self.health <= 0: # Sağlık bittiğinde ekrandaki bütün görüntüler kaldırılır
            self.health = 0  # Sağlık değerinin eksiye düşmemesi için sürekli 0 olarak belirlenir
            self.enemy_sprite.kill()
            self.shot_effect.kill()
            self.target_pointer.kill()
                   

def main(): # Ana fonksiyonumuzla oluşturduğumuz oyun nesnesini çalıştırıyoruz
    game = ArcadeGame(SCREEN_WIDTH, SCREEN_HEIGHT)
    game.setup()
    arcade.run()

if __name__ == "__main__":
    main()

615 views
YORUMLAR