Compare commits

..
4 Commits
Author SHA1 Message Date
BrychanD 2405f1fb53 Update 'README.md' 2021-06-10 01:42:48 +12:00
BrychanD 5a3e3a33fc Update 'RenderHTML.html' 2021-06-10 00:21:00 +12:00
BrychanD 0bc67fe87b Update 'README.md'
Changed docs description to a 'Getting Started'
2021-06-10 00:13:42 +12:00
BrychanD e00558937a Included fetching tite 2021-06-08 22:10:38 +12:00
2 changed files with 70 additions and 54 deletions
+55 -52
View File
@@ -4,63 +4,66 @@
### [View the Documentation](./docs/overview.md) ### [View the Documentation](./docs/overview.md)
## *About Entity-Component-Systems* ## *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. ## About the implementation
This choice of paradigm is as important as it is in typical applications. 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*** Use the reflective component type:
``` java
``` py gameEngine.registerComponent(ExampleComponent.class);
turn = GetTurn()
TurnCar(turn)
if IsCollided(): # and other checks
GameOver()
else:
DrawNextFrame()
turn = GetTurn()
``` ```
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. Next, register the systems that are required.
Each system must be constructed, and passed as a parameter to the Engine.
An Object-Oriented approach could be used instead: - *If the system shall be invoked elsewhere, then you can petition the engine for the instance of the system.*
``` py ``` java
# Create a base-class that is a vehicle, with basic properties: ExampleSystem exampleSystem = new ExampleSystem(gameEngine);
class Vehicle: gameEngine.registerSystem(ExampleSystem.class, exampleSystem);
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
``` ```
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. Assign the components to the entity:
The primary reduction made in ECS is to eliminate or otherwise minimise inhertance cycles to reduce the amount of virtual calls required. ``` 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=12-128)
+15 -2
View File
@@ -7,6 +7,9 @@
background-color: #383c4a; background-color: #383c4a;
} }
</style> </style>
<link rel="stylesheet" href="/css/index.css">
<link rel="stylesheet" href="/css/theme-night-sky.css">
<script> <script>
const queryString = window.location.search; const queryString = window.location.search;
const queryLoc = window.location.origin; const queryLoc = window.location.origin;
@@ -16,6 +19,7 @@
const urlParams = new URLSearchParams(queryString); const urlParams = new URLSearchParams(queryString);
const requestURL = urlParams.get('url') const requestURL = urlParams.get('url')
const selector = urlParams.get('selector') const selector = urlParams.get('selector')
var pageLink;
// Fetch the content // Fetch the content
fetch(queryLoc + requestURL) fetch(queryLoc + requestURL)
.then(function (data) { .then(function (data) {
@@ -29,11 +33,13 @@
var htmlTrimmed = doc.querySelector(selector); var htmlTrimmed = doc.querySelector(selector);
if (htmlTrimmed) { if (htmlTrimmed) {
htmlTrimmed = htmlTrimmed.parentElement; htmlTrimmed = htmlTrimmed.parentElement;
/*
var styleSheets = doc.querySelectorAll("link"); var styleSheets = doc.querySelectorAll("link");
for (var i = 0; i < styleSheets.length; i++) { for (var i = 0; i < styleSheets.length; i++) {
document.head.appendChild(styleSheets[i]); document.head.appendChild(styleSheets[i]);
} } */
// Fetch and refactor links, to use this html doc where appropriate // Fetch and refactor links, to use this html doc where appropriate
document.title = doc.title;
var hlinks = htmlTrimmed.querySelectorAll("a"); var hlinks = htmlTrimmed.querySelectorAll("a");
for (var i = 0; i < hlinks.length; i++) { for (var i = 0; i < hlinks.length; i++) {
if (hlinks[i].href.replace(queryLoc, "").startsWith("/")) { if (hlinks[i].href.replace(queryLoc, "").startsWith("/")) {
@@ -42,7 +48,14 @@
// 2.) disable cross-origin requests // 2.) disable cross-origin requests
var fixedURL = hlinks[i].href.replace(windowLoc.split('#')[0], "").replace(queryLoc, "") var fixedURL = hlinks[i].href.replace(windowLoc.split('#')[0], "").replace(queryLoc, "")
// If the remaining character is the hash, this is a same-page section link // If the remaining character is the hash, this is a same-page section link
if (fixedURL.startsWith("#")) { // There are two cases here;
// 1.) The hash-url is just a typical page-link
// 2.) The hash-url is a page content reference
if (fixedURL.contains("#page=")) {
pageLink.add(fixedURL);
}
else if (fixedURL.startsWith("#")){
fixedURL = requestURL + fixedURL; fixedURL = requestURL + fixedURL;
} }
// selector is the selector used to select the element. Use body if the whole page is required // selector is the selector used to select the element. Use body if the whole page is required