NotSoSuperMario!

NotSoSuperMario!

March 2024

Created an automatic game of Mario! Requires a file with 8 lines with percentages and numbers for things like, the number of lives Mario will have, how big the levels will be, and the chances of objects being placed in the world.

This was a project I had always heard from other students because it is the most challenging due to the fact that you don't have much to go off of from what you've learned in class. I agree that this was difficult until the due date but I enjoyed this assignment the most. Because we were making a game from scratch, it was a nice challenge to be able to create the puzzle pieces and put them together and where they belonged. I will never forget the satisfaction when I got it all working.

See my code here

The most difficult function

For me, writing the StartGame function was the hardest because I had to figure out where and how to put all of the pieces together. Looking back after over 6 months, I would have organized my code a lot more. I originally wanted to create inheritance within my work but got overwhelmed very quickly as I created all of the classes. I think now that is the biggest change I would do. With the function below, I found it easier when I went to a whiteboard and started drawing out a finite state machine with all of the functions I had coded up until that point.

void OutFile::StartGame(string outputFile){
    /*I got help from Kaye in regards to logging in the game into the
    output file. Lines 57-63 and 158-159. 
    */
    ofstream loggerFile(outputFile);
    if (!loggerFile.is_open()) {
        cerr << "Failed to open output file: " << outputFile << endl;
        return; // Exit function if file opening fails
    }
    streambuf* coutToLogger = cout.rdbuf();
    //redirects all couts to the logger file 
    cout.rdbuf(loggerFile.rdbuf()); 

    int currentLevelPlayed = 0;
    bool isGameOver = false;

    //create the levels
    for (int i = 0; i < amountOfLevels; ++i)
    {
        m_levels[i] = level->CreateLevel(i);
        level->DisplayLevel(i, -1, -1);
        cout << endl;
    }

    cout << "Mario is currently at (" << marioInWorld->getRowForMario()
         << ", " << marioInWorld->getColumnForMario() << ")" << endl;
    /*The game itself is a while loop,
    While Mario has lives and the game isn't over, mario will move around 
    randomly in the level using move(), the switch statement will check to 
    see what mario has landed on and determine the next move and what other 
    methods to call from the Mario class.
    */
    while (marioInWorld->getMarioLives() > 0 && !isGameOver)
    {
        int rowOfMario = marioInWorld->getRowForMario();
        int columnOfMario = marioInWorld->getColumnForMario();
        level->DisplayLevel(currentLevelPlayed, marioInWorld->getRowForMario(), marioInWorld->getColumnForMario());

       cout << endl << "Level: " << currentLevelPlayed << ""
        << endl << "Mario is at (" << rowOfMario << ", " << columnOfMario << ")"
        << endl << "Mario is at Power Level: " << marioInWorld->getPowerLevel()
        << endl << "Mario has " << marioInWorld->getMarioLives() << " lives left"
        << endl << "Mario has " << marioInWorld->getCoins() << " coins";

        //tracks the char in the 2D array that mario is going to go on
        char nextPosition = level->getMariosCurrentPosition(currentLevelPlayed, rowOfMario, columnOfMario);
        switch (nextPosition)
        {
        case 'c':
            cout << "\nMario found a coin!";
            marioInWorld->FindsCoin();
            level->MarioHasBeen(currentLevelPlayed, rowOfMario, columnOfMario);
            break;
        case 'm':
            cout << "\nMario found a mushroom!";
            marioInWorld->FindsMushroom();
            level->MarioHasBeen(currentLevelPlayed, rowOfMario, columnOfMario);
            break;
        case 'g':
            cout << "\nMario will fight a goomba";
            if (marioInWorld->fightGoomba())
            {
                level->MarioHasBeen(currentLevelPlayed, rowOfMario, columnOfMario);
            }
            if (marioInWorld->emptyLives())
            {
                    cout << "Mario has lost D:";
                    return;
            }
            break;
        case 'k':
            cout << "\nMario will fight a koopa";
            if (marioInWorld->fightKoopa())
            {
                level->MarioHasBeen(currentLevelPlayed, rowOfMario, columnOfMario);
            }
            if (marioInWorld->emptyLives())
            {
                    cout << "Mario has lost the whole game D:";
                    return;
            }
            break;  
        case 'W':
            cout << "\nMario has found a warp pipe!";
            currentLevelPlayed++;
            level->DisplayLevel(currentLevelPlayed, marioInWorld->getRowForMario(), marioInWorld->getColumnForMario());
            break;  
        case 'B':
        // Mario will continue to fight bowser/boss once they have interacted in the last level to see if he wins of loses
            cout << "\nMario is fighing the BOSS";
            while (!marioInWorld->fightBowser())
            {
                if (marioInWorld->emptyLives())
                {
                    cout << "\nMario has lost D:";
                    return;
                } else if (marioInWorld->fightBowser()) //if fightBowser is true then mario wins
                {
                    cout << "\nMario has won the whole game!! :D";
                    return;
                }
            }
            break;                
        default:
            cout << "\nMario is on an empty space";
            break;
        }
        
        if (currentLevelPlayed != (amountOfLevels))
        {        
                cout << endl;
                marioInWorld->MarioMove();
        } else {
            isGameOver = true;
        }
    }