Phys2D Joints

Runtime

Top Contributor
Hallo alle zusammen,

ich programmiere gerade ein Game, dessen Physik viel mit verbundenen Körpern zu tun hat. Ich benutze Phys2D und wollte zwei Räder mit Joints verbinden, was ja auch geklappt hat, aber leider nicht so wie ich es wollte :). Die Räder jagts einfach durch den Raum und dann ist nur noch ein Rad, das schnell um das andere Rad dreht zu sehen. Was mache ich falsch? :bahnhof:
Java:
    //wird aufgerufe, um die Körper richtig zu positionieren
    public void setLocation(float x, float y) {
        frontWheel.setPosition(x, y);
        backWheel.setPosition(x + 50, y);
        smallWheel.setPosition(x + 150, y);
    }

        //init
    public void init() {
        backWheel = new Body(new Circle(10), 1);
        frontWheel = new Body(new Circle(10), 1);
        smallWheel = new Body(new Circle(5), 0.5f);
        backWheel.setFriction(10);
        frontWheel.setFriction(10);
        backWheel.setRestitution(0.8f);
        frontWheel.setRestitution(0.8f);

        setLocation(0, 0);

        fbJoint = new SpringJoint(backWheel, frontWheel, new Vector2f(10, 10), new Vector2f(10, 10));
    }

Danke! :D
 

Runtime

Top Contributor
Java:
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferStrategy;
import net.phys2d.math.Vector2f;
import net.phys2d.raw.*;
import net.phys2d.raw.shapes.*;
import net.phys2d.raw.strategies.QuadSpaceStrategy;

public class KSKB extends Frame implements Runnable {

    private BufferStrategy bs;
    private World world;
    private Body wheel1;
    private Body wheel2;
    private Body line1;
    private Body line2;

    public KSKB() {
        world = new World(new Vector2f(0.0f, 2.0f), 10, new QuadSpaceStrategy(20, 5));
        wheel1 = new Body(new Circle(10), 1);
        wheel2 = new Body(new Circle(10), 1);
        line1 = new StaticBody(new Line(0, 0, 200, 100));
        line2 = new StaticBody(new Line(0, 0, 200, -100));
        wheel1.setPosition(20, 20);
        wheel2.setPosition(100, 20);
        wheel1.setFriction(1);
        wheel2.setFriction(1);
        line1.setPosition(0, 100);
        line2.setPosition(200, 300);
        Joint j = new BasicJoint(wheel1, wheel2, new Vector2f(10, 10));
        world.add(wheel1);
        world.add(wheel2);
        world.add(line1);
        world.add(line2);
        world.add(j);
        setVisible(true);
        setIgnoreRepaint(true);
        setSize(600, 400);
        setLocationRelativeTo(null);
        setResizable(false);
        createBufferStrategy(2);
        bs = getBufferStrategy();
        new Thread(this).start();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        KSKB kskb = new KSKB();
        kskb.addWindowListener(new WindowListener() {

            public void windowOpened(WindowEvent e) {
            }

            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }

            public void windowClosed(WindowEvent e) {
            }

            public void windowIconified(WindowEvent e) {
            }

            public void windowDeiconified(WindowEvent e) {
            }

            public void windowActivated(WindowEvent e) {
            }

            public void windowDeactivated(WindowEvent e) {
            }
        });
    }

    public void run() {
        while(true) {
            Graphics2D g2 = (Graphics2D) bs.getDrawGraphics();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(Color.white);
            g2.fillRect(0, 0, 600, 400);
            g2.setColor(Color.black);
            drawWheel(g2, (int) wheel1.getPosition().getX(), (int) wheel1.getPosition().getY(), 10, 2, 8, -wheel1.getRotation());
            drawWheel(g2, (int) wheel2.getPosition().getX(), (int) wheel2.getPosition().getY(), 10, 2, 8, -wheel2.getRotation());
            g2.drawLine((int) line1.getPosition().getX(), (int) line1.getPosition().getY(),
                    (int) (line1.getPosition().getX() + 200), (int) (line1.getPosition().getY() + 100));
            g2.drawLine((int) line2.getPosition().getX(), (int) line2.getPosition().getY(),
                    (int) (line2.getPosition().getX() + 200), (int) (line2.getPosition().getY() - 100));
            bs.show();
            g2.dispose();
            world.step();
        }
    }

    private void drawWheel(Graphics2D g, int x, int y, float radius, float tyreWidth, int numLines, float angle) {
        float angleStep = (float) (2 * Math.PI / numLines);
        float length = radius - tyreWidth;
        int cx = Math.round(x);
        int cy = Math.round(y);
        for (int i = 0; i < numLines; i++) {
            float xp = (float) (Math.sin(angle) * length);
            float yp = (float) (Math.cos(angle) * length);
            g.drawLine(cx, cy,
                    Math.round(x + xp), Math.round(y + yp));
            angle += angleStep;
        }
        g.drawOval((int) (x + tyreWidth - radius), (int) (y + tyreWidth - radius), (int) (2 * length), (int) (2 * length));
        g.drawOval((int) (x - radius), (int) (y - radius), (int) (2 * radius), (int) (2 * radius));
    }
}

