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
);
}
š 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.
š¤ 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:
and 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!