Android Open Source - hiddenmarble Body Helper






From Project

Back to project page hiddenmarble.

License

The source code is released under:

Apache License

If you think the Android project hiddenmarble listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.mygdx.hiddenmarble.utils;
//from   w w  w .  j a v  a 2  s .c  o  m
import java.util.HashMap;
import java.util.Map;

import maze.ImmutablePosition;
import maze.Position;

import com.badlogic.gdx.math.MathUtils;
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.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.ChainShape;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.mygdx.hiddenmarble.entities.MazeFixtureDef;
import com.mygdx.hiddenmarble.utils.MazeHelper.MazeDef;

/** Creates Box2D bodies for the game entities. */
public final class BodyHelper {
    private static final float BORDER_FRICTION = 0.8f;
    private static final float BORDER_RESTITUTION = 0.1f;

    private static final float MARBLE_DENSITY = 1.0f;
    private static final float MARBLE_FRICTION = 0.5f;
    private static final float MARBLE_RESTITUTION = 0.0f;

    private static final float MAZE_BOX_FRICTION = 0.5f;
    private static final float MAZE_BOX_RESTITUTION = 0.1f;

    private BodyHelper() {
    }

    /**
     * Creates a body for the screen borders.
     * 
     * @param  world the Box2D world
     * @param  width the scaled width of the screen
     * @param  height the scaled height of the screen
     * @return a new Box2D body
     */
    public static Body getBordersBody(World world, float width, float height) {
        BodyDef bodyDef = new BodyDef();
        bodyDef.position.set(new Vector2(width, height).scl(-0.5f));
        Body body = world.createBody(bodyDef);

        Vector2[] vertices = new Vector2[4];
        vertices[0] = new Vector2(0.0f, 0.0f);
        vertices[1] = new Vector2(width, 0.0f);
        vertices[2] = new Vector2(width, height);
        vertices[3] = new Vector2(0.0f, height);

        ChainShape chain = new ChainShape();
        chain.createLoop(vertices);

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = chain;
        fixtureDef.friction = BORDER_FRICTION;
        fixtureDef.restitution = BORDER_RESTITUTION;
        
        body.createFixture(fixtureDef);

        chain.dispose();

        return body;
    }

    /**
     * Creates a body for the marble.
     * 
     * @param  world the Box2D world
     * @param  position the body position
     * @param  radius the body radius
     * @return a new Box2D body
     */
    public static Body getMarbleBody(World world, Vector2 position, float radius) {
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyType.DynamicBody;
        bodyDef.allowSleep = false;
        bodyDef.position.set(position);

        CircleShape circle = new CircleShape();
        circle.setRadius(radius);
        
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = circle;
        fixtureDef.density = MARBLE_DENSITY;
        fixtureDef.friction = MARBLE_FRICTION;
        fixtureDef.restitution = MARBLE_RESTITUTION;

        Body body = world.createBody(bodyDef);
        body.createFixture(fixtureDef);

        circle.dispose();

        return body;
    }

