A Game of Blobs - Dead Or Alive
Tags: showdev, javascript, react, game
Published: 2021-06-07 18:47:23

One boring day, some month ago during the Covid Quarantine, stuck in my room in Italy, finding something to do I found an article about __Generative Art__ and it blow my mind.

## What the hell is the "Generative Art"?
> “Generative art is art made using a predetermined system that often includes an element of chance – is usually applied to computer based art”

## The Article
{% link https://dev.to/georgedoescode/tutorial-generative-blob-characters-using-svg-1igg %}

The article summarize what "Generative Art" means and explain how to generate using javascript Blobs. Yes, BLOBS! And you know what? I love blobs.

## What to do with infinite Blobs
I lost hours thinking about them to find out something to do with them. And, when i was in the bathroom I had an idea.
What is the better think you can using randomly infinite cute blobs with cute eyes that will make everyone fall in love?
A skill game in which the user must find the "Wanted" blob before the time end. Each time a blob is found the user receive earn point and receive a new blob to find, dead or alive.

## How to make cute Blobs
In the original [article](https://dev.to/georgedoescode/tutorial-generative-blob-characters-using-svg-1igg) a library to generate svg is used to make blobs, but, I decided to use React.
I will not explain how the shape of the blob is made because the [source article](https://dev.to/georgedoescode/tutorial-generative-blob-characters-using-svg-1igg already explain it very well.

## The recipe

Ingredients for cute and juicy Blobs
- a random number of points
- 1 eye for a cyclopic blob or 2 eyes for a normal blob
- a random cute pastel color palette

Start collecting all the ingredients than get the point and [spline](https://en.wikipedia.org/wiki/Spline_(mathematics)) them to get a blobby cute shape, add the eyes in the right position and at last put some color, and, puff you get the nicest blob ever!

![Lilith](https://camo.githubusercontent.com/22091255c54700d04cc379c40634cda23f7c57f8b12197a094056e0042470d6a/68747470733a2f2f626c6f62732d7369782e76657263656c2e6170702f6170692f626c6f623f76657273696f6e3d763126643d4d5459784e6a67334d6a49324e6a55334e546b334d513d3d2537433130302537433130302537433230302537433230302537433135372e37392d3130302c3133322e312d3135352e35392c37312e34382d3134392e33392c33342e32362d3130302c36372e30372d34322e39362c3132372e37362d35312e39312537433130302d3130302d32322537433237362c39362532352c39322532352d3237362c39362532352c322532352d3237362c39362532352c3938253235)

```javascript
const SvgBlobEye = (props) => {
  const { x, y, size, colors } = props
  return (
    <g
      transform={`matrix(1,0,0,1,${x},${y})`}
      className="blob-eye"
    >
      <circle
        r={size}
        cx="0"
        cy="0"
        stroke-width="2"
        stroke={colors.dark}
        fill={colors.light}
        className="blob-eye-iris"
      />
      <circle
        r={size / 2}
        cx="0"
        cy="0"
        fill={colors.dark}
        className="blob-eye-pupil"
        style={{
          '--radius': `${size / 2}px`,
        }}
      />
    </g>
  )
}
const SvgBlob = ({
   width,
   height,
   body,
   eyes,
   colors,
 }) => {
  return (
    <svg
      viewBox={`0 0 ${width} ${height}`}
      className="blob"
    >
      <path
        d={spline(body as any[], 1, true)}
        stroke-width={2}
        stroke={colors.dark}
        fill={colors.primary}
      />
      <g>
        {eyes.map((eye) => <SvgBlobEye {...eye} colors={colors}/>)}
      </g>
    </svg>
  )
}
```

## The cutest blob is the one that move eyes in funny ways

But i wanted more from my blobs, i wanted them to seem alive and interact with the user.
So i decided to add some animations:
- randomly the blobs must move their eyes
- if clicked the blob will shake the eyes

```javascript
const animations = ['eye-roll', 'eye-roll-reverse', 'eye-converge', 'eye-converge-reverse'];
const SvgBlob = ({
   width,
   height,
   body,
   eyes,
   colors,
   animated,
 }) => {
  const [animation, setAnimation] = useState('');
  useEffect(() => {
    if (!animated) return;
    if (!animation) {
      const timeout = setTimeout(() => setAnimation(randomItem(animations)), random(0, 20000))
      return () => clearTimeout(timeout)
    }
  }, [animation, setAnimation])
  return (
    <svg
      viewBox={`0 0 ${width} ${height}`}
      className={`blob ${animated && animation}`}
      onClick={() => setAnimation('eye-flock')}
      onAnimationEnd={() => setAnimation('')}
    >
      <path
        d={spline(body as any[], 1, true)}
        stroke-width={2}
        stroke={colors.dark}
        fill={colors.primary}
      />
      <g>
        ${eyes.map((eye) => <SvgBlobEye {...eye} colors={colors}/>)}
      </g>
    </svg>
  )
}
```

```css
@keyframes roll {
    0% {
        transform: translate(0, 0);
    }
    20% {
        transform: translate(5px, 5px);
    }
    40% {
        transform: translate(5px, 0px);
    }
    60% {
        transform: translate(5px, -5px);
    }
    60% {
        transform: translate(0, -5px);
    }
    100% {
        transform: translate(0, 0);
    }
}

@keyframes converge-left {
    0% {
        transform: translate(0, 0);
    }
    50% {
        transform: translate(5px, 0);
    }
    100% {
        transform: translate(0, 0);
    }
}

@keyframes converge-right {
    0% {
        transform: translate(0, 0);
    }
    50% {
        transform: translate(-5px, 0);
    }
    100% {
        transform: translate(0, 0);
    }
}

@keyframes flock {
    0% {
        transform: translate(0, 0);
    }
    20% {
        transform: translate(5px, 0px);
    }
    40% {
        transform: translate(calc(-5px), 0px);
    }
    60% {
        transform: translate(5px, 0px);
    }
    80% {
        transform: translate(-5px, 0px);
    }
    100% {
        transform: translate(0, 0);
    }
}

.eye-roll .blob-eye-pupil {
    transform: translate(0, 0);
    animation: roll linear 3s;
}

.eye-roll-reverse .blob-eye-pupil {
    transform: translate(0, 0);
    animation: roll linear 3s reverse;
}

.eye-converge .blob-eye:nth-child(1) .blob-eye-pupil {
    transform: translate(0, 0);
    animation: converge-left linear 0.5s;
}

.eye-converge .blob-eye:nth-child(2) .blob-eye-pupil {
    transform: translate(0, 0);
    animation: converge-right linear 0.5s;
}

.eye-converge-reverse .blob-eye:nth-child(1) .blob-eye-pupil {
    transform: translate(0, 0);
    animation: converge-right linear 0.5s;
}

.eye-converge-reverse .blob-eye:nth-child(2) .blob-eye-pupil {
    transform: translate(0, 0);
    animation: converge-left linear 0.5s;
}

.eye-flock .blob-eye-pupil {
    transform: translate(0, 0);
    animation: flock linear 1s;
}
```

Now you can enjoy your juicy blob!

## Last things

This is only a part of the process i used to make the game [Blobs - Dead or Alive](https://alfredosalzillo.me/blobs-dead-or-alive/) but if you want you can look at the full code in the github repository.

{% github https://github.com/alfredosalzillo/blobs-dead-or-alive/ %}