/ants

A web application rendering dots (ants) which move avoiding the cursor and each other.

Primary LanguageTypeScriptMIT LicenseMIT

AnTS

Goal of this project was to create a web application rendering dots (ants) which move avoiding the cursor and each other.

This project was created with TypeScript React. Trigonometric functions have tests created using Jest.

Ants is available at rasmusmerzin.github.io/ants.

Table of contents

Setup

I used Node.js 14.0.0 and Yarn 1.22.4 while developing this project.

Note: I found out that with these versions of Node.js and Yarn and with node-sass versions 4.13.1 and 4.14.0 using CSS variables var(--var) in calc() functions compiles in development mode but throws an error during react-scripts build. In such cases I used Sass variables.

Module versions and scripts are available in package.json.

Downloading and installing

Clone the git repository with git clone https://github.com/rasmusmerzin/ants.git.

Change working directory to ants with cd ants.

When Node.js and yarn or npm are installed one can install needed node modules with yarn or npm install.

Running the app

When node modules are installed it is possible to run the app in development mode with yarn start or npm start.

Open http://localhost:3000 to view it in the browser.

More about development mode at create-react-app.dev.

Running tests

To run tests yarn test or npm test.

More about running tests at create-react-app.dev.

GitHub Pages

To deploy the app to GitHub Pages yarn deploy or npm run deploy.

Deploy script first creates the production build with react-scripts build with project root as rasmusmerzin.github.io/ants and removes source map files. Then the build directory is uploaded to branch gh-pages at github.com/rasmusmerzin/ants which is then served by github.

More about react-app build at create-react-app.dev.
More about gh-pages at npmjs.com.

User interface

When the web page is opened 30 ants are drawn and updated 60 times per second.

Clicking and holding on the screen creates a highlight which ants are trying to avoid. It also shows current distancing range.

In the top left corner there is hamburger icon which opens a menu to configure simulation settings.

Algorithm

When the app component is mounted 30 objects of class Ant are randomly placed in the window space.

Additionally a job is initialized which calculates a velocity and the new position depending on that velocity for each Ant object with an interval depending on the render rate (state.renderRate).

For each Ant object a React component Dot is mapped. They are kept in sync by React runtime.

Mathematics

A velocity for each ant is calculated every frame depending on the count of peers in range.

One peer in range

When there is another ant in distancing range R the a distancing push p will be calculated. Distancing push is a vector with a direction opposite to the direction of the neighbouring ant and a length inversely proportional to the distance d of the same neighbouring ant.

When there is only one neighbour in range the velocity of the given ant is equal to it's neighbour's push vector.

diagram 1

R ‒ distancing range
k ‒ distancing factor

d ‒ neighbour distance
p ‒ distancing push

p=k*R/d

Multiple peers in range

When there are multiple neighbours in range the velocity of the given ant is equal to vector sum of it's neighbours' push vectors.

diagram 2

n ‒ number of neighbours in range
pᵢi neighbour's push

P ‒ push sum

→P=∑(1<=i<=n)(→p_i)

No peers in range

When there are no peers in range ant's velocity will be turned at random to left or right by angle between 0 and ant's agility.

diagram 3

l ‒ previous frame's velocity
α ‒ amount to change velocity direction based on ants agility

(Math.random() -.5) *2 *agility

Summary

It took about eight hours to work out the trigonometry and to implement it in TypeScript React. I wrote automatic tests for the trigonometric functions because I figured these are fundamental and more difficult to debug later on.

It took about 16 hours more to implement control dock to change settings in real time, ants avoiding the cursor and to add a CSS styling and a few animations.