How to change the center of mass? - android

I am try
MassData md = mBody.getMassData();
md.center.set(2f, 0); mBody.setMassData(md);
But this is not working properly. Help me do this correctly.
I want add a bit more weight to the bottom half of my body.

Instead of trying to change mass directly, what you want to do is to add an extra fixture to the bottom of your body. You can do it e.g. like this (this is a snippet, not complete code; create your textures, scene etc).
Sprite sprite = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2, 32, 32, mDTextureRegion, vbom);
Body body = PhysicsFactory.createCircleBody(mPhysicsWorld, sprite, BodyType.DynamicBody, PhysicsFactory.createFixtureDef(0.5f, 0.5f, 0.5f)); // create a simple circle body from the sprite
scene.attachChild(sprite);
Debug.i("ORIG MASS Y: " + body.getMassData().center.y); // this is just generated info
FixtureDef fd = PhysicsFactory.createFixtureDef(10f, 1f, 1f, true); // high density fixture; it is a sensor, i.e. it won't affect collisions
CircleShape cs = new CircleShape();
cs.setRadius(0.1f); // make it very small
fd.shape = cs;
cs.setPosition(new Vector2(0, -0.5f)); // attach below the current centre
body.createFixture(fd); // attach to body
Debug.i("NEW MASS Y: " + mDBody.getMassData().center.y); // the generated info changed
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, body, true, true));
This example body will behave like a spintop, it will try to reposition itself so the bottom of the sprite will touch the ground. When you rotate it, it will try to get to that position again.

Related

Andengine Friction between bodies

I face strange behavior with no friction between two bodies static and dynamic. I declare bodies in follow code(code in kotlin):
val WALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(0f, 0f, 50f)
val ground = Rectangle(this.mCameraWidth / 2, wallWidth / 2 , this.mCameraWidth, wallWidth, this.vertexBufferObjectManager)
PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyDef.BodyType.StaticBody, WALL_FIXTURE_DEF)
...
this.mBall = UniformColorSprite(this.mCameraWidth / 2, this.mCameraHeight /2 , TILE_WIDTH, TILE_HEIGHT, mBallTextureRegion, this.vertexBufferObjectManager)
val body: Body
val objectFixtureDef = PhysicsFactory.createFixtureDef(100f, 0.3f, 10f, false, CATEGORYBIT_CIRCLE, MASKBITS_CIRCLE, 0)
body = PhysicsFactory.createCircleBody(this.mPhysicsWorld, this.mBall, BodyDef.BodyType.DynamicBody, objectFixtureDef)
this.mPhysicsWorld.registerPhysicsConnector(PhysicsConnector(this.mBall, body, true, true))
Do you have any ideas?
If the second body is circle it is getting some torque that can make an impression that fiction of not working when it is actually working and causes torque.
When you are setting setFixedRotation you are prevent circleBody of rolling and then you can observe the fiction.
Try to change circleBody to polygon and see what will happen.

Box2D(LibGDX) - strange behaviour of ball

