{"id":15898709,"url":"https://github.com/prozi/oneforall","last_synced_at":"2026-01-17T16:11:03.120Z","repository":{"id":54465188,"uuid":"391759382","full_name":"Prozi/oneforall","owner":"Prozi","description":"Unity-inspired, reactive Game Framework for pixi.js - GameObject, Prefab, StateMachine, Sprite, CircleBody, PolygonBody, Physics, Sprite, Container, Animator","archived":false,"fork":false,"pushed_at":"2024-04-12T21:47:09.000Z","size":22818,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-14T06:49:00.550Z","etag":null,"topics":["animator","collision-detection","collision-handling","container","framework","game-engine","game-engine-2d","game-object","physics","prefab","reactive","scene","sprite","state-machine","test-driven-development","typescript","typescript-framework","unity","unity2d","webgl"],"latest_commit_sha":null,"homepage":"https://prozi.github.io/oneforall/","language":"TypeScript","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/Prozi.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}},"created_at":"2021-08-01T23:07:28.000Z","updated_at":"2024-04-15T18:44:30.224Z","dependencies_parsed_at":"2024-01-06T23:22:17.988Z","dependency_job_id":"0853f98b-87e9-4cc5-9ca8-071cc235cf12","html_url":"https://github.com/Prozi/oneforall","commit_stats":{"total_commits":125,"total_committers":5,"mean_commits":25.0,"dds":0.536,"last_synced_commit":"98dd63384f873c08eb194eeeca522b65dd905e71"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prozi%2Foneforall","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prozi%2Foneforall/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prozi%2Foneforall/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Prozi%2Foneforall/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Prozi","download_url":"https://codeload.github.com/Prozi/oneforall/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244660080,"owners_count":20489289,"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":["animator","collision-detection","collision-handling","container","framework","game-engine","game-engine-2d","game-object","physics","prefab","reactive","scene","sprite","state-machine","test-driven-development","typescript","typescript-framework","unity","unity2d","webgl"],"created_at":"2024-10-06T10:07:51.148Z","updated_at":"2025-03-20T17:30:29.508Z","avatar_url":"https://github.com/Prozi.png","language":"TypeScript","readme":"# One For All\n\n\u003cimg src=\"https://raw.githubusercontent.com/Prozi/oneforall/main/all-might.png\" alt=\"All Might from Boku No Hero Academia holds One For All in his palm\" width=\"456\" height=\"456\" style=\"image-rendering: pixelated; max-width: 100%;\" /\u003e\n\n### TypeScript gamedev library inspired by Unity\n\n[\u003cimg src=\"https://img.shields.io/npm/v/@pietal.dev/engine?style=for-the-badge\u0026color=success\" alt=\"npm version\" /\u003e](https://www.npmjs.com/package/@pietal.dev/engine?activeTab=versions)\n[\u003cimg src=\"https://img.shields.io/circleci/build/github/Prozi/oneforall/main?style=for-the-badge\" alt=\"build status\" /\u003e](https://app.circleci.com/pipelines/github/Prozi/oneforall)\n[\u003cimg src=\"https://img.shields.io/npm/l/@pietal.dev/engine.svg?style=for-the-badge\u0026color=success\" alt=\"license: MIT\" /\u003e](https://github.com/Prozi/oneforall/blob/master/LICENSE)\n\n## Demo\n\n```\n[1x Scene]\n  ├──[1x WebGL Canvas (pixi.js)]\n  ├──[1x Collision Detection]\n  └──[50x GameObject (Player)]\n       ├──[1x CircleBody]\n       └──[1x Animator]\n            └──[1x StateMachine]\n```\n\nTiny code, big results! Check out the [demo](https://prozi.github.io/oneforall/demo/?fps\u0026debug) to see below code in action.\n\nAlso, here is the [documentation](https://prozi.github.io/oneforall/modules.html).\n\n## Demo Code\n\n`src/demo/index.ts`\n\n```typescript\nasync function start(): Promise\u003cvoid\u003e {\n  const queryParams = Scene.getQueryParams();\n  // create main Scene\n  const scene: Scene = new Scene({\n    visible: true,\n    autoSort: true,\n    showFPS: 'fps' in queryParams,\n    debug: 'debug' in queryParams\n  });\n\n  // initialize scene async - new since pixi 7/8\n  await scene.init({\n    resizeTo: window,\n    autoDensity: true,\n    autoStart: false,\n    sharedTicker: false\n  });\n\n  // wait to load cave-boy.json and cave-boy.png, uses PIXI.Loader inside\n  const data = await Resources.loadResource('./cave-boy.json');\n  const texture = await Resources.loadResource(data.tileset);\n\n  // create 50 sprites from template\n  Array.from({ length: Number(queryParams.limit || 50) }, () =\u003e {\n    create({ scene, data, texture });\n  });\n\n  scene.start();\n  scene.update$.pipe(takeUntil(scene.destroy$)).subscribe(() =\u003e {\n    scene.physics.separate();\n  });\n}\n\nstart();\n```\n\n`src/demo/sprite.prefab.ts`\n\n```typescript\nexport function create({ scene, data, texture }): TGameObject {\n  // create game object\n  const gameObject = new GameObject('Player') as TGameObject;\n\n  // create body\n  gameObject.body = new CircleBody(gameObject, 20, 14, 20, { padding: 7 });\n  gameObject.body.setPosition(\n    Math.random() * innerWidth,\n    Math.random() * innerHeight\n  );\n\n  // create animator with few animations from json + texture\n  gameObject.sprite = new Animator(gameObject, data, texture);\n  gameObject.sprite.setState('idle');\n\n  // insert body to physics and game object to scene\n  scene.addChild(gameObject);\n\n  // subscribe to *own* update function until *own* destroy\n  gameObject.update$\n    .pipe(takeUntil(gameObject.destroy$))\n    .subscribe((deltaTime) =\u003e {\n      update(gameObject, deltaTime);\n    });\n\n  return gameObject;\n}\n\nexport function update(gameObject: TGameObject, deltaTime: number): void {\n  const scene = gameObject.scene;\n  const scale = scene.stage.scale;\n  const gameObjects = scene.children as TGameObject[];\n  // at 60fps deltaTime = 1.0, at 30fps deltaTime = 2.0\n  const safeDelta = Math.min(deltaTime, 2);\n  const chance = safeDelta * 0.01;\n\n  if (Math.random() \u003c chance) {\n    // goto random place\n    gameObject.target = {\n      x: (Math.random() * innerWidth) / scale.x,\n      y: (Math.random() * innerHeight) / scale.y\n    };\n  } else if (Math.random() \u003c chance) {\n    // goto random target\n    gameObject.target =\n      gameObjects[Math.floor(Math.random() * gameObjects.length)];\n  } else if (Math.random() \u003c chance) {\n    // stop\n    gameObject.target = null;\n  }\n\n  if (gameObject.target \u0026\u0026 distance(gameObject.target, gameObject) \u003c 9) {\n    gameObject.target = null;\n  }\n\n  if (!gameObject.target) {\n    gameObject.sprite.setState('idle');\n  } else {\n    gameObject.sprite.setState('run');\n\n    const angle: number = Math.atan2(\n      gameObject.target.y - gameObject.y,\n      gameObject.target.x - gameObject.x\n    );\n    if (!isNaN(angle)) {\n      const offsetX: number = Math.cos(angle);\n      const offsetY: number = Math.sin(angle);\n\n      if (gameObject.sprite instanceof Animator) {\n        const flipX: number =\n          Math.sign(offsetX || gameObject.sprite.scale.x) *\n          Math.abs(gameObject.sprite.scale.x);\n        // flip x so there is no need to duplicate sprites\n        gameObject.sprite.setScale(flipX, gameObject.sprite.scale.y);\n      }\n\n      // update body which updates gameObject game object\n      gameObject.body.setPosition(\n        gameObject.body.x + safeDelta * offsetX,\n        gameObject.body.y + safeDelta * offsetY\n      );\n    }\n  }\n}\n```\n\n## Features\n\n- [Unity-inspired architecture](https://docs.unity3d.com/Manual/CreatingGameplay.html)\n- [State management](https://gamedevelopment.tutsplus.com/tutorials/finite-state-machines-theory-and-implementation--gamedev-11867)\n- [Reactive events](https://www.learnrxjs.io/learn-rxjs/subjects)\n- [Lifecycle cleanup management](https://www.html5gamedevs.com/topic/44780-best-way-to-remove-objects-from-the-stage/)\n- [Collision detection](https://npmjs.com/package/detect-collisions)\n- [Drawing on WebGL canvas](https://npmjs.com/package/pixi.js)\n- Compatible with pixi version 6, 7 and 8 - at the same time!\n\n## Classes this library exports\n\n- **Resources:** Handles loading game assets like images and JSON files.\n- **Scene:** Sets the stage for gameplay, where all the action takes place.\n- **GameObject:** Represents characters, objects, or items in the game world.\n- **Prefab:** Instantiates ready-made templates for creating game elements.\n- **Sprite:** Displays static 2D graphics in the game.\n- **Container:** Organizes and manages groups of game objects for easier handling.\n- **Animator:** Useful JSON to Container with AnimatedSprite children.\n- **StateMachine:** Controls how game objects transition between actions.\n- **CircleBody:** Adds physics properties and interactions for round-shaped objects.\n- **PolygonBody:** Adds physics properties and interactions for polygonal objects.\n- **TextureAtlas:** Allows easy slicing of texture into smaller cached slices.\n\n## Installation\n\n```bash\nnpm i @pietal.dev/engine -D\n```\n\n## We also have tests\n\n```\n PASS  src/state-machine.spec.ts\n  GIVEN StateMachine\n    ✓ THEN you can set validators (4 ms)\n    ✓ THEN you can't change state to invalid state\n    ✓ THEN you can change state to valid state\n\n PASS  src/component.spec.ts\n  GIVEN Component\n    ✓ THEN update publishes update$ (1 ms)\n    ✓ THEN destroy publishes destroy$\n\n PASS  src/circle-body.spec.ts\n  GIVEN CircleBody\n    ✓ THEN it has set property radius (5 ms)\n    ✓ THEN it can't have zero radius (9 ms)\n    ✓ THEN update propagates x/y changes\n\n PASS  src/scene-ssr.spec.ts\n  GIVEN SceneBase\n    ✓ THEN it works (3 ms)\n    ✓ THEN it can have children (1 ms)\n    ✓ THEN scene propagates update to gameobject to component (1 ms)\n\n PASS  src/scene.spec.ts\n  GIVEN Scene\n    ✓ THEN it works (2 ms)\n    ✓ THEN it can have children\n    ✓ THEN scene propagates update to gameobject to component (1 ms)\n\n PASS  src/sprite.spec.ts\n  GIVEN Sprite\n    ✓ THEN update propagates x/y changes (3 ms)\n    ✓ THEN removeChild works\n    ✓ THEN destroy works (1 ms)\n    ✓ THEN destroy works extended (1 ms)\n\n PASS  src/prefab.spec.ts\n  GIVEN Prefab\n    ✓ THEN can be instantiated (3 ms)\n    ✓ THEN can create 100 instances (10 ms)\n\n PASS  src/game-object.spec.ts\n  GIVEN GameObject\n    ✓ THEN you can add component (5 ms)\n    ✓ THEN update propagates to components (1 ms)\n    ✓ THEN you can remove component\n    ✓ THEN destroy removes component (1 ms)\n    ✓ THEN you can get component by label\n    ✓ THEN you can get components by label\n    ✓ THEN you can destroy 1000 bodies without problem (106 ms)\n\n PASS  src/polygon-body.spec.ts\n  GIVEN PolygonBody\n    ✓ THEN update propagates x/y changes\n\n PASS  src/container.spec.ts\n  GIVEN Container\n    ✓ THEN update propagates x/y changes\n    ✓ THEN destroy works (1 ms)\n\n PASS  src/resources.spec.ts\n  GIVEN Resources\n    ✓ THEN it silently fails and proceeds (5 ms)\n\n PASS  src/index.spec.ts\n  GIVEN index.ts\n    ✓ THEN basic imports work (1 ms)\n\n PASS  src/application.spec.ts\n  GIVEN Application\n    ✓ THEN it works\n\nTest Suites: 13 passed, 13 total\nTests:       33 passed, 33 total\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprozi%2Foneforall","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprozi%2Foneforall","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprozi%2Foneforall/lists"}