Add README, bundle phaser.min.js, fix asset paths to be self-contained

This commit is contained in:
grovedruid committed 2026-07-04 17:52:45 +02:00
1 parent 5fff58884f
commit 3e6c496d62
3 files changed
+81 -1

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
# FSYS Agent — Platformer
Help the Collector from Australia collect cards from the clouds in Kenya!
Jump and run through procedurally generated cloud platforms, collect scattered cards, and survive the deadly spikes.
## Play
<https://jr.fsysgame.org>
## Tech Stack
- **Phaser 3** — HTML5 game framework (renderer: Canvas/WebGL)
- **Vanilla JS** — no bundler, no framework, no transpiler; plain ES5-style JS loaded via `<script>` tags
- **DOM Touch Events** — multi-touch joystick + jump for mobile controls (native `TouchEvent` API)
- **CSS Orientation Lock** — rotate-to-landscape overlay with `@media (orientation: portrait) and (pointer: coarse)`
- **No build step** — open `index.html` in a browser or serve any static file server
## Features
- Procedural cloud platform generation with difficulty scaling
- 60 unique cards to collect, each with custom thumbnail art
- Double jump with particle burst effect
- 360° analog joystick (left side) + tap-to-jump (right side) for mobile
- Keyboard support: arrow keys / WASD + Space / Up
- Automatic landscape rotation prompt on mobile
- Fullscreen button on touch devices (auto-fullscreen on first tap)
- Social preview cards (Open Graph / Twitter Card)
## Structure
```
index.html — game entry point
phaser.min.js — Phaser 3 library
preview.png — social preview image (1728×1080)
src/
main.js — Phaser config & game init
scenes/
Boot.js — boot / splash scene
Preloader.js — asset loading with progress bar
TitleScreen.js — title screen
Game.js — main gameplay scene
GameOver.js — game over screen
public/
images/
cloud.png
jump_pad.png
fsys_platform_bg.png
cards/thumbs/ — 60 card thumbnails (56×76)
assets/
sprites/ — player & environment sprites
tiles/ — platform/obstacle tiles
sounds/ — sound effects (OGG)
```
## Controls
| Input | Action |
|-----------|---------------------|
| Arrow/WASD | Move left/right |
| Space / Up | Jump (double jump) |
| Left stick | Move (mobile) |
| Right tap | Jump (mobile) |
## Development
Serve the `game/` directory with any static file server:
```bash
python3 -m http.server 8080
# or
npx serve .
```
No build step, no npm install, no config needed.
## License
FSYS Game — Alliance of Bioversity International and CIAT / CGIAR
+1 -1
View File
@@ -30,7 +30,7 @@
#game-container { display: none; } #game-container { display: none; }
} }
</style> </style>
<script src="../example/phaser.min.js"></script> <script src="phaser.min.js"></script>
</head> </head>
<body> <body>
<div id="rotate-warning"> <div id="rotate-warning">
+1
View File
@@ -0,0 +1 @@
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("Phaser",[],e):"object"==typeof exports?exports.Phaser=e():t.Phaser=e()}(this,()=>(()=>{var t={50792(t){"use strict";var e=Object.prototype.hasOwnProperty,i="~";function r(){}function s(t,e,i){this.fn=t,this.context=e,this.once=i||!1}function n(t,e,r,n,a){if("function"!=typeof r)throw new TypeError("The listener must be a function");var o=new s(r,n||t,a),h=i?i+e:e;return t._events[h]?t._events[h].fn?t._events[h]=[t._events[h],o]:t._events[h].push(o):(t._events[h]=o,t._eventsCount++),t}function a(t,e){0===--t._eventsCount?t._events=new r:delete t._events[e]}function o(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(i=!1)),o.prototype.eventNames=function(){var t,r,s=[];if(0===this._eventsCount)return s;for(r in t=this._events)e.call(t,r)&&s.push(i?r.slice(1):r);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(t)):s},o.prototype.listeners=function(t){var e=i?i+t:t,r=this._events[e];if(!r)return[];if(r.fn)return[r.fn];for(var s=0,n=r.length,a=new Array(n);s<n;s++)a[s]=r[s].fn;return a},o.prototype.listenerCount=function(t){var e=i?i+t:t,r=this._events[e];return r?r.fn?1:r.length:0},o.prototype.emit=function(t,e,r,s,n,a){var o=i?i+t:t;if(!this._events[o])return!1;var h,l,u=this._events[o],d=arguments.length;if(u.fn){switch(u.once&&this.removeListener(t,u.fn,void 0,!0),d){case 1:return u.fn.call(u.context),!0;case 2:return u.fn.call(u.context,e),!0;case 3:return u.fn.call(u.context,e,r),!0;case 4:return u.fn.call(u.context,e,r,s),!0;case 5:return u.fn.call(u.context,e,r,s,n),!0;case 6:return u.fn.call(u.context,e,r,s,n,a),!0}for(l=1,h=new Array(d-1);l<d;l++)h[l-1]=arguments[l];u.fn.apply(u.context,h)}else{var c,f=u.length;for(l=0;l<f;l++)switch(u[l].once&&this.removeListener(t,u[l].fn,void 0,!0),d){case 1:u[l].fn.call(u[l].context);break;case 2:u[l].fn.call(u[l].context,e);break;case 3:u[l].fn.call(u[l].context,e,r);break;case 4:u[l].fn.call(u[l].context,e,r,s);break;default:if(!h)for(c=1,h=new Array(d-1);c<d;c++)h[c-1]=arguments[c];u[l].fn.apply(u[l].context,h)}}return!0},o.prototype.on=function(t,e,i){return n(this,t,e,i,!1)},o.prototype.once=function(t,e,i){return n(this,t,e,i,!0)},o.prototype.removeListener=function(t,e,r,s){var n=i?i+t:t;if(!this._events[n])return this;if(!e)return a(this,n),this;var o=this._events[n];if(o.fn)o.fn!==e||s&&!o.once||r&&o.context!==r||a(this,n);else{for(var h=0,l=[],u=o.length;h<u;h++)(o[h].fn!==e||s&&!o[h].once||r&&o[h].context!==r)&&l.push(o[h]);l.length?this._events[n]=1===l.length?l[0]:l:a(this,n)}return this},o.prototype.removeAllListeners=function(t){var e;return t?(e=i?i+t:t,this._events[e]&&a(this,e)):(this._events=new r,this._eventsCount=0),this},o.prototype.off=o.prototype.removeListener,o.prototype.addListener=o.prototype.on,o.prefixed=i,o.EventEmitter=o,t.exports=o},93300(t,e,i){var r=i(10312);t.exports=function(t,e){Array.isArray(t)||(t=[t]),e||(e={});for(var i=void 0===e.threshold?.5:e.threshold,s=void 0===e.blurRadius?2:e.blurRadius,n=void 0===e.blurSteps?4:e.blurSteps,a=void 0===e.blurQuality?0:e.blurQuality,o=void 0===e.blendAmount?1:e.blendAmount,h=void 0===e.blendMode?r.ADD:e.blendMode,l=[],u=0;u<t.length;u++){var d=t[u];d.enableFilters&&d.enableFilters();var c=(e.useInternal?d.filters.internal:d.filters.external).addParallelFilters(),f=c.top.addThreshold(i,1),p=c.top.addBlur(a,s,s,1,16777215,n);c.blend.blendMode=h,c.blend.amount=o,l.push({item:d,parallelFilters:c,threshold:f,blur:p})}return l}},56704(t,e,i){var r=i(16438),s=i(10312),n=i(41337),a=i(95643),o=i(45650);t.exports=function(t,e){e||(e={}),Array.isArray(t)||(t=[t]);var i=t[0],h=i.scene,l=void 0===e.direction?.5:e.direction%(2*Math.PI),u=void 0===e.scale?2:e.scale,d=(e.radius||.5)/u,c=e.width||i.width||128,f=e.height||i.height||128,p={x:0,y:0};l<0&&(l+=2*Math.PI),l>3*Math.PI/2?p.y=1:l>Math.PI?(p.x=1,p.y=1):l>Math.PI/2&&(p.x=1);for(var g=[],m=0;m<t.length;m++){var v=t[m],y={origin:0,width:c,height:f,config:{offset:-d,repeatMode:3,shapeMode:0,direction:l,length:u,start:p,bands:e.bands||[{interpolation:2,colorStart:16777215,colorEnd:[1,1,1,0],size:d},{colorStart:[1,1,1,0],size:1-d}]}},x=h.make.gradient(y,!1);if(e.displacementMap){var T=e.displacement||.1;x.enableFilters().filters.internal.addDisplacement(e.displacementMap,T,T)}for(var w=o(),b=h.textures;b.exists(w);)w=o();var S=b.addDynamicTexture(w,x.width,x.height),C=h.tweens.add({targets:x,offset:1+d,repeat:-1,yoyo:!!e.yoyo,ease:e.ease,duration:e.duration||2e3,repeatDelay:e.repeatDelay||0,onUpdate:function(){S.clear().draw(x).render()}});v instanceof a&&v.enableFilters();var E,A,_=e.useExternal?v.filters.external:v.filters.internal,M=e.colorFactor||[1.15,.85,.85,1];e.reveal?E=_.addBlend(w,s.MULTIPLY,1,M):(E=(A=_.addParallelFilters()).top.addBlend(w,s.MULTIPLY,1,M),A.blend.blendMode=s.ADD);var R=function(){C.destroy(),S.destroy()};v instanLine truncated