问题
I need to define a 2D plane area in front of a Point(which is our player position) and check which Points(enemies) are within it. In the game it is used to determine what enemies are within the "box" in front of us with X width, Y height and Z length.
I need help calculating the bottom left and top right points of the plane.
Input : We know the player position and we know the player rotation. Only the player Y rotation matters, as the plane should always be in front of the player.
We know the plane width and length. Height is irrelevant in this case, I know how to calculate it. If the width is 8 meters and the length 20, if player position is 0,0,0 the bottom left point would be X= -4 / Y = 0 / Z = 0 and the top right point would be X=4 / Y = 0 / Z = 20
My code only works when the player Y rotation is 0, because I simply add the width/length to current X and Z values. I need the correct math formula to determine where the bottom left and top right points would be, taking in parameter the Player's Y rotation, so that the plane area will always be in the same direction that the player is facing
Here is a visual representation of what I need exactly :
https://gyazo.com/fd5ad0e393f6db8236ee7fd766e7286b
`
float AreaWidth = 8;
float AreaLength = 20;
float AreaHeight = 10;
Point AreaBTMLeftPoint = new Point(PlayerPosition.getX()-(AreaWidth/2),
PlayerPosition.getLoc().getY(), PlayerPosition.getLoc().getZ());
Point AreaTOPRightPoint = new Point(PlayerPosition.getLoc().getX()+
(AreaWidth/2), PlayerPosition.getLoc().getY(),
PlayerPosition.getLoc().getZ()+(AreaLength));
float AreaBTMX = AreaBTMLeftPoint.getX();
float AreaBTMZ = AreaBTMLeftPoint.getZ();
float AreaTOPX = AreaTOPRightPoint.getX();
float AreaTOPZ = AreaTOPRightPoint.getZ();
float AreaMaxY = PlayerPosition.getLoc().getY()+(AreaHeight/2);
float AreaMinY = PlayerPosition.getLoc().getY()-(AreaHeight/2);
if (TargetPosition.getLoc().getX() > AreaBTMX &&
TargetPosition.getLoc().getX() < AreaTOPX &&
TargetPosition.getLoc().getY() > AreaMinY &&
TargetPosition.getLoc().getY() < AreaMaxY &&
TargetPosition.getLoc().getZ() > AreaBTMZ &&
TargetPosition.getLoc().getZ() < AreaTOPZ) {
This target is inside the area, do stuff.
}`
回答1:
Let player position is P, direction angle is Fi, target position is T.
Unit direction vector D:
d.x = cos(Fi) //don't forget about radians
d.y = sin(Fi)
Difference vector
PT = T - P = (T.x - P.x, T.y - P.y)
Perpendicular distance from T to direction line of player is length of orthogonal projection
perplen = Abs(Pt x D) = //cross product
Abs(PT.x * d.y - Pt.y * d.x)
compare it with (AreaWidth/2)
Distance along direction line:
alonglen = (Pt .dot. D) = //dot product
PT.x * d.x + PT.y * d.y
it should be >=0 and <= than AreaLength
If both conditions are true, target lies in inclined rectangle
Proof-of-concept Delphi code:
var
i, px, py, tx, ty, XX, YY, ptx, pty: Integer;
perplen, alonglen: Double;
wdt, lng: Integer;
Fi, cs, sn: Double;
begin
px := 300; py := 300;
wdt := 150; lng := 250;
Fi := Pi / 6; cs := Cos(Fi); sn := Sin(Fi);
Canvas.Brush.Color := clBlack;
Canvas.Ellipse(px - 5, py - 5, px + 6, py + 6); //player
Canvas.Brush.Style := bsClear;
Canvas.MoveTo(px, py);
XX := px - Round(Wdt / 2 * sn); YY := py + Round(Wdt / 2 * cs);
Canvas.LineTo(XX, YY);
XX := XX + Round(lng * cs); YY := YY + Round(lng * sn);
Canvas.LineTo(XX, YY);
XX := XX + Round(Wdt * sn); YY := YY - Round(Wdt * cs);
Canvas.LineTo(XX, YY);
XX := XX - Round(lng * cs); YY := YY - Round(lng * sn);
Canvas.LineTo(XX, YY);
Canvas.LineTo(px, py); //rectangle finished
for i := 0 to 99 do begin
tx := 100 + Random(600); //random target
ty := 100 + Random(600);
ptx := tx - px;
pty := ty - py;
perplen := Abs(ptx * sn - pty * cs);
alonglen := ptx * cs + pty * sn;
if (perplen <= Wdt / 2) and (alonglen >= 0) and (alonglen <= lng) then
Canvas.Brush.Color := clBlue // in region
else
Canvas.Brush.Color := clRed;
Canvas.Ellipse(tx - 3, ty - 3, tx + 4, ty + 4);
end;
来源:https://stackoverflow.com/questions/57599014/3d-create-a-point-to-a-distance-taking-in-consideration-the-player-y-rotation