{"id":13475493,"url":"https://github.com/charmbracelet/harmonica","last_synced_at":"2025-05-13T17:08:40.966Z","repository":{"id":37838780,"uuid":"384259177","full_name":"charmbracelet/harmonica","owner":"charmbracelet","description":"A simple, physics-based animation library 🎼","archived":false,"fork":false,"pushed_at":"2025-02-13T14:31:21.000Z","size":147,"stargazers_count":1157,"open_issues_count":2,"forks_count":24,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-24T01:56:13.162Z","etag":null,"topics":["animation","game-development","go","golang","hacktoberfest","physics"],"latest_commit_sha":null,"homepage":"","language":"Go","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/charmbracelet.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":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-08T22:08:06.000Z","updated_at":"2025-04-22T21:52:43.000Z","dependencies_parsed_at":"2023-10-03T04:14:05.235Z","dependency_job_id":"381afddc-54ed-4197-a4ca-df405c95d66f","html_url":"https://github.com/charmbracelet/harmonica","commit_stats":{"total_commits":41,"total_committers":7,"mean_commits":5.857142857142857,"dds":"0.29268292682926833","last_synced_commit":"f1aaeb7e0495f7b66c0c4d62655f995d13bceb11"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charmbracelet%2Fharmonica","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charmbracelet%2Fharmonica/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charmbracelet%2Fharmonica/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charmbracelet%2Fharmonica/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/charmbracelet","download_url":"https://codeload.github.com/charmbracelet/harmonica/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253990467,"owners_count":21995774,"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":["animation","game-development","go","golang","hacktoberfest","physics"],"created_at":"2024-07-31T16:01:20.882Z","updated_at":"2025-05-13T17:08:35.953Z","avatar_url":"https://github.com/charmbracelet.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"Harmonica\n=========\n\n\u003cp\u003e\n    \u003ca href=\"https://stuff.charm.sh/harmonica/harmonica-art.png\"\u003e\u003cimg src=\"https://stuff.charm.sh/harmonica/harmonica-readme.png\" alt=\"Harmonica Image\" width=\"325\"\u003e\u003c/a\u003e\u003cbr\u003e\n    \u003ca href=\"https://github.com/charmbracelet/harmonica/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/release/charmbracelet/harmonica.svg\" alt=\"Latest Release\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://pkg.go.dev/github.com/charmbracelet/harmonica?tab=doc\"\u003e\u003cimg src=\"https://godoc.org/github.com/golang/gddo?status.svg\" alt=\"GoDoc\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/charmbracelet/harmonica/actions\"\u003e\u003cimg src=\"https://github.com/charmbracelet/harmonica/workflows/build/badge.svg\" alt=\"Build Status\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nA simple, efficient spring animation library for smooth, natural motion.\n\n\u003cimg src=\"https://stuff.charm.sh/harmonica/harmonica-opengl.gif\" width=\"500\" alt=\"Harmonica OpenGL Demo\"\u003e\n\nIt even works well on the command line.\n\n\u003cimg src=\"https://stuff.charm.sh/harmonica/harmonica-tui.gif\" width=\"900\" alt=\"Harmonica TUI Demo\"\u003e\n\n[examples]: https://github.com/charmbracelet/harmonica/tree/master/examples\n[docs]: https://pkg.go.dev/github.com/charmbracelet/harmonica?tab=doc\n\n## Usage\n\nHarmonica is framework-agnostic and works well in 2D and 3D contexts. Simply\ncall [`NewSpring`][newspring] with your settings to initialize and\n[`Update`][update] on each frame to animate.\n\n```go\nimport \"github.com/charmbracelet/harmonica\"\n\n// A thing we want to animate.\nsprite := struct{\n    x, xVelocity float64\n    y, yVelocity float64\n}{}\n\n// Where we want to animate it.\nconst targetX = 50.0\nconst targetY = 100.0\n\n// Initialize a spring with framerate, angular frequency, and damping values.\nspring := harmonica.NewSpring(harmonica.FPS(60), 6.0, 0.5)\n\n// Animate!\nfor {\n    sprite.x, sprite.xVelocity = spring.Update(sprite.x, sprite.xVelocity, targetX)\n    sprite.y, sprite.yVelocity = spring.Update(sprite.y, sprite.yVelocity, targetY)\n    time.Sleep(time.Second/60)\n}\n```\n\nFor details, see the [examples][examples] and the [docs][docs].\n\n[newspring]: https://pkg.go.dev/github.com/charmbracelet/harmonica#NewSpring\n[update]: https://pkg.go.dev/github.com/charmbracelet/harmonica#Update\n\n## Settings\n\n[`NewSpring`][newspring] takes three values:\n\n* **Time Delta:** the time step to operate on. Game engines typically provide\n  a way to determine the time delta, however if that's not available you can\n  simply set the framerate with the included `FPS(int)` utility function. Make\n  sure the framerate you set here matches your actual framerate.\n* **Angular Velocity:** this translates roughly to the speed. Higher values are\n  faster.\n* **Damping Ratio:** the springiness of the animation, generally between `0`\n  and `1`, though it can go higher. Lower values are springier. For details,\n  see below.\n\n## Damping Ratios\n\nThe damping ratio affects the motion in one of three different ways depending\non how it's set.\n\n### Under-Damping\n\nA spring is under-damped when its damping ratio is less than `1`. An\nunder-damped spring reaches equilibrium the fastest, but overshoots and will\ncontinue to oscillate as its amplitude decays over time.\n\n### Critical Damping\n\nA spring is critically-damped the damping ratio is exactly `1`. A critically\ndamped spring will reach equilibrium as fast as possible without oscillating.\n\n### Over-Damping\n\nA spring is over-damped the damping ratio is greater than `1`. An over-damped\nspring will never oscillate, but reaches equilibrium at a slower rate than\na critically damped spring.\n\n## Acknowledgements\n\nThis library is a fairly straightforward port of [Ryan Juckett][juckett]’s\nexcellent damped simple harmonic oscillator originally written in C++ in 2008\nand published in 2012. [Ryan’s writeup][writeup] on the subject is fantastic.\n\n[juckett]: https://www.ryanjuckett.com/\n[writeup]: https://www.ryanjuckett.com/damped-springs/\n\n## Feedback\n\nWe’d love to hear your thoughts on this project. Feel free to drop us a note!\n\n* [Twitter](https://twitter.com/charmcli)\n* [The Fediverse](https://mastodon.social/@charmcli)\n* [Discord](https://charm.sh/chat)\n\n## License\n\n[MIT](https://github.com/charmbracelet/harmonica/raw/master/LICENSE)\n\n***\n\nPart of [Charm](https://charm.sh).\n\n\u003ca href=\"https://charm.sh/\"\u003e\u003cimg alt=\"The Charm logo\" src=\"https://stuff.charm.sh/charm-badge.jpg\" width=\"400\"\u003e\u003c/a\u003e\n\nCharm热爱开源 • Charm loves open source\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharmbracelet%2Fharmonica","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcharmbracelet%2Fharmonica","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharmbracelet%2Fharmonica/lists"}