我正在开发一款游戏,用户用手指移动汽车。汽车被表示为矢量(屏幕中的一个点和旋转角度)。当用户开始拖动汽车时,他会生成一个新点 P。我试图平滑汽车的移动,这样如果该点位于 +/- 10px(汽车的边缘)的某处,它就不会改变其角度(汽车被表示为矩形)。这是一个更好解释的图片:
如何求点M(x,y)?
(请注意,角度α是小车的旋转,而不是O点和P点的角度)
OM 垂直于 PM,且方向由
a
(alpha) 定义,即 OM= m.(cos a, sin a)
。
让我们取消点积:
m.(cos a, sin a).(x1 - m.cos a, y1 - m.sin a) = 0 = m.(x1.cos a + y1.sin a - m)
,
给予
m = x1.cos a + y1.sin a
.
OM
= (x1.cos a + y1.sin a).(cos a, sin a)
。
不确定我是否正确,但是:
您想要消除小角度差异以避免振荡
因此要截断一些角度
const double acc=5.0*M_PI/180.0; // truncate to 5 deg angle steps
double a=atan2(P.y-O.y,P.x-O.x); // P direction [rad]
a=round(a/acc)*acc; // truncate
M.x=x0+delta*cos(a);
M.y=y0+delta*sin(a);
其中
delta
是 speed*time
以获取 M
作为新车位置
你想让汽车更真实
然后改用角度积分:
double alpha=0.0; // car direction [rad]
double omega=0.0; // car rotation speed [rad/s]
double epsilon=0.0; // car rotation acceleration [rad/s^2]
// in timer (update) with interval dt [s]
double a=atan2(P.y-O.y,P.x-O.x); // P direction [rad]
a-=alpha; // get the difference and handle overflows
while (a<-M_PI) a+=2.0*M_PI;
while (a>+M_PI) a-=2.0*M_PI;
epsilon=(some_rotation_speed_constant)*a/M_PI;
omega+=epsilon*dt;
alpha+=omega*dt;
M.x=x0+delta*cos(alpha);
M.y=y0+delta*sin(alpha);
你也应该使用积分来定位。如果您不想手动操作,也可以为转轮添加一些调节器P,PI或PID
你只需要
M
并知道P,O
,以及汽车方向角度a
然后利用点积
D.x=cos(a);
D.y=sin(a);
M=O+(D*dot(P-O,D));
if (|M-P|<10px) ignore_turning;
以防万一
dot(A,B)=(A.x*B.x)+(A.y*B.y);
给定 O(x0, y0)、alpha 和 P(x1, y1):
M.x = 1/2 ( (y0 - y1) / tan(alpha) + x0 + x1 )
M.y = 1/2 ( (x0 - x1) * tan(alpha) + y0 + y1 )
您可能需要调整标志以匹配您的坐标系