Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检测与线条的碰撞并限制移动_Java_Libgdx_2d_Collision Detection - Fatal编程技术网

Java 检测与线条的碰撞并限制移动

Java 检测与线条的碰撞并限制移动,java,libgdx,2d,collision-detection,Java,Libgdx,2d,Collision Detection,我正在用Java制作一个libGDX游戏。我正在做碰撞检测。正如你在图片中看到的,我有一条线,这是一堵墙和一个具有指定半径的玩家。所需位置是玩家试图进入的下一个位置。但是因为有一堵墙,他被放置在实际的位置,在速度向量上,但更接近上一个位置。我在想我怎样才能发现那个更近的位置? 我的尝试: private void move(float deltaTime) { float step; beginMovementAltitude(); if (playerComponen

我正在用Java制作一个libGDX游戏。我正在做碰撞检测。正如你在图片中看到的,我有一条线,这是一堵墙和一个具有指定半径的玩家。所需位置是玩家试图进入的下一个位置。但是因为有一堵墙,他被放置在实际的位置,在速度向量上,但更接近上一个位置。我在想我怎样才能发现那个更近的位置?

我的尝试:

private void move(float deltaTime) {
    float step;
    beginMovementAltitude();
    if (playerComponent.isWalking())
        step = handleAcceleration(playerComponent.getSpeed() + playerComponent.getAcceleration());
    else step = handleDeacceleration(playerComponent.getSpeed(), playerComponent.getAcceleration());
    playerComponent.setSpeed(step);
    if (step == 0) return;
    takeStep(deltaTime, step, 0);
}
private void takeStep(float deltaTime, float step, int rotate) {
    Vector3 position = playerComponent.getCamera().position;
    float x = position.x;
    float y = position.y;
    int radius = playerComponent.getRadius();
    auxEnvelope.init(x, x + radius, y, y + radius);
    List<Line> nearbyLines = lines.query(auxEnvelope);
    float theta;
    int numberOfIntersections = 0;
    float angleToMove = 0;
    Gdx.app.log(step + "", "");
    for (Line line : nearbyLines) {
        VertexElement src = line.getSrc();
        VertexElement dst = line.getDst();
        auxVector3.set(playerComponent.getCamera().direction);
        auxVector3.rotate(Vector3.Z, rotate);
        float nextX = x + (step * deltaTime) * (auxVector3.x);
        float nextY = y + (step * deltaTime) * playerComponent.getCamera().direction.y;
        float dis = Intersector.distanceLinePoint(src.getX(), src.getY(), dst.getX(), dst.getY(), nextX, nextY);
        boolean bodyIntersection = dis <= 0.5f;
        auxVector21.set(src.getX(), src.getY());
        auxVector22.set(dst.getX(), dst.getY());
        auxVector23.set(nextX, nextY);
        if (bodyIntersection) {
            numberOfIntersections++;
            if (numberOfIntersections > 1) {
                return;
            }
            theta = auxVector22.sub(auxVector21).nor().angle();
            float angle = (float) (180.0 / MathUtils.PI * MathUtils.atan2(auxVector23.y - position.y, auxVector23.x - position.x));
            if (angle < 0) angle += 360;
            float diff = (theta > angle) ? theta - angle : angle - theta;
            if (step < 0) step *=-1;
            angleToMove = (diff > 90) ? theta + 180 : theta;
        }
    }
    if (numberOfIntersections == 0) {
        moveCameraByWalking(deltaTime, step, rotate);
    } else {
        moveCameraInDirection(deltaTime, step, angleToMove);
    }
}
private void移动(浮动deltaTime){
浮动台阶;
开始移动高度();
if(playerComponent.isWalking())
步骤=手动加速(playerComponent.getSpeed()+playerComponent.getAcceleration());
else step=handleDeacceleration(playerComponent.getSpeed(),playerComponent.getAcceleration());
playerComponent.设定速度(步长);
如果(步骤==0)返回;
takeStep(deltaTime,step,0);
}
私有void takeStep(浮动增量时间、浮动步长、整数旋转){
Vector3位置=playerComponent.getCamera().position;
浮动x=位置x;
浮动y=位置y;
int radius=playerComponent.getRadius();
初始(x,x+半径,y,y+半径);
List nearbyLines=lines.query(auxEnvelope);
浮动θ;
int numberofcrossions=0;
浮动角度移动=0;
Gdx.app.log(步骤+“”,“”);
用于(行:近署名){
VertexElement src=line.getSrc();
VertexElement dst=line.getDst();
auxVector3.set(playerComponent.getCamera().direction);
auxVector3.rotate(Vector3.Z,rotate);
浮点nextX=x+(步长*增量)*(auxVector3.x);
float nextY=y+(步长*deltaTime)*playerComponent.getCamera().direction.y;
float dis=Intersector.distanceLinePoint(src.getX(),src.getY(),dst.getX(),dst.getY(),nextX,nextY);
布尔体相交=dis 1){
返回;
}
θ=auxVector22.sub(auxVector21.nor().angle();
浮动角度=(浮动)(180.0/MathUtils.PI*MathUtils.atan2(auxVector23.y-position.y,auxVector23.x-position.x));
如果(角度<0)角度+=360;
浮动差=(θ>角度)?θ-角度:角度-θ;
如果(步骤<0)步骤*=-1;
角度移动=(差值>90)?θ+180:θ;
}
}
if(numberofcrossions==0){
移动摄像机穿越(deltaTime、step、rotate);
}否则{
移动方向(deltaTime、step、angleToMove);
}
}

这个想法是找到物体中心的路径和由圆半径移动的线的交点,请参见该图

首先,你需要找到一条线。怎么做,取决于直线是如何定义的,如果它是由两点定义的,那么公式是

nx = ay - by
ny = bx - ax
如果这条线是由正则方程定义的,那么x和y的系数定义了法线,如果我没记错的话

当找到法线时,我们需要对其进行规格化——将坐标除以向量长度,将长度设置为1。就这样吧

然后,我们将在线上的起点、期望点和随机选择点投影到n,将它们视为

向量a到向量b的投影为

但由于b是n,长度等于1,我们将不应用除法,而且我们只想求结果的长度,我们不乘以b。所以我们只计算上述三个点中的每一个,得到三个数字,让我们作为起点的结果,d为期望点,l为线上的选择点

然后我们应该用圆的半径来修改l:

if      (s < d) l -= r;
else if (s > d) l += r;
if(sd)l+=r;
如果s=d,则对象沿直线平行移动,因此直线不会阻碍其移动。这是极不可能的情况,但应该处理

另外,这一点很重要,如果l最初在s和d之间,但修改后不再在s和d之间,这是一种特殊情况,您可能需要处理(例如限制对象移动)

因此,应该计算(d-s)/(l-s)

如果结果大于或等于1,则对象将无法到达直线。
如果结果介于0和1之间,则线会阻碍移动,并且结果指示对象将完成的部分路径。0.5表示对象将中途停止。
如果结果为负值,则表示线位于对象后面,不会阻碍移动


请注意,当使用浮点数时,结果不会非常精确,这就是我们处理这种特殊情况的原因。如果你想阻止这种情况发生,组织循环并尝试近似,直到达到所需的精度。

你尝试了什么,你的错误是什么?在你给出的链接中,我没有看到将播放器置于“固定”位置的相关部分。我一开始试着检查下一个位置离墙的距离是否小于半径。如果是真的,我不会让玩家移动到那里。如果游戏者的速度是固定的,这种行为是正常的。但是在我的游戏中,速度是根据输入来加速和减速的——因此,如果速度高,玩家不会移动,但当速度低时,玩家会移动(在靠近墙的地方减速时会产生一些“慢跑”运动效果),你能提供你在问题中描述的这种尝试的代码吗?是的,在第一种方法中,似乎有很多行重复,这是实际代码吗?我想不会,因为这不会编译(重复变量名)。第二种方法也是如此
if      (s < d) l -= r;
else if (s > d) l += r;