Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

MrBarsack

Frischling

  • »MrBarsack« ist der Autor dieses Themas

Beiträge: 65

Wohnort: NRW

Beruf: Student

  • Private Nachricht senden

1

11.12.2012, 12:18

JBox2D mit LWJGL - Kollisionshülle über das richtige Objekt

Hallo,

Aktuell versuche ich in meine kleine Engine JBox2D zu integrieren. Das klappt soweit halbwegs gut, habe ein kleines, dynamisches Objekt, welches mit einem anderen Objekt physikalisch korrekt reagiert. Nun wollte ich ein etwas größeres, statisches Objekt einbauen. Dies klappt jedoch nicht: die Kollisionsbox ist außerhalb des Objekt, dazu viel größer.

Folgenden Code habe ich dabei verwendet:

Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        bd = new BodyDef();
        bd.type = bodyType; // ist im diesem Falle statisch
        bd.position.set(posX, posY); // Position des Objekt, wird bei glVertex2f verwendet.

        PolygonShape cs = new PolygonShape();

        cs.setAsBox(Breite,Höhe); //Die Breite und Höhe Variablen werden auch fürs Polygon mit der Textur benutzt.

        FixtureDef fd = new FixtureDef();
        fd.shape = cs;
        fd.density = 1.9f;
        fd.friction = 0.3f;
        fd.restitution = -1.0f;

        body = System.world.createBody(bd);
        body.createFixture(fd);


Hoffe ich habe mein Problem richtig erklärt.

Vielen Dank in Voraus,

MrBarsack

2

11.12.2012, 23:59

Hast Du denn schon mehrere kleine dynamische Objekte korrekt gegen einander fliegen sehen? Das hört sich für mich eher danach an, dass Anzeige und physikalische Repräsentation nicht übereinstimmen (und zwar von der Renderfunktionalität her).

MrBarsack

Frischling

  • »MrBarsack« ist der Autor dieses Themas

Beiträge: 65

Wohnort: NRW

Beruf: Student

  • Private Nachricht senden

3

17.12.2012, 13:39

Hallo,

Ja, habe es gerade probiert. Bei mehreren kleinen Objekten funktioniert es genauso gut wie bei 2.
Hab jetzt jedoch auch bemerkt, dass bei kleineren Objekten die Kollisionshülle etwas zu groß ist.


Gruß MrBarsack

MrBarsack

Frischling

  • »MrBarsack« ist der Autor dieses Themas

Beiträge: 65

Wohnort: NRW

Beruf: Student

  • Private Nachricht senden

4

17.12.2012, 18:21

Sorry für Doppelpost, aber ich vermute, dass ich einfach zu wenig Informationen gegeben habe ^^

Hier noch der Render-Code:

Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
        glBegin(GL11.GL_QUADS);
        glTexCoord2f(0,0);
        glVertex2f(Position.x,Position.y);
        glTexCoord2f(1,0);
        glVertex2f(Position.x+Größe.Breite,Position.y);
        glTexCoord2f(1,1);
        glVertex2f(Position.x+Größe.Breite,Position.y+Größe.Hoehe);
        glTexCoord2f(0,1);
        glVertex2f(Position.x,Position.y+Größe.Hoehe);
        glEnd();
            if(rund != null && rund.body.getType() != BodyType.STATIC)
            {
          Position.x = body.getPosition().x;
        Position.y = body.getPosition().y;
            }


Breite, Höhe und Position sind beim Rendern und der Physikabfragen immer die Gleichen.

Hat jemand eine Vermutung, wieso die Kollisionshüllen falsch liegen?

Gruß MrBarsack

Nexxtron

Alter Hase

Beiträge: 424

Wohnort: Heilbronn

Beruf: Student - Software Engineering

  • Private Nachricht senden

5

17.12.2012, 20:20

Zum Einen ist restitution = -1 bei dir, normalerweise sollte der Wert zwischen 0 und 1 liegen.

Und zum Anderen rechnet box2d mit meter und newton-meter und deshalb solltest du die Pixel anzahl aus deiner Engine umrechnen (z.B. das 100 Pixel ein Meter in Box2D sind und wenn ein Objekt 100px breit ist sollte dann die Kollisionshülle in Box2D nur noch 1 Einheit (Meter) groß sein), da ich denke dass er hier mit den Berechnungen was falsch macht, oder die Werte einfach zu groß/klein sind... so etwas hat bei mir viele komische Fehler behoben.

