# Owner of

> From the sprite under the pointer to the piece it belongs to: ownerOf(target) leads a click on a slime's eye to the whole slime, and destroy takes it all.

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

Click a slime. Every part of it is a sprite of its own (the body, each eye, each pupil), and the pointer says which one is under it: `info.target`. `ownerOf(target)` is the slime that sprite belongs to, and `destroy` takes the whole slime: its sprites, its `useUpdate` and its `useCleanup`.

S switches to `destroy(target)` alone: only the sprite clicked goes, and the slime goes on hopping without it. R brings five more.

## Code

`index.ts`:

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

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

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

`components/slime.ts`:

```ts
import { useRandom } from 'nacatamalon/math';
import { createSprite, getColor, useCleanup, useUpdate } from 'nacatamalon';
import type { TSprite } from 'nacatamalon';

const part = (width: number, height: number, hex: string) =>
    createSprite({
        width,
        height,
        tint: getColor(hex),
        transform: {
            x: 0,
            y: 0,
            rotation: 0,
            scaleX: 1,
            scaleY: 1
        }
    });

export const Slime = (x: number, y: number, speed: number, alive: { count: number }) => {
    // Every part is a sprite of its own, and every one belongs to this slime.
    const body = part(28, 20, '#5fd17a');
    const eyes = [part(7, 7, '#ffffff'), part(7, 7, '#ffffff')];
    const pupils = [part(3, 3, '#1b1f3a'), part(3, 3, '#1b1f3a')];

    alive.count++;
    useCleanup(() => {
        alive.count--;
    });

    const random = useRandom();
    let t = random.rand(6);

    useUpdate((delta) => {
        t += delta;
        x += speed * delta;

        if (x < 24 || x > 296) {
            speed = -speed;
        }

        const hop = -Math.abs(Math.sin(t * 4)) * 8;

        // A part destroyed on its own is skipped: the slime goes on without it.
        const place = (sprite: TSprite, dx: number, dy: number) => {
            if (sprite.destroyed) {
                return;
            }

            sprite.transform.x = Math.round(x + dx);
            sprite.transform.y = Math.round(y + hop + dy);
        };

        place(body, 0, 0);
        place(eyes[0], -6, -3);
        place(eyes[1], 6, -3);

        const look = speed > 0 ? 1 : -1;

        place(pupils[0], -6 + look, -3);
        place(pupils[1], 6 + look, -3);
    });

    return {
        body
    };
};
```

`scenes/demo.ts`:

```ts
import { createScene, createText, destroy, ownerOf, sceneOf, useKeyboard, usePointer, useSpawn, useUpdate } from 'nacatamalon';

import { Slime } from '../components/slime';

export const Level = () => {
    const alive = {
        count: 0
    };

    const keys = useKeyboard();
    const add = useSpawn(Slime, 'Slime');

    const more = () => {
        for (let i = 0; i < 5; i++) {
            add(40 + i * 60, 70 + (i % 2) * 50, (i % 2 ? -1 : 1) * (20 + i * 6), alive);
        }
    };

    more();

    let whole = true;

    const mode = createText({
        text: '',
        transform: {
            x: 8,
            y: 8
        }
    });

    const count = createText({
        text: '',
        transform: {
            x: 8,
            y: 20
        },
        tint: '#9aa3c7'
    });

    createText({
        text: 'S SWITCH   R MORE',
        transform: {
            x: 8,
            y: 186
        },
        tint: '#9aa3c7'
    });

    usePointer().onDown(({ target }) => {
        if (target === null) {
            return;
        }

        const slime = ownerOf(target);

        // The texts were made in the scene's body, so their owner is the scene: not a slime.
        if (slime === null || slime === sceneOf(slime)) {
            return;
        }

        destroy(whole ? slime : target);
    });

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

        if (keys.justPressed('r')) {
            more();
        }

        mode.text = whole ? 'CLICK: THE WHOLE SLIME' : 'CLICK: ONLY THAT SPRITE';
        count.text = 'SLIMES ' + alive.count;
    });

    return createScene();
};
```

`settings.ts`:

```ts
export const WIDTH = 320;
export const HEIGHT = 200;
```
