Building a Math Game App
The course is part of this learning path
This is a highly practical course that walks you through how to create a simple math game for school children on Android. We will make use of the Kotlin components that we covered in the Android App Development with Kotlin learning path, bringing them all together in a real-world app.
- Learn how to use Kotlin and Android development tools to build your own app
This course is intended for anyone who wants to learn how to start building their own apps on Android.
To get the most out of this course, you should have some basic knowledge of the fundamentals of Android.
Course GitHub repos:
Hello, everyone. We're going to continue to develop our Math Game application here. So, we need to figure out how to create a timer in this video. So, the timer will be a countdown timer. That means it's going to count down from a specific time to zero. And when the time's up, it'll write on the question TextView, "Sorry, your time is up." So, before our time is up, let's just get to it. So, let's define some variables. So, there's an abstract class in Kotlin that we can use in this game. Its name is CountDownTimer class. I will call this class and create an object from this class. So, I'll write lateinit var_timer : CountDownTimer.
Now notice a CountDownTimer is shown as an abstract class.
Now, in case that's kind of making your brain go, but wait. According to object-oriented programming, we cannot create an object directly from an abstract class. It's true. But here, we don't encounter any errors. We have not initialized it yet. We'll soon encounter an error when we initialize this object. But what I'll do is I'll explain the solution when we get to the problem. So, it's not yet a problem. Okay. So, we'll move on to creating our variables. Then, I'll create a long container to determine the initial value of time. Now there's a concept: the initial value of time. Anyway, I'll write private val.
So, the private keyword is visibility modifiers using Kotlin. If you use the keyword private before a variable or function, you can access that variable or function only from the class you are in. Now so that means private. So, in other words, you prevent access to this variable from all the other different classes. If you don't use this, you won't get any errors. But when you're working with different developers on large projects, you may want to restrict other people's access to your variables and you'll avoid a lot of confusion that way. In such cases, you can use the private keyword. If you don't use any visibility modifier, it is considered public by Kotlin by default. So, it can be accessed from anywhere.
Now, we can continue, startTimerInMillis : Long = 60000. So, I define the initial value of this variable as 60,000 milliseconds because I want to give the user one minute to answer the question. You have to define the time in milliseconds in Kotlin. One second equals 1,000 milliseconds. If you want to give the user more or less time, it's up to you; you can change your initial value. But I want you to remember you've got to define the time in milliseconds. And so, for instance, if you want to give the user 30 seconds, well, you got to write 30,000. I need to now create another long value var timeLeftInMillis : Long = startTimerInMillis. I will use the timeLeftInMillis value in the code.
But for now, I want it to be equally initial value. So now, I want to create another function for the timer like the gameContinue() function. So, the name of this function can be startTimer. So, I'll write fun startTimer(). I will initialize a CountDownTimer object, that is the timer object inside the startTimer() function. And I'll write timer = CountDownTimer. Also, the CountDownTimer class takes two parameters. First one is the initial value, and it will be that timeLeftInMillis. It is 60 seconds that we defined above. And the second one is the countDownInterval value. So, I'll write 1000. That means, it will count down one second by one second from 60 seconds to zero. 59, 58, 57, etc.
Now, did you notice Android Studio gives an error even though we define the parameters? So, just hover your mouse over this CountDownTimer class and you'll see a notification like, "Cannot create an instance of an abstract class." Well in this case, we will use the keyword object which represents the anonymous class. So, I'll write object : here and as you can see, the warnings disappear. But there's one more thing we got to do. We need to implement two functions of the CountDownTimer class here. So, to do this, first I'll define the scope of the CountDownTimer class with curly braces. And if you notice, Android Studio has underlined the keyword object because there are functions that we need to implement.
So, I'll first click on the keyword 'object' and then click on this red light bulb on the left. And from here, I can choose 'Implement Members'. And now there are two functions here: the onTick and onFinish. So, I'll select both functions and click the 'OK' button. So now, we've got two functions inside this CountDownTimer. First one is the onTick function. Whatever we wanted to do every second, well, we'll write it into this method. Also, the Long object given as a parameter here represents the remaining time in milliseconds until the finish. So, I'll write here millisUntilFinished instead of p0 and that'll make more sense. So, the second is the onFinish() method.
So, you'll write into this method what you wanted to do when the time finishes. For instance, it defined one minute. You can write what will happen one minute later. Also, we have to add the .start end of the scope of the CountDownTimer class. So, after that in the onTick method, I will write timeLeftInMillis = millisUntilFinished. So, that means the onTick method will work until 60 seconds play out. So, also the text of the timeTextView should change every second. So, that means it should update the time text every second. So, for that, I can call the updateText() function. So, I'll write this function later though. But now you can see, I'll pass to the onFinish method.
It's in the onFinish method where I will call the pauseTimer() function. I'll create this function later as well. But also when the time is finished, the timer should reset. So, I'll need to call it resetTimer() function. And again, I'll create that function later. And what about the time text? This needs to be updated when the time is finished. So, for this, I will call the updateText() function, and if the user does not answer within this amount of time, the user life should be decreased. So, for this, I'll write userLife--. Then we should update the life TextView. So, I'll write textLife.text = userLife.toString. And also when the time is up, we should tell the user that too.
So, I need to write this message to the user on the question TextView textQuestion.text = "Sorry, Time is up!" Now the timer is ready. So, that's how the timer works. We just need to write in the other red colored methods to support the timer because all the other methods have got to work for the entire timer to work. So, let's do it. We'll write the other methods. First, I'll write the updateText() function fun updateText(), and I'll fill in the function later. Second, I will write the pauseTimer() function fun pauseTimer(). And third, I will write the resetTimer() function fun resetTimer(). So, as you can see, when I create these functions, the red colors are gone.
So, I want to fill in the updateText() function. Inside the updateText method, I will create an integer val remaining Time = timeLeftInMillis divided by 1000. And this will give us the value of the remaining time in seconds but very long value. So, I need to convert this value to integer. So, I just need to add the toInt() function right here at the end of the line. So, after that, I will write this remaining time integer value on the time text. So, to do this, I need to convert this integer value to the string and assign the time TextView textTime.text = String.format(Locale.getDefault (), format: "%02d", remainingTime). So, String.format is to show time in a specific format.
So, inside the parenthesis, I defined how the format is going to show. The format will be two digits. Now, in every second, the text will update. So, let's jump to the pauseTimer() function. So, I want to pause the timer right here in this method. And to do this, I will just use a cancel() function actually, timer.cancel(). And this code will pause the timer, and the last function is resetTimer. So, when the timer is reset, the timeLeftInMillis should be equal to the startTimerInMillis value. And this will set the timer back to 60 seconds. And also the text should be updated. So, I want to call the updateText method once again; updateText(). So, our timer is ready.
We now need to call this startTimer() function somewhere and the best place to do that is in the gameContinue() method. Also, when the user clicks on the OK button, the timer should stop because the user answer the question. So, that stops the timer. So, we'll call the pauseTimer() method into the buttonOk.setOnClickListener method. So, the answer is, well, you know what? In fact, if the answer is true or false, it doesn't matter. The timer's got to stop anyway. So, because of this, I call the pauseTimer() method before the Inner if-else condition. You catch that, right? And also when the user clicks on the next question button, the timer should first stop and then reset. So, I will call the pauseTimer() and resetTimer() functions into the next question button ClickListener method. So, when the user clicks on the next question button, first, the timer will be reset. Then, the startTimer() method will work with the gameContinue() method. So, we can run the application to see if it's working or not. But before you get started, I will reduce the time to 20 seconds because I don't want to wait 60 seconds to see if it's working or not. But wait also, I want to change the title on the action bar and that way we can just squeeze in here how to change the title of the action bar because I promised you that earlier. It's pretty simple to do.
So, just write in here in the onCreate function. I'll write supportActionBar.title = between these double quotes. I'll write the title that I want to appear in the action bar. So, I'll just write in Addition. But since this method can return no, I'll need to put a double exclamation mark here. So now, we can run the application and test it. So, there the application opens. I'll click the 'ADDITION' button. So, look at that. The timer is running. Also, did you notice time is decreasing by one second every second? That's because we define the second parameter of the CountDownTimer class as 1,000 milliseconds. One second. So, when the time finishes, it'll write on the question TextView, Sorry, Time is up! And there the time is up, and the text of the question TextView changed. So, when I click on the 'NEXT' question button, the timer starts again. Also when the time is up, life goes down from 3 to 2. So, it looks like the timer is working. And did you notice the title of the action bar is changed? So far so good. So, we're getting close here. We're getting close to finishing the game. Last thing that we're going to need to develop is the results page. So, when the user life goes to zero, the game will finish. And also, we'll need to show the user their score. But we'll do all that in the next video. So, I'll look forward to seeing you there.
Mehmet graduated from the Electrical & Electronics Engineering Department of the Turkish Military Academy in 2014 and then worked in the Turkish Armed Forces for four years. Later, he decided to become an instructor to share what he knew about programming with his students. He’s currently an Android instructor, is married, and has a daughter.