Creating a Simple 2D Game in Android Using Kotlin and Coroutines

Chirag Vasani
4 min readJan 30, 2024

--

In this tutorial, we’ll create a basic 2D game for Android using Kotlin and coroutines. Our game will feature a bouncing ball that moves around the screen. This example will help you understand the fundamentals of game development on the Android platform.

Setting Up the Project

  1. Open Android Studio and create a new Android project with an Empty Activity.
  2. Set the language to Kotlin.

Creating the GameView

We’ll start by creating a custom SurfaceView to handle the game rendering. This class will be responsible for drawing the ball and updating its position.

// GameView.kt

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.view.SurfaceHolder
import android.view.SurfaceView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlin.random.Random

class GameView(context: Context) : SurfaceView(context), SurfaceHolder.Callback {

private var thread: GameThread? = null
private var ballX: Float = 100f
private var ballY: Float = 100f
private var ballRadius: Float = 30f
private var speedX: Float = 5f
private var speedY: Float = 5f

init {
holder.addCallback(this)
}

override fun surfaceCreated(holder: SurfaceHolder) {
thread = GameThread(holder, this)
thread?.start()
}

override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}

override fun surfaceDestroyed(holder: SurfaceHolder) {
var retry = true
while (retry) {
try {
thread?.join()
retry = false
} catch (e: InterruptedException) {
// Retry
}
}
}

fun resumeGame() {
thread?.running = true
}

fun pauseGame() {
thread?.running = false
}

fun update() {
ballX += speedX
ballY += speedY

// Bounce the ball when it hits the screen edges
if (ballX - ballRadius < 0 || ballX + ballRadius > width) {
speedX = -speedX
}

if (ballY - ballRadius < 0 || ballY + ballRadius > height) {
speedY = -speedY
}
}

override fun draw(canvas: Canvas) {
super.draw(canvas)
canvas.drawColor(Color.BLACK)
val paint = Paint()
paint.color = Color.WHITE
canvas.drawCircle(ballX, ballY, ballRadius, paint)
}
}

Creating the GameThread

Next, we’ll create a separate thread to handle the game loop. This thread will continuously update the game state and redraw the screen.

// GameThread.kt

import android.graphics.Canvas
import android.view.SurfaceHolder

class GameThread(private val surfaceHolder: SurfaceHolder, private val gameView: GameView) : Thread() {

var running = false

override fun run() {
while (running) {
val canvas: Canvas? = surfaceHolder.lockCanvas()
if (canvas != null) {
gameView.update()
gameView.draw(canvas)
surfaceHolder.unlockCanvasAndPost(canvas)
}

try {
sleep(16) // Adjust frame rate as needed
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
}
}

Integrating the GameView into MainActivity

Finally, we’ll integrate our GameView into the MainActivity.

// MainActivity.kt

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

private lateinit var gameView: GameView

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
gameView = GameView(this)
setContentView(gameView)
}

override fun onResume() {
super.onResume()
gameView.resumeGame()
}

override fun onPause() {
super.onPause()
gameView.pauseGame()
}
}

Conclusion

In this tutorial, we’ve created a simple 2D game for Android using Kotlin and coroutines. This example introduces you to the basic concepts of game development on the Android platform. Feel free to expand on this example by adding more features, improving graphics, or implementing additional game mechanics. Happy coding!

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -

Certainly! The above example is a simple demonstration of a bouncing ball game. Here are the key features of the game:

  1. Bouncing Ball: The game features a ball that moves around the screen.
  2. Screen Bouncing: When the ball reaches the edges of the screen, it “bounces” back in the opposite direction. This gives the illusion of the ball bouncing off the screen boundaries.
  3. Custom SurfaceView: The game rendering is handled by a custom SurfaceView called GameView. This view is responsible for drawing the ball on the canvas.
  4. Game Loop: The game loop is implemented in a separate thread (GameThread). This loop continuously updates the game state (e.g., ball position) and redraws the screen.
  5. Coroutines: While coroutines are imported and used in the GameView class, they are not explicitly utilized in this simple example. Coroutines could be used for handling more complex asynchronous tasks in a larger game.

The main components are the GameView, GameThread, and MainActivity. The GameView handles the drawing of the ball and contains the game logic, while the GameThread manages the game loop. The MainActivity sets up and manages the GameView.

This is a very basic example meant for educational purposes. In a real-world scenario, you would expand on this foundation by adding more features, such as user input for controlling the ball, multiple bouncing objects, scoring mechanisms, and possibly more complex game physics.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Android Demos : Click here.

--

--

Chirag Vasani

Passionate Android Developer Creating Seamless User Experiences