@makefully/platypus 4.1.22 → 4.1.23

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.23",
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
@@ -828,8 +828,10 @@ 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
+ * Uses the same crop approach as Paco's ScreenShooter: after camera
832
+ * transforms, the visible area is stage space (0, 0, screenWidth, screenHeight).
833
+ * Extracting only that frame avoids pulling in off-screen world content and
834
+ * avoids GPU texture-size failures when a full level's stage bounds are huge.
833
835
  *
834
836
  * @param {Object} [options]
835
837
  * @param {string} [options.format='png'] Image format for data URLs (`png`, `jpg`/`jpeg`, `webp`).
@@ -857,46 +859,72 @@ class Game extends Messenger {
857
859
  }
858
860
 
859
861
  const
860
- {resolution, screen} = renderer,
861
- frame = new Rectangle(0, 0, screen.width, screen.height),
862
- extractOptions = {
863
- target: stage,
864
- frame,
865
- resolution
862
+ width = Math.max(1, renderer.screen.width | 0),
863
+ height = Math.max(1, renderer.screen.height | 0),
864
+ resolution = renderer.resolution || 1,
865
+ backgroundColor = this.options?.display?.backgroundColor,
866
+ hasBackground = typeof backgroundColor === 'number' && backgroundColor >= 0,
867
+ // Opaque clear — transparent extracts read as a black shot in Notefully.
868
+ clearColor = hasBackground ? backgroundColor : 0x000000,
869
+ mime = format === 'jpg' || format === 'jpeg'
870
+ ? 'image/jpeg'
871
+ : format === 'webp'
872
+ ? 'image/webp'
873
+ : 'image/png',
874
+ toOutput = (canvas) => {
875
+ if (as === 'canvas') {
876
+ return canvas;
877
+ }
878
+
879
+ return typeof quality === 'number'
880
+ ? canvas.toDataURL(mime, quality)
881
+ : canvas.toDataURL(mime);
866
882
  };
867
883
 
868
884
  try {
869
- if (as === 'canvas') {
870
- return renderer.extract.canvas(extractOptions);
871
- }
872
-
873
- return await renderer.extract.base64({
874
- ...extractOptions,
875
- format,
876
- quality
877
- });
885
+ // Screen-sized framed extract (viewport only).
886
+ return toOutput(renderer.extract.canvas({
887
+ target: stage,
888
+ frame: new Rectangle(0, 0, width, height),
889
+ resolution,
890
+ clearColor
891
+ }));
878
892
  } catch (err) {
879
- platypus.debug.warn('Game.captureViewport failed.', err);
893
+ platypus.debug.warn('Game.captureViewport framed extract failed; trying bounds crop.', err);
894
+ }
880
895
 
881
- // Fallback: canvas buffer after the render above (viewport-sized).
882
- try {
883
- if (as === 'canvas') {
884
- return this.canvas;
885
- }
896
+ // Paco ScreenShooter fallback: full extract, then crop the screen origin.
897
+ try {
898
+ const
899
+ bounds = stage.getBounds(),
900
+ full = renderer.extract.canvas(stage),
901
+ dest = document.createElement('canvas'),
902
+ ctx = dest.getContext('2d');
886
903
 
887
- const mime = format === 'jpg' || format === 'jpeg'
888
- ? 'image/jpeg'
889
- : format === 'webp'
890
- ? 'image/webp'
891
- : 'image/png';
904
+ dest.width = width;
905
+ dest.height = height;
892
906
 
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;
907
+ if (hasBackground) {
908
+ ctx.fillStyle = `#${backgroundColor.toString(16).padStart(6, '0')}`;
909
+ ctx.fillRect(0, 0, width, height);
899
910
  }
911
+
912
+ ctx.drawImage(
913
+ full,
914
+ -bounds.x,
915
+ -bounds.y,
916
+ width,
917
+ height,
918
+ 0,
919
+ 0,
920
+ width,
921
+ height
922
+ );
923
+
924
+ return toOutput(dest);
925
+ } catch (err) {
926
+ platypus.debug.warn('Game.captureViewport failed.', err);
927
+ return null;
900
928
  }
901
929
  }
902
930