| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
An ECS (Entity Component System) game engine framework in Java.
The repo includes two example applicaitons showing how to use the engine.
This project was developed in as an academic exercise in ECS (Entity Component System) game engine architecture. The engine implements the core features of a typical general purpose ECS game engine.
This Java version is a port of an earlier C++ version I wrote in 2004. The academic exercise in 2014 required a Java program. So I decided to save some time and port the core features of my original C++ version to Java.
Entities
Components
Systems
ECS Game Engine
A number of generic utility and support libraries are included with the engine to handle peripheral functionality around the core ECS engine.
CommandManager
EventManager
GlobalCache
ResourceManager
AWTJavaPlatform
UtilityClassLibrary
The included demo implements a particle physics simulation that demonstrates all features of the ECA game engine.
The particle simulation itself simulates particles interacting under configurable physics:
Particles are organized into four color-coded groups (red, green, blue, yellow), each with distinct physical properties. Application and simulation properties can be adjusted via settings.properties. Particle group sizes may be set in two ways, either in settings.properties or via the settings menu in the application.
| Key | Action |
|---|---|
| Up / Down Arrow | Cycle through menu buttons |
| Left / Right Arrow | Adjust particle count on settings screen |
| Enter | Activate the selected button |
| Esc | Go back one menu level |
| Key | Action |
|---|---|
| Arrow Keys | Accelerate the selected particle |
| Tab | Select the next particle |
| Shift + Tab | Select the previous particle |
| P | Pause / unpause |
| T | Toggle particle trails |
| W | Toggle wireframe overlay |
| Esc | Deselect all particles, or exit to menu |
v2/
├── build.sh Build script (jpackage)
├── Library/
│ ├── ECSGameEngine/ ECS core (engine, entity, component, system)
│ ├── CommandManager/ Command queue pattern for input decoupling
│ ├── ResourceManager/ Asset registry with load/unload lifecycle
│ ├── AWTJavaPlatform/ Swing/AWT windowing and double-buffered rendering
│ ├── UtilityClassLibrary/ Vector2D, GMath, ApplicationSettings, logging
│ ├── EventManager/ Event publish/subscribe system
│ └── GlobalCache/ Cross-screen key-value data store
│
└── Demo/
├── HelloWorld/ Minimal engine demo
└── ParticleDemo/ Particle simulator (main demo)
├── settings.properties All configurable values
├── src/ Application, engines, systems, components, etc.
├── test/ JUnit 5 unit tests (569 tests)
└── Resources/ Images, fonts, sounds, text
ParticleDemo → ECSGameEngine → CommandManager → UtilityClassLibrary
→ ResourceManager
→ UtilityClassLibrary
→ AWTJavaPlatform → UtilityClassLibrary
→ GlobalCache
Open the project in IntelliJ IDEA and import the modules under Library/ and Demo/ (each module has a src folder, and most also have a test folder). Add the JUnit 5 jars from lib/junit5/ as a library for the test modules, then run Demo/ParticleDemo/src/rohin/gameengine/application/Main.java with the working directory set to the project root. For a command-line workflow, use build.sh (package) and run-tests.sh (tests). The module dependency graph is shown above under Module Dependencies.
The build script uses jpackage to create a self-contained Windows application with a bundled JRE. No Java installation is required on the target machine.
./build.sh # Portable app directory
./build.sh --installer # Windows installer (.exe) — requires WiX 3+Output is placed in build/particle-simulator/. The launcher is particle-simulator.exe.
All simulation parameters are configurable in Demo/ParticleDemo/settings.properties, including:
while running:
commandManager.flush() // execute queued commands
for each system: system.update(t) // run all systems
regulateFrameRate() // target 90 FPS
| Order | System | Role |
|---|---|---|
| 1 | ParticleGroupPropagator | Copy group properties to individual particles |
| 2 | Gravity | Newtonian gravitational attraction (F = Gm1m2/r^2) |
| 3 | Repulsion | Short-range repulsive force (smooth polynomial kernel) |
| 4 | ForceAccumulator | Resolve user input forces, apply F=ma, clear accumulators |
| 5 | Physics | Integrate velocity, apply friction |
| 6 | Collider | Boundary and particle-particle elastic collision |
| 7 | Renderer | Draw background, trails, shadows, sprites, wireframe, HUD |
All user input flows through CommandManager. Keyboard events post ICommand objects that encapsulate their effect on game state. This decouples input source from game logic. The same commands could be issued by an AI agent.
For the sake of interest, here's all the math I used in the particle demo.
Gravitational attraction between two particles using Newtonian mechanics, with a softening parameter $\epsilon$ to prevent singularities at close range.
$$\vec{d} = \vec{p}_2 - \vec{p}_1$$
$$F = \frac{G , m_1 , m_2}{|\vec{d}|^2 + \epsilon^2}$$
$$\hat{n} = \frac{\vec{d}}{|\vec{d}|}$$
$$\vec{F}_1 = F , \hat{n}, \quad \vec{F}_2 = -F , \hat{n}$$
Where:
Short-range repulsive force using a smooth quadratic kernel. Active only when particles are within a threshold distance but not overlapping. Kind of simulates the strong nuclear force.
$$d_{\min} = r_1 + r_2$$
$$d_{\text{threshold}} = 2 , d_{\min}$$
$$s = \frac{|\vec{d}| - d_{\min}}{d_{\text{threshold}} - d_{\min}}, \quad s \in [0, 1]$$
$$F = R , (1 - s)^2$$
$$\vec{F}_1 = F , \hat{n}, \quad \vec{F}_2 = -F , \hat{n}$$
Where:
All forces (gravity, repulsion, user input) are summed into a force accumulator per particle. Newton's second law converts the net force into acceleration, which is then integrated into velocity using explicit Euler integration.
$$\vec{F}_{\text{net}} = \vec{F}_{\text{gravity}} + \vec{F}_{\text{repulsion}} + \vec{F}_{\text{user}}$$
$$\vec{a} = \frac{\vec{F}_{\text{net}}}{m}$$
$$\vec{v}' = \vec{v} + \vec{a} , \Delta t$$
The force accumulator is reset to $\vec{0}$ after each frame.
Position is integrated using explicit Euler integration. Friction is applied as a per-frame damping coefficient.
$$\vec{p}' = \vec{p} + \vec{v} , \Delta t$$
$$\vec{v}' = \vec{v} \cdot k_f$$
Where:
For user-controlled particles, anisotropic friction is applied — the friction coefficient differs per axis depending on whether the user is providing input on that axis:
$$v'_x = v_x \cdot \begin{cases} k_f & \text{if user input on } x \ k_a & \text{otherwise} \end{cases}$$
$$v'_y = v_y \cdot \begin{cases} k_f & \text{if user input on } y \ k_a & \text{otherwise} \end{cases}$$
Where $k_a$ is the anisotropic friction coefficient (stronger damping on the uncontrolled axis).
Wall collisions clamp the particle position to the boundary and reflect the velocity, scaled by an elasticity coefficient $e$:
$$v'_n = -|v_n| \cdot e$$
$$p' = \text{clamp}(p, ; r, ; w - r)$$
Where $v_n$ is the velocity component normal to the wall, and $w$ is the world boundary.
Particle-particle collisions use impulse-based resolution. Overlapping particles are first separated proportionally to their masses, then an impulse is applied along the collision normal.
Overlap separation:
$$\delta = d_{\min} - |\vec{d}|$$
$$\vec{p}'_1 = \vec{p}_1 - \hat{n} \cdot \delta \cdot \frac{m_2}{m_1 + m_2}$$
$$\vec{p}'_2 = \vec{p}_2 + \hat{n} \cdot \delta \cdot \frac{m_1}{m_1 + m_2}$$
Impulse (applied only when particles are approaching, i.e., $v_{\text{rel}} < 0$):
$$v_{\text{rel}} = (\vec{v}_2 - \vec{v}_1) \cdot \hat{n}$$
$$e = \frac{e_1 + e_2}{2}$$
$$j = \frac{-(1 + e) , v_{\text{rel}}}{\dfrac{1}{m_1} + \dfrac{1}{m_2}}$$
$$\vec{v}'_1 = \vec{v}_1 - \frac{j , \hat{n}}{m_1}$$
$$\vec{v}'_2 = \vec{v}_2 + \frac{j , \hat{n}}{m_2}$$
Where:
All particle positions are stored in normalized world coordinates. The projection to screen pixels uses the screen height and a zoom factor.
$$k = h_{\text{screen}} \cdot z$$
$$x_{\text{screen}} = x_{\text{world}} \cdot k - \frac{d}{2}$$
$$y_{\text{screen}} = y_{\text{world}} \cdot k - \frac{d}{2}$$
$$d = 2 , r \cdot k$$
Where:
Released under the MIT License — Copyright © 2014 Rohin Gosling.
| Back | FazBrowse Home | New Git URL |