com.badlogic.gdx.tests.box2d.PhysicalCell.java Source code

Java tutorial

Introduction

Here is the source code for com.badlogic.gdx.tests.box2d.PhysicalCell.java

Source

package com.badlogic.gdx.tests.box2d;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.joints.DistanceJointDef;
import com.badlogic.gdx.physics.box2d.World;

class PhysicalCell {

    World world;
    Body bodies[][];
    Texture texture;
    Mesh mesh;
    private Vector2[][] buttomLeft;
    static private Vector2 textureSize;
    private static Vector2 physicalSize;

    public PhysicalCell(Vector2 pos, Texture texture, World world) {

        // create 3 x 3 mesh

        this.world = world;
        this.texture = texture;
        bodies = new Body[3][3];

        FixtureDef fd = new FixtureDef();
        fd = new FixtureDef();

        //PolygonShape shape = new PolygonShape();
        //shape.setAsBox(physicalSize.x / 6, physicalSize.y / 6);
        CircleShape shape = new CircleShape();
        shape.setRadius(0.2f);

        fd.shape = shape;
        fd.density = 6f;
        fd.friction = 0.0f;
        fd.restitution = 0.0f;

        BodyDef bd = new BodyDef();
        bd.type = BodyType.DynamicBody;

        // body vertices
        float x = pos.x;
        float y = pos.y;
        float dx = physicalSize.x / 2;
        float dy = physicalSize.y / 2;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (i * j == 1)
                    continue;
                bd.position.set(x + i * dx, y + j * dy);
                Body body = world.createBody(bd);
                body.createFixture(fd);
                bodies[i][j] = body;
            }
        }
        // central body
        //shape.setAsBox(0, 0);
        bodies[1][1] = world.createBody(bd);
        shape.dispose();

        // edges

        int n = 3;
        float dr = (float) Math.sqrt(dx * dx + dy * dy);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                Body body = bodies[i][j];
                Body body2;
                if (i < n - 1) {
                    body2 = bodies[i + 1][j];
                    join(body, body2, dx);
                }

                if (j < n - 1) {
                    body2 = bodies[i][j + 1];
                    join(body, body2, dy);
                }

                if (i < n - 1 && j < n - 1) {
                    body2 = bodies[i + 1][j + 1];
                    join(body, body2, dr);
                }

                if (i < n - 1 && j > 0) {
                    body2 = bodies[i + 1][j - 1];
                    join(body, body2, dr);
                }
            }
        }
    } // constructor

    void setTextureBL(Vector2 bl[][]) {
        this.buttomLeft = bl; // 2 x 2 vector of bottom left texture coords for 1/4 cell
    }

    static public void SetSize(Vector2 textureSize, Vector2 physicalSize) {
        PhysicalCell.textureSize = textureSize; // size of each 1/4 cell texture
        PhysicalCell.physicalSize = physicalSize;
    }

    void buildMesh() {

        mesh = new Mesh(true, 4 * 4 * 4, 3 * 2 * 2 * 2, new VertexAttribute(Usage.Position, 2, "a_position"),
                new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"));

        float vertices[] = new float[4 * 4 * 4];
        short indices[] = new short[3 * 2 * 2 * 2];

        Vector2 pos, tex;
        int v = 0;
        int ind = 0;

        // 4 x 1/4 cell

        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                tex = buttomLeft[i][j];

                pos = bodies[i][j].getPosition();
                vertices[4 * (v + 0) + 0] = pos.x - (1 - i) * physicalSize.x / 6;
                vertices[4 * (v + 0) + 1] = pos.y - (1 - j) * physicalSize.y / 6;
                vertices[4 * (v + 0) + 2] = tex.x;
                vertices[4 * (v + 0) + 3] = tex.y;

                pos = bodies[i + 1][j].getPosition();
                vertices[4 * (v + 1) + 0] = pos.x - (0 - i) * physicalSize.x / 6;
                vertices[4 * (v + 1) + 1] = pos.y - (1 - j) * physicalSize.y / 6;
                vertices[4 * (v + 1) + 2] = tex.x + textureSize.x;
                vertices[4 * (v + 1) + 3] = tex.y;

                pos = bodies[i + 1][j + 1].getPosition();
                vertices[4 * (v + 2) + 0] = pos.x - (0 - i) * physicalSize.x / 6;
                vertices[4 * (v + 2) + 1] = pos.y - (0 - j) * physicalSize.y / 6;
                vertices[4 * (v + 2) + 2] = tex.x + textureSize.x;
                vertices[4 * (v + 2) + 3] = tex.y - textureSize.y; // rrrr!!               

                pos = bodies[i][j + 1].getPosition();
                vertices[4 * (v + 3) + 0] = pos.x - (1 - i) * physicalSize.x / 6;
                vertices[4 * (v + 3) + 1] = pos.y - (0 - j) * physicalSize.y / 6;
                vertices[4 * (v + 3) + 2] = tex.x;
                vertices[4 * (v + 3) + 3] = tex.y - textureSize.y; // rrrr!!               

                // two triangles
                indices[ind++] = (short) v;
                indices[ind++] = (short) (v + 1);
                indices[ind++] = (short) (v + 2);

                indices[ind++] = (short) v;
                indices[ind++] = (short) (v + 2);
                indices[ind++] = (short) (v + 3);

                v += 4;

            }
        }

        //Gdx.app.error("", "x = " + vertices[0] + " , y = " + vertices[1]);

        mesh.setVertices(vertices);
        mesh.setIndices(indices);

    } // buildMesh

    void render() {

        buildMesh();

        GL10 gl = Gdx.graphics.getGL10();
        Gdx.gl.glEnable(GL10.GL_TEXTURE_2D);
        //Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        texture.bind();

        gl.glPushMatrix();
        gl.glTranslatef(0.3f, 0.0f, 0.0f);
        //gl.glScalef(0.5f, 0.5f, 1.0f);
        gl.glRotatef(0, 0f, 0f, 1f);
        mesh.render(GL10.GL_TRIANGLES);
        gl.glPopMatrix();
    }

    private void join(Body b1, Body b2, float length) {

        DistanceJointDef jd = new DistanceJointDef();
        jd.localAnchorA.set(0, 0);
        jd.localAnchorB.set(0, 0);
        jd.bodyA = b1;
        jd.bodyB = b2;
        jd.collideConnected = true;
        //jd.maxLength = 10 + 2 * i;
        jd.length = length;
        //jd.maxForce = mass * gravity;
        //jd.maxTorque = mass * radius * gravity;
        jd.dampingRatio = 0f;
        jd.frequencyHz = 6;
        world.createJoint(jd);
    }

    void merge(PhysicalCell peer, int dir) {

        DistanceJointDef jd = new DistanceJointDef();
        jd.length = 0.95f * (physicalSize.x / 3);
        jd.collideConnected = false;
        //jd.dampingRatio = 0.5f;
        //jd.frequencyHz = 6;
        jd.localAnchorA.set(0, 0);
        jd.localAnchorB.set(0, 0);

        if (dir == 1) { // right TODO: fix it

            jd.bodyA = this.bodies[2][0];
            jd.bodyB = peer.bodies[0][0];
            world.createJoint(jd);

            jd.bodyA = this.bodies[2][1];
            jd.bodyB = peer.bodies[0][1];
            world.createJoint(jd);

            jd.bodyA = this.bodies[2][2];
            jd.bodyB = peer.bodies[0][2];
            world.createJoint(jd);
        }
    }

    public void applyForce(int i, int j, Vector2 force) {
        bodies[i][j].applyForce(force, new Vector2(0, 0));
    }

    public void applyLinearImpulse(int i, int j, Vector2 force) {
        bodies[i][j].applyLinearImpulse(force, new Vector2(0, 0));
    }

    public void setType(int i, int j, BodyType type) {
        bodies[i][j].setType(type);
    }

}