Skip to content

Commit c81adf3

Browse files
committed
implementing ECS pattern
1 parent f1a0ad8 commit c81adf3

19 files changed

+1943
-0
lines changed

entity-component-system/README.md

Whitespace-only changes.
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
@startuml
2+
package com.iluwatar {
3+
class App {
4+
+ App()
5+
+ main(args : String[]) {static}
6+
}
7+
abstract class Component {
8+
- isEnabled : boolean
9+
- name : String
10+
- parent : Entity
11+
+ Component()
12+
+ getEnabled() : boolean
13+
+ getName() : String
14+
+ getParent() : Entity
15+
+ setEnabled(isEnabled : boolean)
16+
+ setName(name : String)
17+
+ setParent(parent : Entity)
18+
+ update(float) {abstract}
19+
}
20+
class Entity {
21+
- children : List<Entity>
22+
- components : List<Component>
23+
- entityId : UUID
24+
- gameSystem : GameSystem
25+
- isEnabled : boolean
26+
- name : String
27+
- parent : Entity
28+
- transform : TransformComponent
29+
+ Entity(entityName : String)
30+
+ addChild(child : Entity)
31+
+ addComponent(component : Component)
32+
+ getChildren() : List<Entity>
33+
+ getComponent(componentName : String) : Component
34+
+ getEntityId() : UUID
35+
+ getGameSystem() : GameSystem
36+
+ getMeshRenderComponents() : List<Component>
37+
+ getName() : String
38+
+ getParent() : Entity
39+
+ getTransformComponent() : TransformComponent
40+
+ isEnabled() : boolean
41+
+ removeChild(child : Entity)
42+
+ removeComponent(component : Component)
43+
+ renderEntity()
44+
+ setEnabled(enabled : boolean)
45+
+ setGameSystem(gameSystem : GameSystem)
46+
+ setIsEnabled(isEnabled : boolean)
47+
+ setName(name : String)
48+
+ setParent(newParent : Entity)
49+
+ update(deltaTime : float)
50+
}
51+
class GameSystem {
52+
- entities : List<Entity>
53+
+ GameSystem()
54+
+ addEntity(entity : Entity)
55+
- calculateDistance(point1 : float[], point2 : float[]) : float
56+
+ getSystemMatrix(entity : Entity) : float[][]
57+
+ getSystemPosition(entity : Entity) : float[]
58+
- multiplyMatrices(matrix1 : float[][], matrix2 : float[][]) : float[][]
59+
+ removeEntity(entity : Entity)
60+
+ renderSystem()
61+
+ sortEntitiesByDistance(referencePoint : float[])
62+
+ update(deltaTime : float)
63+
}
64+
class HealthComponent {
65+
- currentHealth : float
66+
- isAlive : boolean
67+
- logger : Logger {static}
68+
- maxHealth : float
69+
+ HealthComponent(maxHealth : float)
70+
+ applyDamage(damage : float)
71+
+ getCurrentHealth() : float
72+
+ getMaxHealth() : float
73+
+ heal(amount : float)
74+
+ isAlive() : boolean
75+
+ setAlive(isAlive : boolean)
76+
+ setCurrentHealth(currentHealth : float)
77+
+ setMaxHealth(maxHealth : float)
78+
+ update(deltaTime : float)
79+
}
80+
class TransformComponent {
81+
- position : float[]
82+
- rotation : float[]
83+
- scale : float[]
84+
+ TransformComponent()
85+
+ TransformComponent(initPosition : float[], initRotation : float[], initScale : float[])
86+
- applyRotation(matrix : float[][])
87+
+ getPosition() : float[]
88+
+ getRotation() : float[]
89+
+ getScale() : float[]
90+
+ getTransformMatrix() : float[][]
91+
+ setPosition(position : float[])
92+
+ setRotation(eulerAngles : float[])
93+
+ setScale(scale : float[])
94+
+ update(deltaTime : float)
95+
}
96+
class VelocityComponent {
97+
- logger : Logger {static}
98+
- velocityX : float
99+
- velocityY : float
100+
- velocityZ : float
101+
+ VelocityComponent(velocityX : float, velocityY : float, velocityZ : float)
102+
+ applyForce(forceX : float, forceY : float, forceZ : float)
103+
+ applyFriction(frictionCoefficient : float)
104+
+ getVelocityX() : float
105+
+ getVelocityY() : float
106+
+ getVelocityZ() : float
107+
+ setVelocityX(velocityX : float)
108+
+ setVelocityY(velocityY : float)
109+
+ setVelocityZ(velocityZ : float)
110+
+ update(deltaTime : float)
111+
}
112+
}
113+
Entity --> "-transform" TransformComponent
114+
Entity --> "-parent" Entity
115+
Entity --> "-children" Entity
116+
Entity --> "-gameSystem" GameSystem
117+
Entity --> "-components" Component
118+
HealthComponent --|> Component
119+
TransformComponent --|> Component
120+
VelocityComponent --|> Component
121+
@enduml

