如何防止二维刚体上的法向力太小? 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());
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)