contra-renderer/www/js/moves/balance.ts

106 lines
4.6 KiB
TypeScript

import { BalanceWeight, Facing, HandConnection, HandTo, PositionKind, facingAdjacent, facingRequireAdjacent } from "../interpreterCommon.js";
import { SemanticAnimationKind } from "../lowLevelMove.js";
import { Hand } from "../rendererConstants.js";
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, Variant, VariantCollection, moveInterpreters } from "./_moveInterpreter.js";
const moveName = "balance";
class BalanceSingleVariant extends SingleVariantMoveInterpreter<Balance, typeof moveName> {
private static readonly balanceOptions : [BalanceWeight, BalanceWeight | undefined, Hand | undefined][]= [
// TODO Any others?
[BalanceWeight.Forward, undefined, undefined],
[BalanceWeight.Forward, BalanceWeight.Backward, undefined],
// TODO Should be left/right/inside/outside hands?
[BalanceWeight.Forward, BalanceWeight.Backward, Hand.Left],
[BalanceWeight.Forward, BalanceWeight.Backward, Hand.Right],
[BalanceWeight.Right, BalanceWeight.Backward, undefined],
[BalanceWeight.Right, BalanceWeight.Left, undefined],
[BalanceWeight.Left, BalanceWeight.Right, undefined],
];
moveAsVariants(previousMoveVariant: string): VariantCollection {
const res = new Map<string, Variant>();
for (const [firstWeight, secondWeight, hand] of BalanceSingleVariant.balanceOptions) {
// If balancing someone, need to know by which hand.
if ((hand === undefined) !== (this.move.parameters.who === "everyone")) continue;
try {
res.set((firstWeight?.toString() ?? "") + (secondWeight?.toString() ?? "") + (hand === undefined ? "" : hand.toString() + "Hand"), {
lowLevelMoves: this.moveAsLowLevelMovesWeights(firstWeight, secondWeight, hand),
previousMoveVariant
});
}
catch { }
}
return res;
}
moveAsLowLevelMovesWeights(firstWeight?: BalanceWeight, secondWeight?: BalanceWeight, hand?: Hand): LowLevelMovesForAllDancers {
if (this.move.parameters.who !== "everyone") {
return this.handlePairedMove(this.move.parameters.who, ({ startPos, withPos }) => {
// TODO Does this need to support balancing inside/outside hands? If so how to identify them?
const hands = hand === undefined ? startPos.hands : new Map<Hand, HandConnection>([[hand, {hand, to: HandTo.DancerForward}]]);
const facing = facingRequireAdjacent(startPos, withPos, this.move.move);
const startingPos = {...startPos, facing, hands};
return this.combine([
{
beats: this.moveInterpreter.balancePartBeats,
endPosition: { ...startingPos, balance: firstWeight, hands },
movementPattern: { kind: SemanticAnimationKind.Linear },
},
{
beats: this.moveInterpreter.balancePartBeats,
endPosition: { ...startingPos, balance: secondWeight, hands },
movementPattern: { kind: SemanticAnimationKind.Linear },
},
], startingPos);
});
} else {
return this.handleMove(({ startPos }) => {
// TODO Use who to determine facing?
// TODO Could be left to right, not back and forth?
// TODO How to determine hand... by next move, I guess?
if (startPos.kind === PositionKind.Circle && startPos.facing === Facing.CenterOfCircle) {
if (firstWeight === BalanceWeight.Left || firstWeight === BalanceWeight.Right || firstWeight === BalanceWeight.Backward
|| secondWeight === BalanceWeight.Left || secondWeight === BalanceWeight.Right || secondWeight === BalanceWeight.Backward) {
throw new Error("Balancing left or right in a circle is unsupported.");
}
}
return this.combine([
{
beats: this.moveInterpreter.balancePartBeats,
endPosition: { ...startPos, balance: firstWeight },
movementPattern: { kind: SemanticAnimationKind.Linear },
},
{
beats: this.moveInterpreter.balancePartBeats,
endPosition: { ...startPos, balance: secondWeight },
movementPattern: { kind: SemanticAnimationKind.Linear },
},
], startPos);
});
}
}
}
class Balance extends MoveInterpreter<typeof moveName> {
public readonly balancePartBeats: number;
constructor(args: MoveInterpreterCtorArgs<typeof moveName>) {
super(args);
this.balancePartBeats = this.move.beats / 2;
}
buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter {
return new BalanceSingleVariant(this, startingPos);
}
}
moveInterpreters.set(moveName, Balance);