Android Uygulama Geliştirmek #2 Oyun Yapmak

Ego1st

Uzman üye
15 Mar 2018
1,109
25
Android Uygulama Yapmak 2. Bölüm

Selam THT Ailesi bu gün Android Uygulama Geliştirmenin 2. bölümündeyiz. Başlamadan önce Android ve Kotlin tarafındaki yeniliklerden bashetmek istiyorum.

rNH656.png


Neler Oldu?

Android Studio 4.1 geldi. Bu büyük güncellemeyle beraber, geliştiriciler tarafından çokça istenen SQL veritabanı görüntüleyicisi getirildi. Artık veritabanlarını görüntüleyebiliyoruz.

database-inspector.gif


Emülatör (Sanal Cihaz)'ı direkt olarak Android Studio içerisinden çalıştırma özelliği geldi. Artık emülatör ikinci bir AVD penceresi açılmadan direkt olarak Android Studio'nun içinde çalıştırabiliyoruz.

emulator-tool-window.gif


Bunun gibi bir sürü özelliğin yanında ek olarak, hatalar ve çökmeler giderildi.

Android 11 güncellemeleri de geldi fakat bunlardan pek bahsetmeyeceğim, geliştirme sürecimizi pek fazla etkileyen bir şey olmadı.

Yeniliklerden kısaca bashettik, şimdi isterseniz 2. uygulamamıza geçelim.

Bu bölümde aslında küçük bir oyun yapacağız ama yine yine bu oyunu yaparken bir sürü teknik öğreneceğiz.

Öncelikle yeni bir proje açalım.



Empty Activity dedikten sonra proje ayarları ekranı geliyor, buna tekrardan deyinmeyeceğim 1. bölüm oldukça detaylı anlatmıştım. Ayarlarımızı yaptıktan sonra Finish diyelim.



Kodlamaya geçmeden önce oyunumuzun genel mantığını anlatayım. Bir karakterimiz olacak, ekranda sürekli olarak yeri değişecek ve biz de onu yakalamaya çalışacağız, her yakaladığımızda 1 puan gelecek ve 15 saniyede bir game over olacak.

Öncelikle internetten sevdiğimiz bir karakterin resmini bulup indirelim. Resim dosyasının çok büyük olmamasına dikkat edin, büyük dosyalarda Android Studio hata veriyor.

Örnek olarak ben,

Zero.gif


bu karakteri seçtim.

Şimdi indirdiğimiz dosyanın adını özel karakter, büyük harf ve sayılarda arındıralım, yoksa Android Studio kabul etmiyor. Ben zero yaptım.

Şimdi dosyamıza CTRL+C yaptıktan sonra Android Studio'da res klasörünün altında drawable'ın altına yapıştıralım.



Burada da görüldüğü gibi drawable v24 değil drawable'ın altına atmamız lazım.

Ok dedikten sonra resim ismi soruyor normalse ne ala, yoksa düzeltelim. Daha sonra refactor diyelim ve resmimiz geldi. Şimdi aşağıdaki kodları activity_main.xml dosyasının altına yapıştıralım.

Kod:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:visibility="invisible"

        android:layout_marginLeft="16dp"
        android:layout_marginTop="15dp"
        app:layout_constraintEnd_toStartOf="@+id/imageView2"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView2"
        app:srcCompat="@drawable/zero" />
    
    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="1dp"
        android:visibility="invisible"

        android:layout_marginRight="1dp"
        app:layout_constraintEnd_toStartOf="@+id/imageView3"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        app:srcCompat="@drawable/zero" />
    
    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:visibility="invisible"
        android:layout_marginRight="16dp"
        app:layout_constraintBottom_toBottomOf="@+id/imageView2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/imageView2"
        app:layout_constraintTop_toTopOf="@+id/imageView2"
        app:srcCompat="@drawable/zero" />

    <ImageView
        android:id="@+id/imageView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:visibility="invisible"

        android:layout_marginLeft="16dp"
        android:layout_marginTop="41dp"
        app:layout_constraintEnd_toStartOf="@+id/imageView5"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        app:srcCompat="@drawable/zero" />

    <ImageView
        android:id="@+id/imageView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="1dp"
        android:layout_marginRight="1dp"
        android:visibility="invisible"

        app:layout_constraintEnd_toStartOf="@+id/imageView6"
        app:layout_constraintStart_toEndOf="@+id/imageView4"
        app:layout_constraintTop_toTopOf="@+id/imageView4"
        app:srcCompat="@drawable/zero" />


    <ImageView
        android:id="@+id/imageView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="41dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:visibility="invisible"

        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/imageView5"
        app:layout_constraintTop_toBottomOf="@+id/imageView3"
        app:srcCompat="@drawable/zero" />

    <ImageView
        android:id="@+id/imageView7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:visibility="invisible"

        android:layout_marginTop="46dp"
        app:layout_constraintEnd_toStartOf="@+id/imageView8"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView4"
        app:srcCompat="@drawable/zero" />
    
    
    <ImageView
        android:id="@+id/imageView8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="1dp"
        android:visibility="invisible"

        android:layout_marginRight="1dp"
        app:layout_constraintEnd_toStartOf="@+id/imageView9"
        app:layout_constraintStart_toEndOf="@+id/imageView7"
        app:layout_constraintTop_toTopOf="@+id/imageView7"
        app:srcCompat="@drawable/zero" />
    
    

    <ImageView
        android:id="@+id/imageView9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:visibility="invisible"

        android:layout_marginRight="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/imageView8"
        app:layout_constraintTop_toTopOf="@+id/imageView8"
        app:srcCompat="@drawable/zero" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:text="Kalan Zaman:"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="13dp"
        android:text="Skor:"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>

