Best Laid Schemes

Contributions

   Project Overview

Personal Notes

It was a unique opportunity to work in the in-house engine, building the game from the ground up in addition to a lack of documentation. I also have a soft spot for both turn based and stealth games.

I had to make our pathfinding, input, navmesh, AI, and our own animation system for all the characters, and I am grateful for the experience.

Development Process

Turn Manager

As we knew we didn't have a lot of time, I made the turn manager while the characters and enemies were being worked on since we knew this was a vital part of the game, meaning that we would have to go through a lot of iterations before we had a viable product. We had a hard time getting the initial "turn based" portion of the gameplay to stick. After deliberating with the other programmers, our solution for it was to make a turn manager that took care of all the characters in one go. The idea was to make something that generalized it as much as possible.

Through a lot of playtesting and the iterative process, we made different states depending on if the character was a player or an AI. Having differing functionality, yet using the same overarching system from the turn manager. 

switch ( _state )

case iTurnState::PLANNING:

{

    m_map->m_chosen_coords.clear();

    for ( cPlayer* player : m_players )

    {

        m_map->m_chosen_coords.emplace_back( player->getPos() / m_map->m_spacing );

    }

    for ( cEnemy* enemy : m_enemies )

    {

        enemy->setState( cCharacter::IDLE );

    }

    checkInput( m_current_character_turn );

}

break;

case iTurnState::WALKING:

    {

    for ( cEnemy* enemy : m_enemies )

    {

        enemy->setState( cCharacter::WALKING );

    }

    for ( cPlayer* player : m_players )

    {

        if( player->getState() != cCharacter::CAUGHT && player->getState() != cCharacter::INTERACTING )

        {

            player->setState( cCharacter::WALKING );

            player->m_finished_moves = false;

            player->m_is_selected    = false;

        }

    }

}

break;

default:

    break;

}

The animations were also done as part of the turn manager

In retrospect, another approach using a base class for both players and enemies would be prefferable for both the verbostiy and cleanliness of states with the turn manager.

Naive A* Implementation

Acknowledging the time constraints, I made a naive implementation of the A* pathfinding algorithm, making it as generalized as possible so we could implement it for both the AI and the player characters. I find the closest tile you could move to from the mouse position using a raycast.

I also made a custom Obstacle Generator for the map, making the map generation itself modular. You could make the navmesh work on any model. I made it using raycasts, checking if it hits any kind of obstacle, and removing it from the navmesh if it did.