Classic Snake Game with Jetpack Compose.

In this post we will build a small clone of the classic snake game using Jetpack Compose. We will focus on the building the game loop and manage the state of the game and draw the basic shapes on the screen. We will not be managing the menus, high scores, etc… how ever these are implemented on my GitHub repo attached to the end of the post.

Possible Snake Movements

The classic snake could only move in a 4 directions so we will create an object class that will have the different directions the snake could move likewise.

State

Let’s start by create the main data class that will hold the state of the game.

  • food — will hold the x and y coordinates of the food.
  • snake — will hold a list of the x and y coordinates of all the snake body parts
  • currentDirection — will hold the direction in which the snake is moving.

Game Engine

Next we will create our game engine.

Let’s start by creating a class called GameEngine and declare a mutableState that will hold the State object we created in the previous step as that is the single source of truth. Which would then be managed using the flow API.

Next let’s define another variable to keep the direction of the snakes movement and we would require a CoroutineScope to make this movement endless.

Now when our engine is created we want to immediately start the game play. Let’s use the init method the make sure the game starts immediately and play for us to be able to play the game endlessly we would need CoroutineScope to avoid clogging the main thread. We will also create two lambda functions what would act like listeners to relay back whether the game has ended or the food has been eaten.

Inside our scope is where the real magic happens. We will be maintaining the size of the snake, generating new location for the food and checking for collision with the edges or with itself. The code would look like this.

The snakeLength variable is responsible for maintaining the length of the snake. We run a while loop with a delay because we want the code in the loop to keep repeating itself after a small delay which is 150 in this case. Now since our source of truth is the mutableState. We just need to update the State values and we are good to go. We do this by calling mutableState.update{} we will calculate the value of the new food location and check if the game has ended or not. We first check if the snake has reached the end of the screen. We do this by getting the location of the snake head by calling it.snake.first() and then checking if the direction is still left. We do the same for all for all the four sides. If any of the 4 conditions come back as true we call the onGameEnded function and reset the size of the snake.

Next let’s check the direction the snake is heading in. We do this with the below code.

Then we calculate the newPosition of the snake. We can simply do this by calculating the position of the head and adding block size to it.

We then need to check if the if the newPosition contains the snake or food. If it contains the food we need to invoke onFoodEaten and increase the size of the snake. If the newPosition contains the snake then we call onGameEnded and reset the snake size. Lastly we update the game state by calling the below and updating the new values so our engine has up to date values to work with.

Next let’s create a new method to reset the game engine when something wrong happens or when we need to restart the game. We can do this likewise.

Now that our game engine is ready. Let’s build the UI for our Game Engine to work with.

D-PAD

Let’s create a new composable that will simply hold the four directional key and will trigger and event based of the key pressed.

AppIconButton is just a simply Composable I created to avoid the boilerplate code for the asthetics of the game.

Board

Now let’s the create the board that will draw the edges, food and the snake.

The board will the game state as a parameter to draw the up to date state of the game. Let’s draw the edges first

Now let’s the draw the food for the snake.

Lastly let’s draw the snake body. We will loop through the snake and draw each block.

Now that we have the Board, Controller and the GameEngine. let’s put them all together in a single activity to make them work efficiently.

The Game Activity

Let’s start by declaring a few variables in out activity.

Now in the onCreate we will render the UI of the game and assign the game engine to the board and update the gameEngine when someone clicks on the dpad.

And there you have it a fully functional classic snake game using Jetpack compose. You can check the complete game with menu and high score from the repo below.

Thanks for reading, if you have my articles feel free to subscribe to my newsletter or share the article.