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

106 lines
4.4 KiB
TypeScript

import { PositionKind, SemanticPosition, Facing, BalanceWeight, handsInLine, CircleSide, handsInLongLines } from "../interpreterCommon.js";
import { SemanticAnimationKind } from "../lowLevelMove.js";
import { Hand } from "../rendererConstants.js";
import { ISingleVariantMoveInterpreter, LowLevelMovesForAllDancers, MoveInterpreter, MoveInterpreterCtorArgs, PartialLowLevelMove, SemanticPositionsForAllDancers, SingleVariantMoveInterpreter, moveInterpreters } from "./_moveInterpreter.js";
const moveName = "Rory O'More";
class RoryOMoreSingleVariant extends SingleVariantMoveInterpreter<RoryOMore, typeof moveName> {
moveAsLowLevelMoves(): LowLevelMovesForAllDancers {
// TODO Could be in long or short lines.
return this.handleMove(({ startPos }) => {
const startingPos: SemanticPosition = {
...startPos,
hands: handsInLine({ wavy: true, which: startPos.which, facing: startPos.facing })
};
let endPos: SemanticPosition;
if (startPos.kind === PositionKind.ShortLines) {
if (startPos.facing !== Facing.Up && startPos.facing !== Facing.Down) {
throw new Error("To be in short wavy lines, must be facing up or down, not " + startPos.facing);
}
const { newPos: endWhich, wrap } = startPos.which.shiftWithWrap(this.moveInterpreter.dir, startPos.facing);
const endLineOffset = !wrap
? startPos.lineOffset
: (startPos.lineOffset ?? 0) + wrap;
if (wrap) {
startingPos.hands = handsInLongLines(true)
}
endPos = {
...startPos,
which: endWhich,
hands: handsInLine({ wavy: true, which: endWhich, facing: startPos.facing }),
lineOffset: endLineOffset,
};
} else {
if (startPos.facing !== Facing.Left && startPos.facing !== Facing.Right) {
throw new Error("To be in long wavy lines, must be facing left or right, not " + startPos.facing);
}
const endWhich = startPos.which.swapUpAndDown();
const sideTowards = (startPos.facing === Facing.Right)
=== (this.moveInterpreter.dir === Hand.Left)
? CircleSide.Bottom
: CircleSide.Top;
const endSetOffset = sideTowards === endWhich.topBottomSide()
? startPos.setOffset
: (startPos.setOffset ?? 0) + (sideTowards === CircleSide.Bottom ? +1 : -1);
endPos = {
...startPos,
which: endWhich,
hands: handsInLine({ wavy: true, which: endWhich, facing: startPos.facing }),
setOffset: endSetOffset,
};
}
const maybeBalance: PartialLowLevelMove[] = (this.move.parameters.bal ? [
{
beats: this.moveInterpreter.balPartBeats,
endPosition: { ...startingPos, balance: this.moveInterpreter.dir === Hand.Left ? BalanceWeight.Left : BalanceWeight.Right },
movementPattern: { kind: SemanticAnimationKind.Linear },
},
{
beats: this.moveInterpreter.balPartBeats,
endPosition: { ...startingPos, balance: this.moveInterpreter.dir === Hand.Left ? BalanceWeight.Right : BalanceWeight.Left },
movementPattern: { kind: SemanticAnimationKind.Linear },
},
] : []);
return this.combine([...maybeBalance,
{
beats: this.moveInterpreter.roryBeats,
endPosition: endPos,
movementPattern: {
kind: SemanticAnimationKind.Linear,
minRotation: this.moveInterpreter.dir === Hand.Right ? +360 : -360,
handsDuring: "None",
},
}
], startingPos);
});
}
}
class RoryOMore extends MoveInterpreter<typeof moveName> {
public readonly dir: Hand;
public readonly balPartBeats: number;
public readonly roryBeats: number;
constructor(args: MoveInterpreterCtorArgs<typeof moveName>) {
super(args);
if (this.move.parameters.who !== "everyone") {
throw new Error(this.move.move + " that doesn't include everyone is unsupported.");
}
this.dir = this.move.parameters.slide ? Hand.Left : Hand.Right;
const balBeats = this.move.parameters.bal ? this.move.beats / 2 : 0;
this.balPartBeats = balBeats / 2;
this.roryBeats = this.move.beats - balBeats;
}
buildSingleVariantMoveInterpreter(startingPos: SemanticPositionsForAllDancers): ISingleVariantMoveInterpreter {
return new RoryOMoreSingleVariant(this, startingPos);
}
}
moveInterpreters.set(moveName, RoryOMore);