I am trying to create simple tennis game. Each side has a wall. There are also a box and a ball. My environment doesn't have gravity. The box and the ball don't have any velocity. When the box contacts the ball(I move this by mouse with different speed), it(the ball) just changes its position and doesn't continue moving and sometimes these objects don't collide with each other:
I want the box can strike the ball using different angle and strength.
How can I do this? What should I change in the properties of the ball and the box?
The code snippet is below:
public void createBall(Vector2 position, Vector2 velocity, float angle, Object userData){
// First we create a body definition
BodyDef bodyDef = new BodyDef();
// We set our body to dynamic, for something like ground which doesnt move we would set it to StaticBody
bodyDef.type = BodyType.DynamicBody;
// Set our body's starting position in the world
bodyDef.position.set(position);
// Create our body in the world using our body definition
Body body = world.createBody(bodyDef);
body.setUserData(userData);
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(10f);
PolygonShape poly = new PolygonShape();
poly.setAsBox(12, 12);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 0.0f;
fixtureDef.friction = 0.2f;
fixtureDef.restitution = 1f; // Make it bounce a little bit
fixtureDef.isSensor=false;
// Create our fixture and attach it to the body
Fixture f = body.createFixture(fixtureDef);
f.setUserData("ball");
circle.dispose();
}
private Body createBox(World world, float width, float height, float density) {
BodyDef def = new BodyDef();
def.type = BodyType.KinematicBody;
Body box = world.createBody(def);
PolygonShape poly = new PolygonShape();
poly.setAsBox(width/2, height/2);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = poly;
fixtureDef.density = 0.0f;
fixtureDef.friction = 0.3f;
fixtureDef.restitution = 0.1f; // Make it bounce a little bit
fixtureDef.isSensor=false;
// Create our fixture and attach it to the body
Fixture f = box.createFixture(fixtureDef);
f.setUserData("platform");
poly.dispose();
return box;
}
public void createWall(World world, Vector2 position, float hx, float hy){
// Create our body definition
BodyDef groundBodyDef =new BodyDef();
// Set its world position
groundBodyDef.position.set(position);
groundBodyDef.type=BodyType.StaticBody;
// Create a body from the defintion and add it to the world
Body groundBody = world.createBody(groundBodyDef);
// Create a polygon shape
PolygonShape groundBox = new PolygonShape();
// Set the polygon shape as a box which is twice the size of our view port and 20 high
// (setAsBox takes half-width and half-height as arguments)
groundBox.setAsBox(hx, hy);
// Create a fixture from our polygon shape and add it to our ground body
groundBody.createFixture(groundBox, 0.0f);
// Clean up after ourselves
groundBox.dispose();
}
You are moving your box by changing its position. But an important part of collision resolution is velocity. And your box's velocity is always zero (from box2d look point). Thus you experience strange collision resolution
I think your screen width and height are too large... if that's the case try using world width and height ... 20x12 units.. not 800x480 something .
Box2D doesn't like bodies, which fixtures has density 0. Usual, simulation performs somehow, but behaviour is not correct. Try value 0.3 for example.
Overlap problem may be solved by setting flag b2BodyDef::bullet. There description from Box2D reference:
bool b2BodyDef::bullet
Is this a fast moving body that should be prevented from tunneling through other moving bodies? Note that all bodies are prevented from tunneling through kinematic and static bodies. This setting is only considered on dynamic bodies.
Warning:
You should use this flag sparingly since it increases processing time.

Chase player with camera in AndEngine and limit world's bounds

