@unboxy/phaser-sdk 0.2.0

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.
@@ -0,0 +1,20 @@
1
+ import Phaser from 'phaser';
2
+ export interface UnboxyGameOptions {
3
+ /** Game width in pixels */
4
+ width: number;
5
+ /** Game height in pixels */
6
+ height: number;
7
+ /** Phaser scene classes to register */
8
+ scenes: (new (...args: any[]) => Phaser.Scene)[];
9
+ /** Background color (default: '#1a1a2e') */
10
+ backgroundColor?: string;
11
+ /** Enable pixel art rendering (default: false) */
12
+ pixelArt?: boolean;
13
+ /** Custom physics config (default: arcade with no gravity) */
14
+ physics?: Phaser.Types.Core.PhysicsConfig;
15
+ }
16
+ /**
17
+ * Create an Unboxy-enhanced Phaser game instance.
18
+ * Includes built-in integrations: screenshot capture, preserveDrawingBuffer, etc.
19
+ */
20
+ export declare function createUnboxyGame(options: UnboxyGameOptions): Phaser.Game;
@@ -0,0 +1,33 @@
1
+ import Phaser from 'phaser';
2
+ import { setupScreenshotListener } from '../screenshot/ScreenshotManager.js';
3
+ import { setupRecordingListener } from '../recording/RecordingManager.js';
4
+ /**
5
+ * Create an Unboxy-enhanced Phaser game instance.
6
+ * Includes built-in integrations: screenshot capture, preserveDrawingBuffer, etc.
7
+ */
8
+ export function createUnboxyGame(options) {
9
+ const config = {
10
+ type: Phaser.AUTO,
11
+ backgroundColor: options.backgroundColor ?? '#1a1a2e',
12
+ scale: {
13
+ mode: Phaser.Scale.FIT,
14
+ autoCenter: Phaser.Scale.CENTER_BOTH,
15
+ width: options.width,
16
+ height: options.height,
17
+ },
18
+ render: {
19
+ preserveDrawingBuffer: true,
20
+ },
21
+ pixelArt: options.pixelArt ?? false,
22
+ physics: options.physics ?? {
23
+ default: 'arcade',
24
+ arcade: { gravity: { x: 0, y: 0 }, debug: false },
25
+ },
26
+ scene: options.scenes,
27
+ };
28
+ const game = new Phaser.Game(config);
29
+ // Built-in integrations
30
+ setupScreenshotListener(game);
31
+ setupRecordingListener(game);
32
+ return game;
33
+ }
@@ -0,0 +1,19 @@
1
+ import Phaser from 'phaser';
2
+ /**
3
+ * Base scene class with common Unboxy utilities.
4
+ * Extend this instead of Phaser.Scene for built-in helpers.
5
+ */
6
+ export declare class UnboxyScene extends Phaser.Scene {
7
+ /**
8
+ * Create a simple text button with hover effects.
9
+ */
10
+ protected createButton(x: number, y: number, text: string, style?: Phaser.Types.GameObjects.Text.TextStyle, onClick?: () => void): Phaser.GameObjects.Text;
11
+ /**
12
+ * Shake the camera briefly (e.g., on damage).
13
+ */
14
+ protected shakeCamera(duration?: number, intensity?: number): void;
15
+ /**
16
+ * Flash the camera briefly (e.g., on hit).
17
+ */
18
+ protected flashCamera(duration?: number, r?: number, g?: number, b?: number): void;
19
+ }
@@ -0,0 +1,38 @@
1
+ import Phaser from 'phaser';
2
+ /**
3
+ * Base scene class with common Unboxy utilities.
4
+ * Extend this instead of Phaser.Scene for built-in helpers.
5
+ */
6
+ export class UnboxyScene extends Phaser.Scene {
7
+ /**
8
+ * Create a simple text button with hover effects.
9
+ */
10
+ createButton(x, y, text, style, onClick) {
11
+ const btn = this.add.text(x, y, text, {
12
+ fontSize: '20px',
13
+ color: '#ffffff',
14
+ backgroundColor: '#4662D8',
15
+ padding: { x: 16, y: 8 },
16
+ ...style,
17
+ })
18
+ .setOrigin(0.5)
19
+ .setInteractive({ useHandCursor: true });
20
+ btn.on('pointerover', () => btn.setAlpha(0.8));
21
+ btn.on('pointerout', () => btn.setAlpha(1));
22
+ if (onClick)
23
+ btn.on('pointerdown', onClick);
24
+ return btn;
25
+ }
26
+ /**
27
+ * Shake the camera briefly (e.g., on damage).
28
+ */
29
+ shakeCamera(duration = 100, intensity = 0.01) {
30
+ this.cameras.main.shake(duration, intensity);
31
+ }
32
+ /**
33
+ * Flash the camera briefly (e.g., on hit).
34
+ */
35
+ flashCamera(duration = 100, r = 255, g = 255, b = 255) {
36
+ this.cameras.main.flash(duration, r, g, b);
37
+ }
38
+ }
@@ -0,0 +1,5 @@
1
+ export { createUnboxyGame } from './core/UnboxyGame.js';
2
+ export type { UnboxyGameOptions } from './core/UnboxyGame.js';
3
+ export { UnboxyScene } from './core/UnboxyScene.js';
4
+ export { setupScreenshotListener, takeScreenshot } from './screenshot/ScreenshotManager.js';
5
+ export { setupRecordingListener } from './recording/RecordingManager.js';
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ // Core
2
+ export { createUnboxyGame } from './core/UnboxyGame.js';
3
+ export { UnboxyScene } from './core/UnboxyScene.js';
4
+ // Screenshot
5
+ export { setupScreenshotListener, takeScreenshot } from './screenshot/ScreenshotManager.js';
6
+ // Recording
7
+ export { setupRecordingListener } from './recording/RecordingManager.js';
@@ -0,0 +1,11 @@
1
+ import Phaser from 'phaser';
2
+ /**
3
+ * Sets up postMessage listeners for video recording of the game canvas.
4
+ *
5
+ * Parent sends: 'startRecording'
6
+ * Game responds: { type: 'recordingStarted' }
7
+ *
8
+ * Parent sends: 'stopRecording'
9
+ * Game responds: { type: 'recordingComplete', data: string (base64 data URL), mimeType: string }
10
+ */
11
+ export declare function setupRecordingListener(game: Phaser.Game): void;
@@ -0,0 +1,59 @@
1
+ let mediaRecorder = null;
2
+ let recordedChunks = [];
3
+ /**
4
+ * Sets up postMessage listeners for video recording of the game canvas.
5
+ *
6
+ * Parent sends: 'startRecording'
7
+ * Game responds: { type: 'recordingStarted' }
8
+ *
9
+ * Parent sends: 'stopRecording'
10
+ * Game responds: { type: 'recordingComplete', data: string (base64 data URL), mimeType: string }
11
+ */
12
+ export function setupRecordingListener(game) {
13
+ window.addEventListener('message', (event) => {
14
+ if (event.data === 'startRecording') {
15
+ try {
16
+ const canvas = game.canvas;
17
+ if (!canvas)
18
+ return;
19
+ recordedChunks = [];
20
+ const stream = canvas.captureStream(30);
21
+ // Pick best available codec
22
+ const mimeType = MediaRecorder.isTypeSupported('video/webm;codecs=vp9')
23
+ ? 'video/webm;codecs=vp9'
24
+ : 'video/webm';
25
+ mediaRecorder = new MediaRecorder(stream, {
26
+ mimeType,
27
+ videoBitsPerSecond: 1500000, // 1.5 Mbps
28
+ });
29
+ mediaRecorder.ondataavailable = (e) => {
30
+ if (e.data.size > 0)
31
+ recordedChunks.push(e.data);
32
+ };
33
+ mediaRecorder.onstop = () => {
34
+ const blob = new Blob(recordedChunks, { type: 'video/webm' });
35
+ const reader = new FileReader();
36
+ reader.onloadend = () => {
37
+ window.parent.postMessage({
38
+ type: 'recordingComplete',
39
+ data: reader.result,
40
+ mimeType: 'video/webm',
41
+ }, '*');
42
+ };
43
+ reader.readAsDataURL(blob);
44
+ };
45
+ mediaRecorder.start(1000); // collect data every 1 second
46
+ window.parent.postMessage({ type: 'recordingStarted' }, '*');
47
+ }
48
+ catch (e) {
49
+ console.error('[UnboxySDK] Recording failed to start:', e);
50
+ window.parent.postMessage({ type: 'recordingError', error: String(e) }, '*');
51
+ }
52
+ }
53
+ if (event.data === 'stopRecording') {
54
+ if (mediaRecorder && mediaRecorder.state !== 'inactive') {
55
+ mediaRecorder.stop();
56
+ }
57
+ }
58
+ });
59
+ }
@@ -0,0 +1,14 @@
1
+ import Phaser from 'phaser';
2
+ /**
3
+ * Sets up a postMessage listener that captures the game canvas
4
+ * when the parent window requests a screenshot.
5
+ *
6
+ * Parent sends: { type: 'screenshot' }
7
+ * Game responds: { type: 'screenshot_result', dataUrl: string }
8
+ */
9
+ export declare function setupScreenshotListener(game: Phaser.Game): void;
10
+ /**
11
+ * Take a screenshot programmatically (e.g., from within a scene).
12
+ * Returns a base64 data URL of the current canvas.
13
+ */
14
+ export declare function takeScreenshot(game: Phaser.Game): string | null;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Sets up a postMessage listener that captures the game canvas
3
+ * when the parent window requests a screenshot.
4
+ *
5
+ * Parent sends: { type: 'screenshot' }
6
+ * Game responds: { type: 'screenshot_result', dataUrl: string }
7
+ */
8
+ export function setupScreenshotListener(game) {
9
+ window.addEventListener('message', (event) => {
10
+ if (event.data?.type === 'screenshot') {
11
+ try {
12
+ const dataUrl = game.canvas.toDataURL('image/png');
13
+ window.parent.postMessage({ type: 'screenshot_result', dataUrl }, '*');
14
+ }
15
+ catch (e) {
16
+ console.error('[UnboxySDK] Screenshot failed:', e);
17
+ }
18
+ }
19
+ });
20
+ }
21
+ /**
22
+ * Take a screenshot programmatically (e.g., from within a scene).
23
+ * Returns a base64 data URL of the current canvas.
24
+ */
25
+ export function takeScreenshot(game) {
26
+ try {
27
+ return game.canvas.toDataURL('image/png');
28
+ }
29
+ catch (e) {
30
+ console.error('[UnboxySDK] Screenshot failed:', e);
31
+ return null;
32
+ }
33
+ }
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@unboxy/phaser-sdk",
3
+ "version": "0.2.0",
4
+ "description": "Unboxy Phaser 3 SDK — game infrastructure for the Unboxy platform",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": ["dist"],
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "prepublishOnly": "npm run build"
11
+ },
12
+ "peerDependencies": {
13
+ "phaser": "^3.60.0"
14
+ },
15
+ "devDependencies": {
16
+ "phaser": "^3.80.0",
17
+ "typescript": "^5.5.0"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "license": "UNLICENSED",
23
+ "private": false
24
+ }