diff --git a/README.md b/README.md index 1d33cfc..d01b03e 100644 --- a/README.md +++ b/README.md @@ -4,63 +4,66 @@ ### [View the Documentation](./docs/overview.md) ## *About Entity-Component-Systems* +An Enity-Component-System comprises of four main parts +1. The [entity](./docs/entity/Entity.md) which is essentially just a unique ID *i.e. an integer value* +2. The [component](./docs/entity/Component.md) which is a `struct` (`class` in Java). Typically contains data, but can be empty (to be used as a flag for certain systems) or contain function definitions. +3. The [system](./docs/system/System.md) which defines two main functions: `init()` and `update()`. Systems define a filter that is used to maintain a current and relevant list of entities that the system will act on. +4. The [engine](./docs/Engine.md), which ties everything together. It exposes the functions that should be called, and methods for retrieving data correctly. The initialisation of everything required also takes place here -Traditional game-engine designs typically follow the standard functional or object-oriented design paradigms. -This choice of paradigm is as important as it is in typical applications. +## About the implementation +The JavaECS project is a Maven project targeting Java SE 1.8. +It is released under the MIT licence. +It is intended to be compiled and packed into a `.jar` and referenced and imported into a project. +The Maven build script will produce a `javadoc` `.jar` with the library. -A functional-paradigm game usually focuses on a 'this-then-that' model, e.g.: +## Getting started with JavaECS +Initialise the library like so: +``` java +Engine gameEngine = new Engine(/* desired number of entities */); +``` +Next, the known components should be added. -***Simple Driving Game*** - -``` py -turn = GetTurn() -TurnCar(turn) -if IsCollided(): # and other checks - GameOver() -else: - DrawNextFrame() - turn = GetTurn() +Use the reflective component type: +``` java +gameEngine.registerComponent(ExampleComponent.class); ``` -Such a system works well for some game-designs; it is simplistic and follows a deterministic sequence of steps. But it lacks scalability and extensibility. - -An Object-Oriented approach could be used instead: -``` py -# Create a base-class that is a vehicle, with basic properties: -class Vehicle: - position = [x,y] - IsCrashed = False - def CalcTurn(): - pass - def IsCollided(): - pass - -# Create the PlayerVehicle class which extends Vehicle to include the player input method -class PlayerVehicle(Vehicle): - def GetPlayerInput(): - pass - -def GameLoop(): - vehicles[] = GetAllVehichles() - allCollided = False - while not allCollided: - for v in vehicles: - turnAmount - if v is PlayerVehicle: - turnAmount = v.GetPlayerInput() - else: - turnAmount = v.CalcTurn() - v.TurnVehicle() - if v.IsCollided(): - v.IsCrashed = True - anyNotCollided = False - for v in vehicles: - if v.IsCrashed = False: - anyNotCollided = True - break +Next, register the systems that are required. +Each system must be constructed, and passed as a parameter to the Engine. +- *If the system shall be invoked elsewhere, then you can petition the engine for the instance of the system.* +``` java +ExampleSystem exampleSystem = new ExampleSystem(gameEngine); +gameEngine.registerSystem(ExampleSystem.class, exampleSystem); ``` -Which allows the instancing of objects. Each action also results in an objective state, which can be simply compared to determine the result. +Next, create the entities that are needed as required. +``` java +Entity newEntity = gameEngine.createEntity(); +``` -ECS are typically built on object-oriented ideas, but make specfic attempts to reduce overheads that come from object-oriented ideas. -The primary reduction made in ECS is to eliminate or otherwise minimise inhertance cycles to reduce the amount of virtual calls required. +Assign the components to the entity: +``` java +gameEngine.addComponent(newEntity, ExampleComponent.class, new ExampleComponent()); +``` + +Be sure to call `init()` on each system, before the logical loop of the program +``` java +exampleSystem.init(); +``` + +Finally, the engine is ready to enter the logical loop, e.g.: +``` java +while (true){ + exampleSystem.update(); +} +``` +* note systems are *not* required to perform their `update()` in the normal logical loop. +* the update can also be performed at a factored rate. E.g. physics can be performed at a different rate to the renderer, in order to improve physics accuracy +* when using your own implmentation of a system, you may leave `init()` empty. Therefore, it isn't necessary to call `init()` before the game loop. **However**, It is recommended that you call `init()` to maintain consistency with all systems in the engine. +* Entities, components, and systems can be created at any time in the program lifecycle. + * Entities can be destroyed. + * Components and systems cannot be destroyed. + * Be aware that component registrations are contained via [BitSet](https://docs.oracle.com/javase/8/docs/api/java/util/BitSet.html). As the array is extended as bits are needed, note that the order of the set bits may impact performance with a large number of component types. + +### Example: +[App.java](/BrychanD/JavaECS-Examples/src/branch/master/demo1/src/main/java/nz/ac/massey/javaecs/examples/App.java#line=29-128)