# Pivot

> pivot: the point a sprite turns and grows about, when it is not where it is anchored.

Example `sprite-pivot`, running at https://nacatamalon.com/en/examples/sprite-pivot. The whole catalogue: https://nacatamalon.com/llms/examples.md.

`anchor` says where a sprite sits; `pivot` says what it turns and grows about. Both are in 0-1 of its own size, and the pivot is the anchor unless it says otherwise. Unturned and ungrown, a sprite sits as its anchor says, whatever its pivot.

The two bikes are anchored under their back wheel, so they stand on the ground at the same point. Crashed, the one with no pivot turns about that wheel, through the floor; the one with `pivot: { x: 0.5, y: 0.5 }` somersaults about its middle and lands where it was. Texts and panels take a `pivot` too, and a box that turns its sprite turns it about the pivot.

Click the preview first so it hears the keyboard. Space crashes both.

## Code

`index.ts`:

```ts
import { createGame } from 'nacatamalon';
import { Garage } from './scenes/demo';
import { ACTIONS, WIDTH, HEIGHT } from './settings';

const game = createGame('#app', {
    width: WIDTH,
    height: HEIGHT,
    background: '#14121c',
    scaling: 'integer',
    actions: ACTIONS
});

// Declare Scenes
game({
    Garage
});
```

`components/bike.ts`:

```ts
import { createSprite, createText } from 'nacatamalon';
import { ANCHOR, BIKE, GROUND } from '../settings';

type TBikeProps = {
    x: number;
    tint: string;
    pivoted: boolean;
};

export const Bike = ({ x, tint, pivoted }: TBikeProps) => {
    const bike = createSprite({
        ...BIKE,
        tint,
        anchor: ANCHOR,
        ...(pivoted ? {
            pivot: {
                x: 0.5,
                y: 0.5
            }
        } : {
        }),
        transform: {
            x,
            y: GROUND
        }
    });

    // The white marker identifies the turning point without moving the sprite's anchor.
    createSprite({
        width: 4,
        height: 4,
        tint: '#ffffff',
        transform: {
            x: pivoted ? x + BIKE.width * (0.5 - ANCHOR.x) : x,
            y: pivoted ? GROUND - BIKE.height / 2 : GROUND
        }
    });
    createText({
        text: pivoted ? 'PIVOT' : 'ANCHOR',
        tint,
        anchor: {
            x: 0.5,
            y: 0
        },
        transform: {
            x: x + (pivoted ? 15 : 10),
            y: 156
        }
    });

    return bike;
};
```

`hooks/use_crash.ts`:

```ts
import { useAction, useUpdate } from 'nacatamalon';
import type { TSprite } from 'nacatamalon';
import { SPIN_SPEED } from '../settings';

export const useCrash = (plain: TSprite, pivoted: TSprite) => {
    const crash = useAction('crash');
    let remaining = 0;

    useUpdate((delta) => {
        if (crash.justPressed()) {
            remaining = Math.PI * 2;
        }

        const turn = Math.min(remaining, delta * SPIN_SPEED);

        remaining -= turn;
        plain.transform.rotation += turn;
        pivoted.transform.rotation += turn;
    });
};
```

`scenes/demo.ts`:

```ts
import { createScene, createSprite, createText, useSpawn } from 'nacatamalon';
import { Bike } from '../components/bike';
import { useCrash } from '../hooks/use_crash';
import { WIDTH, GROUND } from '../settings';

export const Garage = () => {
    createSprite({
        width: WIDTH,
        height: 40,
        tint: '#3b3346',
        anchor: {
            x: 0,
            y: 0
        },
        transform: {
            y: GROUND
        }
    });

    const spawnBike = useSpawn(Bike);

    const plain = spawnBike({
        x: 70,
        tint: '#ff6b1a',
        pivoted: false
    });

    const pivoted = spawnBike({
        x: 210,
        tint: '#58c4ff',
        pivoted: true
    });

    createText({
        text: 'SPACE: CRASH',
        tint: '#9a8fc7',
        transform: {
            x: 8,
            y: 8
        }
    });
    useCrash(plain.api, pivoted.api);

    return createScene();
};
```

`settings.ts`:

```ts
import type { TActionMap } from 'nacatamalon';

export const WIDTH = 320;
export const HEIGHT = 180;
export const GROUND = 140;
export const SPIN_SPEED = 8;

export const BIKE = {
    width: 48,
    height: 24
};

export const ANCHOR = {
    x: 0.2,
    y: 1
};

export const ACTIONS: TActionMap = [
    {
        name: 'crash',
        bindings: [
            {
                type: 'key',
                key: ' '
            },
            {
                type: 'button',
                button: 'a'
            }
        ]
    }
];
```
