# Glow maps: arcade

> Screens, marquees and buttons lit by the model’s glow map. Switch the room’s light off and they stay lit.

Example `glow-maps-arcade`, running at https://nacatamalon.com/en/examples/glow-maps-arcade. The whole catalogue: https://nacatamalon.com/llms/examples.md.

The screens, the marquees, the buttons and the coin slots light up from the model's glow map, and none of it is in the code. Click the preview, then press Space to switch the room's light on and off: the cabinets come and go, the glow does not.

The middle one wears `toonLighting()`. A look builds a shader of its own, and the glow map reaches it as `ctx.emissive`, so it keeps its screen like the other two.

## Code

`index.ts`:

```ts
import { createGame } from 'nacatamalon';

import { WIDTH, HEIGHT } from './settings';
import { Arcade } from './scenes/demo';

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

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

`components/cabinets.ts`:

```ts
import { createMaterial, createMesh, createModel, useLoadModel, usePlaneGeometry, useUpdate } from 'nacatamalon';
import { toonLighting } from 'nacatamalon/shader';

import * as Settings from '../settings';

export const Cabinets = () => {
    const cabinet = useLoadModel({
        src: Settings.MODEL
    });

    const cabinets = [
        createModel({
            model: cabinet,
            transform: {
                x: -1.25,
                rotationY: 0.35
            }
        }),
        createModel({
            model: cabinet,
            lighting: toonLighting({
                bands: 3,
                shadow: 0.2
            }),
            transform: {
                x: 0,
                z: -0.3
            }
        }),
        createModel({
            model: cabinet,
            transform: {
                x: 1.25,
                rotationY: -0.35
            }
        }),
    ];

    createMesh({
        geometry: usePlaneGeometry(),
        material: createMaterial({
            shader: 'mesh3d',
            tint: '#3a2f4a'
        }),
        transform: {
            scaleX: 12,
            scaleZ: 12
        },
    });

    useUpdate((_delta, time) => {
        cabinets[1].transform.rotationY = Math.sin(time * Settings.SWAY.speed) * Settings.SWAY.angle;
    });
};
```

`scenes/demo.ts`:

```ts
import { createScene, useCamera3d, useDirectionalLight, useKeyboard, useUpdate, useSpawn } from 'nacatamalon';

import { bloom, usePostProcess } from 'nacatamalon/effects';
import * as Settings from '../settings';

import { Cabinets } from '../components/cabinets';

export const Arcade = () => {
    useCamera3d(Settings.CAMERA);

    const room = useDirectionalLight({
        color: '#ffe9c4',
        intensity: 0.06,
        ambient: 0.02,
        transform: {
            rotationX: -0.5,
            rotationY: 0.4
        },
    });

    usePostProcess(bloom({
        threshold: 0.7,
        intensity: 1,
        radius: 5
    }));

    useSpawn(Cabinets)();

    const keys = useKeyboard();
    let lit = false;

    useUpdate(() => {
        if (keys.justPressed(' ')) {
            lit = !lit;
        }

        room.intensity = lit ? 1.1 : 0.06;
        room.ambient = lit ? 0.35 : 0.02;
    });

    return createScene();
};
```

`settings.ts`:

```ts
export const WIDTH = 560;
export const HEIGHT = 400;
import type { TCamera3dOptions } from 'nacatamalon';

export const CAMERA = {
    projection: 'perspective',
    fov: 45,
    transform: {
        y: 1.7,
        z: 5.6,
        rotationX: -0.1
    }
} satisfies TCamera3dOptions;
export const MODEL = '/example-assets/assets/3d/gltf/arcade/arcade.gltf';
export const SWAY = {
    speed: 0.6,
    angle: 0.5
};
```
