A high performance cross-platform ballistic calculator
Warning
Alpha software. Expect breaking changes, incomplete features, and rough edges.
A cross-platform ballistic trajectory calculator built with Flutter. Powered by bclibc — a high-performance (3-DOF + spin drift) C++ ballistic solver engine with RK4/Euler integration.
UI/UX inspired by the Strilets ballistic calculator app
| Home | Conditions | Trajectory Tables |
![]() |
![]() |
![]() |
| Convertors | My Profiles | Reticle |
![]() |
![]() |
![]() |
- Screenshots
- Table of Contents
- Features
- Download & Installation
- Architecture
- Building
- Android notes
- Dependencies
- License
- Shooting profiles — create and manage profiles combining weapon, ammunition, and sight configurations
- Weapon, ammo & sight wizards — step-by-step setup with optional import from a built-in collection
- Trajectory tables — compute and display ballistic tables with HTML export
- Environmental conditions — atmosphere, wind, Coriolis, target parameters
- Reticle view — SVG mil-reticle with live drop/windage adjustment indicator, theme-aware colours
- Multi-BC & custom drag — G1/G7 multi-BC tables and custom drag curves (the custom drag table editor is view-only for now)
- Powder sensitivity — temperature-based MV correction tables
- Configurable units — choose your preferred measurement system per quantity in settings
- Adjustment display — arrows / signs / letters format, configurable in settings
- Import / Export — profiles in
.ebcp(native) and.a7p(Archer Ballistic Profile) formats; full backup via Settings, with a choice of what to import (profiles, settings or everything) - Web version — runs in the browser at ebalistyka.o-murphy.net, installable as a PWA; the data stays in the browser (use Settings → Backup to export it)
- In-app help — a guide for every screen, in English and Ukrainian
- Migration — data from the old ObjectBox storage is converted to the new protobuf files on first start after the update (desktop and Android)
Latest release: GitHub Releases
| Platform | File | Notes |
|---|---|---|
| Linux x86_64 | ebalistyka-x86_64.AppImage | requires FUSE 2 |
| Linux x86_64 (portable) | ebalistyka_linux_x86_64.tar.gz | no FUSE required |
| Linux x86_64 (snap) | ebalistyka_linux_x86_64.snap | or snap install ebalistyka |
| Linux x86_64 (flatpak) | ebalistyka_linux_x86_64.flatpak | sideload — see Linux — Flatpak |
| Linux arm64 | ebalistyka-aarch64.AppImage | requires FUSE 2 |
| Linux arm64 (portable) | ebalistyka_linux_aarch64.tar.gz | no FUSE required |
| Linux arm64 (snap) | ebalistyka_linux_aarch64.snap | or snap install ebalistyka |
| Linux arm64 (flatpak) | ebalistyka_linux_aarch64.flatpak | sideload — see Linux — Flatpak |
| Linux x86_64 (deb) | ebalistyka_linux_x86_64.deb | Debian/Ubuntu — see Linux — deb |
| Linux arm64 (deb) | ebalistyka_linux_aarch64.deb | Debian/Ubuntu — see Linux — deb |
| Linux x86_64 (rpm) | ebalistyka_linux_x86_64.rpm | Fedora/RHEL/openSUSE — see Linux — rpm |
| Linux arm64 (rpm) | ebalistyka_linux_aarch64.rpm | Fedora/RHEL/openSUSE — see Linux — rpm |
| Linux x86_64 (AUR) | yay -S ebalistyka-bin |
Arch / Manjaro — see Linux — AUR |
| Linux arm64 (AUR) | yay -S ebalistyka-bin |
Arch / Manjaro — see Linux — AUR |
| Windows x64 (winget) | winget install -e --id o-murphy.ebalistyka |
see Windows — winget |
| Windows x64 | ebalistyka_windows_x86_64.msix | install ebalistyka_cert.cer first (self-signed) |
| Windows x64 (portable) | ebalistyka_windows_x86_64.zip | extract and run |
| Android (Google Play) | Internal Test registration | early access — registration required |
| Android arm64 | ebalistyka_android_arm64.apk | enable "Install from unknown sources" |
| Android armv7 | ebalistyka_android_armeabi_v7a.apk | enable "Install from unknown sources" |
| Android x86_64 | ebalistyka_android_x86_64.apk | enable "Install from unknown sources" |
| Web | ebalistyka.o-murphy.net | any modern browser; installable as a PWA — see Web |
chmod +x ebalistyka-x86_64.AppImage
./ebalistyka-x86_64.AppImageIf FUSE 2 is not available on your system:
./ebalistyka-x86_64.AppImage --appimage-extract-and-runInstall from the Snap Store (auto-updates included):
sudo snap install ebalistykaOr sideload a .snap file from GitHub Releases:
sudo snap install ebalistyka_linux_x86_64.snap --dangerousInstall from repo
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak remote-add --if-not-exists o-murphy https://o-murphy.github.io/flatpak-repo/o_murphy.flatpakrepo
flatpak install o-murphy io.github.o_murphy.ebalistyka
Install from a .flatpak sideload file (Flathub not yet available):
# Install flatpak runtime if needed
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install --user flathub org.gnome.Platform//50
# Install the app
flatpak install --user ebalistyka_linux_x86_64.flatpakRun:
flatpak run io.github.o_murphy.ebalistykaInstall on Debian/Ubuntu and derivatives:
sudo dpkg -i ebalistyka_linux_x86_64.debUninstall:
sudo dpkg -r ebalistykaInstall on Fedora/RHEL/openSUSE:
sudo rpm -i ebalistyka_linux_x86_64.rpmNote for Debian/Ubuntu users: if you are testing the
.rpmon a Debian-based system, RPM cannot resolve package names likegtk3fromapt. Use--nodepsto skip dependency checks — the bundle is self-contained and does not actually require them to be installed via RPM:sudo rpm -i --nodeps ebalistyka_linux_x86_64.rpm
Uninstall:
sudo rpm -e ebalistykaInstall via any AUR helper:
yay -S ebalistyka-binOr manually with makepkg:
git clone https://aur.archlinux.org/ebalistyka-bin.git
cd ebalistyka-bin
makepkg -siUninstall:
sudo pacman -R ebalistyka-binUpdates are delivered via zsync. Download AppImageUpdate, then run:
chmod +x AppImageUpdate-x86_64.AppImage
./AppImageUpdate-x86_64.AppImage ebalistyka-x86_64.AppImageThe tool fetches only the changed blocks from the latest GitHub Release — no need to re-download the full file.
Install:
winget install -e --id o-murphy.ebalistykaUpgrade:
winget upgrade -e --id o-murphy.ebalistykaTip
The app detects winget installations and shows the upgrade command directly in the update notification.
The MSIX is signed with a self-signed certificate. Before installing, trust the certificate:
- Download
ebalistyka_cert.cerfrom the release - Double-click → Install Certificate → Local Machine → Trusted Root Certification Authorities
- Install
ebalistyka_windows_x86_64.msix
Currently available as an internal test — registration is required:
Download the APK for your device ABI from the release and open it to install — if unsure, pick the universal APK. Android will verify the app via Google Play before installing.
Open ebalistyka.o-murphy.net in a modern desktop or mobile browser (tried in Chrome and Firefox on desktop and in Safari/Chrome/Firefox on iPhone). Desktop browsers offer to install it as an app (Settings → About → Install as app); on iPhone/iPad use Share → Add to Home Screen, which also helps keep the browser from clearing your data after a few idle days.
- Everything is calculated in the browser (the solver runs as WebAssembly)
- Your profiles and settings live in the browser's storage and are not synced anywhere — make a backup from time to time (Settings → Backup → Export) and keep only one tab open at a time
- Exporting a profile, a backup or the HTML table downloads a file / opens a new tab instead of sharing it
ebalistyka/
├── lib/
│ ├── features/ # Screen-level feature modules
│ │ ├── home/ # Main screen: profiles, shot, reticle, chart, tables
│ │ ├── conditions/ # Environmental conditions input
│ │ ├── tables/ # Trajectory tables & HTML export
│ │ ├── convertors/ # Unit converters (angular, velocity, length, …)
│ │ └── settings/ # App settings (units, adjustments, theme, locale)
│ ├── core/
│ │ ├── providers/ # Riverpod providers (app state, settings, DB, l10n)
│ │ ├── extensions/ # Typed getters/setters on ebc_db protobuf messages
│ │ ├── formatting/ # UnitFormatterImpl — localized value formatting
│ │ ├── models/ # FieldConstraints and other shared models
│ │ ├── services/ # A7pService/A7pConverter, import/export orchestration
│ │ ├── session/ # Single-instance guard (desktop), single-tab guard + PWA helpers (web)
│ │ └── collection/ # Built-in weapon/ammo/sight collection assets
│ ├── shared/
│ │ ├── widgets/ # Reusable widgets (pickers, inputs, dialogs, wizards)
│ │ ├── models/ # UI-layer models (AdjustmentData, ChartPoint, …)
│ │ ├── helpers/ # Formatting helpers, drag model info
│ │ ├── mixins/ # WizardFormMixin
│ │ └── constants/ # UI dimensions, null string sentinel
│ ├── ob_migrate/ # One-time migration of the old ObjectBox data to protobuf
│ ├── update/ # Update checker and utilities
│ └── l10n/ # Generated AppLocalizations (EN + UA)
├── packages/
│ └── ebc_db/ # Protobuf schema + .ebcp storage/export (settings.ebcp, profiles.ebcp)
└── tools/
└── reticle_gen/ # SVG mil-reticle generator
State management: Riverpod
Navigation: go_router
Local database: two embedded protobuf files (settings.ebcp/profiles.ebcp), via packages/ebc_db
Ballistic engine: bclibc (pub.dev package, bundles bclibc C++ solver via FFI)
Localisation: Flutter ARB / flutter_localizations (EN + UA)
Help: per-screen Markdown topics in assets/markdown/{en,uk} with screenshots — keep them in sync with the screens
Fonts: Roboto, bundled in assets/fonts (Apache-2.0)
- Flutter ≥ 3.47.9 (stable channel; see
.flutter-version) - CMake ≥ 3.13
- C++17 compiler (GCC / Clang on Linux, MSVC 2022 on Windows)
git clone https://github.com/o-murphy/ebalistyka.git
cd ebalistyka# System dependencies (Ubuntu/Debian)
sudo apt-get install -y \
clang cmake ninja-build pkg-config \
libgtk-3-dev liblzma-dev libstdc++-12-dev \
libclang-dev fuse libfuse2
flutter pub get
flutter build linux --releaseOutput: build/linux/x64/release/bundle/
# Requires Visual Studio 2022 with C++ workload
flutter pub get
flutter build windows --releaseOutput: build\windows\x64\runner\Release\
flutter pub get
flutter build apk --release --target-platform android-arm64Output: build/app/outputs/flutter-apk/app-release.apk
make build-web # release build into build/web (scripts/build-web.sh)
make deploy-web # force-pushes build/web to the gh-pages branch, after confirmationThe bundle uses the local CanvasKit (no CDN) and web/CNAME for the custom domain; deploys are manual — there is no workflow for them yet.
GitHub Actions workflows (.github/workflows):
| Workflow | What it does |
|---|---|
test.yml |
flutter analyze + flutter test on pull requests touching code |
release.yml |
On a vX.Y.Z tag: builds every platform and publishes a GitHub Release |
build.yml |
Reusable build workflow used by release.yml and the PR checks |
build-android.yml |
Android APK / bundle |
build-exe.yml |
Windows MSIX + portable zip |
build-linux-package.yml |
Linux AppImage / deb / rpm (reusable) |
build-portable.yml |
Linux portable tar.gz |
build-snap.yml, build-flatpak.yml |
Snap and Flatpak builds |
pr-linux.yml |
Linux build checks on pull requests |
publish-*.yml |
Publishing to AUR, Flathub, the Flatpak repo, Google Play, the Snap Store and winget (called from release.yml or run manually) |
verify-winget-path.yml |
Checks the winget install path the update notification relies on |
Flutter's Impeller renderer (enabled by default on Android since Flutter 3.16) tessellates SVG paths — including circles — into coarse polygons, which makes reticle and target SVGs look jagged. Until Flutter/Impeller resolves path tessellation quality for small shapes, Impeller is explicitly disabled for Android in android/app/src/main/AndroidManifest.xml:
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" />This forces the app to use Skia, which renders SVG circles smoothly. Re-enable Impeller only after verifying that circle/arc quality is acceptable on your target Android version.
On Android, file_picker cannot filter by custom extensions (.ebcp, .a7p) because Android does not know their MIME types. The import dialogs open with FileType.any and validate the extension after the user selects a file. Selecting a wrong file type shows an error message.
| Package | Role |
|---|---|
| flutter_riverpod | State management |
| go_router | Navigation |
| flutter_localizations | EN + UA localisation |
| flutter_svg | SVG reticle & target rendering |
| a7p | .a7p profile format — protobuf encode/decode/validate |
| window_manager | Desktop window size / title / icon |
| file_picker | Import file picker |
| share_plus | Export / share files |
| url_launcher | External links |
| package_info_plus | App version info |
| flutter_markdown_plus | App help widgets |
| ota_update | Autoupdate for Android sideload installations |
| material_ui / cupertino_ui | Material / Cupertino widgets (standalone packages) |
| data_table_2 | Trajectory table with a fixed range column |
| sticky_headers | Sticky section headers |
| shared_preferences | Small persisted values (update checks), also on web |
| path_provider | App data directory (native) |
| http | Update and collection checks |
| intl | Number / date formatting |
| ob_dump_reader | Reads the old ObjectBox data.mdb for the one-time migration |
| flutpak (dev) | Manage flatpak/flathub manifest for sandboxed builds |
The app depends directly on bclibc: one package for the native engine (built by its own build hook), the wasm build for web and the unit types.
| Package | Role |
|---|---|
| bclibc | Ballistic solver — bclibc C++ engine (3-DOF, RK4) LGPL-3, compiled by a build hook; wasm build for web; bindings and unit types |
| ffi | Dart ↔ C FFI bindings |
| Package | Role |
|---|---|
| protobuf | ProfilesData/SettingsData/EbcpData wire format |
| crypto | MD5 integrity check (.ebcp's "md5+ebcpbuf") |
| json_schema | Schema validation against embedded JSON Schema |
| uuid | Client-generated Profile.uuid |
| Package | Role |
|---|---|
| xml | SVG reticle generation |
Copyright (C) 2026 Yaroshenko Dmytro (o-murphy)
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License v3.0 as published by the Free Software Foundation.
See LICENSE for the full text. See CHANGELOG for release history.
Note
The bundled Roboto font (assets/fonts) is licensed under the Apache License 2.0; its license text ships with the app and is listed under Settings → Open source licenses.
Note
bclibc bundles bclibc — the ballistic solver engine — which is licensed separately under the GNU Lesser General Public License v3.0. See the bclibc repository for the engine source and its license.
Warning
Risk notice. This application performs approximate simulations of complex physical processes. Calculation results must not be considered as completely or reliably reflecting actual projectile behaviour. Results may be used for educational purposes only and must not be relied upon in any context where an incorrect calculation could cause financial harm or put a human life at risk.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.





