A classic tank battle game built purely in Java with modern language features.
Control your tank, dodge enemy fire, and destroy all opponents!
- Defeat all enemy tanks to win the match.
- Getting destroyed ends the current round immediately.
- Player bullet firing is rate-limited, with the cooldown configurable in
game.properties. - A pause overlay is shown when the game is paused, and a result overlay is shown after victory or defeat.
- Background music starts automatically and keeps looping for the whole game session.
- Press
Pto pause or resume the current match. - Press
Rto restart at any time, whether the round is still in progress or already over.
flowchart TB
classDef runtime fill:#f8fafc,stroke:#94a3b8,stroke-width:2px,color:#334155,stroke-dasharray: 5 5
classDef engine fill:#eff6ff,stroke:#3b82f6,stroke-width:2px,color:#1e3a8a
classDef entity fill:#fef2f2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d
classDef resource fill:#f0fdf4,stroke:#22c55e,stroke-width:2px,color:#14532d
classDef config fill:#faf5ff,stroke:#a855f7,stroke-width:2px,color:#581c87
classDef ext fill:#fff7ed,stroke:#ea580c,stroke-width:2px,color:#9a3412
%% --- Configuration & Bootstrap Layer ---
subgraph BootLayer ["Bootstrap & Config (JEP 395)"]
Props[/"game.properties"/]
Loader("ConfigLoader")
Record{{"GameConfig"}}
Props -->|"parse"| Loader
Loader -->|"reflect bound"| Record
end
%% --- Runtime Engine Layer ---
subgraph EngineLayer ["Core Engine (JEP 444 & 477)"]
direction LR
Main(("Instance Main"))
VThread[["Virtual Thread Loop"]]
Frame["TankFrame (Double Buffer)"]
Input[/"Key Event Handler"/]
Main -->|"start"| VThread
VThread == "tick (50ms)" === Frame
Input -.->|"mutate state"| Frame
end
%% --- Domain Entity Layer ---
subgraph DomainLayer ["Domain Entities & Physics"]
Tank("Tank (AI & Movement)")
Bullet("Bullet (Projectile)")
Explode("Explode (Animation)")
Tank -->|"fire"| Bullet
Bullet -->|"hit & rollback"| Tank
Bullet -->|"spawn"| Explode
end
%% --- Infrastructure Layer ---
subgraph InfraLayer ["Infrastructure & Media"]
Audio[("Audio System")]
ResMgr[("Resource Manager")]
ImageProc["Image Processor"]
ResMgr -->|"AffineTransform"| ImageProc
end
%% --- Dependencies ---
Record -.->|"inject config"| EngineLayer
Record -.->|"inject config"| DomainLayer
Record -.->|"inject paths"| InfraLayer
EngineLayer == "paint() & update()" === DomainLayer
DomainLayer -->|"play SFX (async)"| Audio
DomainLayer -->|"read sprite"| ResMgr
%% --- Styling ---
class BootLayer,EngineLayer,DomainLayer,InfraLayer runtime
class Props,Loader,Record config
class Main,VThread,Frame,Input engine
class Tank,Bullet,Explode entity
class Audio,ResMgr,ImageProc resource
| Key | Action |
|---|---|
↑ ↓ ← → |
Move tank |
Space |
Fire bullet |
P |
Pause or resume the current match |
R |
Restart the current match |
- Download
tank-war-windows.zipfrom GitHub Releases. - Extract the archive.
- Open the extracted
tank-warfolder and run the application executable inside it.
- Download
tank-war-linux.tar.gzfrom GitHub Releases. - Extract the archive:
tar -xzvf tank-war-linux.tar.gz- Enter the extracted directory and run the launcher:
cd tank-war && ./bin/tank-war- Build or download
tank-war.app. - If macOS blocks the app with a security warning, run the following command in Terminal and then try opening the app again:
sudo xattr -dr com.apple.quarantine tank-war.appWhat this does:
- It removes the
com.apple.quarantineattribute that macOS adds to files downloaded from the internet. - It only affects the specified
tank-war.appbundle on your own Mac.
Is it safe:
- For the app downloaded from this project, this step is expected and safe to use.
- This project is a personal learning game and is not signed or notarized with an Apple Developer account, so macOS may block it on some Macs until the quarantine attribute is removed.
If you prefer to run the game directly from source on any platform, make sure you have JDK 25 and Maven 3.9+ installed:
macOS / Linux:
./scripts/run.shWindows:
scripts\run.batWhat these scripts do:
- Builds the latest jar with
mvn clean package. - Starts the game with preview features enabled.
- Runs
target/tank-war-1.0-SNAPSHOT.jarfor you directly.
If you want to run the jar manually, the underlying command is:
java --enable-preview -jar target/tank-war-1.0-SNAPSHOT.jarThis project is licensed under the MIT License.