the core idea:
implement a simple data structure containing two points, left and right, representing vectors in 2D space from the origin point (0,0). they are treated as rays that point out an infinite distance. we also need a function pointWithin(p) that returns true if p is between left and right
the advantage of this? you can apply shadowcasting to any coordinate system that can map two points => a straight line in 2D space. i think


you can determine if p is within this range using only multiplication, which avoids the kind of floating point numbers you get from sin, cos
if you have 3 points (a,b,p), you can derive the signed area of a triangle using the determinant of a 3x3 matrix, but if (ax,ay)=(0,0) this simplifies to:
bx * py - px * by
if the area of triangle(a,b,p) is
p lies to the left of b. (a,b,p) is counter-clockwisep lies to the right of b. (a,b,p) is clockwise(a,b,p) are collinearlet q = test(left, right). if q is
left,right are collinear, and the range is 180 degrees if dot(left,right) < 0 and empty otherwisespecial cases:
if the range is zero degrees we mark the data structure empty=true
if the range is 360 degrees (eg a full rotation) we mark the data structure engulfed=true. it felt like an appropriate name for a shadowcaster, this will come up later when we calculate the union of two ranges
we then define a function pointWithin(p) which returns true if p is between left and right, using results from test(left, p), test(right, p)
code:
function Sector(_left, _right) constructor {
left = arrayAppend( , _left);
right = arrayAppend( , _right);
static test = function(a, b) {
return a[0]*b[1] - b[0]*a[1];
};
q = -1;
empty = false; // no collisions
engulfed = false; // full circle engulfed
static update = function() {
if (engulfed) return;
// q < 0 := angle < 180
// q > 0 := angle > 180
q = test(left, right);
// q == 0 := angle = 180 or angle = 0
var collinear = (abs(q) <= math_get_epsilon());
q = collinear ? 0 : sign(q);
// ldotr > 0 := angle < 90 or angle > 270
ldotr = dot2(left, right);
if (collinear && ldotr > 0) {
empty = true;
}
};
update();
static pointWithin = function(p) {
if (engulfed) return true;
if (empty) return false;
var sleft = test(left, p);
var sright = test(right, p);
if (q < 0) {
return (sleft <= 0 && sright >= 0);
}
if (q > 0) {
return (sleft <= 0 || sright >= 0);
}
// if (q == 0):
return (sleft <= 0);
};
}
Did you like this post? Tell us
Leave a comment
Log in with your itch.io account to leave a comment.