A quick and satisfying math game for middle school and high school students featuring arithmetic, algebra, trigonometry, and derivatives. Put some earbuds on and solv

Mega-Update Recap

A video displaying the current gameplay

Background Information

In middle school, I wanted an educational game, keyword being a game. The extension to which education is available on the app store comes in three forms 1) Subscriptions I.E various brain games 2) Study Apps I.E Khan Academy and Quizlet 3) Kids Game I.E Toca Life. With this being there is a gap in the market for “higher education” games that also maintain a good user experience. After years of learning the fundamentals of code, I finally decided to put this to use in conjunction with being in my AP Computer Science A class. With this preamble, we should be good to move on.

Materials to Produce This Game

I am using the Unity Game Engine to code the game. Even though I have little experience in C# itself this is the language my code will be in because it is similar enough to the other languages I know. For testing and development, I am using the game editor in Unity alongside Xcode from Apple to create developmental versions for my personal device, iPhone 12 Mini.

What is One By One?

One By One is a game that will draw heavily from the Pokémon leveling mechanic and then possible AdVenture Capitalist for passive income. Players will start in the arithmetic tier and each time they solve a problem they will gain experience points and increase their balance. As players level up they will be given harder problems and given better rewards. As players accumulate more money they’ll be able to purchase different math courses up to calculus. In sum rapid problem repetition boringness will be subdued through dopamine-inducing game mechanics.

Hopes and Plans for One By One

Playable Platforms:

The main platforms will be on mobile devices, both iOS and android, so when students are on the bus or waiting in line, they can be playing this on their phone without feeling bad for playing a game and to be able to practice offline. In the future, depending on success and time, I may focus on porting the game over to larger devices like tablets and to the computer, either through an online browser or Steam.

Features:

As you’ll see later in the post I have coded the core of the game and now it will be mostly cut and paste with editing. The main stages I hope to implement are the following:

Algebra: This will probably start off with problems like x+1=2 and go up to 3x2+1=4. As I talk to my peers and teachers I will redefine the problems I plan to ask to be more functional.

Trigonometry: This will mostly apply to some geometry students and precalc+ students who are not able to remember what operations like sin(0) equals. I will probably use both degree and radians derived from the Unit Circle. To help fill questions in the higher tiers I may also implement arc trig operations.

Probability: I will have to discuss with my previous Stats teacher what types of problems I could do that still fit the format of the game but possibly simple binomial questions.

(Calculus) Derivatives: I will probably follow the general order that the derivative rules are taught in like product rule and power rule and then go up to loga(x) d/dx = 1/xln(a). To code this I may do a set of switch cases each containing a different rule or find a library that has already done the Calculus, we will see.

(Calculus) Integrals: Similar to the derivatives but these will just follow the integral rules.

I hope to add a shop system where in addition to players buying new levels they can upgrade their passive income by either increasing the return rate and/or the compounding period based on this formula, P=P0(1+r/n)nt to hopefully get students comfortable with how compounding interest works. In addition to this maybe cheat sheets? like displaying a unit circle when applicable or a derivative rule when applicable. Another idea is possibly cosmetic additions like a different theme. Having a good way to spend your money is crucial to incentive players to gain the money so I will have to talk with a lot of people to see what they would suggest.

I hope this game does reach a majority of the students in my ideal demographic which would be from middle school to high school. Maybe if the game becomes so successful I might code a Quest system in which teachers can assign homework disguised as “Quests”. I.E. the teacher could assign a Quest worth 50 points (for a grade) where a student would have to solve 10 tier 20 problems from the Arithmetic stage. This is very long term but something to keep in mind.

The Progression of the Game up to January 19th.

December 26th

I started the game by seeing how the UI would look. The UI I show below was the initial plan so there has been some deviation and lack of implementing certain features as I have not hit that point yet.

Above are the decided logo and launch screen. One By One is meant to invoke a math pun like 1×1 and I think the app icon, due to its modern and vague design, would provoke enough curiosity on the app store to click and see what it is about. I beige color was chosen as a soft color on the eye and the vintage or nostalgic vibe it might give off.

Design Choices:

When designing the game I wanted to play off the feeling of nostalgia in an old calculator and/or computer. I created a mood board and the image that sums up the design would be this. It’s a mostly line art aspect but I also wanted to use ASCII to drive the graphic as inspired by Stone Story RPG. The font driving the application is mostly Roboto Mono which can be found on Google Fonts. In a later demonstration, I’ll also show off the sound design.

December 27th

These dates are driven from my Snapchat story so I will also include those videos when applicable. With the UI in mind I started putting together the stages (haven’t really used Unity before but it was pretty straightforward) I mainly created the very fundamental aspects like a way to input an answer when a problem comes up on the screen.

This is me explaining how I am applying the knowledge from AP Computer Science A in generating the objects for each level using a class system.

December 28th

