Cart updating

ShopsvgYour cart is currently is empty. You could visit our shop and start shopping.

Now Reading: A Sweet Start to Android Game Development: Build a Cookie Clicker App in Kotlin

Loading

A Sweet Start to Android Game Development: Build a Cookie Clicker App in Kotlin

When learning to create Android apps it’s important to start small so that you understand all of the code and features that you implement. If your a new aspiring Android app developer you’ll want to start off with “Hello World” like projects.

That’s okay and all but it isn’t very fun or exciting. That’s why I created this post so that you can follow along and learn how to create a Android game, natively in Android Studio using the Kotlin programming language.

With the help of ChatGPT we can skip the boring jargon and get straight to the fun stuff. Follow along and create this cute cookie clicker game with us. With ChatGPT, we won’t have to write any of the code ourselves.

Instead, we can focus on the fun parts of creating, playing, testing and improving upon the game.

The Magic ChatGPT Prompt – Kotlin Cookie Clicker Tutorial

Head on over to https://chat.openai.com/ and then enter the following prompt:

Create a simple cookie clicker game in Kotlin on Android Studio with the following features:

1. Incrementing combo counter on each click.

2. Combo counter and cookie image change based on combo count.

3. Bounce animation for the cookie image on click.

4. Animate the cookie image to the total cookies text when combo is a multiple of 50.

5. Decrease combo timer with each multiple of 50 combo.

6. Save the total cookies count in shared preferences.

Create a new empty activity project in Android Studio.

Download the cookie assets below and then copy them into the res/drawable directory.

cookie_assets

.zip

Download ZIP • 179KB

Replace the content of your activity_main.xml file with the following:

<?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/cookieAnimation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <ImageView
        android:id="@+id/cookieImageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@drawable/cookie_asset_1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/comboTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="168dp"
        android:layout_marginBottom="36dp"
        android:fontFamily="@font/press_start_regular"
        android:text="x1"
        android:textColor="@android:color/black"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/cookieImageView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.272"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/totalCookiesTextView"
        app:layout_constraintVertical_bias="1.0" />
    <TextView
        android:id="@+id/totalCookiesTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="60dp"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="60dp"
        android:fontFamily="@font/press_start_regular"
        android:text="Total cookies: 0"
        android:textSize="18sp"
        android:textColor="#FFA500"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/comboTimerTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/comboTextView"
        android:layout_centerHorizontal="true"
        android:layout_marginStart="80dp"
        android:layout_marginTop="27dp"
        android:layout_marginEnd="80dp"
        android:layout_marginBottom="116dp"
        android:fontFamily="@font/press_start_regular"
        android:text="Combo Timer: 0"
        android:textColor="@android:color/white"
        android:textSize="18sp"
        app:layout_constraintBottom_toTopOf="@+id/comboTextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/totalCookiesTextView" />

</androidx.constraintlayout.widget.ConstraintLayout>

Here’s the Kotlin code for the MainActivity class that ChatGPT provided:

import android.animation.*
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Color
import android.os.Bundle
import android.os.CountDownTimer
import android.os.Handler
import android.os.Looper
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import kotlin.math.min
class MainActivity : AppCompatActivity() {
    private lateinit var cookieImageView: ImageView
    private lateinit var comboTextView: TextView
    private lateinit var totalCookiesTextView: TextView
    private lateinit var cookieAnimation: ImageView
    private lateinit var comboTimerTextView: TextView
    private var comboTimerInstance: CountDownTimer? = null
    private var comboCounter = 0
    private var totalCookies = 0
    private var comboTimer = 1500L
    private var comboThreshold = 10
    private val comboColorList = arrayOf(Color.BLACK, Color.RED, Color.parseColor("#FF4500"), Color.parseColor("#FF6347"), Color.parseColor("#FF7F50"))
    private lateinit var sharedPreferences: SharedPreferences
    private val comboTimeoutRunnable = Runnable {
        if (comboCounter >= 50) {
            totalCookies++
            sharedPreferences.edit().putInt("total_cookies", totalCookies).apply()
            updateTotalCookiesText()
        }
        resetCombo()
    }
    private val handler = Handler(Looper.getMainLooper())
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        cookieImageView = findViewById(R.id.cookieImageView)
        comboTextView = findViewById(R.id.comboTextView)
        totalCookiesTextView = findViewById(R.id.totalCookiesTextView)
        cookieAnimation = findViewById(R.id.cookieAnimation)
        cookieAnimation.visibility = View.INVISIBLE
        comboTimerTextView = findViewById(R.id.comboTimerTextView)
        sharedPreferences = getSharedPreferences("cookie_clicker", Context.MODE_PRIVATE)
        totalCookies = sharedPreferences.getInt("total_cookies", 0)
        updateTotalCookiesText()
        cookieImageView.setOnClickListener {
            incrementCombo()
            startComboTimer()
            updateCookieImage()
            bounceAnimation(cookieImageView)
        }
    }
    private fun updateComboTimerText(remainingTime: Long) {
        comboTimerTextView.text = "Combo Timer: $remainingTime ms"
    }
    private fun incrementCombo() {
        comboCounter++
        val scaleFactor = 1f + (comboCounter / 50) * 0.1f
        val colorIndex = min(comboCounter / 50, comboColorList.size - 1)
        comboTextView.text = "x$comboCounter"
        comboTextView.textSize = 24f * scaleFactor
        comboTextView.setTextColor(comboColorList[colorIndex])
        if (comboCounter % 50 == 0) {
            totalCookies++
            sharedPreferences.edit().putInt("total_cookies", totalCookies).apply()
            updateTotalCookiesText()
            animateCookieToTotal()
            decreaseComboTimer()
        }
    }
    // Makes the game harder
    // User must tap faster with each multiple of 50 combo
    private fun decreaseComboTimer() {
        comboTimer = (comboTimer * 0.8).toLong() // Decrease the combo timer by 20%
    }
    private fun resetCombo() {
        comboCounter = 0
        comboThreshold = 10
        comboTimer = 2000L
        comboTextView.text = "x$comboCounter"
        comboTextView.textSize = 24f
        comboTextView.setTextColor(comboColorList[0])
        updateCookieImage()
    }
    private fun bounceAnimation(view: View) {
        val anim = ObjectAnimator.ofPropertyValuesHolder(
            view,
            PropertyValuesHolder.ofFloat(View.SCALE_X, 1f, 1.2f, 1f),
            PropertyValuesHolder.ofFloat(View.SCALE_Y, 1f, 1.2f, 1f)
        )
        anim.duration = 100
        anim.start()
    }
    private fun updateTotalCookiesText() {
        totalCookiesTextView.text = "Total cookies: $totalCookies"
    }
    private fun updateCookieImage() {
        val cookieImageResource = when {
            comboCounter < comboThreshold -> R.drawable.cookie_asset_1
            comboCounter < comboThreshold * 2 -> R.drawable.cookie_asset_2
            comboCounter < comboThreshold * 3 -> R.drawable.cookie_asset_3
            else -> R.drawable.cookie_asset_4
        }
        cookieImageView.setImageResource(cookieImageResource)
    }
    private fun startComboTimer() {
        handler.removeCallbacks(comboTimeoutRunnable) // Cancel the previous timer
        handler.postDelayed(comboTimeoutRunnable, comboTimer) // Start a new timer
        comboTimerInstance?.cancel() // Cancel the previous timer
        comboTimerInstance = object : CountDownTimer(comboTimer, 50) {
            override fun onTick(millisUntilFinished: Long) {
                updateComboTimerText(millisUntilFinished)
            }
            override fun onFinish() {
            }
        }.start()
    }
    private fun animateCookieToTotal() {
        val totalCookiesLocation = IntArray(2)
        val cookieAnimationLocation = IntArray(2)
        totalCookiesTextView.getLocationOnScreen(totalCookiesLocation)
        cookieImageView.getLocationOnScreen(cookieAnimationLocation)
        val xDelta = totalCookiesLocation[0] - cookieAnimationLocation[0]
        val yDelta = totalCookiesLocation[1] - cookieAnimationLocation[1]
        val xAnimator = ObjectAnimator.ofFloat(cookieAnimation, View.TRANSLATION_X, xDelta.toFloat())
        val yAnimator = ObjectAnimator.ofFloat(cookieAnimation, View.TRANSLATION_Y, yDelta.toFloat())
        val alphaAnimator = ObjectAnimator.ofFloat(cookieAnimation, View.ALPHA, 1f, 0f)
        val scaleXAnimator = ObjectAnimator.ofFloat(cookieAnimation, View.SCALE_X, 1f, 0f)
        val scaleYAnimator = ObjectAnimator.ofFloat(cookieAnimation, View.SCALE_Y, 1f, 0f)
        val animatorSet = AnimatorSet().apply {
            playTogether(xAnimator, yAnimator, alphaAnimator, scaleXAnimator, scaleYAnimator)
            duration = 1000
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationStart(animation: Animator) {
                    cookieAnimation.visibility = View.VISIBLE
                    cookieAnimation.setImageResource(R.drawable.cookie_asset_4)
                }
                override fun onAnimationEnd(animation: Animator) {
                    cookieAnimation.visibility = View.INVISIBLE
                    cookieAnimation.alpha = 1f
                    cookieAnimation.scaleX = 1f
                    cookieAnimation.scaleY = 1f
                    cookieAnimation.translationX = 0f
                    cookieAnimation.translationY = 0f
                }
            })
        }
        animatorSet.start()
    }
}

That’s it! Now run the game on your phone or emulator and start tapping to accumulate cookies! Now you can prompt ChatGPT to add more features to the app. Perhaps create a high score system so that you can challenge your friends and show off the app!

If you want to learn more tips, tricks, and strategies to create money making Android Kotlin apps with me and ChatGPT be sure to check out my book “Android App Development for Pirates” and “The ChatGPT Advantage”.

Grab your copy of the books and let’s get started!

Android App Development for Pirates: https://www.amazon.com/Android-App-Development-Pirates-Fun-Loving-ebook/dp/B0C38YK6GK?ref_=ast_author_mpb

The ChatGPT Advantage: https://www.amazon.com/ChatGPT-Advantage-Money-Making-Android-Minutes-ebook/dp/B0BZ17DQNT?ref_=ast_author_dp

svg

What do you think?

Show comments / Leave a comment

Leave a reply

Loading
svg
Quick Navigation
  • 01

    A Sweet Start to Android Game Development: Build a Cookie Clicker App in Kotlin