Ansonsten sehe ich zumindest keine Fehler.
New Project: Operation CityRacer

6

17.12.2012, 20:44

Zitat von »"IF YOU USE PIXEL UNITS YOU WILL BE SHOT.txt"«


A little overdramatic, I know.

Seriously, though, if you use pixel units, this engine will probably suck, and you'll get all sorts of jitter and stuff. Please, please, PLEASE, factor in a scaling factor, or (better) a camera class that transforms your physics data before you draw it. Your physics objects should always be roughly between .1 and 10 world-units, which using pixel scale is far too small. Things will NOT work well at the 100-500 unit range, as the engine is not tuned for such large numbers.

The org.jbox2d.dynamics.DebugDraw class has the following stub methods:
setCamera(float x, float y, float scale)
screenToWorld(float screenx, float screeny)
worldToScreen(float worldx, float worldy)

Overloading these in your implementation and using the results of worldToScreen() when you draw will make your life much easier, and will also mean you don't submit a bug report to me, which makes mine easier.

It is also strongly suggested that you add worldToScreenVector and screenToWorldVector methods, which transform vectors just by scaling their direction (i.e. don't apply camera translation, only camera scale).

org.jbox2d.testbed.ProcessingDebugDraw implements DebugDraw in this way, if you don't know what to do you might start looking at that to see.

You are warned!

aus http://code.google.com/p/jbox2d/source/b…+SHOT.txt?r=279 ;) Scheint in der aktuellen Version nicht mehr drin zu liegen... Ich glaube das ganze gilt deshalb nicht mehr so, weil es jetzt die Klasse org.jbox2d.common.OBBViewportTransform gibt. Die solltest Du auch nutzen, dann müsste es keine Probleme geben... Falls Du das noch nicht tust... Da kann man dann auch ein "scale" übergeben. Die Funktion getWorldToScreen ist Dein Freund. Schau Dir sonst mal http://code.google.com/p/jbox2d/source/b…bugDrawJ2D.java an wie das Malen dort umgesetzt wird.

Achja und dann möchte ich Dir noch das hier ans Herz legen: http://www.torsten-horn.de/techdocs/java…tions-JavaTypen, Sonderzeichen wie üöäß würde ich im Code (nicht unbedingt in den Kommentaren) außerdem auch weglassen...

Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von »Chromanoid« (17.12.2012, 21:19)


MrBarsack

Frischling

  • »MrBarsack« ist der Autor dieses Themas

Beiträge: 65

Wohnort: NRW

Beruf: Student

  • Private Nachricht senden

7

18.12.2012, 17:51

Hallo,

Danke für die Antworten :)

Erstmal, ja ich weiß, meine Namensgebung ist nicht die Beste :D Und glaubt mir, wenn ihr den Rest des Codes seht werde ihr wohl die Tastatur vor'n Kopf hauen :D

Nun, zu den Antworten. So wie ich verstanden habe, rechnen die Funktionen Meter in Pixel und andersherum um. Nur wann genau muss ich das denn jetzt benutzen?
Habe jetzt folgenden Code benutzt:

Java-Quelltext

1
2
3
4
5
6
7
8
        OBBViewportTransform test = new OBBViewportTransform(); // Jaja, jetzt habe ich mich sogar selbst übertroffen und "test" als Namen verwendet :D

        test.getScreenToWorld(new Vec2(posX,posY), position);
        bd.position.set(position.x,  position.y);

        PolygonShape cs = new PolygonShape();
        test.getScreenToWorld(new Vec2(Höhe,Breite), position);
        cs.setAsBox(position.x, position.y);


Und natürlich die Anmerkung von Nexxtron befolgt :)

Nur hat sich nichts verändert. Was mache ich falsch bzw. wo und wie muss man die Funktionen verwenden?

Gruß MrBarsack

Nexxtron

Alter Hase

Beiträge: 424

Wohnort: Heilbronn

Beruf: Student - Software Engineering

  • Private Nachricht senden

8

19.12.2012, 23:48

