如何阻止二维刚体上的法向力太小? (Java 二维)

How to stop the normal force from being too small on a 2D rigidbody? (Java 2D)

我正在尝试使用 LWJGL 3 在 Java 中创建一个 2D 游戏引擎。目前对象只是带有盒子碰撞器的矩形。对于碰撞检测,我将矩形的边缘更改为具有 y = ax + b 结构的线。其中一个矩形具有刚体组件,使其能够移动并与环境交互。现在的想法是在开始时给刚体一个力,重力关闭,没有摩擦,并且完美反弹(弹性= 1)。一切都很好,直到它碰到一个没有垂直和水平边缘的矩形。我发现如果非刚体物体旋转 90 度或 180 度以外的角度,则法向力是错误的(太小),错误程度取决于旋转。刚体的旋转对问题没有贡献。

Vector2 rotSurface = new Vector2(-collision.surface.ToVector().y, collision.surface.ToVector().x).getNormalized();

System.out.println("Angle: "+Physics.Angle(rotSurface, rb.force));

Vector2 normalForce = rotSurface.multiplyBy(rotSurface.multiplyBy(rb.force).getMagnitude());

rb.force = rb.force.add(normalForce).multiplyBy(1f - rb.friction).add(normalForce.multiplyBy(rb.bounciness));
                           
System.out.println("Angle: "+Physics.Angle(rotSurface, rb.force));
System.out.println("===");

我是不是在计算新的刚体力或法向力本身时做错了什么?如果您需要更多信息来帮助我解决这个问题,请询问。

我在上面的代码中使用的

类:

public class Collision {
    Collider collider;
    ArrayList<Vector2> contactPoints = new ArrayList<Vector2>();
    Vector2 center = Vector2.zero;
    Line surface;
    
    public Collision(Collider collider, ArrayList<Vector2> contactPoints, Line surface) {
        this.collider = collider;
        this.contactPoints = contactPoints;
        for(int i = 0; i < contactPoints.size(); i++) {
            center = contactPoints.get(i).add(center).divideBy(2);
        }
        this.surface = surface;
    }
}

class Line {
    Vector2 begin, eind;
    public float rc = 0;
    public float b = 0;
    public float x, y;
    public boolean vertical = false;
    public boolean horizontal = false;
    
    public Line(Vector2 begin, Vector2 eind) {
        this.begin = begin;
        this.eind = eind;
        if(begin.y == eind.y) {
            this.y = begin.y;
            this.horizontal = true;
        }
        else if(begin.x == eind.x){
            this.x = begin.x;
            this.vertical = true;
        } else {
            this.rc = (eind.y - begin.y) / (eind.x - begin.x);
            this.b = GetB(rc, begin);
        }
    }
    
    public float GetB(float rc, Vector2 punt) {
        return punt.y - (rc * punt.x);
    }
    
    public Vector2 GetIntersection(Line l2) {
        float x_ = rc - l2.rc;
        if(vertical) {
            x_ = x;
            if(l2.horizontal) {
                return new Vector2(x, l2.y);
            }
            else if(!l2.vertical){
                //System.out.println("gert");
                return new Vector2(x, l2.rc * x + l2.b);
            }
        } else if(horizontal) {
            if(l2.vertical) {
                return new Vector2(l2.x, y);
            } else if(!l2.horizontal) {
                return new Vector2((y-l2.b) / l2.rc, y);
            }
        } else {
            if(l2.vertical) {
                return new Vector2(l2.x, rc * l2.x + b);
            } else if(l2.horizontal) {
                return new Vector2((l2.y - b) / rc, l2.y);
            }
        }
        if(x_ == 0) {
            return null;
        }
        float getal = l2.b - b;
        x_ = getal / x_;
        float y_ = rc * x_ + b;
        return new Vector2(x_, y_);
    }
    
    public Vector2 ToVector() {
        return eind.substract(begin);
    }
    
    public float GetDisTo(Vector2 point) {
        Vector2 point1 = begin.add(eind).divideBy(2);
        return (float) Math.sqrt(Math.pow(point1.x - point.x, 2) + Math.pow(point1.y - point.y, 2));
    }
    
    public boolean Overlaps(Line line) {
        if(horizontal && y == line.y) {
            if(((line.begin.x > begin.x && line.begin.x < eind.x) || (line.eind.x > begin.x && line.eind.x < eind.x)) ||
               ((begin.x > line.begin.x && begin.x < line.eind.x) || (line.eind.x > line.begin.x && eind.x < line.eind.x)))
            return true;
        } else if(vertical && x == line.x) {
            //return true;
        }
        return false;
    }
}

class Vector2 {
    float x, y;
    public static Vector2 zero = new Vector2(0, 0);
    
    public Vector2(float x, float y) {
        this.x = x;
        this.y = y;
    }
    
    public Vector2 multiplyBy(Vector2 vector) {
        return new Vector2(x * vector.x, y * vector.y);
    }
    
    public Vector2 multiplyBy(float getal) {
        return new Vector2(x * getal, y * getal);
    }
    
    public Vector2 divideBy(Vector2 vector) {
        return new Vector2(x / vector.x, y / vector.y);
    }
    
    public Vector2 divideBy(float getal) {
        return new Vector2(x / getal, y / getal);
    }
    
    public Vector2 add(Vector2 vector) {
        return new Vector2(x + vector.x, y + vector.y);
    }
    
    public Vector2 substract(Vector2 vector) {
        return new Vector2(x - vector.x, y - vector.y);
    }
    
    public float getMagnitude() {
        return (float)Math.sqrt(x*x + y*y);
    }
    
    public Vector2 getNormalized() {
        return divideBy(getMagnitude());
    }
}

用鼻窦固定了它。 我替换了

Vector2 normalForce = rotSurface.multiplyBy(rotSurface.multiplyBy(rb.force).getMagnitude());

Vector2 normalForce = rotSurface.multiplyBy((float)Math.sin(Math.toRadians((double) (90f - Physics.Angle(rotSurface, force)))) * force.getMagnitude());