# Polygons in pixels

> fillPolygon paints a filled polygon into a picture made in code: hills, a ramp, a roof.

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

`fillPolygon(pixels, points, color)` fills a polygon in a picture painted in code: a ramp, a slope of ground, a roof, a range of hills. A pixel is painted when its middle is inside the outline or on it, so the edge is stepped like pixel art, a ramp up and a ramp down are mirror images, and two polygons that share a side leave no gap between them.

The picture is shown as any other (`createPixelTexture`), and painted again whenever it changes, then sent with `updatePixelTexture`.

Click the preview first so it hears the keyboard. Space paints new hills.

## Code

`index.ts`:

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

const game = createGame('#app', {
    width: WIDTH,
    height: HEIGHT,
    background: '#ffd9a8',
    scaling: 'integer',
    seed: SEED
});

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

`art/landscape.ts`:

```ts
import { getColor } from 'nacatamalon';
import { fillPolygon, fillRect } from 'nacatamalon/pixels';
import type { TPixels } from 'nacatamalon/pixels';
import * as Settings from '../settings';

const hills = (rand: () => number, pixels: TPixels, base: number, rise: number, hex: string) => {
    const points = [
        {
            x: 0,
            y: Settings.HEIGHT
        }
    ];

    for (let x = 0; x <= Settings.WIDTH; x += 40) {
        points.push({
            x,
            y: base - rand() * rise
        });
    }

    points.push({
        x: Settings.WIDTH,
        y: Settings.HEIGHT
    });
    fillPolygon(pixels, points, getColor(hex));
};

export const paint = (pixels: TPixels, rand: () => number) => {
    fillRect(pixels, 0, 0, Settings.WIDTH, Settings.HEIGHT, '#ffd9a8');
    hills(rand, pixels, 110, 50, '#c98a7a');
    hills(rand, pixels, 130, 30, '#8a6a8f');
    // The ground, and a ramp up to a ledge: a ramp up and a ramp down are mirror images.
    fillRect(pixels, 0, 150, Settings.WIDTH, 30, '#3e3550');
    fillPolygon(pixels, [
        {
            x: 30,
            y: 150
        },
        {
            x: 90,
            y: 120
        },
        {
            x: 150,
            y: 120
        },
        {
            x: 150,
            y: 150
        }
    ], '#5a4d72');
    // The house: walls, and the roof sharing their top edge.
    fillRect(pixels, 200, 110, 60, 40, '#e9e1d0');
    fillPolygon(pixels, [
        {
            x: 192,
            y: 110
        },
        {
            x: 230,
            y: 84
        },
        {
            x: 268,
            y: 110
        }
    ], '#b3402e');
    fillRect(pixels, 222, 128, 14, 22, '#6b4a32');
};
```

`components/canvas.ts`:

```ts
import { createSprite, useKeyboard, useUpdate } from 'nacatamalon';
import { createPixelTexture, createPixels, updatePixelTexture } from 'nacatamalon/pixels';

import * as Settings from '../settings';
import { useRandom } from 'nacatamalon/math';
import { paint } from '../art/landscape';

export const Canvas = () => {
    const random = useRandom();
    const pixels = createPixels(Settings.WIDTH, Settings.HEIGHT);

    paint(pixels, random.rand);

    const picture = createPixelTexture(pixels);

    createSprite({
        texture: picture,
        anchor: {
            x: 0,
            y: 0
        }
    });

    const keys = useKeyboard();

    useUpdate(() => {
        if (keys.justPressed(' ')) {
            paint(pixels, random.rand);
            updatePixelTexture(picture);
        }
    });
};
```

`scenes/demo.ts`:

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

import { Canvas } from '../components/canvas';

export const Landscape = () => {
    useSpawn(Canvas)();

    return createScene();
};
```

`settings.ts`:

```ts
export const WIDTH = 320;
export const HEIGHT = 180;
export const SEED = 3;
```