Using AndEngine for Android, I would like to have my scene look like this:
The red box is the world which must be limited to a given size, say 2000px*450px.
The blue box is the Camera, which is limited as well (as usual), for example to 750px*450px.
For the whole scene, I have a background image that is exactly 450px high. So my Camera can be scaled to whatever size is appropriate, but the background must exactly fit to the height. The width of the Camera may be variable.
The player (circle) must always be in the center (horizontally) but may not leave the world's boundaries.
To achieve this, I've tried adding two types of sizes:
camera size (CAMERA_WIDTH, CAMERA_HEIGHT)
world size (WORLD_WIDTH, WORLD_HEIGHT)
And this function was to add boundaries to the world so that the physics engine prevents the player from leaving those boundaries:
private void createWorldBoundaries() {
Body body;
final Rectangle wall_top = new Rectangle(0, WORLD_HEIGHT-5, WORLD_WIDTH, 10, mVertexManager);
final Rectangle wall_bottom = new Rectangle(0, 5, WORLD_WIDTH, 10, mVertexManager);
final Rectangle wall_left = new Rectangle(5, 0, 10, WORLD_HEIGHT, mVertexManager);
final Rectangle wall_right = new Rectangle(WORLD_WIDTH-5, 0, 10, WORLD_HEIGHT, mVertexManager);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_top, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_top.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_bottom, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_bottom.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_left, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_left.setUserData(body);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, wall_right, BodyType.StaticBody, new PhysicsFactory.createFixtureDef(0.0f, 0.5f, 0.5f));
wall_right.setUserData(body);
attachChild(wall_top);
attachChild(wall_bottom);
attachChild(wall_left);
attachChild(wall_right);
}
But this is not working, unfortunately. (see edit)
Setting the camera to chase the player has the wrong result for me: The player does really stay in the center of the screen all time, but I want the player only to stay in the center horizontally, not vertically.
What am I doing wrong and what can I change? And the basic question is: How can I make the world wider than the camera view, while the height is equal to the camera view. The result should be that you can horizontally walk through your world (moving camera) and you can always see the full height.
Edit:
As you define the coordinates of the Rectangle's center and not its top-left corner, you have to do it like this, it seems:
final Rectangle wall_top = new Rectangle(WORLD_WIDTH/2, WORLD_HEIGHT-1, WORLD_WIDTH, 2, mVertexManager);
final Rectangle wall_bottom = new Rectangle(WORLD_WIDTH/2, FIELD_BASELINE_Y+1, WORLD_WIDTH, 2, mVertexManager);
final Rectangle wall_left = new Rectangle(1, WORLD_HEIGHT/2, 2, WORLD_HEIGHT, mVertexManager);
final Rectangle wall_right = new Rectangle(WORLD_WIDTH-1, WORLD_HEIGHT/2, 2, WORLD_HEIGHT, mVertexManager);
However, I had found the other solution in several tutorials. Are these authors not testing their code before writing the tutorials or did the behaviour change from GLES1 to GLES2 or with any recent version?
i think your question about the world boundaries is self answered, isn't it?
PhysicsWorld Boundaries
for further research you can download nicolas' AndEngine Examples App from the Play Store and look up the different examples here (GLES_2, didn't look for AnchorCenter yet): https://github.com/nicolasgramlich/AndEngineExamples/tree/GLES2/src/org/andengine/examples
Taken from the PhysicsExample, the code for the rectangles should look like this, if the bounds are set to the camera bounds. in your case, you can extend width like you want (3 times CAMERA_WIDTH?)
final Rectangle ground = new Rectangle(0, CAMERA_HEIGHT - 2, WORLD_WIDTH, 2, vertexBufferObjectManager);
final Rectangle roof = new Rectangle(0, 0, WORLD_WIDTH, 2, vertexBufferObjectManager);
final Rectangle left = new Rectangle(0, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
final Rectangle right = new Rectangle(WORLD_WIDTH - 2, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
Camera following player
for the Camera to follow your player, you can lookup the code of the BoundCameraExample https://github.com/nicolasgramlich/AndEngineExamples/blob/GLES2/src/org/andengine/examples/BoundCameraExample.java
the interesting part for you should be the addFace method at the bottom
private void addFace(final float pX, final float pY) {
final FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager()).animate(100);
final Body body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face, BodyType.DynamicBody, objectFixtureDef);
this.mScene.attachChild(face);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(face, body, true, true));
this.mBoundChaseCamera.setChaseEntity(face);
}
this method creates a physics body + sprite for "your player" (in this case, a boxed face) and sets the sprite as a chaseEntity for the camera to follow. Since the camera has bounds, that it can't exceed and your camera will have the height of your PhysicWorld boundaries, you can use this to let your camera follow the player in x, but not in y direction.
if you (i don't know why) don't want to use these boundaries, you can overwrite the onUpdate method of your Sprite and re-locate your camera only in x-direction, instead of xy coords
face.registerUpdateHandler(new IUpdateHandler() {
#Override
public void onUpdate(final float pSecondsElapsed) {
float[] coord = face.getSceneCenterCoordinates();
this.mBoundChaseCamera.setCenter(sceneCenterCoordinates[0], CAMERA_Y_POSITION);
}
}
where the CAMERA_Y_POSITION is a static final field with the y-position.
I hope this answers your question(s). :-)
edit: oops, i forgot to mention, how to achieve the camera to be bound and i will edit the world width above:
this.mBoundChaseCamera.setBounds(0, 0,
WORLD_WIDTH, CAMERA_HEIGHT);
all settings are like your image given (except the exact position of the face, that has to be given to the addFace(px, py))
Edit: Difference between scene boundaries in Andengine GLES2 vs GLES2-AnchorCenter
As far as i understood the question, i thought you would use GLES2, i thought of the (older) default GLES2 branch of AndEngine and posted the boundaries. As you found out yourself before and stated in the comments, you use another approach to set the rectangles - where you need to set the rectangles center as pX and pY. The reason for this is in fact, that with the AnchorCenter branch, you won't set the upper left position of an entity anymore and instead use it's center position.

Body Adjustable Velocity AndEngine/Box2D

I was trying to change the velocity of a Physics Body that is attached to a rectangle with the movement of the accelerometer. I cannot get the body to change velocity, is it a permanent property once it is set?
this is in my populateScene:
rect = new Rectangle(220, -200, 24, 24, this.getVertexBufferObjectManager());
rect.setColor(Color.GREEN);
mScene.attachChild(rect);
ball = PhysicsFactory.createBoxBody(mPhysicsWorld, rect, BodyType.DynamicBody, droppingBoxDef);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(
rect, ball));
and this is where I try to change the velocity:
#Override
public void onAccelerationChanged(AccelerationData pAccelerationData) {
int accellerometerSpeedX = (int)pAccelerationData.getX();
// accellerometerSpeedY = (int)pAccelerometerData.getY();
//Log.v("Accelerometer X Y Z: ", ""+pAccelerationData);
ball.setLinearVelocity(accellerometerSpeedX, 0);
}
Without the second portion above the rectangle loads fine and has its physics body working correctly. It seems to disappear when I try to use:
ball.setLinearVelocity.
The Body object is a global variable in the class so it can be referenced in both methods. I have tried using a update handler inside of Populatescene and setting ball.setLinearVelocity in there, however that gave the same results.
Essentially my question is: Can the velocity of a Body be changed after it has been connected to the physics world?
Typicly in Box2D you do not setVelocities, but rather apply impulses or forces to a body to cause it to accelerate or decelerate.
For what you are describing above, you should not be using setLinearVelocity. Try using
ball.applyForce(new Vector2(accellerometerSpeedX, 0), ball.getWorldCenter());
or
boxBody.applyAngularImpulse(new Vector2(accellerometerSpeedX, 0));

