3 min read
ShipWrecked Bird

ShipWrecked Bird gameplay

The ShipWrecked Bird project is a game developed in Unity that incorporates elements of machine learning, fuzzy logic, and various intriguing mechanics. The game is compatible with mobile devices, desktop systems, and supports VR technology.

šŸ¦˜ Game Physics

The game does not utilize physics libraries; instead, its mechanics are entirely based on mathematical models. For instance, the characterā€™s jump is a modified version of a parabolic trajectory. The Move method shifts an object in 3D space from one point to another, with an additional curve effect along the Y-axis.

public void Move(
    Transform target,
    Vector3 startPosition,
    Vector3 endPosition,
    float time
)
{
    const float fallFactor = 0.2f;

    float modifiedTime = (time > 0.5f)
        ? 0.5f + fallFactor * (time - 0.5f)
        : time;

    float targetX = startPosition.x +
        (endPosition.x - startPosition.x) * time;

    float targetY = startPosition.y +
        (endPosition.y - startPosition.y) * modifiedTime +
        0.6f * (1 - (Mathf.Abs(0.5f - modifiedTime) / 0.5f) *
        (Mathf.Abs(0.5f - modifiedTime) / 0.5f));

    float targetZ = startPosition.z +
        (endPosition.z - startPosition.z) * time;

    target.position = Vector3.Lerp(
        target.position,
        new Vector3(targetX, targetY, targetZ),
        1f
    );
}

Super Mario Bros jump proces

šŸ† Fuzzy Logic

The game features an intriguing difficulty model where the level of difficulty is determined by two parameters: the playerā€™s high score and the current number of collected coins during gameplay. This approach aims to make the game more challenging for experienced players compared to novices, ensuring it remains a constant challenge without requiring players to repeatedly face levels that are too easy for them.

Fuzzy Logic model

šŸ¤– Machine Learning

The opponentsā€™ logic was trained using reinforcement learning with the ML Agents library.

public class EnemyLogicAgent : Agent
{
    public override void CollectObservations(VectorSensor sensor)
    {
        sensor.AddObservation(EnemyManager.GetCoordinates()[0]);
        sensor.AddObservation(EnemyManager.GetCoordinates()[1]);
        sensor.AddObservation(EnemyManager.GetDirection());
        sensor.AddObservation(EnemyManager.GetDistanceToPlayer());
        sensor.AddObservation(PlayerManager.GetCoordinates()[0]);
        sensor.AddObservation(PlayerManager.GetCoordinates()[1]);
    }

    public override void OnActionReceived(ActionBuffers actions)
    {
        switch (actions.DiscreteActions[0])
        {
            case 0:
                EnemyManager.GoUP();
                break;
            case 1:
                EnemyManager.GoLeft();
                break;
            case 2:
                EnemyManager.GoRight();
                break;
        }

        CheckEnemyPosition();
    }

    public override void OnEpisodeBegin()
    {
        BoxManager.ResetGame();
        PlayerManager.ResetGame();
        EnemyManager.ResetGame();
    }

    private void CheckEnemyPosition()
    {
        if (EnemyManager.GetPosition() == PlayerManager.GetPosition())
        {
            SetReward(+1f);
            EndEpisode();
        }
        else if (EnemyManager.GetPositionStatus() == 3)
        {
            SetReward(-1f);
            EndEpisode();
        }
    }
}

Indicators of successful learning include parameters such as the dynamics of reward accumulation over time:

the dynamics of reward accumulation over time

and the change in episode length over time:

the change in episode length over time

šŸš€ Curious About Project?

The game is still in its top-secret beta phase. Itā€™s been put on hold while the developerā€™s ā€˜to-doā€™ list mysteriously grew to the size of a novel.

Stay tuned, because this gameā€™s comingā€”just as soon as we figure out how to clone ourselves or invent a 48-hour day!

Screenshot of the tutorial