3D在考虑玩家Y旋转的情况下创建到距离的点

时间:2019-08-21 20:49:12

标签: java point quaternions

我需要在Point(这是我们的玩家位置)前面定义一个2D平面区域,并检查其中包含哪些Point(敌人)。 在游戏中,它用于通过X宽度,Y高度和Z长度来确定我们前面的“盒子”中有哪些敌人。

我需要帮助计算飞机的左下角和右上角。

输入:我们知道玩家的位置,我们知道玩家的旋转。只有飞机Y旋转很重要,因为飞机必须始终在运动员的前方。

我们知道飞机的宽度和长度。在这种情况下,身高无关紧要,我知道如何计算。如果宽度为8米,长度为20,如果玩家位置为0,0,0,则左下角将为X = -4 / Y = 0 / Z = 0,右上角将为X = 4 / Y = 0 / Z = 20

我的代码仅在玩家Y旋转为0时有效,因为我只是将宽度/长度添加到当前的X和Z值。我需要正确的数学公式来确定左下角和右上角的位置,并输入参数Player的Y旋转角度,以使平面区域始终与玩家所面对的方向相同

这是我确切需要的视觉呈现:

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 个答案:

答案 0 :(得分:0)

让玩家位置为P,方向角为Fi,目标位置为T。
单位方向向量D:

d.x = cos(Fi) //don't forget about radians
d.y = sin(Fi)

差异向量

PT = T - P = (T.x - P.x, T.y - P.y)

从T到玩家方向线的垂直距离是正交投影的长度

perplen = Abs(Pt x D) =                  //cross product
          Abs(PT.x * d.y - Pt.y * d.x)
compare it with (AreaWidth/2)

沿方向线的距离:

alonglen = (Pt .dot. D) =                  //dot product
           PT.x * d.x + PT.y * d.y
it should be >=0 and <= than AreaLength

如果两个条件都成立,则目标位于倾斜的矩形

概念验证Delphi代码:

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;

enter image description here