-
Notifications
You must be signed in to change notification settings - Fork 0
Entitas CSharp Components
comp Movable
Is a definition of a flag component which results in following code:
using Entitas;
public partial class MovableComponent : IComponent {
}
namespace Entitas {
public partial class Entity {
static readonly MovableComponent movableComponent = new MovableComponent();
public bool isMovable {
get { return HasComponent(ComponentIds.Movable); }
set {
if (value != isMovable) {
if (value) {
AddComponent(ComponentIds.Movable, movableComponent);
} else {
RemoveComponent(ComponentIds.Movable);
}
}
}
}
public Entity IsMovable(bool value) {
isMovable = value;
return this;
}
}
}
public partial class Matcher {
static IMatcher _matcherMovable;
public static IMatcher Movable {
get {
if (_matcherMovable == null) {
var matcher = (Matcher)Matcher.AllOf(ComponentIds.Movable);
matcher.componentNames = ComponentIds.componentNames;
_matcherMovable = matcher;
}
return _matcherMovable;
}
}
}
As you can see the get/set prefix for entity method is is
we can change it by defining an alternativ prefix:
comp Movable / "isFlaggedAs"
...
namespace Entitas {
public partial class Entity {
static readonly MovableComponent movableComponent = new MovableComponent();
public bool isFlaggedAsMovable {
get { return HasComponent(ComponentIds.Movable); }
set {
if (value != isFlaggedAsMovable) {
if (value) {
AddComponent(ComponentIds.Movable, movableComponent);
} else {
RemoveComponent(ComponentIds.Movable);
}
}
}
}
public Entity IsFlaggedAsMovable(bool value) {
isFlaggedAsMovable = value;
return this;
}
}
}
...
The component can also be defined as unique
which means that it can be present only once in the pool.
comp unique Movable / "isFlaggedAs"
This implies that the Pool
class is also extended.
...
public partial class Pool {
public Entity movableEntity { get { return GetGroup(Matcher.Movable).GetSingleEntity(); } }
public bool isFlaggedAsMovable {
get { return movableEntity != null; }
set {
var entity = movableEntity;
if (value != (entity != null)) {
if (value) {
CreateEntity().isFlaggedAsMovable = true;
} else {
DestroyEntity(entity);
}
}
}
}
}
...
If we want our component to hold values we have to first define a type alias.
alias int = "int"
This is needed because the DSL is programming language agnostic and have no awareness even from primitive types.
comp HealthPoints : int
If we want to define a component which holds only one value we can do it as written above. This produces following code
using Entitas;
public partial class HealthPointsComponent : IComponent {
public int value;
}
namespace Entitas {
public partial class Entity {
public HealthPointsComponent healthPoints { get { return (HealthPointsComponent)GetComponent(ComponentIds.HealthPoints); } }
public bool hasHealthPoints { get { return HasComponent(ComponentIds.HealthPoints); } }
public Entity AddHealthPoints(int newValue) {
var component = CreateComponent<HealthPointsComponent>(ComponentIds.HealthPoints);
component.value = newValue;
return AddComponent(ComponentIds.HealthPoints, component);
}
public Entity ReplaceHealthPoints(int newValue) {
var component = CreateComponent<HealthPointsComponent>(ComponentIds.HealthPoints);
component.value = newValue;
ReplaceComponent(ComponentIds.HealthPoints, component);
return this;
}
public Entity RemoveHealthPoints() {
return RemoveComponent(ComponentIds.HealthPoints);
}
}
}
public partial class Matcher {
static IMatcher _matcherHealthPoints;
public static IMatcher HealthPoints {
get {
if (_matcherHealthPoints == null) {
var matcher = (Matcher)Matcher.AllOf(ComponentIds.HealthPoints);
matcher.componentNames = ComponentIds.componentNames;
_matcherHealthPoints = matcher;
}
return _matcherHealthPoints;
}
}
}
As we can see, the generated component class has a value
field of type int
and Entity method / Matcher were generated accordingly.
comp unique HealthPoints : int
This is how we define the HealthPoints
component to be unique.
comp HealthPoints {
health : int
}
Is another way to describe the component. Here we actually tell what the property name is.
comp Position {
x : int
y : int
}
We use the same notation to describe a component with multiple properties.
comp Position {x: int, y: int}
And this is how we can write it on one line.
using Entitas;
public partial class PositionComponent : IComponent {
public int x;
public int y;
}
namespace Entitas {
public partial class Entity {
public PositionComponent position { get { return (PositionComponent)GetComponent(ComponentIds.Position); } }
public bool hasPosition { get { return HasComponent(ComponentIds.Position); } }
public Entity AddPosition(int newX, int newY) {
var component = CreateComponent<PositionComponent>(ComponentIds.Position);
component.x = newX;
component.y = newY;
return AddComponent(ComponentIds.Position, component);
}
public Entity ReplacePosition(int newX, int newY) {
var component = CreateComponent<PositionComponent>(ComponentIds.Position);
component.x = newX;
component.y = newY;
ReplaceComponent(ComponentIds.Position, component);
return this;
}
public Entity RemovePosition() {
return RemoveComponent(ComponentIds.Position);
}
}
}
public partial class Matcher {
static IMatcher _matcherPosition;
public static IMatcher Position {
get {
if (_matcherPosition == null) {
var matcher = (Matcher)Matcher.AllOf(ComponentIds.Position);
matcher.componentNames = ComponentIds.componentNames;
_matcherPosition = matcher;
}
return _matcherPosition;
}
}
}
Entitas-CSharp has a concept of multiple pools. In order to use it we have to specify them first
ctx Core, Meta
In ECS-Lang we call pools context (ctx for short)
comp[Core] Position {x: int, y: int}
comp[Meta] Score : int
This is how we can annotate affiliation of a component.
comp[Core, Meta] PlayerId : string
As we can see in the last example, a component can be affiliated with multiple pools/context.
using Entitas;
public partial class PlayerIdComponent : IComponent {
public string value;
}
namespace Entitas {
public partial class Entity {
public PlayerIdComponent playerId { get { return (PlayerIdComponent)GetComponent(MetaComponentIds.PlayerId); } }
public bool hasPlayerId { get { return HasComponent(MetaComponentIds.PlayerId); } }
public Entity AddPlayerId(string newValue) {
var component = CreateComponent<PlayerIdComponent>(MetaComponentIds.PlayerId);
component.value = newValue;
return AddComponent(MetaComponentIds.PlayerId, component);
}
public Entity ReplacePlayerId(string newValue) {
var component = CreateComponent<PlayerIdComponent>(MetaComponentIds.PlayerId);
component.value = newValue;
ReplaceComponent(MetaComponentIds.PlayerId, component);
return this;
}
public Entity RemovePlayerId() {
return RemoveComponent(MetaComponentIds.PlayerId);
}
}
}
public partial class MetaMatcher {
static IMatcher _matcherPlayerId;
public static IMatcher PlayerId {
get {
if (_matcherPlayerId == null) {
var matcher = (Matcher)Matcher.AllOf(MetaComponentIds.PlayerId);
matcher.componentNames = MetaComponentIds.componentNames;
_matcherPlayerId = matcher;
}
return _matcherPlayerId;
}
}
}
public partial class CoreMatcher {
static IMatcher _matcherPlayerId;
public static IMatcher PlayerId {
get {
if (_matcherPlayerId == null) {
var matcher = (Matcher)Matcher.AllOf(MetaComponentIds.PlayerId);
matcher.componentNames = CoreComponentIds.componentNames;
_matcherPlayerId = matcher;
}
return _matcherPlayerId;
}
}
}