@thewhateverapp/tile-sdk 0.14.3 → 0.14.5
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/dist/scene/SceneFromJson.d.ts +8 -1
- package/dist/scene/SceneFromJson.d.ts.map +1 -1
- package/dist/scene/SceneFromJson.js +12 -3
- package/dist/scene/SceneRenderer.d.ts.map +1 -1
- package/dist/scene/SceneRenderer.js +13 -3
- package/dist/scene/physics/PhysicsEngine.js +2 -2
- package/package.json +1 -1
|
@@ -8,6 +8,13 @@ export interface SceneFromJsonProps extends Omit<SceneRendererProps, 'spec'> {
|
|
|
8
8
|
json: unknown;
|
|
9
9
|
/** Show validation errors in UI instead of throwing */
|
|
10
10
|
showErrors?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Container sizing mode:
|
|
13
|
+
* - 'tile': Fills parent container (w-full h-full) - default
|
|
14
|
+
* - 'page': Fills viewport (w-full h-screen)
|
|
15
|
+
* - 'none': No container wrapper (you manage sizing)
|
|
16
|
+
*/
|
|
17
|
+
container?: 'tile' | 'page' | 'none';
|
|
11
18
|
}
|
|
12
19
|
/**
|
|
13
20
|
* SceneFromJson - Renders a scene from a JSON object with validation
|
|
@@ -23,5 +30,5 @@ export interface SceneFromJsonProps extends Omit<SceneRendererProps, 'spec'> {
|
|
|
23
30
|
* }
|
|
24
31
|
* ```
|
|
25
32
|
*/
|
|
26
|
-
export declare function SceneFromJson({ json, showErrors, onEvent, ...props }: SceneFromJsonProps): React.JSX.Element;
|
|
33
|
+
export declare function SceneFromJson({ json, showErrors, onEvent, container, ...props }: SceneFromJsonProps): React.JSX.Element;
|
|
27
34
|
//# sourceMappingURL=SceneFromJson.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneFromJson.d.ts","sourceRoot":"","sources":["../../src/scene/SceneFromJson.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAC1E,4DAA4D;IAC5D,IAAI,EAAE,OAAO,CAAC;IACd,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SceneFromJson.d.ts","sourceRoot":"","sources":["../../src/scene/SceneFromJson.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC;IAC1E,4DAA4D;IAC5D,IAAI,EAAE,OAAO,CAAC;IACd,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CACtC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,UAAiB,EACjB,OAAO,EACP,SAAkB,EAClB,GAAG,KAAK,EACT,EAAE,kBAAkB,qBAiFpB"}
|
|
@@ -16,7 +16,14 @@ import { SceneRenderer } from './SceneRenderer.js';
|
|
|
16
16
|
* }
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
-
export function SceneFromJson({ json, showErrors = true, onEvent, ...props }) {
|
|
19
|
+
export function SceneFromJson({ json, showErrors = true, onEvent, container = 'tile', ...props }) {
|
|
20
|
+
// Container styles based on mode
|
|
21
|
+
const containerStyle = container === 'none'
|
|
22
|
+
? undefined
|
|
23
|
+
: {
|
|
24
|
+
width: '100%',
|
|
25
|
+
height: container === 'page' ? '100vh' : '100%',
|
|
26
|
+
};
|
|
20
27
|
// Validate the JSON
|
|
21
28
|
const validationResult = React.useMemo(() => {
|
|
22
29
|
try {
|
|
@@ -45,7 +52,7 @@ export function SceneFromJson({ json, showErrors = true, onEvent, ...props }) {
|
|
|
45
52
|
// Show errors if validation failed
|
|
46
53
|
if (!validationResult.valid) {
|
|
47
54
|
if (showErrors) {
|
|
48
|
-
|
|
55
|
+
const errorContent = (React.createElement("div", { style: {
|
|
49
56
|
width: '100%',
|
|
50
57
|
height: '100%',
|
|
51
58
|
backgroundColor: '#1a0a0a',
|
|
@@ -62,6 +69,7 @@ export function SceneFromJson({ json, showErrors = true, onEvent, ...props }) {
|
|
|
62
69
|
":"),
|
|
63
70
|
" ",
|
|
64
71
|
error.message)))));
|
|
72
|
+
return containerStyle ? React.createElement("div", { style: containerStyle }, errorContent) : errorContent;
|
|
65
73
|
}
|
|
66
74
|
// Throw if not showing errors
|
|
67
75
|
throw new Error(`Scene validation failed: ${validationResult.errors.map((e) => e.message).join(', ')}`);
|
|
@@ -70,5 +78,6 @@ export function SceneFromJson({ json, showErrors = true, onEvent, ...props }) {
|
|
|
70
78
|
if (validationResult.warnings.length > 0) {
|
|
71
79
|
console.warn('Scene validation warnings:', validationResult.warnings);
|
|
72
80
|
}
|
|
73
|
-
|
|
81
|
+
const sceneContent = (React.createElement(SceneRenderer, { spec: json, onEvent: onEvent, ...props }));
|
|
82
|
+
return containerStyle ? React.createElement("div", { style: containerStyle }, sceneContent) : sceneContent;
|
|
74
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneRenderer.d.ts","sourceRoot":"","sources":["../../src/scene/SceneRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4D,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SceneRenderer.d.ts","sourceRoot":"","sources":["../../src/scene/SceneRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAEjF,OAAO,KAAK,EAAE,WAAW,EAAU,MAAM,2BAA2B,CAAC;AAqDrE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,IAAI,EAAE,WAAW,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,kCAAkC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EAAE,SAAS,EACf,OAAO,EACP,MAAc,EACd,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,EACnB,KAAa,GACd,EAAE,kBAAkB,qBA0CpB;AAiPD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import React, { useEffect, useRef, useCallback, useMemo, useState } from 'react';
|
|
3
|
+
import Matter from 'matter-js';
|
|
3
4
|
import { compileScene } from '@thewhateverapp/scene-sdk';
|
|
4
5
|
import { PixiGame, useGameLoop, Container } from '../pixi/index.js';
|
|
5
6
|
import { SceneContext, createEntityState, createPlayerState, createCameraState, createInputState, createTimelineState, } from './SceneContext.js';
|
|
@@ -10,6 +11,7 @@ import { useComponentRunner } from './components/ComponentRunner.js';
|
|
|
10
11
|
import { useTimelineExecutor } from './timeline/TimelineExecutor.js';
|
|
11
12
|
import { useCameraController } from './camera/CameraController.js';
|
|
12
13
|
import { TILE_WIDTH, TILE_HEIGHT } from '../react/PixiGame.js';
|
|
14
|
+
const { Body } = Matter;
|
|
13
15
|
/**
|
|
14
16
|
* Hook to track container size using ResizeObserver
|
|
15
17
|
*/
|
|
@@ -132,16 +134,24 @@ function SceneContent({ spec, onEvent, paused, width, height, debug, }) {
|
|
|
132
134
|
// Find player entity and reset position
|
|
133
135
|
for (const [, state] of entitiesRef.current) {
|
|
134
136
|
if (state.entity.tags?.includes('player')) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
const respawnX = player.checkpointX ?? state.entity.transform.x;
|
|
138
|
+
const respawnY = player.checkpointY ?? state.entity.transform.y;
|
|
139
|
+
state.x = respawnX;
|
|
140
|
+
state.y = respawnY;
|
|
137
141
|
state.velocityX = 0;
|
|
138
142
|
state.velocityY = 0;
|
|
139
143
|
state.rotation = 0;
|
|
144
|
+
// Update physics body if it exists
|
|
145
|
+
if (state.body) {
|
|
146
|
+
Body.setPosition(state.body, { x: respawnX, y: respawnY });
|
|
147
|
+
Body.setVelocity(state.body, { x: 0, y: 0 });
|
|
148
|
+
Body.setAngle(state.body, 0);
|
|
149
|
+
}
|
|
140
150
|
break;
|
|
141
151
|
}
|
|
142
152
|
}
|
|
143
153
|
emitEvent('player.respawn', { x: player.checkpointX, y: player.checkpointY });
|
|
144
|
-
}, [
|
|
154
|
+
}, [emitEvent]);
|
|
145
155
|
// Build context value
|
|
146
156
|
const contextValue = useMemo(() => ({
|
|
147
157
|
spec,
|
|
@@ -137,8 +137,8 @@ export function usePhysicsEngine(context, width, height) {
|
|
|
137
137
|
// Simple ground check - if velocity.y is very small and we're not in the air
|
|
138
138
|
playerState.grounded = Math.abs(body.velocity.y) < 0.5;
|
|
139
139
|
}
|
|
140
|
-
// Check for death (fell off screen)
|
|
141
|
-
if (playerEntity && playerEntity.y > height +
|
|
140
|
+
// Check for death (fell off screen) - only if height is valid
|
|
141
|
+
if (playerEntity && height > 0 && playerEntity.y > height + 200) {
|
|
142
142
|
if (!playerState.dead) {
|
|
143
143
|
playerState.dead = true;
|
|
144
144
|
playerState.deaths++;
|