    /**
     * Creates a body for the maze box.
     * 
     * @param  world the Box2D world
     * @param  mazeDef the maze definition
     * @return a new Box2D body
     */
    public static Body getMazeBoxBody(World world, MazeDef mazeDef) {
        int width = mazeDef.maze.getWidth();
        int height = mazeDef.maze.getHeight();
        
        Vector2 offset = new Vector2(width, height);
        offset.scl(0.5f);
        offset.sub(0.5f, 0.5f);
        
        BodyDef bodyDef = new BodyDef();
        bodyDef.position.sub(offset);
        Body body = world.createBody(bodyDef);

        Map<Position, Fixture> fixtureMap =
                new HashMap<Position, Fixture>(height * width);
        
        /* Sets up the maze wall blocks. */
        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                if (mazeDef.maze.isWall(x, y)) {
                    PolygonShape square = new PolygonShape();
                    Vector2 center = new Vector2(x, (height - y - 1));
                    square.setAsBox(0.5f, 0.5f, center, 0.0f);
                    
                    FixtureDef fixtureDef = new FixtureDef();
                    fixtureDef.shape = square;
                    fixtureDef.friction = MAZE_BOX_FRICTION;
                    fixtureDef.restitution = MAZE_BOX_RESTITUTION;
                    
                    Fixture fixture = body.createFixture(fixtureDef);
                    fixture.setUserData(new MazeFixtureDef(center, false, false));
                    
                    fixtureMap.put(new ImmutablePosition(x, y), fixture);
                    
                    square.dispose();
                }
            }
        }
        
        /* Removes the fixture at the exit position. */
        Fixture exitFixture = fixtureMap.get(mazeDef.exit);
        body.destroyFixture(exitFixture);
        
        Position[] corners = new Position[4];
        corners[0] = new ImmutablePosition(0, 0);
        corners[1] = new ImmutablePosition(0, height - 1);
        corners[2] = new ImmutablePosition(width - 1, height - 1);
        corners[3] = new ImmutablePosition(width - 1, 0);
        
        /* Sets up the corners. */
        for (int i = 0; i < corners.length; ++i) {
            Position pos = corners[i];
            Fixture toDestroy = fixtureMap.get(pos);
            Vector2 center = ((MazeFixtureDef)toDestroy.getUserData()).center;
            body.destroyFixture(toDestroy);
            
            PolygonShape corner = createCorner(pos, center, 1.0f, width, height);
            
            FixtureDef fixtureDef = new FixtureDef();
            fixtureDef.shape = corner;
            fixtureDef.friction = MAZE_BOX_FRICTION;
            fixtureDef.restitution = MAZE_BOX_RESTITUTION;
            
            Fixture fixture = body.createFixture(fixtureDef);
            fixture.setUserData(new MazeFixtureDef(center, true, false));
            
            corner.dispose();
        }
        
        PolygonShape rectangle = new PolygonShape();
        rectangle.setAsBox((width - 2) / 2.0f, (height - 1) / 2.0f, offset, 0.0f);
        
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = rectangle;

        /* Sets up the sensor area. */
        Fixture fixture = body.createFixture(fixtureDef);
        fixture.setSensor(true);
        fixture.setUserData(new MazeFixtureDef(offset, false, true));
        
        rectangle.dispose();
        
        return body;
    }
    
    /**
     * Creates a rounded corner.
     * 
     * @param  pos the position of the corner in the maze
     * @param  center where the corner block is centered
     * @param  radius the radius of the corner
     * @param  mazeWidth the width of the maze
     * @param  mazeHeight the height of the maze
     * @return a new rounded corner shape
     * @throws IllegalArgumentException if the specified position does not
     *         correspond to a corner of the maze
     */
    private static PolygonShape createCorner(Position pos, Vector2 center,
            float radius, int mazeWidth, int mazeHeight) {
        
        Vector2 circOrigin = new Vector2(center);
        Vector2 rotate = new Vector2();
        float halfRadius = radius / 2.0f;
        
        if (pos.getX() == 0 && pos.getY() == 0) {
            /* Upper left. */
            circOrigin.add(halfRadius, -halfRadius);
            rotate.set(-1.0f, 1.0f);
        } else if (pos.getX() == 0 && pos.getY() == mazeHeight - 1) {
            /* Lower left. */
            circOrigin.add(halfRadius, halfRadius);
            rotate.set(-1.0f, -1.0f);
        } else if (pos.getX() == mazeWidth - 1 && pos.getY() == mazeHeight - 1) {
            /* Lower right. */
            circOrigin.add(-halfRadius, halfRadius);
            rotate.set(1.0f, -1.0f);
        } else if (pos.getX() == mazeWidth - 1 && pos.getY() == 0) {
            /* Upper right. */
            circOrigin.add(-halfRadius, -halfRadius);
            rotate.set(1.0f, 1.0f);
        } else {
            throw new IllegalArgumentException("Not a corner");
        }
        
        int vertexCount = 8; // Maximum is 8.
        Vector2[] vertices = new Vector2[vertexCount];
        vertices[0] = circOrigin;
        for (int i = 0; i < vertexCount - 1; ++i) {
            float angle = (float)i / (vertexCount - 2) * 90.0f * MathUtils.degreesToRadians;
            Vector2 next = new Vector2(radius, radius);
            next.scl(MathUtils.cos(angle), MathUtils.sin(angle));
            next.scl(rotate);
            next.add(circOrigin);
            vertices[i + 1] = next;
        }

        PolygonShape shape = new PolygonShape();
        shape.set(vertices);
        return shape;
    }
}




Java Source Code List

com.mygdx.hiddenmarble.android.AndroidLauncher.java
com.mygdx.hiddenmarble.desktop.DesktopLauncher.java
com.mygdx.hiddenmarble.entities.AbstractDynamicEntity.java
com.mygdx.hiddenmarble.entities.AbstractEntity.java
com.mygdx.hiddenmarble.entities.Borders.java
com.mygdx.hiddenmarble.entities.DefaultBorders.java
com.mygdx.hiddenmarble.entities.DefaultMarble.java
com.mygdx.hiddenmarble.entities.DefaultMazeBox.java
com.mygdx.hiddenmarble.entities.DynamicEntity.java
com.mygdx.hiddenmarble.entities.Entity.java
com.mygdx.hiddenmarble.entities.Marble.java
com.mygdx.hiddenmarble.entities.Material.java
com.mygdx.hiddenmarble.entities.MazeBox.java
com.mygdx.hiddenmarble.entities.MazeFixtureDef.java
com.mygdx.hiddenmarble.ui.GameScreen.java
com.mygdx.hiddenmarble.ui.HiddenMarble.java
com.mygdx.hiddenmarble.ui.WorldRenderer.java
com.mygdx.hiddenmarble.utils.Assets.java
com.mygdx.hiddenmarble.utils.BodyHelper.java
com.mygdx.hiddenmarble.utils.MazeHelper.java
com.mygdx.hiddenmarble.utils.SaveState.java
com.mygdx.hiddenmarble.utils.Serialization.java
com.mygdx.hiddenmarble.utils.SpriteHelper.java
com.mygdx.hiddenmarble.world.GameWorldAdapter.java
com.mygdx.hiddenmarble.world.GameWorldListener.java
com.mygdx.hiddenmarble.world.GameWorld.java