@jacekpietal/oneforall v6.2.1
One For All
TypeScript gamedev library inspired by Unity
Demo
[1x Scene]
├──[1x HTML Canvas]
├──[1x Collision Detection]
└──[50x GameObject (Player)]
├──[1x CircleBody]
└──[1x Animator]
└──[1x StateMachine]
Tiny code, big results! Check out the demo to see below code in action.
Also, here is the documentation.
Demo Code
src/demo/index.ts
async function start(): Promise<void> {
const queryParams = Scene.getQueryParams();
// create main Scene
const scene: Scene = new Scene({
visible: true,
autoSort: true,
showFPS: 'fps' in queryParams,
debug: 'debug' in queryParams
});
// initialize scene async - new since pixi 7/8
await scene.init({
resizeTo: window,
autoDensity: true,
autoStart: false,
sharedTicker: false
});
// wait to load cave-boy.json and cave-boy.png, uses PIXI.Loader inside
const data = await Resources.loadResource('./cave-boy.json');
const texture = await Resources.loadResource(data.tileset);
// create 50 sprites from template
Array.from({ length: Number(queryParams.limit || 50) }, () => {
createSprite({ scene, data, texture });
});
scene.start();
scene.update$.pipe(takeUntil(scene.destroy$)).subscribe(() => {
scene.physics.separate();
});
}
start();
src/demo/sprite.prefab.ts
export function createSprite({ scene, data, texture }): TGameObject {
// create game object
const gameObject = new GameObject('Player') as TGameObject;
// create body
gameObject.body = new CircleBody(gameObject, 20, 14);
gameObject.body.setPosition(
Math.random() * innerWidth,
Math.random() * innerHeight
);
// insert body to physics and game object to scene
scene.physics.insert(gameObject.body);
scene.addChild(gameObject);
// create animator with few animations from json + texture
gameObject.sprite = new Animator(gameObject, data, texture);
gameObject.sprite.setState('idle');
// subscribe to *own* update function until *own* destroy
gameObject.update$
.pipe(takeUntil(gameObject.destroy$))
.subscribe((deltaTime) => {
updateSprite(gameObject, deltaTime);
});
return gameObject;
}
export function updateSprite(gameObject: TGameObject, deltaTime: number): void {
const scale = gameObject.scene.stage.scale;
const gameObjects = gameObject.scene.children as TGameObject[];
const safeDelta = Math.min(60, deltaTime);
const chance = safeDelta * 0.01;
if (Math.random() < chance) {
// goto random place
gameObject.target = {
x: (Math.random() * innerWidth) / scale.x,
y: (Math.random() * innerHeight) / scale.y
};
} else if (Math.random() < chance) {
// goto random target
gameObject.target =
gameObjects[Math.floor(Math.random() * gameObjects.length)];
} else if (Math.random() < chance) {
// stop
gameObject.target = null;
}
if (gameObject.target && distance(gameObject.target, gameObject) < 9) {
gameObject.target = null;
}
if (!gameObject.target) {
gameObject.sprite.setState('idle');
} else {
gameObject.sprite.setState('run');
const angle: number = Math.atan2(
gameObject.target.y - gameObject.y,
gameObject.target.x - gameObject.x
);
if (!isNaN(angle)) {
const offsetX: number = Math.cos(angle);
const offsetY: number = Math.sin(angle);
if (gameObject.sprite instanceof Animator) {
const flipX: number =
Math.sign(offsetX || gameObject.sprite.scale.x) *
Math.abs(gameObject.sprite.scale.x);
// flip x so there is no need to duplicate sprites
gameObject.sprite.setScale(flipX, gameObject.sprite.scale.y);
}
// update body which updates parent game object
gameObject.body.setPosition(
gameObject.body.x + safeDelta * offsetX,
gameObject.body.y + safeDelta * offsetY
);
}
}
}
Features
- Unity-inspired architecture
- State management
- Reactive events
- Lifecycle cleanup management
- Collision detection
- Drawing on WebGL canvas
Classes this library exports
- Resources: Handles loading game assets like images and JSON files.
- Scene: Sets the stage for gameplay, where all the action takes place.
- GameObject: Represents characters, objects, or items in the game world.
- Prefab: Instantiates ready-made templates for creating game elements.
- Sprite: Displays static 2D graphics in the game.
- Container: Organizes and manages groups of game objects for easier handling.
- Animator: Useful JSON to Container with AnimatedSprite children.
- StateMachine: Controls how game objects transition between actions.
- CircleBody: Adds physics properties and interactions for round-shaped objects.
- PolygonBody: Adds physics properties and interactions for polygonal objects.
- TextureAtlas: Allows easy slicing of texture into smaller cached slices.
Installation
npm i @jacekpietal/oneforall --save
We also have tests
PASS src/state-machine.spec.ts
GIVEN StateMachine
✓ THEN you can set validators (4 ms)
✓ THEN you can't change state to invalid state
✓ THEN you can change state to valid state
PASS src/component.spec.ts
GIVEN Component
✓ THEN update publishes update$ (1 ms)
✓ THEN destroy publishes destroy$
PASS src/circle-body.spec.ts
GIVEN CircleBody
✓ THEN it has set property radius (5 ms)
✓ THEN it can't have zero radius (9 ms)
✓ THEN update propagates x/y changes
PASS src/scene-base.spec.ts
GIVEN SceneBase
✓ THEN it works (3 ms)
✓ THEN it can have children (1 ms)
✓ THEN scene propagates update to gameobject to component (1 ms)
PASS src/scene.spec.ts
GIVEN Scene
✓ THEN it works (2 ms)
✓ THEN it can have children
✓ THEN scene propagates update to gameobject to component (1 ms)
PASS src/sprite.spec.ts
GIVEN Sprite
✓ THEN update propagates x/y changes (3 ms)
✓ THEN removeChild works
✓ THEN destroy works (1 ms)
✓ THEN destroy works extended (1 ms)
PASS src/prefab.spec.ts
GIVEN Prefab
✓ THEN can be instantiated (3 ms)
✓ THEN can create 100 instances (10 ms)
PASS src/game-object.spec.ts
GIVEN GameObject
✓ THEN you can add component (5 ms)
✓ THEN update propagates to components (1 ms)
✓ THEN you can remove component
✓ THEN destroy removes component (1 ms)
✓ THEN you can get component by label
✓ THEN you can get components by label
✓ THEN you can destroy 1000 bodies without problem (106 ms)
PASS src/polygon-body.spec.ts
GIVEN PolygonBody
✓ THEN update propagates x/y changes
PASS src/container.spec.ts
GIVEN Container
✓ THEN update propagates x/y changes
✓ THEN destroy works (1 ms)
PASS src/resources.spec.ts
GIVEN Resources
✓ THEN it silently fails and proceeds (5 ms)
PASS src/index.spec.ts
GIVEN index.ts
✓ THEN basic imports work (1 ms)
PASS src/application.spec.ts
GIVEN Application
✓ THEN it works
Test Suites: 13 passed, 13 total
Tests: 33 passed, 33 total
15 days ago
15 days ago
15 days ago
15 days ago
15 days ago
16 days ago
16 days ago
17 days ago
17 days ago
17 days ago
17 days ago
17 days ago
17 days ago
20 days ago
21 days ago
20 days ago
20 days ago
20 days ago
20 days ago
20 days ago
20 days ago
20 days ago
20 days ago
20 days ago
20 days ago
20 days ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
12 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago