{"id":16182789,"url":"https://github.com/snowfrogdev/adventure","last_synced_at":"2026-01-20T11:32:42.238Z","repository":{"id":98331513,"uuid":"117370921","full_name":"snowfrogdev/adventure","owner":"snowfrogdev","description":null,"archived":false,"fork":false,"pushed_at":"2018-04-16T17:38:18.000Z","size":352,"stargazers_count":1,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-07T18:48:27.554Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/snowfrogdev.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-01-13T19:13:03.000Z","updated_at":"2019-10-07T09:05:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"ff0e0b32-ec5e-4771-8eef-d4a4e1d5c67e","html_url":"https://github.com/snowfrogdev/adventure","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/snowfrogdev/adventure","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowfrogdev%2Fadventure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowfrogdev%2Fadventure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowfrogdev%2Fadventure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowfrogdev%2Fadventure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/snowfrogdev","download_url":"https://codeload.github.com/snowfrogdev/adventure/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snowfrogdev%2Fadventure/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28602461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T10:46:13.255Z","status":"ssl_error","status_checked_at":"2026-01-20T10:42:51.865Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":"2024-10-10T06:43:57.854Z","updated_at":"2026-01-20T11:32:42.222Z","avatar_url":"https://github.com/snowfrogdev.png","language":"TypeScript","readme":"# Introduction\n\nThis is a template project for using TypeScript and WebPack to build [PlayCanvas](https://playcanvas.com) projects.\n\nPlayCanvas is a fantastic open source WebGL Engine and online Editor (which you can get access to for free or pay for an organisational license).\n\nPlayCanvas have developed a shared model that means you can edit your 3D scenes as a collaborative experience with\nteam mates around the office, or around the world - it's great.  They have applied the same to code editing, which \nis fine for some use cases but imposes certain limitations:\n\n* No offline access to source code\n* You are stuck with their web editor - which is \"ok\" but no WebStorm, Sublime or VSCode\n* No source control\n* Someone else can change your file when you aren't looking and you'll never know who!\n* No ES6 features or type safety, just pure Javascript\n* No NPM ecosystem, meaning you are scrabbling for browserified versions of libraries or more often doing something again or just not bothering\n\nAll of this means that it is hard to choose PlayCanvas for serious development projects without going \"Engine Only\"\nand that loses you many of the advantages of having a fantastic online editor and layout tool.  So now why choose\nPlayCanvas when Three.js would give you just as much if not more?\n\nThe answer has to be to produce code in a proper offline build environment with all the advantages of TypeScript, WebPack, NPM et al and still be able to use the output in the PlayCanvas online Editor.  [Mike Talbot](https://github.com/whydoidoit) paved the way for this project with his awesome [babel-playcanvas-template](https://github.com/whydoidoit/babel-playcanvas-template) project which I have forked and adapted for use with TypeScript.\n\n## Why ES6\n\nIf you are asking why you should use TypeScript and ES6 then I'd say it's for one simple reason: a programming language should try to get the hell out of your way and let you express what you want.\n\nWhen we code Javascript for WebGL we are coding for the browser and nearly everything that touches the outside world will be async.  Expressing async in traditional Javascript is messy as hell.  Try writing a for-next loop that loads a list of things from the web in sequence using Promises or callbacks and it will become immediately obvious.  With TypeScript and ES6 it's just a loop.  Everything else is a christmas tree.  Yes it's possible, but it's easy to have a\nhard to spot bug, so you do LESS of it than you would otherwise and refactoring is a scary prospect.  That's not right.  That's damaging your creativity to my mind.\n\n```javascript\n\nfunction requestFromUrl(url, info) { return new Promise(/* code */)}\n\nasync function getData() {\n    let urls = [\"https://blah1.org\", \"https://blah1.org/blah\", \"https://blah2.org/blah/blah\"];\n    let data = \"\";\n    for(let i = 0; i \u003c urls.length; i++) {\n        data = await requestFromUrl(urls[i], data);\n    }\n    return data;\n}\n\n```\n\nI know this is a contrived example, but this \"kind of thing\" happens all of the time in my developments, and they are better for me being able to implement them easily. Write that as just promises or callbacks and it will be illegible\nto most developers without a lot of study.\n\nES6/ES7 etc exist to create a better programming language for the web, I say let's use it.\n\n### Not many browsers support ES6 let alone ES7\n\nTypeScript takes care of that. If the browser doesn't support something, it provides that support for you.  Plus it compiles your ES6 to ES5.\n\n## Why TypeScript\n\nYou might be wondering \"**Why add types to JavaScript?**\"\n\nTypes have proven ability to enhance code quality and understandability. Large teams (Google, Microsoft, Facebook) have continually arrived at this conclusion. Specifically:\n\n* Types increase your agility when doing refactoring. *It's better for the compiler to catch errors than to have things fail at runtime.*\n* Types are one of the best forms of documentation you can have. *The function signature is a theorem and the function body is the proof*. \n\nHowever types have a way of being unnecessarily ceremonious. Thankfully TypeScript is very particular about keeping the barrier to entry as low as possible.\n\n## Why NPM\n\nIf you need some standard function, algorithm or procedure there's a good chance that there is tested code out there to install.\nwith one line of shell script.\n\n## Why WebPack\n\nWebPack is going to make building all of this and serving it to your browser an automated process.\n\n# Getting Started\n\nThe shortest way to get started is really simple.\n\n## Prerequisites\n\nYou must have a version of Node and NPM installed.\n\nYou can get that from [here](https://nodejs.org).\n\n## Installing the template project\n\n**EITHER**\n\nDownload this repo, change to the directory and type:\n\n```shell\nnpm install\n```\n\n**OR**\n\nMake a directory and change to it\n\n```shell\nnpm install typescript-playcanvas-template\n```\n\nNow in `[YOUR_DIRECTORY]/node_modules/typescript-playcanvas-template` are all of the files you need.  Either develop in there or copy that whole directory structure somewhere you want to develop.\n\nThe entry point - which is where you will import your own code - is in `src/main.ts`\n\nIn the template this imports a bunch of PlayCanvas extensions and then a single\n`example.ts` script that uses a couple of ES6 and TypeScript features for a demo.\n\n## Writing your own code\n\nCreate a file in `src` or a sub directory and script what you like. Just make sure that it is imported by `main.ts` (note that paths are relative to `src` and must start with a `./`).\n\nWhen you start developing things that import each other, you just need to make sure that something in `main.ts` imports something that imports the code you add!\n\nIf you find that something didn't show up, that's probably why.\n\n### Using ES6 classes\n\nUnfortunately, the way the PlayCanvas engine is architected makes it impossible to simply define scripts with the new ES6 class keyword. Using the convenience of decorators, this project allows you to do just that. So instead of this:\n\n```javascript\nvar Rotate = pc.createScript(\"rotate\");\n\nRotate.prototype.update = function (dt) {\n    this.entity.rotate(0, 10*dt, 0);\n};\n```\n\nyou can do this:\n\n```typescript\n@createScript()\nclass Rotate extends ScriptTypeBase implements ScriptType {\n    update(dt: number) {\n        this.entity.rotate(0, 10 * dt, 0);\n    }\n}\n```\n\nThis becomes especially useful when your script has a mix bag of public, private and static properties and methods allowing for cleaner, clearer code. Also makes the use of `this` a little easier.\n\n## Building, debugging and testing your code\n\nFirstly we need to make a configuration file - there's an example called `config.example.json`.\n\nThe config file is in the root of the project (the parent of `src`) and needs\nto be called `config.json`.  This will eventually also control the automatic upload\nof your code to PlayCanvas, but to start with, just copy the example to `config.json`.\n\nYou can build your code using either `webpack` or an automated process with `npm`.\n\nSo typing `npm run build` in the root folder of the project (the parent of `src`)\nthe template will build a production version of your code into the `build` folder.\n\n**Either** build your code with NPM\n\n```shell\nnpm run build\n```\n\n**Or** build your production code with webpack\n\n```shell\nwebpack --config webpack.production.config.js\n```\n\nThe output file will be called `main.build.js`.  To use that in PlayCanvas just drag and drop\nit onto the PlayCanvas editor for your project.\n\nNow open your developer tools in the browser with the PlayCanvas Editor open and in \nthe Javascript console type\n\n```javascript\nconfig.accessToken\n```\n\nCopy the result of this and paste it into the `config.json` file as your bearer token.\n\nThen in the javascript console type\n\n```javascript\nconfig.project.id\n```\n\nAnd put that in the project id part of `config.json`\n\nFinally if you haven't already done it, drag `main.build.js` and drop it in the PlayCanvas assets window.  \n\nWhen it's imported click on it and in the properties window on the right, take it's ID and put that in \n`config.json` as your assetId.\n\nNow every time you run `npm run build` it will upload the result to PlayCanvas for you. \n\n### Local serving your development build\n\nThere's a better way to do ongoing development though, you only really need to upload your build when\nthe attributes of something change, you add a new script or you want to publish your build.\n\nThis template project has a solution for that too.  You will be able to see all of your source code in your developer tools when you use any means of making a `development` build.\n\n#### Loading Screen Method\n\nIf you have a loading screen or can make one then you can use either the whole script in\n`utility-scripts/loading_screen_scripts_2_0.js` or add the `utility-scripts/exerpt.js` to\nthe top of your own.\n\nThis will allow you to serve files locally if you add a `?local=http://localhost:8081` to\nyour launch url query string **AND** you change the protocol of the launch page to be `http`.\nIf you really need `https` then see the section later on how to do that instead.\n\n#### PlayCanvas Script Method\n\nThis is less reliable.  Create a script in PlayCanvas Editor.  Copy `utility-scripts/exerpt.js`\ninto it and set it's loading order to be before `main.build.js`.\n\nSee the instruction about the URL in the previous section on how to modify your launch to use\nit.\n\n#### Starting the server\n\nNow you can type `npm start` in the project root. This will, build and upload your code, then start a local server\nto serve any changes you make.  When you change your code, your launch window will automatically\nupdate.\n\nIf you need to upload again, just stop the server with CTRL+C and type `npm start` again. Then refresh\nyour launch and Editor windows.\n\n### Development builds without local serving\n\nType `webpack --config webpack.development.config.js` to build and (if configured) upload a development\nversion of your code which will have source mapping to make it possible to see your own code\nwhen you debug.\n\n## Production Build\n\nJust type `npm run build` any time you want a production build.\n\nProduction builds are minified and don't have source maps embedded (they are a separate file).\n\n## Using NPM\n\nYou can just use NPM like normal.  Basically find the module you need and type\n\n```shell\nnpm install --save \u003cmodule-name\u003e\n```\n\nYou can then import it into the file you need it in by adding an `import` statement at the top of your file.\n\n```javascript\nimport blah from 'blah-module';\n\n...\n\nblah(something);\n\n```\n\nYou may also use `require` syntax if the whole file is written that way.\n\n# Conclusion\n\nHopefully this will get you started using TypeScript, ES6 and modules with PlayCanvas. Feel free to ask for @neoflash on the PlayCanvas forum if you want to discuss.\n\nEnjoy!\n\n\n\n*- Ends -*\n\n----\n\n\n\n##### HTTPS serving\n\nYou can configure webpack to HTTPS serve instead of HTTP.\n\nUse `npm run https` to start your local development build. Then:\n\n* Either: in a separate window navigate to https://localhost:8081/main.build.js and if you are warned it isn't safe, just proceed anyway. This will mean that you always see that the launch page is untrusted and may cause other issues, it's normally fine for me.\n\n* Or: get your browser to trust `node_modules/webpack-dev-server/ssl/server.pem`. This can be easier said than done.  You can also replace `server.pem` with your own trusted `localhost` certificate.  Just you'll have to pack it as a `.pem` file. (On Apple by default it will be a `.p12`, Google for how to change it).\n\n**Don't forget to change your launch URL and the local parameter `?local=http://localhost:8081` to HTTPS!!**\n\nPersonally I've used [Certificate Tools](https://certificatetools.com) to make certs that work. Make sure you sent the `Subject\nAlternative Name(s) DNS` to `localhost` **as well as** `Common Names`.  It also provides you with a thing\nto run to pack .p12 into a .pem after you've generated your certificate.  It only took me about 5 tries\nto work out what I had to do with it!\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnowfrogdev%2Fadventure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnowfrogdev%2Fadventure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnowfrogdev%2Fadventure/lists"}