Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 85 additions & 39 deletions demo/src/animationDemo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,47 @@ import {
Axis2dAction,
buttonMoments,
createAnimation,
FlipComponent,
createResetInputsEcsSystem,
createSpriteAnimationEcsSystem,
createUpdateInputEcsSystem,
flipId,
Game,
InputManager,
inputsId,
KeyboardAxis1dBinding,
KeyboardAxis2dBinding,
KeyboardInputSource,
KeyboardTriggerBinding,
keyCodes,
MouseAxis2dBinding,
MouseInputSource,
PositionComponent,
registerInputs,
ScaleComponent,
positionId,
scaleId,
Sprite,
SpriteAnimationComponent,
SpriteComponent,
spriteAnimationId,
spriteId,
Time,
TriggerAction,
Vector2,
World,
} from '../../src';
import { EcsWorld } from '../../src/new-ecs';
import { FiniteStateMachine } from '../../src/finite-state-machine/finite-state-machine';
import { Transition } from '../../src/finite-state-machine/transition';
import { ADVENTURER_ANIMATIONS, SHIP_ANIMATIONS } from './animationEnums';
import { ControlAdventurerComponent } from './control-adventurer-component';
import { controlAdventurerId } from './control-adventurer-component';

export function setupAnimationsDemo(
world: World,
world: EcsWorld,
game: Game,
time: Time,
shipSprite: Sprite,
adventurerSprite: Sprite,
): ReturnType<typeof setupInputs> {
const inputs = setupInputs(world, game, time);

// Add animation system
world.addSystem(createSpriteAnimationEcsSystem(time));

const ShipController = createShipAnimationController();
buildShipEntities(world, shipSprite, ShipController);

Expand All @@ -58,7 +65,7 @@ export function setupAnimationsDemo(
return inputs;
}

function setupInputs(world: World, game: Game, time: Time) {
function setupInputs(world: EcsWorld, game: Game, time: Time) {
const gameInputGroup = 'game';

const attackInput = new TriggerAction('attack', gameInputGroup);
Expand All @@ -78,22 +85,28 @@ function setupInputs(world: World, game: Game, time: Time) {
actionResetTypes.noReset,
);

const { inputsManager } = registerInputs(world, time, {
triggerActions: [
attackInput,
runRInput,
runLInput,
jumpInput,
takeDamageInput,
],
axis2dActions: [axis2dInput],
axis1dActions: [axis1dInput],
});
// Create input manager and register actions
const inputsManager = new InputManager(gameInputGroup);
inputsManager.addTriggerActions(
attackInput,
runRInput,
runLInput,
jumpInput,
takeDamageInput,
);
inputsManager.addAxis2dActions(axis2dInput);
inputsManager.addAxis1dActions(axis1dInput);

// Create an entity with inputs component
const inputEntity = world.createEntity();
world.addComponent(inputEntity, inputsId, { inputManager: inputsManager });

inputsManager.setActiveGroup(gameInputGroup);
// Add input systems
world.addSystem(createUpdateInputEcsSystem(time));
world.addSystem(createResetInputsEcsSystem());

const keyboardInputSource = new KeyboardInputSource(inputsManager);
const mouseInputSource = new MouseInputSource(inputsManager, game);
const mouseInputSource = new MouseInputSource(inputsManager, game.container);

keyboardInputSource.axis2dBindings.add(
new KeyboardAxis2dBinding(
Expand Down Expand Up @@ -234,32 +247,65 @@ function createAdventurerControllableInputs() {
}

function buildShipEntities(
world: World,
world: EcsWorld,
shipSprite: Sprite,
stateMachine: FiniteStateMachine<AnimationInputs, AnimationClip>,
) {
const animationInputs = new AnimationInputs();

world.buildAndAddEntity([
new PositionComponent(-500, -150),
new SpriteComponent(shipSprite),
new ScaleComponent(0.5, 0.5),
new SpriteAnimationComponent(stateMachine, animationInputs),
]);
const entity = world.createEntity();
world.addComponent(entity, positionId, {
local: new Vector2(-500, -150),
world: new Vector2(-500, -150),
});
world.addComponent(entity, spriteId, {
sprite: shipSprite,
enabled: true,
});
world.addComponent(entity, scaleId, {
local: new Vector2(0.5, 0.5),
world: new Vector2(0.5, 0.5),
});
world.addComponent(entity, spriteAnimationId, {
animationFrameIndex: 0,
playbackSpeed: 1,
frameDurationMilliseconds: 33.3333,
lastFrameChangeTimeInSeconds: 0,
animationInputs,
stateMachine,
});
}

function buildAdventurerControllableEntities(
world: World,
world: EcsWorld,
adventurerSprite: Sprite,
stateMachine: FiniteStateMachine<AnimationInputs, AnimationClip>,
animationInputs: AnimationInputs,
) {
world.buildAndAddEntity([
new PositionComponent(400, 0),
new SpriteComponent(adventurerSprite),
new ScaleComponent(0.3, 0.6),
new SpriteAnimationComponent(stateMachine, animationInputs, 33.3333, 0.3),
new ControlAdventurerComponent(),
new FlipComponent(),
]);
const entity = world.createEntity();
world.addComponent(entity, positionId, {
local: new Vector2(400, 0),
world: new Vector2(400, 0),
});
world.addComponent(entity, spriteId, {
sprite: adventurerSprite,
enabled: true,
});
world.addComponent(entity, scaleId, {
local: new Vector2(0.3, 0.6),
world: new Vector2(0.3, 0.6),
});
world.addComponent(entity, spriteAnimationId, {
animationFrameIndex: 0,
playbackSpeed: 0.3,
frameDurationMilliseconds: 33.3333,
lastFrameChangeTimeInSeconds: 0,
animationInputs,
stateMachine,
});
world.addTag(entity, controlAdventurerId);
world.addComponent(entity, flipId, {
flipX: false,
flipY: false,
});
}
4 changes: 2 additions & 2 deletions demo/src/control-adventurer-component.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { Component } from '../../src';
import { createTagId } from '../../src/new-ecs/ecs-component';

export class ControlAdventurerComponent extends Component {}
export const controlAdventurerId = createTagId('control-adventurer');
79 changes: 28 additions & 51 deletions demo/src/control-adventurer-system.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,46 @@
import {
Entity,
FlipComponent,
PositionComponent,
SpriteAnimationComponent,
System,
FlipEcsComponent,
flipId,
PositionEcsComponent,
positionId,
SpriteAnimationEcsComponent,
spriteAnimationId,
TriggerAction,
} from '../../src';
import { ControlAdventurerComponent } from './control-adventurer-component';

export class ControlAdventurerSystem extends System {
private readonly _attackTriggerInput: TriggerAction;
private readonly _runRTriggerInput: TriggerAction;
private readonly _runLTriggerInput: TriggerAction;
private readonly _jumpTriggerInput: TriggerAction;
private readonly _takeDamageTriggerInput: TriggerAction;

constructor(
attackTriggerInput: TriggerAction,
runRTriggerInput: TriggerAction,
runLTriggerInput: TriggerAction,
jumpTriggerInput: TriggerAction,
takeDamageTriggerInput: TriggerAction,
) {
super(
[
ControlAdventurerComponent,
SpriteAnimationComponent,
FlipComponent,
PositionComponent,
],
'ControlAdventurerSystem',
);

this._attackTriggerInput = attackTriggerInput;
this._runRTriggerInput = runRTriggerInput;
this._runLTriggerInput = runLTriggerInput;
this._jumpTriggerInput = jumpTriggerInput;
this._takeDamageTriggerInput = takeDamageTriggerInput;
}

public run(entity: Entity): void {
const spriteAnimationComponent = entity.getComponentRequired(
SpriteAnimationComponent,
);

const flipComponent = entity.getComponentRequired(FlipComponent);
import { EcsSystem } from '../../src/new-ecs';
import { controlAdventurerId } from './control-adventurer-component';

export const createControlAdventurerEcsSystem = (
attackTriggerInput: TriggerAction,
runRTriggerInput: TriggerAction,
runLTriggerInput: TriggerAction,
jumpTriggerInput: TriggerAction,
takeDamageTriggerInput: TriggerAction,
): EcsSystem<
[SpriteAnimationEcsComponent, FlipEcsComponent, PositionEcsComponent]
> => ({
query: [controlAdventurerId, spriteAnimationId, flipId, positionId],
run: (result) => {
const [spriteAnimationComponent, flipComponent] = result.components;

const animationInputs = spriteAnimationComponent.animationInputs;

if (this._jumpTriggerInput.isTriggered) {
if (jumpTriggerInput.isTriggered) {
console.log('Jumping!');

animationInputs.setTrigger('jump');

return;
}

if (this._runLTriggerInput.isTriggered) {
if (runLTriggerInput.isTriggered) {
animationInputs.setToggle('run', true);
flipComponent.flipX = true;

return;
}

if (this._runRTriggerInput.isTriggered) {
if (runRTriggerInput.isTriggered) {
animationInputs.setToggle('run', true);
flipComponent.flipX = false;

Expand All @@ -72,13 +49,13 @@ export class ControlAdventurerSystem extends System {

animationInputs.setToggle('run', false);

if (this._attackTriggerInput.isTriggered) {
if (attackTriggerInput.isTriggered) {
animationInputs.setText('attack', 'attack is being set');

return;
}

if (this._takeDamageTriggerInput.isTriggered) {
if (takeDamageTriggerInput.isTriggered) {
const health = animationInputs.getNumber('health');

if (!health) {
Expand All @@ -87,5 +64,5 @@ export class ControlAdventurerSystem extends System {

health.value = Math.max(0, health.value - 50);
}
}
}
},
});
29 changes: 12 additions & 17 deletions demo/src/fire-system.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
import { HoldAction, InputsComponent, System, TriggerAction } from '../../src';
import { HoldAction, InputsEcsComponent, inputsId, TriggerAction } from '../../src';
import { EcsSystem } from '../../src/new-ecs';

export class FireSystem extends System {
private readonly _fireAction: TriggerAction;
private readonly _runAction: HoldAction;

constructor(fireAction: TriggerAction, runAction: HoldAction) {
super([InputsComponent], 'FireSystem');

this._fireAction = fireAction;
this._runAction = runAction;
}

public run(): void {
if (this._fireAction.isTriggered) {
export const createFireEcsSystem = (
fireAction: TriggerAction,
runAction: HoldAction,
): EcsSystem<[InputsEcsComponent]> => ({
query: [inputsId],
run: () => {
if (fireAction.isTriggered) {
console.log(`Fire action triggered`);
}

if (this._runAction.isHeld) {
if (runAction.isHeld) {
console.log(`Run action is being held`);
}
}
}
},
});
20 changes: 17 additions & 3 deletions demo/src/game.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {
cameraId,
createCameraEcsSystem,
createGame,
createImageSprite,
createRenderEcsSystem,
positionId,
Random,
Rect,
registerCamera,
spriteId,
Vector2,
} from '../../src';
Expand All @@ -20,9 +21,21 @@ enum RenderLayer {

const { game, world, renderContext, time } = createGame('demo-container');

registerCamera(world, time, {
scissorRect: new Rect(Vector2.zero, new Vector2(0.5, 1)),
// Create camera entity
const cameraEntity = world.createEntity();
world.addComponent(cameraEntity, positionId, {
world: Vector2.zero,
local: Vector2.zero,
});
world.addComponent(cameraEntity, cameraId, {
zoom: 1,
zoomSensitivity: 0.1,
panSensitivity: 1,
minZoom: 0.1,
maxZoom: 10,
isStatic: false,
layerMask: RenderLayer.default | RenderLayer.foreground,
scissorRect: new Rect(Vector2.zero, new Vector2(0.5, 1)),
});

const planetSprite = await createImageSprite(
Expand Down Expand Up @@ -86,6 +99,7 @@ setInterval(() => {
}, 1000);

world.addSystem(createMoveEcsSystem(time));
world.addSystem(createCameraEcsSystem(time));
world.addSystem(createRenderEcsSystem(renderContext));

game.run();