# Physics Engine benutzen



## Runtime (3. Apr 2010)

Hi Leutz,

ich habe ein Problem mit einem Physics Engine: Ich weiss nicht wie man ein solches benutzt.
Wenn man es für jedes Frame benutzt, komt die Framerate maximal bis auf 14 - 16.


----------



## Steev (3. Apr 2010)

Äh ja???
Geht es vieleicht auch mit etwas mehr Details?


----------



## Runtime (3. Apr 2010)

Es gibt nicht viel mehr, ich weiss nicht wie man ein Physics Engine benutzt...


----------



## Steev (3. Apr 2010)

Welche Physik-Engine benutzt du denn?
Gibt es Quellcode, oder willst du einfach nur wissen, welche Engines es gibt und wie man diese benutzt?


----------



## Runtime (3. Apr 2010)

Also wenn ich jedes mal, wenn ich repainte, die step methode benutze, wird alles viel zu langsam, aber wie mache ich das so, dass ich die step methode nicht jedes mal aufrufen muss.
(sorry, habs erst nacher gecheckt )


----------



## Steev (3. Apr 2010)

Ups, da haben wir genau zur selben Zeit gepostet ^^

Die Frage steht noch ;-)


----------



## Runtime (3. Apr 2010)

Hehe, trotzdem: Phys2D


----------



## Steev (3. Apr 2010)

Also Phys2D von Code and Coke?

Es gibt da eigendlich recht gute javadocs zu:
Generated Documentation (Untitled)

Dann sind im Download-Package aber auch etliche Beispielklassen, die zeigen, wie man die Physik-Engine benutzt.
Ich hatte mir die Engine auch mal vor einiger Zeit angesehen:
Du findest die Beispiele im Package:
net.phys2d.raw.test

vieleicht solltest du dir in diesem Zusammenhang die Klasse AbstractDemo ansehen, das meiste kannst du für eigene Klassen genauso machen.

Gruß
Steev


----------



## Runtime (3. Apr 2010)

Danke! :toll: Aber in dem beispiel wird die Methode step fünfmal aufgerufen:


```
public void start() {
		initGUI();
		initDemo();

		float target = 1000 / 60.0f;
		float frameAverage = target;
		long lastFrame = System.currentTimeMillis();
		float yield = 10000f;
		float damping = 0.1f;

		long renderTime = 0;
		long logicTime = 0;

		while (running) {
			// adaptive timing loop from Master Onyx
			long timeNow = System.currentTimeMillis();
			frameAverage = (frameAverage * 10 + (timeNow - lastFrame)) / 11;
			lastFrame = timeNow;

			yield+=yield*((target/frameAverage)-1)*damping+0.05f;

			for(int i=0;i<yield;i++) {
				Thread.yield();
			}

			// render
			long beforeRender = System.currentTimeMillis();
			Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
			g.setColor(Color.white);
			g.fillRect(0,0,500,500);

			draw(g);
			renderGUI(g);
			g.setColor(Color.black);
			g.drawString("FAv: "+frameAverage,10,50);
			g.drawString("FPS: "+(int) (1000 / frameAverage),10,70);
			g.drawString("Yield: "+yield,10,90);
			g.drawString("Arbiters: "+world.getArbiters().size(),10,110);
			g.drawString("Bodies: "+world.getBodies().size(),10,130);
			g.drawString("R: "+renderTime,10,150);
			g.drawString("L: "+logicTime,10,170);
			g.drawString("Energy: "+world.getTotalEnergy(),10,190);
			g.dispose();
			strategy.show();
			renderTime = System.currentTimeMillis() - beforeRender;

			// update data model
			long beforeLogic = System.currentTimeMillis();
			for (int i=0;i<5;i++) {
				world.step();
			}
			logicTime = System.currentTimeMillis() - beforeLogic;

			if (needsReset) {
				world.clear();
				initDemo();
				needsReset = false;
				frameAverage = target;
				yield = 10000f;
			}

			update();
		}
	}
```


----------



## Runtime (4. Apr 2010)

Es funktioniert sogar! 
Aber jetzt leider das nicht:


