Flutter ile Aim Master Oyunu yapalım

Kadir Bekar
Flutter Türkiye
Published in
5 min readDec 27, 2020

Selamlar. Animasyonlar konusuna göz atarken kodu kendimce daha eğlenceli hale getirebilmek için ufak bir oyun senaryosu oluşturdum. Bu yöntem akıcı bir şekilde projeyi çıkarmama sebep oldu. Sizlere de tavsiye ederim.

Proje içerisinde birbirinden farklı yapıları işleyeceğimiz için faydalı olacağını düşünüyorum. Lafı fazla uzatmadan hemen konuya geçmek istiyorum.

Projede kullanılan farklı konu başlıkları:

1- Get paketi ile tema değişimi, navigasyon

2- Get Storage paketi ile yerel hafızaya veri kayıt etme, okuma(key, value)

3- Timer kullanımı

4- Animasyon kullanımı

Yazıya ihtiyaç duymadan Github üzerinde projeyi görüntülemek için bu linke tıklayabilirsiniz.

Projemi oluşturmak için terminal ekranımı açıyorum, kayıt etmek istediğim dizine gidip flutter create aim_master yazarak enter’a basıyorum.

Uygulamada kullanacağım resmi ve fontu assets klasörüne ekliyorum, kullanılan paketleri ise dependencies tagı altına soldan 2 boşluk bırakacak şeklide ekliyorum ve terminale flutter pub get komutunu yazıp çalıştırıyorum.

Uygulamada kullanılan paketler:

Uygulamayı ilk açtığımızda bizi karşılayan ekranın resmini ekliyorum, sonrasında ise sayfada yapılan işlemleri anlatacağım.

Tema değiştirme işleminden başlayalım. Sırasıyla yapacaklarımız;

1- libcorecontrollertheme_controller.dart şeklinde klasörlerimi ve dosyamı oluşturuyorum. Oluşturduğum class GetxController sınıfını miras alıyor bu sayede burada yaptığım bir değişikliği başka dosyalarda oluşturduğum aynı controller nesnesi ile dinleyebilirim.

2- Get Storage key, value şeklinde çalışan bir yapı. Tema değerini kayıt etmek için key değerim olarak bir constant tanımlıyorum. Yerel hafızadan temanın güncel değerine ulaşmak istediğimde bu unique değeri vermem yeterli olacaktır. Kayıt etmek istediğim value değerini ise parametre olarak metoda gönderiyorum. Kayıt işlemi sonunda update(); metodunu çağırıp, bu değeri dinleyen yerlere kayıt ettiğim değerin güncel halini bildiriyorum.

3- Tema değişikliği yapmak istediğim sayfada en üstte bulunan widgetimi GetBuilder ile sarmalayıp oluşturduğum ThemeController classımı generic type olarak veriyorum. En üstte oluşturma sebebim scope dahilinde isteğim herhangi bir yerden kolay bir şekilde erişim sağlayabilmek.

4- IconButton (tema değiştirme butonum) widgetim altında yaptığım işlemler sırası ile;

  • Güncel tema değerine göre farklı tema değiştir iconu ekrana koymak
  • Tema değişimi sırasında yerel hafızaya daha önce kayıt ettiğim bool değerin alınması, yeni değer olarak tam tersinin verilmesi. (true = DarkTheme, false = LightTheme)
  • Get.changeTheme metoduna verilen parametreye göre temanın çok kolay bir şekilde değiştirilmesi

5- main.dart sayfasında uygulama henüz başlatılmadan main fonksiyonu içerisinde öncelikle yerel hafızayı başlatıyoruz. Daha önceden bir tema değişikliği yoksa false değeri atıyoruz var ise güncel değeri alıp theme değerine atamasını yapıyoruz.

Şimdi ise navigasyon işlemlerinde neler yaptık ona bakalım;

1- Yukarıdaki kodda 21. satırda görüldüğü gibi, uygulamada kullandığım sayfaları bir class altında oluşturup getPages propertisine parametre olarak verdim.

2- Başlangıç sayfam olarak HomePage widgetimi atadım.

MaterialApp widgeti yerine neden GetMaterialApp widgeti kullanıyoruz sorusunu cevaplayalım. Get paketini sadece state management, dependency injection için kullanmak istediğimizde MaterialApp bizim ihtiyacımızı karşılayacaktır fakat get paketi içerisinde birçok yapıyı barındırıyor. En basitinden örnek vermek gerekirse context’e ihtiyaç duymadan yapılan navigasyon işlemleri (Get.to(HomePage())), dil değişimi, SnackBar gösterimi ve birçok diğer güzel özelliği kullanmak istediğimizde GetMaterialApp widgetini uygulamanın en üst widgeti ile sarmalamamız gerekiyor.

