A.I, Data and Software Engineering

Break your nails with TIMER BOMB DEFUSAL game

B

Are you fast and durable enough to defuse a deadly bomb? Let try to create the bomb defusal game with Android Studio and Kotlin! Video tutorial is at the end of the post.

The mechanic

Players need to click as fast as they can to beat the speed of the timer bomb. When the progress goes down to 0, the bomb will be disabled. In contrast, if it reaches the full bar, the bomb will explode, and it will be a very sad day for the player.

The UI

It is a simple design with 3 widgets:

  • An image view
  • A progress bar
  • A start button

The XML should look similar to this:

<?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/image"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:src="@drawable/ic_bomb"
        app:layout_constraintBottom_toTopOf="@+id/progress"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <ProgressBar
        android:id="@+id/progress"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:indeterminate="false"
        android:max="100"
        android:padding="20dp"
        android:progress="0"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.82" />
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start"
        android:onClick="start"
        android:background="@drawable/btn"
        android:textColor="#FFFFFF"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progress" />
</androidx.constraintlayout.widget.ConstraintLayout>

The background music

This is optional. However, games should always include music. We will create a flexible service that can change music based on the resource id. The media player is preferable to play longer music files.

//Kotlin Implementation
class BackgroundSoundService : Service() {
    var mediaPlayer: MediaPlayer? = null
    var soundID: Int = R.raw.grasshopper
    override fun onBind(intent: Intent): IBinder? {
        return null
    }
    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        soundID = intent.getIntExtra("id", R.raw.grasshopper)
        mediaPlayer = MediaPlayer.create(this, this.soundID)
        mediaPlayer!!.isLooping = false // Set looping
        mediaPlayer!!.setVolume(100f, 100f)
        mediaPlayer!!.start()
        return startId
    }
    override fun onDestroy() {
        mediaPlayer!!.stop()
        mediaPlayer!!.release()
    }
}

Progressbar Animation

We animate the progress bar when players start the game. And change the colour from Green to Red using a RGB colour filter. The colour will vary based on the value of the current progress.

class ProgressBarAnimation(
    private val progressBar: ProgressBar,
    var from: Float,
    private val to: Float
) : Animation() {
    override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
        super.applyTransformation(interpolatedTime, t)
        val value = from + (to - from)*interpolatedTime
        progressBar.progress = value.toInt()
        progressBar.progressDrawable.colorFilter = LightingColorFilter(
            Color.rgb(255 * progressBar.progress/progressBar.max,
            255 - 255*progressBar.progress/progressBar.max,
            0), Color.BLACK
        )
    }
}

The main activity

We wire up all logics to this class. It should be able to handle the progress bar and also user click. Therefore, we implement two interfaces, i.e, AnimationListener, View.OnClickListener.

class MainActivity : AppCompatActivity(), AnimationListener, View.OnClickListener { ... }

Don’t forget to register the listener to corresponding component. For example, we can register the bomb or the parent view to receive the click and the progresss bar to monitor the animation.

We may need to consider the reset method to put everything in their initial state.

private fun reset() {
    startMusic(R.raw.grasshopper)
    image.setImageResource(R.drawable.ic_bomb)
    progress.setScaleY(3f);
    progress.progress = 0
    anim = ProgressBarAnimation(progress, 0f, 100f)
    anim.setAnimationListener(this)
    anim.duration = 2000
    button.isEnabled = true
}

Nevertheless, the most important part is how to control user interaction, especially when they click the bomb continuously. We need to reduce the progress by some value and update the animation accordingly.

override fun onClick(p0: View?) {
    progress.progress -= 1
    if (progress.progress <= 0) {
        progress.clearAnimation()
    } else {
        anim.from = progress.progress.toFloat()
        progress.startAnimation(anim)
    }
}

Finally, we can make the decision when animation finished, i.e, when the progress reach 0 or full bar.

override fun onAnimationEnd(p0: Animation?) {
    if (progress.progress == progress.max) {
        Toast.makeText(this, "OMG! You did it!", Toast.LENGTH_LONG).show()
        image.setImageResource(R.drawable.ic_explode)
        startMusic(R.raw.explosion_1)
        progress.setOnClickListener(null)
    } else {
        Toast.makeText(this, "Woohoo! You finished it!", Toast.LENGTH_LONG).show()
        image.setImageResource(R.drawable.ic_melon)
        startMusic(R.raw.wow)
    }
    Handler().postDelayed({reset()}, 10000)
}

Video tutorial

Enjoy the 10 minute video tutorial for the bomb defusal game implementation.

Other useful links

Add comment

💬

A.I, Data and Software Engineering

PetaMinds focuses on developing the coolest topics in data science, A.I, and programming, and make them so digestible for everyone to learn and create amazing applications in a short time.

Categories