我试图理解第二世界的碰撞检测。我最近得到了这个教程http://www.gotoandplay.it/_articles/2003/12/bezierCollision.php。我有一些问题让我很困惑 - 如果我尝试交换起点和终点,那么flash演示球正在下降而没有响应。 有人可以解释我,模拟是如何工作的。 我修改了示例代码。它工作完美,直到开始和结束点交换,这是目标c中的相同代码
提前致谢。
-(void)render:(ccTime)dt {
if(renderer)
{
CGPoint b = ball.position;
float bvx = ball.vx;
float bvy = ball.vy;
bvx += .02;
bvy -= .2;
b.x += bvx;
b.y += bvy;
float br = ball.contentSize.width/2;
for ( int p = 0 ; p < [map count] ; p++ ) {
line *l = [map objectAtIndex:p];
CGPoint p0 = l.end;
CGPoint p1 = l.start;
float p0x = p0.x, p0y = p0.y, p1x = p1.x, p1y = p1.y;
// get Angle //
float dx = p0x - p1x;
float dy = p0y - p1y;
float angle = atan2( dy , dx );
float _sin = sin ( angle );
float _cos = cos ( angle );
// rotate p1 ( need only 'x' ) //
float p1rx = dy * _sin + dx * _cos + p0x;
// rotate ball //
float px = p0x - b.x;
float py = p0y - b.y;
float brx = py * _sin + px * _cos + p0x;
float bry = py * _cos - px * _sin + p0y;
float cp = ( b.x - p0x ) * ( p1y - p0y ) - ( b.y - p0y ) * ( p1x - p0x );
if ( bry > p0y - br && brx > p0x && brx < p1rx && cp > 0 ) {
// calc new Vector //
float vx = bvy * _sin + bvx * _cos;
float vy = bvy * _cos - bvx * _sin;
vy *= -.8;
vx *= .98;
float __sin = sin ( -angle );
float __cos = cos ( -angle );
bvx = vy * __sin + vx * __cos;
bvy = vy * __cos - vx * __sin;
// calc new Position //
bry = p0y - br;
dx = p0x - brx;
dy = p0y - bry;
b.x = dy * __sin + dx * __cos + p0x;
b.y = dy * __cos - dx * __sin + p0y;
}
}
ball.position = b;
ball.vx = bvx;
ball.vy = bvy;
if ( b.y < 42)
{
ball.position = ccp(50, size.height - 42);
ball.vx = .0f;
ball.vy = .0f;
}
}
}
答案 0 :(得分:2)
点的顺序定义了曲线上的方向。如果起点位于左侧,而终点位于右侧,则曲线的方向使得“向上”指向曲线上方。但是,如果你交换起点/终点曲线是相反的,所以现在“向上”实际上指向曲线下方。
当您的代码检测到碰撞然后更正速度时,它会使用曲线的方向。这就是为什么当球在曲线上落下并且开始/结束点交换时,它似乎会跳过曲线。
要纠正此问题,您的碰撞分辨率代码应检查球所在的曲线的哪一侧(相对于曲线的方向),并相应地进行调整。
答案 1 :(得分:1)
如果交换l.end和l.start,它将用于没有段的行(l.start,l.end)。这是因为所有值都在这里签名。 算法转动平面,使得线条是水平的,并且其中一个线段末端不移动。之后,很容易理解球是否接触线。如果确实如此,它的速度应该改变:在旋转平面中它只是反转y坐标,我们应该将其旋转回来以使线不再水平。 实际上并不是一个很好的实现。所有这一切都可以在没有罪,cos,只是向量的情况下完成。