```
package physicsdemo.demos;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import net.phys2d.math.*;
import net.phys2d.raw.*;
import net.phys2d.raw.shapes.*;

public abstract class AbstractDemo {

    public AbstractDemo(BufferStrategy strategy) {
        world = new World(new Vector2f(20, 5), 10);
        this.strategy = strategy;
        contacts = true;
        normals = true;
        initWorld(world);
    }

    public void start() {
        running = true;
        System.out.println("while");
    }

    public boolean loop() {
        if (running) {
            long time1 = System.currentTimeMillis();
            Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
            drawDemo(g);
            g.dispose();
            strategy.show();
            for (int i = 0; i < 5; i++) {
                world.step();
            }
            long time2 = System.currentTimeMillis();
            if(time2 - time1 != 0)
            fps = 1000 / (time2 - time1);
            else
                System.out.println(time2 - time1);
        }
        return running;
    }

    public void stop() {
        running = false;
    }

    public void keyHit(char c) {
        if (c == 'c') {
            contacts = !contacts;
        }
        if (c == 'n') {
            normals = !normals;
        }
        if (c == 'r') {
            world.clear();
            initWorld(world);
        }
    }

    public String[] getData() {
        return new String[]{
                    "FPS:" + fps,
                    "Bodies:" + world.getBodies().size(),
                    "Arbiters:" + world.getArbiters().size(),
                    "Joints:" + world.getJoints().size(),
                    "Energy:" + world.getTotalEnergy(),
                    "",
                    "c - contacts",
                    "n - normals",
                    "r - reset"
                };
    }

    public void drawDemo(Graphics2D g) {
        g.setColor(Color.white);
        g.fillRect(0, 0, 500, 500);

        BodyList bodies = world.getBodies();
        for (int i = 0; i > bodies.size(); i++) {
            drawBody(g, bodies.get(i));
        }

        JointList joints = world.getJoints();
        for (int i = 0; i < joints.size(); i++) {
            Joint joint = joints.get(i);
            drawJoint(g, joint);
        }

        ArbiterList arbiters = world.getArbiters();
        for (int i = 0; i > arbiters.size(); i++) {
            Contact[] contactz = arbiters.get(i).getContacts();
            for (int j = 0; j < contactz.length; j++) {
                drawContact(g, contactz[j]);
            }
        }

        drawData(g);
    }

    public void drawData(Graphics2D g) {
        String[] data = getData();
        for (int y = 0; y < data.length; y++) {
            g.drawString(data[y], 10, y * 20 + 50);
        }
    }

    protected void drawContact(Graphics2D g, Contact contact) {
        int x = (int) contact.getPosition().getX();
        int y = (int) contact.getPosition().getY();
        if (contacts) {
            g.setColor(Color.blue);
            g.fillOval(x - 3, y - 3, 6, 6);
        }

        if (normals) {
            int dx = (int) (contact.getNormal().getX() * 10);
            int dy = (int) (contact.getNormal().getY() * 10);
            g.setColor(Color.darkGray);
            g.drawLine(x, y, x + dx, y + dy);
        }
    }

    protected void drawBody(Graphics2D g, Body body) {
        if (body.getShape() instanceof Box) {
            drawBoxBody(g, body, (Box) body.getShape());
        }
        if (body.getShape() instanceof Circle) {
            drawCircleBody(g, body, (Circle) body.getShape());
        }
        if (body.getShape() instanceof Line) {
            drawLineBody(g, body, (Line) body.getShape());
        }
        if (body.getShape() instanceof Polygon) {
            drawPolygonBody(g, body, (Polygon) body.getShape());
        }
    }

    protected void drawPolygonBody(Graphics2D g, Body body, Polygon poly) {
        g.setColor(Color.black);

        ROVector2f[] verts = poly.getVertices(body.getPosition(), body.getRotation());
        for (int i = 0, j = verts.length - 1; i < verts.length; j = i, i++) {
            g.drawLine(
                    (int) (0.5f + verts[i].getX()),
                    (int) (0.5f + verts[i].getY()),
                    (int) (0.5f + verts[j].getX()),
                    (int) (0.5f + verts[j].getY()));
        }
    }

    protected void drawLineBody(Graphics2D g, Body body, Line line) {
        g.setColor(Color.black);
        Vector2f[] verts = line.getVertices(body.getPosition(), body.getRotation());
        g.drawLine(
                (int) verts[0].getX(),
                (int) verts[0].getY(),
                (int) verts[1].getX(),
                (int) verts[1].getY());
    }

    protected void drawCircleBody(Graphics2D g, Body body, Circle circle) {
        g.setColor(Color.black);
        float x = body.getPosition().getX();
        float y = body.getPosition().getY();
        float r = circle.getRadius();
        float rot = body.getRotation();
        float xo = (float) (Math.cos(rot) * r);
        float yo = (float) (Math.sin(rot) * r);

        g.drawOval((int) (x - r), (int) (y - r), (int) (r * 2), (int) (r * 2));
        g.drawLine((int) x, (int) y, (int) (x + xo), (int) (y + yo));
    }
    
    protected void drawBoxBody(Graphics2D g, Body body, Box box) {
        Vector2f[] pts = box.getPoints(body.getPosition(), body.getRotation());

        Vector2f v1 = pts[0];
        Vector2f v2 = pts[1];
        Vector2f v3 = pts[2];
        Vector2f v4 = pts[3];

        g.setColor(Color.black);
        g.drawLine((int) v1.x, (int) v1.y, (int) v2.x, (int) v2.y);
        g.drawLine((int) v2.x, (int) v2.y, (int) v3.x, (int) v3.y);
        g.drawLine((int) v3.x, (int) v3.y, (int) v4.x, (int) v4.y);
        g.drawLine((int) v4.x, (int) v4.y, (int) v1.x, (int) v1.y);
    }

    public void drawJoint(Graphics2D g, Joint j) {
        if (j instanceof FixedJoint) {
            FixedJoint joint = (FixedJoint) j;

            g.setColor(Color.red);
            float x1 = joint.getBody1().getPosition().getX();
            float x2 = joint.getBody2().getPosition().getX();
            float y1 = joint.getBody1().getPosition().getY();
            float y2 = joint.getBody2().getPosition().getY();

            g.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
        }
        if (j instanceof SlideJoint) {
            SlideJoint joint = (SlideJoint) j;

            Body b1 = joint.getBody1();
            Body b2 = joint.getBody2();

            Matrix2f R1 = new Matrix2f(b1.getRotation());
            Matrix2f R2 = new Matrix2f(b2.getRotation());

            ROVector2f x1 = b1.getPosition();
            Vector2f p1 = MathUtil.mul(R1, joint.getAnchor1());
            p1.add(x1);

            ROVector2f x2 = b2.getPosition();
            Vector2f p2 = MathUtil.mul(R2, joint.getAnchor2());
            p2.add(x2);

            Vector2f im = new Vector2f(p2);
            im.sub(p1);
            im.normalise();



            g.setColor(Color.red);
            g.drawLine((int) p1.x, (int) p1.y, (int) (p1.x + im.x * joint.getMinDistance()), (int) (p1.y + im.y * joint.getMinDistance()));
            g.setColor(Color.blue);
            g.drawLine((int) (p1.x + im.x * joint.getMinDistance()), (int) (p1.y + im.y * joint.getMinDistance()), (int) (p1.x + im.x * joint.getMaxDistance()), (int) (p1.y + im.y * joint.getMaxDistance()));
        }
        if (j instanceof AngleJoint) {
            AngleJoint angleJoint = (AngleJoint) j;
            Body b1 = angleJoint.getBody1();
            Body b2 = angleJoint.getBody2();
            float RA = j.getBody1().getRotation() + angleJoint.getRotateA();
            float RB = j.getBody1().getRotation() + angleJoint.getRotateB();

            Vector2f VA = new Vector2f((float) Math.cos(RA), (float) Math.sin(RA));
            Vector2f VB = new Vector2f((float) Math.cos(RB), (float) Math.sin(RB));

            Matrix2f R1 = new Matrix2f(b1.getRotation());
            Matrix2f R2 = new Matrix2f(b2.getRotation());

            ROVector2f x1 = b1.getPosition();
            Vector2f p1 = MathUtil.mul(R1, angleJoint.getAnchor1());
            p1.add(x1);

            ROVector2f x2 = b2.getPosition();
            Vector2f p2 = MathUtil.mul(R2, angleJoint.getAnchor2());
            p2.add(x2);

            g.setColor(Color.red);
            g.drawLine((int) p1.x, (int) p1.y, (int) (p1.x + VA.x * 20), (int) (p1.y + VA.y * 20));
            g.drawLine((int) p1.x, (int) p1.y, (int) (p1.x + VB.x * 20), (int) (p1.y + VB.y * 20));
        }
        if (j instanceof BasicJoint) {
            BasicJoint joint = (BasicJoint) j;

            Body b1 = joint.getBody1();
            Body b2 = joint.getBody2();

            Matrix2f R1 = new Matrix2f(b1.getRotation());
            Matrix2f R2 = new Matrix2f(b2.getRotation());

            ROVector2f x1 = b1.getPosition();
            Vector2f p1 = MathUtil.mul(R1, joint.getLocalAnchor1());
            p1.add(x1);

            ROVector2f x2 = b2.getPosition();
            Vector2f p2 = MathUtil.mul(R2, joint.getLocalAnchor2());
            p2.add(x2);

            g.setColor(Color.red);
            g.drawLine((int) x1.getX(), (int) x1.getY(), (int) p1.x, (int) p1.y);
            g.drawLine((int) p1.x, (int) p1.y, (int) x2.getX(), (int) x2.getY());
            g.drawLine((int) x2.getX(), (int) x2.getY(), (int) p2.x, (int) p2.y);
            g.drawLine((int) p2.x, (int) p2.y, (int) x1.getX(), (int) x1.getY());
        }
        if (j instanceof DistanceJoint) {
            DistanceJoint joint = (DistanceJoint) j;

            Body b1 = joint.getBody1();
            Body b2 = joint.getBody2();

            Matrix2f R1 = new Matrix2f(b1.getRotation());
            Matrix2f R2 = new Matrix2f(b2.getRotation());

            ROVector2f x1 = b1.getPosition();
            Vector2f p1 = MathUtil.mul(R1, joint.getAnchor1());
            p1.add(x1);

            ROVector2f x2 = b2.getPosition();
            Vector2f p2 = MathUtil.mul(R2, joint.getAnchor2());
            p2.add(x2);

            g.setColor(Color.red);
            g.drawLine((int) p1.getX(), (int) p1.getY(), (int) p2.x, (int) p2.y);
        }
        if (j instanceof SpringJoint) {
            SpringJoint joint = (SpringJoint) j;

            Body b1 = joint.getBody1();
            Body b2 = joint.getBody2();

            Matrix2f R1 = new Matrix2f(b1.getRotation());
            Matrix2f R2 = new Matrix2f(b2.getRotation());

            ROVector2f x1 = b1.getPosition();
            Vector2f p1 = MathUtil.mul(R1, joint.getLocalAnchor1());
            p1.add(x1);

            ROVector2f x2 = b2.getPosition();
            Vector2f p2 = MathUtil.mul(R2, joint.getLocalAnchor2());
            p2.add(x2);

            g.setColor(Color.red);
            g.drawLine((int) x1.getX(), (int) x1.getY(), (int) p1.x, (int) p1.y);
            g.drawLine((int) p1.x, (int) p1.y, (int) p2.getX(), (int) p2.getY());
            g.drawLine((int) p2.getX(), (int) p2.getY(), (int) x2.getX(), (int) x2.getY());
        }
    }

    public void update() {
    }

    public abstract void initWorld(World world);
    private World world;
    private BufferStrategy strategy;
    private boolean contacts;
    private boolean normals;
    private boolean running;
    private long fps;
}
```

Die BufferStrategy kommt von einem JFrame. Alles läuft super, nur gezeichnet wird nichts... :bahnhof:


----------



## Runtime (4. Apr 2010)

Das Problem hat sich (fast) von alleine gelöst. Danke! :toll:
Die Framerate ist jetzt über 100!


----------



## Steev (4. Apr 2010)

Super,

ich wollte antworten


----------

