cubeforge 0.0.5 → 0.0.7
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/components/Animation.d.ts +3 -1
- package/dist/components/BoxCollider.d.ts +8 -1
- package/dist/components/Camera2D.d.ts +4 -1
- package/dist/components/Checkpoint.d.ts +1 -1
- package/dist/components/CircleCollider.d.ts +11 -0
- package/dist/components/DevTools.d.ts +15 -0
- package/dist/components/Game.d.ts +16 -2
- package/dist/components/RigidBody.d.ts +5 -1
- package/dist/context.d.ts +5 -2
- package/dist/hooks/useCamera.d.ts +37 -0
- package/dist/hooks/useContact.d.ts +57 -0
- package/dist/hooks/useInputMap.d.ts +25 -0
- package/dist/hooks/useSnapshot.d.ts +42 -0
- package/dist/index.d.ts +16 -3
- package/dist/index.js +1105 -191
- package/package.json +1 -1
|
@@ -7,6 +7,8 @@ interface AnimationProps {
|
|
|
7
7
|
loop?: boolean;
|
|
8
8
|
/** Whether currently playing, default true */
|
|
9
9
|
playing?: boolean;
|
|
10
|
+
/** Called once when a non-looping animation finishes playing */
|
|
11
|
+
onComplete?: () => void;
|
|
10
12
|
}
|
|
11
|
-
export declare function Animation({ frames, fps, loop, playing }: AnimationProps): null;
|
|
13
|
+
export declare function Animation({ frames, fps, loop, playing, onComplete }: AnimationProps): null;
|
|
12
14
|
export {};
|
|
@@ -5,6 +5,13 @@ interface BoxColliderProps {
|
|
|
5
5
|
offsetY?: number;
|
|
6
6
|
isTrigger?: boolean;
|
|
7
7
|
layer?: string;
|
|
8
|
+
/** Which layers this collider interacts with. '*' = all (default). */
|
|
9
|
+
mask?: string | string[];
|
|
10
|
+
/**
|
|
11
|
+
* One-way platform: only blocks entities falling onto the top surface.
|
|
12
|
+
* Entities below pass through freely (useful for jump-through ledges).
|
|
13
|
+
*/
|
|
14
|
+
oneWay?: boolean;
|
|
8
15
|
}
|
|
9
|
-
export declare function BoxCollider({ width, height, offsetX, offsetY, isTrigger, layer, }: BoxColliderProps): null;
|
|
16
|
+
export declare function BoxCollider({ width, height, offsetX, offsetY, isTrigger, layer, mask, oneWay, }: BoxColliderProps): null;
|
|
10
17
|
export {};
|
|
@@ -15,6 +15,9 @@ interface Camera2DProps {
|
|
|
15
15
|
w: number;
|
|
16
16
|
h: number;
|
|
17
17
|
};
|
|
18
|
+
/** World-space offset applied to the follow target (look-ahead, vertical bias, etc.) */
|
|
19
|
+
followOffsetX?: number;
|
|
20
|
+
followOffsetY?: number;
|
|
18
21
|
}
|
|
19
|
-
export declare function Camera2D({ followEntity, zoom, smoothing, background, bounds, deadZone, }: Camera2DProps): null;
|
|
22
|
+
export declare function Camera2D({ followEntity, zoom, smoothing, background, bounds, deadZone, followOffsetX, followOffsetY, }: Camera2DProps): null;
|
|
20
23
|
export {};
|
|
@@ -9,7 +9,7 @@ interface CheckpointProps {
|
|
|
9
9
|
onActivate?: () => void;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* A trigger zone that fires `onActivate` when
|
|
12
|
+
* A trigger zone that fires `onActivate` once when a player-tagged entity enters it.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* <Checkpoint x={800} y={450} onActivate={() => setCheckpoint(800)} />
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface CircleColliderProps {
|
|
2
|
+
radius: number;
|
|
3
|
+
offsetX?: number;
|
|
4
|
+
offsetY?: number;
|
|
5
|
+
isTrigger?: boolean;
|
|
6
|
+
layer?: string;
|
|
7
|
+
/** Which layers this collider interacts with. '*' = all (default). */
|
|
8
|
+
mask?: string | string[];
|
|
9
|
+
}
|
|
10
|
+
export declare function CircleCollider({ radius, offsetX, offsetY, isTrigger, layer, mask, }: CircleColliderProps): null;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { WorldSnapshot } from '@cubeforge/core';
|
|
3
|
+
import type { ECSWorld, GameLoop } from '@cubeforge/core';
|
|
4
|
+
export declare const MAX_DEVTOOLS_FRAMES = 600;
|
|
5
|
+
export interface DevToolsHandle {
|
|
6
|
+
buffer: WorldSnapshot[];
|
|
7
|
+
onFrame?: () => void;
|
|
8
|
+
}
|
|
9
|
+
interface DevToolsProps {
|
|
10
|
+
handle: DevToolsHandle;
|
|
11
|
+
loop: GameLoop;
|
|
12
|
+
ecs: ECSWorld;
|
|
13
|
+
}
|
|
14
|
+
export declare function DevToolsOverlay({ handle, loop, ecs }: DevToolsProps): React.ReactPortal;
|
|
15
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { type CSSProperties } from 'react';
|
|
2
|
-
import { type Plugin } from '@cubeforge/core';
|
|
2
|
+
import { type Plugin, type System, type EntityId } from '@cubeforge/core';
|
|
3
3
|
export interface GameControls {
|
|
4
4
|
pause(): void;
|
|
5
5
|
resume(): void;
|
|
@@ -21,11 +21,25 @@ interface GameProps {
|
|
|
21
21
|
scale?: 'none' | 'contain' | 'pixel';
|
|
22
22
|
/** Called once the engine is ready — receives pause/resume/reset controls */
|
|
23
23
|
onReady?: (controls: GameControls) => void;
|
|
24
|
+
/** Enable time-travel debugging overlay (frame scrubber + entity inspector). */
|
|
25
|
+
devtools?: boolean;
|
|
26
|
+
/** Run the simulation in deterministic mode using a seeded RNG. */
|
|
27
|
+
deterministic?: boolean;
|
|
28
|
+
/** Seed for the deterministic RNG (default 0). Only used when deterministic=true. */
|
|
29
|
+
seed?: number;
|
|
24
30
|
/** Custom plugins to register after core systems. Each plugin's systems run after Render. */
|
|
25
31
|
plugins?: Plugin[];
|
|
32
|
+
/**
|
|
33
|
+
* Custom render system constructor. Must implement the System interface and accept
|
|
34
|
+
* `(canvas: HTMLCanvasElement, entityIds: Map<string, EntityId>)`.
|
|
35
|
+
*
|
|
36
|
+
* Defaults to the built-in Canvas2D RenderSystem.
|
|
37
|
+
* Example: `import { WebGLRenderSystem } from '@cubeforge/webgl-renderer'`
|
|
38
|
+
*/
|
|
39
|
+
renderer?: new (canvas: HTMLCanvasElement, entityIds: Map<string, EntityId>) => System;
|
|
26
40
|
style?: CSSProperties;
|
|
27
41
|
className?: string;
|
|
28
42
|
children?: React.ReactNode;
|
|
29
43
|
}
|
|
30
|
-
export declare function Game({ width, height, gravity, debug, scale, onReady, plugins, style, className, children, }: GameProps): import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
export declare function Game({ width, height, gravity, debug, devtools, scale, deterministic, seed, onReady, plugins, renderer: CustomRenderer, style, className, children, }: GameProps): import("react/jsx-runtime").JSX.Element;
|
|
31
45
|
export {};
|
|
@@ -6,6 +6,10 @@ interface RigidBodyProps {
|
|
|
6
6
|
friction?: number;
|
|
7
7
|
vx?: number;
|
|
8
8
|
vy?: number;
|
|
9
|
+
/** Prevent any horizontal movement — velocity.x is zeroed every frame */
|
|
10
|
+
lockX?: boolean;
|
|
11
|
+
/** Prevent any vertical movement — velocity.y is zeroed every frame (disables gravity) */
|
|
12
|
+
lockY?: boolean;
|
|
9
13
|
}
|
|
10
|
-
export declare function RigidBody({ mass, gravityScale, isStatic, bounce, friction, vx, vy, }: RigidBodyProps): null;
|
|
14
|
+
export declare function RigidBody({ mass, gravityScale, isStatic, bounce, friction, vx, vy, lockX, lockY, }: RigidBodyProps): null;
|
|
11
15
|
export {};
|
package/dist/context.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { ECSWorld, EventBus, AssetManager, EntityId } from '@cubeforge/core';
|
|
2
2
|
import type { InputManager } from '@cubeforge/input';
|
|
3
|
-
import type { Canvas2DRenderer } from '@cubeforge/renderer';
|
|
3
|
+
import type { Canvas2DRenderer, RenderSystem } from '@cubeforge/renderer';
|
|
4
4
|
import type { PhysicsSystem } from '@cubeforge/physics';
|
|
5
5
|
import type { GameLoop } from '@cubeforge/core';
|
|
6
6
|
export interface EngineState {
|
|
7
7
|
ecs: ECSWorld;
|
|
8
8
|
input: InputManager;
|
|
9
|
-
renderer
|
|
9
|
+
/** Canvas2D renderer. Undefined when a custom WebGL renderer is used via the `renderer` Game prop. */
|
|
10
|
+
renderer?: Canvas2DRenderer;
|
|
11
|
+
/** The active render system. Undefined when a custom renderer is used. */
|
|
12
|
+
renderSystem?: RenderSystem;
|
|
10
13
|
physics: PhysicsSystem;
|
|
11
14
|
events: EventBus;
|
|
12
15
|
assets: AssetManager;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface CameraControls {
|
|
2
|
+
/**
|
|
3
|
+
* Trigger a screen-shake effect.
|
|
4
|
+
* @param intensity - Maximum pixel displacement per frame.
|
|
5
|
+
* @param duration - How long the shake lasts in seconds.
|
|
6
|
+
*/
|
|
7
|
+
shake(intensity: number, duration: number): void;
|
|
8
|
+
/**
|
|
9
|
+
* Set the world-space offset applied to the camera's follow target.
|
|
10
|
+
* Useful for look-ahead: `setFollowOffset(facing * 80, 0)`.
|
|
11
|
+
*/
|
|
12
|
+
setFollowOffset(x: number, y: number): void;
|
|
13
|
+
/**
|
|
14
|
+
* Instantly move the camera center to a world-space position.
|
|
15
|
+
* Bypasses smoothing — useful for instant scene cuts.
|
|
16
|
+
*/
|
|
17
|
+
setPosition(x: number, y: number): void;
|
|
18
|
+
/**
|
|
19
|
+
* Programmatically set the camera zoom level.
|
|
20
|
+
*/
|
|
21
|
+
setZoom(zoom: number): void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Returns controls for the active Camera2D in the scene.
|
|
25
|
+
* Must be used inside `<Game>`.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* function HUD() {
|
|
30
|
+
* const camera = useCamera()
|
|
31
|
+
* return (
|
|
32
|
+
* <button onClick={() => camera.shake(8, 0.4)}>Shake!</button>
|
|
33
|
+
* )
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function useCamera(): CameraControls;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { EntityId } from '@cubeforge/core';
|
|
2
|
+
interface ContactOpts {
|
|
3
|
+
/** Only fire if the other entity has this tag */
|
|
4
|
+
tag?: string;
|
|
5
|
+
/** Only fire if the other entity's BoxCollider is on this layer */
|
|
6
|
+
layer?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fires once when another entity's collider first overlaps this entity's trigger.
|
|
10
|
+
* Must be used inside an `<Entity>`.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* function CoinPickup() {
|
|
14
|
+
* useTriggerEnter((other) => collectCoin(), { tag: 'player' })
|
|
15
|
+
* return null
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
export declare function useTriggerEnter(handler: (other: EntityId) => void, opts?: ContactOpts): void;
|
|
19
|
+
/**
|
|
20
|
+
* Fires once when an overlapping entity's collider leaves this entity's trigger.
|
|
21
|
+
* Must be used inside an `<Entity>`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useTriggerExit(handler: (other: EntityId) => void, opts?: ContactOpts): void;
|
|
24
|
+
/**
|
|
25
|
+
* Fires once on the first frame two solid dynamic bodies touch.
|
|
26
|
+
* Must be used inside an `<Entity>`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* function Enemy() {
|
|
30
|
+
* useCollisionEnter((other) => takeDamage(), { tag: 'player' })
|
|
31
|
+
* return null
|
|
32
|
+
* }
|
|
33
|
+
*/
|
|
34
|
+
export declare function useCollisionEnter(handler: (other: EntityId) => void, opts?: ContactOpts): void;
|
|
35
|
+
/**
|
|
36
|
+
* Fires once when two solid dynamic bodies separate.
|
|
37
|
+
* Must be used inside an `<Entity>`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function useCollisionExit(handler: (other: EntityId) => void, opts?: ContactOpts): void;
|
|
40
|
+
/**
|
|
41
|
+
* Fires once when another entity's CircleCollider first overlaps this entity's CircleCollider.
|
|
42
|
+
* Also fires when a CircleCollider overlaps a BoxCollider.
|
|
43
|
+
* Must be used inside an `<Entity>`.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* function Asteroid() {
|
|
47
|
+
* useCircleEnter((other) => onHit(other), { tag: 'bullet' })
|
|
48
|
+
* return null
|
|
49
|
+
* }
|
|
50
|
+
*/
|
|
51
|
+
export declare function useCircleEnter(handler: (other: EntityId) => void, opts?: ContactOpts): void;
|
|
52
|
+
/**
|
|
53
|
+
* Fires once when two CircleCollider entities stop overlapping.
|
|
54
|
+
* Must be used inside an `<Entity>`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function useCircleExit(handler: (other: EntityId) => void, opts?: ContactOpts): void;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ActionBindings } from '@cubeforge/input';
|
|
2
|
+
export interface BoundInputMap {
|
|
3
|
+
/** True every frame any bound key is held. */
|
|
4
|
+
isActionDown(action: string): boolean;
|
|
5
|
+
/** True only on the first frame any bound key was pressed. */
|
|
6
|
+
isActionPressed(action: string): boolean;
|
|
7
|
+
/** True only on the frame any bound key was released. */
|
|
8
|
+
isActionReleased(action: string): boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* React hook that returns a pre-bound action map for use inside `<Game>`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* function MyScript() {
|
|
16
|
+
* const actions = useInputMap({
|
|
17
|
+
* left: ['ArrowLeft', 'KeyA'],
|
|
18
|
+
* right: ['ArrowRight', 'KeyD'],
|
|
19
|
+
* jump: ['Space', 'ArrowUp', 'KeyW'],
|
|
20
|
+
* })
|
|
21
|
+
* // use actions.isActionDown('left') in a Script update or game loop callback
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function useInputMap(bindings: ActionBindings): BoundInputMap;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { WorldSnapshot } from '@cubeforge/core';
|
|
2
|
+
export interface SnapshotControls {
|
|
3
|
+
/**
|
|
4
|
+
* Capture a full serialisable snapshot of all ECS entity/component data.
|
|
5
|
+
* Safe to JSON-stringify and store externally (localStorage, server, etc.)
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const { save, restore } = useSnapshot()
|
|
10
|
+
* const checkpoint = save() // capture at checkpoint
|
|
11
|
+
* restore(checkpoint) // reset to that state
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
save(): WorldSnapshot;
|
|
15
|
+
/**
|
|
16
|
+
* Restore the world to a previously captured snapshot.
|
|
17
|
+
* All current entities are replaced with the snapshot's entities.
|
|
18
|
+
*
|
|
19
|
+
* Note: React component state is NOT rolled back — only ECS data is restored.
|
|
20
|
+
* For a full game reset, prefer remounting the `<Game>` key instead.
|
|
21
|
+
*/
|
|
22
|
+
restore(snapshot: WorldSnapshot): void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns save/restore controls for the ECS world snapshot system.
|
|
26
|
+
* Must be used inside `<Game>`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* function SaveButton() {
|
|
31
|
+
* const { save, restore } = useSnapshot()
|
|
32
|
+
* const [slot, setSlot] = useState<WorldSnapshot | null>(null)
|
|
33
|
+
* return (
|
|
34
|
+
* <>
|
|
35
|
+
* <button onClick={() => setSlot(save())}>Save</button>
|
|
36
|
+
* <button onClick={() => slot && restore(slot)}>Load</button>
|
|
37
|
+
* </>
|
|
38
|
+
* )
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function useSnapshot(): SnapshotControls;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { Transform } from './components/Transform';
|
|
|
5
5
|
export { Sprite } from './components/Sprite';
|
|
6
6
|
export { RigidBody } from './components/RigidBody';
|
|
7
7
|
export { BoxCollider } from './components/BoxCollider';
|
|
8
|
+
export { CircleCollider } from './components/CircleCollider';
|
|
8
9
|
export { Script } from './components/Script';
|
|
9
10
|
export { Camera2D } from './components/Camera2D';
|
|
10
11
|
export { Animation } from './components/Animation';
|
|
@@ -18,23 +19,35 @@ export { ScreenFlash } from './components/ScreenFlash';
|
|
|
18
19
|
export type { ScreenFlashHandle } from './components/ScreenFlash';
|
|
19
20
|
export type { TiledObject, TiledLayer } from './components/Tilemap';
|
|
20
21
|
export { useGame } from './hooks/useGame';
|
|
22
|
+
export { useCamera } from './hooks/useCamera';
|
|
23
|
+
export type { CameraControls } from './hooks/useCamera';
|
|
24
|
+
export { useSnapshot } from './hooks/useSnapshot';
|
|
25
|
+
export type { SnapshotControls } from './hooks/useSnapshot';
|
|
21
26
|
export { useEntity } from './hooks/useEntity';
|
|
22
27
|
export { useInput } from './hooks/useInput';
|
|
28
|
+
export { useInputMap } from './hooks/useInputMap';
|
|
23
29
|
export { useEvents, useEvent } from './hooks/useEvents';
|
|
24
30
|
export { usePlatformerController } from './hooks/usePlatformerController';
|
|
25
31
|
export { useTopDownMovement } from './hooks/useTopDownMovement';
|
|
32
|
+
export { useTriggerEnter, useTriggerExit, useCollisionEnter, useCollisionExit, useCircleEnter, useCircleExit } from './hooks/useContact';
|
|
26
33
|
export type { SpriteAtlas } from './components/spriteAtlas';
|
|
27
34
|
export { createAtlas } from './components/spriteAtlas';
|
|
28
35
|
export type { EngineState } from './context';
|
|
29
36
|
export type { GameControls } from './components/Game';
|
|
37
|
+
export type { DevToolsHandle } from './components/DevTools';
|
|
30
38
|
export type { PlatformerControllerOptions } from './hooks/usePlatformerController';
|
|
31
39
|
export type { TopDownMovementOptions } from './hooks/useTopDownMovement';
|
|
32
|
-
export type { EntityId, ECSWorld, ScriptUpdateFn, Plugin } from '@cubeforge/core';
|
|
33
|
-
export { definePlugin } from '@cubeforge/core';
|
|
34
|
-
export
|
|
40
|
+
export type { EntityId, ECSWorld, ScriptUpdateFn, Plugin, WorldSnapshot } from '@cubeforge/core';
|
|
41
|
+
export { definePlugin, findByTag } from '@cubeforge/core';
|
|
42
|
+
export { overlapBox, raycast } from '@cubeforge/physics';
|
|
43
|
+
export type { RaycastHit } from '@cubeforge/physics';
|
|
44
|
+
export type { InputManager, ActionBindings, InputMap } from '@cubeforge/input';
|
|
45
|
+
export { createInputMap } from '@cubeforge/input';
|
|
46
|
+
export type { BoundInputMap } from './hooks/useInputMap';
|
|
35
47
|
export type { TransformComponent } from '@cubeforge/core';
|
|
36
48
|
export type { RigidBodyComponent } from '@cubeforge/physics';
|
|
37
49
|
export type { BoxColliderComponent } from '@cubeforge/physics';
|
|
50
|
+
export type { CircleColliderComponent } from '@cubeforge/physics';
|
|
38
51
|
export type { SpriteComponent } from '@cubeforge/renderer';
|
|
39
52
|
export type { AnimationStateComponent } from '@cubeforge/renderer';
|
|
40
53
|
export type { SquashStretchComponent } from '@cubeforge/renderer';
|