Uygulamada kullandığımız HomePage sayfasından GamePage sayfasına geçiş yapmak istediğimizde kullandığımız kod → Get.off(GamePage());

Evet bu kadar az ve temiz bir kodla çok kolay bir şekilde sayfa değişikliği yapabiliyoruz. Get.off kısaca Navigation.pushReplacement() yerine kullanılıyor. Bir önceki sayfayı stack yapısından silip geri gitmeyi engelliyor. Genellikle login sayfasında başarılı bir işlem olunca yönlendirme yaptığımız anasayfa veya splash sayfasından bir sonraki sayfaya yönlendirme yaptığımız durumlarda kullanılan metot.

GamePage sayfasından HomePage sayfasına geçişte ise kullandığımız kod → Get.offAll(HomePage());

Get.offAll() metodu ise Navigation.pushAndRemoveUntil() yerine kullanılıyor. Uygulamanın stack yapısında bulunan bütün sayfaları siliyor.

Kullanıcı adını yazmadan oyunu başlatmaya kalkarsa SnackBar gösterimi için kullandığımız kod;

it shows SnackBar at the bottom of the page

Paketin diğer özelliklerini detaylıca öğrenmek için paketi incelemenizi tavsiye ederim.

Şimdi biraz da uygulamanın nasıl çalıştığını anlatmak istiyorum.

home_page.dart

Oyunumuz için öncelikle bir kullanıcı adı giriyoruz sonrasında ise Slider widgeti ile oynamak istediğimiz süreyi(saniye) seçiyoruz. Son olarak ise bir level seçip oyunumuzu başlatıyoruz. Seçilen level bize ekranda hareket eden hedefin ne kadar hızlı veya yavaş hareket ettiğini temsil ediyor. HomePage için örnek kodlarımı ekliyorum.

home_page.dart

Start butonuna bastık ve game_page.dart sayfasına yönlendirildik.

game_page.dart

Start butonuna bastığımızda seçtiğimiz süre ve levele göre ekrandaki hedefimiz hareket edecektir. Hedefe her tıkladığımızda bir puan kazanacağız. İşleri bir tık zorlaştırmak için ise oyun başladığı zaman sağ alt tarafta bulunan start butonu, stop butonu ile yer değiştirecektir. Süre bitmeden bu butona yanlışlıkla basarsak oyun sonlanacaktır.

Ekranda hareket eden widgetim AnimatedContainer widgetidir. Bu widgeti kullanma sebebim ise start butonuna bastığımda oluşturduğum timer nesnemin içerisine hedefimin renk, border radius gibi değerlerlerini tanımlamam, her saniye farklı bir görüntü vermek istememdir.

Oluşturduğum hedef widgetini ise Stack widgeti içerisine tanımladığım Positioned widgetine child widget olarak veriyorum. Stack kullanma sebebim her saniye hedef değiştirecek olan hedefimin rastgele aldığı Alignment değerini Stack widgetinde bulunan alignment propertisine vermek istemem bu sayede her saniye farklı bir konuma rastgele hedefimi taşıyabiliyorum.

Hedefimin oyun süresince ekranın farklı bir yerinde olmasını sağlamak için List<AlignmentGeometry> positions diye bir liste oluşturuyorum. Bütün hizalama özelliklerini bu listeye initState içerisinde dolduruyorum. Oyun başladığında bu listeden her saniye rastgele bir position değeri seçip bunu yukarıda belirttiğim gibi Stack widgeti içerisindeki alignment propertisine atıyorum. Hedefimin her saniye ekranda hareket etmesini sağlamak için ise AnimationController ve Animation classlarından faydalanıyorum.

Son olarak ise oyunun bitiş süresini takip edebilmek için Timer.periodic metodunu kullanıyorum. Geçen her saniye için süreyi bir bir azaltıp AppBar widgetine koyduğum süre text widgetine bu değişkeni veriyorum. Süre bittiği zaman skor tablosunu ekranda gösteriyorum, timer ve animasyon nesnelerimi dispose ediyorum. Burada önemli olan diğer bir konu ise skor gösterildiği zaman geri tuşuna basıp oyunu manipüle ettirmemek için alert dialog çıktığı zaman geri tuşunu WillPopScope sayesinde pasif duruma getiriyorum.

Dilerseniz game_page.dart sayfasındaki kodları ekleyelim.

Umarım faydalı bir içerik olmuştur. Herhangi bir geri bildirimde bulunursanız çok memnun olurum, iyi kodlamalar dilerim :)

--

--