Strange error when creating physics body in Andengine - java

I`m trying to create a polygonal physics body by such code:
final float halfWidth = pAreaShape.getWidthScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
final float halfHeight = pAreaShape.getHeightScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
final float centerX = 0;
final float left = -halfWidth;
final float right = halfWidth;
final float top = -halfHeight + 9f / PIXEL_TO_METER_RATIO_DEFAULT;
final float bottom = halfHeight;
final PolygonShape shape1 = new PolygonShape();
final Vector2[] vertices = {
new Vector2(centerX, bottom),
new Vector2(left+8f/PIXEL_TO_METER_RATIO_DEFAULT, bottom-19f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(left+7f/PIXEL_TO_METER_RATIO_DEFAULT, bottom-23f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(left+10f/PIXEL_TO_METER_RATIO_DEFAULT, top+14f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(left+13f/PIXEL_TO_METER_RATIO_DEFAULT, top+8f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(right-14f/PIXEL_TO_METER_RATIO_DEFAULT, top+8f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(right-11f/PIXEL_TO_METER_RATIO_DEFAULT, top+14f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(right-9f/PIXEL_TO_METER_RATIO_DEFAULT, bottom-23f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(right-10f/PIXEL_TO_METER_RATIO_DEFAULT, bottom-19f/PIXEL_TO_METER_RATIO_DEFAULT)
};
Body body = PhysicsFactory.createPolygonBody(pPhysicsWorld, pAreaShape, vertices, pBodyType, pFixtureDef);
Variable vertices contains vertices of this shape.
And it doesn`t work — applications starts(shows black screen and applications title bar), than it quits without any errors(there is no crash dialog and no errors in LogCat).
BUT when i delete one of the elements of vertices array, it works fine.
What i`m doing wrong?

Box2D has a maximum of 8 vertices in a polygon, and will fail by assertion if you specify more. I'm not sure what version of Box2D ANDEngine uses, but try making a loop or edge shape

Related

libGDX Strange Dot in Box2DDebugRenderer

I create Body object that cannot precision collide with ground. There are strange dot(.) between them.
Here the pic:
Here my script to create Body object:
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(Static.toMeter(128), Static.toMeter(128));
bodyDef.type = BodyDef.BodyType.DynamicBody;
body = world.createBody(bodyDef);
// Define mario shape
PolygonShape shape = new PolygonShape();
shape.setAsBox(Static.toMeter(32) / 2, Static.toMeter(32) / 2);
FixtureDef fixture = new FixtureDef();
fixture.shape = shape;
body.createFixture(fixture);
body.setUserData(this);
Why this happen?
Did I create something wrong?
I checked some example online and didn't show the dot.
UPDATE:
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
public static final float PIXEL_TO_METER = 1/300f;
public static final float METER_TO_PIXEL = 300;
By default the box2d debug renderer renders everything box2d, this means it renders fixtures, joints, etc., see the constructor:
new Box2DDebugRenderer(drawBodies, drawJoints, drawAABBs, drawInactiveBodies, drawVelocities, drawContacts);
This small dot is a contact.
Basically I just set conversion to big. 300 pixel = 1 meter.
When I change it under 100 pixel = 1 meter. It works fine. So, I change to this:
public static final float PIXEL_TO_METER = 1/64f;
public static final float METER_TO_PIXEL = 64;

Dot game failed , cannot identify and draw dots around image correctly

What i am trying to achieve is to draw dot at the exact same location as black dot already present in image , but there are problem that i have to face regarding image:
Image can change its densities in multiple screens(so no fixed size)
Given image can be of any size , i have to convert it to appropriate size to show on custom View.
and How to show image in custom view so its density remain the same ?
Now problems regarding dots drawing:
How can i identify black dots x,y axis dynamically to draw at the same exact black dot drawn in image of custom view.
Is there a good way to achieve question 1 dynamically or i should hard code dots.
What i have done so far:
I have moved all images to drawable folder and done layout_width = wrap_content and height the same as width.
<com.jutt.dotbot.ConnectDotsView
android:id="#+id/gfxImage"
android:layout_width="500dpi"
android:layout_height="600dpi"
android:layout_marginTop="100dip"
android:layout_centerHorizontal="true"/>
I've look hard coded points by Toast the point on each ACTION_DOWN in onTouchEvent and then noted then and given to the class ConnectDotsView .
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
L.s(getContext(), "x = "+x+"y = "+y);
break;
After i've noted all points drawn , i am giving this class back that same points to draw , by calling:
public void setPoints(List<Point> points) {
this.mPoints = points;
}
Now Biggest problem [which i think still persist] , (x,y) on screen 1152w*720h may not be same on 480w*600h , so what i've done is who a function to actually convert those points.
private static final int OLDSCREENX = 1152;
private static final int OLDSCREENY = 720;
private int[] makeDimentionGeneric(float oldScreenX, float oldScreenY,
float oldX, float oldY) {
// get screen size
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
final float y = displaymetrics.heightPixels;
final float x = displaymetrics.widthPixels;
int[] i = new int[] { (int) ((oldX / oldScreenX) * x),
(int) ((oldY / oldScreenY) * y) };
return i;
}
and i am calling this while setting the points like makeDimentionGeneric(OLDSCREENX, OLDSCREENY, p.x, p.y); when p.x and p.y are hardcoded stored value from screen.
Now what happens when i try to run it in different devices.
When am i doing it wrong and how can i achieve it correctly ? please guys i've worked hard studied but can't seems to find a better approach than i've mentioned.
[Update] as requested(21 jul 2015):
private int[] makeDimentionGeneric(float oldScreenX, float oldScreenY,
float oldX, float oldY) {
// convert all px to dp
oldScreenY = convertPixelsToDp(oldScreenY, this);
oldScreenX = convertPixelsToDp(oldScreenX,this);
oldX = convertPixelsToDp(oldX,this);
oldY = convertPixelsToDp(oldY,this);
// get screen size
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
final float y = convertPixelsToDp(displaymetrics.heightPixels, this);
final float x = convertPixelsToDp(displaymetrics.widthPixels, this);
int[] i = new int[] { (int)((oldX / oldScreenX) * x),
(int) ((oldY / oldScreenY) * y) };
return i;
}
Since your image differs depending on DPI your pixel calculations must also differ depending on DPI. Consider the following question:
Converting pixels to dp
In your case (copied from answer in above question) you probably want to use this method:
/**
* This method converts device specific pixels to density independent pixels.
*
* #param px A value in px (pixels) unit. Which we need to convert into db
* #param context Context to get resources and device specific display metrics
* #return A float value to represent dp equivalent to px value
*/
public static float convertPixelsToDp(float px, Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}

Why will my geometry not appear? (jMonkeyEngine)

I'm just now picking up jMonkeyEngine and I've encountered an issue I can't seem to solve.
In the simpleInitApp method in the main class, I can use the following code to successfully render a box:
Box playerBase = new Box(Vector3f.ZERO,1f,1f,1f);
Geometry playerBaseGeom = new Geometry("playerBase", playerBase);
Transform fixBaseHeight = new Transform(
new Vector3f(0f,(0.5f * 2f),0f));
playerBaseGeom.setLocalTransform(fixBaseHeight);
Material playerBaseMaterial = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
playerBaseMaterial.setColor("Color", ColorRGBA.Yellow);
playerBaseGeom.setMaterial(playerBaseMaterial);
rootNode.attachChild(playerBaseGeom);
I tried to use a class called Tower to be able to spawn several boxes representing towers (for a simple tower defense game). The tower class looks like this:
public class Tower {
private static final float HEIGHT = 0.5f;
private static final float WIDTH = 0.2f;
private static final float DEPTH = 0.2f;
private Geometry towerGeom;
private Material towerMaterial;
private Box tower;
public Tower(AssetManager assetManager, float x_coord, float z_coord) {
tower = new Box();
towerGeom = new Geometry("tower", tower);
towerMaterial = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
towerMaterial.setColor("Color", ColorRGBA.Green);
towerGeom.setMaterial(towerMaterial);
towerGeom.setLocalTranslation(x_coord, (0.5f * .5f),z_coord);
towerGeom.setLocalScale(WIDTH, HEIGHT, DEPTH);
}
public Geometry getGeometry() {
return towerGeom;
}
}
In the main class, in the simpleInitApp method, I tried to use my new Tower class like this:
List <Tower> towers = new ArrayList<Tower>();
towers.add(new Tower(assetManager, 10f,8f));
for(Tower t:towers) {
rootNode.attachChild(t.getGeometry());
}
However, no cube is rendered. Why? I used the exact same procedure shown in the beginning, which worked.
The Box() constructor is meant for serialization only and doesn't initialize the mesh. The constructor in your upper example is deprecated. Use:
tower = new Box(0.5f, 0.5f, 0.5f);
This will create a cube of the size 1x1x1 centered at [0, 0, 0].
Also, make sure you look at the tower. With the default camera position and the tower at [10, 0, 8], it will be placed behind you.
getCamera().lookAt( new Vector3f(10f, 0, 8f), Vector3f.UNIT_Y );
I recommend consulting the jME source code for this kind of problem so you can be sure whats going on.

Box2d setAngularVelocity do not work for high speeds

I am using Box2d for a game, and although I use large constants to set angular velocity, the fastest speed I can get is 1 revolution at 3.86 seconds.
I had checked my source code in the following thread and everything is the same with what I have been suggested from both users in here and in tutorials:
setAngularVelocity rotates really slowly
However than I noticed the following unresolved thread:
http://www.reddit.com/r/libgdx/comments/1qr2m3/the_strangest_libgdxbox2d_behaviour/
and noticed that might actually be the problem. Here is my dispose method
public void dispose() {
//Get Rid of Everything!
Assets.Clear();
GameEngine.Clear();
BallMap.clear();
PlayerMap.clear();
shapeRenderer.dispose();
debugRenderer.dispose();
world.dispose();
batch.dispose();
font.dispose();
}
They are all reinitialized on the beginning as follows:
this.game = game;
this.cameraWidth = cameraWidth*pixelRatio;
this.cameraHeight = cameraHeight*pixelRatio;
batch = new SpriteBatch();
shapeRenderer = new ShapeRenderer();
stateTime = 0F;
Scores = new Integer[]{0, 0};
debugRenderer = new Box2DDebugRenderer();
world = new World(new Vector2(0, 0), true); //Create a world with no gravity
GameEngine.setContactListener(world);
I navigate through screens with the following code:
public void create () {
scene_menu = new MainMenuScreen(this, cameraWidth, cameraHeight);
setScreen(scene_menu);
}
public void swtogame(){
scene_menu.dispose();
scene_game = new MatchScreen(this, cameraWidth, cameraHeight);
setScreen(scene_game);
}
public void swtomenu(){
scene_game.dispose();
scene_menu = new MainMenuScreen(this, cameraWidth, cameraHeight);
setScreen(scene_menu);
}
the way i initialize objects:
public Object(World world, short category, short mask, float x, float y, float radius, Sprite image,
float maxSpeed, float frictionStrength, float linearDamping, float angularDamping, boolean movable,
float elasticity, float mass){
this.world = world;
this.category = category;
this.mask = mask;
// We set our body type
this.bodyDef = new BodyDef();
if(movable==true){bodyDef.type = BodyType.DynamicBody;}else{bodyDef.type = BodyType.StaticBody;}
// Set body's starting position in the world
bodyDef.position.set(x, y);
bodyDef.linearDamping = linearDamping;
bodyDef.angularDamping = angularDamping;
// Create our body in the world using our body definition
this.body = world.createBody(bodyDef);
// Create a circle shape and set its radius
CircleShape circle = new CircleShape();
circle.setRadius(radius);
// Create a fixture definition to apply our shape to
fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = (float) (mass/(Math.PI*radius*radius));
fixtureDef.friction = frictionStrength;
fixtureDef.restitution = elasticity;
fixtureDef.filter.categoryBits = category;
fixtureDef.filter.maskBits = mask;
// Create our fixture and attach it to the body
this.fixture = body.createFixture(fixtureDef);
// BodyDef and FixtureDef don't need disposing, but shapes do.
circle.dispose();
... unrelated functions after that
}
Am I disposing correctly? Is this a bug? Is there any way to get around it and use the setAngularVelocity properly?
Because you haven't shown much code, I can I'm not 100% sure that I'm right, but I think that you are hitting the built in maximum movement limit of 2.0 units per time step. This means that at a typical framerate of 60Hz a body covering 2 units per timestep is moving at 120 m/s or 432 km/h (270 mph). Unfortunately it seems that there is no direct way to change this limit in Java, because this limit seems to be defined in the native C++ librarys.
But I think that the real problem is that you have a wrong scale. Box2D uses MKS (meters, kilograms, and seconds). And you may have used pixels instead of meters. The FAQ of Box2D suggests to use
objects [that are] between 0.1 - 10 meters
otherwise you can get strange situations.
See http://www.iforce2d.net/b2dtut/gotchas#speedlimit
and https://code.google.com/p/box2d/wiki/FAQ
I just found the problem, and it was pretty simple. Im just going to post this here for future googlers:
Object was actually rotating properly, the problem was in my drawing method, I didn't use conversion between radians to degrees in my batch.draw, and it interpreted everything in radians. I know such an amateur mistake! Thanks a lot for your time.

Shaky unstable JBox2D bodies

Edit 2: http://youtu.be/KiCzUZ69gpA - as you can see in this video, the shaking effect is amplified when I also render some text for each body. Observe how the ground body (blue) shakes violently when each body has some text rendered near it, and how it does not when text rendering is commented out. This has to be connected!
Edit: I've made two important additions to the original question: I've added my rendering functions, and the camera (translation) methods, and I think that the error is actually there, not in JBox2D.
I'm trying to simulate and render a lot of random bodies (2-20) connected with RevoluteJoints. One body can be connected to multiple others, and there are no separate constructions, i.e. all the bodies are interconnected.
However, when watching the live rendering, it is very shaky and unstable. By that I mean that bodies' positions (or maybe angles) seem to be randomly fluctuating for no apparent reason, making the simulation look unstable.
Here's a video of what I'm observing:
http://youtu.be/xql-ypso1ZU
Notice the middle square and the rotating rectangle. The middle square is shifting its position back and forth slightly at seemingly random intervals, and the rotating rectangle is very jittery (take a look at the point it is rotating about).
What could this effect be due? Is it some known issue with (J)Box2D, or is it an issue with my rendering system? I think that I have somehow misconfigured the physics engine, but also some floating point math in the rendering system could be the culprit.
Here's how I'm creating the bodies and the joints:
private Body setPart(Part part) {
// body definition
BodyDef bd = new BodyDef();
bd.position.set(0f, -10f);
bd.angle = 0f;
bd.type = BodyType.DYNAMIC;
// define shape of the body.
PolygonShape Shape = new PolygonShape();
Shape.setAsBox(part.width / 2, part.height / 2);
// define fixture of the body.
FixtureDef fd = new FixtureDef();
Filter filter = new Filter();
filter.groupIndex = -1;
fd.filter = filter;
fd.shape = Shape;
fd.density = 0.5f;
fd.friction = 0.3f;
fd.restitution = 0.5f;
// create the body and add fixture to it
Body body = world.createBody(bd);
body.createFixture(fd);
body.setUserData(new PartUserData());
return body;
}
private void setJoint(PartJoint partJoint) {
Body bodyOne = partToBody.get(partJoint.partOne);
Body bodyTwo = partToBody.get(partJoint.partTwo);
RevoluteJointDef jointDef = new RevoluteJointDef();
jointDef.bodyA = bodyOne;
jointDef.bodyB = bodyTwo;
jointDef.localAnchorA = partJoint.partOne
.getAnchor(partJoint.percentOne);
jointDef.localAnchorB = partJoint.partTwo
.getAnchor(partJoint.percentTwo);
// rotation
jointDef.lowerAngle = GeomUtil.circle(partJoint.rotateFrom);
jointDef.upperAngle = GeomUtil.circle(partJoint.rotateTo);
jointDef.enableLimit = true;
jointDef.maxMotorTorque = 10.0f; // TODO limit maximum torque
jointDef.motorSpeed = GeomUtil.circle(partJoint.angularVelocity);
jointDef.enableMotor = true;
world.createJoint(jointDef);
}
The time step is 0.01f.
Here is how I draw bodies:
private void drawBody(Body body) {
// setup the transforms
Vector position = camera.translate(body.getPosition());
currentGraphics.translate(position.x, position.y);
currentGraphics.rotate(body.getAngle());
// do the actual rendering
for (Fixture fixture = body.getFixtureList(); fixture != null; fixture = fixture
.getNext()) {
PolygonShape shape = (PolygonShape) fixture.getShape();
if (body.getUserData() instanceof PartUserData) {
fillShape(shape, partFillColor);
currentGraphics.setStroke(partOutlineStroke);
outlineShape(shape, partOutlineColor);
} else {
fillShape(shape, groundFillColor);
outlineShape(shape, groundOutlineColor);
}
}
// clean up
currentGraphics.rotate(-body.getAngle());
currentGraphics.translate(-position.x, -position.y);
currentGraphics.setColor(defaultColor);
currentGraphics.setStroke(defaultStroke);
}
I think that the issue might be the way I'm handling rendering of all the bodies.
This is the algorithm for each body:
1. Translate the Graphics2D object to its position
2. Rotate it by body.getAngle()
3. Render the body
4. Rotate the graphics back
5. Translate the graphics back
Could it be that amongst all these transforms something goes wrong?
When I removed the calls to camera's methods, the effect seems to have been reduced. These are the relevant camera methods:
public Vector translate(Vec2 worldPosition) {
Vector point = new Vector();
point.x = (int) (worldPosition.x * pixelsPerMeter) - position.x;
point.y = (int) (worldPosition.y * pixelsPerMeter) - position.y;
point.x = (int) (point.x * zoom);
point.y = (int) (point.y * zoom);
point.x += renderer.getWidth() / 2;
point.y += renderer.getHeight() / 2;
return point;
}
public Vector translateRelative(Vec2 worldPosition) {
Vector point = new Vector();
point.x = (int) (worldPosition.x * pixelsPerMeter);
point.y = (int) (worldPosition.y * pixelsPerMeter);
point.x = (int) (point.x * zoom);
point.y = (int) (point.y * zoom);
return point;
}
But what part of them would cause an issue?
tl;dr: I've found a solution, but haven't identified the exact problem. Quite sure it's with my translation methods.
It seems that I have identified the scope of the problem and the solution, but I am still not sure what exactly is causing this behavior.
In those translation formulas I posted in the question, all JBox2D vectors are multiplied by a scale called pixelsPerMeter. When I set this scale to a low value, the shaking effect occurs (it's also important to note that there is another factor as well, called zoom, which is usually greater for a lower pixelsPerMeter).
So, it could be that when multiplying by a relatively low pixelsPerMeter, I have to multiply with a higher zoom factor, and since I'm converting to ints in both steps, there could be some errors in the floating point math or something. Please see the translation methods I've posted in the question.
Here's a video that demonstrates this: (to be uploaded)
Notice that when I set the pixelsPerMeter to 250, shaking seems to be gone, while when I set it to 25, it's quite visible.
Your solution was the correct one. You are not supposed to use pixel units for the Box2D physics engine :)
http://box2d.org/2011/12/pixels/
and
https://code.google.com/p/box2d/wiki/FAQ#How_do_I_convert_pixels_to_meters?

Categories