{"id":25990357,"url":"https://github.com/harshdoesdev/square","last_synced_at":"2025-08-11T06:45:26.048Z","repository":{"id":37972180,"uuid":"492801375","full_name":"harshdoesdev/square","owner":"harshdoesdev","description":"An Entity Component System Based Game Engine","archived":false,"fork":false,"pushed_at":"2022-07-24T17:49:40.000Z","size":81,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-13T22:28:52.146Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/harshdoesdev.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}},"created_at":"2022-05-16T11:16:09.000Z","updated_at":"2024-05-16T17:47:50.000Z","dependencies_parsed_at":"2022-09-04T21:10:35.538Z","dependency_job_id":null,"html_url":"https://github.com/harshdoesdev/square","commit_stats":null,"previous_names":["harshdoesdev/square","rare-earth/square"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/harshdoesdev/square","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harshdoesdev%2Fsquare","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harshdoesdev%2Fsquare/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harshdoesdev%2Fsquare/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harshdoesdev%2Fsquare/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/harshdoesdev","download_url":"https://codeload.github.com/harshdoesdev/square/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harshdoesdev%2Fsquare/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269843250,"owners_count":24484115,"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","status":"online","status_checked_at":"2025-08-11T02:00:10.019Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2025-03-05T13:54:27.394Z","updated_at":"2025-08-11T06:45:26.017Z","avatar_url":"https://github.com/harshdoesdev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Square Banner](https://github.com/rare-earth/Square/raw/main/banner.png)\n\n# Square\n\nAn Entity Component System(ECS) Based Game Framework\n\n## Installation\n\n**NPM**\n```bash\nnpm i square-ecs\n```\n**CDN**\n```javascript\nimport { Application } from 'https://unpkg.com/square-ecs@latest';\n\n// your code\n```\n\n## Example\n\n**app.js**\n```javascript\nimport { Application } from \"square-ecs\";\nimport { InputSystem, RenderingSystem, ShapeRenderer, GravitySystem, MovementSystem } from \"./src/systems.js\";\nimport { BoxShapeComponent, VectorComponent } from \"./src/components.js\";\n\nconst app = new Application({\n    data: {\n        config: {\n            canvas: {\n                width: 400,\n                height: 400,\n            }\n        },\n        state: {\n            score: 0,\n            loading: true\n        }\n    },\n    systems: [\n        RenderingSystem, \n        ShapeRenderer, \n        InputSystem, \n        GravitySystem,\n        MovementSystem\n    ]\n});\n\napp.on(\"init\", app =\u003e {\n    const player = app.entityPool.getEntity();\n\n    player.tag(\"visible\")\n          .tag(\"controllable\")\n          .tag(\"player\")\n          .attach(\"position\", new VectorComponent(20, 20))\n          .attach(\"shape\", new BoxShapeComponent(32, 32))\n          .attach(\"speed\", 100)\n          .attach(\"jumpforce\", 500)\n          .attach(\"velocity\", new VectorComponent);\n\n    app.add(player);\n});\n\napp.start();\n```\n\n**systems.js**\n```javascript\nimport { RenderableQuery, KinematicBodyQuery } from \"./queries.js\";\n\nexport function RenderingSystem(app) {\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = app.data.config.canvas.width;\n    canvas.height = app.data.config.canvas.height;\n    canvas.style.background = \"#000\";\n\n    const context = canvas.getContext(\"2d\");\n\n    app.on(\"init\", () =\u003e {\n      document.body.appendChild(canvas);\n    });\n\n    app.on(\"update\", () =\u003e {\n        context.clearRect(0, 0, canvas.width, canvas.height);\n        app.emit(\"render\", context, canvas);\n    });\n};\n\nexport function InputSystem(app) {\n    app.data.state.keyboard = {};\n\n    const handleKey = ({ key, type }) =\u003e {\n        app.data.state.keyboard[key === \" \" ? \"Spacebar\" : key] = type === \"keydown\";\n    };\n\n    window.addEventListener(\"keydown\", handleKey);\n    window.addEventListener(\"keyup\", handleKey);\n}\n\nexport function MovementSystem(app) {\n    app.on(\"update\", dt =\u003e {\n        const [player] = app.query(\"controllable\");\n        if(!player.tags.has(\"jumping\") \u0026\u0026 app.data.state.keyboard.Spacebar) {\n            player.velocity.y -= player.jumpforce * dt;\n        }\n    });\n}\n\nexport function ShapeRenderer(app) {\n    app.on(\"render\", ctx =\u003e {\n        const entities = app.query(RenderableQuery);\n\n        entities.forEach(entity =\u003e {\n            ctx.fillStyle = '#fff';\n            ctx.fillRect(entity.position.x, entity.position.y, entity.shape.width, entity.shape.height);\n        });\n    });\n}\n\nexport function GravitySystem(app) {\n    app.on(\"update\", dt =\u003e {\n        const entities = app.query(KinematicBodyQuery);\n        entities.forEach(entity =\u003e {\n            entity.position.y += entity.velocity.y;\n            \n            if(entity.position.y \u003c 200) {\n                entity.tag(\"jumping\");\n                entity.velocity.y += 5 * GravitySystem.GRAVITY_CONSTANT * dt;\n            } else {\n                entity.untag(\"jumping\");\n                entity.velocity.y = 0;\n            }\n        });\n    });\n}\n\nGravitySystem.GRAVITY_CONSTANT = 6.5;\n```\n\n**queries.js**\n```javascript\nexport const RenderableQuery = ['@position', '@shape', 'visible'];\n\nexport const KinematicBodyQuery = ['@position', '@shape', '@velocity'];\n```\n\n**components.js**\n```javascript\nexport class BoxShapeComponent {\n    constructor(width, height) {\n        this.type = \"box\";\n        this.width = width;\n        this.height = height;\n    }\n}\n\nexport class VectorComponent {\n    constructor(x = 0, y = 0) {\n        this.x = x;\n        this.y = y;\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharshdoesdev%2Fsquare","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fharshdoesdev%2Fsquare","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharshdoesdev%2Fsquare/lists"}