Şimdi burada karakterimizin resmine sahip olan ve INVISIBLE yani görünmez olan 9 tane Image View'ımız ve 2 tane Text View'ımız var bunlar kalan zaman ve skor değerlerini tutmak için.

Kodlamaya başlayalım, öncelikle ilk başta sınıfın altında activity'nin üstünde kullanacağımız şeyleri tanımlayalım.

Kod:
var skor = 0
var dizi = ArrayList<ImageView>()
var handler = Handler()
var runnable = Runnable {}

skor, tahmin edebileceğiniz üzere skorları tutmak için. ImageView dizisi image'leri tutmak ve teker teker göstermek için. Handler ve Runnable ise sayacı yapmak ve skoru arttırmak için, şu an ne olduğuna girmiyorum sadece görelim.

Kod:
dizi.add(imageView)
dizi.add(imageView2)
dizi.add(imageView3)
dizi.add(imageView4)
dizi.add(imageView5)
dizi.add(imageView6)
dizi.add(imageView7)
dizi.add(imageView8)
dizi.add(imageView9)


Array List'imize ImageView'larımızı ekledik. Şimdi, sınıfın içinde hideImages isimli bir fonksiyon oluşturalım.

Kod:
fun hideImages() {

        runnable = Runnable {
            override fun run() {
                for (image in imageArray) {
                    image.visibility = View.INVISIBLE
                }

                val random = Random()
                val randomIndex = random.nextInt(9)
                imageArray[randomIndex].visibility = View.VISIBLE

                handler.postDelayed(runnable,500)
            }

        }

        handler.post(runnable)

    }

Gördüğünüz gibi butun Image'ları gizleyip, Random olarak seçtiğimiz bir tanesini görünür hale getirdik. Ve bunu 500 milisaniye delaylı (gecikmeli) bir şekilde yaptık.

Daha sonra aktivitemizin altında bu fonksiyonu çağıralım.

Kod:
hideImages()

Bir tane de increaseScore adlı fonksiyon oluşturalım, bunu skoru arttırmak için kullanacağız.

Kod:
 fun increaseScore(view: View){
        skor += 1
        textView2.text = "Skor: $skor"

    }

Bu şekilde yazdık, skorun değerini 1 arttırıp daha sonra textView'daki değeri de skor değişkenimiz yaptık.

Şimdi sayacımızı yazalım.

Kod:
object : CountDownTimer(16500,1000){
            override fun onFinish() {

                textView.text = "Kalan Zaman: 0"

                handler.removeCallbacks(runnable)

                for (image in dizi) {
                    image.visibility = View.INVISIBLE
                }

                val alert = AlertDialog.Builder(this@MainActivity)

                alert.setTitle("Oyun Bitti")
                alert.setMessage("Yeniden Başla?")
                alert.setPositiveButton("Evet") { _, _ ->
                    val intent = intent
                    finish()
                    startActivity(intent)
                }

                alert.setNegativeButton("Hayır") { _, _ ->
                    Toast.makeText(this@MainActivity,"Oyun Bitti", Toast.LENGTH_LONG).show()
                }

                alert.show()

            }

            override fun onTick(millisUntilFinished: Long) {
                textView.text = "Kalan Zaman: " + millisUntilFinished/1000
            }

        }.start()

CountDownTimer Nedir?

CountDownTimer iki tane değer -toplam süre ve işlemler bittiğinde beklenecek süre- olmak üzere iki tane basit değerle çalışan bir sınıftır. Her verdiğimiz milisaniye geçtiğinde onTick fonksiyonu çalışır, bittiğinde ise onFinish() çalışır.

CountDownTimer'ı eklediğimizde iki tane override fonksiyon geliyor. Biri onTick diğeri onFinish

onTick'te sadece kalan zamanı milisaniye olduğu için 1000'e bölüp textview'da gösteriyoruz.

onFinish'te sırasıyla, kalan zamanı 0 yapıyoruz, bütün imageviewlarımızı for döngüsü yardımıyla görünmez hale getiriyoruz. Ve daha sonra bir alert dialog koyuyoruz.

Alet Dialog Nedir?

Alert Dialog, Android'in kullanıcılara uyarı vermek amaçlı geliştirdiği bir açılan penceredir. Burada negative (olumsuz -) ve positive (olumlu +) butonlarla işlemler yapabiliriz.

Bu alert dialog Oyun Bitti Yeniden başlamak ister misin diye soruyor. Evet dersek aktiviteyi Intent yardımıyla yeniden başlatıyor, hayır dersek Toast Message gösterip bırakıyor.

Kodlarımız bu kadar son olarak bütün Image View'ların On Clicklerine increaseScore demeyi unutmayalım çünkü tıklandığında skorun artmasını istiyoruz.

Evet kodlarımız bu kadardı.

Bu gün neler öğrendik?

+Handler ve Runnable Kullanımını
+ArrayList ve For Döngüsünün Etkili Bir Şekilde Kullanılmasını
+CountDownTimer Kullanımını ve
+Alert Dialog Kullanımını öğrendik.

Uygulama İçi Ekran Görüntüleri





Sağlıcakla kalın :))

 
Son düzenleme:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.