entity-component-system/pom.xml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
5+
6+
The MIT License
7+
Copyright © 2014-2022 Ilkka Seppälä
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
-->
28+
<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/xsd/maven-4.0.0.xsd">
29+
<parent>
30+
<artifactId>java-design-patterns</artifactId>
31+
<groupId>com.iluwatar</groupId>
32+
<version>1.26.0-SNAPSHOT</version>
33+
</parent>
34+
<groupId>com.iluwatar</groupId>
35+
<version>1.26.0-SNAPSHOT</version>
36+
<modelVersion>4.0.0</modelVersion>
37+
<artifactId>entity-component-system</artifactId>
38+
<dependencies>
39+
<dependency>
40+
<groupId>org.junit.jupiter</groupId>
41+
<artifactId>junit-jupiter-engine</artifactId>
42+
<scope>test</scope>
43+
</dependency>
44+
<dependency>
45+
<groupId>org.junit.jupiter</groupId>
46+
<artifactId>junit-jupiter-api</artifactId>
47+
<scope>test</scope>
48+
</dependency>
49+
<dependency>
50+
<groupId>org.junit.jupiter</groupId>
51+
<artifactId>junit-jupiter-api</artifactId>
52+
<scope>test</scope>
53+
</dependency>
54+
</dependencies>
55+
<build>
56+
<plugins>
57+
<plugin>
58+
<groupId>org.apache.maven.plugins</groupId>
59+
<artifactId>maven-assembly-plugin</artifactId>
60+
<executions>
61+
<execution>
62+
<configuration>
63+
<archive>
64+
<manifest>
65+
<mainClass>com.iluwatar.entity-component-system.Main</mainClass>
66+
</manifest>
67+
</archive>
68+
</configuration>
69+
</execution>
70+
</executions>
71+
</plugin>
72+
</plugins>
73+
</build>
74+
</project>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
3+
*
4+
* The MIT License
5+
* Copyright © 2014-2022 Ilkka Seppälä
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package com.iluwatar;
26+
27+
/**
28+
* The main entry point for the application.
29+
* This class simulates a game loop where entities are created, updated, and their states are modified.
30+
*/
31+
public class App {
32+
33+
/**
34+
* The main method that runs the application.
35+
* It creates entities, adds components, updates them over several frames,
36+
* and demonstrates applying damage and forces to entities.
37+
*
38+
* @param args Command-line arguments (not used in this application)
39+
*/
40+
public static void main(String[] args) {
41+
// Create example entities
42+
Entity entity1 = new Entity("Entity1");
43+
Entity entity2 = new Entity("Entity2");
44+
45+
// Set up some transform components (position, rotation, scale)
46+
TransformComponent transform1 = new TransformComponent(new float[]{0.0f, 0.0f, 0.0f},
47+
new float[]{0.0f, 0.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f});
48+
TransformComponent transform2 = new TransformComponent(new float[]{5.0f, 0.0f, 0.0f},
49+
new float[]{0.0f, 45.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f});
50+
51+
// Set the transform components for each entity
52+
entity1.addComponent(transform1);
53+
entity2.addComponent(transform2);
54+
55+
// Create a health component for entity1 with initial health of 100
56+
HealthComponent health1 = new HealthComponent(100); // Ensure HealthComponent is implemented
57+
entity1.addComponent(health1);
58+
59+
// Create a velocity component for entity1
60+
VelocityComponent velocity1 = new VelocityComponent(1.0f, 0.0f, 0.0f);
61+
entity1.addComponent(velocity1);
62+
63+
// Set up a system and add entities to the system
64+
GameSystem gameSystem = new GameSystem();
65+
gameSystem.addEntity(entity1);
66+
gameSystem.addEntity(entity2);
67+
68+
// Simulate game update loop (e.g., 60 FPS)
69+
float deltaTime = 1.0f / 60.0f; // 60 FPS
70+
71+
// Simulate for a few frames
72+
for (int i = 0; i < 10; i++) {
73+
System.out.println("Frame: " + (i + 1));
74+
75+
// Update all entities in the system
76+
gameSystem.update(deltaTime);
77+
78+
// Apply some damage to entity1's health component at frame 6
79+
if (i == 5) {
80+
health1.applyDamage(30);
81+
System.out.println("Entity1's health after damage: " + health1.getCurrentHealth());
82+
}
83+
84+
// Apply some force to entity1's velocity at frame 3
85+
if (i == 3) {
86+
velocity1.applyForce(0.5f, 0.0f, 0.0f);
87+
System.out.println("Entity1's velocity after force: (" + velocity1.getVelocityX() + ", "
88+
+ velocity1.getVelocityY() + ", " + velocity1.getVelocityZ() + ")");
89+
}
90+
91+
// Render the system (optional rendering logic can be added here)
92+
gameSystem.renderSystem();
93+
}
94+
95+
// After the simulation, check final entity states
96+
System.out.println("\nFinal Entity States:");
97+
System.out.println("Entity1 position: " + entity1.getTransformComponent().getPosition()[0] + ", "
98+
+ entity1.getTransformComponent().getPosition()[1] + ", "
99+
+ entity1.getTransformComponent().getPosition()[2]);
100+
System.out.println("Entity1 velocity: " + velocity1.getVelocityX() + ", "
101+
+ velocity1.getVelocityY() + ", " + velocity1.getVelocityZ());
102+
System.out.println("Entity1 health: " + health1.getCurrentHealth());
103+
}
104+
}

0 commit comments

Comments
 (0)