Learning and Applying Mathematics using Computing

Lines of Sight

Last post, we developed a game where your robotic opponents all come towards you and you must fire at them to stop them. It was made somewhat easier by the fact that you can see all your opponents all the time, which allowed you to plan what to do quite easily. What would be better is if only the enemies (and parts of the arena) that you can see would be shown.

So how can we show only the enemies and walls that you can see? Well, we can only see any given square if we have direct line of sight into them, uninterrupted by other obstacles. So line of sight is just another special case of using our line drawing algorithm!

One way to implement visibility would be to attempt to trace a line from our location to each square in the arena — if we get there without going through walls then we can see that particular square, otherwise we cannot. That would work fine, but it would get quite time consuming as the arena grows larger. If the arena was 50 by 50, that’s 2500 lines to trace!

A more efficient way to do it is to instead trace a small number of lines heading out from the player at regular (angular) intervals:

So you trace each line and see what squares you cross. You can see all the empty squares you pass through, and the first square with an obstacle in. With enough lines, this will show all the squares that you can see. Tracing lines at regular intervals uses our old friends sine and cosine, in the same way as last post:

for (int angle = 0; angle < 360; angle += 5)
{
double dirX = Math.cos(Math.toRadians(angle));
double dirY = Math.sin(Math.toRadians(angle));
v.followLine(getPlayer().getX(), getPlayer().getY(), dirX, dirY);
}

Everything is made invisible by default, and only made visible if a line-of-sight hits it. Where we used to see everything:

We now trace lines of sight outwards:

And only show what has been hit:

That now makes our game more difficult. You can have a play with the finished version to see how this pans out in practice.