I added the screen to display the player’s progress alongside added sounds to reaffirm the player’s success. I also went through a commented my code for future reference and finished to tier 20.

If you would like to see the code and comments the video is 4K so you should be able to see the detail.

December 29th

Since I was on break I was able to spend 8+ hours each day developing the game so time and development went by very fast. I finished setting up the levels from 30-70. Below is an example of how I have each case set up to generate a problem

// level 60-69
// 50% exponents 0-12 ^ 2
// 30% division 26-144
// 20% multiplication 16-20
case 60:
    if (randomPercent > 50) { exponentProblem(0,12,2); }
    else if (randomPercent > 30) { divisionProblem(26,144); }
    else { multiplicationProblem(12,15,12); }
    maxReward = 1000;
    break;

Please excuse such simple mistakes in playing the math as my brain was fired; however, play testing I have noticed a discernible increase in my quick mental math skill, and would be interesting to conduct a study on this in how it affects one’s performance in mental math at a later time. Nonetheless, towards the end of the video, I show some of the code for how the PEMDAS system works. At this time I had only created the first tier in PEMDAS and I’ll show a snippet of the code below.

    void pemdasProblem(int difficulty)
    {
        Text input = inputObject.GetComponent<Text>();
        switch (difficulty)
        {  
                // level I just has 4 ints for MDAS
            case 1:
                    // 50% chance of being multiplication 
                if (UnityEngine.Random.Range(0,101) > 50)
                {  
                    int1 = UnityEngine.Random.Range(0,12);
                    int2 = UnityEngine.Random.Range(0,12);
                    int3 = UnityEngine.Random.Range(0,12);
                    int4 = UnityEngine.Random.Range(0,12);
                        // 33% of being a*b()c()d
                    if(UnityEngine.Random.Range(0,101) > 67){
                            // 50% chance of being a*b+c()d
                        if(UnityEngine.Random.Range(0,101)>50){
                                // 50% of being a*b+c+d
                            if(UnityEngine.Random.Range(0,101)>50){
                                ans = int1*int2+int3+int4;
                                input.text = int1+"*"+int2+"+"+int3+"+"+int4+"=";
                                Debug.Log("Problem ID: 6");
                                // 50% of being a*b+c-d
                            } else {
                                ans = int1*int2+int3-int4;
                                input.text = int1+"*"+int2+"+"+int3+"-"+int4+"=";
                                Debug.Log("Problem ID: 7");
                            }
                            // 50% of being a*b-c()d
                        } else {
                            // 50% of being a*b-c+d
                            if(UnityEngine.Random.Range(0,101)>50){
                                ans = int1*int2-int3+int4;
                                input.text = int1+"*"+int2+"-"+int3+"+"+int4+"=";
                                Debug.Log("Problem ID: 8");
                                // 50% of being a*b-c-d
                            } else {
                                ans = int1*int2-int3-int4;
                                input.text = int1+"*"+int2+"-"+int3+"-"+int4+"=";
                                Debug.Log("Problem ID: 9");
                            }
                        }   
                    }

I wanted to make sure that every permutation could of abcd, where there’s one MD operation and 2 AS operation. This also goes for the harder PEMDAS problems.

December 29th was also a cool day as I figured out how to port the game to my phone so I can play it on there.

December 30th

My main goal was to finish the second and third level of PEMDAS and I managed to do this a created a monstrous function that’s 1000 lines because I had to check every permutation. I also had to create a new division function to make sure that I created integer-resulting problem. I’ll show you some snippets of the code.

// level III is PEMDAS problems
case 3:
    // 33% of being (a[]b)²[]c[]d
    if (UnityEngine.Random.Range(0,101) > 67)
    {
            // 50% chance of being multiplication 
        if (UnityEngine.Random.Range(0,101) > 50)
        {  
            int1 = UnityEngine.Random.Range(0,12);
            int2 = UnityEngine.Random.Range(0,12);
            int3 = UnityEngine.Random.Range(0,12);
            int4 = UnityEngine.Random.Range(0,12);
                // 50% chance of being (a[]b)²(c)[]d
            if(UnityEngine.Random.Range(0,101) > 50){
                    // 50% chance of being (a+b)²(c)[]d
                if(UnityEngine.Random.Range(0,101)>50){
                        // 50% of being (a+b)²(c)+d
                    if(UnityEngine.Random.Range(0,101)>50){
                        ans = ((int) Mathf.Pow((float) int1+ (float) int2, 2))*int3+int4;
                        input.text = "("+int1+"+"+int2+")"+"²"+"("+int3+")"+"+"+int4+"=";
                        Debug.Log("Problem ID: 78");
                        // 50% of being (a+b)²(c)-d
                    } else {
                        ans = ((int) Mathf.Pow((float) int1+ (float) int2, 2))*int3-int4;
                        input.text = "("+int1+"+"+int2+")"+"²"+"("+int3+")"+"-"+int4+"=";
                        Debug.Log("Problem ID: 79");
                    }
                    // 50% of being (a-b)²(c)[]d
                } else {
                    // 50% of being (a-b)²(c)+d
                    if(UnityEngine.Random.Range(0,101)>50){
                        ans = ((int) Mathf.Pow((float) int1- (float) int2, 2))*int3+int4;
                        input.text = "("+int1+"-"+int2+")"+"²"+"("+int3+")"+"+"+int4+"=";
                        Debug.Log("Problem ID: 80");
                        // 50% of being (a-b)²(c)-d
                    } else {
                        ans = ((int) Mathf.Pow((float) int1- (float) int2, 2))*int3-int4;
                        input.text = "("+int1+"-"+int2+")"+"²"+"("+int3+")"+"-"+int4+"=";
                        Debug.Log("Problem ID: 81");
                    }
                }

Here you see that I am following the same process as before but now using exponents and parentheses.

// when its int2 / (int3-int4)²
case 19:
    while ( ((int2 % ((int) Mathf.Pow((float) int3- (float) int4, 2))) != 0) || (i < (1000)) )
    { 
        int2 = UnityEngine.Random.Range(0, 13);
        int3 = UnityEngine.Random.Range(1, 13);
        int4 = UnityEngine.Random.Range(1, 13);
        while(int3 == int4){
            int4 = UnityEngine.Random.Range(1, 13);
        }
        i++;
        if (i >=998 ){
            int1 = 0;
            int2 = 0;
            int3 = 1;
        }
    }
    break;

This is an example of the code I used to make sure that int2 / (int3-int4)² results only in integers

January 1st

This was the start to make trying to figure how to use SQLite. Spoiler Alert: it is quite annoying, especially with iOS. I decided to use an offline database solution so that players were not reliant on the internet and it is more simple for me to implement. I needed a database so I could start storing player’s score over time and plot it on a graph.

Here is an example of what the databased looked like.

January 2nd

Looking back it seemed like days between Jan 1st and Jan 2nd. Nonetheless, this day was quite cool as I coded an ASCII graph. To do this I created a 2D array in which each element would represent a character in the array. I am quite proud of this so I’ll show an image of it in use and also a video explaining the code.

I also coded for when the slope is negative; however, this is not needed in the current version of the game. (Also pro tip: you can scrub the bar up and down to see the rough draft and final draft)

January 5th

Development slowed down as I ran into issues with running the database on the iPhone. The issue was file paths so I have to create the database locally on the phone in order to generate the graph.

January 10th

School is in session so development again is slowed, especially with finals week, nonetheless I fixed a bug where the progress bar was not in a monospaced font so I used a native Apple monospaced font. I also created a streak system. This streak system will help users who know basic arithmetic progress faster as well as add a new pacing to the game.

public void streakCalculator()
{
    int deltaStreak = PlayerPrefs.GetInt("currentStreak") - prevStreak;
    if ((deltaStreak > 0)){
        currentTime = 3f;
        startCountdown = true;
        if (PlayerPrefs.GetInt("currentStreak") > 1) { countdownAudio.Play(); } else {}
    }
    prevStreak = PlayerPrefs.GetInt("currentStreak");
    deltaStreak = 0;
}

// Update is called once per frame
void Update()
{
    
    if(startCountdown && (currentTime > 0))
    {
        currentTime -= 1* Time.deltaTime;
        if (PlayerPrefs.GetInt("currentStreak") > 1)
        {
            if((PlayerPrefs.GetInt("currentStreak") >= 15)) { PlayerPrefs.SetInt("currentMultiplier", 5); }
            else if(PlayerPrefs.GetInt("currentStreak") >= 10) { PlayerPrefs.SetInt("currentMultiplier", 4); }
            else if(PlayerPrefs.GetInt("currentStreak") >= 5) { PlayerPrefs.SetInt("currentMultiplier", 3); }
            else { PlayerPrefs.SetInt("currentMultiplier", 2); }
            streakTextObject.text = "|Streak Alert|\n" + PlayerPrefs.GetInt("currentMultiplier") + "x  :" + currentTime.ToString("0.00");
        }
    } else if (startCountdown) {
        if (PlayerPrefs.GetInt("currentStreak") > 1)
        {
            countdownAudio.Stop();
            streakTextObject.text = "|Streak Alert|\nOVER";
            timeTilMsgGone = 1f;
        } else {}
        startCountdown = false;
        PlayerPrefs.SetInt("currentStreak", 0);
        prevStreak = 0;
    } else {
        timeTilMsgGone -= 1*Time.deltaTime;
        if (timeTilMsgGone <= 0) { streakTextObject.text = "";}
    }
}

January 19th

This is the current day of uploading. I haven’t made much if any progress since due to finals just finishing up and I have more pressing school work to deal with and complete like my AP Research project. The next steps will hopefully be to start creating the Algebra stage.

Leave a Reply

Share :

Twitter
Telegram
WhatsApp