Ich kenn mich jetzt zwar nicht mit OBBViewportTransform aus, aber ich denke mit der getWorldToScreen(..) Funktion kannst du dann wieder die richtige Position für die Textur auslesen. Aber wie genau das funktioniert, weiß ich auch nicht.


[Auszug aus dem Spiel, andem ich gerade arbeite]


Ich setze so die Box2D Position:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
BodyDef def = new BodyDef();
def.type = BodyType.DynamicBody;
def.position.set(map.getStartX(),map.getStartY());        // getStartX/Y() ist schon durch meterPixelRatio geteilt worden

CircleShape circle = new CircleShape();
circle.setRadius(20.0f/meterPixelRatio);        

FixtureDef fix = new FixtureDef();
fix.shape = circle;
fix.density = 0.2f;
fix.friction = 4.0f;        

player = new Sphere(this,world,def,new Texture(Gdx.files.internal("testBall.png")));


Und setze so dann die Textur Position:

C-/C++-Quelltext

1
2
3
renderer.begin(ShapeType.Circle);
renderer.circle(getBody().getPosition().x * GameWorld.meterPixelRatio, getBody().getPosition().y * GameWorld.meterPixelRatio, 20);
renderer.end();


und meterPixelRatio ist 10.0f aber da kannst du variieren.
Wobei ich dir lieber empfehle OBBViewportTransform zu benutzen, da bist du um einiges Flexibler.
New Project: Operation CityRacer

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Nexxtron« (20.12.2012, 00:13)


MrBarsack

Frischling

  • »MrBarsack« ist der Autor dieses Themas

Beiträge: 65

Wohnort: NRW

Beruf: Student

  • Private Nachricht senden

9

21.12.2012, 17:38

Hallo,

Danke für die Antwort. Nur funktioniert es leider weiterhin bei mir nicht ;o

Ich vermute, dass es irgendwo anders im Code liegt. Da die Engine eh noch sehr klein ist, wäre es sehr nett, wenn jemand mal drüber schauen würde.

https://github.com/MrBarsack/BarsackEngine

Wahrscheinlich bekommen manche von euch dadurch Augenkrebs und ähnliches, trotzdem wäre wirklich sehr nett, denn alleine komme ich irgendwie nicht weiter!

Gruß MrBarsack

MrBarsack

Frischling

  • »MrBarsack« ist der Autor dieses Themas

Beiträge: 65

Wohnort: NRW

Beruf: Student

  • Private Nachricht senden

10

22.12.2012, 11:50

Hallo,

Ich habe nun meinen Code genauer angeschaut und habe den Fehler bzw. eine Lösung gefunden:

Einmal habe ich den Rendercode verändert, statt:

Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
        texture[Nummer].bind();
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glTexCoord2f(0,0);
        GL11.glVertex2f(Position.x,Position.y);
        GL11.glTexCoord2f(1,0);
        GL11.glVertex2f(Position.x+Größe.Breite,Position.y);
        GL11.glTexCoord2f(1,1);
        GL11.glVertex2f(Position.x+Größe.Breite,Position.y+Größe.Hoehe);
        GL11.glTexCoord2f(0,1);
        GL11.glVertex2f(Position.x,Position.y+Größe.Hoehe);
        GL11.glEnd();


Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
        texture[Nummer].bind();
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glTexCoord2f(0,0);
        GL11.glVertex2f(Position.x-Größe.Breite / 2,Position.y-Größe.Hoehe / 2);
        GL11.glTexCoord2f(1,0);
        GL11.glVertex2f(Position.x+Größe.Breite / 2,Position.y -Größe.Hoehe / 2);
        GL11.glTexCoord2f(1,1);
        GL11.glVertex2f(Position.x+Größe.Breite / 2,Position.y+Größe.Hoehe / 2);
        GL11.glTexCoord2f(0,1);
        GL11.glVertex2f(Position.x-Größe.Breite / 2,Position.y+Größe.Hoehe / 2);
        GL11.glEnd();


Die Koordinate muss der Mittelpunkt des Quads sein. Außerdem musste ich die Größe der Kollisionsbox halbieren.

Trotzdem vielen Dank an alle, die mir geholfen haben! :thumbsup:

Gruß MrBarsack

Werbeanzeige