Your First System - NocturnalWisp/Tynted-Engine GitHub Wiki

Getting Started

Alright, so having created the game in the first scene, systems happen to be relatively quick and similar to implement. The idea of systems is to control an aspect of the game, whether that be to render some sprites, or to apply physics to physics bodies. Either way, systems are fairly important to the logic of your game.

Setting Up a System

First you need to create your own custom class inheriting from System. This shell will be where you place all of your logic. I am going to create a "moving object" system which will move objects 😛

using Tynted;

public class MovingObjectSystem : Tynted.System
{
    
}

Overrides

Now we can implement the overrides. (Same as the game class with two extra.)

using Tynted;
using Tynted.SFML.Graphics;

public class MovingObjectSystem : Tynted.System
    public override void Initialize()
    {
	base.Initialize();
    }

    public override void Update(GameTime gameTime)
    {
	base.Update(gameTime);
    }

    public override void Draw(RenderWindow renderWindow)
    {
	base.Draw(renderWindow);
    }
}

Attributes

This topic is a bit more complicated and involves using attributes to determine what entities the system will have access to. There are currently 4 different attributes that determine different aspects of an entity:

  • GetComponents - Requires the entity to have each of the passed components.
  • RequireTags - Selects only entities with one of those tags.
  • RequireScenes - Selects only the entities in one of those scenes.
  • Manager - Overrides all the previous tags to not select any entities. This is for globally run systems that don't run on entities.

To start off simple, we are going to use GetComponents. Its syntax is easy enough:

[GetComponents(typeof(Components.Transform))]

We place that just before the class deceleration which end up looking like this:

using Tynted;
using Tynted.SFML.Graphics;
//This just sets a global reference to Components.Transform through the name Transform,
//I often use this because of how SFML and Box2d have their own Transform classes.
using Transform = Components.Transform;

[GetComponents(typeof(Components.Transform))]
public class MovingObjectSystem : Tynted.System
    public override void Initialize()
    {
	base.Initialize();
    }

    public override void Update(GameTime gameTime)
    {
	base.Update(gameTime);
    }

    public override void Draw(RenderWindow renderWindow)
    {
	base.Draw(renderWindow);
    }
}

Making It Work

So now that we have the basic shell, we should probably do something with it, so I am using various tools at my disposal to alter the transforms of the entities that we have received. (Behind the scenes, the system is actually calling GetComponentEntityActiveList which is returning those it needs.) I am also removing the useless overrides.

using Tynted;
using Tynted.SFML.Graphics;
using Transform = Components.Transform;

[GetComponents(typeof(Components.Transform))]
public class MovingObjectSystem : Tynted.System
    private float objectMoveSpeed;

    public override void Initialize()
    {
	base.Initialize();

	objectMoveSpeed = 50.0f;
    }

    public override void Update(GameTime gameTime)
    {
        base.Update(gameTime);

        //This gets all the entities the system has grabbed.
        var allEntities = GetEntities();

        //Loop through each entity in that list.
        foreach (Entity entity in allEntities)
        {
            //Grab the transform component off the current entity.
            Transform transform = entity.GetComponent<Transform>();
            //Get the world position from the transform.
            Vec2 pos = transform.GetWorldPosition();
            //Move the object along the x at a certain speed multiplied by the 
            //time between frames for constancy.
            pos.X += objectMoveSpeed * gameTime.elapsedTime.AsSeconds();
            //Reapply the position back to the transform.
            transform.LocalPosition = pos;
        }
    }
}

Connecting It

Last but not least, we need to inform the game of the new system. Update

using Tynted;
using Tynted.Components;
using Tynted.SFML.Graphics;
using Box2DNet.Common;

public class YourGameName : Game
{
    public YourGameName(GameOptions options) : base(options) { }

    public override void Initialize()
    {
        base.Initialize();

        //IMPORTANT!!!! ADD SYSTEM HERE.
        ECSManager.AddSystem(typeof(MovingObjectSystem));
        
        //Create the entity.
        ECSManager.CreateEntity("Test1");
        
        //Make sure you have a texture in your /Res/ folder
        var texture = new Texture("Res/img.png");
        
        //Add Components to the entity "Test1".
        ECSManager.RegisterEntityComponents(new List<EntityComponentIdentifier>()
        {
            new EntityComponentIdentifier("Test1", new Transform(new Vec2(200, 200))),
            new EntityComponentIdentifier("Test1", new SpriteRenderee(texture))
        });
    }
}

Congratulations

And there you have it, your first system. That wasn't so hard was it? You can now go run it, and your image should move on the X axis. Now you can head on over to making your own Component.

⚠️ **GitHub.com Fallback** ⚠️