An isometric city-builder where same-level buildings merge 2048-style. Build, merge, expand, and advance through ages — Python + pygame-ce.
Place buildings on the isometric grid, then slide them with WASD/arrows to merge same-level neighbors into a higher-level building (just like 2048). Higher-level buildings produce more income. Spend income to construct new buildings, expand the land, or advance to the next age to unlock better building tiers.
| Menu | Build mode | Inspection |
|---|---|---|
![]() |
![]() |
![]() |
| Action | Input |
|---|---|
| Move building (merge direction) | WASD / Arrow keys |
| Construct a building | Spacebar |
| Toggle inspection mode | INFORMATION button |
| Build a new building | BUILD button |
| Expand the land | EXPAND button |
| Advance to next age | NEXT AGE button |
| Inspect / sell building | Click a building in inspection mode |
Grab a ready-to-play build for your OS from itch.io or the latest GitHub release — no Python required. Unzip and run:
| OS | Run |
|---|---|
| Windows | Extract highrise-windows.zip, run highrise.exe |
| macOS | Extract highrise-macos.zip, open Highrise.app |
| Linux | Extract highrise-linux.zip, run ./highrise/highrise |
macOS Gatekeeper: the app is unsigned, so the first launch needs right-click → Open (or
xattr -dr com.apple.quarantine Highrise.app).Windows SmartScreen: the app is unsigned, so the first launch shows "Windows protected your PC." Click More info → Run anyway. This is Microsoft's download-reputation check, not a virus warning — brand-new unsigned executables always trigger it.
- Python 3.12+
- pygame-ce, pyyaml (resolved automatically from
pyproject.toml/uv.lock) - uv (optional but recommended)
git clone --recurse-submodules https://github.com/vectorviolet/highrise.git
cd highrise
uv sync
uv run python __main__.pyIf you forgot --recurse-submodules, or the engine folder is out of step after a pull:
git submodule update --init (on Windows, scripts\sync-pygamine.bat does the same).
Without uv: pip install . then python __main__.py.
Builds are produced by PyInstaller from highrise.spec, which bundles assets/ and config/ alongside the executable (onedir). To build locally for your current OS:
uv sync --group build
uv run pyinstaller highrise.spec --noconfirmThe result lands in dist/highrise/ (dist/Highrise.app on macOS).
Per-OS bundles for Windows, macOS, and Linux are built and published automatically by .github/workflows/release.yml when a version tag is pushed:
git tag v0.1.0
git push origin v0.1.0The workflow builds on each OS, zips the bundle, attaches all three to a GitHub Release (with auto-generated notes), and pushes each build to its itch.io channel via Butler. Use the workflow's Run workflow button to test a build without publishing.
__main__.py Entry point — injects src/ + src/pygamine/ into sys.path
src/app/game.py Game class — wires Application + Events + Persistence mixins
src/domain/ Pure data (Player)
src/gameplay/ Tilemap, tile selector, buildings, clouds
src/ui/ Info panel and UI helpers
src/util/ Frozen-build resource path resolution
src/pygamine/ Engine submodule (Application, PanelLoaderExt, Database, ...)
config/ YAML: assets, panels, settings
databases/ SQLite save file (auto-created on first run)
assets/ Images, sounds, fonts
See CLAUDE.md for the full architecture overview.
Art, UI and sounds from Kenney — Hexagon Buildings and UI Pack (CC0); the font is Titillium Web (SIL OFL 1.1). Music : Sakura Girl - Day Off (CC BY 3.0), link : youtu.be/vAv9KtrU_5c. See CREDITS.md for every asset, font and library with its license; it also ships with the game.
Every file under assets/ is listed in assets/SOURCES.yaml with its source:
- A pack, given by its slug (for example
kenney-ui-pack). The entry also gives the file's path inside that pack asoriginal. Images built from several pack files list them undercomposited_frominstead. Edited pack files say what changed undermodified. own, for files made for this game.
The packs section names each pack, its author, URL, license and what the game uses it for.
Each pack's own license text is in licenses/assets/<slug>.txt, and every build ships it.
When you add, replace or remove an asset:
- Update
assets/SOURCES.yaml, and addlicenses/assets/<slug>.txtfor any new pack. - Run
uv run python scripts/gen_credits.pyto regenerate CREDITS.md's asset section. Don't edit that section by hand. - Run the tests.
tests/test_sources.pyfails if a file is missing fromSOURCES.yaml, if a listed file doesn't exist, if a pack has no license text, or if CREDITS.md is out of date.
Only use assets whose license allows bundling them in a distributed game.
- Formatting: Black-compatible, enforced by
ruff format(line length 88, double quotes, otherwise Black's defaults; see[tool.ruff.format]inpyproject.toml). - Lint:
ruff check, deliberately narrow (pyflakes rules only). - CI: runs both. The
src/pygaminesubmodule is excluded; it has its own setup.
Run both locally before committing:
uv run --group dev ruff format . # reformat
uv run --group dev ruff check . # lint
uv run --group dev ruff format --check . # what CI runs: fails if anything would be reformattedThe commit that first applied the formatter is listed in .git-blame-ignore-revs. To have
git blame skip it and show the real author of each line:
git config blame.ignoreRevsFile .git-blame-ignore-revs- Fork this repository.
- Clone your fork:
git clone --recurse-submodules https://github.com/<you>/highrise.git - Create a branch:
git checkout -b feature/<your-feature> - Commit + push:
git commit -am "<message>" && git push origin feature/<your-feature> - Open a pull request.
Umutcan Ekinci — umutcannekinci@gmail.com
See also the contributors.
This project is licensed under the MIT License — see the LICENSE file.



