Dancing Robots

robots dance using vanilla js

by Leonardo Trimarchi

HTML

<canvas></canvas>
<!-- 
                  ,--.    ,--.
                 ((O ))--((O ))
               ,'_`--'____`--'_`.
              _:  ____________  :_
             | | ||::::::::::|| | |
             | | ||::::::::::|| | |
             | | ||::::::::::|| | |
             |_| |/__________\| |_|
               |________________|
            __..-'            `-..__
         .-| : .----------------. : |-.
       ,\ || | |\______________/| | || /.
      /`.\:| | ||  __  __  __  || | |;/,'\
     :`-._\;.| || '--''--''--' || |,:/_.-':
     |    :  | || .----------. || |  :    |
     |    |  | || '----SSt---' || |  |    |
     |    |  | ||   _   _   _  || |  |    |
     :,--.;  | ||  (_) (_) (_) || |  :,--.;
     (`-'|)  | ||______________|| |  (|`-')
      `--'   | |/______________\| |   `--'
             |____________________|
              `.________________,'
               (_______)(_______)
               (_______)(_______)
               (_______)(_______)
               (_______)(_______)
              |        ||        |
              '--------''--------'
-->

CSS

body, html {
	position: absolute;
	margin: 0;
	padding: 0;
	width: 100%;
	height: 100%;
	overflow: hidden;
}

canvas {
	position: absolute;
	width: 100%;
	height: 100%;
	background:#000;
	cursor: pointer;
}

JavaScript

{
	class Robot {
		constructor(color, light, size, x, y, struct) {
			this.x = x;
			this.points = [];
			this.links = [];
			this.frame = 0;
			this.dir = 1;
			this.size = size;
			this.color = Math.round(color);
			this.light = light;
			// ---- create points ----
			for (const p of struct.points) {
				this.points.push(new Robot.Point(size * p.x + x, size * p.y + y, p.f));
			}
			// ---- create links ----
			for (const link of struct.links) {
				const p0 = this.points[link.p0];
				const p1 = this.points[link.p1];
				const dx = p0.x - p1.x;
				const dy = p0.y - p1.y;
				this.links.push(
					new Robot.Link(
						this,
						p0,
						p1,
						Math.sqrt(dx * dx + dy * dy),
						link.size * size / 3,
						link.lum,
						link.force,
						link.disk
					)
				);
			}
		}
		update() {
			if (++this.frame % 20 === 0) this.dir = -this.dir;
			if (
				dancerDrag &&
				this === dancerDrag &&
				this.size < 16 &&
				this.frame > 600
			) {
				dancerDrag = null;
				dancers.push(
					new Robot(
						this.color + 90,
						this.light * 1.25,
						this.size * 2,
						pointer.x,
						pointer.y - 100 * this.size * 2,
						struct
					)
				);
				dancers.sort(function(d0, d1) {
					return d0.size - d1.size;
				});
			}
			// ---- update links ----
			for (const link of this.links) {
				const p0 = link.p0;
				const p1 = link.p1;
				const dx = p0.x - p1.x;
				const dy = p0.y - p1.y;
				const dist = Math.sqrt(dx * dx + dy * dy);
				if (dist) {
					const tw = p0.w + p1.w;
					const r1 = p1.w / tw;
					const r0 = p0.w / tw;
					const dz = (link.distance - dist) * link.force;
					const sx = dx / dist * dz;
					const sy = dy / dist * dz;
					p1.x -= sx * r0;
					p1.y -= sy * r0;
					p0.x += sx * r1;
					p0.y += sy * r1;
				}
			}
			// ---- update points ----
			for (const point of this.points) {
				// ---- dragging ----
				if (this === dancerDrag && point === pointDrag) {
					point.x += (pointer.x - point.x) * 0.1;
					point.y +=...