@makefully/platypus 4.1.22 → 4.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makefully/platypus",
3
- "version": "4.1.22",
3
+ "version": "4.1.24",
4
4
  "description": "2D tile-based HTML5 game engine with a component-based entity model",
5
5
  "license": "MIT",
6
6
  "contributors": [
package/src/Game.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /* global document, platypus, window */
2
2
  import {Application} from 'springroll';
3
- import {CullerPlugin, Application as PixiApplication, Rectangle, Ticker, extensions} from 'pixi.js';
3
+ import {CullerPlugin, Application as PixiApplication, RenderTexture, Ticker, extensions} from 'pixi.js';
4
4
  import {arrayCache, greenSlice, greenSplice, union} from './utils/array.js';
5
5
  import Data from './Data.js';
6
6
  import Entity from './Entity.js';
@@ -828,13 +828,14 @@ class Game extends Messenger {
828
828
  * Captures a screenshot of the currently visible game viewport (the canvas /
829
829
  * camera view), not the full stage or world bounds.
830
830
  *
831
- * Prefer this over `renderer.extract.*(stage)` without a frame — extracting
832
- * the bare stage uses content bounds and can include off-screen world area.
831
+ * Renders the stage into a screen-sized render texture (same space as the
832
+ * backbuffer), then extracts that texture. Never extracts the full stage —
833
+ * large levels exceed GPU max texture / renderbuffer size.
833
834
  *
834
835
  * @param {Object} [options]
835
836
  * @param {string} [options.format='png'] Image format for data URLs (`png`, `jpg`/`jpeg`, `webp`).
836
837
  * @param {number} [options.quality] Encoder quality for lossy formats (0–1).
837
- * @param {boolean} [options.render=true] Render the stage before capturing.
838
+ * @param {boolean} [options.render=true] Unused; kept for API compatibility (always renders to the capture target).
838
839
  * @param {string} [options.as='dataURL'] Return type: `dataURL` or `canvas`.
839
840
  * @return {Promise<string|HTMLCanvasElement|null>} Screenshot, or null if unavailable.
840
841
  **/
@@ -843,7 +844,6 @@ class Game extends Messenger {
843
844
  {
844
845
  format = 'png',
845
846
  quality,
846
- render = true,
847
847
  as = 'dataURL'
848
848
  } = options,
849
849
  {renderer, stage} = this;
@@ -852,50 +852,51 @@ class Game extends Messenger {
852
852
  return null;
853
853
  }
854
854
 
855
- if (render) {
856
- renderer.render(stage);
857
- }
858
-
859
855
  const
860
- {resolution, screen} = renderer,
861
- frame = new Rectangle(0, 0, screen.width, screen.height),
862
- extractOptions = {
863
- target: stage,
864
- frame,
865
- resolution
866
- };
856
+ width = Math.max(1, renderer.screen.width | 0),
857
+ height = Math.max(1, renderer.screen.height | 0),
858
+ resolution = renderer.resolution || 1,
859
+ backgroundColor = this.options?.display?.backgroundColor,
860
+ hasBackground = typeof backgroundColor === 'number' && backgroundColor >= 0,
861
+ // Opaque clear — transparent captures read as a black shot in Notefully.
862
+ clearColor = hasBackground ? backgroundColor : 0x000000,
863
+ mime = format === 'jpg' || format === 'jpeg'
864
+ ? 'image/jpeg'
865
+ : format === 'webp'
866
+ ? 'image/webp'
867
+ : 'image/png';
868
+
869
+ let target = null;
867
870
 
868
871
  try {
872
+ target = RenderTexture.create({
873
+ width,
874
+ height,
875
+ resolution
876
+ });
877
+
878
+ renderer.render({
879
+ container: stage,
880
+ target,
881
+ clear: true,
882
+ clearColor
883
+ });
884
+
885
+ const canvas = renderer.extract.canvas(target);
886
+
869
887
  if (as === 'canvas') {
870
- return renderer.extract.canvas(extractOptions);
888
+ return canvas;
871
889
  }
872
890
 
873
- return await renderer.extract.base64({
874
- ...extractOptions,
875
- format,
876
- quality
877
- });
891
+ return typeof quality === 'number'
892
+ ? canvas.toDataURL(mime, quality)
893
+ : canvas.toDataURL(mime);
878
894
  } catch (err) {
879
895
  platypus.debug.warn('Game.captureViewport failed.', err);
880
-
881
- // Fallback: canvas buffer after the render above (viewport-sized).
882
- try {
883
- if (as === 'canvas') {
884
- return this.canvas;
885
- }
886
-
887
- const mime = format === 'jpg' || format === 'jpeg'
888
- ? 'image/jpeg'
889
- : format === 'webp'
890
- ? 'image/webp'
891
- : 'image/png';
892
-
893
- return typeof quality === 'number'
894
- ? this.canvas.toDataURL(mime, quality)
895
- : this.canvas.toDataURL(mime);
896
- } catch (fallbackErr) {
897
- platypus.debug.warn('Game.captureViewport canvas fallback failed.', fallbackErr);
898
- return null;
896
+ return null;
897
+ } finally {
898
+ if (target) {
899
+ target.destroy(true);
899
900
  }
900
901
  }
901
902
  }