Compare commits

...
9 Commits
Author SHA1 Message Date
BrychanD 05c57efc52 Updated examples to the latest version
For release, used in the report/presentation
2021-06-15 18:13:49 +12:00
BrychanD 3c45ca9de8 Fixed exceptions due to the renderer not being ready 2021-06-12 15:56:13 +12:00
BrychanD 117589b17b Got example 2 working
Player input; and a different way of setting up the renderer
2021-06-12 15:53:30 +12:00
BrychanD bca92faa88 Upgraded to 0.9.9, minor physics improvements 2021-06-12 12:54:54 +12:00
BrychanD 4febf41721 Added some skeletons 2021-06-11 21:09:41 +12:00
BrychanD 8082817860 Added player control example base 2021-06-11 20:55:42 +12:00
BrychanD 21513f69ed Added a perftest 2021-06-11 14:42:19 +12:00
BrychanD 87389e78eb Merge branch 'master' of https://git.software.kauripeak.co.nz/BrychanD/JavaECS-Examples 2021-06-11 11:37:53 +12:00
BrychanD 73228ed05a Improved the physics system 2021-06-11 11:37:50 +12:00
36 changed files with 976 additions and 153 deletions
+2
View File
@@ -26,3 +26,5 @@ buildNumber.properties
.factorypath .factorypath
.project .project
.vscode/ .vscode/
*.jar
+9 -9
View File
@@ -19,8 +19,8 @@
<!-- JaCoCo thresholds. Increase gradually as you add tests. --> <!-- JaCoCo thresholds. Increase gradually as you add tests. -->
<jacoco.unit-tests.limit.instruction-ratio>0%</jacoco.unit-tests.limit.instruction-ratio> <jacoco.unit-tests.limit.instruction-ratio>0%</jacoco.unit-tests.limit.instruction-ratio>
<jacoco.unit-tests.limit.branch-ratio>0%</jacoco.unit-tests.limit.branch-ratio> <jacoco.unit-tests.limit.branch-ratio>0%</jacoco.unit-tests.limit.branch-ratio>
<jacoco.unit-tests.limit.class-complexity>20</jacoco.unit-tests.limit.class-complexity> <jacoco.unit-tests.limit.class-complexity>2100</jacoco.unit-tests.limit.class-complexity>
<jacoco.unit-tests.limit.method-complexity>5</jacoco.unit-tests.limit.method-complexity> <jacoco.unit-tests.limit.method-complexity>1000</jacoco.unit-tests.limit.method-complexity>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@@ -38,12 +38,12 @@
<dependency> <dependency>
<groupId>nz.ac.massey.javaecs</groupId> <groupId>nz.ac.massey.javaecs</groupId>
<artifactId>javaecs</artifactId> <artifactId>javaecs</artifactId>
<version>0.9.2-PRERELEASE</version> <version>1.0.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <!-- <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>${maven-enforcer-plugin.version}</version> <version>${maven-enforcer-plugin.version}</version>
@@ -93,8 +93,8 @@
</goals> </goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin> -->
<plugin> <!--<plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version> <version>${maven-surefire-plugin.version}</version>
@@ -165,7 +165,7 @@
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin> -->
</plugins> </plugins>
</build> </build>
<reporting> <reporting>
@@ -179,7 +179,7 @@
</reporting> </reporting>
<profiles> <profiles>
<!-- Publish coverage report to Coveralls, only when running in Travis. --> <!-- Publish coverage report to Coveralls, only when running in Travis. -->
<profile> <!-- <profile>
<id>travis</id> <id>travis</id>
<activation> <activation>
<property> <property>
@@ -195,6 +195,6 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</profile> </profile> -->
</profiles> </profiles>
</project> </project>
@@ -1,6 +1,7 @@
package nz.ac.massey.javaecs.examples; package nz.ac.massey.javaecs.examples;
import java.util.Random; import java.util.Random;
import java.util.concurrent.Semaphore;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import nz.ac.massey.javaecs.*; import nz.ac.massey.javaecs.*;
@@ -14,6 +15,8 @@ public final class App {
private App() { private App() {
} }
public static Semaphore rendererReadySemaphore = new Semaphore(0);
/** /**
* Simple physics simulation. * Simple physics simulation.
* @param args The arguments of the program. * @param args The arguments of the program.
@@ -52,7 +55,7 @@ public final class App {
LogUpdateSystem logUpdateSystem = new LogUpdateSystem(gameEngine); LogUpdateSystem logUpdateSystem = new LogUpdateSystem(gameEngine);
gameEngine.registerSystem(LogUpdateSystem.class, logUpdateSystem); gameEngine.registerSystem(LogUpdateSystem.class, logUpdateSystem);
RenderSystem renderSystem = new RenderSystem(gameEngine, 10.); RenderSystem renderSystem = new RenderSystem(gameEngine, 5.);
gameEngine.registerSystem(RenderSystem.class, renderSystem); gameEngine.registerSystem(RenderSystem.class, renderSystem);
ExistenceSystem existenceSystem = new ExistenceSystem(gameEngine); ExistenceSystem existenceSystem = new ExistenceSystem(gameEngine);
@@ -70,28 +73,28 @@ public final class App {
// Bottom boundary // Bottom boundary
Entity newEnt = gameEngine.createEntity(); Entity newEnt = gameEngine.createEntity();
gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(-50., -50.,0)); gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(-50., -50.,0));
gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(0., 0., 0., 0., 0.f, 0., -1.)); gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(0., 0., 0., 0., 0.f, 0.25, -1.));
gameEngine.addComponent(newEnt, Collider.class, new Collider(200., 50.)); // 200 along, 50 up gameEngine.addComponent(newEnt, Collider.class, new Collider(200., 50.)); // 200 along, 50 up
gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class)); gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class));
gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(200, 50, 64, 64, 64)); gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(200, 50, 64, 64, 64));
// Left boundary // Left boundary
newEnt = gameEngine.createEntity(); newEnt = gameEngine.createEntity();
gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(-50., -50.,0)); gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(-50., -50.,0));
gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(0., 0., 0., 0., 0.f, 0., -1.)); gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(0., 0., 0., 0., 0.f, 0.25, -1.));
gameEngine.addComponent(newEnt, Collider.class, new Collider(50., 200.)); gameEngine.addComponent(newEnt, Collider.class, new Collider(50., 200.));
gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class)); gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class));
gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(50, 200, 64, 64, 64)); gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(50, 200, 64, 64, 64));
// Top boundary // Top boundary
newEnt = gameEngine.createEntity(); newEnt = gameEngine.createEntity();
gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(-50., 100.,0)); gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(-50., 100.,0));
gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(0., 0., 0., 0., 0.f, 0., -1.)); gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(0., 0., 0., 0., 0.f, 0.25, -1.));
gameEngine.addComponent(newEnt, Collider.class, new Collider(200., 50.)); gameEngine.addComponent(newEnt, Collider.class, new Collider(200., 50.));
gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class)); gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class));
gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(200, 50, 64, 64, 64)); gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(200, 50, 64, 64, 64));
// Right boundary // Right boundary
newEnt = gameEngine.createEntity(); newEnt = gameEngine.createEntity();
gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(100., -50.,0)); gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(100., -50.,0));
gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(0., 0., 0., 0., 0.f, 0., -1.)); gameEngine.addComponent(newEnt, RidgidBody.class, new RidgidBody(0., 0., 0., 0., 0.f, 0.25, -1.));
gameEngine.addComponent(newEnt, Collider.class, new Collider(50., 200.)); gameEngine.addComponent(newEnt, Collider.class, new Collider(50., 200.));
gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class)); gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class));
gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(50, 200, 64, 64, 64)); gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(50, 200, 64, 64, 64));
@@ -110,7 +113,7 @@ public final class App {
gameEngine.addComponent(newEnt, Reporter.class, new Reporter()); gameEngine.addComponent(newEnt, Reporter.class, new Reporter());
gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(5,5,0)); gameEngine.addComponent(newEnt, Vec2D.class, new Vec2D(5,5,0));
/* // Uncomment this block to enable the stress-test (runs 500 square entities, with physics etc.) // Uncomment this block to enable the stress-test (runs 500 square entities, with physics etc.)
Random rand = new Random(); Random rand = new Random();
for (int i = 0; i < 500; i++) { for (int i = 0; i < 500; i++) {
newEnt = gameEngine.createEntity(); newEnt = gameEngine.createEntity();
@@ -122,15 +125,16 @@ public final class App {
gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class)); gameEngine.addComponent(newEnt, Render.class, new Render(BoxRender.class));
gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(size, size, 30 + rand.nextInt(225), 30 + rand.nextInt(225), 30 + rand.nextInt(225))); gameEngine.addComponent(newEnt, BoxRender.class, new BoxRender(size, size, 30 + rand.nextInt(225), 30 + rand.nextInt(225), 30 + rand.nextInt(225)));
gameEngine.addComponent(newEnt, TimedExistence.class, new TimedExistence(25 + rand.nextDouble() * 90)); gameEngine.addComponent(newEnt, TimedExistence.class, new TimedExistence(25 + rand.nextDouble() * 90));
} */ }
/************************************ /************************************
** Run init() on the systems ** ** Run init() on the systems **
*************************************/ *************************************/
renderSystem.init();
rendererReadySemaphore.acquire();
physicsSystem.init(); physicsSystem.init();
collisionSystem.init(); collisionSystem.init();
logUpdateSystem.init(); logUpdateSystem.init();
renderSystem.init();
existenceSystem.init(); existenceSystem.init();
reportSystem.init(); reportSystem.init();
@@ -142,14 +146,15 @@ public final class App {
double frameRate = 1.0 / 144; // 1 second divided by target number of frames double frameRate = 1.0 / 144; // 1 second divided by target number of frames
boolean exit = false; boolean exit = false;
Thread.sleep(5000);
long startTime = System.nanoTime(); long startTime = System.nanoTime();
while (!exit){ while (!exit){
// Run system updates // Run system updates
collisionSystem.update(); collisionSystem.update(dt);
physicsSystem.update(dt); physicsSystem.update(dt);
existenceSystem.update(dt); existenceSystem.update(dt);
reportSystem.update(); reportSystem.update(dt);
renderSystem.update(); renderSystem.update(dt);
dt = (System.nanoTime() - startTime) / 1e9; // convert nanoseconds to seconds dt = (System.nanoTime() - startTime) / 1e9; // convert nanoseconds to seconds
startTime = System.nanoTime(); startTime = System.nanoTime();
@@ -1,14 +1,11 @@
package nz.ac.massey.javaecs.examples.Systems; package nz.ac.massey.javaecs.examples.Systems;
import java.util.BitSet; import java.util.BitSet;
import java.util.HashSet;
import java.util.Set;
import nz.ac.massey.javaecs.ECSSystem; import nz.ac.massey.javaecs.ECSSystem;
import nz.ac.massey.javaecs.Engine; import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity; import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.Components.Collider; import nz.ac.massey.javaecs.examples.Components.Collider;
import nz.ac.massey.javaecs.examples.Components.Gravity;
import nz.ac.massey.javaecs.examples.Components.RidgidBody; import nz.ac.massey.javaecs.examples.Components.RidgidBody;
import nz.ac.massey.javaecs.examples.Components.Vec2D; import nz.ac.massey.javaecs.examples.Components.Vec2D;
@@ -28,41 +25,35 @@ public class CollisionSystem extends ECSSystem {
public void init() { public void init() {
} }
// This is a quick & naive physics implementation. Not all collision states are accurately calculated // This is a quick & naive physics implementation.
// I also expect it is highly inefficient, though I was able to run it with 500 subscribed entities // I expect it is highly inefficient, though it is able to run it with 500
// subscribed entities
// with no major performance issues // with no major performance issues
// Replace this with a proper system as required // Replace this with a proper system as required - I.e. Box2D or etc.
@Override @Override
public void update() { public void update(double dt) {
Set<Entity> processed = new HashSet<>();
// Gets all items we have collided with
for (Entity entity : entities) { for (Entity entity : entities) {
Vec2D pos = (Vec2D) gameEngine.getComponentData(entity, Vec2D.class); Vec2D pos = (Vec2D) gameEngine.getComponentData(entity, Vec2D.class);
RidgidBody ridgidBody = (RidgidBody) gameEngine.getComponentData(entity, RidgidBody.class); RidgidBody ridgidBody = (RidgidBody) gameEngine.getComponentData(entity, RidgidBody.class);
Collider collider = (Collider) gameEngine.getComponentData(entity, Collider.class); Collider collider = (Collider) gameEngine.getComponentData(entity, Collider.class);
if (ridgidBody.mass >= 0) { if (ridgidBody.mass >= 0) {
// Only ignore non-static colliders // Only ignore non-static colliders
//processed.add(entity);
for (Entity entity2 : entities) { for (Entity entity2 : entities) {
if (!processed.contains(entity2)) {
// skip entities that have already been processed // skip entities that have already been processed
Vec2D otherPos = (Vec2D) gameEngine.getComponentData(entity2, Vec2D.class); Vec2D otherPos = (Vec2D) gameEngine.getComponentData(entity2, Vec2D.class);
RidgidBody otherRidgidBody = (RidgidBody) gameEngine.getComponentData(entity2, RidgidBody otherRidgidBody = (RidgidBody) gameEngine.getComponentData(entity2, RidgidBody.class);
RidgidBody.class);
Collider otherCollider = (Collider) gameEngine.getComponentData(entity2, Collider.class); Collider otherCollider = (Collider) gameEngine.getComponentData(entity2, Collider.class);
if (ridgidBody.mass >= 0 || otherRidgidBody.mass >= 0) { if (otherRidgidBody.mass < 0) {
// Evaluate a collision in the top-left // Evaluate a collision in the top-left
boolean tlCollide = pos.x > otherPos.x && pos.x < otherPos.x + otherCollider.x boolean tlCollide = pos.x > otherPos.x && pos.x < otherPos.x + otherCollider.x
&& pos.y > otherPos.y && pos.y < otherPos.y + otherCollider.y; && pos.y > otherPos.y && pos.y < otherPos.y + otherCollider.y;
// Evaluate a collision in the bottom-left // Evaluate a collision in the bottom-left
boolean blCollide = pos.x > otherPos.x && pos.x < otherPos.x + otherCollider.x boolean blCollide = pos.x > otherPos.x && pos.x < otherPos.x + otherCollider.x
&& pos.y + collider.y > otherPos.y && pos.y + collider.y > otherPos.y && pos.y + collider.y < otherPos.y + otherCollider.y;
&& pos.y + collider.y < otherPos.y + otherCollider.y;
// Evaluate a collision in the bottom-right // Evaluate a collision in the bottom-right
boolean brCollide = pos.x + collider.x > otherPos.x boolean brCollide = pos.x + collider.x > otherPos.x
&& pos.x + collider.x < otherPos.x + otherCollider.x && pos.x + collider.x < otherPos.x + otherCollider.x && pos.y + collider.y > otherPos.y
&& pos.y + collider.y > otherPos.y
&& pos.y + collider.y < otherPos.y + otherCollider.y; && pos.y + collider.y < otherPos.y + otherCollider.y;
// Evaluate a collision in the top-right // Evaluate a collision in the top-right
boolean trCollide = pos.x + collider.x > otherPos.x boolean trCollide = pos.x + collider.x > otherPos.x
@@ -74,8 +65,7 @@ public class CollisionSystem extends ECSSystem {
double totalYVel = Math.abs(ridgidBody.yVel) + Math.abs(otherRidgidBody.yVel); double totalYVel = Math.abs(ridgidBody.yVel) + Math.abs(otherRidgidBody.yVel);
double xMult = 0; double xMult = 0;
double yMult = 0; double yMult = 0;
double multTot = (1 + ridgidBody.bounciness); double multTot = 1;
double totalMass = ridgidBody.mass + otherRidgidBody.mass;
boolean fullEdge = false; boolean fullEdge = false;
// left-hand collision // left-hand collision
if (tlCollide && blCollide) { if (tlCollide && blCollide) {
@@ -90,7 +80,7 @@ public class CollisionSystem extends ECSSystem {
xMult = -multTot; xMult = -multTot;
} }
// Bottom collision // Bottom collision
if (blCollide && brCollide) { else if (blCollide && brCollide) {
fullEdge = true; fullEdge = true;
// pos.y = otherPos.y + otherCollider.y; // pos.y = otherPos.y + otherCollider.y;
pos.y = otherPos.y - collider.y; pos.y = otherPos.y - collider.y;
@@ -104,26 +94,12 @@ public class CollisionSystem extends ECSSystem {
yMult = multTot; yMult = multTot;
} }
if (fullEdge) { if (fullEdge) {
// Finally, actuate the calculation double newXVel = totalXVel * (xMult
// entity 2 is immovable; full acceleration applied to the current entity * (Math.abs(xMult) + (ridgidBody.bounciness * otherRidgidBody.bounciness)));
double newYVel = totalYVel * (yMult
if (otherRidgidBody.mass > 0){ * (Math.abs(yMult) + (ridgidBody.bounciness * otherRidgidBody.bounciness)));
ridgidBody.xVel += totalXVel * xMult * ((totalMass - ridgidBody.mass) / totalMass); ridgidBody.xVel += newXVel;
ridgidBody.yVel += totalYVel * yMult * ((totalMass - ridgidBody.mass) / totalMass); ridgidBody.yVel += newYVel;
otherRidgidBody.xVel -= totalXVel * xMult * ((totalMass - otherRidgidBody.mass) / totalMass);
otherRidgidBody.yVel -= totalYVel * yMult * ((totalMass - otherRidgidBody.mass) / totalMass);
}
else{
ridgidBody.xVel += totalXVel * xMult;
ridgidBody.yVel += totalYVel * yMult;
}
Object grav = gameEngine.getComponentData(entity, Gravity.class);
if (grav != null) {
// negate gravity while collided
Gravity gravity = (Gravity) grav;
ridgidBody.xAcc += gravity.x * -1.;
ridgidBody.yAcc += gravity.y * -1.;
} }
} }
} }
@@ -131,30 +107,4 @@ public class CollisionSystem extends ECSSystem {
} }
} }
} }
}
}
/**
* Zero degrees is straight up, 90 east -90 (270) = west 180 south
*
* @param xVel
* @param yVel
* @return
*/
public static double calcAngle(double xVel, double yVel) {
if (xVel == 0) { // Div zero; = +- 90
return yVel < 0 ? 270 : 90;
} else if (xVel < 0 && yVel < 0) { // bottom-left quad (180 - 270)
return 180. + Math.tanh(yVel / xVel);
} else if (xVel < 0) { // Top left quad (270 - 360)
return 360 - Math.tanh(yVel / xVel);
} else if (yVel < 0) {
return 180 - Math.tanh(yVel / xVel);
} else {
return Math.tanh(yVel / xVel);
}
}
} }
@@ -34,9 +34,6 @@ public class ExistenceSystem extends ECSSystem{
} }
@Override @Override
public void update() {
}
public void update(double dt){ public void update(double dt){
Queue<Entity> deletions = new LinkedList<>(); Queue<Entity> deletions = new LinkedList<>();
for (Entity entity : entities) { for (Entity entity : entities) {
@@ -24,7 +24,7 @@ public class LogUpdateSystem extends ECSSystem{
} }
@Override @Override
public void update() { public void update(double dt) {
for (Entity entity : entities) { for (Entity entity : entities) {
Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class); Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class);
System.out.println(String.format("X: %.6g, Y: %.6g", pos.x, pos.y)); System.out.println(String.format("X: %.6g, Y: %.6g", pos.x, pos.y));
@@ -30,11 +30,6 @@ public class PhysicsSystem extends ECSSystem {
} }
@Override @Override
public void update() {
// TODO Auto-generated method stub
}
public void update(double dt){ public void update(double dt){
for (Entity entity : entities) { for (Entity entity : entities) {
Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class); Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class);
@@ -14,6 +14,7 @@ import javafx.stage.Stage;
import nz.ac.massey.javaecs.ECSSystem; import nz.ac.massey.javaecs.ECSSystem;
import nz.ac.massey.javaecs.Engine; import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity; import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.App;
import nz.ac.massey.javaecs.examples.Components.BoxRender; import nz.ac.massey.javaecs.examples.Components.BoxRender;
import nz.ac.massey.javaecs.examples.Components.Render; import nz.ac.massey.javaecs.examples.Components.Render;
import nz.ac.massey.javaecs.examples.Components.TextRender; import nz.ac.massey.javaecs.examples.Components.TextRender;
@@ -24,8 +25,8 @@ public class RenderSystem extends ECSSystem{
Engine gameEngine; Engine gameEngine;
Thread renderThread; Thread renderThread;
double renderScale; double renderScale;
int screenX = 1024; int screenX = 512;
int screenY = 1024; int screenY = 512;
public RenderSystem(Engine gameEngine, double renderScale){ public RenderSystem(Engine gameEngine, double renderScale){
this.gameEngine = gameEngine; this.gameEngine = gameEngine;
@@ -44,7 +45,8 @@ public class RenderSystem extends ECSSystem{
} }
@Override @Override
public void update() { public void update(double dt) {
// This approach needs reconsidering, as it creates an excessive amount of objects that
Group renderScene = new Group(); Group renderScene = new Group();
for (Entity entity : entities) { for (Entity entity : entities) {
if (((Render)gameEngine.getComponentData(entity, Render.class)).renderType == BoxRender.class){ if (((Render)gameEngine.getComponentData(entity, Render.class)).renderType == BoxRender.class){
@@ -53,8 +55,8 @@ public class RenderSystem extends ECSSystem{
Rectangle rect = new Rectangle(box.xSize* renderScale, box.ySize * renderScale); Rectangle rect = new Rectangle(box.xSize* renderScale, box.ySize * renderScale);
rect.setFill(new Color(box.r, box.g, box.b, box.a)); rect.setFill(new Color(box.r, box.g, box.b, box.a));
rect.setX(12 + (vec2d.x * renderScale)); rect.setX(6 + (vec2d.x * renderScale));
rect.setY(1012 - (vec2d.y * renderScale) - rect.getHeight()); rect.setY(506 - (vec2d.y * renderScale) - rect.getHeight());
renderScene.getChildren().add(rect); renderScene.getChildren().add(rect);
} }
else if (((Render)gameEngine.getComponentData(entity, Render.class)).renderType == TextRender.class){ else if (((Render)gameEngine.getComponentData(entity, Render.class)).renderType == TextRender.class){
@@ -99,9 +101,11 @@ public class RenderSystem extends ECSSystem{
public void start(Stage primaryStage) throws Exception { public void start(Stage primaryStage) throws Exception {
// based on the colorful circles sample at https://docs.oracle.com/javase/8/javafx/get-started-tutorial/animation.htm // based on the colorful circles sample at https://docs.oracle.com/javase/8/javafx/get-started-tutorial/animation.htm
root = new Group(); root = new Group();
Scene scene = new Scene(root, 1024, 1024, Color.BLACK); Scene scene = new Scene(root, 512, 512, Color.BLACK);
primaryStage.setScene(scene); primaryStage.setScene(scene);
primaryStage.show(); primaryStage.show();
// Signal the renderer is ready
App.rendererReadySemaphore.release();
} }
public static void run(){ public static void run(){
@@ -23,7 +23,7 @@ public class ReportSystem extends ECSSystem{
} }
@Override @Override
public void update() { public void update(double dt) {
for (Entity entity : entities) { for (Entity entity : entities) {
TextRender text = (TextRender)gameEngine.getComponentData(entity, TextRender.class); TextRender text = (TextRender)gameEngine.getComponentData(entity, TextRender.class);
text.content = "Num Entities: " + gameEngine.getNumEntities(); text.content = "Num Entities: " + gameEngine.getNumEntities();
+17
View File
@@ -0,0 +1,17 @@
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 80
[*.sh]
end_of_line = lf
[*.java]
indent_size = 4
max_line_length = 120
+2
View File
@@ -0,0 +1,2 @@
# When shell scripts end in CRLF, bash gives a cryptic error message
*.sh text eol=lf
+28
View File
@@ -0,0 +1,28 @@
#
# Standard Maven .gitignore
#
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
#
# IntelliJ
#
*.iml
.idea/*
!.idea/runConfigurations/
#
# Visual Studio Code
#
.settings/
.classpath
.factorypath
.project
.vscode/
+4
View File
@@ -0,0 +1,4 @@
language: java
jdk: openjdk8
after_success:
- mvn coveralls:report
+200
View File
@@ -0,0 +1,200 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>nz.ac.massey.javaecs.examples</groupId>
<artifactId>demo2</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>5.6.0</junit.version>
<maven-enforcer-plugin.version>3.0.0-M3</maven-enforcer-plugin.version>
<maven-checkstyle-plugin.version>3.1.0</maven-checkstyle-plugin.version>
<checkstyle.version>8.29</checkstyle.version>
<checkstyle-rules.version>4.0.1</checkstyle-rules.version>
<maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>
<jacoco-maven-plugin.version>0.8.4</jacoco-maven-plugin.version>
<maven-javadoc-plugin.version>3.0.0</maven-javadoc-plugin.version>
<coveralls-maven-plugin.version>4.3.0</coveralls-maven-plugin.version>
<!-- JaCoCo thresholds. Increase gradually as you add tests. -->
<jacoco.unit-tests.limit.instruction-ratio>0%</jacoco.unit-tests.limit.instruction-ratio>
<jacoco.unit-tests.limit.branch-ratio>0%</jacoco.unit-tests.limit.branch-ratio>
<jacoco.unit-tests.limit.class-complexity>20</jacoco.unit-tests.limit.class-complexity>
<jacoco.unit-tests.limit.method-complexity>5</jacoco.unit-tests.limit.method-complexity>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>nz.ac.massey.javaecs</groupId>
<artifactId>javaecs</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${maven-enforcer-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>3.6.3</version>
</requireMavenVersion>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${maven-checkstyle-plugin.version}</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>${checkstyle.version}</version>
</dependency>
<dependency>
<groupId>com.github.ngeor</groupId>
<artifactId>checkstyle-rules</artifactId>
<version>${checkstyle-rules.version}</version>
</dependency>
</dependencies>
<configuration>
<configLocation>com/github/ngeor/checkstyle.xml</configLocation>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<skip>${skipTests}</skip>
</configuration>
<executions>
<execution>
<id>checkstyle</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>check-unit-test</id>
<phase>test</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>INSTRUCTION</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco.unit-tests.limit.instruction-ratio}</minimum>
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco.unit-tests.limit.branch-ratio}</minimum>
</limit>
</limits>
</rule>
<rule>
<element>CLASS</element>
<limits>
<limit>
<counter>COMPLEXITY</counter>
<value>TOTALCOUNT</value>
<maximum>${jacoco.unit-tests.limit.class-complexity}</maximum>
</limit>
</limits>
</rule>
<rule>
<element>METHOD</element>
<limits>
<limit>
<counter>COMPLEXITY</counter>
<value>TOTALCOUNT</value>
<maximum>${jacoco.unit-tests.limit.method-complexity}</maximum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
</plugin>
</plugins>
</reporting>
<profiles>
<!-- Publish coverage report to Coveralls, only when running in Travis. -->
<profile>
<id>travis</id>
<activation>
<property>
<name>env.TRAVIS</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>${coveralls-maven-plugin.version}</version>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,120 @@
package nz.ac.massey.javaecs.examples;
import java.io.FileInputStream;
import java.util.concurrent.Semaphore;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.Components.Control;
import nz.ac.massey.javaecs.examples.Components.Input;
import nz.ac.massey.javaecs.examples.Components.Render;
import nz.ac.massey.javaecs.examples.Components.Sprite;
import nz.ac.massey.javaecs.examples.Components.Vec2D;
import nz.ac.massey.javaecs.examples.Systems.ControlSystem;
import nz.ac.massey.javaecs.examples.Systems.PlayerSystem;
import nz.ac.massey.javaecs.examples.Systems.RenderSystem;
/**
* Hello world!
*/
public class App {
static App thisApp;
public App() {
thisApp = this;
}
static Engine gameEngine;
public static Stage worldStage;
public static Group worldGroup;
static Integer syncManager = 0;
static Semaphore rendererFinished = new Semaphore(0);
/**
* Says hello to the world.
* @param args The arguments of the program.
*/
public static void main(String[] args) throws Exception{
/************************************
** Initialise engine **
*************************************/
gameEngine = new Engine(16384);
/************************************
** Register game components **
*************************************/
gameEngine.registerComponent(Control.class);
gameEngine.registerComponent(Render.class);
gameEngine.registerComponent(Sprite.class);
gameEngine.registerComponent(Vec2D.class);
gameEngine.registerComponent(Input.class);
/************************************
** Register and initialise systems **
*************************************/
ControlSystem controlSystem = new ControlSystem(gameEngine);
gameEngine.registerSystem(ControlSystem.class, controlSystem);
RenderSystem renderSystem = new RenderSystem(gameEngine, 5.);
gameEngine.registerSystem(RenderSystem.class, renderSystem);
PlayerSystem playerSystem = new PlayerSystem(gameEngine);
gameEngine.registerSystem(PlayerSystem.class, playerSystem);
/************************************
** Create known entities **
*************************************/
// Input controller - gets player input
Entity inputEntity = gameEngine.createEntity();
gameEngine.addComponent(inputEntity, Input.class, new Input());
Entity playerEntity = gameEngine.createEntity();
gameEngine.addComponent(playerEntity, Vec2D.class, new Vec2D(25,25));
gameEngine.addComponent(playerEntity, Render.class, new Render(Sprite.class));
gameEngine.addComponent(playerEntity, Control.class, new Render(Control.class));
// Load the sprite
System.err.println(System.getProperty("user.dir"));
Image image = new Image(new FileInputStream("sprite.png"));
gameEngine.addComponent(playerEntity, Sprite.class, new Sprite(image, 50, 50));
// Push rendering into its own thread (to meet the design principle of a JavaFX program)
Thread renderThread = new Thread(new RenderStarter());
renderThread.start();
// Use a semaphore to block until the renderer is set-up
rendererFinished.acquire();
/************************************
** Run init() on the systems **
*************************************/
controlSystem.init(worldStage);
playerSystem.init(inputEntity);
renderSystem.init(worldGroup);
double dt = 0.001;
double frameRate = 1.0 / 144; // 1 second divided by target number of frames
boolean exit = false;
long startTime = System.nanoTime();
while (!exit){
// Run system updates
controlSystem.update(dt);
playerSystem.update(dt);
renderSystem.update(dt);
dt = (System.nanoTime() - startTime) / 1e9; // convert nanoseconds to seconds
startTime = System.nanoTime();
if (dt < frameRate){
Thread.sleep((int)((frameRate-dt)*1000));
dt = (System.nanoTime() - startTime) / 1e9;
startTime = System.nanoTime();
}
}
renderThread.join(); // Wait for any render task to exit
}
}
@@ -0,0 +1,5 @@
package nz.ac.massey.javaecs.examples.Components;
public class Control {
public int input = -1;
}
@@ -0,0 +1,9 @@
package nz.ac.massey.javaecs.examples.Components;
import java.util.concurrent.atomic.AtomicInteger;
public class Input {
// As this is a user-input- (i.e. timeframe in 10's or 100's of milliseconds) -derived value, the performance impact of
// AtomicInteger is irrelevant compared to its synchronisation ability.
public AtomicInteger input = new AtomicInteger(-1);
}
@@ -0,0 +1,11 @@
package nz.ac.massey.javaecs.examples.Components;
import java.lang.reflect.Type;
public class Render {
public Type renderType;
public Render(Type t){
renderType = t;
}
}
@@ -0,0 +1,15 @@
package nz.ac.massey.javaecs.examples.Components;
import javafx.scene.image.Image;
public class Sprite {
public Image sprite;
public Integer height;
public Integer width;
public Sprite(Image sprite, int height, int width){
this.sprite = sprite;
this.width = width;
this.height = height;
}
}
@@ -0,0 +1,11 @@
package nz.ac.massey.javaecs.examples.Components;
public class Vec2D {
public double x;
public double y;
public Vec2D(double x, double y){
this.x = x;
this.y = y;
}
}
@@ -0,0 +1,28 @@
package nz.ac.massey.javaecs.examples;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class JFXView extends Application {
public static Group root;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("JavaECS Demo 2");
App.worldGroup = new Group();
App.worldStage = primaryStage;
Scene scene = new Scene(App.worldGroup, 512, 512, Color.BLACK);
primaryStage.setScene(scene);
primaryStage.show();
// Notifiy that the renderer is ready
App.rendererFinished.release();
}
public static void run(){
launch(new String[0]);
}
}
@@ -0,0 +1,16 @@
package nz.ac.massey.javaecs.examples;
import javafx.scene.Group;
// Add a renderer
public class RenderStarter implements Runnable{
@Override
public void run() {
JFXView.run();
}
void updateScene(Group newGroup){
JFXView.root.getChildren().clear();
JFXView.root.getChildren().add(newGroup);
}
}
@@ -0,0 +1,81 @@
package nz.ac.massey.javaecs.examples.Systems;
import java.util.BitSet;
import javafx.application.Platform;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import nz.ac.massey.javaecs.ECSSystem;
import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.Components.Input;
/**
* The control system creates a handler for input in the world stage.
* It then passes input events as they occur to the Input component
* The ControlSystem reads this input every frame update and enacts
* on the player controller
*/
public class ControlSystem extends ECSSystem {
Engine gameEngine;
Entity inputEntity;
public ControlSystem(Engine gamEngine){
this.gameEngine = gamEngine;
registrationSet = new BitSet();
registrationSet.set(gameEngine.getComponentIndex(Input.class));
}
public void init(Stage world) {
// use a single entity to control inputs, it is present in the world stage
// and is responsible for collecting & passing data
inputEntity = entities.iterator().next();
// Add an event handler to the stage. This
Platform.runLater(new Runnable(){
@Override
public void run() {
world.addEventHandler(KeyEvent.KEY_PRESSED, (key) -> {
if(key.getCode()==KeyCode.W) {
updateKeyPress(0);
System.err.println("W pressed");
}
else if(key.getCode()==KeyCode.S) {
updateKeyPress(1);
System.err.println("S pressed");
}
else if(key.getCode()==KeyCode.A) {
updateKeyPress(2);
System.err.println("A pressed");
}
else if(key.getCode()==KeyCode.D) {
updateKeyPress(3);
System.err.println("D pressed");
}
});
}
});
}
@Override
public void update(double dt) {
//Input inputUpdate = (Input)gameEngine.getComponentData(inputEntity, Input.class);
// TODO Auto-generated method stub
}
// Updates the input's keypressed state
protected void updateKeyPress(int dir){
Input inputUpdate = (Input)gameEngine.getComponentData(inputEntity, Input.class);
inputUpdate.input.set(dir);
}
@Override
public void init() throws Exception {
// TODO Auto-generated method stub
}
}
@@ -0,0 +1,59 @@
package nz.ac.massey.javaecs.examples.Systems;
import java.util.BitSet;
import nz.ac.massey.javaecs.ECSSystem;
import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.Components.Control;
import nz.ac.massey.javaecs.examples.Components.Input;
import nz.ac.massey.javaecs.examples.Components.Sprite;
import nz.ac.massey.javaecs.examples.Components.Vec2D;
public class PlayerSystem extends ECSSystem{
Engine gameEngine;
Entity inputEntity; // Entity which recieves event data
public PlayerSystem(Engine gameEngine){
this.gameEngine = gameEngine;
registrationSet = new BitSet();
registrationSet.set(gameEngine.getComponentIndex(Control.class));
}
public void init(Entity inputEntity){
this.inputEntity = inputEntity;
}
@Override
public void init() throws Exception {
// TODO Auto-generated method stub
}
@Override
public void update(double dt) {
int state = ((Input)gameEngine.getComponentData(inputEntity, Input.class)).input.get();
// The value of the input may change before control leaves here; sychronisation isn't
// hugely important through this section. So we can just ignore the change
for (Entity entity : entities) {
Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class);
Sprite sprite = (Sprite)gameEngine.getComponentData(entity, Sprite.class);
if (state == 0){ // W
pos.y -= sprite.height/2;
}
else if (state == 1){ // S
pos.y += sprite.height/2;
}
else if (state == 2){ // A
pos.x -= sprite.width/2;
}
else if (state == 3){ // D
pos.x += sprite.width/2;
}
}
// Finally, unset the state
((Input)gameEngine.getComponentData(inputEntity, Input.class)).input.set(-1); // Unset the state, it has been handled
}
}
@@ -0,0 +1,69 @@
package nz.ac.massey.javaecs.examples.Systems;
import java.util.BitSet;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.image.ImageView;
import nz.ac.massey.javaecs.ECSSystem;
import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.Components.Render;
import nz.ac.massey.javaecs.examples.Components.Sprite;
import nz.ac.massey.javaecs.examples.Components.Vec2D;
/*
* This render system is different from demo 1, as its main functionality is provided directly by the program, not as an entity.
*/
public class RenderSystem extends ECSSystem {
Engine gameEngine;
Group renderGroup;
Thread renderThread;
double renderScale;
int screenX = 512;
int screenY = 512;
public RenderSystem(Engine gameEngine, double renderScale){
this.gameEngine = gameEngine;
// Set registrations
registrationSet = new BitSet();
registrationSet.set(gameEngine.getComponentIndex(Render.class));
this.renderScale = renderScale;
}
public void init(Group renderGroup) throws Exception {
this.renderGroup = renderGroup;
}
@Override
public void init() throws Exception {
// TODO Auto-generated method stub
}
@Override
public void update(double dt) {
Group frame = new Group();
for (Entity entity : entities) {
Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class);
if (((Render)gameEngine.getComponentData(entity, Render.class)).renderType == Sprite.class){
// Render the sprite
Sprite sprite = (Sprite)gameEngine.getComponentData(entity, Sprite.class);
ImageView spriteRender = new ImageView(sprite.sprite);
spriteRender.setX(pos.x);
spriteRender.setY(pos.y);
spriteRender.setFitWidth(sprite.width);
spriteRender.setFitHeight(sprite.height);
frame.getChildren().add(spriteRender);
}
}
// Must be run by the UI thread, not the main thread.
// This dispatches the operation run() to the UI.
Platform.runLater(new Runnable(){
@Override
public void run() {
renderGroup.getChildren().clear();
renderGroup.getChildren().add(frame);
}
});
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,18 @@
package nz.ac.massey.javaecs.examples;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Unit test for simple App.
*/
class AppTest {
/**
* Rigorous Test.
*/
@Test
void testApp() {
assertEquals(1, 1);
}
}
+3
View File
@@ -26,3 +26,6 @@ buildNumber.properties
.factorypath .factorypath
.project .project
.vscode/ .vscode/
# Ignore logs, these came from an error in the VM
*.log
+5
View File
@@ -35,6 +35,11 @@
<version>${junit.version}</version> <version>${junit.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>nz.ac.massey.javaecs</groupId>
<artifactId>javaecs</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
@@ -15,9 +15,51 @@ public final class App {
/** /**
* Says hello to the world. * Says hello to the world.
* @param args The arguments of the program. * @param args The arguments of the program.
* @throws InterruptedException
*/ */
public static void main(String[] args) { public static void main(String[] args) throws InterruptedException {
Engine engine = new Engine(); int nEntities = 1_000_000;
double startTime = System.nanoTime();
Engine engine = new Engine(nEntities);
double endTime = System.nanoTime();
System.out.println("Constructor Time taken: " + (endTime - startTime) / 1e6+ " ms " + "("+ (endTime - startTime) / 1e9 + " seconds )");
engine.registerComponent(ComflabulationComponent.class);
engine.registerComponent(DirectionComponent.class);
engine.registerComponent(PositionComponent.class);
ComflabSystem comflabSystem = new ComflabSystem(engine);
engine.registerSystem(ComflabSystem.class, comflabSystem);
MovementSystem movementSystem = new MovementSystem(engine);
engine.registerSystem(MovementSystem.class, movementSystem);
startTime = System.nanoTime();
for (int i = 0; i < nEntities; i++) {
Entity entity = engine.createEntity();
engine.addComponent(entity, PositionComponent.class, new PositionComponent());
engine.addComponent(entity, DirectionComponent.class, new DirectionComponent());
if (i % 2 != 0){
engine.addComponent(entity, ComflabulationComponent.class, new ComflabulationComponent());
}
}
endTime = System.nanoTime();
System.out.println("Entity creation Time taken: " + (endTime - startTime) / 1e6+ " ms " + "("+ (endTime - startTime) / 1e9 + " seconds )");
// Delay as object creation is multithreaded in at least OpenJDK 1.8 - lets use see the single core performance
Thread.sleep(5000);
double dt = 1.0f/60.0f;
startTime = System.nanoTime();
movementSystem.update(dt);
comflabSystem.update(dt);
endTime = System.nanoTime();
System.out.println("Single Loop Time taken: " + (endTime - startTime) / 1e6+ " ms " + "("+ (endTime - startTime) / 1e9 + " seconds )");
System.out.println("Hello World!"); System.out.println("Hello World!");
} }
} }
@@ -0,0 +1,22 @@
package nz.ac.massey.javaecs.examples.Components;
public class ComflabulationComponent {
public double thingy;
public int dingy;
public boolean mingy;
public String stringy;
public ComflabulationComponent(double thingy, int dingy, boolean mingy, String stringy){
this.thingy = thingy;
this.dingy = dingy;
this.mingy = mingy;
this.stringy = stringy;
}
public ComflabulationComponent(){
thingy = 0.0f;
dingy = 0;
mingy = false;
stringy = "";
}
}
@@ -0,0 +1,16 @@
package nz.ac.massey.javaecs.examples.Components;
public class DirectionComponent {
public double x;
public double y;
public DirectionComponent(double x, double y){
this.x = x;
this.y = y;
}
public DirectionComponent(){
x = 0.0f;
y = 0.0f;
}
}
@@ -0,0 +1,16 @@
package nz.ac.massey.javaecs.examples.Components;
public class PositionComponent {
public double x;
public double y;
public PositionComponent(double x, double y){
this.x = x;
this.y = y;
}
public PositionComponent(){
x = 0.0f;
y = 0.0f;
}
}
@@ -0,0 +1,34 @@
package nz.ac.massey.javaecs.examples.Systems;
import java.util.BitSet;
import nz.ac.massey.javaecs.ECSSystem;
import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.Components.ComflabulationComponent;
public class ComflabSystem extends ECSSystem {
Engine ecs;
public ComflabSystem(Engine ecs){
this.ecs = ecs;
registrationSet = new BitSet();
registrationSet.set(ecs.getComponentIndex(ComflabulationComponent.class));
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public void update(double dt) {
for (Entity entity : entities) {
ComflabulationComponent comflab = (ComflabulationComponent)ecs.getComponentData(entity, ComflabulationComponent.class);
comflab.thingy *= 1.000001;
comflab.mingy = !comflab.mingy;
comflab.dingy++;
}
}
}
@@ -0,0 +1,39 @@
package nz.ac.massey.javaecs.examples.Systems;
import java.util.BitSet;
import nz.ac.massey.javaecs.ECSSystem;
import nz.ac.massey.javaecs.Engine;
import nz.ac.massey.javaecs.Entity;
import nz.ac.massey.javaecs.examples.Components.DirectionComponent;
import nz.ac.massey.javaecs.examples.Components.PositionComponent;
public class MovementSystem extends ECSSystem {
Engine ecs;
public MovementSystem(Engine ecs){
this.ecs = ecs;
registrationSet = new BitSet();
registrationSet.set(ecs.getComponentIndex(PositionComponent.class));
registrationSet.set(ecs.getComponentIndex(DirectionComponent.class));
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public void update(double dt) {
for (Entity entity : entities) {
PositionComponent position = (PositionComponent)ecs.getComponentData(entity, PositionComponent.class);
DirectionComponent direction = (DirectionComponent)ecs.getComponentData(entity, DirectionComponent.class);
position.x += direction.x * dt;
position.y += direction.y * dt;
}
}
}