{"id":13528860,"url":"https://github.com/AustinEast/echo","last_synced_at":"2025-04-01T14:33:26.348Z","repository":{"id":37579980,"uuid":"163479903","full_name":"AustinEast/echo","owner":"AustinEast","description":"Simple Physics Library written in Haxe","archived":false,"fork":false,"pushed_at":"2024-03-02T20:29:22.000Z","size":2232,"stargazers_count":146,"open_issues_count":9,"forks_count":27,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-26T16:08:22.649Z","etag":null,"topics":["2d-physics-engine","gamedev","haxe","haxelib","physics"],"latest_commit_sha":null,"homepage":"https://austineast.dev/echo","language":"Haxe","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AustinEast.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-29T05:44:17.000Z","updated_at":"2025-03-12T19:55:07.000Z","dependencies_parsed_at":"2024-08-01T07:42:06.825Z","dependency_job_id":null,"html_url":"https://github.com/AustinEast/echo","commit_stats":null,"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AustinEast%2Fecho","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AustinEast%2Fecho/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AustinEast%2Fecho/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AustinEast%2Fecho/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AustinEast","download_url":"https://codeload.github.com/AustinEast/echo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246655379,"owners_count":20812624,"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":["2d-physics-engine","gamedev","haxe","haxelib","physics"],"created_at":"2024-08-01T07:00:26.539Z","updated_at":"2025-04-01T14:33:21.332Z","avatar_url":"https://github.com/AustinEast.png","language":"Haxe","funding_links":[],"categories":["Physics"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/austineast/echo/gh-pages/logo.png\"\u003e\n\u003c/p\u003e\n\n# echo\nA 2D Physics library written in Haxe.\n\n![Build Status](https://github.com/AustinEast/echo/actions/workflows/build-and-release.yml/badge.svg)\n\nEcho focuses on maintaining a simple API that is easy to integrate into any engine/framework (Heaps, OpenFL, Kha, etc). All Echo needs is an update loop and its ready to go!\n\nTry the [Samples 🎮](https://austineast.dev/echo)!\n\nCheck out the [API 📖](https://austineast.dev/echo/api/echo/Echo)!\n\n# Features\n* Semi-implicit euler integration physics\n* SAT-powered collision detection\n* Quadtree for broadphase collision querying\n* Collision listeners to provide collision callbacks\n* Physics State History Management with Built-in Undo/Redo functionality\n* Extendable debug drawing\n\n# Getting Started\n\nEcho requires [Haxe 4.2+](https://haxe.org/download/) to run.\n\nInstall the library from haxelib:\n```\nhaxelib install echo\n```\nAlternatively the dev version of the library can be installed from github:\n```\nhaxelib git echo https://github.com/AustinEast/echo.git\n```\n\nThen for standard Haxe applications, include the library in your project's `.hxml`:\n```hxml\n-lib echo\n```\n\nFor OpenFL users, add the library into your `Project.xml`:\n\n```xml\n\u003chaxelib name=\"echo\" /\u003e\n```\n\nFor Kha users (who don't use haxelib), clone echo to thee `Libraries` folder in your project root, and then add the following to your `khafile.js`:\n\n```js\nproject.addLibrary('echo');\n```\n\n# Usage\n\n## Concepts\n\n### Echo\n\nThe `Echo` Class holds helpful utility methods to help streamline the creation and management of Physics Simulations.\n\n### World\n\nA `World` is an Object representing the state of a Physics simulation and it configurations. \n\n### Bodies\n\nA `Body` is an Object representing a Physical Body in a `World`. A `Body` has a position, velocity, mass, optional collider shapes, and many other properties that are used in a `World` simulation.\n\n### Shapes\n\nA Body's collider is represented by different Shapes. Without a `Shape` to define it's form, a `Body` can be thought of a just a point in the `World` that cant collide with anything.\n\nAvailable Shapes:\n* Rectangle\n* Circle\n* Polygon (Convex Only)\n\nWhen a Shape is added to a Body, it's transform (x, y, rotation) becomes relative to its parent Body. In this case, a Shape's local transform can still be accessed through `shape.local_x`, `shape.local_y`, and `shape.local_rotation`.\n\nIt's important to note that all Shapes (including Rectangles) have their origins centered.\n\n### Lines\n\nUse Lines to perform Linecasts against other Lines, Bodies, and Shapes. Check out the `Echo` class for various methods to preform Linecasts.\n\n### Listeners\n\nListeners keep track of collisions between Bodies - enacting callbacks and physics responses depending on their configurations. Once you add a `Listener` to a `World`, it will automatically update itself as the `World` is stepped forward.\n\n## Integration\n\n### Codebase Integration\nEcho has a couple of ways to help integrate itself into codebases through the `Body` class. \n\nFirst, the `Body` class has two public fields named `on_move` and `on_rotate`. If these are set on a body, they'll be called any time the body moves or rotates. This is useful for things such as syncing the Body's transform with external objects:\n```haxe\nvar body = new echo.Body();\nbody.on_move = (x,y) -\u003e entity.position.set(x,y);\nbody.on_rotate = (rotation) -\u003e entity.rotation = rotation;\n```\n\nSecond, a build macro is available to add custom fields to the `Body` class, such as a reference to an `Entity` class:\n\nin build.hxml:\n```hxml\n--macro echo.Macros.add_data(\"entity\", \"some.package.Entity\")\n```\n\nin Main.hx\n```haxe\nvar body = new echo.Body();\nbody.entity = new some.package.Entity();\n```\n\n### Other Math Library Integration\n\nEcho comes with basic implementations of common math structures (Vector2, Vector3, Matrix3), but also allows these structures to be extended and used seamlessly with other popular Haxe math libraries. \n\nSupport is currently available for the following libraries (activated by adding the listed compiler flag to your project's build parameters):\n\n| Library | Compiler Flag |\n| --- | --- |\n| [hxmath](https://github.com/tbrosman/hxmath) | ECHO_USE_HXMATH |\n| [vector-math](https://github.com/haxiomic/vector-math) | ECHO_USE_VECTORMATH |\n| [zerolib](https://github.com/01010111/zerolib) | ECHO_USE_ZEROLIB |\n| [heaps](https://heaps.io) | ECHO_USE_HEAPS |\n\n(pull requests for other libraries happily accepted!)\n\nIf you compile your project with a standard `.hxml`:\n```hxml\n# hxmath support\n-lib hxmath\n-D ECHO_USE_HXMATH\n```\n\nFor OpenFL users, add one of the following into your `Project.xml`:\n```xml\n\u003c!-- hxmath support --\u003e\n\u003chaxelib name=\"hxmath\" /\u003e\n\u003chaxedef name=\"ECHO_USE_HXMATH\" /\u003e\n```\n\nFor Kha users, add one of the following into your `khafile.js`:\n```js\n// hxmath support\nproject.addLibrary('hxmath');\nproject.addDefine('ECHO_USE_HXMATH');\n```\n\n# Examples\n\n## Basic\n```haxe\nimport echo.Echo;\n\nclass Main {\n  static function main() {\n    // Create a World to hold all the Physics Bodies\n    // Worlds, Bodies, and Listeners are all created with optional configuration objects.\n    // This makes it easy to construct object configurations, reuse them, and even easily load them from JSON!\n    var world = Echo.start({\n      width: 64, // Affects the bounds for collision checks.\n      height: 64, // Affects the bounds for collision checks.\n      gravity_y: 20, // Force of Gravity on the Y axis. Also available for the X axis.\n      iterations: 2 // Sets the number of Physics iterations that will occur each time the World steps.\n    });\n\n    // Create a Body with a Circle Collider and add it to the World\n    var a = world.make({\n      material: {elasticity: 0.2},\n      shape: {\n        type: CIRCLE,\n        radius: 16,\n      }\n    });\n\n    // Create a Body with a Rectangle collider and add it to the World\n    // This Body will be static (ie have a Mass of `0`), rendering it as unmovable\n    // This is useful for things like platforms or walls.\n    var b = world.make({\n      mass: STATIC, // Setting this to Static/`0` makes the body unmovable by forces and collisions\n      y: 48, // Set the object's Y position below the Circle, so that gravity makes them collide\n      material: {elasticity: 0.2},\n      shape: {\n        type: RECT,\n        width: 10,\n        height: 10\n      }\n    });\n\n    // Create a listener and attach it to the World.\n    // This listener will react to collisions between Body \"a\" and Body \"b\", based on the configuration options passed in\n    world.listen(a, b, {\n      separate: true, // Setting this to true will cause the Bodies to separate on Collision. This defaults to true\n      enter: (a, b, c) -\u003e trace(\"Collision Entered\"), // This callback is called on the first frame that a collision starts\n      stay: (a, b, c) -\u003e trace(\"Collision Stayed\"), // This callback is called on frames when the two Bodies are continuing to collide\n      exit: (a, b) -\u003e trace(\"Collision Exited\"), // This callback is called when a collision between the two Bodies ends\n    });\n\n    // Set up a Timer to act as an update loop (at 60fps)\n    new haxe.Timer(16).run = () -\u003e {\n      // Step the World's Physics Simulation forward (at 60fps)\n      world.step(16 / 1000);\n      // Log the World State in the Console\n      echo.util.Debug.log(world);\n    }\n  }\n}\n```\n\n## Samples\nCheck out the source code for the [Echo Samples](https://austineast.dev/echo/) here: https://github.com/AustinEast/echo/tree/master/sample/state\n\n## Engine/Framework Specific\n\n* [HaxeFlixel](https://haxeflixel.com): https://github.com/AustinEast/echo-flixel\n* [Heaps](https://heaps.io): https://github.com/AustinEast/echo-heaps\n* [Peyote View](https://github.com/maitag/peote-view): https://github.com/maitag/peote-views-samples/tree/master/echo\n* [HaxePunk](https://haxepunk.com): https://github.com/XANOZOID/EchoHaxePunk\n\n\n# Roadmap\n## Sooner\n* Endless length Line support\n* Update Readme with info on the various utilities (Tilemap, Bezier, etc)\n## Later\n* Allow Concave Polygons (through Convex Decomposition)\n* Sleeping Body optimations\n* Constraints\n* Compiler Flag to turn off a majority of inlined functions (worse performance, but MUCH smaller filesize)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAustinEast%2Fecho","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAustinEast%2Fecho","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAustinEast%2Fecho/lists"}