Demo Highlight: 2dVis
Tags: miniscript, minimicro, demo, programming
Published: 2023-11-15 16:36:01

[Mini Micro](https://miniscript.org/MiniMicro/) comes with over 40 built-in demos in the /sys/demo directory.  But a surprising number of users have never taken the time to really explore these.  So, I'm going to highlight some of my favorites, starting with the very first one (alphabetically), **2dVis**.

![Screenshot of 2dVis demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g70rwf7kqjg4v9mxiq7p.png)

This is a fun demonstration of a very powerful technique: calculating the _two-dimensional visibility region_ from a given viewpoint, in an arbitrarily complex environment.  The code is based on [this excellent article](https://www.redblobgames.com/articles/visibility/) from Red Blob Games.

To follow along, download [Mini Micro](https://miniscript.org/MiniMicro/) if you don't have it already, launch it, and enter these commands:

```
cd "/sys/demo"
dir
load "2dVis"
run
```

(The `dir` or _directory listing_ command is not strictly necessary, but is a good habit to get into.)

You should see a display like the screen shot above.  Now simply click and drag anywhere in the map.  As you do, the yellow "light source" or viewpoint will move around, and you can instantly see where a light at that point would cast into the environment.

![Animated GIF of 2DVis demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ux5xexirhgsufnpzvjh.gif)

You can also think of the yellow dot as the viewpoint — say, the position of the player in a game — and the lit areas as all the parts of the map that can be seen from that point.

The code for this is rather complex, though the Red Blob Games article does a good job of explaining the algorithm.  In a nutshell, what it does is:

1. Sort all the endpoints of the line segments that make up the environment, in counter-clockwise order around the viewpoint.
2. "Sweep" over these sorted points, figuring out which line segments are visible or partly visible.
3. For each visible part, add the ends to a growing polygon that represents the visible area.

The demo code then draws this visible-area polygon in a lighter color, before drawing the line segments and yellow ball on top.

Although this is in /sys/demo, it is written in such a way that it can actually be used as an import library!  To use it in your own projects, you would do something like this:

1. Copy 2dVis.ms into your own folder, or else add /sys/demo to the import paths: `env.importPaths.push "/sys/demo"`
2. `import "2dVis"`
3. make a  new Visibility object (and note that because `2dVis` is not a valid identifier, we have to index into locals to find the imported module: `vis = new locals["2dVis"].Visibility`
4. build your environment by calling `vis.loadMap`, `vis.addBlock`, or `vis.addSegments` as desired
5. finally, whenever the viewpoint changes:
   (a) call `vis.setViewpoint` with the new location;
   (b) call `vis.sweep`;
   (c) do whatever you need with the `vis.output` polygon.

So, what could you do with this?  You might make a sneaker game where you have to avoid being seen by roving guards.  (The mathUtil module in /sys/lib has some handy polygon-related methods, like `pointInPoly` for testing whether a given point is within a polygon).  Or you could make a roguelike dungeon crawler, with everything outside the visible polygon hidden.  Or how about a puzzle game, where obstacles change in some predictable way — but only when you can't see them?

Or, like all demos, you can simply explore the code and see what new tips and tricks you discover.

What do you think of this demo?  Does it inspire any ideas?  Let me know in the comments below!