FacebookTwitterGoogle+Share

Testing vision

I’m coming off the tail end of a HaXe+nme code binge. It’s been awesome, but it had to end sometime.

I started by attempting to port my GDF6 demo from AS3 to haXe — just for interest’s sake. (Which I accomplished, btw.)
It’s something I’d really like to write more about as a whole, but instead let’s discuss vision.

I’m sure I’ll end up implementing again, at some point.

Press spacebar to switch between methods. You can drag either object around. Enemy's line of sight follows the mouse position.

I specified a viewAngle and a sightDistance. Armed with those two values (and, of course, positions) I hoped to discover what could be seen.

The interesting (useful) part here was in trying to discover if the object (or part of the object) was contained within the triangle those values defined. After much discussion with Karl (more accurately, patient explaination by Karl) we settled on one of two methods which may or may not end up being perfectly equivalent.
He drew a picture a picture, which I’ll include below.

 

Method one

Arbitrary projection plane

vision diagram 1 - arbitrary projection plane

The clear circles indicate the points we will find for the vectors in question, and the black circles where they fall on the arbitrary projection plane. As it says in the image, for simplicity the projection plane is at a distance of one, bringing with it the ease of the unit circle.

enemyLeft and enemyRight are the left- and right-most bounds of sight, as defined by viewAngle (angle +/- viewAngle).
enemyDirection is the vector of exactly where on the unit circle we’re looking.
playerLeft and playerRight I merged into playerCentre, for convenience.

Given an angle, or three in this case, enemyLeft, enemyRight, and enemyDirection are described as <cos(angle),sin(angle)> on the unit circle.
the projectionPlane, perpendicular to enemyDirection is described by <y,-x>.

playerCentre is of course described by some variation of player – enemy.

I feel like we’re getting too math-y, but I’m going to ignore that feeling for now and press on.

The thing is, as you’ve probably realized, enemyLeft and enemyRight are on the unit circle. And since so is enemyDirection, assuming they’re not all the exact same point, they can’t very well be on the projectionPlane. But don’t worry, that’s where this second picture comes in! (again, by Karl.)

 

Similar triangles

vision diagram 2 - similar triangles

 

Why, similar triangles, of course! Since we have py, and <ox, oy> it’s easy to calculate px. (py is 1 because of all this unit circle business, and since that line is enemyDirection. (<ox, oy> is enemyLeft.)

But, hey! It turns out that due to a few tiny wonders of math, we actually never even had to calculate enemyLeft (or for that matter enemyRight; symmetry).
px, or what I now fondly refer to as viewWidth, is just tan(viewAngle).

Now comes the scariest part: finding out where playerCentre intersects with projectionPlane. Apparently, at least according to wikipedia as of ~three minutes ago, if only one of your vectors (b) is a unit vector a dot b = abs(a)*cos(angle) (the distance along b, when a is projected directly onto it).

That can give us the distances we need to provide a nice ratio for another set of similar triangles ( playerCentre dotted with enemyDirection and projectionPlane, since enemyDirection and projectionPlane are, themselves, parallel). Since the length to the projection plane along the enemyDirection is just 1 (unit circle), that ratio describes the distance along the projectionPlane where playerCentre intersects it.
I then use playerRadius/distance to find the offset for the left- and right-most sides at that distance. (This doesn’t work correctly, as the image above illustrates).

After that, it’s just a comparison of distances (playerCentreProjected +/- playerEdgeOffset, and viewWidth) to see if at least one of the edges are in range (or both are out on opposite sides).

After a lot of help from Karl with the math, I implemented this method in the example above.

 

After all that, I hope you’re at least a little disappointed that I went another way entirely.

I feel like I should apologize at this point for all the mistakes above (I’m sure there are many). I should and I do want to, but you know what, I’m not going to. Sorry.
(That was just for refusing to apologize though.)

 

Comments

You must be logged in to post a comment.