{"id":15882645,"url":"https://github.com/oliviersohn/hamazed","last_synced_at":"2025-03-17T13:31:27.034Z","repository":{"id":56844552,"uuid":"109905682","full_name":"OlivierSohn/hamazed","owner":"OlivierSohn","description":"Monorepo for a multi-player game engine, and game examples","archived":false,"fork":false,"pushed_at":"2022-02-13T22:25:10.000Z","size":4664,"stargazers_count":42,"open_issues_count":0,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-16T12:07:33.242Z","etag":null,"topics":["addition","animation","ascii-art","ascii-game","ascii-graphics","collision","game","haskell","laser","mathematics","retrogaming"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OlivierSohn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-08T00:05:57.000Z","updated_at":"2024-06-30T19:13:38.000Z","dependencies_parsed_at":"2022-09-09T04:11:40.722Z","dependency_job_id":null,"html_url":"https://github.com/OlivierSohn/hamazed","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlivierSohn%2Fhamazed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlivierSohn%2Fhamazed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlivierSohn%2Fhamazed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlivierSohn%2Fhamazed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OlivierSohn","download_url":"https://codeload.github.com/OlivierSohn/hamazed/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244041523,"owners_count":20388257,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["addition","animation","ascii-art","ascii-game","ascii-graphics","collision","game","haskell","laser","mathematics","retrogaming"],"created_at":"2024-10-06T04:05:59.866Z","updated_at":"2025-03-17T13:31:26.270Z","avatar_url":"https://github.com/OlivierSohn.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- TOC depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 --\u003e\n\n- [What is it?](#what-is-it)\n- [Packages](#packages)\n- [Development setup](#development-setup)\n\t- [Install dependencies (C libraries)](#install-dependencies-c-libraries)\n- [Build](#build)\n- [Run the games in single-player mode](#run-the-games-in-single-player-mode)\n- [Run the games in Multi-player mode](#run-the-games-in-multi-player-mode)\n\t- [Connect to a running game server](#connect-to-a-running-game-server)\n\t\t- [Connect to a Heroku-hosted server](#connect-to-a-heroku-hosted-server)\n- [CI](#ci)\n- [Game engine highlights](#game-engine-highlights)\n\t- [Supported platforms](#supported-platforms)\n\t- [Music](#music)\n\t\t- [Notation](#notation)\n\t\t- [Playback](#playback)\n\t- [Rendering](#rendering)\n\n\u003c!-- /TOC --\u003e\n\n# What is it?\n\nMonorepo for a Haskell multi-player game engine and games made with it.\n\nThe games can be played locally, in single-player mode, or in multi-player mode, after having run the [deployment script]\nto host the game server on [Heroku].\n\nYou can even create your own multi-player game, starting from the [tutorial-game](/imj-game-tutorial-increment).\n\n# Supported platforms\n\nOfficially supported client platforms are (recent versions of) macOS and Ubuntu,\nwhere a C++17-enabled compiler is available.\n\n# Packages\n\nList of packages, inverse-topologically sorted wrt dependencies, with keywords / short description for each of them:\n\n- [imj-audio]\n  - Bindings to a C++17 lock-free audio engine.\n\t- The C++ sources are located in [submodules](/imj-audio/c).\n- [imj-music](/imj-music)\n  - Polyphonic music scores creation and playback.\n- [imj-prelude](/imj-prelude)\n  - Prelude library used by packages hereunder, mainly to factorize imports.\n- [imj-time]\n  - Timing library based on the system monotonic clock.\n- [imj-base]\n  - Containers (Graph, Matrix, Cyclic matrix, Dynamic vector, etc...)\n  - Geometry, text animations\n  - 8-bit color manipulation in different color spaces\n  - Easing, inverse-easing, interpolation, rectangular frame morphing.\n  - Physics\n  - UI components building blocks\n    - Chat\n  - Rendering backends, using [delta-rendering](/imj-base/src/Imj/Graphics/Render/Delta.hs):\n     - In a GLFW-driven OpenGL window\n     - In the terminal\n  - Player input, window management.\n- [imj-space](/imj-space)\n  - Randomized creation of 2D game levels, given some topological constraints.\n- [imj-particlesystem](/imj-particlesystem) (formerly `imj-animation`)\n  - Physics-based and geometric particle systems.\n- [imj-measure-stdout](/imj-measure-stdout)\n  - An executable to measure the maximum capacity of stdout, and observe\n  the effect of different buffering modes. This was used while developing\n\t[delta-rendering](/imj-base/src/Imj/Graphics/Render/Delta.hs).\n- [imj-server](/imj-server)\n  - Using [websockets] to communicate between server and clients.\n  - Broadcast messages to all clients\n  - Handle connection failures generically (so that a client handler, when broadcasting a message,\n    won't have to handle exceptions due to another client's connection being down.)\n  - Detect client reconnection (keep track of clients identities using their MAC address)\n  - Logging\n- [imj-serve-highscores]\n  - [Servant]-based web service to persist and access highscores.\n- [imj-game]\n  - Multi-player game engine\n  - Listens to server events, and player events\n  - [Handles generic events](/imj-game/src/Imj/Game/Update.hs), so that the game implementation\n  contains only game-specific code.\n    - Real-time music playback.\n  - Debugging features : record and display events graphically, event logging.\n- [imj-game-tutorial-increment](/imj-game-tutorial-increment)\n  - A tutorial on how to use [imj-game] to build a multi-player game.\n- [imj-game-synths]\n  - \"A jam session, in the cloud, with loops and synthesizers.\"\n  - Players are playing music together, in real-time, using either real MIDI devices,\n\t or computer keyboards.\n- [imj-game-hamazed]\n  - You're a ship pilot, shooting at flying numbers.\n\t- Each level has its own original music!\n  - Levels generation is randomized, so that you will (very likely) never play the same game twice.\n  - Demo (when the game was mono-player and had no music):\n      [![asciicast](https://asciinema.org/a/156059.png)](https://asciinema.org/a/156059)\n- [imj-profile](/imj-profile)\n  - An executable precomputing optimal strategies used for random level generation.\n  - And other profiling tests.\n\n# Development setup\n\nAfter checking out the repo, run `git submodule init \u0026\u0026 git submodule update` to download the submodules.\n\n## Install dependencies (C libraries)\n\n- [ftgl] is needed by [imj-base] to render fonts with OpenGL.\n- [portaudio 19] is needed by [imj-audio] for audio I/O.\n- [libpq] and [postgresql] are needed by a dependency of [imj-serve-highscores].\n\nTo install them:\n\n- On OSX:\n\n```shell\nbrew install ftgl\nbrew install portaudio\nbrew install postgresql\n```\n\n- On Linux:\n\n```shell\nsudo apt-get update\nsudo apt-get install ftgl-dev\nsudo apt-get install portaudio19-dev\nsudo apt-get install postgresql\nsudo apt-get install libpq-dev\n```\n\n# Build\n\n[stack] is the preferred tool to build the project:\n\n```shell\nstack build --pedantic\n```\n\nA recent enough C compiler should be used by GHC, so as to be able to build C++17.\n\n# Run the games in single-player mode\n\nPassing no command line argument will run the games in single player mode:\n\n```shell\nstack exec \u003cgame-executable\u003e\n```\n\n# Deploy a game server for Multi-player mode\n\nUse the [deployment script] to host the games on a [Heroku] server.\n\n# Run the games in Multi-player mode\n\n### Connect to a running game server\n\n```shell\nstack exec -- \u003cgame-executable\u003e -n \u003cserverName\u003e -p\u003cserverPort\u003e\n```\n\n### Connect to a Heroku-hosted server\n\nWhen the game server is hosted on [Heroku], the port to connect to is `80`:\n\n```shell\nstack exec -- \u003cgame-executable\u003e -n \u003cherokuAppDomain\u003e -p80\n```\n\n# CI\n\nThe [CI script](/.travis.yml) verifies that compilation and tests succeed with\nGHC versions 8.2.2 and 8.4.3.\n\n# Game engine highlights\n\n## Music\n\n### Notation\n\n[Melodies](/imj-game-hamazed/src/Imj/Game/Hamazed/Music.hs)\nare written using the `notes` quasiquoter, where:\n\n- notes names follow [the solfege notation]\n- a note can be shifted by octaves using `v` and `^`\n- `-` extends the preceding note\n- `.` indicates a pause\n\n### Playback\n\nEvery game made with [imj-game] can have the server send midi-like\nnote on / note off events to game clients, allowing to perfectly synchronize the music with the game.\n\nThe music won't pause during garbage collection because we use\n[an audio engine](/imj-audio) whose audio realtime thread is\nnot managed by the GHC runtime.\n\n## Rendering\n\nThe screen is conceptually divided in small blocks of equal size,\nwhere each block can contain a character with 8-bit background and foreground colors.\n\nThe [fonts](/imj-base/fonts) and font size for rendering can be modified at run time.\n\n[deployment script]: ./deploy-heroku.sh\n[ftgl]: http://ftgl.sourceforge.net/docs/html/\n[Heroku]: https://www.heroku.com/\n[imj-base]: /imj-base\n[imj-audio]: /imj-audio\n[imj-game]: /imj-game\n[imj-game-hamazed]: /imj-game-hamazed\n[imj-game-synths]: /imj-game-synths\n[imj-serve-highscores]: /imj-serve-highscores\n[imj-time]: /imj-time\n[libpq]: https://www.postgresql.org/docs/9.5/static/libpq.html\n[postgresql]: https://www.postgresql.org/\n[portaudio 19]: http://www.portaudio.com/\n[Servant]: http://haskell-servant.readthedocs.io/en/stable/\n[stack]: https://docs.haskellstack.org\n[the solfege notation]: https://en.wikipedia.org/wiki/Solf%C3%A8ge#Fixed_do_solf%C3%A8ge\n[websockets]: http://hackage.haskell.org/package/websockets\n\n# Build status\n\nCurrently, the CI build errors because the \"build from scratch\" process plus unit tests takes more than one hour and hits a timeout :\n[![Build Status](https://travis-ci.org/OlivierSohn/hamazed.svg?branch=master)](https://travis-ci.org/OlivierSohn/hamazed)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foliviersohn%2Fhamazed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foliviersohn%2Fhamazed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foliviersohn%2Fhamazed/lists"}