Ok hier gehts noch, aber das Vorderrad dreht sich nicht.
 

Anhänge

  • phys2d.jar
    107,5 KB · Aufrufe: 9

Marco13

Top Contributor
Man müßte da mehr Zeit investieren, um das alles nachzuvollziehen, aber ... wird das, was du erreichen willst, nicht durch einen DistanceJoint erreicht? Mit
DistanceJoint j = new DistanceJoint(wheel1, wheel2, new Vector2f(10,10), new Vector2f(10,10), 80);
sieht's doch ganz OK aus... :bahnhof:
 

Marco13

Top Contributor
Joa
Java:
	/**
	 * @see net.phys2d.raw.Joint#setRelaxation(float)
	 */
	public void setRelaxation(float relaxation) {
	}
:autsch:

Du könntest für sowas auch mal in den speziellen Foren dazu nachfragen. Der Code sieht zwar SEHR schön und sauber und aufgeräumt aus - aber wenn man versucht, es nachzuvollziehen, tauchen einige IMHO Stellen auf, die ... naja, vielleicht täuscht der Eindruck da auch.

Das, was du erreichen willst (eine "starre" Distanz zwischen den Rädern) sollte mit dem DistanceJoint ja eigentlich schon erledigt sein, aber ... joa, was weiß ich, das ist eben ein Spezialfall, weil die Drehung der Räder (d.h. das eigentlich aufwändige bei Starrkörpersimulation: Trägheit, Drehimpuls & Co) wegfallen. Hab' mal versucht, das auf ein Minimum zu reduzieren...
Java:
class SimpleJoint implements Joint {

    private static int NEXT_ID = 0;
    private Body body1;
    private Body body2;
    private int id;

    public SimpleJoint(Body b1, Body b2) {
        id = NEXT_ID++;
        body1 = b1;
        body2 = b2;
    }
    public void setRelaxation(float relaxation) {
    }
    public Body getBody1() {
        return body1;
    }
    public Body getBody2() {
        return body2;
    }
    public void preStep(float invDT) {
    }

    /**
     * Apply the impulse caused by the joint to the bodies attached.
     */
    public void applyImpulse() 
    {
        Vector2f dp = new Vector2f(body2.getPosition());
        dp.sub(body1.getPosition());

        Vector2f dv = new Vector2f(body2.getVelocity());
        dv.sub(body1.getVelocity());

        dp.normalise();
        Vector2f impulse = new Vector2f(dp);
        impulse.scale(-0.5f * dp.dot(dv));

        if (!body1.isStatic()) {
            Vector2f delta1 = new Vector2f(impulse);
            delta1.scale(-1/body1.getMass());
            body1.adjustVelocity(delta1);
        }

        if (!body2.isStatic()) {
            Vector2f delta2 = new Vector2f(impulse);
            delta2.scale(1/body2.getMass());
            body2.adjustVelocity(delta2);
        }
    }

    public int hashCode() {
        return id;
    }

    public boolean equals(Object other) {
        if (other.getClass() == getClass()) {
            return ((SimpleJoint) other).id == id;
        }

        return false;
    }
}

Für weitere Anpassungen solltest du in Erwägung ziehen, dazu überzugehen, dich selbst durch den Code zu wühlen ;)
 

Neue Themen


Oben