# Copies of a box

> useSpawn(boxFromDoc): a reusable box, as the editor saves one, made again and again while the game runs.

Example `box-from-doc`, running at https://nacatamalon.com/en/examples/box-from-doc. The whole catalogue: https://nacatamalon.com/llms/examples.md.

A reusable box (a `.box` file, as the editor saves one) made again and again while the game runs, with `useSpawn(boxFromDoc)`. Each copy is built as a scene builds its boxes: its sprites, its children and its behaviours, which run on every copy, and ids of its own.

## Code

`index.ts`:

```ts
import { registerFall } from './scripts/fall';
import { createGame } from 'nacatamalon';
import { WIDTH, HEIGHT } from './settings';
import { Level } from './scenes/demo';

registerFall();

const game = createGame('#app', {
    width: WIDTH,
    height: HEIGHT,
    background: '#101820'
});

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

`components/coinrain.ts`:

```ts
import { useSpawn, useTimer } from 'nacatamalon';
import { boxFromDoc, parseSceneDoc } from 'nacatamalon/files';
import * as Settings from '../settings';
import { useRandom } from 'nacatamalon/math';
import { COIN_BOX } from '../data/coin';

export const CoinRain = () => {
    const random = useRandom();
    const coin = parseSceneDoc(COIN_BOX, 'boxes/Coin.box');

    // useSpawn hands boxFromDoc what it needs to build a box while the game runs: where it goes
    // (the scene, not this body) and the moment it is called. Each copy gets ids of its own.
    const spawn = useSpawn(boxFromDoc, {
        parent: 'scene'
    });

    useTimer().every(Settings.INTERVAL, () => spawn(coin, {
        x: 20 + random.rand(Settings.WIDTH - 40),
        y: -10
    }));
};
```

`data/coin.ts`:

```ts
export const COIN_BOX = {
    format: 'nacatamalon-scene',
    version: 1,
    name: 'Coin',
    assets: [],
    root: {
        id: 'root',
        name: 'Coin',
        transform: null,
        components: [],
        children: [
            {
                id: 'coin',
                name: 'Coin',
                transform: {
                    x: 0,
                    y: 0
                },
                components: [
                    {
                        type: 'sprite',
                        id: 'art',
                        texture: null,
                        tint: {
                            r: 1,
                            g: 0.8,
                            b: 0.2,
                            a: 1
                        },
                        width: 10,
                        height: 10
                    },
                    {
                        type: 'script',
                        id: 'fall',
                        ref: 'fall',
                        props: {
                            speed: 90
                        }
                    },
                ],
                children: [
                    {
                        id: 'shine',
                        name: 'Shine',
                        transform: {
                            x: -2,
                            y: -2
                        },
                        children: [],
                        components: [
                            {
                                type: 'sprite',
                                id: 'shine-art',
                                texture: null,
                                tint: {
                                    r: 1,
                                    g: 1,
                                    b: 1,
                                    a: 1
                                },
                                width: 3,
                                height: 3
                            }
                        ],
                    }
                ],
            }
        ],
    },
};
```

`scenes/demo.ts`:

```ts
import { createScene, useSpawn } from 'nacatamalon';

import { CoinRain } from '../components/coinrain';

export const Level = () => {
    useSpawn(CoinRain)();

    return createScene();
};
```

`scripts/fall.ts`:

```ts
import { destroy, registerScript, useGame, useUpdate } from 'nacatamalon';

export const registerFall = () => {
    registerScript<{ speed: number }>('fall', (self, props) => {
        const game = useGame();

        useUpdate((delta) => {
            if (self.transform === null) {
                return;
            }

            self.transform.y += props.speed * delta;
            self.transform.rotation += 3 * delta;

            if (self.transform.y > game.getHeight() + 10) {
                destroy(self);
            }
        });
    }, [
        {
            key: 'speed',
            label: 'Falls (px a second)',
            type: 'number',
            default: 60
        }
    ]);
};
```

`settings.ts`:

```ts
export const WIDTH = 480;
export const HEIGHT = 320;
export const INTERVAL = 0.15;
```