Why physics body automatically moves upwards in andengine gles2 anchor center live wallpaper

I am trying to develop a live wallpaper using andengine gles2 anchor center , with some physics.But when i add a physics object it was moving upwards.instead of moving downward due to gravity
what are the mistakes i am making
please help me to sort out the issue
Here is my code
FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f,
0.5f);
mPhysicsWorld = new PhysicsWorld(new Vector2(0,
SensorManager.GRAVITY_EARTH), false);
final AnimatedSprite animatedSprite;
animatedSprite = new AnimatedSprite(500, 250,
this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager());
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, animatedSprite,
BodyType.DynamicBody, FIXTURE_DEF);
scene.attachChild(animatedSprite);
animatedSprite.animate(200);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(
animatedSprite, body, true, true));
Just multiply SensorManager.GRAVITY_EARTH by -1.
Setting negative gravity did not respond properly to sensor data. By adding acceleration to the sensor data in the overridden method **onAccelerationChanged()**, could make the bject falling down with sensor flat.
public void onAccelerationChanged(final AccelerationData pAccelerationData) {
/* Add constant value for vertical gravity*/
final Vector2 gravity = Vector2Pool.obtain(pAccelerationData.getX(), pAccelerationData.getY() + 4.0);
this.mPhysicsWorld.setGravity(gravity);
Vector2Pool.recycle(gravity);
}
This will make your phy world in real gravity experience and you will get objects influenced by sensor data properly

Categories

Resources