{"id":15044724,"url":"https://github.com/smoudjs/tiny","last_synced_at":"2025-10-24T09:30:37.515Z","repository":{"id":38974563,"uuid":"220511514","full_name":"smoudjs/tiny","owner":"smoudjs","description":"Tiny canvas framework for HTML5 games and playable ads developing.","archived":false,"fork":false,"pushed_at":"2025-01-25T14:23:06.000Z","size":30723,"stargazers_count":19,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-25T15:23:44.153Z","etag":null,"topics":["canvas","canvas2d","game","game-engine","javascript","playable","playable-ad","renderer","rendering","rendering-2d-graphics","rendering-engine","threejs","tiny","webgl","webgl-library"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smoudjs.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":"2019-11-08T16:59:51.000Z","updated_at":"2024-12-06T16:56:03.000Z","dependencies_parsed_at":"2023-10-04T02:57:00.634Z","dependency_job_id":"49b5258a-5119-4ce1-a9bf-a66b3104e4e9","html_url":"https://github.com/smoudjs/tiny","commit_stats":{"total_commits":94,"total_committers":3,"mean_commits":"31.333333333333332","dds":0.0957446808510638,"last_synced_commit":"2fce883dc7bee738ffb883a681d32156c8a2cdec"},"previous_names":["smoudjs/tiny","peter-hutsul/h5tiny"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoudjs%2Ftiny","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoudjs%2Ftiny/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoudjs%2Ftiny/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoudjs%2Ftiny/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smoudjs","download_url":"https://codeload.github.com/smoudjs/tiny/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237944085,"owners_count":19391588,"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":["canvas","canvas2d","game","game-engine","javascript","playable","playable-ad","renderer","rendering","rendering-2d-graphics","rendering-engine","threejs","tiny","webgl","webgl-library"],"created_at":"2024-09-24T20:50:57.362Z","updated_at":"2025-10-24T09:30:36.597Z","avatar_url":"https://github.com/smoudjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HTML5 Tiny\n\n[![NPM Package][npm]][npm-url]\n[![Build Size][build-size]][build-size-url]\n[![Build Size][build-size-gziped]][build-size-url]\n[![NPM Downloads][npm-downloads]][npmtrends-url]\n[![DeepScan][deepscan]][deepscan-url]\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://smoudjs.github.io/tiny/examples/res/image2.png\" width=\"450\" alt=\"Tiny intro\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://smoudjs.github.io/tiny/examples/index.html\"\u003eExamples\u003c/a\u003e |\n    \u003ca href=\"https://smoudjs.github.io/tiny\"\u003eDocumentation\u003c/a\u003e\n\u003c/p\u003e\n\nIt is a fast, comfortable, lightweight and flexible html5 game framework, you can use for building 2D games and playable ads.\nThe first version of this project was based on PIXI library.\nThe syntax of application is pretty similar to the Phaser framework.\n\nUse our plugins to extend Tiny abilities:\n\n- [three 📦](https://github.com/smoudjs/tiny/tree/master/plugins/three)\n- [particles 🔥](https://github.com/smoudjs/tiny/tree/master/plugins/particles)\n- [sound 🎵](https://github.com/smoudjs/tiny/tree/master/plugins/sound)\n- [create 🛠](https://github.com/smoudjs/tiny/tree/master/plugins/create)\n- [anim 🎬](https://github.com/smoudjs/tiny/tree/master/plugins/anim)\n- [extra ❤️](https://github.com/smoudjs/tiny/tree/master/plugins/extra)\n\n### Installation\n\nInstall via npm:\n\n```sh\n$ npm install tiny\n```\n\nUse CDN:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/tiny@2.0.10/build/tiny.js\"\u003e\u003c/script\u003e\n```\n\n### API Documentation\n\nWork in progress ...\n\nBut\n\nSee the sources for details, it's easy !\n\n### Usages\n\nBasic Usage:\n\n```javascript\nvar renderer = new Tiny.CanvasRenderer(640, 320);\ndocument.body.appendChild(renderer.domElement);\n\nvar scene = new Tiny.Scene();\nvar text = new Tiny.Text(\"Hello World!\");\nscene.add(text);\nrenderer.render(scene);\n\n```\n\nTiny application with basic systems and state manager:\n\n```javascript\nvar renderer = new Tiny.CanvasRenderer(640, 320);\ndocument.body.appendChild(renderer.domElement);\n\nvar scene = new Tiny.Scene();\n\nvar states = {\n    preload: function() {\n        // Tiny.Loader\n        // this.load.image(\"key\", source);\n    },\n    create: function() {\n\n        // var sprite = new Tiny.Sprite(\"key\");\n\n        var text = new Tiny.Text(\"Hello World!\");\n        this.text = text;\n        text.x = 200;\n        text.y = 100;\n        scene.add(text);\n    },\n    update: function(time, delta) {\n        this.text.rotation += delta * 0.001;\n    },\n    render: function() {\n        renderer.render(scene);\n    }\n}\n\nnew Tiny.App(states);\n\n```\n\nTiny application with class (full example)\n\n```javascript\nimport 'tiny';\n\nclass MyGame extends Tiny.App {\n\n    constructor(width, height) {\n\n        super();\n\n        this.width = width;\n        this.height = height;\n\n        this.renderer = new Tiny.CanvasRenderer(this.width, this.height);\n\n        /**\n         * Specify DOM element for Tiny.Input \n         */\n        this.inputView = this.renderer.domElement;\n\n        document.body.appendChild(this.renderer.domElement);\n\n        this.scene = new Tiny.Scene();\n    }\n\n    preload() {\n        // Tiny.Loader\n        // this.load.image(\"image1\", source);\n        // this.load.atlas(\"image2\", source, sourceFrames);\n        // this.load.spritesheet(\"image3\", source, sourceFrames);\n    }\n\n    create() {\n\n        // var sprite = new Tiny.Sprite(image1);\n        // var sprite2 = new Tiny.Sprite(\"image2\", \"frameName\");\n        // var graphics = new Tiny.Graphics();\n        // graphics.drawRect(20, 20, 100, 50);\n        // var container = new Tiny.Object2D();\n        // container.add(sprite2d);\n        // container.add(new Tiny.Text(\"In container!\"));\n\n        var text = new Tiny.Text(\"Hello World!\");\n        this.text = text;\n        text.x = 200;\n        text.y = 100;\n        this.scene.add(text);\n\n        // Tiny.Timer\n        this.timer.add(1000, function() {\n            console.log(\"Timer example: one time\");\n        });\n\n        this.timer.loop(1000, function() {\n            console.log(\"Timer example: loop\");\n        })\n\n        // Tiny.Input\n        this.input.on(\"down\", function(e) {\n            console.log(\"Down on game\");\n        });\n\n        this.input.on(\"move\", function(e) {\n            console.log(\"Mouse move: \" + e.x + \":\" + e.y);\n        });\n\n        this.input.add(text);\n        text.input.on(\"click\", function(e) {\n            console.log(\"Click on text\");\n        });\n\n        text.input.on(\"down\", function(e) {\n            console.log(\"Down on text\");\n        });\n\n        text.input.on(\"up\", function(e) {\n            console.log(\"Up on text\");\n        });\n\n        this.tweens.add(text.scale).to({\n            x: 1.1,\n            y: 1.1\n        }, 500).yoyo(true).easing(Tiny.Easing.Sinusoidal.InOut).repeat(Infinity).start();\n    }\n\n    update(time, delta) {\n        this.text.rotation += delta * 0.001;\n    }\n\n    render() {\n        this.renderer.render(this.scene);\n    }\n\n    resize(width, height) {\n\n        super.resize(width, height);\n\n        this.renderer.setSize(width, height);\n    }\n\n    destroy(clearCache) {\n\n        super.destroy(clearCache);\n\n        this.scene.destroy();\n        this.renderer.destroy(true);\n    }\n\n}\n\nnew MyGame(640, 320);\n\n```\n\n### Plugins\n\nThree.js plugin (three):\n\n```javascript\nimport 'tiny';\nimport 'tiny/plugins/three';\n\nclass MyGame extends Tiny.App {\n\n    constructor(width, height) {\n\n        super();\n\n        this.width = width;\n        this.height = height;\n\n        this.renderer = new THREE.WebGLRenderer({\n            antialias: true\n        });\n\n        this.renderer.outputEncoding = THREE.sRGBEncoding;\n        this.renderer.setSize(this.width, this.height);\n        this.inputView = this.renderer.domElement;\n        document.body.appendChild(this.renderer.domElement);\n\n        this.scene = new THREE.Scene();\n        this.camera = new THREE.OrthographicCamera(1, 1, 1, 1, 0.3, 500);\n\n        this.camera.position.set(40, 50, 40);\n        this.camera.lookAt(0, 0, 0);\n        this.camera.distance = 4;\n\n        this.screen2d = new Tiny.Screen2D(this.width, this.height);\n\n        this.setupCamera();\n    }\n\n    preload() {\n        // Tiny.Loader\n        // this.load.image(\"image1\", source);\n        // this.load.atlas(\"image2\", source, sourceFrames);\n        // this.load.spritesheet(\"image3\", source, sourceFrames);\n\n        // this.load.gltf(\"model\", gltfJson, splitObjects = false );\n        // this.load.texture3d(\"texture\", imageSrc);\n    }\n\n    create() {\n\n        var light = new THREE.DirectionalLight(0xffffff, 1);\n        light.position.set(15, 59, 53);\n        light.lookAt(0, 0, 0);\n        this.scene.add(light);\n\n        var text = new Tiny.Text(\"Hello World!\", {\n            fill: \"#ffffff\"\n        });\n        this.text = text;\n        text.x = 200;\n        text.y = 100;\n        this.screen2d.add(text);\n\n        this.tweens.add(text.scale).to({\n            x: 1.1,\n            y: 1.1\n        }, 500).yoyo(true).easing(Tiny.Easing.Sinusoidal.InOut).repeat(Infinity).start();\n\n        var mesh = new THREE.Mesh(new THREE.BoxBufferGeometry(1, 1, 1), new THREE.MeshLambertMaterial({\n            color: \"#ff4534\"\n        }));\n        mesh.material.color.convertSRGBToLinear();\n        this.scene.add(mesh);\n\n        // var importedScene = this.cache.gltf[\"model\"].scene;\n        // this.scene.add(importedScene);\n\n        // var importedSceneMesh = this.cache.mesh3d[\"model.meshName\"];\n        // importedSceneMesh.material.map = this.cache.texture3d[\"texture\"];\n        // this.scene.add(importedSceneMesh);\n    }\n\n    update(time, delta) {\n        this.text.rotation += delta * 0.001;\n    }\n\n    setupCamera() {\n\n        var aspect = this.width / this.height;\n        var distance = this.camera.distance;\n\n        if (this.camera) {\n            if (this.camera.isOrthographicCamera) {\n                this.camera.left = -distance * aspect;\n                this.camera.right = distance * aspect;\n                this.camera.top = distance;\n                this.camera.bottom = -distance;\n            } else {\n                this.camera.fov = distance * 1.2;\n                this.camera.aspect = aspect;\n            }\n\n            this.camera.updateProjectionMatrix();\n        }\n    }\n\n    setPixelRatio(dpr) {\n        this.renderer.setPixelRatio(dpr);\n        this.screen2d.renderer.setPixelRatio(dpr);\n    }\n\n    render() {\n        this.renderer.autoClear = true;\n        this.renderer.render(this.scene, this.camera);\n        this.renderer.autoClear = false;\n        this.renderer.render(this.screen2d.scene, this.screen2d.camera);\n    }\n\n    resize(width, height) {\n\n        super.resize(width, height);\n\n        this.screen2d.setSize(width, height)\n        this.renderer.setSize(width, height);\n        this.setupCamera();\n    }\n\n    destroy(clearCache) {\n\n        super.destroy(clearCache);\n\n        this.screen2d.scene.dispose();\n        this.scene.dispose();\n        if (this.renderer.domElement.parentNode) {\n            this.renderer.domElement.parentNode.removeChild(this.renderer.domElement);\n        }\n\n        this.renderer.dispose();\n        this.renderer = undefined;\n    }\n}\n\nnew MyGame(640, 320);\n\n```\n\nParticles plugin (particles)\n\n```javascript\nimport 'tiny';\nimport 'tiny/plugins/particles';\n\nclass SmokeParticle extends Tiny.Particle {\n\n    constructor(emitter) {\n        super(emitter);\n    }\n\n    update(time, delta) {\n        this.scale.set(Math.min(time / 1000, 0.7));\n        this.alpha = Math.min(time / 1000, 1)\n\n        this.y -= this.yspeed * delta\n        this.x += this.xspeed * delta\n        this.rotation += this.rotationsp\n    }\n\n    onEmit() {\n        this.xspeed = Tiny.rnd(-4, 4) * 0.05\n        this.yspeed = Tiny.rnd(2, 10) * 0.05\n        this.rotationsp = Math.random() * 0.02 - 0.01\n    }\n\n    draw(context, resolution) {\n        context.fillRect(0, 0, 100 * resolution, 100 * resolution)\n    }\n}\n\nclass MyGame extends Tiny.App {\n\n    constructor(width, height) {\n\n        super();\n\n        this.width = width;\n        this.height = height;\n\n        this.renderer = new Tiny.CanvasRenderer(this.width, this.height);\n\n        /**\n         * Specify DOM element for Tiny.Input \n         */\n        this.inputView = this.renderer.domElement;\n\n        document.body.appendChild(this.renderer.domElement);\n\n        this.scene = new Tiny.Scene();\n    }\n\n    preload() {\n        // Tiny.Loader\n        // this.load.image(\"image1\", source);\n    }\n\n    create() {\n        var emitter = new Tiny.Emitter(300);\n        emitter.x = 200;\n        emitter.y = 250;\n        emitter.width = 40\n\n        emitter.pattern = SmokeParticle;\n        emitter.fillStyle = \"#666666\";\n\n        emitter.makeParticles();\n        // emitter.makeParticles(\"image1\");\n\n        emitter.scale.set(0.7);\n        emitter.flow(1000, 100, 8);\n\n        // Tiny.ParticleSystem\n        this.particles.add(emitter);\n\n        this.scene.add(emitter);\n    }\n\n    render() {\n        this.renderer.render(this.scene);\n    }\n\n    resize(width, height) {\n\n        super.resize(width, height);\n\n        this.renderer.setSize(width, height);\n    }\n\n    destroy(clearCache) {\n\n        super.destroy(clearCache);\n\n        this.scene.destroy();\n        this.renderer.destroy(true);\n    }\n\n}\n\nnew MyGame(640, 320);\n\n```\n\n### Demos\n\nCheck the [examples](https://smoudjs.github.io/tiny/examples/index.html) to see more\n\n[\u003cdiv align=\"center\"\u003e\u003cimg alt=\"Tiny examples intro\" width=\"550\" src=\"https://smoudjs.github.io/tiny/examples/res/image.png\" /\u003e\u003c/div\u003e](https://smoudjs.github.io/tiny/examples/index.html)\n\n[npm]: https://img.shields.io/npm/v/@smoud/tiny\n[npm-url]: https://www.npmjs.com/package/@smoud/tiny\n[build-size]: https://badgen.net/bundlephobia/min/@smoud/tiny\n[build-size-gziped]: https://badgen.net/bundlephobia/minzip/@smoud/tiny\n[build-size-url]: https://bundlephobia.com/result?p=@smoud/tiny\n[npm-downloads]: https://img.shields.io/npm/dw/@smoud/tiny\n[npmtrends-url]: https://www.npmtrends.com/@smoud/tiny\n[deepscan]: https://deepscan.io/api/teams/19616/projects/23076/branches/688845/badge/grade.svg\n[deepscan-url]: https://deepscan.io/dashboard/#view=project\u0026tid=19616\u0026pid=23076\u0026bid=688845\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmoudjs%2Ftiny","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmoudjs%2Ftiny","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmoudjs%2Ftiny/lists"}