From 7b09b13889d6cf74e2b6558265dcd9a86bd92b4a Mon Sep 17 00:00:00 2001 From: Brychan Dempsey Date: Sat, 5 Jun 2021 15:40:56 +1200 Subject: [PATCH] Added System docs Improved the accuracy of system.md Added ECSSystem.md and SystemManager.md --- docs/overview.md | 9 +-- docs/system/ECSSystem.md | 67 ++++++++++++++++++++ docs/system/SystemManager.md | 87 ++++++++++++++++++++++++++ docs/system/dir.md | 4 +- docs/system/system.md | 116 +++++++++++++++++++++++++---------- 5 files changed, 244 insertions(+), 39 deletions(-) create mode 100644 docs/system/ECSSystem.md create mode 100644 docs/system/SystemManager.md diff --git a/docs/overview.md b/docs/overview.md index 7d96713..b0b06de 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -3,16 +3,13 @@ ### In this folder [Implementation](./implementation.md) *how to use JavaECS* -[Usage](#Usage) - -[Notes](#Notes) ### See also: -[entity](./entity/entity.md) +[Entity](./entity/Entity.md) -[component](./component/component.md) +[Component](./component/Component.md) -[system](./system/system.md) +[System](./system/System.md) [event](./) diff --git a/docs/system/ECSSystem.md b/docs/system/ECSSystem.md new file mode 100644 index 0000000..ed53d8c --- /dev/null +++ b/docs/system/ECSSystem.md @@ -0,0 +1,67 @@ +*| [JavaECS](../../README.md) | [docs](../overview.md) | [system](./dir.md) | ECSSystem[]().md* +# System Manager + +### In this section +[About](#about) + +[Implementation](#implementation) + +[Constructors](#constructors) + +[Methods](#methods) + +[Fields](#fields) + +[Examples](#examples) + +[Notes](#notes) + + +## About +The system manager class controls references to the systems. + +## Implementation +See [System.md](./System.md#implmentation) +## Constructors +Default constructor +``` java +public ECSSystem(){} +``` + +
+ +## Methods +### init +``` java +public void init(){} +``` +Functionality that needs to occur at the initialisation of the system should be performed here +* `init()` should be called only once, before the system is utilised +* An example of the type of call that could be made here is opening a file + +
+ +### update +``` java +public void update(){} +``` +Functionality that needs to be called regularly should be defined here +* `update()` is intended to be called regularly + +
+ + +## Fields +### entities +``` java +Set entities = new HashSet<>(); +``` +The list of entities associated with this system + +
+ +## Examples + +
+ +## Notes \ No newline at end of file diff --git a/docs/system/SystemManager.md b/docs/system/SystemManager.md new file mode 100644 index 0000000..4f41e00 --- /dev/null +++ b/docs/system/SystemManager.md @@ -0,0 +1,87 @@ +*| [JavaECS](../../README.md) | [docs](../overview.md) | [system](./dir.md) | SystemManager[]().md* +# System Manager + +### In this section +[About](#about) + +[Implementation](#implementation) + +[Constructors](#constructors) + +[Methods](#methods) + +[Fields](#fields) + +[Examples](#examples) + +[Notes](#notes) + + +## About +The system manager class controls references to the systems. + +## Implementation +Before attempting to use a system, it must be registered. + +Registration requires a call to `registerSystem(String systemName, ECSSystem system)`, with params of the `String name` and a object reference of the [ECSSystem](./ECSSystem.md). Using the object reference, a system can be invoked at any time. + +## Constructors +Default constructor +``` java +public SystemManager(){} +``` +
+ +## Methods + +### entityDestroyed +``` java +public void entityDestroyed(int entity); +``` +Removes the specified entity from every system, if it was associated + +
+ +### entitySignatureChanged +``` java +public void entitySignatureChanged(int entity, BitSet entitySignature); +``` +Checks the entity's new signature against the current registrations. Registers the entity if it wasn't previously registered, or removes it if it is no longer registered. + +
+ +### registerSystem +``` java +public boolean registerSystem(String systemName, ECSSystem system); +``` +Registers the specified system name and system reference to this manager. + +*adds a `systemName:system` pair to [systems](#systems)* + +*and a `systemName:new BitSet()` pair to [signatures](#signatures)* + +
+ +### setSignature +``` java +public void setSignature(String system, BitSet registrations); +``` +Sets the required signature of the `system` + +
+ +## Fields +### signatures +``` java +Map signatures = new HashMap<>(); +``` + +
+ +### systems +``` java +Map systems = new HashMap<>(); +``` + +
+ diff --git a/docs/system/dir.md b/docs/system/dir.md index 76eac34..184d1ae 100644 --- a/docs/system/dir.md +++ b/docs/system/dir.md @@ -1,4 +1,6 @@ *| [JavaECS](../README.md) | [docs](../overview.md) | system* # Overview ### In this folder -[system.md](./system.md) \ No newline at end of file +* [ECSSystem.md](./ECSSystem.md) +* [System.md](./System.md) +* [SystemManager.md](./SystemManager.md) \ No newline at end of file diff --git a/docs/system/system.md b/docs/system/system.md index cf0866e..f7563fd 100644 --- a/docs/system/system.md +++ b/docs/system/system.md @@ -1,4 +1,4 @@ -*| [JavaECS](../../README.md) | [docs](../overview.md) | [system](./dir.md) | system[]().md* +*| [JavaECS](../../README.md) | [docs](../overview.md) | [system](./dir.md) | System[]().md* # System ### In this section @@ -12,51 +12,103 @@ ## About -The system runs operations that must be performed on its assoiciated components. +>A system is a functionality that is executed regularly by the game engine. -Typically, this is expected to be run every frame, though this is not a strict requirement. +The [SystemManager](./SystemManager.md) ensures that the system has an up-to-date list of entities that the system would act upon. This is performed by comparing the system's declared required components with the components of a potential entity. An entity containing all required components is added to the system's list. -A system must implement the Runnable interface (this is a limited case of inheritence in this library) +A system does not explicitly require any entities to be registered; but it can make more sense to directly perform such operations in the game loop. -This allows a simpler implementation of any system, and also allows concurrency to be implemented with relative ease. +`TODO` +There is a single layer of inheritence in this design, which is the overriden `init()` and `update()` functions. +This allows each system's `update()` to be called in a uniform way. - - - -Examples of the `system` include the `health_system`; which reads the value of the entitie's `health` component and ensures h > 0. -``` java -void health_system(){ - for (i = 0; i < registeredComponents.size(); i++){ - if (registeredComponents[i].health <= 0){ - registeredComponents[i].dead = true; - if (registeredComponents[i].isPlayer){ - GameOver(); - } - } - } -} -``` ## Implementation -The systems are managed by the following code: +All systems should extend [ECSSystem](./ECSSystem.md), which implements the entities list as a simple set. + +This can be overriden if there are certain requirements for the order of the entities (e.g. a Render System might require the further-most elements to be drawn first, to ensure the correct z-ordering) ``` java -class SystemManager{ - ECS baseECS; - int systemIndex; - - public SystemManager(ECS baseECS){ - this.baseECS = baseECS; - systemIndex = 0; +class ECSSystem{ + Set entities = new HashSet<>(); +} +``` +``` java +class NewSystem extends ECSSystem{ + void init() {} + void update(/* any required parameters*/){ + /* implementation */ } } ``` ## Examples +### System that operates on entities with multiple components +``` java +public class PhysicsSystem extends ECSSystem{ + ECS gameEngine; + public PhysicsSystem(ECS gameEngine){ + this.gameEngine = gameEngine; + } + + void init() {} + + void update(double dt){ + for (Integer entity : entities) { + // Get entity components + Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class.getName()); + RidgidBody ridgidBody = (RidgidBody)gameEngine.getComponentData(entity, RidgidBody.class.getName()); + Gravity gravity = (Gravity)gameEngine.getComponentData(entity, Gravity.class.getName()); + // Add the result of the accelerative forces to the ridgidbody's velocity + ridgidBody.xdot += ridgidBody.xAcc * dt; + ridgidBody.ydot += ridgidBody.yAcc * dt; + + // Gravity is a force of acceleration as above, but is generally considered to be constant. + if (gravity.terminalX < 0 || Math.abs(ridgidBody.xdot) < gravity.terminalX){ + ridgidBody.xdot += gravity.x * dt; + } + if (gravity.terminalY < 0 || Math.abs(ridgidBody.ydot) < gravity.terminalY){ + ridgidBody.ydot += gravity.y * dt; + } + + // Finally, move the vec2d by the new velocity + pos.x += ridgidBody.xdot * dt; + pos.y += ridgidBody.ydot * dt; + } + } +} +``` +### System that operates on a single component +``` java +public class LogVec2DSystem extends ECSSystem{ + ECS gameEngine; + public LogVec2DSystem(ECS gameEngine){ + this.gameEngine = gameEngine; + } + + void init() {} + + void update(double dt){ + for (Integer entity : entities) { + Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class.getName()); + System.out.println(String.format("X: %.6g, Y: %.6g", pos.x, pos.y)); + } + } +} +``` +### System that operates on no components +Note that it does not require a reference the the `gameEngine`; no component data is accessed. +``` java +public class FrameRateSystem extends ECSSystem{ + void init() {} + + void update(double dt, double idleTime){ + System.out.print(String.format("dt: %.3g (%.3g idle) ", dt, idleTime)); + } +} +``` ## Notes -* Each system is represented by a name-index pair, and the action that gets executed every time the system is performed. - * This is implicitly sequential, but a custom system that performs concurrent actions can be implemented. - * Care must be taken to ensure all threads are synchronised before the concurrent system finishes its execution +